diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2022-07-11 21:45:08 +0200 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2022-07-12 13:14:11 +0200 |
commit | 448f737730c38e65f45eeaf5cc257c253ad2c648 (patch) | |
tree | df02f6c1cff5d31cec264a3a03548caa26b292c6 /src/nspawn/nspawn-mount.c | |
parent | nspawn: Rewrap --overlay docs (diff) | |
download | systemd-448f737730c38e65f45eeaf5cc257c253ad2c648.tar.xz systemd-448f737730c38e65f45eeaf5cc257c253ad2c648.zip |
nspawn: Support relative source paths for --bind and --overlay
Diffstat (limited to 'src/nspawn/nspawn-mount.c')
-rw-r--r-- | src/nspawn/nspawn-mount.c | 83 |
1 files changed, 62 insertions, 21 deletions
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 26a2cc9e7e..60cb007baa 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -83,13 +83,38 @@ static int custom_mount_compare(const CustomMount *a, const CustomMount *b) { return CMP(a->type, b->type); } -static bool source_path_is_valid(const char *p) { +static int source_path_parse(const char *p, char **ret) { assert(p); + assert(ret); + + if (isempty(p)) + return -EINVAL; + + if (*p == '+') { + if (!path_is_absolute(p + 1)) + return -EINVAL; + + char *s = strdup(p); + if (!s) + return -ENOMEM; - if (*p == '+') - p++; + *ret = TAKE_PTR(s); + return 0; + } - return path_is_absolute(p); + return path_make_absolute_cwd(p, ret); +} + +static int source_path_parse_nullable(const char *p, char **ret) { + assert(p); + assert(ret); + + if (isempty(p)) { + *ret = NULL; + return 0; + } + + return source_path_parse(p, ret); } static char *resolve_source_path(const char *dest, const char *source) { @@ -212,7 +237,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n) { } int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) { - _cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL; + _cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL, *p = NULL; CustomMount *m; int r; @@ -235,10 +260,9 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) return -ENOMEM; } - if (isempty(source)) - source = mfree(source); - else if (!source_path_is_valid(source)) - return -EINVAL; + r = source_path_parse_nullable(source, &p); + if (r < 0) + return r; if (!path_is_absolute(destination)) return -EINVAL; @@ -247,7 +271,7 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) if (!m) return -ENOMEM; - m->source = TAKE_PTR(source); + m->source = TAKE_PTR(p); m->destination = TAKE_PTR(destination); m->read_only = read_only; m->options = TAKE_PTR(opts); @@ -295,7 +319,7 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl _cleanup_free_ char *upper = NULL, *destination = NULL; _cleanup_strv_free_ char **lower = NULL; CustomMount *m; - int k; + int r, k; k = strv_split_full(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (k < 0) @@ -303,12 +327,22 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl if (k < 2) return -EADDRNOTAVAIL; if (k == 2) { + _cleanup_free_ char *p = NULL; + /* 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. */ - if (!source_path_is_valid(lower[0]) || - !source_path_is_valid(lower[1])) - return -EINVAL; + r = source_path_parse(lower[0], &p); + if (r < 0) + return r; + + free_and_replace(lower[0], p); + + r = source_path_parse(lower[1], &p); + if (r < 0) + return r; + + free_and_replace(lower[1], p); upper = TAKE_PTR(lower[1]); @@ -316,22 +350,29 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl if (!destination) return -ENOMEM; } else { + _cleanup_free_ char *p = NULL; + /* 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. */ destination = lower[k - 1]; upper = TAKE_PTR(lower[k - 2]); - STRV_FOREACH(i, lower) - if (!source_path_is_valid(*i)) - return -EINVAL; + STRV_FOREACH(i, lower) { + r = source_path_parse(*i, &p); + if (r < 0) + return r; + + free_and_replace(*i, p); + } /* If the upper directory is unspecified, then let's create it automatically as a throw-away directory * in /var/tmp */ - if (isempty(upper)) - upper = mfree(upper); - else if (!source_path_is_valid(upper)) - return -EINVAL; + r = source_path_parse_nullable(upper, &p); + if (r < 0) + return r; + + free_and_replace(upper, p); if (!path_is_absolute(destination)) return -EINVAL; |