diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-09-11 12:21:58 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2022-09-23 09:20:37 +0200 |
commit | a9bc518c08d4d3a111b637e348f5a60e5a50025f (patch) | |
tree | 0d7250a5967f387b84d142679162481ed5155142 /src/tmpfiles | |
parent | c5d554aa666f7d87113a1f93547ce122d5ad4d14 (diff) | |
download | systemd-a9bc518c08d4d3a111b637e348f5a60e5a50025f.tar.gz |
tmpfiles: generalize CreationMode and pass it everywhere
For some purposes we had CreationMode which indicates whether an inode
was created by us, or is pre-existing. Let's generalize that for *all*
operations. This is later useful to conditionalize certain operations on
that (and makes the codebase more systematic)
Diffstat (limited to 'src/tmpfiles')
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 212 |
1 files changed, 140 insertions, 72 deletions
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 7b1e84e8af..b29614d9a5 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -180,6 +180,14 @@ typedef enum DirectoryType { _DIRECTORY_TYPE_MAX, } DirectoryType; +typedef enum { + CREATION_NORMAL, + CREATION_EXISTING, + CREATION_FORCE, + _CREATION_MODE_MAX, + _CREATION_MODE_INVALID = -EINVAL, +} CreationMode; + static bool arg_cat_config = false; static bool arg_user = false; static OperationMask arg_operation = 0; @@ -205,6 +213,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_exclude_prefixes, freep); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); +static const char *const 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 specifier_machine_id_safe(char specifier, const void *data, const char *root, const void *userdata, char **ret) { int r; @@ -844,7 +860,13 @@ static mode_t process_mask_perms(mode_t mode, mode_t current) { return mode; } -static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st) { +static int fd_set_perms( + Item *i, + int fd, + const char *path, + const struct stat *st, + CreationMode creation) { + struct stat stbuf; mode_t new_mode; bool do_chown; @@ -979,7 +1001,11 @@ static int path_open_safe(const char *path) { return fd; } -static int path_set_perms(Item *i, const char *path) { +static int path_set_perms( + Item *i, + const char *path, + CreationMode creation) { + _cleanup_close_ int fd = -1; assert(i); @@ -989,7 +1015,7 @@ static int path_set_perms(Item *i, const char *path) { if (fd < 0) return fd; - return fd_set_perms(i, fd, path, NULL); + return fd_set_perms(i, fd, path, /* st= */ NULL, creation); } static int parse_xattrs_from_arg(Item *i) { @@ -1028,7 +1054,13 @@ static int parse_xattrs_from_arg(Item *i) { return 0; } -static int fd_set_xattrs(Item *i, int fd, const char *path, const struct stat *st) { +static int fd_set_xattrs( + Item *i, + int fd, + const char *path, + const struct stat *st, + CreationMode creation) { + assert(i); assert(fd >= 0); assert(path); @@ -1042,7 +1074,11 @@ static int fd_set_xattrs(Item *i, int fd, const char *path, const struct stat *s return 0; } -static int path_set_xattrs(Item *i, const char *path) { +static int path_set_xattrs( + Item *i, + const char *path, + CreationMode creation) { + _cleanup_close_ int fd = -1; assert(i); @@ -1052,7 +1088,7 @@ static int path_set_xattrs(Item *i, const char *path) { if (fd < 0) return fd; - return fd_set_xattrs(i, fd, path, NULL); + return fd_set_xattrs(i, fd, path, /* st = */ NULL, creation); } static int parse_acls_from_arg(Item *item) { @@ -1075,7 +1111,13 @@ static int parse_acls_from_arg(Item *item) { } #if HAVE_ACL -static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) { +static int path_set_acl( + const char *path, + const char *pretty, + acl_type_t type, + acl_t acl, + bool modify) { + _cleanup_(acl_free_charpp) char *t = NULL; _cleanup_(acl_freep) acl_t dup = NULL; int r; @@ -1124,7 +1166,13 @@ static int path_set_acl(const char *path, const char *pretty, acl_type_t type, a } #endif -static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *st) { +static int fd_set_acls( + Item *item, + int fd, + const char *path, + const struct stat *st, + CreationMode creation) { + int r = 0; #if HAVE_ACL struct stat stbuf; @@ -1174,7 +1222,7 @@ static int fd_set_acls(Item *item, int fd, const char *path, const struct stat * return r; } -static int path_set_acls(Item *item, const char *path) { +static int path_set_acls(Item *item, const char *path, CreationMode creation) { int r = 0; #if HAVE_ACL _cleanup_close_ int fd = -1; @@ -1186,7 +1234,7 @@ static int path_set_acls(Item *item, const char *path) { if (fd < 0) return fd; - r = fd_set_acls(item, fd, path, NULL); + r = fd_set_acls(item, fd, path, /* st= */ NULL, creation); #endif return r; } @@ -1275,7 +1323,13 @@ static int parse_attribute_from_arg(Item *item) { return 0; } -static int fd_set_attribute(Item *item, int fd, const char *path, const struct stat *st) { +static int fd_set_attribute( + Item *item, + int fd, + const char *path, + const struct stat *st, + CreationMode creation) { + _cleanup_close_ int procfs_fd = -1; struct stat stbuf; unsigned f; @@ -1325,7 +1379,7 @@ static int fd_set_attribute(Item *item, int fd, const char *path, const struct s return 0; } -static int path_set_attribute(Item *item, const char *path) { +static int path_set_attribute(Item *item, const char *path, CreationMode creation) { _cleanup_close_ int fd = -1; if (!item->attribute_set || item->attribute_mask == 0) @@ -1335,7 +1389,7 @@ static int path_set_attribute(Item *item, const char *path) { if (fd < 0) return fd; - return fd_set_attribute(item, fd, path, NULL); + return fd_set_attribute(item, fd, path, /* st= */ NULL, creation); } static int write_argument_data(Item *i, int fd, const char *path) { @@ -1359,7 +1413,7 @@ static int write_argument_data(Item *i, int fd, const char *path) { return 0; } -static int write_one_file(Item *i, const char *path) { +static int write_one_file(Item *i, const char *path, CreationMode creation) { _cleanup_close_ int fd = -1, dir_fd = -1; _cleanup_free_ char *bn = NULL; int r; @@ -1402,13 +1456,14 @@ static int write_one_file(Item *i, const char *path) { if (r < 0) return r; - return fd_set_perms(i, fd, path, NULL); + return fd_set_perms(i, fd, path, NULL, creation); } static int create_file(Item *i, const char *path) { _cleanup_close_ int fd = -1, dir_fd = -1; _cleanup_free_ char *bn = NULL; struct stat stbuf, *st = NULL; + CreationMode creation; int r = 0; assert(i); @@ -1457,19 +1512,25 @@ static int create_file(Item *i, const char *path) { path); st = &stbuf; - } else if (item_binary_argument(i)) { - r = write_argument_data(i, fd, path); - if (r < 0) - return r; + creation = CREATION_EXISTING; + } else { + if (item_binary_argument(i)) { + r = write_argument_data(i, fd, path); + if (r < 0) + return r; + } + + creation = CREATION_NORMAL; } - return fd_set_perms(i, fd, path, st); + return fd_set_perms(i, fd, path, st, creation); } static int truncate_file(Item *i, const char *path) { _cleanup_close_ int fd = -1, dir_fd = -1; _cleanup_free_ char *bn = NULL; struct stat stbuf, *st = NULL; + CreationMode creation; bool erofs = false; int r = 0; @@ -1493,10 +1554,16 @@ static int truncate_file(Item *i, const char *path) { if (dir_fd < 0) return dir_fd; - RUN_WITH_UMASK(0000) { - mac_selinux_create_file_prepare(path, S_IFREG); - fd = RET_NERRNO(openat(dir_fd, bn, O_CREAT|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode)); - mac_selinux_create_file_clear(); + creation = CREATION_EXISTING; + fd = RET_NERRNO(openat(dir_fd, bn, O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode)); + if (fd == -ENOENT) { + creation = CREATION_NORMAL; /* Didn't work without O_CREATE, try again with */ + + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(path, S_IFREG); + fd = RET_NERRNO(openat(dir_fd, bn, O_CREAT|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode)); + mac_selinux_create_file_clear(); + } } if (fd < 0) { @@ -1518,6 +1585,7 @@ static int truncate_file(Item *i, const char *path) { } erofs = true; + creation = CREATION_EXISTING; } if (fstat(fd, &stbuf) < 0) @@ -1544,7 +1612,7 @@ static int truncate_file(Item *i, const char *path) { return r; } - return fd_set_perms(i, fd, path, st); + return fd_set_perms(i, fd, path, st, creation); } static int copy_files(Item *i) { @@ -1597,36 +1665,22 @@ static int copy_files(Item *i) { if (fd < 0) return log_error_errno(errno, "Failed to openat(%s): %m", i->path); - return fd_set_perms(i, fd, i->path, NULL); + return fd_set_perms(i, fd, i->path, /* st = */ NULL, _CREATION_MODE_INVALID); } -typedef enum { - CREATION_NORMAL, - CREATION_EXISTING, - CREATION_FORCE, - _CREATION_MODE_MAX, - _CREATION_MODE_INVALID = -EINVAL, -} CreationMode; - -static const char *const 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_directory_or_subvolume( + const char *path, + mode_t mode, + bool subvol, + CreationMode *ret_creation) { -static int create_directory_or_subvolume(const char *path, mode_t mode, bool subvol, CreationMode *creation) { _cleanup_free_ char *bn = NULL; _cleanup_close_ int pfd = -1; CreationMode c; - int r; + int r, fd; assert(path); - if (!creation) - creation = &c; - r = path_extract_filename(path, &bn); if (r < 0) return log_error_errno(r, "Failed to extract filename from path '%s': %m", path); @@ -1677,32 +1731,36 @@ static int create_directory_or_subvolume(const char *path, mode_t mode, bool sub return log_warning_errno(SYNTHETIC_ERRNO(EEXIST), "\"%s\" already exists and is not a directory.", path); - *creation = CREATION_EXISTING; + c = CREATION_EXISTING; } else - *creation = CREATION_NORMAL; + c = CREATION_NORMAL; - log_debug("%s directory \"%s\".", creation_mode_verb_to_string(*creation), path); + log_debug("%s directory \"%s\".", creation_mode_verb_to_string(c), path); - r = openat(pfd, bn, O_NOCTTY|O_CLOEXEC|O_DIRECTORY); - if (r < 0) + fd = openat(pfd, bn, O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) return log_error_errno(errno, "Failed to open directory '%s': %m", bn); - return r; + if (ret_creation) + *ret_creation = c; + + return fd; } static int create_directory(Item *i, const char *path) { _cleanup_close_ int fd = -1; + CreationMode creation; assert(i); assert(IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY)); - fd = create_directory_or_subvolume(path, i->mode, false, NULL); + fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, &creation); if (fd == -EEXIST) return 0; if (fd < 0) return fd; - return fd_set_perms(i, fd, path, NULL); + return fd_set_perms(i, fd, path, /* st= */ NULL, creation); } static int create_subvolume(Item *i, const char *path) { @@ -1713,7 +1771,7 @@ static int create_subvolume(Item *i, const char *path) { assert(i); assert(IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)); - fd = create_directory_or_subvolume(path, i->mode, true, &creation); + fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, &creation); if (fd == -EEXIST) return 0; if (fd < 0) @@ -1736,14 +1794,14 @@ static int create_subvolume(Item *i, const char *path) { log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path); } - r = fd_set_perms(i, fd, path, NULL); + r = fd_set_perms(i, fd, path, /* st= */ NULL, creation); if (q < 0) /* prefer the quota change error from above */ return q; return r; } -static int empty_directory(Item *i, const char *path) { +static int empty_directory(Item *i, const char *path, CreationMode creation) { int r; assert(i); @@ -1763,7 +1821,7 @@ static int empty_directory(Item *i, const char *path) { return 0; } - return path_set_perms(i, path); + return path_set_perms(i, path, creation); } static int create_device(Item *i, mode_t file_type) { @@ -1841,7 +1899,7 @@ static int create_device(Item *i, mode_t file_type) { if (fd < 0) return log_error_errno(errno, "Failed to openat(%s): %m", i->path); - return fd_set_perms(i, fd, i->path, NULL); + return fd_set_perms(i, fd, i->path, /* st = */ NULL, creation); } static int create_fifo(Item *i, const char *path) { @@ -1901,13 +1959,19 @@ static int create_fifo(Item *i, const char *path) { if (fd < 0) return log_error_errno(errno, "Failed to openat(%s): %m", path); - return fd_set_perms(i, fd, i->path, NULL); + return fd_set_perms(i, fd, i->path, /* st = */ NULL, creation); } -typedef int (*action_t)(Item *i, const char *path); -typedef int (*fdaction_t)(Item *i, int fd, const char *path, const struct stat *st); +typedef int (*action_t)(Item *i, const char *path, CreationMode creation); +typedef int (*fdaction_t)(Item *i, int fd, const char *path, const struct stat *st, CreationMode creation); + +static int item_do( + Item *i, + int fd, + const char *path, + CreationMode creation, + fdaction_t action) { -static int item_do(Item *i, int fd, const char *path, fdaction_t action) { struct stat st; int r = 0, q; @@ -1920,9 +1984,8 @@ static int item_do(Item *i, int fd, const char *path, fdaction_t action) { goto finish; } - /* This returns the first error we run into, but nevertheless - * tries to go on */ - r = action(i, fd, path, &st); + /* This returns the first error we run into, but nevertheless tries to go on */ + r = action(i, fd, path, &st, creation); if (S_ISDIR(st.st_mode)) { _cleanup_closedir_ DIR *d = NULL; @@ -1954,7 +2017,7 @@ static int item_do(Item *i, int fd, const char *path, fdaction_t action) { q = log_oom(); else /* Pass ownership of dirent fd over */ - q = item_do(i, de_fd, de_path, action); + q = item_do(i, de_fd, de_path, CREATION_EXISTING, action); } if (q < 0 && r == 0) @@ -1977,7 +2040,8 @@ static int glob_item(Item *i, action_t action) { return log_error_errno(k, "glob(%s) failed: %m", i->path); STRV_FOREACH(fn, g.gl_pathv) { - k = action(i, *fn); + /* We pass CREATION_EXISTING here, since if we are globbing for it, it always has to exist */ + k = action(i, *fn, CREATION_EXISTING); if (k < 0 && r == 0) r = k; } @@ -2011,7 +2075,7 @@ static int glob_item_recursively(Item *i, fdaction_t action) { continue; } - k = item_do(i, fd, *fn, action); + k = item_do(i, fd, *fn, CREATION_EXISTING, action); if (k < 0 && r == 0) r = k; @@ -2404,7 +2468,7 @@ static int create_item(Item *i) { return 0; } -static int remove_item_instance(Item *i, const char *instance) { +static int remove_item_instance(Item *i, const char *instance, CreationMode creation) { int r; assert(i); @@ -2477,7 +2541,11 @@ static char *age_by_to_string(AgeBy ab, bool is_dir) { return ret; } -static int clean_item_instance(Item *i, const char* instance) { +static int clean_item_instance( + Item *i, + const char* instance, + CreationMode creation) { + _cleanup_closedir_ DIR *d = NULL; STRUCT_STATX_DEFINE(sx); int mountpoint, r; @@ -2562,7 +2630,7 @@ static int clean_item(Item *i) { case TRUNCATE_DIRECTORY: case IGNORE_PATH: case COPY_FILES: - clean_item_instance(i, i->path); + clean_item_instance(i, i->path, CREATION_EXISTING); return 0; case EMPTY_DIRECTORY: case IGNORE_DIRECTORY_PATH: |