summaryrefslogtreecommitdiff
path: root/src/tmpfiles
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-09-11 12:21:58 +0200
committerLennart Poettering <lennart@poettering.net>2022-09-23 09:20:37 +0200
commita9bc518c08d4d3a111b637e348f5a60e5a50025f (patch)
tree0d7250a5967f387b84d142679162481ed5155142 /src/tmpfiles
parentc5d554aa666f7d87113a1f93547ce122d5ad4d14 (diff)
downloadsystemd-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.c212
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: