[systemd-commits] 5 commits - Makefile.am TODO src/core src/libsystemd src/machine src/shared src/sysv-generator src/tty-ask-password-agent

Lennart Poettering lennart at kemper.freedesktop.org
Fri Dec 19 11:45:02 PST 2014


 Makefile.am                                         |    3 
 TODO                                                |    4 
 src/core/manager.c                                  |    2 
 src/libsystemd/sd-bus/bus-common-errors.c           |    1 
 src/libsystemd/sd-bus/bus-common-errors.h           |    1 
 src/machine/image-dbus.c                            |  234 +++++++++++++++++
 src/machine/image.c                                 |  266 +++++++++++---------
 src/machine/image.h                                 |   14 -
 src/machine/machine-dbus.c                          |   23 -
 src/machine/machined-dbus.c                         |   28 ++
 src/machine/machined.c                              |   11 
 src/machine/machined.h                              |    1 
 src/machine/org.freedesktop.machine1.conf           |    4 
 src/shared/dropin.c                                 |    2 
 src/shared/fdset.c                                  |    2 
 src/shared/install.c                                |    8 
 src/shared/util.c                                   |   33 +-
 src/shared/util.h                                   |    5 
 src/sysv-generator/Makefile                         |    2 
 src/sysv-generator/sysv-generator.c                 |    4 
 src/tty-ask-password-agent/tty-ask-password-agent.c |    2 
 21 files changed, 482 insertions(+), 168 deletions(-)

New commits:
commit 2cd3aa24820e5d82375c8cc3e4446d884ee4fee0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 19 20:44:49 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index c58f503..fedcf59 100644
--- a/TODO
+++ b/TODO
@@ -39,8 +39,6 @@ Features:
 
 * "machinectl start/enable/disable foo" as aliases for "systemctl start/enable/disable systemd-nspawn at foo.service"
 
-* "machinectl list-images" for showing a list of container trees collected from /var/lib/containers
-
 * "machinectl snapshot" to make a snapshot of a tree or container into /var/lib/containers
 
 * "machinectl rm" to remove a container tree from /var/lib/containers
@@ -51,6 +49,8 @@ Features:
 
 * "machinectl status" should show 10 most recent log lines of both the host logs of the unit of the machine, plus the logs generated in the machine
 
+* make "machinectl login" use a new machined call AllocateMachinePty() or so to get a pty in a machine. That would open up logins to unprivileged clients
+
 * add transparent btrfs pool in a loopback file in /var if btrfs operations (such as systemd-import pull-dck) are used and /var is not a btrfs file system
 
 * machined: open up certain commands to unprivileged clients via polkit

commit ebeccf9eecf5939a2ef772c3160e89efcad96194
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 19 20:43:18 2014 +0100

    machined: add a full bus object for images

diff --git a/Makefile.am b/Makefile.am
index 840b871..9edc235 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5039,7 +5039,8 @@ libsystemd_machine_core_la_SOURCES = \
 	src/machine/image.c \
 	src/machine/image.h \
 	src/machine/machined-dbus.c \
-	src/machine/machine-dbus.c
+	src/machine/machine-dbus.c \
+	src/machine/image-dbus.c
 
 libsystemd_machine_core_la_LIBADD = \
 	libsystemd-label.la \
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
new file mode 100644
index 0000000..afb849b
--- /dev/null
+++ b/src/machine/image-dbus.c
@@ -0,0 +1,234 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "bus-label.h"
+#include "bus-common-errors.h"
+#include "strv.h"
+#include "image.h"
+
+static int image_find_by_bus_path(const char *path, Image **ret) {
+        _cleanup_free_ char *e = NULL;
+        const char *p;
+
+        assert(path);
+
+        p = startswith(path, "/org/freedesktop/machine1/image/");
+        if (!p)
+                return 0;
+
+        e = bus_label_unescape(p);
+        if (!e)
+                return -ENOMEM;
+
+        return image_find(e, ret);
+}
+
+static int image_find_by_bus_path_with_error(const char *path, Image **ret, sd_bus_error *error) {
+        int r;
+
+        assert(path);
+
+        r = image_find_by_bus_path(path, ret);
+        if (r == 0)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "Image doesn't exist.");
+
+        return r;
+}
+
+static int property_get_name(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        _cleanup_(image_unrefp) Image *image = NULL;
+        int r;
+
+        assert(bus);
+        assert(reply);
+
+        r = image_find_by_bus_path_with_error(path, &image, error);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "s", image->name);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int property_get_path(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        _cleanup_(image_unrefp) Image *image = NULL;
+        int r;
+
+        assert(bus);
+        assert(reply);
+
+        r = image_find_by_bus_path_with_error(path, &image, error);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "s", image->path);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int property_get_type(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+
+        _cleanup_(image_unrefp) Image *image = NULL;
+        int r;
+
+        assert(bus);
+        assert(reply);
+
+        r = image_find_by_bus_path_with_error(path, &image, error);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "s", image_type_to_string(image->type));
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int property_get_read_only(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+
+        _cleanup_(image_unrefp) Image *image = NULL;
+        int r;
+
+        assert(bus);
+        assert(reply);
+
+        r = image_find_by_bus_path_with_error(path, &image, error);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "b", image->read_only);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+const sd_bus_vtable image_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Name",     "s", property_get_name,      0, 0),
+        SD_BUS_PROPERTY("Path",     "s", property_get_path,      0, 0),
+        SD_BUS_PROPERTY("Type",     "s", property_get_type,      0, 0),
+        SD_BUS_PROPERTY("ReadOnly", "b", property_get_read_only, 0, 0),
+        SD_BUS_VTABLE_END
+};
+
+int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+        int r;
+
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+
+        r = image_find_by_bus_path(path, NULL);
+        if (r <= 0)
+                return r;
+
+        *found = NULL;
+        return 1;
+}
+
+char *image_bus_path(const char *name) {
+        _cleanup_free_ char *e = NULL;
+
+        assert(name);
+
+        e = bus_label_escape(name);
+        if (!e)
+                return NULL;
+
+        return strappend("/org/freedesktop/machine1/image/", e);
+}
+
+int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+        _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
+        _cleanup_strv_free_ char **l = NULL;
+        Image *image;
+        Iterator i;
+        int r;
+
+        assert(bus);
+        assert(path);
+        assert(nodes);
+
+        images = hashmap_new(&string_hash_ops);
+        if (!images)
+                return -ENOMEM;
+
+        r = image_discover(images);
+        if (r < 0)
+                return r;
+
+        HASHMAP_FOREACH(image, images, i) {
+                char *p;
+
+                p = image_bus_path(image->name);
+                if (!p)
+                        return -ENOMEM;
+
+                r = strv_consume(&l, p);
+                if (r < 0)
+                        return r;
+        }
+
+        *nodes = l;
+        l = NULL;
+
+        return 1;
+}
diff --git a/src/machine/image.c b/src/machine/image.c
index 8f577ad..c81c5f6 100644
--- a/src/machine/image.c
+++ b/src/machine/image.c
@@ -24,8 +24,8 @@
 #include "strv.h"
 #include "utf8.h"
 #include "btrfs-util.h"
+#include "path-util.h"
 #include "image.h"
-#include "bus-label.h"
 
 static const char image_search_path[] =
         "/var/lib/container\0"
@@ -71,9 +71,11 @@ static int image_new(
                 return -ENOMEM;
 
         if (path) {
-                i->path = strdup(path);
+                i->path = strjoin(path, "/", name, NULL);
                 if (!i->path)
                         return -ENOMEM;
+
+                path_kill_slashes(i->path);
         }
 
         *ret = i;
@@ -264,18 +266,6 @@ void image_hashmap_free(Hashmap *map) {
         hashmap_free(map);
 }
 
-char *image_bus_path(const char *name) {
-        _cleanup_free_ char *e = NULL;
-
-        assert(name);
-
-        e = bus_label_escape(name);
-        if (!e)
-                return NULL;
-
-        return strappend("/org/freedesktop/machine1/image/", e);
-}
-
 static const char* const image_type_table[_IMAGE_TYPE_MAX] = {
         [IMAGE_DIRECTORY] = "directory",
         [IMAGE_SUBVOLUME] = "subvolume",
diff --git a/src/machine/image.h b/src/machine/image.h
index f298fc3..f04be23 100644
--- a/src/machine/image.h
+++ b/src/machine/image.h
@@ -5,7 +5,7 @@
 /***
   This file is part of systemd.
 
-  Copyright 2013 Lennart Poettering
+  Copyright 2014 Lennart Poettering
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -23,6 +23,7 @@
 
 #include "time-util.h"
 #include "hashmap.h"
+#include "machined.h"
 
 typedef enum ImageType {
         IMAGE_DIRECTORY,
@@ -43,16 +44,20 @@ typedef struct Image {
 } Image;
 
 Image *image_unref(Image *i);
-
 void image_hashmap_free(Hashmap *map);
 
+DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, image_hashmap_free);
+
 int image_find(const char *name, Image **ret);
 int image_discover(Hashmap *map);
 
+extern const sd_bus_vtable image_vtable[];
+
 char *image_bus_path(const char *name);
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, image_hashmap_free);
+int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
+int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
 
 const char* image_type_to_string(ImageType t) _const_;
 ImageType image_type_from_string(const char *s) _pure_;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 163c73d..f6fd9cf 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -32,7 +32,6 @@
 #include "fileio.h"
 #include "in-addr-util.h"
 #include "local-addresses.h"
-#include "image.h"
 #include "machine.h"
 
 static int property_get_id(
@@ -476,11 +475,9 @@ char *machine_bus_path(Machine *m) {
 }
 
 int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
-        _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
         _cleanup_strv_free_ char **l = NULL;
         Machine *machine = NULL;
         Manager *m = userdata;
-        Image *image;
         Iterator i;
         int r;
 
@@ -500,26 +497,6 @@ int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
                         return r;
         }
 
-        images = hashmap_new(&string_hash_ops);
-        if (!images)
-                return -ENOMEM;
-
-        r = image_discover(images);
-        if (r < 0)
-                return r;
-
-        HASHMAP_FOREACH(image, images, i) {
-                char *p;
-
-                p = image_bus_path(image->name);
-                if (!p)
-                        return -ENOMEM;
-
-                r = strv_consume(&l, p);
-                if (r < 0)
-                        return r;
-        }
-
         *nodes = l;
         l = NULL;
 
diff --git a/src/machine/machined.c b/src/machine/machined.c
index ef59497..82cfcf0 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -27,15 +27,14 @@
 #include <sys/epoll.h>
 
 #include "sd-daemon.h"
-
 #include "strv.h"
 #include "conf-parser.h"
 #include "cgroup-util.h"
 #include "mkdir.h"
 #include "bus-util.h"
 #include "bus-error.h"
-#include "machined.h"
 #include "label.h"
+#include "machined.h"
 
 Manager *manager_new(void) {
         Manager *m;
@@ -152,6 +151,14 @@ static int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add machine enumerator: %m");
 
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add image object vtable: %m");
+
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add image enumerator: %m");
+
         r = sd_bus_add_match(m->bus,
                              NULL,
                              "type='signal',"
diff --git a/src/machine/machined.h b/src/machine/machined.h
index 2dba303..ed0bd70 100644
--- a/src/machine/machined.h
+++ b/src/machine/machined.h
@@ -33,6 +33,7 @@
 typedef struct Manager Manager;
 
 #include "machine.h"
+#include "image.h"
 
 struct Manager {
         sd_event *event;

commit c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 19 20:07:23 2014 +0100

    machined: add new GetImage() bus call for retrieving the bus path for an image

diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
index 3dc00b5..8e90738 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 5b7f41e..9007b85 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 0ba9652..8f577ad 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 c77fd19..f298fc3 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 949c7d6..0229564 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 3745c52..bd8fbef 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 1ad82b2..06b6077 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 712f65a..1804b8c 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);
 

commit 821d4b6e068b2afaad94d43db22171c34a30400e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 19 20:04:55 2014 +0100

    sysv-generator: properly add Makefile symlink

diff --git a/src/sysv-generator/Makefile b/src/sysv-generator/Makefile
deleted file mode 100644
index 530e5e9..0000000
--- a/src/sysv-generator/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile
diff --git a/src/sysv-generator/Makefile b/src/sysv-generator/Makefile
new file mode 120000
index 0000000..d0b0e8e
--- /dev/null
+++ b/src/sysv-generator/Makefile
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file

commit a34bf9db5da0fdd6bdb14459e203dbe41ee99614
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 19 20:03:36 2014 +0100

    util: rename ignore_file() to hidden_file()
    
    hidden_file() is a bit more precise, since dot files usually shouldn't
    be ignored, but certainly be considered hidden.

diff --git a/src/core/manager.c b/src/core/manager.c
index afd911d..9705e64 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1028,7 +1028,7 @@ static void manager_build_unit_path_cache(Manager *m) {
                 while ((de = readdir(d))) {
                         char *p;
 
-                        if (ignore_file(de->d_name))
+                        if (hidden_file(de->d_name))
                                 continue;
 
                         p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
index 40e6fee..d1baad6 100644
--- a/src/shared/dropin.c
+++ b/src/shared/dropin.c
@@ -148,7 +148,7 @@ static int iterate_dir(
                 if (!de)
                         break;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 f = strjoin(path, "/", de->d_name, NULL);
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
index 37cbd85..46f7773 100644
--- a/src/shared/fdset.c
+++ b/src/shared/fdset.c
@@ -127,7 +127,7 @@ int fdset_new_fill(FDSet **_s) {
         while ((de = readdir(d))) {
                 int fd = -1;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 r = safe_atoi(de->d_name, &fd);
diff --git a/src/shared/install.c b/src/shared/install.c
index efbe61e..3b06544 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -240,7 +240,7 @@ static int remove_marked_symlinks_fd(
                 if (!de)
                         break;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 dirent_ensure_type(d, de);
@@ -415,7 +415,7 @@ static int find_symlinks_fd(
                 if (!de)
                         return r;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 dirent_ensure_type(d, de);
@@ -2094,7 +2094,7 @@ int unit_file_preset_all(
                         if (!de)
                                 break;
 
-                        if (ignore_file(de->d_name))
+                        if (hidden_file(de->d_name))
                                 continue;
 
                         if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
@@ -2206,7 +2206,7 @@ int unit_file_get_list(
                         if (!de)
                                 break;
 
-                        if (ignore_file(de->d_name))
+                        if (hidden_file(de->d_name))
                                 continue;
 
                         if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
diff --git a/src/shared/util.c b/src/shared/util.c
index 5f18d34..1ad82b2 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -1510,7 +1510,7 @@ char *ascii_strlower(char *t) {
         return t;
 }
 
-_pure_ static bool ignore_file_allow_backup(const char *filename) {
+_pure_ static bool hidden_file_allow_backup(const char *filename) {
         assert(filename);
 
         return
@@ -1527,13 +1527,13 @@ _pure_ static bool ignore_file_allow_backup(const char *filename) {
                 endswith(filename, ".swp");
 }
 
-bool ignore_file(const char *filename) {
+bool hidden_file(const char *filename) {
         assert(filename);
 
         if (endswith(filename, "~"))
                 return true;
 
-        return ignore_file_allow_backup(filename);
+        return hidden_file_allow_backup(filename);
 }
 
 int fd_nonblock(int fd, bool nonblock) {
@@ -1627,7 +1627,7 @@ int close_all_fds(const int except[], unsigned n_except) {
         while ((de = readdir(d))) {
                 int fd = -1;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 if (safe_atoi(de->d_name, &fd) < 0)
@@ -2531,7 +2531,7 @@ int dir_is_empty(const char *path) {
                 if (!de)
                         return 1;
 
-                if (!ignore_file(de->d_name))
+                if (!hidden_file(de->d_name))
                         return 0;
         }
 }
@@ -3996,7 +3996,7 @@ const char *default_term_for_tty(const char *tty) {
 bool dirent_is_file(const struct dirent *de) {
         assert(de);
 
-        if (ignore_file(de->d_name))
+        if (hidden_file(de->d_name))
                 return false;
 
         if (de->d_type != DT_REG &&
@@ -4015,7 +4015,7 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
             de->d_type != DT_UNKNOWN)
                 return false;
 
-        if (ignore_file_allow_backup(de->d_name))
+        if (hidden_file_allow_backup(de->d_name))
                 return false;
 
         return endswith(de->d_name, suffix);
@@ -5909,7 +5909,7 @@ int on_ac_power(void) {
                 if (!de)
                         break;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
diff --git a/src/shared/util.h b/src/shared/util.h
index e783ec6..712f65a 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -317,7 +317,7 @@ char *ascii_strlower(char *path);
 bool dirent_is_file(const struct dirent *de) _pure_;
 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
 
-bool ignore_file(const char *filename) _pure_;
+bool hidden_file(const char *filename) _pure_;
 
 bool chars_intersect(const char *a, const char *b) _pure_;
 
@@ -771,7 +771,7 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *root
                                 on_error;                               \
                         }                                               \
                         break;                                          \
-                } else if (ignore_file((de)->d_name))                   \
+                } else if (hidden_file((de)->d_name))                   \
                         continue;                                       \
                 else
 
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 45c8b4e..6730843 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -704,7 +704,7 @@ static int enumerate_sysv(LookupPaths lp, Hashmap *all_services) {
                         _cleanup_free_ char *fpath = NULL, *name = NULL;
                         int r;
 
-                        if (ignore_file(de->d_name))
+                        if (hidden_file(de->d_name))
                                 continue;
 
                         fpath = strjoin(*path, "/", de->d_name, NULL);
@@ -777,7 +777,7 @@ static int set_dependencies_from_rcnd(LookupPaths lp, Hashmap *all_services) {
                         while ((de = readdir(d))) {
                                 int a, b;
 
-                                if (ignore_file(de->d_name))
+                                if (hidden_file(de->d_name))
                                         continue;
 
                                 if (de->d_name[0] != 'S' && de->d_name[0] != 'K')
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 5fc27f9..b4405ce 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -438,7 +438,7 @@ static int show_passwords(void) {
                 if (de->d_type != DT_REG)
                         continue;
 
-                if (ignore_file(de->d_name))
+                if (hidden_file(de->d_name))
                         continue;
 
                 if (!startswith(de->d_name, "ask."))



More information about the systemd-commits mailing list