machine-image: properly support searching for images below some --root= path

systemd-sysext supports --root= for everything but the image discovery.
Fix that.
This commit is contained in:
Lennart Poettering
2021-01-19 13:41:42 +01:00
parent 7a87fb6119
commit d577d4a432
13 changed files with 82 additions and 61 deletions
+2 -2
View File
@@ -66,7 +66,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
int r, fd;
if (hostname_is_valid(argv[1], 0)) {
r = image_find(IMAGE_MACHINE, argv[1], &image);
r = image_find(IMAGE_MACHINE, argv[1], NULL, &image);
if (r == -ENOENT)
return log_error_errno(r, "Machine image %s not found.", argv[1]);
if (r < 0)
@@ -142,7 +142,7 @@ static int export_raw(int argc, char *argv[], void *userdata) {
int r, fd;
if (hostname_is_valid(argv[1], 0)) {
r = image_find(IMAGE_MACHINE, argv[1], &image);
r = image_find(IMAGE_MACHINE, argv[1], NULL, &image);
if (r == -ENOENT)
return log_error_errno(r, "Machine image %s not found.", argv[1]);
if (r < 0)
+1 -1
View File
@@ -132,7 +132,7 @@ static int import_fs(int argc, char *argv[], void *userdata) {
local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+2 -2
View File
@@ -70,7 +70,7 @@ static int import_tar(int argc, char *argv[], void *userdata) {
local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
@@ -165,7 +165,7 @@ static int import_raw(int argc, char *argv[], void *userdata) {
local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+2 -2
View File
@@ -78,7 +78,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
@@ -164,7 +164,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+2 -2
View File
@@ -408,7 +408,7 @@ static int image_object_find(sd_bus *bus, const char *path, const char *interfac
if (r < 0)
return r;
r = image_find(IMAGE_MACHINE, e, &image);
r = image_find(IMAGE_MACHINE, e, NULL, &image);
if (r == -ENOENT)
return 0;
if (r < 0)
@@ -452,7 +452,7 @@ static int image_node_enumerator(sd_bus *bus, const char *path, void *userdata,
if (!images)
return -ENOMEM;
r = image_discover(IMAGE_MACHINE, images);
r = image_discover(IMAGE_MACHINE, NULL, images);
if (r < 0)
return r;
+4 -4
View File
@@ -124,7 +124,7 @@ static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_erro
if (r < 0)
return r;
r = image_find(IMAGE_MACHINE, name, NULL);
r = image_find(IMAGE_MACHINE, name, NULL, NULL);
if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
if (r < 0)
@@ -480,7 +480,7 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er
if (!images)
return -ENOMEM;
r = image_discover(IMAGE_MACHINE, images);
r = image_discover(IMAGE_MACHINE, NULL, images);
if (r < 0)
return r;
@@ -562,7 +562,7 @@ static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_
if (!image_name_is_valid(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
r = image_find(IMAGE_MACHINE, name, &i);
r = image_find(IMAGE_MACHINE, name, NULL, &i);
if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
if (r < 0)
@@ -755,7 +755,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err
goto child_fail;
}
r = image_discover(IMAGE_MACHINE, images);
r = image_discover(IMAGE_MACHINE, NULL, images);
if (r < 0)
goto child_fail;
+1 -1
View File
@@ -2940,7 +2940,7 @@ static int determine_names(void) {
if (arg_machine) {
_cleanup_(image_unrefp) Image *i = NULL;
r = image_find(IMAGE_MACHINE, arg_machine, &i);
r = image_find(IMAGE_MACHINE, arg_machine, NULL, &i);
if (r == -ENOENT)
return log_error_errno(r, "No image for machine '%s'.", arg_machine);
if (r < 0)
+4 -4
View File
@@ -495,7 +495,7 @@ int portable_extract(
assert(name_or_path);
r = image_find_harder(IMAGE_PORTABLE, name_or_path, &image);
r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
if (r < 0)
return r;
@@ -953,7 +953,7 @@ static int install_image_symlink(
/* If the image is outside of the image search also link it into it, so that it can be found with short image
* names and is listed among the images. */
if (image_in_search_path(IMAGE_PORTABLE, image_path))
if (image_in_search_path(IMAGE_PORTABLE, NULL, image_path))
return 0;
r = image_symlink(image_path, flags, &sl);
@@ -987,7 +987,7 @@ int portable_attach(
assert(name_or_path);
r = image_find_harder(IMAGE_PORTABLE, name_or_path, &image);
r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
if (r < 0)
return r;
@@ -1193,7 +1193,7 @@ int portable_detach(
return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name);
if (path_is_absolute(marker) &&
!image_in_search_path(IMAGE_PORTABLE, marker)) {
!image_in_search_path(IMAGE_PORTABLE, NULL, marker)) {
r = set_ensure_consume(&markers, &path_hash_ops_free, TAKE_PTR(marker));
if (r < 0)
+1 -1
View File
@@ -606,7 +606,7 @@ int bus_image_acquire(
if (image_name_is_valid(name_or_path)) {
/* If it's a short name, let's search for it */
r = image_find(IMAGE_PORTABLE, name_or_path, &loaded);
r = image_find(IMAGE_PORTABLE, name_or_path, NULL, &loaded);
if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PORTABLE_IMAGE, "No image '%s' found.", name_or_path);
+1 -1
View File
@@ -92,7 +92,7 @@ int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *erro
/* A wrapper around image_discover() (for finding images in search path) and portable_discover_attached() (for
* finding attached images). */
r = image_discover(IMAGE_PORTABLE, images);
r = image_discover(IMAGE_PORTABLE, NULL, images);
if (r < 0)
return r;
+57 -36
View File
@@ -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;
r = chase_symlinks_and_opendir(path, root, CHASE_PREFIX_ROOT, &resolved, &d);
if (r == -ENOENT)
continue;
if (r < 0)
return r;
return -errno;
}
/* 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;
+4 -4
View File
@@ -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);
+1 -1
View File
@@ -897,7 +897,7 @@ static int run(int argc, char *argv[]) {
if (!images)
return log_oom();
r = image_discover(IMAGE_EXTENSION, images);
r = image_discover(IMAGE_EXTENSION, arg_root, images);
if (r < 0)
return log_error_errno(r, "Failed to discover extension images: %m");