From: Michael Tremer Date: Fri, 19 Aug 2022 09:00:16 +0000 (+0000) Subject: util: Refactor pakfire_basename/dirname and pakfire_mkdir X-Git-Tag: 0.9.28~440 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bbbc9842813356bce753879d82db967ee1f15713;p=pakfire.git util: Refactor pakfire_basename/dirname and pakfire_mkdir Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index 957560e54..0e8e301b1 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -123,7 +123,7 @@ static struct pakfire_cgroup* pakfire_cgroup_parent(struct pakfire_cgroup* cgrou return NULL; // Determine the path of the parent - char* path = pakfire_dirname(cgroup->path); + const char* path = pakfire_dirname(cgroup->path); if (!path) { ERROR(cgroup->pakfire, "Could not determine path for parent cgroup: %m\n"); return NULL; @@ -131,7 +131,7 @@ static struct pakfire_cgroup* pakfire_cgroup_parent(struct pakfire_cgroup* cgrou // dirname() returns . if no directory component could be found if (strcmp(path, ".") == 0) - *path = '\0'; + path = NULL; // Open the cgroup r = pakfire_cgroup_open(&parent, cgroup->pakfire, path, 0); @@ -140,9 +140,6 @@ static struct pakfire_cgroup* pakfire_cgroup_parent(struct pakfire_cgroup* cgrou parent = NULL; } - // Cleanup - free(path); - return parent; } diff --git a/src/libpakfire/dist.c b/src/libpakfire/dist.c index dd9ac18df..81453a689 100644 --- a/src/libpakfire/dist.c +++ b/src/libpakfire/dist.c @@ -108,13 +108,12 @@ static int pakfire_makefile_set_defaults(struct pakfire* pakfire, } // Set BASEDIR - char* dirname = pakfire_dirname(path); + const char* dirname = pakfire_dirname(path); if (dirname) { const char* root = pakfire_get_path(pakfire); pakfire_parser_set(parser, NULL, "BASEDIR", pakfire_path_relpath(root, dirname), 0); - free(dirname); } long processors_online = sysconf(_SC_NPROCESSORS_ONLN); @@ -320,14 +319,14 @@ static int pakfire_dist_add_files(struct pakfire* pakfire, struct pakfire_packag int r = 1; // Find the parent directory - char* dirname = pakfire_dirname(path); + const char* dirname = pakfire_dirname(path); if (!dirname) return 1; DEBUG(pakfire, "Adding all files in '%s' to package...\n", dirname); char* paths[2] = { - dirname, NULL, + (char*)dirname, NULL, }; FTS* f = fts_open(paths, FTS_NOCHDIR|FTS_NOSTAT, NULL); @@ -366,8 +365,6 @@ ERROR: if (f) fts_close(f); - free(dirname); - return r; } diff --git a/src/libpakfire/downloader.c b/src/libpakfire/downloader.c index 36a01fe7f..44a02fd44 100644 --- a/src/libpakfire/downloader.c +++ b/src/libpakfire/downloader.c @@ -319,11 +319,9 @@ static struct pakfire_transfer* pakfire_downloader_create_transfer( // Or use the filename } else { - char* filename = pakfire_basename(url); - if (filename) { + const char* filename = pakfire_basename(url); + if (filename) pakfire_string_set(transfer->title, filename); - free(filename); - } } // Copy URL diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index 47a40adf9..b9d947ed8 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -35,8 +35,8 @@ char* pakfire_unquote_in_place(char* s); int pakfire_path_exists(const char* path); time_t pakfire_path_age(const char* path); -char* pakfire_basename(const char* path); -char* pakfire_dirname(const char* path); +const char* pakfire_basename(const char* path); +const char* pakfire_dirname(const char* path); char* pakfire_remove_trailing_newline(char* str); diff --git a/src/libpakfire/package.c b/src/libpakfire/package.c index 09cfe60a6..0bef43eb5 100644 --- a/src/libpakfire/package.c +++ b/src/libpakfire/package.c @@ -622,18 +622,14 @@ PAKFIRE_EXPORT const char* pakfire_package_get_path(struct pakfire_package* pkg) } PAKFIRE_EXPORT void pakfire_package_set_path(struct pakfire_package* pkg, const char* path) { - char* basename = pakfire_basename(path); - char* dirname = pakfire_dirname(path); + const char* basename = pakfire_basename(path); + const char* dirname = pakfire_dirname(path); - if (basename) { + if (basename) pakfire_package_set_string(pkg, SOLVABLE_MEDIAFILE, basename); - free(basename); - } - if (dirname) { + if (dirname) pakfire_package_set_string(pkg, SOLVABLE_MEDIABASE, dirname); - free(dirname); - } pakfire_string_set(pkg->path, path); } @@ -1362,8 +1358,8 @@ static int pakfire_package_append_file(struct pakfire_package* pkg, const char* Repodata* repodata = pakfire_repo_get_repodata(repo); pakfire_repo_unref(repo); - char* basename = pakfire_basename(path); - char* dirname = pakfire_dirname(path); + const char* basename = pakfire_basename(path); + const char* dirname = pakfire_dirname(path); // Convert directory into ID Id did = repodata_str2dir(repodata, dirname, 1); @@ -1374,9 +1370,6 @@ static int pakfire_package_append_file(struct pakfire_package* pkg, const char* repodata_add_dirstr(repodata, pkg->id, SOLVABLE_FILELIST, did, basename); - free(basename); - free(dirname); - return 0; } diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index 347cf4202..ee5498dc0 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -828,7 +828,7 @@ PAKFIRE_EXPORT int pakfire_create(struct pakfire** pakfire, const char* path, // Make sure that our private directory exists r = pakfire_mkdir(private_dir, 0755); - if (r && errno != EEXIST) { + if (r) { ERROR(p, "Could not create private directory %s: %m\n", private_dir); goto ERROR; } diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c index 664fc24c5..3fc219a5e 100644 --- a/src/libpakfire/util.c +++ b/src/libpakfire/util.c @@ -158,28 +158,28 @@ ERROR: return r; } -char* pakfire_basename(const char* path) { - char* name = strdup(path); +const char* pakfire_basename(const char* path) { + static char buffer[PATH_MAX]; + int r; - char* r = basename(name); + // Copy string + r = pakfire_string_set(buffer, path); if (r) - r = strdup(r); - - free(name); + return NULL; - return r; + return basename(buffer); } -char* pakfire_dirname(const char* path) { - char* parent = strdup(path); +const char* pakfire_dirname(const char* path) { + static char buffer[PATH_MAX]; + int r; - char* r = dirname(parent); + // Copy string + r = pakfire_string_set(buffer, path); if (r) - r = strdup(r); - - free(parent); + return NULL; - return r; + return dirname(buffer); } char* pakfire_remove_trailing_newline(char* str) { @@ -353,41 +353,72 @@ int pakfire_touch(const char* path, mode_t mode) { } int pakfire_mkparentdir(const char* path, mode_t mode) { - int r; - - char* dirname = pakfire_dirname(path); + const char* dirname = pakfire_dirname(path); if (!dirname) return 1; - // We have arrived at the top of the tree - if (*dirname == '.' || strcmp(dirname, "/") == 0) - return 0; + return pakfire_mkdir(dirname, mode); +} - // Ensure the parent directory exists - r = pakfire_mkparentdir(dirname, mode); - if (r) - goto END; +static int pakfire_try_mkdir(const char* path, const mode_t mode) { + struct stat st; + int r; - // Create this directory - r = mkdir(dirname, mode); + // Call stat() on path + r = stat(path, &st); - // Ignore when the directory already exists - if (r && errno == EEXIST) - r = 0; + // Path exists, but is it a directory? + if (r == 0) { + if (S_ISDIR(st.st_mode)) + return 0; -END: - free(dirname); + // Not a directory + errno = ENOTDIR; + return 1; - return r; + // Path does not exist + } else if (r && errno == ENOENT) { + // Try to create it + r = mkdir(path, mode); + if (r) + return r; + + // Raise any other errors + } else { + return r; + } + + // Success + return 0; } int pakfire_mkdir(const char* path, mode_t mode) { - int r = pakfire_mkparentdir(path, mode); + char buffer[PATH_MAX]; + int r; + + // Copy dirname into buffer + r = pakfire_string_set(buffer, path); if (r) return r; - // Finally, create the directory we want - return mkdir(path, mode); + // Recursively create all directories + for (char* p = buffer + 1; *p; p++) { + if (*p == '/') { + // Cut off at slash + *p = '\0'; + + // Try to create partition directory + r = pakfire_try_mkdir(buffer, mode); + if (r) + return r; + + // Reset slash + *p = '/'; + } + } + + // Create final directory + return pakfire_try_mkdir(path, mode); } FILE* pakfire_mktemp(char* path) { diff --git a/tests/libpakfire/string.c b/tests/libpakfire/string.c index d5b8835c4..c2408b91d 100644 --- a/tests/libpakfire/string.c +++ b/tests/libpakfire/string.c @@ -273,17 +273,16 @@ static int test_format_size(const struct test* t) { char small_buffer[2]; int r; - ASSERT(pakfire_format_size(buffer, 0) == 2); + ASSERT_SUCCESS(pakfire_format_size(buffer, 0)); ASSERT_STRING_EQUALS(buffer, "0 "); - ASSERT(pakfire_format_size(buffer, 1024) == 2); + ASSERT_SUCCESS(pakfire_format_size(buffer, 1024)); ASSERT_STRING_EQUALS(buffer, "1k"); - ASSERT(pakfire_format_size(buffer, 1024 * 1024) == 4); + ASSERT_SUCCESS(pakfire_format_size(buffer, 1024 * 1024) ); ASSERT_STRING_EQUALS(buffer, "1.0M"); - ASSERT(pakfire_format_size(small_buffer, 0) == 2); - ASSERT_STRING_EQUALS(small_buffer, ""); + ASSERT_ERRNO(pakfire_format_size(small_buffer, 0), ENOMEM); return EXIT_SUCCESS; diff --git a/tests/libpakfire/util.c b/tests/libpakfire/util.c index d6543ecb8..70f411b7c 100644 --- a/tests/libpakfire/util.c +++ b/tests/libpakfire/util.c @@ -18,8 +18,6 @@ # # #############################################################################*/ -#include - #include #include "../testsuite.h" @@ -27,9 +25,7 @@ static int test_basename(const struct test* t) { const char* dir = "/a/b/c"; - char* output = pakfire_basename(dir); - ASSERT_STRING_EQUALS(output, "c"); - free(output); + ASSERT_STRING_EQUALS(pakfire_basename(dir), "c"); return EXIT_SUCCESS; @@ -40,9 +36,35 @@ FAIL: static int test_dirname(const struct test* t) { const char* dir = "/a/b/c"; - char* output = pakfire_dirname(dir); - ASSERT_STRING_EQUALS(output, "/a/b"); - free(output); + ASSERT_STRING_EQUALS(pakfire_dirname(dir), "/a/b"); + + return EXIT_SUCCESS; + +FAIL: + return EXIT_FAILURE; +} + +static int test_mkdir(const struct test* t) { + char path[PATH_MAX]; + + // Create some random path + ASSERT_SUCCESS(pakfire_path(t->pakfire, path, "%s", "/a/b/c/d/e")); + + // Create this directory + ASSERT_SUCCESS(pakfire_mkdir(path, 0755)); + + // Check if this exists + ASSERT_SUCCESS(!pakfire_path_exists(path)); + + // Create path again (nothing should happen) + ASSERT_SUCCESS(pakfire_mkdir(path, 0755)); + + // Create the parent directory for /test/1/file.txt + ASSERT_SUCCESS(pakfire_mkparentdir("/test/1/file.txt", 0755)); + + // Check that only the parent directory exists + ASSERT_SUCCESS(!pakfire_path_exists("/test/1")); + ASSERT_SUCCESS(!!pakfire_path_exists("/test/1/file.txt")); return EXIT_SUCCESS; @@ -53,6 +75,7 @@ FAIL: int main(int argc, const char* argv[]) { testsuite_add_test(test_basename); testsuite_add_test(test_dirname); + testsuite_add_test(test_mkdir); return testsuite_run(argc, argv); }