mirror of
https://github.com/systemd/systemd
synced 2024-07-22 02:34:54 +00:00
nspawn: Support relative source paths for --bind and --overlay
This commit is contained in:
parent
f075e32ca1
commit
448f737730
|
@ -1357,7 +1357,8 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
|
||||||
source path is taken relative to the image's root directory. This permits setting up bind mounts within the
|
source path is taken relative to the image's root directory. This permits setting up bind mounts within the
|
||||||
container image. The source path may be specified as empty string, in which case a temporary directory below
|
container image. The source path may be specified as empty string, in which case a temporary directory below
|
||||||
the host's <filename>/var/tmp/</filename> directory is used. It is automatically removed when the container is
|
the host's <filename>/var/tmp/</filename> directory is used. It is automatically removed when the container is
|
||||||
shut down. The <option>--bind-ro=</option> option creates read-only bind mounts. Backslash escapes are interpreted,
|
shut down. If the source path is not absolute, it is resolved relative to the current working directory.
|
||||||
|
The <option>--bind-ro=</option> option creates read-only bind mounts. Backslash escapes are interpreted,
|
||||||
so <literal>\:</literal> may be used to embed colons in either path. This option may be specified
|
so <literal>\:</literal> may be used to embed colons in either path. This option may be specified
|
||||||
multiple times for creating multiple independent bind mount points.</para>
|
multiple times for creating multiple independent bind mount points.</para>
|
||||||
|
|
||||||
|
@ -1481,7 +1482,8 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
|
||||||
used. The directory is removed automatically when the container is shut down. This behaviour is
|
used. The directory is removed automatically when the container is shut down. This behaviour is
|
||||||
useful in order to make read-only container directories writable while the container is running. For
|
useful in order to make read-only container directories writable while the container is running. For
|
||||||
example, use <literal>--overlay=+/var::/var</literal> in order to automatically overlay a writable
|
example, use <literal>--overlay=+/var::/var</literal> in order to automatically overlay a writable
|
||||||
temporary directory on a read-only <filename>/var/</filename> directory.</para>
|
temporary directory on a read-only <filename>/var/</filename> directory. If a source path is not
|
||||||
|
absolute, it is resolved relative to the current working directory.</para>
|
||||||
|
|
||||||
<para>For details about overlay file systems, see <ulink
|
<para>For details about overlay file systems, see <ulink
|
||||||
url="https://docs.kernel.org/filesystems/overlayfs.html">Overlay Filesystem</ulink>.
|
url="https://docs.kernel.org/filesystems/overlayfs.html">Overlay Filesystem</ulink>.
|
||||||
|
|
|
@ -83,13 +83,38 @@ static int custom_mount_compare(const CustomMount *a, const CustomMount *b) {
|
||||||
return CMP(a->type, b->type);
|
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(p);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
if (*p == '+')
|
if (isempty(p))
|
||||||
p++;
|
return -EINVAL;
|
||||||
|
|
||||||
return path_is_absolute(p);
|
if (*p == '+') {
|
||||||
|
if (!path_is_absolute(p + 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
char *s = strdup(p);
|
||||||
|
if (!s)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*ret = TAKE_PTR(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
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) {
|
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;
|
CustomMount *m;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -235,10 +260,9 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isempty(source))
|
r = source_path_parse_nullable(source, &p);
|
||||||
source = mfree(source);
|
if (r < 0)
|
||||||
else if (!source_path_is_valid(source))
|
return r;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!path_is_absolute(destination))
|
if (!path_is_absolute(destination))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -247,7 +271,7 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only)
|
||||||
if (!m)
|
if (!m)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
m->source = TAKE_PTR(source);
|
m->source = TAKE_PTR(p);
|
||||||
m->destination = TAKE_PTR(destination);
|
m->destination = TAKE_PTR(destination);
|
||||||
m->read_only = read_only;
|
m->read_only = read_only;
|
||||||
m->options = TAKE_PTR(opts);
|
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_free_ char *upper = NULL, *destination = NULL;
|
||||||
_cleanup_strv_free_ char **lower = NULL;
|
_cleanup_strv_free_ char **lower = NULL;
|
||||||
CustomMount *m;
|
CustomMount *m;
|
||||||
int k;
|
int r, k;
|
||||||
|
|
||||||
k = strv_split_full(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
k = strv_split_full(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
if (k < 0)
|
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)
|
if (k < 2)
|
||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
if (k == 2) {
|
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
|
/* 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. */
|
* we'll also define the destination mount point the same as the upper. */
|
||||||
|
|
||||||
if (!source_path_is_valid(lower[0]) ||
|
r = source_path_parse(lower[0], &p);
|
||||||
!source_path_is_valid(lower[1]))
|
if (r < 0)
|
||||||
return -EINVAL;
|
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]);
|
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)
|
if (!destination)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
} else {
|
} else {
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
|
|
||||||
/* If more than two parameters are specified, the last one is the destination, the second to last one
|
/* 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. */
|
* the "upper", and all before that the "lower" directories. */
|
||||||
|
|
||||||
destination = lower[k - 1];
|
destination = lower[k - 1];
|
||||||
upper = TAKE_PTR(lower[k - 2]);
|
upper = TAKE_PTR(lower[k - 2]);
|
||||||
|
|
||||||
STRV_FOREACH(i, lower)
|
STRV_FOREACH(i, lower) {
|
||||||
if (!source_path_is_valid(*i))
|
r = source_path_parse(*i, &p);
|
||||||
return -EINVAL;
|
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
|
/* If the upper directory is unspecified, then let's create it automatically as a throw-away directory
|
||||||
* in /var/tmp */
|
* in /var/tmp */
|
||||||
if (isempty(upper))
|
r = source_path_parse_nullable(upper, &p);
|
||||||
upper = mfree(upper);
|
if (r < 0)
|
||||||
else if (!source_path_is_valid(upper))
|
return r;
|
||||||
return -EINVAL;
|
|
||||||
|
free_and_replace(upper, p);
|
||||||
|
|
||||||
if (!path_is_absolute(destination))
|
if (!path_is_absolute(destination))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Reference in a new issue