diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-01-12 17:18:53 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-01-19 13:41:42 +0100 |
commit | d577d4a432dd7bb056d2f7df53956122ebcb1ab0 (patch) | |
tree | 12fe73d70c67def5ad1cc4b8afd5b8a699928be1 /src/shared | |
parent | 7a87fb611986db0b55dbc045230b5edceef05a87 (diff) | |
download | systemd-d577d4a432dd7bb056d2f7df53956122ebcb1ab0.tar.gz |
machine-image: properly support searching for images below some --root= path
systemd-sysext supports --root= for everything but the image discovery.
Fix that.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/machine-image.c | 93 | ||||
-rw-r--r-- | src/shared/machine-image.h | 8 |
2 files changed, 61 insertions, 40 deletions
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index f7b1f90c6f..d2b726efc4 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -421,7 +421,11 @@ static int image_make( return -EMEDIUMTYPE; } -int image_find(ImageClass class, const char *name, Image **ret) { +int image_find(ImageClass class, + const char *name, + const char *root, + Image **ret) { + const char *path; int r; @@ -434,20 +438,22 @@ int image_find(ImageClass class, const char *name, Image **ret) { return -ENOENT; NULSTR_FOREACH(path, image_search_path[class]) { + _cleanup_free_ char *resolved = NULL; _cleanup_closedir_ DIR *d = NULL; struct stat st; + int flags; - d = opendir(path); - if (!d) { - if (errno == ENOENT) - continue; - - return -errno; - } + r = chase_symlinks_and_opendir(path, root, CHASE_PREFIX_ROOT, &resolved, &d); + if (r == -ENOENT) + continue; + if (r < 0) + return r; - /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people to - * symlink block devices into the search path */ - if (fstatat(dirfd(d), name, &st, 0) < 0) { + /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people + * to symlink block devices into the search path. (For now, we disable that when operating + * relative to some root directory.) */ + flags = root ? AT_SYMLINK_NOFOLLOW : 0; + if (fstatat(dirfd(d), name, &st, flags) < 0) { _cleanup_free_ char *raw = NULL; if (errno != ENOENT) @@ -457,8 +463,7 @@ int image_find(ImageClass class, const char *name, Image **ret) { if (!raw) return -ENOMEM; - if (fstatat(dirfd(d), raw, &st, 0) < 0) { - + if (fstatat(dirfd(d), raw, &st, flags) < 0) { if (errno == ENOENT) continue; @@ -468,13 +473,13 @@ int image_find(ImageClass class, const char *name, Image **ret) { if (!S_ISREG(st.st_mode)) continue; - r = image_make(name, dirfd(d), path, raw, &st, ret); + r = image_make(name, dirfd(d), resolved, raw, &st, ret); } else { if (!S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode)) continue; - r = image_make(name, dirfd(d), path, name, &st, ret); + r = image_make(name, dirfd(d), resolved, name, &st, ret); } if (IN_SET(r, -ENOENT, -EMEDIUMTYPE)) continue; @@ -488,7 +493,7 @@ int image_find(ImageClass class, const char *name, Image **ret) { } if (class == IMAGE_MACHINE && streq(name, ".host")) { - r = image_make(".host", AT_FDCWD, NULL, "/", NULL, ret); + r = image_make(".host", AT_FDCWD, NULL, empty_to_root(root), NULL, ret); if (r < 0) return r; @@ -513,14 +518,18 @@ int image_from_path(const char *path, Image **ret) { return image_make(NULL, AT_FDCWD, NULL, path, NULL, ret); } -int image_find_harder(ImageClass class, const char *name_or_path, Image **ret) { +int image_find_harder(ImageClass class, const char *name_or_path, const char *root, Image **ret) { if (image_name_is_valid(name_or_path)) - return image_find(class, name_or_path, ret); + return image_find(class, name_or_path, root, ret); return image_from_path(name_or_path, ret); } -int image_discover(ImageClass class, Hashmap *h) { +int image_discover( + ImageClass class, + const char *root, + Hashmap *h) { + const char *path; int r; @@ -529,29 +538,30 @@ int image_discover(ImageClass class, Hashmap *h) { assert(h); NULSTR_FOREACH(path, image_search_path[class]) { + _cleanup_free_ char *resolved = NULL; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; - d = opendir(path); - if (!d) { - if (errno == ENOENT) - continue; - - return -errno; - } + r = chase_symlinks_and_opendir(path, root, CHASE_PREFIX_ROOT, &resolved, &d); + if (r == -ENOENT) + continue; + if (r < 0) + return r; FOREACH_DIRENT_ALL(de, d, return -errno) { _cleanup_(image_unrefp) Image *image = NULL; _cleanup_free_ char *truncated = NULL; const char *pretty; struct stat st; + int flags; if (dot_or_dot_dot(de->d_name)) continue; - /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people - * to symlink block devices into the search path */ - if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { + /* As mentioned above, we follow symlinks on this fstatat(), because we want to + * permit people to symlink block devices into the search path. */ + flags = root ? AT_SYMLINK_NOFOLLOW : 0; + if (fstatat(dirfd(d), de->d_name, &st, flags) < 0) { if (errno == ENOENT) continue; @@ -581,7 +591,7 @@ int image_discover(ImageClass class, Hashmap *h) { if (hashmap_contains(h, pretty)) continue; - r = image_make(pretty, dirfd(d), path, de->d_name, &st, &image); + r = image_make(pretty, dirfd(d), resolved, de->d_name, &st, &image); if (IN_SET(r, -ENOENT, -EMEDIUMTYPE)) continue; if (r < 0) @@ -600,7 +610,7 @@ int image_discover(ImageClass class, Hashmap *h) { if (class == IMAGE_MACHINE && !hashmap_contains(h, ".host")) { _cleanup_(image_unrefp) Image *image = NULL; - r = image_make(".host", AT_FDCWD, NULL, "/", NULL, &image); + r = image_make(".host", AT_FDCWD, NULL, empty_to_root("/"), NULL, &image); if (r < 0) return r; @@ -743,7 +753,7 @@ int image_rename(Image *i, const char *new_name) { if (r < 0) return r; - r = image_find(IMAGE_MACHINE, new_name, NULL); + r = image_find(IMAGE_MACHINE, new_name, NULL, NULL); if (r >= 0) return -EEXIST; if (r != -ENOENT) @@ -856,7 +866,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) { if (r < 0) return r; - r = image_find(IMAGE_MACHINE, new_name, NULL); + r = image_find(IMAGE_MACHINE, new_name, NULL, NULL); if (r >= 0) return -EEXIST; if (r != -ENOENT) @@ -1248,16 +1258,27 @@ bool image_name_is_valid(const char *s) { return true; } -bool image_in_search_path(ImageClass class, const char *image) { +bool image_in_search_path( + ImageClass class, + const char *root, + const char *image) { + const char *path; assert(image); NULSTR_FOREACH(path, image_search_path[class]) { - const char *p; + const char *p, *q; size_t k; - p = path_startswith(image, path); + if (!empty_or_root(root)) { + q = path_startswith(path, root); + if (!q) + continue; + } else + q = path; + + p = path_startswith(q, path); if (!p) continue; diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h index eea94e0324..c568fff751 100644 --- a/src/shared/machine-image.h +++ b/src/shared/machine-image.h @@ -62,10 +62,10 @@ Image *image_ref(Image *i); DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref); -int image_find(ImageClass class, const char *name, Image **ret); +int image_find(ImageClass class, const char *root, const char *name, Image **ret); int image_from_path(const char *path, Image **ret); -int image_find_harder(ImageClass class, const char *name_or_path, Image **ret); -int image_discover(ImageClass class, Hashmap *map); +int image_find_harder(ImageClass class, const char *root, const char *name_or_path, Image **ret); +int image_discover(ImageClass class, const char *root, Hashmap *map); int image_remove(Image *i); int image_rename(Image *i, const char *new_name); @@ -84,7 +84,7 @@ int image_set_limit(Image *i, uint64_t referenced_max); int image_read_metadata(Image *i); -bool image_in_search_path(ImageClass class, const char *image); +bool image_in_search_path(ImageClass class, const char *root, const char *image); static inline bool IMAGE_IS_HIDDEN(const struct Image *i) { assert(i); |