diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index f8a79eca2f1..6782c74b807 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -180,6 +180,61 @@ int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) { return 0; } +int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) { + _cleanup_free_ char *upper = NULL, *destination = NULL; + _cleanup_strv_free_ char **lower = NULL; + CustomMount *m; + unsigned k = 0; + char **i; + int r; + + r = strv_split_extract(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + + STRV_FOREACH(i, lower) { + if (!path_is_absolute(*i)) + return -EINVAL; + + k++; + } + + if (k < 2) + return -EADDRNOTAVAIL; + if (k == 2) { + /* If two parameters are specified, + * the first one is the lower, the + * second one the upper directory. And + * we'll also define the destination + * mount point the same as the upper. */ + upper = lower[1]; + lower[1] = NULL; + + destination = strdup(upper); + if (!destination) + return -ENOMEM; + + } else { + upper = lower[k - 2]; + destination = lower[k - 1]; + lower[k - 2] = NULL; + } + + m = custom_mount_add(l, n, CUSTOM_MOUNT_OVERLAY); + if (!m) + return -ENOMEM; + + m->destination = destination; + m->source = upper; + m->lower = lower; + m->read_only = read_only; + + upper = destination = NULL; + lower = NULL; + + return 0; +} + static int tmpfs_patch_options( const char *options, bool userns, diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 74aee7ee7f5..83acd01e00a 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -61,8 +61,10 @@ typedef struct CustomMount { CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t); void custom_mount_free_all(CustomMount *l, unsigned n); + int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only); int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s); +int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only); int custom_mount_compare(const void *a, const void *b); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 9a308688e14..e739df7f722 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -789,69 +789,15 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_OVERLAY: - case ARG_OVERLAY_RO: { - _cleanup_free_ char *upper = NULL, *destination = NULL; - _cleanup_strv_free_ char **lower = NULL; - CustomMount *m; - unsigned n = 0; - char **i; - - r = strv_split_extract(&lower, optarg, ":", EXTRACT_DONT_COALESCE_SEPARATORS); - if (r == -ENOMEM) - return log_oom(); - else if (r < 0) { - log_error("Invalid overlay specification: %s", optarg); - return r; - } - - STRV_FOREACH(i, lower) { - if (!path_is_absolute(*i)) { - log_error("Overlay path %s is not absolute.", *i); - return -EINVAL; - } - - n++; - } - - if (n < 2) { - log_error("--overlay= needs at least two colon-separated directories specified."); - return -EINVAL; - } - - if (n == 2) { - /* If two parameters are specified, - * the first one is the lower, the - * second one the upper directory. And - * we'll also define the destination - * mount point the same as the upper. */ - upper = lower[1]; - lower[1] = NULL; - - destination = strdup(upper); - if (!destination) - return log_oom(); - - } else { - upper = lower[n - 2]; - destination = lower[n - 1]; - lower[n - 2] = NULL; - } - - m = custom_mount_add(&arg_custom_mounts, &arg_n_custom_mounts, CUSTOM_MOUNT_OVERLAY); - if (!m) - return log_oom(); - - m->destination = destination; - m->source = upper; - m->lower = lower; - m->read_only = c == ARG_OVERLAY_RO; - - upper = destination = NULL; - lower = NULL; + case ARG_OVERLAY_RO: + r = overlay_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg, c == ARG_OVERLAY_RO); + if (r == -EADDRNOTAVAIL) + return log_error_errno(r, "--overlay(-ro)= needs at least two colon-separated directories specified."); + if (r < 0) + return log_error_errno(r, "Failed to parse --overlay(-ro)= argument %s: %m", optarg); arg_settings_mask |= SETTING_CUSTOM_MOUNTS; break; - } case 'E': { char **n;