free(m->work_dir);
}
+ if (m->rm_rf_tmpdir) {
+ (void) rm_rf(m->rm_rf_tmpdir, REMOVE_ROOT|REMOVE_PHYSICAL);
+ free(m->rm_rf_tmpdir);
+ }
+
strv_free(m->lower);
}
free(m->source);
m->source = s;
+ } else {
+ /* No source specified? In that case, use a throw-away temporary directory in /var/tmp */
+
+ m->rm_rf_tmpdir = strdup("/var/tmp/nspawn-temp-XXXXXX");
+ if (!m->rm_rf_tmpdir)
+ return log_oom();
+
+ if (!mkdtemp(m->rm_rf_tmpdir)) {
+ m->rm_rf_tmpdir = mfree(m->rm_rf_tmpdir);
+ return log_error_errno(errno, "Failed to acquire temporary directory: %m");
+ }
+
+ m->source = strjoin(m->rm_rf_tmpdir, "/src");
+ if (!m->source)
+ return log_oom();
+
+ if (mkdir(m->source, 0755) < 0)
+ return log_error_errno(errno, "Failed to create %s: %m", m->source);
}
if (m->type == CUSTOM_MOUNT_OVERLAY) {
return -ENOMEM;
}
- if (!source_path_is_valid(source))
+ if (isempty(source))
+ source = NULL;
+ else if (!source_path_is_valid(source))
return -EINVAL;
+
if (!path_is_absolute(destination))
return -EINVAL;
if (!destination)
return -ENOMEM;
} else {
- int i;
+ char **i;
/* If more than two parameters are specified, the last one is the destination, the second to last one
* the "upper", and all before that the "lower" directories. */
- for (i = 0; i < k - 1; i++)
- if (!source_path_is_valid(lower[i]))
- return -EINVAL;
-
destination = lower[k - 1];
upper = lower[k - 2];
lower[k - 2] = NULL;
+ STRV_FOREACH(i, lower)
+ if (!source_path_is_valid(*i))
+ return -EINVAL;
+
+ /* If the upper directory is unspecified, then let's create it automatically as a throw-away directory
+ * in /var/tmp */
+ if (isempty(upper))
+ upper = NULL;
+ else if (!source_path_is_valid(upper))
+ return -EINVAL;
+
if (!path_is_absolute(destination))
return -EINVAL;
}
{ NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
{ "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL, NULL, MS_BIND, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ...*/
{ NULL, "/proc/sysrq-trigger", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, MOUNT_FATAL|MOUNT_IN_USERNS },
/* outer child mounts */
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, MOUNT_FATAL },
{ "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
{ "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
{ "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL }, /* skipped if above was mounted */
if (!ro && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_APIVFS_RO))
continue;
- r = chase_symlinks(mount_table[k].where, dest, CHASE_NON_EXISTING|CHASE_PREFIX_ROOT, &where);
+ r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where);
if (r < 0)
- return log_error_errno(r, "Failed to resolve %s: %m", mount_table[k].where);
+ return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where);
r = path_is_mount_point(where, NULL, 0);
if (r < 0 && r != -ENOENT)
if (stat(m->source, &source_st) < 0)
return log_error_errno(errno, "Failed to stat %s: %m", m->source);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NON_EXISTING, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0)
- return log_error_errno(r, "Failed to resolve %s: %m", m->destination);
+ return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r > 0) { /* Path exists already? */
if (stat(where, &dest_st) < 0)
assert(dest);
assert(m);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NON_EXISTING, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0)
- return log_error_errno(r, "Failed to resolve %s: %m", m->destination);
+ return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */
r = mkdir_p_label(where, 0755);
if (r < 0)
assert(dest);
assert(m);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NON_EXISTING, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0)
- return log_error_errno(r, "Failed to resolve %s: %m", m->destination);
+ return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */
r = mkdir_label(where, 0755);
if (r < 0)
(void) rmdir(template);
return r;
}
-
-VolatileMode volatile_mode_from_string(const char *s) {
- int b;
-
- if (isempty(s))
- return _VOLATILE_MODE_INVALID;
-
- b = parse_boolean(s);
- if (b > 0)
- return VOLATILE_YES;
- if (b == 0)
- return VOLATILE_NO;
-
- if (streq(s, "state"))
- return VOLATILE_STATE;
-
- return _VOLATILE_MODE_INVALID;
-}