#include "def.h"
#include "dirent-util.h"
#include "dissect-image.h"
+#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "mountpoint-util.h"
#include "offline-passwd.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
CREATION_EXISTING,
CREATION_FORCE,
_CREATION_MODE_MAX,
- _CREATION_MODE_INVALID = -1
+ _CREATION_MODE_INVALID = -EINVAL,
} CreationMode;
static const char *const creation_mode_verb_table[_CREATION_MODE_MAX] = {
return pfd;
if (subvol) {
- if (btrfs_is_subvol(empty_to_root(arg_root)) <= 0)
-
+ r = getenv_bool("SYSTEMD_TMPFILES_FORCE_SUBVOL");
+ if (r < 0) {
+ if (r != -ENXIO) /* env var is unset */
+ log_warning_errno(r, "Cannot parse value of $SYSTEMD_TMPFILES_FORCE_SUBVOL, ignoring.");
+ r = btrfs_is_subvol(empty_to_root(arg_root)) > 0;
+ }
+ if (!r)
/* Don't create a subvolume unless the root directory is
* one, too. We do this under the assumption that if the
* root directory is just a plain directory (i.e. very
return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", path);
if (k < 0)
return log_error_errno(k, "Failed to check if %s exists: %m", path);
- if (!k) {
- log_warning("\"%s\" already exists and is not a directory.", path);
- return -EEXIST;
- }
+ if (!k)
+ return log_warning_errno(SYNTHETIC_ERRNO(EEXIST),
+ "\"%s\" already exists and is not a directory.", path);
*creation = CREATION_EXISTING;
} else
}
if (r < 0)
return log_error_errno(r, "is_dir() failed on path %s: %m", path);
- if (r == 0)
- return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
- "'%s' already exists and is not a directory.",
- path);
+ if (r == 0) {
+ log_warning("\"%s\" already exists and is not a directory.", path);
+ return 0;
+ }
return path_set_perms(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);
+ log_warning("\"%s\" already exists is not a device node.", i->path);
return 0;
}
} else
/* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence
* there's no immediate need for action by the user. However, in the interest of making things less confusing
* to the user, let's still inform the user that these snippets should really be updated. */
- log_syntax(NULL, LOG_NOTICE, fname, line, 0, "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", *path, n);
+ log_syntax(NULL, LOG_NOTICE, fname, line, 0,
+ "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.",
+ *path, n);
free_and_replace(*path, n);
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_root);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
if (r < 0)
return r;
break;
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"This systemd-tmpfiles version is compiled without support for --image=.");
#else
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
if (r < 0)
return r;
#endif
_cleanup_fclose_ FILE *_f = NULL;
unsigned v = 0;
FILE *f;
- Item *i;
+ ItemArray *ia;
int r = 0;
assert(fn);
}
/* we have to determine age parameter for each entry of type X */
- ORDERED_HASHMAP_FOREACH(i, globs) {
- Item *j, *candidate_item = NULL;
-
- if (i->type != IGNORE_DIRECTORY_PATH)
- continue;
+ ORDERED_HASHMAP_FOREACH(ia, globs)
+ for (size_t ni = 0; ni < ia->n_items; ni++) {
+ ItemArray *ja;
+ Item *i = ia->items + ni, *candidate_item = NULL;
- ORDERED_HASHMAP_FOREACH(j, items) {
- if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
+ if (i->type != IGNORE_DIRECTORY_PATH)
continue;
- if (path_equal(j->path, i->path)) {
- candidate_item = j;
- break;
- }
+ ORDERED_HASHMAP_FOREACH(ja, items)
+ for (size_t nj = 0; nj < ja->n_items; nj++) {
+ Item *j = ja->items + nj;
- if ((!candidate_item && path_startswith(i->path, j->path)) ||
- (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
- candidate_item = j;
- }
+ if (!IN_SET(j->type, CREATE_DIRECTORY,
+ TRUNCATE_DIRECTORY,
+ CREATE_SUBVOLUME,
+ CREATE_SUBVOLUME_INHERIT_QUOTA,
+ CREATE_SUBVOLUME_NEW_QUOTA))
+ continue;
+
+ if (path_equal(j->path, i->path)) {
+ candidate_item = j;
+ break;
+ }
- if (candidate_item && candidate_item->age_set) {
- i->age = candidate_item->age;
- i->age_set = true;
+ if (candidate_item
+ ? (path_startswith(j->path, candidate_item->path) && fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)
+ : path_startswith(i->path, j->path) != NULL)
+ candidate_item = j;
+ }
+
+ if (candidate_item && candidate_item->age_set) {
+ i->age = candidate_item->age;
+ i->age_set = true;
+ }
}
- }
if (ferror(f)) {
log_error_errno(errno, "Failed to read from file %s: %m", fn);
if (r <= 0)
return r;
- log_setup_service();
+ log_setup();
+
+ /* We require /proc/ for a lot of our operations, i.e. for adjusting access modes, for anything
+ * SELinux related, for recursive operation, for xattr, acl and chattr handling, for btrfs stuff and
+ * a lot more. It's probably the majority of invocations where /proc/ is required. Since people
+ * apparently invoke it without anyway and are surprised about the failures, let's catch this early
+ * and output a nice and friendly warning. */
+ if (proc_mounted() == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "/proc/ is not mounted, but required for successful operation of systemd-tmpfiles. "
+ "Please mount /proc/. Alternatively, consider using the --root= or --image= switches.");
/* Descending down file system trees might take a lot of fds */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
r = mount_image_privately_interactively(
arg_image,
- DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+ DISSECT_IMAGE_GENERIC_ROOT |
+ DISSECT_IMAGE_REQUIRE_ROOT |
+ DISSECT_IMAGE_VALIDATE_OS |
+ DISSECT_IMAGE_RELAX_VAR_CHECK |
+ DISSECT_IMAGE_FSCK,
&unlink_dir,
&loop_device,
&decrypted_image);