[systemd-commits] 6 commits - Makefile.am TODO src/core src/cryptsetup src/fstab-generator src/getty-generator src/rc-local-generator src/readahead src/shared src/system-update-generator src/systemctl units/systemd-readahead-collect.service.in units/systemd-readahead-drop.service units/systemd-readahead-replay.service.in

Lennart Poettering lennart at kemper.freedesktop.org
Tue May 22 18:52:03 PDT 2012


 Makefile.am                                           |    1 
 TODO                                                  |    4 
 src/core/manager.c                                    |  209 +++++++++++-------
 src/core/manager.h                                    |    2 
 src/cryptsetup/cryptsetup-generator.c                 |    4 
 src/fstab-generator/fstab-generator.c                 |    6 
 src/getty-generator/getty-generator.c                 |   14 -
 src/rc-local-generator/rc-local-generator.c           |   12 -
 src/readahead/readahead-collect.c                     |    2 
 src/readahead/readahead-replay.c                      |    2 
 src/readahead/sd-readahead.c                          |    3 
 src/shared/install.c                                  |    3 
 src/shared/path-lookup.c                              |  186 +++++++++++-----
 src/shared/path-lookup.h                              |    2 
 src/shared/strv.c                                     |   62 +++--
 src/shared/strv.h                                     |    4 
 src/system-update-generator/system-update-generator.c |   19 +
 src/systemctl/systemctl.c                             |    3 
 units/systemd-readahead-collect.service.in            |    3 
 units/systemd-readahead-drop.service                  |   18 +
 units/systemd-readahead-replay.service.in             |    1 
 21 files changed, 374 insertions(+), 186 deletions(-)

New commits:
commit 7b63bde1ed0d4f30c799c9b4737fa926465929f9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 23 03:51:55 2012 +0200

    update TODO

diff --git a/TODO b/TODO
index eb4e908..b3b8f40 100644
--- a/TODO
+++ b/TODO
@@ -23,6 +23,10 @@ Bugfixes:
 
 Features:
 
+* drop accountsservice's StandardOutput=syslog and Type=dbus fields
+
+* systemctl status for a unloaded unit is broken (Michal?)
+
 * make sure show-logs checks for utf8 validity, not ascii validity
 
 * add CapbilityBoundingSet to system.conf to set system-wide caps bounds, and same for TimerSlackNS

commit db5eea5a79b98a2b889f15dc21a5e0b57859b86b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 23 03:51:48 2012 +0200

    readahead: disable collect/replay during system updates

diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index abda5a0..d148550 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -60,6 +60,19 @@ static int generate_symlink(void) {
 
         free(p);
 
+        /* Also try to disable readahead, but don't try too hard */
+        p = strappend(arg_dest, "/systemd-readahead-collect.service");
+        if (p) {
+                symlink("/dev/null", p);
+                free(p);
+        }
+
+        p = strappend(arg_dest, "/systemd-readahead-replay.service");
+        if (p) {
+                symlink("/dev/null", p);
+                free(p);
+        }
+
         return 0;
 }
 

commit 08231e5142bff7ace79957835656672ac100031b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 23 03:51:25 2012 +0200

    readahead: avoid running of readahead services if readahead is already done

diff --git a/src/readahead/sd-readahead.c b/src/readahead/sd-readahead.c
index a334066..d48cd76 100644
--- a/src/readahead/sd-readahead.c
+++ b/src/readahead/sd-readahead.c
@@ -57,7 +57,8 @@ static int touch(const char *path) {
         mkdir("/run/systemd", 0755);
         mkdir("/run/systemd/readahead", 0755);
 
-        if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666)) < 0)
+        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666);
+        if (fd < 0)
                 return -errno;
 
         for (;;) {
diff --git a/units/systemd-readahead-collect.service.in b/units/systemd-readahead-collect.service.in
index 7fe20d5..6ad286b 100644
--- a/units/systemd-readahead-collect.service.in
+++ b/units/systemd-readahead-collect.service.in
@@ -11,6 +11,8 @@ DefaultDependencies=no
 Wants=systemd-readahead-done.timer
 Conflicts=shutdown.target
 Before=sysinit.target shutdown.target
+ConditionFileExists=!/run/systemd/readahead/cancel
+ConditionFileExists=!/run/systemd/readahead/done
 ConditionVirtualization=no
 
 [Service]
diff --git a/units/systemd-readahead-replay.service.in b/units/systemd-readahead-replay.service.in
index 6a10167..7324ba3 100644
--- a/units/systemd-readahead-replay.service.in
+++ b/units/systemd-readahead-replay.service.in
@@ -10,6 +10,7 @@ Description=Replay Read-Ahead Data
 DefaultDependencies=no
 Conflicts=shutdown.target
 Before=sysinit.target shutdown.target
+ConditionPathExists=!/run/systemd/readahead/noreplay
 ConditionPathExists=/.readahead
 ConditionVirtualization=no
 

commit e905f48fdc78fe3e4708aeb8515fc260eaf4eb6b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 23 03:50:53 2012 +0200

    readahead: avoid activating the journal by accident, log directly to kmsg

diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c
index 359b97b..1d56b11 100644
--- a/src/readahead/readahead-collect.c
+++ b/src/readahead/readahead-collect.c
@@ -683,7 +683,7 @@ int main(int argc, char *argv[]) {
         int r;
         const char *root;
 
-        log_set_target(LOG_TARGET_AUTO);
+        log_set_target(LOG_TARGET_SAFE);
         log_parse_environment();
         log_open();
 
diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c
index 886e16f..344dcd4 100644
--- a/src/readahead/readahead-replay.c
+++ b/src/readahead/readahead-replay.c
@@ -360,7 +360,7 @@ int main(int argc, char*argv[]) {
         int r;
         const char *root;
 
-        log_set_target(LOG_TARGET_AUTO);
+        log_set_target(LOG_TARGET_SAFE);
         log_parse_environment();
         log_open();
 

commit 18975735984b1245bb4003ec287df002f7c4cf7f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 23 03:50:15 2012 +0200

    readahead: when doing a system update drop readahead file

diff --git a/Makefile.am b/Makefile.am
index d5cf309..65a2898 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2379,6 +2379,7 @@ rootlibexec_PROGRAMS += \
 	systemd-readahead-replay
 
 dist_systemunit_DATA += \
+	units/systemd-readahead-drop.service \
 	units/systemd-readahead-done.timer
 
 nodist_systemunit_DATA += \
diff --git a/units/systemd-readahead-collect.service.in b/units/systemd-readahead-collect.service.in
index 887339c..7fe20d5 100644
--- a/units/systemd-readahead-collect.service.in
+++ b/units/systemd-readahead-collect.service.in
@@ -22,3 +22,4 @@ OOMScoreAdjust=1000
 
 [Install]
 WantedBy=default.target
+Also=systemd-readahead-drop.service
diff --git a/units/systemd-readahead-drop.service b/units/systemd-readahead-drop.service
new file mode 100644
index 0000000..a9d97d7
--- /dev/null
+++ b/units/systemd-readahead-drop.service
@@ -0,0 +1,18 @@
+#  This file is part of systemd.
+#
+#  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.
+
+[Unit]
+Description=Drop Read-Ahead Data
+ConditionPathExists=/.readahead
+
+[Service]
+Type=oneshot
+ExecStart=/bin/rm -f /.readahead
+
+[Install]
+WantedBy=system-update.target
+Also=systemd-readahead-collect.service

commit 07719a21b6425d378b36bb8d7f47ad5ec5296d28
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 23 03:43:29 2012 +0200

    manager: rework generator logic
    
    Previously generated units were always placed at the end of the search
    path. With this change there will be three unit dirs instead of one, to
    place generated entries at the beginning, in the middle and at the end
    of the search path:
    
    beginning: for units that need to override all configuration, regardless
    of user or vendor. Example use: system-update-generator uses this to
    temporarily redirect default.target.
    
    middle: for units that need to override vendor configuration, but not
    vendor configuration. Example use: /etc/fstab should override vendor
    supplied configuration (think /tmp), but should not override native user
    configuration.
    
    end: does not override anything but is available as well. Possible usage
    might be to convert D-Bus bus service files to native units but allowing
    vendor supplied native units to win.

diff --git a/src/core/manager.c b/src/core/manager.c
index 3043742..5c6d636 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -299,9 +299,6 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) {
         if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
                 goto fail;
 
-        if ((r = lookup_paths_init(&m->lookup_paths, m->running_as, true)) < 0)
-                goto fail;
-
         if ((r = manager_setup_signals(m)) < 0)
                 goto fail;
 
@@ -637,6 +634,14 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
 
         manager_run_generators(m);
 
+        r = lookup_paths_init(
+                        &m->lookup_paths, m->running_as, true,
+                        m->generator_unit_path,
+                        m->generator_unit_path_early,
+                        m->generator_unit_path_late);
+        if (r < 0)
+                return r;
+
         manager_build_unit_path_cache(m);
 
         /* If we will deserialize make sure that during enumeration
@@ -649,12 +654,15 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         r = manager_enumerate(m);
 
         /* Second, deserialize if there is something to deserialize */
-        if (serialization)
-                if ((q = manager_deserialize(m, serialization, fds)) < 0)
+        if (serialization) {
+                q = manager_deserialize(m, serialization, fds);
+                if (q < 0)
                         r = q;
+        }
 
         /* Third, fire things up! */
-        if ((q = manager_coldplug(m)) < 0)
+        q = manager_coldplug(m);
+        if (q < 0)
                 r = q;
 
         if (serialization) {
@@ -1871,18 +1879,21 @@ int manager_reload(Manager *m) {
 
         assert(m);
 
-        if ((r = manager_open_serialization(m, &f)) < 0)
+        r = manager_open_serialization(m, &f);
+        if (r < 0)
                 return r;
 
         m->n_reloading ++;
 
-        if (!(fds = fdset_new())) {
+        fds = fdset_new();
+        if (!fds) {
                 m->n_reloading --;
                 r = -ENOMEM;
                 goto finish;
         }
 
-        if ((r = manager_serialize(m, f, fds)) < 0) {
+        r = manager_serialize(m, f, fds);
+        if (r < 0) {
                 m->n_reloading --;
                 goto finish;
         }
@@ -1896,29 +1907,37 @@ int manager_reload(Manager *m) {
         /* From here on there is no way back. */
         manager_clear_jobs_and_units(m);
         manager_undo_generators(m);
-
-        /* Find new unit paths */
         lookup_paths_free(&m->lookup_paths);
-        if ((q = lookup_paths_init(&m->lookup_paths, m->running_as, true)) < 0)
-                r = q;
 
+        /* Find new unit paths */
         manager_run_generators(m);
 
+        q = lookup_paths_init(
+                        &m->lookup_paths, m->running_as, true,
+                        m->generator_unit_path,
+                        m->generator_unit_path_early,
+                        m->generator_unit_path_late);
+        if (q < 0)
+                r = q;
+
         manager_build_unit_path_cache(m);
 
         /* First, enumerate what we can from all config files */
-        if ((q = manager_enumerate(m)) < 0)
+        q = manager_enumerate(m);
+        if (q < 0)
                 r = q;
 
         /* Second, deserialize our stored data */
-        if ((q = manager_deserialize(m, f, fds)) < 0)
+        q = manager_deserialize(m, f, fds);
+        if (q < 0)
                 r = q;
 
         fclose(f);
         f = NULL;
 
         /* Third, fire things up! */
-        if ((q = manager_coldplug(m)) < 0)
+        q = manager_coldplug(m);
+        if (q < 0)
                 r = q;
 
         assert(m->n_reloading > 0);
@@ -2030,17 +2049,76 @@ void manager_check_finished(Manager *m) {
                    format_timespan(sum, sizeof(sum), total_usec));
 }
 
+static int create_generator_dir(Manager *m, char **generator, const char *name) {
+        char *p;
+        int r;
+
+        assert(m);
+        assert(generator);
+        assert(name);
+
+        if (*generator)
+                return 0;
+
+        if (m->running_as == MANAGER_SYSTEM && getpid() == 1) {
+
+                p = strappend("/run/systemd/", name);
+                if (!p) {
+                        log_error("Out of memory");
+                        return -ENOMEM;
+                }
+
+                r = mkdir_p(p, 0755);
+                if (r < 0) {
+                        log_error("Failed to create generator directory: %s", strerror(-r));
+                        free(p);
+                        return r;
+                }
+        } else {
+                p = join("/tmp/systemd-", name, ".XXXXXX", NULL);
+                if (!p) {
+                        log_error("Out of memory");
+                        return -ENOMEM;
+                }
+
+                if (!mkdtemp(p)) {
+                        free(p);
+                        log_error("Failed to create generator directory: %m");
+                        return -errno;
+                }
+        }
+
+        *generator = p;
+        return 0;
+}
+
+static void trim_generator_dir(Manager *m, char **generator) {
+        assert(m);
+        assert(generator);
+
+        if (!*generator)
+                return;
+
+        if (rmdir(*generator) >= 0) {
+                free(*generator);
+                *generator = NULL;
+        }
+
+        return;
+}
+
 void manager_run_generators(Manager *m) {
         DIR *d = NULL;
         const char *generator_path;
-        const char *argv[3];
+        const char *argv[5];
         mode_t u;
+        int r;
 
         assert(m);
 
         generator_path = m->running_as == MANAGER_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
-        if (!(d = opendir(generator_path))) {
-
+        d = opendir(generator_path);
+        if (!d) {
                 if (errno == ENOENT)
                         return;
 
@@ -2048,79 +2126,57 @@ void manager_run_generators(Manager *m) {
                 return;
         }
 
-        if (!m->generator_unit_path) {
-                const char *p;
-                char user_path[] = "/tmp/systemd-generator-XXXXXX";
-
-                if (m->running_as == MANAGER_SYSTEM && getpid() == 1) {
-                        p = "/run/systemd/generator";
-
-                        if (mkdir_p(p, 0755) < 0) {
-                                log_error("Failed to create generator directory: %m");
-                                goto finish;
-                        }
+        r = create_generator_dir(m, &m->generator_unit_path, "generator");
+        if (r < 0)
+                goto finish;
 
-                } else {
-                        if (!(p = mkdtemp(user_path))) {
-                                log_error("Failed to create generator directory: %m");
-                                goto finish;
-                        }
-                }
+        r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early");
+        if (r < 0)
+                goto finish;
 
-                if (!(m->generator_unit_path = strdup(p))) {
-                        log_error("Failed to allocate generator unit path.");
-                        goto finish;
-                }
-        }
+        r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late");
+        if (r < 0)
+                goto finish;
 
         argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
         argv[1] = m->generator_unit_path;
-        argv[2] = NULL;
+        argv[2] = m->generator_unit_path_early;
+        argv[3] = m->generator_unit_path_late;
+        argv[4] = NULL;
 
         u = umask(0022);
         execute_directory(generator_path, d, (char**) argv);
         umask(u);
 
-        if (rmdir(m->generator_unit_path) >= 0) {
-                /* Uh? we were able to remove this dir? I guess that
-                 * means the directory was empty, hence let's shortcut
-                 * this */
-
-                free(m->generator_unit_path);
-                m->generator_unit_path = NULL;
-                goto finish;
-        }
-
-        if (!strv_find(m->lookup_paths.unit_path, m->generator_unit_path)) {
-                char **l;
-
-                if (!(l = strv_append(m->lookup_paths.unit_path, m->generator_unit_path))) {
-                        log_error("Failed to add generator directory to unit search path: %m");
-                        goto finish;
-                }
-
-                strv_free(m->lookup_paths.unit_path);
-                m->lookup_paths.unit_path = l;
-
-                log_debug("Added generator unit path %s to search path.", m->generator_unit_path);
-        }
+        trim_generator_dir(m, &m->generator_unit_path);
+        trim_generator_dir(m, &m->generator_unit_path_early);
+        trim_generator_dir(m, &m->generator_unit_path_late);
 
 finish:
         if (d)
                 closedir(d);
 }
 
-void manager_undo_generators(Manager *m) {
+static void remove_generator_dir(Manager *m, char **generator) {
         assert(m);
+        assert(generator);
 
-        if (!m->generator_unit_path)
+        if (!*generator)
                 return;
 
-        strv_remove(m->lookup_paths.unit_path, m->generator_unit_path);
-        rm_rf(m->generator_unit_path, false, true, false);
+        strv_remove(m->lookup_paths.unit_path, *generator);
+        rm_rf(*generator, false, true, false);
 
-        free(m->generator_unit_path);
-        m->generator_unit_path = NULL;
+        free(*generator);
+        *generator = NULL;
+}
+
+void manager_undo_generators(Manager *m) {
+        assert(m);
+
+        remove_generator_dir(m, &m->generator_unit_path);
+        remove_generator_dir(m, &m->generator_unit_path_early);
+        remove_generator_dir(m, &m->generator_unit_path_late);
 }
 
 int manager_set_default_controllers(Manager *m, char **controllers) {
@@ -2146,18 +2202,17 @@ int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) {
         assert(m);
 
         for (i = 0; i < RLIMIT_NLIMITS; i++) {
-                if (default_rlimit[i]) {
-                        m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1);
+                if (!default_rlimit[i])
+                        continue;
 
-                        if (!m->rlimit[i])
-                                return -ENOMEM;
-                }
+                m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1);
+                if (!m->rlimit[i])
+                        return -ENOMEM;
         }
 
         return 0;
 }
 
-
 void manager_recheck_journal(Manager *m) {
         Unit *u;
 
diff --git a/src/core/manager.h b/src/core/manager.h
index 9b947c9..b29d0a7 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -152,6 +152,8 @@ struct Manager {
         dual_timestamp finish_timestamp;
 
         char *generator_unit_path;
+        char *generator_unit_path_early;
+        char *generator_unit_path_late;
 
         /* Data specific to the device subsystem */
         struct udev* udev;
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 51706b7..de64afd 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -240,8 +240,8 @@ int main(int argc, char *argv[]) {
         int r = EXIT_SUCCESS;
         unsigned n = 0;
 
-        if (argc > 2) {
-                log_error("This program takes one or no arguments.");
+        if (argc > 1 && argc != 4) {
+                log_error("This program takes three or no arguments.");
                 return EXIT_FAILURE;
         }
 
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 8a519fc..8676a20 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -498,8 +498,8 @@ finish:
 int main(int argc, char *argv[]) {
         int r;
 
-        if (argc > 2) {
-                log_error("This program takes one or no arguments.");
+        if (argc > 1 && argc != 4) {
+                log_error("This program takes three or no arguments.");
                 return EXIT_FAILURE;
         }
 
@@ -510,8 +510,6 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
-        log_set_max_level(LOG_DEBUG);
-
         umask(0022);
 
         r = parse_fstab();
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
index b2e4f52..8560026 100644
--- a/src/getty-generator/getty-generator.c
+++ b/src/getty-generator/getty-generator.c
@@ -38,8 +38,8 @@ static int add_symlink(const char *fservice, const char *tservice) {
         assert(fservice);
         assert(tservice);
 
-        asprintf(&from, SYSTEM_DATA_UNIT_PATH "/%s", fservice);
-        asprintf(&to, "%s/getty.target.wants/%s", arg_dest, tservice);
+        from = strappend(SYSTEM_DATA_UNIT_PATH "/", fservice);
+        to = join(arg_dest,"/getty.target.wants/", tservice, NULL);
 
         if (!from || !to) {
                 log_error("Out of memory");
@@ -99,20 +99,20 @@ int main(int argc, char *argv[]) {
         char *active;
         const char *j;
 
-        if (argc > 2) {
-                log_error("This program takes one or no arguments.");
+        if (argc > 1 && argc != 4) {
+                log_error("This program takes three or no arguments.");
                 return EXIT_FAILURE;
         }
 
+        if (argc > 1)
+                arg_dest = argv[1];
+
         log_set_target(LOG_TARGET_SAFE);
         log_parse_environment();
         log_open();
 
         umask(0022);
 
-        if (argc > 1)
-            arg_dest = argv[1];
-
         if (detect_container(NULL) > 0) {
                 log_debug("Automatically adding console shell.");
 
diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c
index 1464c8e..38168cc 100644
--- a/src/rc-local-generator/rc-local-generator.c
+++ b/src/rc-local-generator/rc-local-generator.c
@@ -66,7 +66,6 @@ static int add_symlink(const char *service, const char *where) {
         }
 
 finish:
-
         free(from);
         free(to);
 
@@ -83,20 +82,21 @@ static bool file_is_executable(const char *f) {
 }
 
 int main(int argc, char *argv[]) {
-
         int r = EXIT_SUCCESS;
 
-        if (argc > 2) {
-                log_error("This program takes one or no arguments.");
+        if (argc > 1 && argc != 4) {
+                log_error("This program takes three or no arguments.");
                 return EXIT_FAILURE;
         }
 
+        if (argc > 1)
+                arg_dest = argv[1];
+
         log_set_target(LOG_TARGET_SAFE);
         log_parse_environment();
         log_open();
 
-        if (argc > 1)
-                arg_dest = argv[1];
+        umask(0022);
 
         if (file_is_executable(SCRIPT_PATH_START)) {
                 log_debug("Automatically adding rc-local.service.");
diff --git a/src/shared/install.c b/src/shared/install.c
index d6644e5..7e4f666 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -60,7 +60,8 @@ static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope)
 
         return lookup_paths_init(paths,
                                  scope == UNIT_FILE_SYSTEM ? MANAGER_SYSTEM : MANAGER_USER,
-                                 scope == UNIT_FILE_USER);
+                                 scope == UNIT_FILE_USER,
+                                 NULL, NULL, NULL);
 }
 
 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index 41ebc7f..32ddb38 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -34,7 +34,8 @@
 int user_config_home(char **config_home) {
         const char *e;
 
-        if ((e = getenv("XDG_CONFIG_HOME"))) {
+        e = getenv("XDG_CONFIG_HOME");
+        if (e) {
                 if (asprintf(config_home, "%s/systemd/user", e) < 0)
                         return -ENOMEM;
 
@@ -42,7 +43,8 @@ int user_config_home(char **config_home) {
         } else {
                 const char *home;
 
-                if ((home = getenv("HOME"))) {
+                home = getenv("HOME");
+                if (home) {
                         if (asprintf(config_home, "%s/.config/systemd/user", home) < 0)
                                 return -ENOMEM;
 
@@ -53,7 +55,11 @@ int user_config_home(char **config_home) {
         return 0;
 }
 
-static char** user_dirs(void) {
+static char** user_dirs(
+                const char *generator,
+                const char *generator_early,
+                const char *generator_late) {
+
         const char * const config_unit_paths[] = {
                 USER_CONFIG_UNIT_PATH,
                 "/etc/systemd/user",
@@ -89,15 +95,19 @@ static char** user_dirs(void) {
 
         home = getenv("HOME");
 
-        if ((e = getenv("XDG_CONFIG_DIRS")))
-                if (!(config_dirs = strv_split(e, ":")))
+        e = getenv("XDG_CONFIG_DIRS");
+        if (e) {
+                config_dirs = strv_split(e, ":");
+                if (!config_dirs)
                         goto fail;
+        }
 
         /* We don't treat /etc/xdg/systemd here as the spec
          * suggests because we assume that that is a link to
          * /etc/systemd/ anyway. */
 
-        if ((e = getenv("XDG_DATA_HOME"))) {
+        e = getenv("XDG_DATA_HOME");
+        if (e) {
                 if (asprintf(&data_home, "%s/systemd/user", e) < 0)
                         goto fail;
 
@@ -116,57 +126,87 @@ static char** user_dirs(void) {
                 (void) symlink("../../../.config/systemd/user", data_home);
         }
 
-        if ((e = getenv("XDG_DATA_DIRS")))
+        e = getenv("XDG_DATA_DIRS");
+        if (e)
                 data_dirs = strv_split(e, ":");
         else
                 data_dirs = strv_new("/usr/local/share",
                                      "/usr/share",
                                      NULL);
-
         if (!data_dirs)
                 goto fail;
 
         /* Now merge everything we found. */
+        if (generator_early) {
+                t = strv_append(r, generator_early);
+                if (!t)
+                        goto fail;
+                strv_free(r);
+                r = t;
+        }
+
         if (config_home) {
-                if (!(t = strv_append(r, config_home)))
+                t = strv_append(r, config_home);
+                if (!t)
                         goto fail;
                 strv_free(r);
                 r = t;
         }
 
         if (!strv_isempty(config_dirs)) {
-                if (!(t = strv_merge_concat(r, config_dirs, "/systemd/user")))
+                t = strv_merge_concat(r, config_dirs, "/systemd/user");
+                if (!t)
                         goto finish;
                 strv_free(r);
                 r = t;
         }
 
-        if (!(t = strv_merge(r, (char**) config_unit_paths)))
+        t = strv_merge(r, (char**) config_unit_paths);
+        if (!t)
                 goto fail;
         strv_free(r);
         r = t;
 
+        if (generator) {
+                t = strv_append(r, generator);
+                if (!t)
+                        goto fail;
+                strv_free(r);
+                r = t;
+        }
+
         if (data_home) {
-                if (!(t = strv_append(r, data_home)))
+                t = strv_append(r, data_home);
+                if (!t)
                         goto fail;
                 strv_free(r);
                 r = t;
         }
 
         if (!strv_isempty(data_dirs)) {
-                if (!(t = strv_merge_concat(r, data_dirs, "/systemd/user")))
+                t = strv_merge_concat(r, data_dirs, "/systemd/user");
+                if (!t)
                         goto fail;
                 strv_free(r);
                 r = t;
         }
 
-        if (!(t = strv_merge(r, (char**) data_unit_paths)))
+        t = strv_merge(r, (char**) data_unit_paths);
+        if (!t)
                 goto fail;
         strv_free(r);
         r = t;
 
+        if (generator_late) {
+                t = strv_append(r, generator_late);
+                if (!t)
+                        goto fail;
+                strv_free(r);
+                r = t;
+        }
+
         if (!path_strv_make_absolute_cwd(r))
-            goto fail;
+                goto fail;
 
 finish:
         free(config_home);
@@ -182,7 +222,14 @@ fail:
         goto finish;
 }
 
-int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal) {
+int lookup_paths_init(
+                LookupPaths *p,
+                ManagerRunningAs running_as,
+                bool personal,
+                const char *generator,
+                const char *generator_early,
+                const char *generator_late) {
+
         const char *e;
         char *t;
 
@@ -190,64 +237,83 @@ int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal
 
         /* First priority is whatever has been passed to us via env
          * vars */
-        if ((e = getenv("SYSTEMD_UNIT_PATH")))
-                if (!(p->unit_path = path_split_and_make_absolute(e)))
+        e = getenv("SYSTEMD_UNIT_PATH");
+        if (e) {
+                p->unit_path = path_split_and_make_absolute(e);
+                if (!p->unit_path)
                         return -ENOMEM;
+        } else
+                p->unit_path = NULL;
 
         if (strv_isempty(p->unit_path)) {
-
                 /* Nothing is set, so let's figure something out. */
                 strv_free(p->unit_path);
 
+                /* For the user units we include share/ in the search
+                 * path in order to comply with the XDG basedir
+                 * spec. For the system stuff we avoid such
+                 * nonsense. OTOH we include /lib in the search path
+                 * for the system stuff but avoid it for user
+                 * stuff. */
+
                 if (running_as == MANAGER_USER) {
 
                         if (personal)
-                                p->unit_path = user_dirs();
+                                p->unit_path = user_dirs(generator, generator_early, generator_late);
                         else
                                 p->unit_path = strv_new(
                                                 /* If you modify this you also want to modify
                                                  * systemduserunitpath= in systemd.pc.in, and
                                                  * the arrays in user_dirs() above! */
+                                                STRV_IFNOTNULL(generator_early),
                                                 USER_CONFIG_UNIT_PATH,
                                                 "/etc/systemd/user",
                                                 "/run/systemd/user",
+                                                STRV_IFNOTNULL(generator),
                                                 "/usr/local/lib/systemd/user",
                                                 "/usr/local/share/systemd/user",
                                                 USER_DATA_UNIT_PATH,
                                                 "/usr/lib/systemd/user",
                                                 "/usr/share/systemd/user",
+                                                STRV_IFNOTNULL(generator_late),
                                                 NULL);
 
                         if (!p->unit_path)
                                 return -ENOMEM;
 
-                } else
-                        if (!(p->unit_path = strv_new(
-                                              /* If you modify this you also want to modify
-                                               * systemdsystemunitpath= in systemd.pc.in! */
-                                              SYSTEM_CONFIG_UNIT_PATH,
-                                              "/etc/systemd/system",
-                                              "/run/systemd/system",
-                                              "/usr/local/lib/systemd/system",
-                                              SYSTEM_DATA_UNIT_PATH,
-                                              "/usr/lib/systemd/system",
+                } else {
+                        p->unit_path = strv_new(
+                                        /* If you modify this you also want to modify
+                                         * systemdsystemunitpath= in systemd.pc.in! */
+                                        STRV_IFNOTNULL(generator_early),
+                                        SYSTEM_CONFIG_UNIT_PATH,
+                                        "/etc/systemd/system",
+                                        "/run/systemd/system",
+                                        STRV_IFNOTNULL(generator),
+                                        "/usr/local/lib/systemd/system",
+                                        SYSTEM_DATA_UNIT_PATH,
+                                        "/usr/lib/systemd/system",
 #ifdef HAVE_SPLIT_USR
-                                              "/lib/systemd/system",
+                                        "/lib/systemd/system",
 #endif
-                                              NULL)))
+                                        STRV_IFNOTNULL(generator_late),
+                                        NULL);
+
+                        if (!p->unit_path)
                                 return -ENOMEM;
+                }
         }
 
-        if (p->unit_path)
-                if (!path_strv_canonicalize(p->unit_path))
-                        return -ENOMEM;
+        if (!path_strv_canonicalize(p->unit_path))
+                return -ENOMEM;
 
         strv_uniq(p->unit_path);
         path_strv_remove_empty(p->unit_path);
 
         if (!strv_isempty(p->unit_path)) {
 
-                if (!(t = strv_join(p->unit_path, "\n\t")))
+                t = strv_join(p->unit_path, "\n\t");
+                if (!t)
                         return -ENOMEM;
                 log_debug("Looking for unit files in:\n\t%s", t);
                 free(t);
@@ -261,51 +327,58 @@ int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal
 #ifdef HAVE_SYSV_COMPAT
                 /* /etc/init.d/ compatibility does not matter to users */
 
-                if ((e = getenv("SYSTEMD_SYSVINIT_PATH")))
-                        if (!(p->sysvinit_path = path_split_and_make_absolute(e)))
+                e = getenv("SYSTEMD_SYSVINIT_PATH");
+                if (e) {
+                        p->sysvinit_path = path_split_and_make_absolute(e);
+                        if (!p->sysvinit_path)
                                 return -ENOMEM;
+                } else
+                        p->sysvinit_path = NULL;
 
                 if (strv_isempty(p->sysvinit_path)) {
                         strv_free(p->sysvinit_path);
 
-                        if (!(p->sysvinit_path = strv_new(
-                                              SYSTEM_SYSVINIT_PATH,     /* /etc/init.d/ */
-                                              NULL)))
+                        p->sysvinit_path = strv_new(
+                                        SYSTEM_SYSVINIT_PATH,     /* /etc/init.d/ */
+                                        NULL);
+                        if (!p->sysvinit_path)
                                 return -ENOMEM;
                 }
 
-                if ((e = getenv("SYSTEMD_SYSVRCND_PATH")))
-                        if (!(p->sysvrcnd_path = path_split_and_make_absolute(e)))
+                e = getenv("SYSTEMD_SYSVRCND_PATH");
+                if (e) {
+                        p->sysvrcnd_path = path_split_and_make_absolute(e);
+                        if (!p->sysvrcnd_path)
                                 return -ENOMEM;
+                } else
+                        p->sysvrcnd_path = NULL;
 
                 if (strv_isempty(p->sysvrcnd_path)) {
                         strv_free(p->sysvrcnd_path);
 
-                        if (!(p->sysvrcnd_path = strv_new(
-                                              SYSTEM_SYSVRCND_PATH,     /* /etc/rcN.d/ */
-                                              NULL)))
+                        p->sysvrcnd_path = strv_new(
+                                        SYSTEM_SYSVRCND_PATH,     /* /etc/rcN.d/ */
+                                        NULL);
+                        if (!p->sysvrcnd_path)
                                 return -ENOMEM;
                 }
 
-                if (p->sysvinit_path)
-                        if (!path_strv_canonicalize(p->sysvinit_path))
-                                return -ENOMEM;
+                if (!path_strv_canonicalize(p->sysvinit_path))
+                        return -ENOMEM;
 
-                if (p->sysvrcnd_path)
-                        if (!path_strv_canonicalize(p->sysvrcnd_path))
-                                return -ENOMEM;
+                if (!path_strv_canonicalize(p->sysvrcnd_path))
+                        return -ENOMEM;
 
                 strv_uniq(p->sysvinit_path);
                 strv_uniq(p->sysvrcnd_path);
-
                 path_strv_remove_empty(p->sysvinit_path);
                 path_strv_remove_empty(p->sysvrcnd_path);
 
                 if (!strv_isempty(p->sysvinit_path)) {
 
-                        if (!(t = strv_join(p->sysvinit_path, "\n\t")))
+                        t = strv_join(p->sysvinit_path, "\n\t");
+                        if (!t)
                                 return -ENOMEM;
-
                         log_debug("Looking for SysV init scripts in:\n\t%s", t);
                         free(t);
                 } else {
@@ -316,7 +389,8 @@ int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal
 
                 if (!strv_isempty(p->sysvrcnd_path)) {
 
-                        if (!(t = strv_join(p->sysvrcnd_path, "\n\t")))
+                        t = strv_join(p->sysvrcnd_path, "\n\t");
+                        if (!t)
                                 return -ENOMEM;
 
                         log_debug("Looking for SysV rcN.d links in:\n\t%s", t);
diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h
index e8a5a77..96c49c2 100644
--- a/src/shared/path-lookup.h
+++ b/src/shared/path-lookup.h
@@ -34,7 +34,7 @@ typedef struct LookupPaths {
 
 int user_config_home(char **config_home);
 
-int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal);
+int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal, const char *generator, const char *generator_early, const char *generator_late);
 void lookup_paths_free(LookupPaths *p);
 
 #endif
diff --git a/src/shared/strv.c b/src/shared/strv.c
index 18de4f8..c8d8563 100644
--- a/src/shared/strv.c
+++ b/src/shared/strv.c
@@ -106,28 +106,44 @@ char **strv_new_ap(const char *x, va_list ap) {
         unsigned n = 0, i = 0;
         va_list aq;
 
+        /* As a special trick we ignore all listed strings that equal
+         * (const char*) -1. This is supposed to be used with the
+         * STRV_IFNOTNULL() macro to include possibly NULL strings in
+         * the string list. */
+
         if (x) {
-                n = 1;
+                n = x == (const char*) -1 ? 0 : 1;
 
                 va_copy(aq, ap);
-                while (va_arg(aq, const char*))
+                while ((s = va_arg(aq, const char*))) {
+                        if (s == (const char*) -1)
+                                continue;
+
                         n++;
+                }
+
                 va_end(aq);
         }
 
-        if (!(a = new(char*, n+1)))
+        a = new(char*, n+1);
+        if (!a)
                 return NULL;
 
         if (x) {
-                if (!(a[i] = strdup(x))) {
-                        free(a);
-                        return NULL;
+                if (x != (const char*) -1) {
+                        a[i] = strdup(x);
+                        if (!a[i])
+                                goto fail;
+                        i++;
                 }
 
-                i++;
-
                 while ((s = va_arg(ap, const char*))) {
-                        if (!(a[i] = strdup(s)))
+
+                        if (s == (const char*) -1)
+                                continue;
+
+                        a[i] = strdup(s);
+                        if (!a[i])
                                 goto fail;
 
                         i++;
@@ -169,25 +185,27 @@ char **strv_merge(char **a, char **b) {
         if (!b)
                 return strv_copy(a);
 
-        if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
+        r = new(char*, strv_length(a) + strv_length(b) + 1);
+        if (!r)
                 return NULL;
 
-        for (k = r; *a; k++, a++)
-                if (!(*k = strdup(*a)))
+        for (k = r; *a; k++, a++) {
+                *k = strdup(*a);
+                if (!*k)
                         goto fail;
-        for (; *b; k++, b++)
-                if (!(*k = strdup(*b)))
+        }
+
+        for (; *b; k++, b++) {
+                *k = strdup(*b);
+                if (!*k)
                         goto fail;
+        }
 
         *k = NULL;
         return r;
 
 fail:
-        for (k--; k >= r; k--)
-                free(*k);
-
-        free(r);
-
+        strv_free(r);
         return NULL;
 }
 
@@ -221,11 +239,7 @@ char **strv_merge_concat(char **a, char **b, const char *suffix) {
         return r;
 
 fail:
-        for (k--; k >= r; k--)
-                free(*k);
-
-        free(r);
-
+        strv_free(r);
         return NULL;
 
 }
diff --git a/src/shared/strv.h b/src/shared/strv.h
index afb31f3..635e92b 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -47,6 +47,10 @@ char **strv_uniq(char **l);
 char **strv_new(const char *x, ...) _sentinel_ _malloc_;
 char **strv_new_ap(const char *x, va_list ap) _malloc_;
 
+static inline const char* STRV_IFNOTNULL(const char *x) {
+        return x ? x : (const char *) -1;
+}
+
 static inline bool strv_isempty(char **l) {
         return !l || !*l;
 }
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index f4e8daf..abda5a0 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -66,13 +66,13 @@ static int generate_symlink(void) {
 int main(int argc, char *argv[]) {
         int r;
 
-        if (argc > 2) {
-                log_error("This program takes one or no arguments.");
+        if (argc > 1 && argc != 4) {
+                log_error("This program takes three or no arguments.");
                 return EXIT_FAILURE;
         }
 
         if (argc > 1)
-                arg_dest = argv[1];
+                arg_dest = argv[2];
 
         log_set_target(LOG_TARGET_SAFE);
         log_parse_environment();
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 03c2fd2..66f4113 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3697,12 +3697,11 @@ static int enable_sysv_units(char **args) {
          * afterwards only the native units remain */
 
         zero(paths);
-        r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
+        r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, NULL, NULL, NULL);
         if (r < 0)
                 return r;
 
         r = 0;
-
         for (f = 1; args[f]; f++) {
                 const char *name;
                 char *p;



More information about the systemd-commits mailing list