X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ftmpfiles%2Ftmpfiles.c;h=0e1bd86748396228bf4412ae98ea9ca9f74ad431;hp=5bd7cfecfe22d31a655d18fba9571b89282dd8b1;hb=294929f8916ca37d89ccb1757868d22f8068c56b;hpb=582deb8446b7c76f945bb3174a8059d56b5edb65 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 5bd7cfecf..0e1bd8674 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -308,6 +308,28 @@ static int dir_is_mount_point(DIR *d, const char *subdir) { return r; } +static DIR* xopendirat_nomod(int dirfd, const char *path) { + DIR *dir; + + dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME); + if (!dir) { + log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", + dirfd == AT_FDCWD ? "" : "sub", path); + if (errno == EPERM) { + dir = xopendirat(dirfd, path, O_NOFOLLOW); + if (!dir) + log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", + dirfd == AT_FDCWD ? "" : "sub", path); + } + } + + return dir; +} + +static DIR* opendir_nomod(const char *path) { + return xopendirat_nomod(AT_FDCWD, path); +} + static int dir_cleanup( Item *i, const char *p, @@ -398,7 +420,7 @@ static int dir_cleanup( _cleanup_closedir_ DIR *sub_dir; int q; - sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME); + sub_dir = xopendirat_nomod(dirfd(d), dent->d_name); if (!sub_dir) { if (errno != ENOENT) r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path); @@ -443,18 +465,12 @@ static int dir_cleanup( continue; } - if (i->type == IGNORE_DIRECTORY_PATH && streq(dent->d_name, p)) - log_debug("Ignoring directory \"%s\"", sub_path); - else { - log_debug("Removing directory \"%s\".", sub_path); - - if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) { - if (errno != ENOENT && errno != ENOTEMPTY) { - log_error_errno(errno, "rmdir(%s): %m", sub_path); - r = -errno; - } + log_debug("Removing directory \"%s\".", sub_path); + if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) + if (errno != ENOENT && errno != ENOTEMPTY) { + log_error_errno(errno, "rmdir(%s): %m", sub_path); + r = -errno; } - } } else { /* Skip files for which the sticky bit is @@ -817,11 +833,9 @@ static int item_do_children(Item *i, const char *path, action_t action) { /* This returns the first error we run into, but nevertheless * tries to go on */ - d = opendir(path); - if (!d) { - log_debug_errno(errno, "Cannot open directory \"%s\": %m", path); + d = opendir_nomod(path); + if (!d) return errno == ENOENT || errno == ENOTDIR ? 0 : -errno; - } for (;;) { _cleanup_free_ char *p = NULL; @@ -859,12 +873,18 @@ static int item_do_children(Item *i, const char *path, action_t action) { } static int glob_item(Item *i, action_t action, bool recursive) { - _cleanup_globfree_ glob_t g = {}; + _cleanup_globfree_ glob_t g = { + .gl_closedir = (void (*)(void *)) closedir, + .gl_readdir = (struct dirent *(*)(void *)) readdir, + .gl_opendir = (void *(*)(const char *)) opendir_nomod, + .gl_lstat = lstat, + .gl_stat = stat, + }; int r = 0, k; char **fn; errno = 0; - k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); if (k != 0 && k != GLOB_NOMATCH) return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path); @@ -883,9 +903,28 @@ static int glob_item(Item *i, action_t action, bool recursive) { return r; } +typedef enum { + CREATION_NORMAL, + CREATION_EXISTING, + CREATION_FORCE, +} CreationMode; + +static const char* creation_verb(CreationMode mode) { + switch(mode) { + case CREATION_NORMAL: + return "Created"; + case CREATION_EXISTING: + return "Found existing"; + case CREATION_FORCE: + return "Created replacement"; + } + assert_not_reached("Bad creation"); +} + static int create_item(Item *i) { struct stat st; int r = 0; + CreationMode creation; assert(i); @@ -970,8 +1009,11 @@ static int create_item(Item *i) { log_debug("\"%s\" already exists and is not a directory.", i->path); return 0; } - } - log_debug("Created directory \"%s\".", i->path); + + creation = CREATION_EXISTING; + } else + creation = CREATION_NORMAL; + log_debug("%s directory \"%s\".", creation_verb(creation), i->path); r = path_set_perms(i, i->path); if (r < 0) @@ -1006,13 +1048,16 @@ static int create_item(Item *i) { if (r < 0) return log_error_errno(r, "Failed to create fifo %s: %m", i->path); + creation = CREATION_FORCE; } else { log_debug("%s is not a fifo.", i->path); return 0; } - } - } - log_debug("Created fifo \"%s\".", i->path); + } else + creation = CREATION_EXISTING; + } else + creation = CREATION_NORMAL; + log_debug("%s fifo \"%s\".", creation_verb(creation), i->path); r = path_set_perms(i, i->path); if (r < 0) @@ -1042,13 +1087,16 @@ static int create_item(Item *i) { if (r < 0) return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path); + creation = CREATION_FORCE; } else { log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path); return 0; } - } - } - log_debug("Created symlink \"%s\".", i->path); + } else + creation = CREATION_EXISTING; + } else + creation = CREATION_NORMAL; + log_debug("%s symlink \"%s\".", creation_verb(creation), i->path); break; @@ -1098,14 +1146,18 @@ static int create_item(Item *i) { } if (r < 0) - return log_error_errno(r, "Failed to create device node %s: %m", i->path); + return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path); + creation = CREATION_FORCE; } else { log_debug("%s is not a device node.", i->path); return 0; } - } - } - log_debug("Created %s device node \"%s\" %u:%u.", + } else + creation = CREATION_EXISTING; + } else + creation = CREATION_NORMAL; + log_debug("%s %s device node \"%s\" %u:%u.", + creation_verb(creation), i->type == CREATE_BLOCK_DEVICE ? "block" : "char", i->path, major(i->mode), minor(i->mode)); @@ -1248,7 +1300,7 @@ static int clean_item_instance(Item *i, const char* instance) { cutoff = n - i->age; - d = opendir(instance); + d = opendir_nomod(instance); if (!d) { if (errno == ENOENT || errno == ENOTDIR) { log_debug_errno(errno, "Directory \"%s\": %m", instance); @@ -1723,8 +1775,8 @@ static void help(void) { " --clean Clean up marked directories\n" " --remove Remove marked files/directories\n" " --boot Execute actions only safe at boot\n" - " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n" - " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n" + " --prefix=PATH Only apply rules with the specified prefix\n" + " --exclude-prefix=PATH Ignore rules with the specified prefix\n" " --root=PATH Operate on an alternate filesystem root\n", program_invocation_short_name); }