From b1353744f0f12e8e8de3e920c4305306aea5eb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Wed, 12 May 2021 10:32:49 -0300 Subject: [PATCH 1/2] Create xbps_walk_dir function. It's used in both xbps-create and xbps-uchroot. Even though neither uses the "dirent" arg in fn, leave it in for possible future use. This implementation also fixes a bug with the version of walk_dir in those binaries where it leaks all the list[i] items. This version frees them after using them and does a final cleanup in case the for loop ended before going through all of them. xbps-create requires this function to use alphasort, but xbps-uchroot wouldn't. For implemenation simplicity, use alphasort in all cases. --- include/xbps_utils.h | 32 +++++++++++++++++ lib/Makefile | 1 + lib/walk_dir.c | 83 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 include/xbps_utils.h create mode 100644 lib/walk_dir.c diff --git a/include/xbps_utils.h b/include/xbps_utils.h new file mode 100644 index 000000000..bda387828 --- /dev/null +++ b/include/xbps_utils.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2021 Érico Nogueira Rolim. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *- + */ + +#include + +#include "xbps_api_impl.h" + +int xbps_walk_dir(const char *, + int (*fn) (const char *, const struct stat *, const struct dirent *)); diff --git a/lib/Makefile b/lib/Makefile index 822b9d743..f9e579e91 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -51,6 +51,7 @@ OBJS += repo.o repo_sync.o OBJS += rpool.o cb_util.o proplib_wrapper.o OBJS += package_alternatives.o OBJS += conf.o log.o +OBJS += walk_dir.o OBJS += $(EXTOBJS) $(COMPAT_OBJS) # unnecessary unless pkgdb format changes # OBJS += pkgdb_conversion.o diff --git a/lib/walk_dir.c b/lib/walk_dir.c new file mode 100644 index 000000000..de54ba6a9 --- /dev/null +++ b/lib/walk_dir.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2021 Érico Nogueira Rolim. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "xbps_utils.h" + +int +xbps_walk_dir(const char *path, + int (*fn) (const char *, const struct stat *, const struct dirent *)) +{ + int rv, i, count; + struct dirent **list; + char tmp_path[PATH_MAX] = { 0 }; + struct stat sb; + + count = scandir(path, &list, NULL, alphasort); + for (i = count - 1; i >= 0; i--) { + if (strcmp(list[i]->d_name, ".") == 0 || strcmp(list[i]->d_name, "..") == 0) + goto cleanup; + if (strlen(path) + strlen(list[i]->d_name) + 1 >= PATH_MAX - 1) { + errno = ENAMETOOLONG; + rv = -1; + break; + } + strncpy(tmp_path, path, PATH_MAX - 1); + strncat(tmp_path, "/", PATH_MAX - 1 - strlen(tmp_path)); + strncat(tmp_path, list[i]->d_name, PATH_MAX - 1 - strlen(tmp_path)); + if (lstat(tmp_path, &sb) < 0) { + break; + } + + if (S_ISDIR(sb.st_mode)) { + if (xbps_walk_dir(tmp_path, fn) < 0) { + rv = -1; + break; + } + } + + rv = fn(tmp_path, &sb, list[i]); + if (rv != 0) { + break; + + cleanup: + free(list[i]); + } + + } + for (; i >= 0; i--) { + free(list[i]); + } + free(list); + return rv; +} From 91cbd8c7aa7770ae06aa7975e8813b190960e1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Wed, 12 May 2021 11:12:28 -0300 Subject: [PATCH 2/2] xbps-uchroot,xbps-create: use xbps_walk_dir --- bin/xbps-create/main.c | 45 ++-------------------------------- bin/xbps-uchroot/main.c | 53 +++-------------------------------------- 2 files changed, 5 insertions(+), 93 deletions(-) diff --git a/bin/xbps-create/main.c b/bin/xbps-create/main.c index 1ff0640cf..888300842 100644 --- a/bin/xbps-create/main.c +++ b/bin/xbps-create/main.c @@ -43,6 +43,7 @@ #include #include +#include "xbps_utils.h" #include "queue.h" #ifdef __clang__ @@ -510,48 +511,6 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED return 0; } -static int -walk_dir(const char *path, - int (*fn) (const char *, const struct stat *sb, const struct dirent *dir)) -{ - int rv, i; - struct dirent **list; - char tmp_path[PATH_MAX] = { 0 }; - struct stat sb; - - rv = scandir(path, &list, NULL, alphasort); - for (i = rv - 1; i >= 0; i--) { - if (strcmp(list[i]->d_name, ".") == 0 || strcmp(list[i]->d_name, "..") == 0) - continue; - if (strlen(path) + strlen(list[i]->d_name) + 1 >= PATH_MAX - 1) { - errno = ENAMETOOLONG; - rv = -1; - break; - } - strncpy(tmp_path, path, PATH_MAX - 1); - strncat(tmp_path, "/", PATH_MAX - 1 - strlen(tmp_path)); - strncat(tmp_path, list[i]->d_name, PATH_MAX - 1 - strlen(tmp_path)); - if (lstat(tmp_path, &sb) < 0) { - break; - } - - if (S_ISDIR(sb.st_mode)) { - if (walk_dir(tmp_path, fn) < 0) { - rv = -1; - break; - } - } - - rv = fn(tmp_path, &sb, list[i]); - if (rv != 0) { - break; - } - - } - free(list); - return rv; -} - static void process_xentry(const char *key, const char *mutable_files) { @@ -620,7 +579,7 @@ process_xentry(const char *key, const char *mutable_files) static void process_destdir(const char *mutable_files) { - if (walk_dir(".", ftw_cb) < 0) + if (xbps_walk_dir(".", ftw_cb) < 0) die("failed to process destdir files (nftw):"); /* Process regular files */ diff --git a/bin/xbps-uchroot/main.c b/bin/xbps-uchroot/main.c index db93e2887..20714ae28 100644 --- a/bin/xbps-uchroot/main.c +++ b/bin/xbps-uchroot/main.c @@ -50,12 +50,11 @@ #include #include #include /* PATH_MAX */ -#include #include #include -#include #include +#include "xbps_utils.h" #include "queue.h" #ifndef SECBIT_NOROOT @@ -115,7 +114,7 @@ die(const char *fmt, ...) } static int -ftw_cb(const char *fpath, const struct stat *sb) +ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED) { int sverrno = 0; @@ -132,52 +131,6 @@ ftw_cb(const char *fpath, const struct stat *sb) return 0; } -static int -walk_dir(const char *path, - int (*fn)(const char *fpath, const struct stat *sb)) -{ - struct dirent **list; - struct stat sb; - const char *p; - char tmp_path[PATH_MAX] = {0}; - int rv = 0, i; - - i = scandir(path, &list, NULL, alphasort); - if (i == -1) { - rv = -1; - goto out; - } - while (i--) { - p = list[i]->d_name; - if (strcmp(p, ".") == 0 || strcmp(p, "..") == 0) - continue; - if (strlen(path) + strlen(p) + 1 >= (PATH_MAX - 1)) { - errno = ENAMETOOLONG; - rv = -1; - break; - } - strncpy(tmp_path, path, PATH_MAX - 1); - strncat(tmp_path, "/", PATH_MAX - 1 - strlen(tmp_path)); - strncat(tmp_path, p, PATH_MAX - 1 - strlen(tmp_path)); - if (lstat(tmp_path, &sb) < 0) { - break; - } - if (S_ISDIR(sb.st_mode)) { - if (walk_dir(tmp_path, fn) < 0) { - rv = -1; - break; - } - } - rv = fn(tmp_path, &sb); - if (rv != 0) { - break; - } - } -out: - free(list); - return rv; -} - static void cleanup_overlayfs(void) { @@ -188,7 +141,7 @@ cleanup_overlayfs(void) goto out; /* recursively remove the temporary dir */ - if (walk_dir(tmpdir, ftw_cb) != 0) { + if (xbps_walk_dir(tmpdir, ftw_cb) != 0) { fprintf(stderr, "Failed to remove directory tree %s: %s\n", tmpdir, strerror(errno)); exit(EXIT_FAILURE);