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:
+2
-2
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user