diff options
| author | Lennart Poettering <lennart@poettering.net> | 2014-12-19 20:07:23 +0100 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2014-12-19 20:07:23 +0100 | 
| commit | c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0 (patch) | |
| tree | c76b52cfb0c996f8175c447f06ff5c44963eb708 | |
| parent | 821d4b6e068b2afaad94d43db22171c34a30400e (diff) | |
machined: add new GetImage() bus call for retrieving the bus path for an image
| -rw-r--r-- | src/libsystemd/sd-bus/bus-common-errors.c | 1 | ||||
| -rw-r--r-- | src/libsystemd/sd-bus/bus-common-errors.h | 1 | ||||
| -rw-r--r-- | src/machine/image.c | 248 | ||||
| -rw-r--r-- | src/machine/image.h | 1 | ||||
| -rw-r--r-- | src/machine/machined-dbus.c | 28 | ||||
| -rw-r--r-- | src/machine/org.freedesktop.machine1.conf | 4 | ||||
| -rw-r--r-- | src/shared/util.c | 17 | ||||
| -rw-r--r-- | src/shared/util.h | 1 | 
8 files changed, 200 insertions, 101 deletions
| diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 3dc00b5e4a..8e90738790 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -45,6 +45,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {          SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING,            EHOSTDOWN),          SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE,              ENXIO), +        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE,                ENOENT),          SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID,           ENXIO),          SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS,               EEXIST),          SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING,        ENOSYS), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index 5b7f41ef19..9007b85c19 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -43,6 +43,7 @@  #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"  #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" +#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"  #define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"  #define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"  #define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking" diff --git a/src/machine/image.c b/src/machine/image.c index 0ba9652497..8f577adb59 100644 --- a/src/machine/image.c +++ b/src/machine/image.c @@ -27,6 +27,10 @@  #include "image.h"  #include "bus-label.h" +static const char image_search_path[] = +        "/var/lib/container\0" +        "/var/lib/machine\0"; +  Image *image_unref(Image *i) {          if (!i)                  return NULL; @@ -37,24 +41,23 @@ Image *image_unref(Image *i) {          return NULL;  } -static int add_image( -                Hashmap *h, +static int image_new(                  ImageType t,                  const char *name,                  const char *path,                  bool read_only,                  usec_t mtime, -                usec_t btime) { +                usec_t btime, +                Image **ret) {          _cleanup_(image_unrefp) Image *i = NULL; -        int r; -        assert(h);          assert(t >= 0);          assert(t < _IMAGE_TYPE_MAX);          assert(name); +        assert(ret); -        i = new(Image, 1); +        i = new0(Image, 1);          if (!i)                  return -ENOMEM; @@ -73,136 +76,179 @@ static int add_image(                          return -ENOMEM;          } -        r = hashmap_put(h, i->name, i); -        if (r < 0) -                return r; - +        *ret = i;          i = NULL; +          return 0;  } -int image_discover(Hashmap *h) { -        const char *path; +static int image_make(int dfd, const char *name, const char *path, Image **ret) { +        struct stat st;          int r; -        assert(h); +        assert(dfd >= 0); +        assert(name); -        FOREACH_STRING(path, "/var/lib/container", "/var/lib/machine") { -                _cleanup_closedir_ DIR *d = NULL; -                struct dirent *de; +        /* We explicitly *do* follow symlinks here, since we want to +         * allow symlinking trees into /var/lib/container/, and treat +         * them normally. */ -                d = opendir(path); -                if (!d) { -                        if (errno == ENOENT) -                                return 0; +        if (fstatat(dfd, name, &st, 0) < 0) +                return -errno; -                        return -errno; -                } +        if (S_ISDIR(st.st_mode)) { -                FOREACH_DIRENT_ALL(de, d, return -errno) { -                        struct stat st; +                if (!ret) +                        return 1; -                        if (STR_IN_SET(de->d_name, ".", "..")) -                                continue; +                /* btrfs subvolumes have inode 256 */ +                if (st.st_ino == 256) { +                        _cleanup_close_ int fd = -1; +                        struct statfs sfs; -                        /* Temporary files for atomically creating new files */ -                        if (startswith(de->d_name, ".#")) -                                continue; +                        fd = openat(dfd, name, O_CLOEXEC|O_NOCTTY|O_DIRECTORY); +                        if (fd < 0) +                                return -errno; -                        if (string_has_cc(de->d_name, NULL)) -                                continue; +                        if (fstatfs(fd, &sfs) < 0) +                                return -errno; -                        if (!utf8_is_valid(de->d_name)) -                                continue; +                        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) { +                                usec_t btime = 0; +                                int ro; -                        if (hashmap_contains(h, de->d_name)) -                                continue; +                                /* It's a btrfs subvolume */ -                        /* We explicitly *do* follow symlinks here, -                         * since we want to allow symlinking trees -                         * into /var/lib/container/, and treat them -                         * normally. */ -                        if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { -                                if (errno == ENOENT) -                                        continue; +                                ro = btrfs_subvol_is_read_only_fd(fd); +                                if (ro < 0) +                                        return ro; -                                return -errno; +                                /* r = btrfs_subvol_get_btime(fd, &btime); */ +                                /* if (r < 0) */ +                                /*         return r; */ + +                                r = image_new(IMAGE_SUBVOLUME, +                                              name, +                                              path, +                                              ro, +                                              0, +                                              btime, +                                              ret); +                                if (r < 0) +                                        return r; + +                                return 1;                          } +                } -                        if (S_ISDIR(st.st_mode)) { +                /* It's just a normal directory. */ -                                /* btrfs subvolumes have inode 256 */ -                                if (st.st_ino == 256) { -                                        _cleanup_close_ int fd = -1; -                                        struct statfs sfs; +                r = image_new(IMAGE_DIRECTORY, +                              name, +                              path, +                              false, +                              0, +                              0, +                              ret); +                if (r < 0) +                        return r; -                                        fd = openat(dirfd(d), de->d_name, O_CLOEXEC|O_NOCTTY|O_DIRECTORY); -                                        if (fd < 0) { -                                                if (errno == ENOENT) -                                                        continue; +                return 1; -                                                return -errno; -                                        } +        } else if (S_ISREG(st.st_mode) && endswith(name, ".gpt")) { -                                        if (fstatfs(fd, &sfs) < 0) -                                                return -errno; +                /* It's a GPT block device */ -                                        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) { -                                                usec_t btime = 0; -                                                int ro; +                if (!ret) +                        return 1; -                                                /* It's a btrfs subvolume */ +                r = image_new(IMAGE_GPT, +                              name, +                              path, +                              !!(st.st_mode & 0111), +                              timespec_load(&st.st_mtim), +                              0, +                              ret); +                if (r < 0) +                        return r; -                                                ro = btrfs_subvol_is_read_only_fd(fd); -                                                if (ro < 0) -                                                        return ro; +                return 1; +        } -                                                /* r = btrfs_subvol_get_btime(fd, &btime); */ -                                                /* if (r < 0) */ -                                                /*         return r; */ +        return 0; +} -                                                r = add_image(h, -                                                              IMAGE_SUBVOLUME, -                                                              de->d_name, -                                                              path, -                                                              ro, -                                                              0, -                                                              btime); +int image_find(const char *name, Image **ret) { +        const char *path; +        int r; -                                                if (r < 0) -                                                        return r; +        assert(name); -                                                continue; -                                        } -                                } +        /* There are no images with invalid names */ +        if (!image_name_is_valid(name)) +                return 0; -                                /* It's just a normal directory. */ +        NULSTR_FOREACH(path, image_search_path) { +                _cleanup_closedir_ DIR *d = NULL; -                                r = add_image(h, -                                              IMAGE_DIRECTORY, -                                              de->d_name, -                                              path, -                                              false, -                                              0, -                                              0); -                                if (r < 0) -                                        return r; +                d = opendir(path); +                if (!d) { +                        if (errno == ENOENT) +                                continue; -                        } else if (S_ISREG(st.st_mode) && -                                   endswith(de->d_name, ".gpt")) { +                        return -errno; +                } -                                /* It's a GPT block device */ +                r = image_make(dirfd(d), name, path, ret); +                if (r == 0 || r == -ENOENT) +                        continue; +                if (r < 0) +                        return r; -                                r = add_image(h, -                                              IMAGE_GPT, -                                              de->d_name, -                                              path, -                                              !!(st.st_mode & 0111), -                                              timespec_load(&st.st_mtim), -                                              0); -                                if (r < 0) -                                        return r; -                        } +                return 1; +        } + +        return 0; +}; + +int image_discover(Hashmap *h) { +        const char *path; +        int r; + +        assert(h); + +        NULSTR_FOREACH(path, image_search_path) { +                _cleanup_closedir_ DIR *d = NULL; +                struct dirent *de; + +                d = opendir(path); +                if (!d) { +                        if (errno == ENOENT) +                                return 0; + +                        return -errno; +                } + +                FOREACH_DIRENT_ALL(de, d, return -errno) { +                        _cleanup_(image_unrefp) Image *image = NULL; + +                        if (!image_name_is_valid(de->d_name)) +                                continue; + +                        if (hashmap_contains(h, de->d_name)) +                                continue; + +                        r = image_make(dirfd(d), de->d_name, path, &image); +                        if (r == 0 || r == -ENOENT) +                                continue; +                        if (r < 0) +                                return r; + +                        r = hashmap_put(h, image->name, image); +                        if (r < 0) +                                return r; + +                        image = NULL;                  }          } diff --git a/src/machine/image.h b/src/machine/image.h index c77fd19d8d..f298fc3049 100644 --- a/src/machine/image.h +++ b/src/machine/image.h @@ -46,6 +46,7 @@ Image *image_unref(Image *i);  void image_hashmap_free(Hashmap *map); +int image_find(const char *name, Image **ret);  int image_discover(Hashmap *map);  char *image_bus_path(const char *name); diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 949c7d6b20..0229564234 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -68,6 +68,33 @@ static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userda          return sd_bus_reply_method_return(message, "o", p);  } +static int method_get_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { +        _cleanup_free_ char *p = NULL; +        Manager *m = userdata; +        const char *name; +        int r; + +        assert(bus); +        assert(message); +        assert(m); + +        r = sd_bus_message_read(message, "s", &name); +        if (r < 0) +                return r; + +        r = image_find(name, NULL); +        if (r == 0) +                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); +        if (r < 0) +                return r; + +        p = image_bus_path(name); +        if (!p) +                return -ENOMEM; + +        return sd_bus_reply_method_return(message, "o", p); +} +  static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {          _cleanup_free_ char *p = NULL;          Manager *m = userdata; @@ -491,6 +518,7 @@ static int method_list_images(sd_bus *bus, sd_bus_message *message, void *userda  const sd_bus_vtable manager_vtable[] = {          SD_BUS_VTABLE_START(0),          SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED), +        SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),          SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),          SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),          SD_BUS_METHOD("ListImages", NULL, "a(ssbo)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf index 3745c527ff..bd8fbeff4f 100644 --- a/src/machine/org.freedesktop.machine1.conf +++ b/src/machine/org.freedesktop.machine1.conf @@ -54,6 +54,10 @@                  <allow send_destination="org.freedesktop.machine1"                         send_interface="org.freedesktop.machine1.Manager" +                       send_member="GetImage"/> + +                <allow send_destination="org.freedesktop.machine1" +                       send_interface="org.freedesktop.machine1.Manager"                         send_member="GetMachineAddresses"/>                  <allow send_destination="org.freedesktop.machine1" diff --git a/src/shared/util.c b/src/shared/util.c index 1ad82b27dd..06b6077843 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -4257,6 +4257,23 @@ bool machine_name_is_valid(const char *s) {          return true;  } +bool image_name_is_valid(const char *s) { +        if (!filename_is_valid(s)) +                return false; + +        if (string_has_cc(s, NULL)) +                return false; + +        if (!utf8_is_valid(s)) +                return false; + +        /* Temporary files for atomically creating new files */ +        if (startswith(s, ".#")) +                return false; + +        return true; +} +  int pipe_eof(int fd) {          struct pollfd pollfd = {                  .fd = fd, diff --git a/src/shared/util.h b/src/shared/util.h index 712f65a957..1804b8c3a2 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -545,6 +545,7 @@ bool hostname_is_valid(const char *s) _pure_;  char* hostname_cleanup(char *s, bool lowercase);  bool machine_name_is_valid(const char *s) _pure_; +bool image_name_is_valid(const char *s) _pure_;  char* strshorten(char *s, size_t l); | 
