static bool arg_create = false;
static bool arg_clean = false;
static bool arg_remove = false;
-static bool arg_unsafe = false;
+static bool arg_boot = false;
static char **include_prefixes = NULL;
static char **exclude_prefixes = NULL;
+static char *arg_root = NULL;
static const char conf_file_dirs[] =
"/etc/tmpfiles.d\0"
}
static int dir_is_mount_point(DIR *d, const char *subdir) {
- struct file_handle *h;
+ union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ };
int mount_id_parent, mount_id;
int r_p, r;
- h = alloca(MAX_HANDLE_SZ);
-
- h->handle_bytes = MAX_HANDLE_SZ;
- r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0);
+ r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
if (r_p < 0)
r_p = -errno;
- h->handle_bytes = MAX_HANDLE_SZ;
- r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0);
+ h.handle.handle_bytes = MAX_HANDLE_SZ;
+ r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
if (r < 0)
r = -errno;
}
static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) {
- int r;
-
/* not using i->path directly because it may be a glob */
if (i->mode_set)
if (chmod(path, i->mode) < 0) {
}
}
- r = label_fix(path, false, false);
- return r == -ENOENT && ignore_enoent ? 0 : r;
+ return label_fix(path, ignore_enoent, false);
}
static int item_set_perms(Item *i, const char *path) {
unescaped = cunescape(i->argument);
if (unescaped == NULL) {
- close_nointr_nofail(fd);
+ safe_close(fd);
return log_oom();
}
if (n < 0 || (size_t) n < l) {
log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
- close_nointr_nofail(fd);
+ safe_close(fd);
return n < 0 ? n : -EIO;
}
}
- close_nointr_nofail(fd);
+ safe_close(fd);
if (stat(path, &st) < 0) {
log_error("stat(%s) failed: %m", path);
for (;;) {
struct dirent *de;
- bool is_dir;
+ bool dir;
int r;
_cleanup_free_ char *entry_path = NULL;
}
if (de->d_type == DT_UNKNOWN) {
- struct stat st;
-
- if (lstat(entry_path, &st) < 0) {
+ r = is_dir(entry_path);
+ if (r < 0) {
if (ret == 0 && errno != ENOENT)
ret = -errno;
continue;
}
- is_dir = S_ISDIR(st.st_mode);
+ dir = r;
} else
- is_dir = de->d_type == DT_DIR;
+ dir = de->d_type == DT_DIR;
r = item_set_perms(i, entry_path);
if (r < 0) {
continue;
}
- if (is_dir) {
+ if (dir) {
r = recursive_relabel_children(i, entry_path);
if (r < 0 && ret == 0)
ret = r;
break;
case CREATE_SYMLINK: {
- char *x;
+ _cleanup_free_ char *x = NULL;
label_context_set(i->path, S_IFLNK);
r = symlink(i->argument, i->path);
}
if (!streq(i->argument, x)) {
- free(x);
log_error("%s is not the right symlinks.", i->path);
return -EEXIST;
}
- free(x);
break;
}
if (strlen(action) > 2 || (strlen(action) > 1 && action[1] != '!')) {
log_error("[%s:%u] Unknown modifier '%s'", fname, line, action);
return -EINVAL;
- } else if (strlen(action) > 1 && !arg_unsafe)
+ } else if (strlen(action) > 1 && !arg_boot)
return 0;
type = action[0];
if (!should_include_path(i->path))
return 0;
+ if (arg_root) {
+ char *p = strappend(arg_root, i->path);
+ if (!p)
+ return log_oom();
+
+ free(i->path);
+ i->path = p;
+ }
+
if (user && !streq(user, "-")) {
const char *u = user;
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n"
- " --unsafe Execute actions only safe at boot\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",
+ " --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;
ARG_CREATE,
ARG_CLEAN,
ARG_REMOVE,
- ARG_UNSAFE,
+ ARG_BOOT,
ARG_PREFIX,
ARG_EXCLUDE_PREFIX,
+ ARG_ROOT,
};
static const struct option options[] = {
{ "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE },
- { "unsafe", no_argument, NULL, ARG_UNSAFE },
+ { "boot", no_argument, NULL, ARG_BOOT },
{ "prefix", required_argument, NULL, ARG_PREFIX },
{ "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
+ { "root", required_argument, NULL, ARG_ROOT },
{}
};
arg_remove = true;
break;
- case ARG_UNSAFE:
- arg_unsafe = true;
+ case ARG_BOOT:
+ arg_boot = true;
break;
case ARG_PREFIX:
- if (strv_extend(&include_prefixes, optarg) < 0)
+ if (strv_push(&include_prefixes, optarg) < 0)
return log_oom();
break;
case ARG_EXCLUDE_PREFIX:
- if (strv_extend(&exclude_prefixes, optarg) < 0)
+ if (strv_push(&exclude_prefixes, optarg) < 0)
+ return log_oom();
+ break;
+
+ case ARG_ROOT:
+ arg_root = path_make_absolute_cwd(optarg);
+ if (!arg_root)
return log_oom();
+ path_kill_slashes(arg_root);
break;
case '?':
assert(fn);
- r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f);
+ r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
_cleanup_strv_free_ char **files = NULL;
char **f;
- r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+ 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));
goto finish;
hashmap_free(items);
hashmap_free(globs);
- strv_free(include_prefixes);
+ free(include_prefixes);
+ free(exclude_prefixes);
+ free(arg_root);
set_free_free(unix_sockets);