X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ftmpfiles%2Ftmpfiles.c;h=b7f6a2e058bcdcf539c5aaa7e06c7cf69b60b710;hp=fb25b77b2bd2602b73ba9b6636b1e61b88807248;hb=eb9da376d76b48585b3b63b4f91903b54f7abd36;hpb=1731e34a4ebddf6e1247ad252c7a45c2c1163f42 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index fb25b77b2..b7f6a2e05 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -52,6 +52,7 @@ #include "conf-files.h" #include "capability.h" #include "specifier.h" +#include "build.h" /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates * them in the file system. This is intended to be used to create @@ -69,6 +70,7 @@ typedef enum ItemType { CREATE_SYMLINK = 'L', CREATE_CHAR_DEVICE = 'c', CREATE_BLOCK_DEVICE = 'b', + ADJUST_MODE = 'm', /* These ones take globs */ IGNORE_PATH = 'x', @@ -257,8 +259,8 @@ static int dir_cleanup( dev_t rootdev, bool mountpoint, int maxdepth, - bool keep_this_level) -{ + bool keep_this_level) { + struct dirent *dent; struct timespec times[2]; bool deleted = false; @@ -274,12 +276,15 @@ static int dir_cleanup( continue; if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { + if (errno == ENOENT) + continue; - if (errno != ENOENT) { + /* FUSE, NFS mounts, SELinux might return EACCES */ + if (errno == EACCES) + log_debug("stat(%s/%s) failed: %m", p, dent->d_name); + else log_error("stat(%s/%s) failed: %m", p, dent->d_name); - r = -errno; - } - + r = -errno; continue; } @@ -429,12 +434,16 @@ finish: return r; } -static int item_set_perms(Item *i, const char *path) { +static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) { + int r; + /* not using i->path directly because it may be a glob */ if (i->mode_set) if (chmod(path, i->mode) < 0) { - log_error("chmod(%s) failed: %m", path); - return -errno; + if (errno != ENOENT || !ignore_enoent) { + log_error("chmod(%s) failed: %m", path); + return -errno; + } } if (i->uid_set || i->gid_set) @@ -442,16 +451,25 @@ static int item_set_perms(Item *i, const char *path) { i->uid_set ? i->uid : (uid_t) -1, i->gid_set ? i->gid : (gid_t) -1) < 0) { - log_error("chown(%s) failed: %m", path); - return -errno; + if (errno != ENOENT || !ignore_enoent) { + log_error("chown(%s) failed: %m", path); + return -errno; + } } - return label_fix(path, false, false); + r = label_fix(path, false, false); + return r == -ENOENT && ignore_enoent ? 0 : r; +} + +static int item_set_perms(Item *i, const char *path) { + return item_set_perms_full(i, path, false); } static int write_one_file(Item *i, const char *path) { - int r, e, fd, flags; + int e, flags; + int fd = -1; struct stat st; + int r = 0; flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND : i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0; @@ -623,8 +641,9 @@ static int glob_item(Item *i, int (*action)(Item *, const char *)) { } static int create_item(Item *i) { - int r, e; + int e; struct stat st; + int r = 0; assert(i); @@ -642,6 +661,7 @@ static int create_item(Item *i) { if (r < 0) return r; break; + case WRITE_FILE: r = glob_item(i, write_one_file); if (r < 0) @@ -649,6 +669,13 @@ static int create_item(Item *i) { break; + case ADJUST_MODE: + r = item_set_perms_full(i, i->path, true); + if (r < 0) + return r; + + break; + case TRUNCATE_DIRECTORY: case CREATE_DIRECTORY: @@ -819,6 +846,7 @@ static int remove_item_instance(Item *i, const char *instance) { case RELABEL_PATH: case RECURSIVE_RELABEL_PATH: case WRITE_FILE: + case ADJUST_MODE: break; case REMOVE_PATH: @@ -864,6 +892,7 @@ static int remove_item(Item *i) { case RELABEL_PATH: case RECURSIVE_RELABEL_PATH: case WRITE_FILE: + case ADJUST_MODE: break; case REMOVE_PATH: @@ -973,10 +1002,7 @@ static void item_free(Item *i) { free(i); } -static inline void item_freep(Item **i) { - if (*i) - item_free(*i); -} +DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free); #define _cleanup_item_free_ _cleanup_(item_freep) static bool item_equal(Item *a, Item *b) { @@ -1106,6 +1132,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { case RECURSIVE_REMOVE_PATH: case RELABEL_PATH: case RECURSIVE_RELABEL_PATH: + case ADJUST_MODE: break; case CREATE_SYMLINK: @@ -1240,6 +1267,7 @@ static int help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Creates, deletes and cleans up volatile and temporary files and directories.\n\n" " -h --help Show this help\n" + " --version Show package version\n" " --create Create marked files/directories\n" " --clean Clean up marked directories\n" " --remove Remove marked files/directories\n" @@ -1253,6 +1281,7 @@ static int help(void) { static int parse_argv(int argc, char *argv[]) { enum { + ARG_VERSION = 0x100, ARG_CREATE, ARG_CLEAN, ARG_REMOVE, @@ -1262,12 +1291,13 @@ static int parse_argv(int argc, char *argv[]) { static const struct option options[] = { { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, { "create", no_argument, NULL, ARG_CREATE }, { "clean", no_argument, NULL, ARG_CLEAN }, { "remove", no_argument, NULL, ARG_REMOVE }, { "prefix", required_argument, NULL, ARG_PREFIX }, { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, - { NULL, 0, NULL, 0 } + {} }; int c; @@ -1280,7 +1310,11 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { case 'h': - help(); + return help(); + + case ARG_VERSION: + puts(PACKAGE_STRING); + puts(SYSTEMD_FEATURES); return 0; case ARG_CREATE: @@ -1309,8 +1343,7 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; default: - log_error("Unknown option code %c", c); - return -EINVAL; + assert_not_reached("Unhandled option"); } }