X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ftmpfiles%2Ftmpfiles.c;h=45d31fb5d803c03d1c78efd9de66179759851efe;hp=68cfa55ce9cee09e96985c76ac2390cfbe5140f7;hb=8d3d7072e609ef0e0fb37e1d19a29307d58146c3;hpb=2f3b873a49734f8ecc8d929612d33153acbda891 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 68cfa55ce..45d31fb5d 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -117,15 +117,7 @@ static char **arg_include_prefixes = NULL; static char **arg_exclude_prefixes = NULL; static char *arg_root = NULL; -static const char conf_file_dirs[] = - "/etc/tmpfiles.d\0" - "/run/tmpfiles.d\0" - "/usr/local/lib/tmpfiles.d\0" - "/usr/lib/tmpfiles.d\0" -#ifdef HAVE_SPLIT_USR - "/lib/tmpfiles.d\0" -#endif - ; +static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles"); #define MAX_DEPTH 256 @@ -165,7 +157,7 @@ static void load_unix_sockets(void) { /* We maintain a cache of the sockets we found in * /proc/net/unix to speed things up a little. */ - unix_sockets = set_new(string_hash_func, string_compare_func); + unix_sockets = set_new(&string_hash_ops); if (!unix_sockets) return; @@ -259,7 +251,7 @@ static int dir_is_mount_point(DIR *d, const char *subdir) { /* got only one handle; assume different mount points if one * of both queries was not supported by the filesystem */ - if (r_p == -ENOSYS || r_p == -ENOTSUP || r == -ENOSYS || r == -ENOTSUP) + if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP) return true; /* return error */ @@ -453,35 +445,39 @@ finish: } static int item_set_perms(Item *i, const char *path) { + struct stat st; + bool st_valid; + assert(i); assert(path); + st_valid = stat(path, &st) == 0; + /* not using i->path directly because it may be a glob */ if (i->mode_set) { mode_t m = i->mode; - if (i->mask_perms) { - struct stat st; - - if (stat(path, &st) >= 0) { - if (!(st.st_mode & 0111)) - m &= ~0111; - if (!(st.st_mode & 0222)) - m &= ~0222; - if (!(st.st_mode & 0444)) - m &= ~0444; - if (!S_ISDIR(st.st_mode)) - m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */ - } + if (i->mask_perms && st_valid) { + if (!(st.st_mode & 0111)) + m &= ~0111; + if (!(st.st_mode & 0222)) + m &= ~0222; + if (!(st.st_mode & 0444)) + m &= ~0444; + if (!S_ISDIR(st.st_mode)) + m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */ } - if (chmod(path, m) < 0) { - log_error("chmod(%s) failed: %m", path); - return -errno; + if (!st_valid || m != (st.st_mode & 07777)) { + if (chmod(path, m) < 0) { + log_error("chmod(%s) failed: %m", path); + return -errno; + } } } - if (i->uid_set || i->gid_set) + if ((!st_valid || (i->uid != st.st_uid || i->gid != st.st_gid)) && + (i->uid_set || i->gid_set)) if (chown(path, i->uid_set ? i->uid : (uid_t) -1, i->gid_set ? i->gid : (gid_t) -1) < 0) { @@ -505,9 +501,9 @@ static int write_one_file(Item *i, const char *path) { i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0; RUN_WITH_UMASK(0000) { - label_context_set(path, S_IFREG); + mac_selinux_create_file_prepare(path, S_IFREG); fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); - label_context_clear(); + mac_selinux_create_file_clear(); } if (fd < 0) { @@ -671,10 +667,8 @@ static int create_item(Item *i) { if (r < 0) { struct stat a, b; - if (r != -EEXIST) { - log_error("Failed to copy files to %s: %s", i->path, strerror(-r)); - return -r; - } + if (r != -EEXIST) + return log_error_errno(r, "Failed to copy files to %s: %m", i->path); if (stat(i->argument, &a) < 0) { log_error("stat(%s) failed: %m", i->argument); @@ -714,10 +708,8 @@ static int create_item(Item *i) { } if (r < 0) { - if (r != -EEXIST) { - log_error("Failed to create directory %s: %s", i->path, strerror(-r)); - return r; - } + if (r != -EEXIST) + return log_error_errno(r, "Failed to create directory %s: %m", i->path); if (stat(i->path, &st) < 0) { log_error("stat(%s) failed: %m", i->path); @@ -739,9 +731,9 @@ static int create_item(Item *i) { case CREATE_FIFO: RUN_WITH_UMASK(0000) { - label_context_set(i->path, S_IFIFO); + mac_selinux_create_file_prepare(i->path, S_IFIFO); r = mkfifo(i->path, i->mode); - label_context_clear(); + mac_selinux_create_file_clear(); } if (r < 0) { @@ -760,15 +752,13 @@ static int create_item(Item *i) { if (i->force) { RUN_WITH_UMASK(0000) { - label_context_set(i->path, S_IFIFO); + mac_selinux_create_file_prepare(i->path, S_IFIFO); r = mkfifo_atomic(i->path, i->mode); - label_context_clear(); + mac_selinux_create_file_clear(); } - if (r < 0) { - log_error("Failed to create fifo %s: %s", i->path, strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to create fifo %s: %m", i->path); } else { log_debug("%s is not a fifo.", i->path); return 0; @@ -784,9 +774,9 @@ static int create_item(Item *i) { case CREATE_SYMLINK: - label_context_set(i->path, S_IFLNK); + mac_selinux_create_file_prepare(i->path, S_IFLNK); r = symlink(i->argument, i->path); - label_context_clear(); + mac_selinux_create_file_clear(); if (r < 0) { _cleanup_free_ char *x = NULL; @@ -800,14 +790,12 @@ static int create_item(Item *i) { if (r < 0 || !streq(i->argument, x)) { if (i->force) { - label_context_set(i->path, S_IFLNK); + mac_selinux_create_file_prepare(i->path, S_IFLNK); r = symlink_atomic(i->argument, i->path); - label_context_clear(); + mac_selinux_create_file_clear(); - if (r < 0) { - log_error("symlink(%s, %s) failed: %s", i->argument, i->path, strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path); } else { log_debug("%s is not a symlink or does not point to the correct path.", i->path); return 0; @@ -834,9 +822,9 @@ static int create_item(Item *i) { file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR; RUN_WITH_UMASK(0000) { - label_context_set(i->path, file_type); + mac_selinux_create_file_prepare(i->path, file_type); r = mknod(i->path, i->mode | file_type, i->major_minor); - label_context_clear(); + mac_selinux_create_file_clear(); } if (r < 0) { @@ -861,15 +849,13 @@ static int create_item(Item *i) { if (i->force) { RUN_WITH_UMASK(0000) { - label_context_set(i->path, file_type); + mac_selinux_create_file_prepare(i->path, file_type); r = mknod_atomic(i->path, i->mode | file_type, i->major_minor); - label_context_clear(); + mac_selinux_create_file_clear(); } - if (r < 0) { - log_error("Failed to create device node %s: %s", i->path, strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to create device node %s: %m", i->path); } else { log_debug("%s is not a device node.", i->path); return 0; @@ -942,10 +928,8 @@ static int remove_item_instance(Item *i, const char *instance) { /* FIXME: we probably should use dir_cleanup() here * instead of rm_rf() so that 'x' is honoured. */ r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false); - if (r < 0 && r != -ENOENT) { - log_error("rm_rf(%s): %s", instance, strerror(-r)); - return r; - } + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "rm_rf(%s): %m", instance); break; } @@ -1060,7 +1044,7 @@ static int clean_item(Item *i) { static int process_item(Item *i) { int r, q, p; - char prefix[PATH_MAX]; + _cleanup_free_ char *prefix = NULL; assert(i); @@ -1069,6 +1053,10 @@ static int process_item(Item *i) { i->done = true; + prefix = malloc(strlen(i->path) + 1); + if (!prefix) + return log_oom(); + PATH_FOREACH_PREFIX(prefix, i->path) { Item *j; @@ -1397,18 +1385,15 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { } r = hashmap_put(h, i->path, i); - if (r < 0) { - log_error("Failed to insert item %s: %s", i->path, strerror(-r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to insert item %s: %m", i->path); i = NULL; /* avoid cleanup */ return 0; } -static int help(void) { - +static void 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" @@ -1421,8 +1406,6 @@ static int help(void) { " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n" " --root=PATH Operate on an alternate filesystem root\n", program_invocation_short_name); - - return 0; } static int parse_argv(int argc, char *argv[]) { @@ -1456,12 +1439,13 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': - return help(); + help(); + return 0; case ARG_VERSION: puts(PACKAGE_STRING); @@ -1509,7 +1493,6 @@ static int parse_argv(int argc, char *argv[]) { default: assert_not_reached("Unhandled option"); } - } if (!arg_clean && !arg_create && !arg_remove) { log_error("You need to specify at least one of --clean, --create or --remove."); @@ -1534,8 +1517,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) { if (ignore_enoent && r == -ENOENT) return 0; - log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r)); - return r; + return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn); } FOREACH_LINE(line, f, break) { @@ -1575,7 +1557,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) { candidate_item = j; } - if (candidate_item) { + if (candidate_item && candidate_item->age_set) { i->age = candidate_item->age; i->age_set = true; } @@ -1605,10 +1587,10 @@ int main(int argc, char *argv[]) { umask(0022); - label_init(NULL); + mac_selinux_init(NULL); - items = hashmap_new(string_hash_func, string_compare_func); - globs = hashmap_new(string_hash_func, string_compare_func); + items = hashmap_new(&string_hash_ops); + globs = hashmap_new(&string_hash_ops); if (!items || !globs) { r = log_oom(); @@ -1632,7 +1614,7 @@ int main(int argc, char *argv[]) { r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs); if (r < 0) { - log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r)); + log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m"); goto finish; } @@ -1665,7 +1647,7 @@ finish: set_free_free(unix_sockets); - label_finish(); + mac_selinux_finish(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }