X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Ftmpfiles%2Ftmpfiles.c;h=a0ff76dcf0196e366e224d4f0d083290083cb666;hb=15411c0cb1192799b37ec8f25d6f30e8d7292fc6;hp=d70dbc470753676428c8b7fa6c47b8bd54118b24;hpb=df99a9ef5bb7a89b92ccfb103b2f3e7046c62ef5;p=elogind.git diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index d70dbc470..a0ff76dcf 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -37,8 +35,6 @@ #include #include #include -#include -#include #include #include "log.h" @@ -465,18 +461,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 @@ -688,7 +678,6 @@ static int path_set_xattrs(Item *i, const char *path) { static int get_acls_from_arg(Item *item) { #ifdef HAVE_ACL int r; - _cleanup_(acl_freep) acl_t a = NULL, d = NULL; assert(item); @@ -696,7 +685,7 @@ static int get_acls_from_arg(Item *item) { * afterwards, so the mask can be added now if necessary. */ r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force); if (r < 0) - log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring", + log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument); #else log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring"); @@ -705,11 +694,15 @@ static int get_acls_from_arg(Item *item) { return 0; } +#ifdef HAVE_ACL static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) { _cleanup_(acl_freep) acl_t dup = NULL; int r; _cleanup_(acl_free_charpp) char *t = NULL; + /* Returns 0 for success, positive error if already warned, + * negative error otherwise. */ + if (modify) { r = acls_for_file(path, type, acl, &dup); if (r < 0) @@ -737,34 +730,36 @@ static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modif r = acl_set_file(path, type, dup); if (r < 0) - return log_error_errno(-errno, - "Setting %s ACL \"%s\" on %s failed: %m", - type == ACL_TYPE_ACCESS ? "access" : "default", - strna(t), path); + return -log_error_errno(errno, + "Setting %s ACL \"%s\" on %s failed: %m", + type == ACL_TYPE_ACCESS ? "access" : "default", + strna(t), path); + return 0; } +#endif static int path_set_acls(Item *item, const char *path) { + int r = 0; #ifdef HAVE_ACL - int r; - assert(item); assert(path); - if (item->acl_access) { + if (item->acl_access) r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force); - if (r < 0) - return r; - } - if (item->acl_default) { + if (r == 0 && item->acl_default) r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force); - if (r < 0) - return r; - } -#endif - return 0; + if (r > 0) + return -r; /* already warned */ + else if (r == -EOPNOTSUPP) { + log_debug_errno(r, "ACLs not supported by file system at %s", path); + return 0; + } else if (r < 0) + log_error_errno(r, "ACL operation on \"%s\" failed: %m", path); +#endif + return r; } static int write_one_file(Item *i, const char *path) { @@ -879,17 +874,13 @@ static int item_do_children(Item *i, const char *path, action_t action) { } static int glob_item(Item *i, action_t action, bool recursive) { -DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES -DISABLE_WARNING_DECLARATION_AFTER_STATEMENT _cleanup_globfree_ glob_t g = { - .gl_closedir = closedir, - .gl_readdir = readdir, - .gl_opendir = opendir_nomod, + .gl_closedir = (void (*)(void *)) closedir, + .gl_readdir = (struct dirent *(*)(void *)) readdir, + .gl_opendir = (void *(*)(const char *)) opendir_nomod, .gl_lstat = lstat, .gl_stat = stat, }; -REENABLE_WARNING -REENABLE_WARNING int r = 0, k; char **fn; @@ -913,9 +904,26 @@ REENABLE_WARNING return r; } +typedef enum { + CREATION_NORMAL, + CREATION_EXISTING, + CREATION_FORCE, + _CREATION_MODE_MAX, + _CREATION_MODE_INVALID = -1 +} CreationMode; + +static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = { + [CREATION_NORMAL] = "Created", + [CREATION_EXISTING] = "Found existing", + [CREATION_FORCE] = "Created replacement", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode); + static int create_item(Item *i) { struct stat st; int r = 0; + CreationMode creation; assert(i); @@ -1000,8 +1008,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_mode_verb_to_string(creation), i->path); r = path_set_perms(i, i->path); if (r < 0) @@ -1036,13 +1047,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_mode_verb_to_string(creation), i->path); r = path_set_perms(i, i->path); if (r < 0) @@ -1072,13 +1086,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_mode_verb_to_string(creation), i->path); break; @@ -1128,14 +1145,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_mode_verb_to_string(creation), i->type == CREATE_BLOCK_DEVICE ? "block" : "char", i->path, major(i->mode), minor(i->mode)); @@ -1485,23 +1506,25 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { _cleanup_(item_free_contents) Item i = {}; ItemArray *existing; Hashmap *h; - int r, c = -1, pos; + int r, pos; bool force = false, boot = false; assert(fname); assert(line >= 1); assert(buffer); - r = sscanf(buffer, - "%ms %ms %ms %ms %ms %ms %n", + r = unquote_many_words(&buffer, &action, &path, &mode, &user, &group, &age, - &c); - if (r < 2) { + &i.argument, + NULL); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line); + else if (r < 2) { log_error("[%s:%u] Syntax error.", fname, line); return -EIO; } @@ -1538,15 +1561,6 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { return r; } - if (c >= 0) { - c += strspn(buffer+c, WHITESPACE); - if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) { - i.argument = unquote(buffer+c, "\""); - if (!i.argument) - return log_oom(); - } - } - switch (i.type) { case CREATE_FILE: @@ -1725,9 +1739,11 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { unsigned n; for (n = 0; n < existing->count; n++) { - if (!item_compatible(existing->items + n, &i)) + if (!item_compatible(existing->items + n, &i)) { log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.", fname, line, i.path); + return 0; + } } } else { existing = new0(ItemArray, 1); @@ -1753,8 +1769,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); }