--- man/tmpfiles.d.xml | 3 +++ src/tmpfiles/tmpfiles.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 7 deletions(-) Index: systemd-221/man/tmpfiles.d.xml =================================================================== --- systemd-221.orig/man/tmpfiles.d.xml +++ systemd-221/man/tmpfiles.d.xml @@ -528,6 +528,9 @@ f, F, and w may be used to specify a short string that is written to the file, suffixed by a newline. For + x, X, a comma separated list of + usernames. If given, only paths belonging to these users will be excluded + during directory cleanup. Ignored for all other lines. For C, specifies the source file or directory. For t, T determines extended attributes to be set. For Index: systemd-221/src/tmpfiles/tmpfiles.c =================================================================== --- systemd-221.orig/src/tmpfiles/tmpfiles.c +++ systemd-221/src/tmpfiles/tmpfiles.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "log.h" #include "util.h" @@ -358,6 +359,7 @@ static int dir_cleanup( struct timespec times[2]; bool deleted = false; int r = 0; + Item *found = NULL; while ((dent = readdir(d))) { struct stat s; @@ -408,14 +410,45 @@ static int dir_cleanup( } /* Is there an item configured for this path? */ - if (ordered_hashmap_get(items, sub_path)) { - log_debug("Ignoring \"%s\": a separate entry exists.", sub_path); - continue; + bool found_glob = false; + found = ordered_hashmap_get(items, sub_path); + if (!found) { + found_glob = true; + found = find_glob(globs, sub_path); } - - if (find_glob(globs, sub_path)) { - log_debug("Ignoring \"%s\": a separate glob exists.", sub_path); - continue; + if (found) { + struct passwd *pw; + char *userfound = NULL, *args; + bool match = false; + uid_t uid = -1; + + /* evaluate username arguments in ignore statements */ + if ((found->type != IGNORE_PATH && found->type != IGNORE_DIRECTORY_PATH) || + !found->argument) { + if (found_glob) + log_debug("Ignoring \"%s\": a separate glob exists.", sub_path); + else + log_debug("Ignoring \"%s\": a separate entry exists.", sub_path); + continue; + } + args = strdup(found->argument); + assert_se(args != NULL); + while ((userfound = strsep(&args, ",")) != NULL) { + pw = getpwnam(userfound); + if (pw == NULL) { + log_error("Unknown user '%s' in ignore statement.", userfound); + continue; + } + uid = pw->pw_uid; + if (s.st_uid == uid) { + match = true; + break; + } + } + if (match) { + found = NULL; + continue; + } } if (S_ISDIR(s.st_mode)) {