[systemd-commits] 10 commits - Makefile.am TODO src/analyze src/core src/hostname src/import src/journal src/libsystemd src/locale src/login src/machine src/run src/shared src/systemctl src/systemd src/timedate src/udev

Lennart Poettering lennart at kemper.freedesktop.org
Wed Dec 24 07:53:14 PST 2014


 Makefile.am                          |    2 
 TODO                                 |   14 
 src/analyze/analyze.c                |    2 
 src/core/mount.c                     |    4 
 src/core/path.c                      |    4 
 src/hostname/hostnamectl.c           |    2 
 src/import/curl-util.c               |   31 ++
 src/import/curl-util.h               |    1 
 src/import/import-dkr.c              |   48 ++-
 src/import/import-dkr.h              |    4 
 src/import/import-gpt.c              |  504 +++++++++++++++++++++++++++++++++++
 src/import/import-gpt.h              |   37 ++
 src/import/import.c                  |  104 ++++++-
 src/journal/journal-file.c           |    6 
 src/journal/journal-vacuum.c         |    9 
 src/journal/sd-journal.c             |    4 
 src/libsystemd/libsystemd.sym.m4     |    2 
 src/libsystemd/sd-bus/bus-internal.h |    2 
 src/libsystemd/sd-bus/bus-util.c     |    8 
 src/libsystemd/sd-bus/bus-util.h     |    2 
 src/libsystemd/sd-bus/busctl.c       |    6 
 src/libsystemd/sd-bus/sd-bus.c       |   14 
 src/locale/localectl.c               |    2 
 src/login/loginctl.c                 |    2 
 src/machine/image.c                  |    2 
 src/machine/machinectl.c             |    4 
 src/run/run.c                        |    4 
 src/shared/util.c                    |   66 ++++
 src/shared/util.h                    |   14 
 src/systemctl/systemctl.c            |   12 
 src/systemd/sd-bus.h                 |    2 
 src/timedate/timedatectl.c           |    2 
 src/udev/udevd.c                     |    4 
 33 files changed, 838 insertions(+), 86 deletions(-)

New commits:
commit de146bb2aac13361ade3050d37696499ac4ca9ae
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:52:20 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index af7863c..100d3f2 100644
--- a/TODO
+++ b/TODO
@@ -31,8 +31,6 @@ External:
 
 Features:
 
-* rename sd_bus_open_system_container() to sd_bus_open_system_machine()
-
 * Port various tools to make use of verbs.[ch], where applicable
 
 * Check all invocations of access() and consider turning them into laccess()
@@ -47,10 +45,22 @@ Features:
 
 * "machinectl diff"
 
+* "machinectl commit" that takes a writable snapshot of a tree, invokes a shell in it, and marks it read-only after use
+
 * "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
 
 * add transparent btrfs pool in a loopback file in /var if btrfs operations (such as systemd-import pull-dkr) are used and /var is not a btrfs file system
 
+* systemd-nspawn -M should look for gpt images if neither -D nor -i are specified.
+
+* systemd-nspawn -i should run things read-only if image file has no writable bits
+
+* systemd-nspawn -x should support ephemeral instances of gpt images
+
+* systemd-import pull-gpt should make a read-only download, plus a writable reflinked copy
+
+* machinectl list should show crtimes of snapshots and GPT images
+
 * hostnamectl: show root image uuid
 
 * sysfs set api in libudev is not const

commit 901992209e3c87a4cf06b530d7b26ae2d35680ef
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:44:56 2014 +0100

    import: add a new "pull-gpt" verb for downloading GPT disk images from the internet

diff --git a/Makefile.am b/Makefile.am
index 4173147..89f3af8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5136,6 +5136,8 @@ bin_PROGRAMS += \
 
 systemd_import_SOURCES = \
 	src/import/import.c \
+	src/import/import-gpt.c \
+	src/import/import-gpt.h \
 	src/import/import-dkr.c \
 	src/import/import-dkr.h \
 	src/import/curl-util.c \
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index eaaebae..78a58a8 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -413,3 +413,34 @@ int curl_header_strdup(const void *contents, size_t sz, const char *field, char
         *value = s;
         return 1;
 }
+
+int curl_parse_http_time(const char *t, time_t *ret) {
+        struct tm tm;
+        time_t v;
+
+        assert(t);
+        assert(ret);
+
+        RUN_WITH_LOCALE(LC_TIME, "C") {
+                const char *e;
+
+                /* RFC822 */
+                e = strptime(t, "%a, %d %b %Y %H:%M:%S %Z", &tm);
+                if (!e || *e != 0)
+                        /* RFC 850 */
+                        e = strptime(t, "%A, %d-%b-%y %H:%M:%S %Z", &tm);
+                if (!e || *e != 0)
+                        /* ANSI C */
+                        e = strptime(t, "%a %b %d %H:%M:%S %Y", &tm);
+                if (!e || *e != 0)
+                        return -EINVAL;
+
+                v = timegm(&tm);
+        }
+
+        if (v == (time_t) -1)
+                return -EINVAL;
+
+        *ret = v;
+        return 0;
+}
diff --git a/src/import/curl-util.h b/src/import/curl-util.h
index 5a7550d..b4d75e8 100644
--- a/src/import/curl-util.h
+++ b/src/import/curl-util.h
@@ -51,6 +51,7 @@ void curl_glue_remove_and_free(CurlGlue *g, CURL *c);
 
 struct curl_slist *curl_slist_new(const char *first, ...) _sentinel_;
 int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value);
+int curl_parse_http_time(const char *t, time_t *ret);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_easy_cleanup);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct curl_slist*, curl_slist_free_all);
diff --git a/src/import/import-gpt.c b/src/import/import-gpt.c
new file mode 100644
index 0000000..eda6dca
--- /dev/null
+++ b/src/import/import-gpt.c
@@ -0,0 +1,504 @@
+/*-*- 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 <sys/xattr.h>
+#include <curl/curl.h>
+
+#include "hashmap.h"
+#include "utf8.h"
+#include "curl-util.h"
+#include "import-gpt.h"
+
+typedef struct GptImportFile GptImportFile;
+
+struct GptImportFile {
+        GptImport *import;
+
+        char *url;
+        char *local;
+
+        CURL *curl;
+        struct curl_slist *request_header;
+
+        char *temp_path;
+        char *final_path;
+        char *etag;
+        char *old_etag;
+
+        uint64_t content_length;
+        uint64_t written;
+
+        time_t mtime;
+
+        bool force_local;
+        bool done;
+
+        int disk_fd;
+};
+
+struct GptImport {
+        sd_event *event;
+        CurlGlue *glue;
+
+        Hashmap *files;
+
+        gpt_import_on_finished on_finished;
+        void *userdata;
+
+        bool finished;
+};
+
+static GptImportFile *gpt_import_file_unref(GptImportFile *f) {
+        if (!f)
+                return NULL;
+
+        if (f->import)
+                curl_glue_remove_and_free(f->import->glue, f->curl);
+        curl_slist_free_all(f->request_header);
+
+        safe_close(f->disk_fd);
+
+        free(f->final_path);
+
+        if (f->temp_path) {
+                unlink(f->temp_path);
+                free(f->temp_path);
+        }
+
+        free(f->url);
+        free(f->local);
+        free(f->etag);
+        free(f->old_etag);
+        free(f);
+
+        return NULL;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(GptImportFile*, gpt_import_file_unref);
+
+static void gpt_import_finish(GptImport *import, int error) {
+        assert(import);
+
+        if (import->finished)
+                return;
+
+        import->finished = true;
+
+        if (import->on_finished)
+                import->on_finished(import, error, import->userdata);
+        else
+                sd_event_exit(import->event, error);
+}
+
+static void gpt_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
+        GptImportFile *f = NULL;
+        struct stat st;
+        CURLcode code;
+        long status;
+        int r;
+
+        if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, &f) != CURLE_OK)
+                return;
+
+        if (!f)
+                return;
+
+        f->done = true;
+
+        if (result != CURLE_OK) {
+                log_error("Transfer failed: %s", curl_easy_strerror(result));
+                r = -EIO;
+                goto fail;
+        }
+
+        code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
+        if (code != CURLE_OK) {
+                log_error("Failed to retrieve response code: %s", curl_easy_strerror(code));
+                r = -EIO;
+                goto fail;
+        } else if (status == 304) {
+                log_info("File unmodified.");
+                r = 0;
+                goto fail;
+        } else if (status >= 300) {
+                log_error("HTTP request to %s failed with code %li.", f->url, status);
+                r = -EIO;
+                goto fail;
+        } else if (status < 200) {
+                log_error("HTTP request to %s finished with unexpected code %li.", f->url, status);
+                r = -EIO;
+                goto fail;
+        }
+
+        if (f->disk_fd < 0) {
+                log_error("No data received.");
+                r = -EIO;
+                goto fail;
+        }
+
+        if (f->content_length != (uint64_t) -1 &&
+            f->content_length != f->written) {
+                log_error("Download truncated.");
+                r = -EIO;
+                goto fail;
+        }
+
+        if (f->etag)
+                (void) fsetxattr(f->disk_fd, "user.etag", f->etag, strlen(f->etag), XATTR_CREATE);
+
+        if (f->mtime != 0) {
+                struct timespec ut[2];
+
+                timespec_store(&ut[0], (usec_t) f->mtime * USEC_PER_SEC);
+                ut[1] = ut[0];
+
+                (void) futimens(f->disk_fd, ut);
+        }
+
+        if (fstat(f->disk_fd, &st) < 0) {
+                r = log_error_errno(errno, "Failed to stat file: %m");
+                goto fail;
+        }
+
+        /* Mark read-only */
+        (void) fchmod(f->disk_fd, st.st_mode & 07444);
+
+        f->disk_fd = safe_close(f->disk_fd);
+
+        assert(f->temp_path);
+        assert(f->final_path);
+
+        r = rename(f->temp_path, f->final_path);
+        if (r < 0) {
+                r = log_error_errno(errno, "Failed to move GPT file into place: %m");
+                goto fail;
+        }
+
+        r = 0;
+
+fail:
+        gpt_import_finish(f->import, r);
+}
+
+static int gpt_import_file_open_disk(GptImportFile *f) {
+        int r;
+
+        assert(f);
+
+        if (f->disk_fd >= 0)
+                return 0;
+
+        assert(f->final_path);
+
+        if (!f->temp_path) {
+                r = tempfn_random(f->final_path, &f->temp_path);
+                if (r < 0)
+                        return log_oom();
+        }
+
+        f->disk_fd = open(f->temp_path, O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC|O_WRONLY, 0644);
+        if (f->disk_fd < 0)
+                return log_error_errno(errno, "Failed to create %s: %m", f->temp_path);
+
+        return 0;
+}
+
+static size_t gpt_import_file_write_callback(void *contents, size_t size, size_t nmemb, void *userdata) {
+        GptImportFile *f = userdata;
+        size_t sz = size * nmemb;
+        ssize_t n;
+        int r;
+
+        assert(contents);
+        assert(f);
+
+        r = gpt_import_file_open_disk(f);
+        if (r < 0)
+                goto fail;
+
+        if (f->written + sz < f->written) {
+                log_error("File too large, overflow");
+                r = -EOVERFLOW;
+                goto fail;
+        }
+
+        if (f->content_length != (uint64_t) -1 &&
+            f->written + sz > f->content_length) {
+                log_error("Content length incorrect.");
+                r = -EFBIG;
+                goto fail;
+        }
+
+        n = write(f->disk_fd, contents, sz);
+        if (n < 0) {
+                log_error_errno(errno, "Failed to write file: %m");
+                goto fail;
+        }
+
+        if ((size_t) n < sz) {
+                log_error("Short write");
+                r = -EIO;
+                goto fail;
+        }
+
+        f->written += sz;
+
+        return sz;
+
+fail:
+        gpt_import_finish(f->import, r);
+        return 0;
+}
+
+static size_t gpt_import_file_header_callback(void *contents, size_t size, size_t nmemb, void *userdata) {
+        GptImportFile *f = userdata;
+        size_t sz = size * nmemb;
+        _cleanup_free_ char *length = NULL, *last_modified = NULL;
+        char *etag;
+        int r;
+
+        assert(contents);
+        assert(f);
+
+        r = curl_header_strdup(contents, sz, "ETag:", &etag);
+        if (r < 0) {
+                log_oom();
+                goto fail;
+        }
+        if (r > 0) {
+                free(f->etag);
+                f->etag = etag;
+
+                if (streq_ptr(f->old_etag, f->etag)) {
+                        log_info("Image already up to date. Finishing.");
+                        gpt_import_finish(f->import, 0);
+                        return sz;
+                }
+
+                return sz;
+        }
+
+        r = curl_header_strdup(contents, sz, "Content-Length:", &length);
+        if (r < 0) {
+                log_oom();
+                goto fail;
+        }
+        if (r > 0) {
+                (void) safe_atou64(length, &f->content_length);
+                return sz;
+        }
+
+        r = curl_header_strdup(contents, sz, "Last-Modified:", &last_modified);
+        if (r < 0) {
+                log_oom();
+                goto fail;
+        }
+        if (r > 0) {
+                (void) curl_parse_http_time(last_modified, &f->mtime);
+                return sz;
+        }
+
+        return sz;
+
+fail:
+        gpt_import_finish(f->import, r);
+        return 0;
+}
+
+static int gpt_import_file_begin(GptImportFile *f) {
+        int r;
+
+        assert(f);
+        assert(!f->curl);
+
+        log_info("Getting %s.", f->url);
+
+        r = curl_glue_make(&f->curl, f->url, f);
+        if (r < 0)
+                return r;
+
+        if (f->old_etag) {
+                const char *hdr;
+
+                hdr = strappenda("If-None-Match: ", f->old_etag);
+
+                f->request_header = curl_slist_new(hdr, NULL);
+                if (!f->request_header)
+                        return -ENOMEM;
+
+                if (curl_easy_setopt(f->curl, CURLOPT_HTTPHEADER, f->request_header) != CURLE_OK)
+                        return -EIO;
+        }
+
+        if (curl_easy_setopt(f->curl, CURLOPT_WRITEFUNCTION, gpt_import_file_write_callback) != CURLE_OK)
+                return -EIO;
+
+        if (curl_easy_setopt(f->curl, CURLOPT_WRITEDATA, f) != CURLE_OK)
+                return -EIO;
+
+        if (curl_easy_setopt(f->curl, CURLOPT_HEADERFUNCTION, gpt_import_file_header_callback) != CURLE_OK)
+                return -EIO;
+
+        if (curl_easy_setopt(f->curl, CURLOPT_HEADERDATA, f) != CURLE_OK)
+                return -EIO;
+
+        r = curl_glue_add(f->import->glue, f->curl);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int gpt_import_new(GptImport **import, sd_event *event, gpt_import_on_finished on_finished, void *userdata) {
+        _cleanup_(gpt_import_unrefp) GptImport *i = NULL;
+        int r;
+
+        assert(import);
+
+        i = new0(GptImport, 1);
+        if (!i)
+                return -ENOMEM;
+
+        i->on_finished = on_finished;
+        i->userdata = userdata;
+
+        if (event)
+                i->event = sd_event_ref(event);
+        else {
+                r = sd_event_default(&i->event);
+                if (r < 0)
+                        return r;
+        }
+
+        r = curl_glue_new(&i->glue, i->event);
+        if (r < 0)
+                return r;
+
+        i->glue->on_finished = gpt_import_curl_on_finished;
+        i->glue->userdata = i;
+
+        *import = i;
+        i = NULL;
+
+        return 0;
+}
+
+GptImport* gpt_import_unref(GptImport *import) {
+        GptImportFile *f;
+
+        if (!import)
+                return NULL;
+
+        while ((f = hashmap_steal_first(import->files)))
+                gpt_import_file_unref(f);
+        hashmap_free(import->files);
+
+        curl_glue_unref(import->glue);
+        sd_event_unref(import->event);
+
+        free(import);
+
+        return NULL;
+}
+
+int gpt_import_cancel(GptImport *import, const char *url) {
+        GptImportFile *f;
+
+        assert(import);
+        assert(url);
+
+        f = hashmap_remove(import->files, url);
+        if (!f)
+                return 0;
+
+        gpt_import_file_unref(f);
+        return 1;
+}
+
+int gpt_import_pull(GptImport *import, const char *url, const char *local, bool force_local) {
+        _cleanup_(gpt_import_file_unrefp) GptImportFile *f = NULL;
+        char etag[LINE_MAX];
+        ssize_t n;
+        int r;
+
+        assert(import);
+        assert(gpt_url_is_valid(url));
+        assert(machine_name_is_valid(local));
+
+        if (hashmap_get(import->files, url))
+                return -EEXIST;
+
+        r = hashmap_ensure_allocated(&import->files, &string_hash_ops);
+        if (r < 0)
+                return r;
+
+        f = new0(GptImportFile, 1);
+        if (!f)
+                return -ENOMEM;
+
+        f->import = import;
+        f->disk_fd = -1;
+        f->content_length = (uint64_t) -1;
+
+        f->url = strdup(url);
+        if (!f->url)
+                return -ENOMEM;
+
+        f->local = strdup(local);
+        if (!f->local)
+                return -ENOMEM;
+
+        f->final_path = strjoin("/var/lib/container/", local, ".gpt", NULL);
+        if (!f->final_path)
+                return -ENOMEM;
+
+        n = getxattr(f->final_path, "user.etag", etag, sizeof(etag));
+        if (n > 0) {
+                f->old_etag = strndup(etag, n);
+                if (!f->old_etag)
+                        return -ENOMEM;
+        }
+
+        r = hashmap_put(import->files, f->url, f);
+        if (r < 0)
+                return r;
+
+        r = gpt_import_file_begin(f);
+        if (r < 0) {
+                gpt_import_cancel(import, f->url);
+                f = NULL;
+                return r;
+        }
+
+        f = NULL;
+        return 0;
+}
+
+bool gpt_url_is_valid(const char *url) {
+        if (isempty(url))
+                return false;
+
+        if (!startswith(url, "http://") &&
+            !startswith(url, "https://"))
+                return false;
+
+        return ascii_is_valid(url);
+}
diff --git a/src/import/import-gpt.h b/src/import/import-gpt.h
new file mode 100644
index 0000000..e4c534c
--- /dev/null
+++ b/src/import/import-gpt.h
@@ -0,0 +1,37 @@
+/*-*- 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 "sd-event.h"
+#include "util.h"
+
+typedef struct GptImport GptImport;
+
+typedef void (*gpt_import_on_finished)(GptImport *import, int error, void *userdata);
+
+int gpt_import_new(GptImport **import, sd_event *event, gpt_import_on_finished on_finished, void *userdata);
+GptImport* gpt_import_unref(GptImport *import);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(GptImport*, gpt_import_unref);
+
+int gpt_import_pull(GptImport *import, const char *url, const char *local, bool force_local);
+int gpt_import_cancel(GptImport *import, const char *name);
+
+bool gpt_url_is_valid(const char *url);
diff --git a/src/import/import.c b/src/import/import.c
index 54f3113..a81200c 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -25,13 +25,103 @@
 #include "event-util.h"
 #include "verbs.h"
 #include "build.h"
+#include "import-gpt.h"
 #include "import-dkr.h"
 
 static bool arg_force = false;
 
 static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
 
-static void on_finished(DkrImport *import, int error, void *userdata) {
+static void on_gpt_finished(GptImport *import, int error, void *userdata) {
+        sd_event *event = userdata;
+        assert(import);
+
+        if (error == 0)
+                log_info("Operation completed successfully.");
+        else
+                log_info_errno(error, "Operation failed: %m");
+
+        sd_event_exit(event, error);
+}
+
+static int pull_gpt(int argc, char *argv[], void *userdata) {
+        _cleanup_(gpt_import_unrefp) GptImport *import = NULL;
+        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_free_ char *local_truncated = NULL, *local_generated = NULL;
+        const char *url, *local, *suffix;
+        int r;
+
+        url = argv[1];
+        local = argv[2];
+
+        if (!gpt_url_is_valid(url)) {
+                log_error("URL '%s' is not valid.", url);
+                return -EINVAL;
+        }
+
+        if (isempty(local) || streq(local, "-"))
+                local = NULL;
+
+        if (!local) {
+                const char *e, *p;
+
+                e = url + strlen(url);
+                while (e > url && e[-1] == '/')
+                        e--;
+
+                p = e;
+                while (p > url && p[-1] != '/')
+                        p--;
+
+                local_generated = strndup(p, e - p);
+                if (!local_generated)
+                        return log_oom();
+
+                local = local_generated;
+        }
+
+        suffix = endswith(local, ".gpt");
+        if (suffix) {
+                local_truncated = strndup(local, suffix - local);
+                if (!local_truncated)
+                        return log_oom();
+
+                local = local_truncated;
+        }
+
+        if (!machine_name_is_valid(local)) {
+                log_error("Local image name '%s' is not valid.", local);
+                return -EINVAL;
+        }
+
+        log_info("Pulling '%s' as '%s'", url, local);
+
+        r = sd_event_default(&event);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate event loop: %m");
+
+        assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
+        sd_event_add_signal(event, NULL, SIGTERM, NULL,  NULL);
+        sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+
+        r = gpt_import_new(&import, event, on_gpt_finished, event);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate importer: %m");
+
+        r = gpt_import_pull(import, url, local, arg_force);
+        if (r < 0)
+                return log_error_errno(r, "Failed to pull image: %m");
+
+        r = sd_event_loop(event);
+        if (r < 0)
+                return log_error_errno(r, "Failed to run event loop: %m");
+
+        log_info("Exiting.");
+
+        return 0;
+}
+
+static void on_dkr_finished(DkrImport *import, int error, void *userdata) {
         sd_event *event = userdata;
         assert(import);
 
@@ -141,7 +231,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --force                  Force creation of image\n"
                "     --dkr-index-url=URL      Specify index URL to use for downloads\n\n"
                "Commands:\n"
-               "  pull-dkr REMOTE [NAME]      Download an image\n",
+               "  pull-dkr REMOTE [NAME]      Download a DKR image\n"
+               "  pull-gpt URL [NAME]         Download a GPT image\n",
                program_invocation_short_name);
 
         return 0;
@@ -208,6 +299,7 @@ static int import_main(int argc, char *argv[]) {
         static const Verb verbs[] = {
                 { "help",     VERB_ANY, VERB_ANY, 0, help     },
                 { "pull-dkr", 2,        3,        0, pull_dkr },
+                { "pull-gpt", 2,        3,        0, pull_gpt },
                 {}
         };
 

commit 0c7bf33a989a58922b3eb9aaa96abd773c8754c4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:43:46 2014 +0100

    import: three minor fixes

diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c
index 05b1062..8f26191 100644
--- a/src/import/import-dkr.c
+++ b/src/import/import-dkr.c
@@ -1131,7 +1131,7 @@ int dkr_import_pull(DkrImport *import, const char *name, const char *tag, const
                 n->force_local = force_local;
         }
 
-        r = hashmap_put(import->names, name, n);
+        r = hashmap_put(import->names, n->name, n);
         if (r < 0)
                 return r;
 
diff --git a/src/import/import.c b/src/import/import.c
index 8b9ca4f..54f3113 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -73,7 +73,7 @@ static int pull_dkr(int argc, char *argv[], void *userdata) {
                         local = name;
         }
 
-        if (streq(local, "-") || isempty(local))
+        if (isempty(local) || streq(local, "-"))
                 local = NULL;
 
         if (!dkr_name_is_valid(name)) {
@@ -89,7 +89,7 @@ static int pull_dkr(int argc, char *argv[], void *userdata) {
         if (local) {
                 const char *p;
 
-                if (!machine_name_is_valid(tag)) {
+                if (!machine_name_is_valid(local)) {
                         log_error("Local image name '%s' is not valid.", local);
                         return -EINVAL;
                 }

commit a36544cd45d607ee7f075157f55e7f646df1d34f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:43:20 2014 +0100

    import: print friendly error messages on errors

diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c
index e7dbe0f..05b1062 100644
--- a/src/import/import-dkr.c
+++ b/src/import/import-dkr.c
@@ -822,7 +822,7 @@ static size_t dkr_import_job_write_callback(void *contents, size_t size, size_t
 
                 l = fwrite(contents, size, nmemb, j->tar_stream);
                 if (l != nmemb) {
-                        r = -errno;
+                        r = log_error_errno(errno, "Failed to write to tar: %m");
                         goto fail;
                 }
 
@@ -830,13 +830,14 @@ static size_t dkr_import_job_write_callback(void *contents, size_t size, size_t
         }
 
         if (j->payload_size + sz > PAYLOAD_MAX) {
+                log_error("Payload too large.");
                 r = -EFBIG;
                 goto fail;
         }
 
         p = realloc(j->payload, j->payload_size + sz);
         if (!p) {
-                r = -ENOMEM;
+                r = log_oom();
                 goto fail;
         }
 

commit 14ed8b9273690b82fed2d437f58e9e01487e9f69
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:42:41 2014 +0100

    import: remember when we were finished importing

diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c
index 594da54..e7dbe0f 100644
--- a/src/import/import-dkr.c
+++ b/src/import/import-dkr.c
@@ -100,6 +100,8 @@ struct DkrImport {
 
         dkr_import_on_finished on_finished;
         void *userdata;
+
+        bool finished;
 };
 
 #define PROTOCOL_PREFIX "https://"
@@ -181,6 +183,11 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImportName*, dkr_import_name_unref);
 static void dkr_import_finish(DkrImport *import, int error) {
         assert(import);
 
+        if (import->finished)
+                return;
+
+        import->finished = true;
+
         if (import->on_finished)
                 import->on_finished(import, error, import->userdata);
         else

commit ea1ae8c38e669351b909cf8cc0c1e6fd140c1b58
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:41:51 2014 +0100

    import: make the dkr import URL a part of the import object, not the import name object

diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c
index 205deb9..594da54 100644
--- a/src/import/import-dkr.c
+++ b/src/import/import-dkr.c
@@ -76,7 +76,6 @@ struct DkrImportJob {
 struct DkrImportName {
         DkrImport *import;
 
-        char *index_url;
         char *name;
         char *tag;
         char *id;
@@ -94,6 +93,8 @@ struct DkrImport {
         sd_event *event;
         CurlGlue *glue;
 
+        char *index_url;
+
         Hashmap *names;
         Hashmap *jobs;
 
@@ -163,7 +164,6 @@ static DkrImportName *dkr_import_name_unref(DkrImportName *name) {
         if (name->job_layer)
                 set_remove(name->job_layer->needed_by, name);
 
-        free(name->index_url);
         free(name->name);
         free(name->id);
         free(name->tag);
@@ -998,16 +998,18 @@ static int dkr_import_name_begin(DkrImportName *name) {
         assert(name);
         assert(!name->job_images);
 
-        url = strappenda(name->index_url, "/v1/repositories/", name->name, "/images");
+        url = strappenda(name->import->index_url, "/v1/repositories/", name->name, "/images");
 
         return dkr_import_name_add_job(name, DKR_IMPORT_JOB_IMAGES, url, &name->job_images);
 }
 
-int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished on_finished, void *userdata) {
+int dkr_import_new(DkrImport **import, sd_event *event, const char *index_url, dkr_import_on_finished on_finished, void *userdata) {
         _cleanup_(dkr_import_unrefp) DkrImport *i = NULL;
+        char *e;
         int r;
 
         assert(import);
+        assert(dkr_url_is_valid(index_url));
 
         i = new0(DkrImport, 1);
         if (!i)
@@ -1016,6 +1018,14 @@ int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished o
         i->on_finished = on_finished;
         i->userdata = userdata;
 
+        i->index_url = strdup(index_url);
+        if (!i->index_url)
+                return -ENOMEM;
+
+        e = endswith(i->index_url, "/");
+        if (e)
+                *e = 0;
+
         if (event)
                 i->event = sd_event_ref(event);
         else {
@@ -1055,6 +1065,8 @@ DkrImport* dkr_import_unref(DkrImport *import) {
         curl_glue_unref(import->glue);
         sd_event_unref(import->event);
 
+        free(import->index_url);
+
         free(import);
 
         return NULL;
@@ -1074,13 +1086,11 @@ int dkr_import_cancel(DkrImport *import, const char *name) {
         return 1;
 }
 
-int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, const char *tag, const char *local, bool force_local) {
+int dkr_import_pull(DkrImport *import, const char *name, const char *tag, const char *local, bool force_local) {
         _cleanup_(dkr_import_name_unrefp) DkrImportName *n = NULL;
-        char *e;
         int r;
 
         assert(import);
-        assert(dkr_url_is_valid(index_url));
         assert(dkr_name_is_valid(name));
         assert(dkr_tag_is_valid(tag));
         assert(!local || machine_name_is_valid(local));
@@ -1098,13 +1108,6 @@ int dkr_import_pull(DkrImport *import, const char *index_url, const char *name,
 
         n->import = import;
 
-        n->index_url = strdup(index_url);
-        if (!n->index_url)
-                return -ENOMEM;
-        e = endswith(n->index_url, "/");
-        if (e)
-                *e = 0;
-
         n->name = strdup(name);
         if (!n->name)
                 return -ENOMEM;
@@ -1132,7 +1135,6 @@ int dkr_import_pull(DkrImport *import, const char *index_url, const char *name,
         }
 
         n = NULL;
-
         return 0;
 }
 
@@ -1168,6 +1170,8 @@ bool dkr_id_is_valid(const char *id) {
 }
 
 bool dkr_url_is_valid(const char *url) {
+        if (isempty(url))
+                return false;
 
         if (!startswith(url, "http://") &&
             !startswith(url, "https://"))
diff --git a/src/import/import-dkr.h b/src/import/import-dkr.h
index a951695..8e6a462 100644
--- a/src/import/import-dkr.h
+++ b/src/import/import-dkr.h
@@ -26,12 +26,12 @@ typedef struct DkrImport DkrImport;
 
 typedef void (*dkr_import_on_finished)(DkrImport *import, int error, void *userdata);
 
-int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished on_finished, void *userdata);
+int dkr_import_new(DkrImport **import, sd_event *event, const char *index_url, dkr_import_on_finished on_finished, void *userdata);
 DkrImport* dkr_import_unref(DkrImport *import);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImport*, dkr_import_unref);
 
-int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, const char *tag, const char *local, bool force_local);
+int dkr_import_pull(DkrImport *import, const char *name, const char *tag, const char *local, bool force_local);
 int dkr_import_cancel(DkrImport *import, const char *name);
 
 bool dkr_name_is_valid(const char *name);
diff --git a/src/import/import.c b/src/import/import.c
index 11d2e05..8b9ca4f 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -115,11 +115,11 @@ static int pull_dkr(int argc, char *argv[], void *userdata) {
         sd_event_add_signal(event, NULL, SIGTERM, NULL,  NULL);
         sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
 
-        r = dkr_import_new(&import, event, on_finished, event);
+        r = dkr_import_new(&import, event, arg_dkr_index_url, on_dkr_finished, event);
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate importer: %m");
 
-        r = dkr_import_pull(import, arg_dkr_index_url, name, tag, local, arg_force);
+        r = dkr_import_pull(import, name, tag, local, arg_force);
         if (r < 0)
                 return log_error_errno(r, "Failed to pull image: %m");
 

commit 51929718dd2dc056f841a97e79efb48a8d8fd64b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:40:30 2014 +0100

    machined: fix writability check for GPT images

diff --git a/src/machine/image.c b/src/machine/image.c
index c81c5f6..2ffe944 100644
--- a/src/machine/image.c
+++ b/src/machine/image.c
@@ -167,7 +167,7 @@ static int image_make(int dfd, const char *name, const char *path, Image **ret)
                 r = image_new(IMAGE_GPT,
                               name,
                               path,
-                              !!(st.st_mode & 0111),
+                              !!(st.st_mode & 0222),
                               timespec_load(&st.st_mtim),
                               0,
                               ret);

commit 4a4d89b682d2a8d32e899c4b47950f64df74fb7c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 16:39:55 2014 +0100

    util: make creation time xattr logic more generic

diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index fec54f3..48c27ee 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -26,7 +26,6 @@
 #include <sys/statvfs.h>
 #include <fcntl.h>
 #include <stddef.h>
-#include <sys/xattr.h>
 
 #include "journal-def.h"
 #include "journal-file.h"
@@ -2526,8 +2525,6 @@ int journal_file_open(
         }
 
         if (f->last_stat.st_size == 0 && f->writable) {
-                uint64_t crtime;
-
                 /* Let's attach the creation time to the journal file,
                  * so that the vacuuming code knows the age of this
                  * file even if the file might end up corrupted one
@@ -2538,8 +2535,7 @@ int journal_file_open(
                  * attributes are not supported we'll just skip this,
                  * and rely solely on mtime/atime/ctime of the file. */
 
-                crtime = htole64((uint64_t) now(CLOCK_REALTIME));
-                fsetxattr(f->fd, "user.crtime_usec", &crtime, sizeof(crtime), XATTR_CREATE);
+                fd_setcrtime(f->fd, now(CLOCK_REALTIME));
 
 #ifdef HAVE_GCRYPT
                 /* Try to load the FSPRG state, and if we can't, then
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index 4973409..832c327 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -75,9 +75,8 @@ static void patch_realtime(
                 const struct stat *st,
                 unsigned long long *realtime) {
 
-        usec_t x;
-        uint64_t crtime;
         _cleanup_free_ const char *path = NULL;
+        usec_t x, crtime;
 
         /* The timestamp was determined by the file name, but let's
          * see if the file might actually be older than the file name
@@ -112,10 +111,8 @@ static void patch_realtime(
         if (!path)
                 return;
 
-        if (getxattr(path, "user.crtime_usec", &crtime, sizeof(crtime)) == sizeof(crtime)) {
-                crtime = le64toh(crtime);
-
-                if (crtime > 0 && crtime != (uint64_t) -1 && crtime < *realtime)
+        if (path_getcrtime(path, &crtime) >= 0) {
+                if (crtime < *realtime)
                         *realtime = crtime;
         }
 }
diff --git a/src/shared/util.c b/src/shared/util.c
index e95f6ed..98b3465 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -59,6 +59,7 @@
 #include <langinfo.h>
 #include <locale.h>
 #include <sys/personality.h>
+#include <sys/xattr.h>
 #include <libgen.h>
 #undef basename
 
@@ -84,6 +85,7 @@
 #include "gunicode.h"
 #include "virt.h"
 #include "def.h"
+#include "sparse-endian.h"
 
 int saved_argc = 0;
 char **saved_argv = NULL;
@@ -7558,3 +7560,62 @@ int openpt_in_namespace(pid_t pid, int flags) {
 
         return -EIO;
 }
+
+int fd_getcrtime(int fd, usec_t *usec) {
+        uint64_t u;
+        le64_t le;
+        ssize_t n;
+
+        assert(fd >= 0);
+        assert(usec);
+
+        /* Until Linux gets a real concept of birthtime/creation time,
+         * let's fake one with xattrs */
+
+        n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
+        if (n < 0)
+                return -errno;
+        if (n != sizeof(le))
+                return -EIO;
+
+        u = le64toh(le);
+        if (u == 0 || u == (uint64_t) -1)
+                return -EIO;
+
+        *usec = (usec_t) u;
+        return 0;
+}
+
+int path_getcrtime(const char *p, usec_t *usec) {
+        uint64_t u;
+        le64_t le;
+        ssize_t n;
+
+        assert(p);
+        assert(usec);
+
+        n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
+        if (n < 0)
+                return -errno;
+        if (n != sizeof(le))
+                return -EIO;
+
+        u = le64toh(le);
+        if (u == 0 || u == (uint64_t) -1)
+                return -EIO;
+
+        *usec = (usec_t) u;
+        return 0;
+}
+
+int fd_setcrtime(int fd, usec_t usec) {
+        le64_t le;
+
+        assert(fd >= 0);
+
+        le = htole64((uint64_t) usec);
+        if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), XATTR_CREATE) < 0)
+                return -errno;
+
+        return 0;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 7f02f42..4d5b982 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -1062,3 +1062,7 @@ union inotify_event_buffer {
 int ptsname_malloc(int fd, char **ret);
 
 int openpt_in_namespace(pid_t pid, int flags);
+
+int fd_setcrtime(int fd, usec_t usec);
+int fd_getcrtime(int fd, usec_t *usec);
+int path_getcrtime(const char *p, usec_t *usec);

commit de33fc625725d199629ed074d6278504deb23deb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Dec 23 23:38:13 2014 +0100

    sd-bus: rename sd_bus_open_system_container() to sd_bus_open_system_machine()
    
    Pretty much everywhere else we use the generic term "machine" when
    referring to containers in API, so let's do though in sd-bus too. In
    particular, since the concept of a "container" exists in sd-bus too, but
    as part of the marshalling system.

diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 9a5fd74..6a68551 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -1313,7 +1313,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index b3ce851..de4ce7e 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -405,7 +405,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4
index de8bec3..80a61ba 100644
--- a/src/libsystemd/libsystemd.sym.m4
+++ b/src/libsystemd/libsystemd.sym.m4
@@ -169,7 +169,7 @@ global:
         sd_bus_open_user;
         sd_bus_open_system;
         sd_bus_open_system_remote;
-        sd_bus_open_system_container;
+        sd_bus_open_system_machine;
         sd_bus_new;
         sd_bus_set_address;
         sd_bus_set_fd;
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 48c20c9..e9f1a81 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -386,7 +386,7 @@ char *bus_address_escape(const char *v);
 int bus_set_address_system(sd_bus *bus);
 int bus_set_address_user(sd_bus *bus);
 int bus_set_address_system_remote(sd_bus *b, const char *host);
-int bus_set_address_system_container(sd_bus *b, const char *machine);
+int bus_set_address_system_machine(sd_bus *b, const char *machine);
 
 int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
 
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index 0f1a89c..389b6ad 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -1156,8 +1156,8 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b
                 r = sd_bus_open_system_remote(bus, host);
                 break;
 
-        case BUS_TRANSPORT_CONTAINER:
-                r = sd_bus_open_system_container(bus, host);
+        case BUS_TRANSPORT_MACHINE:
+                r = sd_bus_open_system_machine(bus, host);
                 break;
 
         default:
@@ -1191,8 +1191,8 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us
                 r = sd_bus_open_system_remote(bus, host);
                 break;
 
-        case BUS_TRANSPORT_CONTAINER:
-                r = sd_bus_open_system_container(bus, host);
+        case BUS_TRANSPORT_MACHINE:
+                r = sd_bus_open_system_machine(bus, host);
                 break;
 
         default:
diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h
index 696daa1..0609882 100644
--- a/src/libsystemd/sd-bus/bus-util.h
+++ b/src/libsystemd/sd-bus/bus-util.h
@@ -30,7 +30,7 @@
 typedef enum BusTransport {
         BUS_TRANSPORT_LOCAL,
         BUS_TRANSPORT_REMOTE,
-        BUS_TRANSPORT_CONTAINER,
+        BUS_TRANSPORT_MACHINE,
         _BUS_TRANSPORT_MAX,
         _BUS_TRANSPORT_INVALID = -1
 } BusTransport;
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index 009739f..c9eeb91 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -1854,7 +1854,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
@@ -2035,8 +2035,8 @@ int main(int argc, char *argv[]) {
                         r = bus_set_address_system_remote(bus, arg_host);
                         break;
 
-                case BUS_TRANSPORT_CONTAINER:
-                        r = bus_set_address_system_container(bus, arg_host);
+                case BUS_TRANSPORT_MACHINE:
+                        r = bus_set_address_system_machine(bus, arg_host);
                         break;
 
                 default:
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 69ee239..f87c316 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -950,7 +950,7 @@ static int bus_parse_next_address(sd_bus *b) {
                                 return r;
 
                         break;
-                } else if (startswith(a, "x-container-unix:")) {
+                } else if (startswith(a, "x-machine-unix:")) {
 
                         a += 17;
                         r = parse_container_unix_address(b, &a, &guid);
@@ -958,7 +958,7 @@ static int bus_parse_next_address(sd_bus *b) {
                                 return r;
 
                         break;
-                } else if (startswith(a, "x-container-kernel:")) {
+                } else if (startswith(a, "x-machine-kernel:")) {
 
                         a += 19;
                         r = parse_container_kernel_address(b, &a, &guid);
@@ -1334,7 +1334,7 @@ fail:
         return r;
 }
 
-int bus_set_address_system_container(sd_bus *b, const char *machine) {
+int bus_set_address_system_machine(sd_bus *b, const char *machine) {
         _cleanup_free_ char *e = NULL;
 
         assert(b);
@@ -1345,9 +1345,9 @@ int bus_set_address_system_container(sd_bus *b, const char *machine) {
                 return -ENOMEM;
 
 #ifdef ENABLE_KDBUS
-        b->address = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
+        b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
 #else
-        b->address = strjoin("x-container-unix:machine=", e, NULL);
+        b->address = strjoin("x-machine-unix:machine=", e, NULL);
 #endif
         if (!b->address)
                 return -ENOMEM;
@@ -1355,7 +1355,7 @@ int bus_set_address_system_container(sd_bus *b, const char *machine) {
         return 0;
 }
 
-_public_ int sd_bus_open_system_container(sd_bus **ret, const char *machine) {
+_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
         sd_bus *bus;
         int r;
 
@@ -1367,7 +1367,7 @@ _public_ int sd_bus_open_system_container(sd_bus **ret, const char *machine) {
         if (r < 0)
                 return r;
 
-        r = bus_set_address_system_container(bus, machine);
+        r = bus_set_address_system_machine(bus, machine);
         if (r < 0)
                 goto fail;
 
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 0d0233b..41a88a8 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -565,7 +565,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 6881edb..03abb75 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -1173,7 +1173,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 472fab6..d223e78 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1024,7 +1024,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
         assert(bus);
 
         if (arg_transport != BUS_TRANSPORT_LOCAL &&
-            arg_transport != BUS_TRANSPORT_CONTAINER) {
+            arg_transport != BUS_TRANSPORT_MACHINE) {
                 log_error("Login only supported on local machines.");
                 return -ENOTSUP;
         }
@@ -1221,7 +1221,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
diff --git a/src/run/run.c b/src/run/run.c
index 05bfc61..b183e4e 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -214,7 +214,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
@@ -679,7 +679,7 @@ static int start_transient_service(
                         if (r < 0)
                                 return log_error_errno(r, "Failed to determine tty name: %m");
 
-                } else if (arg_transport == BUS_TRANSPORT_CONTAINER) {
+                } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
                         _cleanup_bus_unref_ sd_bus *system_bus = NULL;
                         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                         const char *s;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 4c4648f..abe23ec 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -622,7 +622,7 @@ static int get_unit_list_recursive(
                         _cleanup_bus_close_unref_ sd_bus *container = NULL;
                         int k;
 
-                        r = sd_bus_open_system_container(&container, *i);
+                        r = sd_bus_open_system_machine(&container, *i);
                         if (r < 0) {
                                 log_error_errno(r, "Failed to connect to container %s: %m", *i);
                                 continue;
@@ -1713,7 +1713,7 @@ static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
         assert(mi);
 
         if (!bus) {
-                r = sd_bus_open_system_container(&container, mi->name);
+                r = sd_bus_open_system_machine(&container, mi->name);
                 if (r < 0)
                         return r;
 
@@ -3704,12 +3704,12 @@ static void print_status_info(
 
         if (i->control_group &&
             (i->main_pid > 0 || i->control_pid > 0 ||
-             ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
+             ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
                 unsigned c;
 
                 printf("   CGroup: %s\n", i->control_group);
 
-                if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
+                if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
                         unsigned k = 0;
                         pid_t extra[2];
                         static const char prefix[] = "           ";
@@ -4603,7 +4603,7 @@ static int show_system_status(sd_bus *bus) {
                format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
 
         printf("   CGroup: %s\n", mi.control_group ?: "/");
-        if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
+        if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
                 int flags =
                         arg_all * OUTPUT_SHOW_ALL |
                         (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
@@ -6682,7 +6682,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index c27537f..300b949 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -117,7 +117,7 @@ int sd_bus_open(sd_bus **ret);
 int sd_bus_open_user(sd_bus **ret);
 int sd_bus_open_system(sd_bus **ret);
 int sd_bus_open_system_remote(sd_bus **ret, const char *host);
-int sd_bus_open_system_container(sd_bus **ret, const char *machine);
+int sd_bus_open_system_machine(sd_bus **ret, const char *machine);
 
 int sd_bus_new(sd_bus **ret);
 
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 49196ca..74f40b9 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -436,7 +436,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 

commit 0254e9448f3c645758ed63618a3bbb13c242f5e7
Author: Shawn Paul Landden <shawn at churchofgit.com>
Date:   Tue Dec 23 13:47:16 2014 -0800

    util: fix strict aliasing violations in use of struct inotify_event v5
    
    There is alot of cleanup that will have to happen to turn on
    -fstrict-aliasing, but I think our code should be "correct" to the rule.

diff --git a/src/core/mount.c b/src/core/mount.c
index f8731bb..110eafd 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1701,11 +1701,11 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                  * internal behaviour of libmount here. */
 
                 for (;;) {
-                        uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
+                        union inotify_event_buffer buffer;
                         struct inotify_event *e;
                         ssize_t l;
 
-                        l = read(fd, buffer, sizeof(buffer));
+                        l = read(fd, &buffer, sizeof(buffer));
                         if (l < 0) {
                                 if (errno == EAGAIN || errno == EINTR)
                                         break;
diff --git a/src/core/path.c b/src/core/path.c
index 656ed69..0fdf483 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -157,7 +157,7 @@ void path_spec_unwatch(PathSpec *s) {
 }
 
 int path_spec_fd_event(PathSpec *s, uint32_t revents) {
-        uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
+        union inotify_event_buffer buffer;
         struct inotify_event *e;
         ssize_t l;
         int r = 0;
@@ -167,7 +167,7 @@ int path_spec_fd_event(PathSpec *s, uint32_t revents) {
                 return -EINVAL;
         }
 
-        l = read(s->inotify_fd, buffer, sizeof(buffer));
+        l = read(s->inotify_fd, &buffer, sizeof(buffer));
         if (l < 0) {
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index d46dc3c..2ce9262 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -2188,11 +2188,11 @@ _public_ int sd_journal_process(sd_journal *j) {
         j->last_process_usec = now(CLOCK_MONOTONIC);
 
         for (;;) {
-                uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
+                union inotify_event_buffer buffer;
                 struct inotify_event *e;
                 ssize_t l;
 
-                l = read(j->inotify_fd, buffer, sizeof(buffer));
+                l = read(j->inotify_fd, &buffer, sizeof(buffer));
                 if (l < 0) {
                         if (errno == EAGAIN || errno == EINTR)
                                 return got_something ? determine_change(j) : SD_JOURNAL_NOP;
diff --git a/src/shared/util.c b/src/shared/util.c
index 97ff320..e95f6ed 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -39,7 +39,6 @@
 #include <linux/tiocl.h>
 #include <termios.h>
 #include <stdarg.h>
-#include <sys/inotify.h>
 #include <sys/poll.h>
 #include <ctype.h>
 #include <sys/prctl.h>
@@ -2106,7 +2105,7 @@ int acquire_terminal(
                 assert(notify >= 0);
 
                 for (;;) {
-                        uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
+                        union inotify_event_buffer buffer;
                         struct inotify_event *e;
                         ssize_t l;
 
@@ -2129,7 +2128,7 @@ int acquire_terminal(
                                 }
                         }
 
-                        l = read(notify, buffer, sizeof(buffer));
+                        l = read(notify, &buffer, sizeof(buffer));
                         if (l < 0) {
                                 if (errno == EINTR || errno == EAGAIN)
                                         continue;
diff --git a/src/shared/util.h b/src/shared/util.h
index ec0a663..7f02f42 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -42,6 +42,7 @@
 #include <locale.h>
 #include <mntent.h>
 #include <sys/socket.h>
+#include <sys/inotify.h>
 
 #if SIZEOF_PID_T == 4
 #  define PID_FMT "%" PRIu32
@@ -1047,10 +1048,15 @@ int sethostname_idempotent(const char *s);
 #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
 
 #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
-        for ((e) = (struct inotify_event*) (buffer);    \
-             (uint8_t*) (e) < (uint8_t*) (buffer) + (sz); \
+        for ((e) = &buffer.ev;                                \
+             (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \
              (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len))
 
+union inotify_event_buffer {
+        struct inotify_event ev;
+        uint8_t raw[INOTIFY_EVENT_MAX];
+};
+
 #define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
 
 int ptsname_malloc(int fd, char **ret);
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 8bec03e..c367825 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -816,11 +816,11 @@ static int synthesize_change(struct udev_device *dev) {
 }
 
 static int handle_inotify(struct udev *udev) {
-        uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event);
+        union inotify_event_buffer buffer;
         struct inotify_event *e;
         ssize_t l;
 
-        l = read(fd_inotify, buffer, sizeof(buffer));
+        l = read(fd_inotify, &buffer, sizeof(buffer));
         if (l < 0) {
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;



More information about the systemd-commits mailing list