From 7f8a64dd39fc1fe35889d803274290f33dabe8ab Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Jul 2026 18:49:28 +0200 Subject: [PATCH] util: promote rmrf() from tmpfiles.c, fix silent mksubsys() skip rmrf() is needed outside tmpfiles.c. The move also deduplicates the nftw callback: the contents-only removal used by tmpfiles 'D' entries is now rmcontents(), sharing the callback with rmrf(). mksubsys() did nothing at all when the user could not be resolved, no directory and no message, and callers had no way to tell. Now the directory is always created, ownership is best effort, and an unknown user is warned about. Signed-off-by: Joachim Wiberg --- src/tmpfiles.c | 31 +------------------------------ src/util.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- src/util.h | 2 ++ 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/tmpfiles.c b/src/tmpfiles.c index 4cf7ec07..4825ee6a 100644 --- a/src/tmpfiles.c +++ b/src/tmpfiles.c @@ -130,33 +130,6 @@ static int parse_mm(char *arg, int *major, int *minor) return 0; } -static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw) -{ - (void)sb; - (void)tflag; - - if (ftw->level == 0) - return 1; - - if (remove(fpath) && errno != EBUSY) - warn("Failed removing %s", fpath); - - return 0; - -} - -static int rmrf(const char *path) -{ - if (!fisdir(path)) - return 0; - - nftw(path, do_delete, 20, FTW_DEPTH | FTW_PHYS); - if (remove(path) && errno != ENOENT) - warn("Failed removing path %s", path); - - return 0; -} - static void mkparent(char *path, mode_t mode) { mkpath(dirname(strdupa(path)), mode); @@ -465,9 +438,7 @@ static void tmpfiles(char *line) case 'd': break; case 'D': - if (fisdir(path)) { - nftw(path, do_delete, 20, FTW_DEPTH | FTW_PHYS); - } + rmcontents(path); break; case 'e': case 'f': diff --git a/src/util.c b/src/util.c index 4fe6a2db..7cc8b095 100644 --- a/src/util.c +++ b/src/util.c @@ -45,6 +45,7 @@ # include #endif #include +#include /* rmrf() */ #include /* sysinfo() */ #include /* statfs */ #include @@ -310,6 +311,42 @@ int getcgroup(char *buf, size_t len) return 0; } +static int rmrf_cb(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw) +{ + (void)sb; + (void)tflag; + + if (ftw->level == 0) + return 0; + + if (remove(fpath) && errno != EBUSY) + warn("Failed removing %s", fpath); + + return 0; +} + +/* empty a directory but keep it, silently ignores a missing path */ +int rmcontents(const char *path) +{ + if (!fisdir(path)) + return 0; + + return nftw(path, rmrf_cb, 20, FTW_DEPTH | FTW_PHYS); +} + +/* rm -rf, silently ignores a missing path */ +int rmrf(const char *path) +{ + if (!fisdir(path)) + return 0; + + nftw(path, rmrf_cb, 20, FTW_DEPTH | FTW_PHYS); + if (remove(path) && errno != ENOENT) + warn("Failed removing path %s", path); + + return 0; +} + int mksubsys(const char *dir, mode_t mode, char *user, char *group) { mode_t omask; @@ -318,18 +355,20 @@ int mksubsys(const char *dir, mode_t mode, char *user, char *group) omask = umask(0); + rc = makedir(dir, mode); + if (rc && errno == EEXIST) + rc = chmod(dir, mode); + uid = getuser(user, NULL); if (uid >= 0) { gid = getgroup(group); if (gid < 0) gid = 0; - rc = makedir(dir, mode); - if (rc && errno == EEXIST) - rc = chmod(dir, mode); if (chown(dir, uid, gid)) err(1, "Failed chown(%s, %d, %d)", dir, uid, gid); - } + } else + warnx("Cannot find user %s, %s is owned by root", user, dir); umask(omask); diff --git a/src/util.h b/src/util.h index b0ae8614..53cfd84e 100644 --- a/src/util.h +++ b/src/util.h @@ -72,6 +72,8 @@ int getcuser (char *buf, size_t len); int getcgroup (char *buf, size_t len); int mksubsys (const char *dir, mode_t mode, char *user, char *group); +int rmcontents (const char *path); +int rmrf (const char *path); char *fslurp (size_t *lenp, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); char *vfslurp (size_t *lenp, const char *fmt, va_list ap);