[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Thu Jan 7 00:00:02 UTC 2021


The branch, master has been updated
       via  38c989fab78 s3:lib: Create the cache path of user gencache recursively
       via  bf7b165877b lib:util: Add directory_create_or_exists_recursive()
      from  31943cc9c0d s3:utils - explicitly free cmdline_messaging_context

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 38c989fab78c3baade3e441829b7becf6b25ef3f
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Dec 21 10:36:46 2020 +0100

    s3:lib: Create the cache path of user gencache recursively
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14601
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Wed Jan  6 23:59:58 UTC 2021 on sn-devel-184

commit bf7b165877bdfd07eb84ecafdc87bd7a6d945f09
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Dec 21 10:35:51 2020 +0100

    lib:util: Add directory_create_or_exists_recursive()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14601
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/util/samba_util.h      |  14 ++++++
 lib/util/tests/test_util.c | 116 +++++++++++++++++++++++++++++++++++++++++++--
 lib/util/util.c            |  40 ++++++++++++++++
 source3/lib/gencache.c     |   2 +-
 4 files changed, 166 insertions(+), 6 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
index 3a60b618083..4ff3f7ff35c 100644
--- a/lib/util/samba_util.h
+++ b/lib/util/samba_util.h
@@ -478,6 +478,20 @@ _PUBLIC_ bool file_check_permissions(const char *fname,
  */
 _PUBLIC_ bool directory_create_or_exist(const char *dname, mode_t dir_perms);
 
+/**
+ * @brief Try to create a specified directory and the parent directory if they
+ *        don't exist.
+ *
+ * @param[in]  dname     The directory path to create.
+ *
+ * @param[in]  dir_perms The permission of the directories.
+ *
+ * @return true on success, false otherwise.
+ */
+_PUBLIC_ bool directory_create_or_exists_recursive(
+		const char *dname,
+		mode_t dir_perms);
+
 _PUBLIC_ bool directory_create_or_exist_strict(const char *dname,
 					       uid_t uid,
 					       mode_t dir_perms);
diff --git a/lib/util/tests/test_util.c b/lib/util/tests/test_util.c
index e547668ade3..62f10edeca4 100644
--- a/lib/util/tests/test_util.c
+++ b/lib/util/tests/test_util.c
@@ -4,6 +4,7 @@
  *  Unit test for util.c
  *
  *  Copyright (C) Christof Schmitt 2020
+ *  Copyright (C) Andreas Schneider 2020
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -19,13 +20,22 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "lib/util/util.c"
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <setjmp.h>
 #include <cmocka.h>
 
+#include "lib/replace/replace.h"
+#include "system/dir.h"
+
+#include "lib/util/util.c"
+
 struct test_paths {
 	char testdir[PATH_MAX];
 	char none[PATH_MAX];
 	char dir[PATH_MAX];
+	char dir_recursive[PATH_MAX];
 	mode_t dir_mode;
 	char file[PATH_MAX];
 	mode_t file_mode;
@@ -59,6 +69,12 @@ static int group_setup(void **state)
 	ret = mkdir(paths->dir, paths->dir_mode);
 	assert_return_code(ret, errno);
 
+	strlcpy(paths->dir_recursive, testdir, sizeof(paths->dir));
+	strlcat(paths->dir_recursive, "/dir_recursive", sizeof(paths->dir));
+	paths->dir_mode = 0750;
+	ret = mkdir(paths->dir_recursive, paths->dir_mode);
+	assert_return_code(ret, errno);
+
 	strlcpy(paths->file, testdir, sizeof(paths->file));
 	strlcat(paths->file, "/file", sizeof(paths->file));
 	paths->file_mode = 0640;
@@ -89,14 +105,79 @@ static int group_setup(void **state)
 	return 0;
 }
 
+static int torture_rmdirs(const char *path)
+{
+	DIR *d;
+	struct dirent *dp;
+	struct stat sb;
+	char *fname;
+
+	if ((d = opendir(path)) != NULL) {
+		while(stat(path, &sb) == 0) {
+			/* if we can remove the directory we're done */
+			if (rmdir(path) == 0) {
+				break;
+			}
+			switch (errno) {
+				case ENOTEMPTY:
+				case EEXIST:
+				case EBADF:
+					break; /* continue */
+				default:
+					closedir(d);
+					return 0;
+			}
+
+			while ((dp = readdir(d)) != NULL) {
+				size_t len;
+				/* skip '.' and '..' */
+				if (dp->d_name[0] == '.' &&
+						(dp->d_name[1] == '\0' ||
+						 (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) {
+					continue;
+				}
+
+				len = strlen(path) + strlen(dp->d_name) + 2;
+				fname = malloc(len);
+				if (fname == NULL) {
+					closedir(d);
+					return -1;
+				}
+				snprintf(fname, len, "%s/%s", path, dp->d_name);
+
+				/* stat the file */
+				if (lstat(fname, &sb) != -1) {
+					if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
+						if (rmdir(fname) < 0) { /* can't be deleted */
+							if (errno == EACCES) {
+								closedir(d);
+								SAFE_FREE(fname);
+								return -1;
+							}
+							torture_rmdirs(fname);
+						}
+					} else {
+						unlink(fname);
+					}
+				} /* lstat */
+				SAFE_FREE(fname);
+			} /* readdir */
+
+			rewinddir(d);
+		}
+	} else {
+		return -1;
+	}
+
+	closedir(d);
+	return 0;
+}
+
 static int group_teardown(void **state)
 {
 	struct test_paths *paths = *state;
 	int ret;
 
-	ret = rmdir(paths->dir);
-	assert_return_code(ret, errno);
-
 	ret = unlink(paths->file);
 	assert_return_code(ret, errno);
 
@@ -109,7 +190,7 @@ static int group_teardown(void **state)
 	ret = unlink(paths->symlink_file);
 	assert_return_code(ret, errno);
 
-	ret = rmdir(paths->testdir);
+	ret = torture_rmdirs(paths->testdir);
 	assert_return_code(ret, errno);
 
 	free(paths);
@@ -220,6 +301,30 @@ static void test_directory_create_or_exists_symlink_file(void **state)
 	assert_true(S_ISLNK(sbuf.st_mode));
 }
 
+static void test_directory_create_or_exists_recursive(void **state)
+{
+	struct test_paths *paths = *state;
+	char recursive_testdir[PATH_MAX] = {0};
+	struct stat sbuf = {0};
+	bool ok;
+	int ret;
+
+	ret = snprintf(recursive_testdir,
+		       sizeof(recursive_testdir),
+		       "%s/wurst/brot",
+		       paths->dir_recursive);
+	assert_int_not_equal(ret, -1);
+
+	ok = directory_create_or_exists_recursive(recursive_testdir,
+						  0700);
+	assert_true(ok);
+
+	ret = lstat(recursive_testdir, &sbuf);
+	assert_return_code(ret, errno);
+	assert_int_equal(sbuf.st_mode & 0777, 0700);
+	assert_true(S_ISDIR(sbuf.st_mode));
+}
+
 int main(int argc, char **argv)
 {
 	const struct CMUnitTest tests[] = {
@@ -230,6 +335,7 @@ int main(int argc, char **argv)
 		cmocka_unit_test(test_directory_create_or_exists_symlink_none),
 		cmocka_unit_test(test_directory_create_or_exists_symlink_dir),
 		cmocka_unit_test(test_directory_create_or_exists_symlink_file),
+		cmocka_unit_test(test_directory_create_or_exists_recursive),
 	};
 
 	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
diff --git a/lib/util/util.c b/lib/util/util.c
index d7331f743f3..3ca6b61df32 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -35,6 +35,7 @@
 #include "debug.h"
 #include "samba_util.h"
 #include "lib/util/select.h"
+#include <libgen.h>
 
 #ifdef HAVE_SYS_PRCTL_H
 #include <sys/prctl.h>
@@ -246,6 +247,45 @@ _PUBLIC_ bool directory_create_or_exist(const char *dname,
 	return true;
 }
 
+_PUBLIC_ bool directory_create_or_exists_recursive(
+		const char *dname,
+		mode_t dir_perms)
+{
+	bool ok;
+
+	ok = directory_create_or_exist(dname, dir_perms);
+	if (!ok) {
+		if (!directory_exist(dname)) {
+			char tmp[PATH_MAX] = {0};
+			char *parent = NULL;
+			size_t n;
+
+			/* Use the null context */
+			n = strlcpy(tmp, dname, sizeof(tmp));
+			if (n < strlen(dname)) {
+				DBG_ERR("Path too long!\n");
+				return false;
+			}
+
+			parent = dirname(tmp);
+			if (parent == NULL) {
+				DBG_ERR("Failed to create dirname!\n");
+				return false;
+			}
+
+			ok = directory_create_or_exists_recursive(parent,
+								  dir_perms);
+			if (!ok) {
+				return false;
+			}
+
+			ok = directory_create_or_exist(dname, dir_perms);
+		}
+	}
+
+	return ok;
+}
+
 /**
  * @brief Try to create a specified directory if it doesn't exist.
  *
diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c
index 896bf50cbd7..07a08fa8268 100644
--- a/source3/lib/gencache.c
+++ b/source3/lib/gencache.c
@@ -124,7 +124,7 @@ static bool gencache_init(void)
 			return false;
 		}
 
-		ok = directory_create_or_exist(cache_dname, 0700);
+		ok = directory_create_or_exists_recursive(cache_dname, 0700);
 		if (!ok) {
 			DBG_ERR("Failed to create directory: %s - %s\n",
 				cache_dname, strerror(errno));


-- 
Samba Shared Repository



More information about the samba-cvs mailing list