X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ftmpfiles%2Ftmpfiles.c;h=7edeeb742840ffbe96ed32a7b0e8c8b8873ee121;hp=7081b4dc57eb5d1b03fa6a87c56b38c2844fcb91;hb=dd4105b0a90c3c146a01e5a7734ee76c3a9aa1cd;hpb=f8eeeaf9b783ebbab30672629abf3920db286811 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 7081b4dc5..7edeeb742 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -76,10 +76,12 @@ typedef enum ItemType { CREATE_CHAR_DEVICE = 'c', CREATE_BLOCK_DEVICE = 'b', COPY_FILES = 'C', - SET_XATTR = 't', - SET_ACL = 'a', /* These ones take globs */ + SET_XATTR = 't', + RECURSIVE_SET_XATTR = 'T', + SET_ACL = 'a', + RECURSIVE_SET_ACL = 'A', WRITE_FILE = 'w', IGNORE_PATH = 'x', IGNORE_DIRECTORY_PATH = 'X', @@ -151,7 +153,11 @@ static bool needs_glob(ItemType t) { RECURSIVE_REMOVE_PATH, ADJUST_MODE, RELABEL_PATH, - RECURSIVE_RELABEL_PATH); + RECURSIVE_RELABEL_PATH, + SET_XATTR, + RECURSIVE_SET_XATTR, + SET_ACL, + RECURSIVE_SET_ACL); } static bool takes_ownership(ItemType t) { @@ -486,7 +492,7 @@ finish: return r; } -static int item_set_perms(Item *i, const char *path) { +static int path_set_perms(Item *i, const char *path) { struct stat st; bool st_valid; @@ -568,7 +574,7 @@ static int get_xattrs_from_arg(Item *i) { return r; } -static int item_set_xattrs(Item *i, const char *path) { +static int path_set_xattrs(Item *i, const char *path) { char **name, **value; assert(i); @@ -594,7 +600,9 @@ static int get_acls_from_arg(Item *item) { assert(item); - r = parse_acl(item->argument, &item->acl_access, &item->acl_default); + /* If force (= modify) is set, we will not modify the acl + * 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", item->argument); @@ -605,7 +613,46 @@ static int get_acls_from_arg(Item *item) { return 0; } -static int item_set_acl(Item *item, const char *path) { +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; + + if (modify) { + r = acls_for_file(path, type, acl, &dup); + if (r < 0) + return r; + + r = calc_acl_mask_if_needed(&dup); + if (r < 0) + return r; + } else { + dup = acl_dup(acl); + if (!dup) + return -errno; + + /* the mask was already added earlier if needed */ + } + + r = add_base_acls_if_needed(&dup, path); + if (r < 0) + return r; + + r = acl_set_file(path, type, dup); + if (r < 0) { + _cleanup_(acl_free_charpp) char *t; + + r = -errno; + t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE); + log_error_errno(r, + "Setting %s ACL \"%s\" on %s failed: %m", + type == ACL_TYPE_ACCESS ? "access" : "default", + strna(t), path); + } + + return r; +} + +static int path_set_acls(Item *item, const char *path) { #ifdef HAVE_ACL int r; @@ -613,27 +660,15 @@ static int item_set_acl(Item *item, const char *path) { assert(path); if (item->acl_access) { - r = acl_set_file(path, ACL_TYPE_ACCESS, item->acl_access); - if (r < 0) { - _cleanup_(acl_free_charpp) char *t; - - t = acl_to_any_text(item->acl_access, NULL, ',', TEXT_ABBREVIATE); - return log_error_errno(errno, - "Setting access ACL \"%s\" on %s failed: %m", - strna(t), path); - } + r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force); + if (r < 0) + return r; } if (item->acl_default) { - r = acl_set_file(path, ACL_TYPE_DEFAULT, item->acl_default); - if (r < 0) { - _cleanup_(acl_free_charpp) char *t; - - t = acl_to_any_text(item->acl_default, NULL, ',', TEXT_ABBREVIATE); - return log_error_errno(errno, - "Setting default ACL \"%s\" on %s failed: %m", - strna(t), path); - } + r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force); + if (r < 0) + return r; } #endif @@ -693,14 +728,16 @@ static int write_one_file(Item *i, const char *path) { return -EEXIST; } - r = item_set_perms(i, path); + r = path_set_perms(i, path); if (r < 0) return r; return 0; } -static int item_set_perms_children(Item *i, const char *path) { +typedef int (*action_t)(Item *, const char *); + +static int item_do_children(Item *i, const char *path, action_t action) { _cleanup_closedir_ DIR *d; int r = 0; @@ -735,12 +772,12 @@ static int item_set_perms_children(Item *i, const char *path) { if (!p) return -ENOMEM; - q = item_set_perms(i, p); + q = action(i, p); if (q < 0 && q != -ENOENT && r == 0) r = q; if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) { - q = item_set_perms_children(i, p); + q = item_do_children(i, p, action); if (q < 0 && r == 0) r = q; } @@ -749,42 +786,26 @@ static int item_set_perms_children(Item *i, const char *path) { return r; } -static int item_set_perms_recursive(Item *i, const char *path) { - int r, q; - - assert(i); - assert(path); - - r = item_set_perms(i, path); - if (r < 0) - return r; - - q = item_set_perms_children(i, path); - if (q < 0 && r == 0) - r = q; - - return r; -} - -static int glob_item(Item *i, int (*action)(Item *, const char *)) { +static int glob_item(Item *i, action_t action, bool recursive) { _cleanup_globfree_ glob_t g = {}; int r = 0, k; char **fn; errno = 0; k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); - if (k != 0 && k != GLOB_NOMATCH) { - if (errno == 0) - errno = EIO; - - log_error_errno(errno, "glob(%s) failed: %m", i->path); - return -errno; - } + if (k != 0 && k != GLOB_NOMATCH) + return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path); STRV_FOREACH(fn, g.gl_pathv) { k = action(i, *fn); if (k < 0 && r == 0) r = k; + + if (recursive) { + k = item_do_children(i, *fn, action); + if (k < 0 && r == 0) + r = k; + } } return r; @@ -831,14 +852,14 @@ static int create_item(Item *i) { } } - r = item_set_perms(i, i->path); + r = path_set_perms(i, i->path); if (r < 0) return r; break; case WRITE_FILE: - r = glob_item(i, write_one_file); + r = glob_item(i, write_one_file, false); if (r < 0) return r; @@ -875,7 +896,7 @@ static int create_item(Item *i) { } } - r = item_set_perms(i, i->path); + r = path_set_perms(i, i->path); if (r < 0) return r; @@ -915,7 +936,7 @@ static int create_item(Item *i) { } } - r = item_set_perms(i, i->path); + r = path_set_perms(i, i->path); if (r < 0) return r; @@ -1006,7 +1027,7 @@ static int create_item(Item *i) { } } - r = item_set_perms(i, i->path); + r = path_set_perms(i, i->path); if (r < 0) return r; @@ -1015,29 +1036,40 @@ static int create_item(Item *i) { case ADJUST_MODE: case RELABEL_PATH: - - r = glob_item(i, item_set_perms); + r = glob_item(i, path_set_perms, false); if (r < 0) return r; break; case RECURSIVE_RELABEL_PATH: - - r = glob_item(i, item_set_perms_recursive); + r = glob_item(i, path_set_perms, true); if (r < 0) return r; break; case SET_XATTR: - r = item_set_xattrs(i, i->path); + r = glob_item(i, path_set_xattrs, false); + if (r < 0) + return r; + break; + + case RECURSIVE_SET_XATTR: + r = glob_item(i, path_set_xattrs, true); if (r < 0) return r; break; case SET_ACL: - r = item_set_acl(i, i->path); + r = glob_item(i, path_set_acls, false); + if (r < 0) + return r; + break; + + case RECURSIVE_SET_ACL: + r = glob_item(i, path_set_acls, true); if (r < 0) return r; + break; } log_debug("%s created successfully.", i->path); @@ -1068,7 +1100,9 @@ static int remove_item_instance(Item *i, const char *instance) { case WRITE_FILE: case COPY_FILES: case SET_XATTR: + case RECURSIVE_SET_XATTR: case SET_ACL: + case RECURSIVE_SET_ACL: break; case REMOVE_PATH: @@ -1114,13 +1148,15 @@ static int remove_item(Item *i) { case WRITE_FILE: case COPY_FILES: case SET_XATTR: + case RECURSIVE_SET_XATTR: case SET_ACL: + case RECURSIVE_SET_ACL: break; case REMOVE_PATH: case TRUNCATE_DIRECTORY: case RECURSIVE_REMOVE_PATH: - r = glob_item(i, remove_item_instance); + r = glob_item(i, remove_item_instance, false); break; } @@ -1187,7 +1223,7 @@ static int clean_item(Item *i) { clean_item_instance(i, i->path); break; case IGNORE_DIRECTORY_PATH: - r = glob_item(i, clean_item_instance); + r = glob_item(i, clean_item_instance, false); break; default: break; @@ -1458,6 +1494,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { } case SET_XATTR: + case RECURSIVE_SET_XATTR: if (!i.argument) { log_error("[%s:%u] Set extended attribute requires argument.", fname, line); return -EBADMSG; @@ -1468,6 +1505,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { break; case SET_ACL: + case RECURSIVE_SET_ACL: if (!i.argument) { log_error("[%s:%u] Set ACLs requires argument.", fname, line); return -EBADMSG;