[systemd-commits] 14 commits - Makefile.am TODO man/systemd-gpt-auto-generator.xml src/core src/cryptsetup src/efi-boot-generator src/fstab-generator src/gpt-auto-generator src/login src/shared src/sleep units/systemd-tmpfiles-setup-dev.service.in units/systemd-update-utmp.service.in

Lennart Poettering lennart at kemper.freedesktop.org
Wed Mar 5 20:08:40 PST 2014


 Makefile.am                                 |    5 
 TODO                                        |   11 -
 man/systemd-gpt-auto-generator.xml          |   84 ++++++-
 src/core/device.c                           |  112 +++++++---
 src/core/manager.c                          |    2 
 src/core/shutdown.c                         |    2 
 src/core/unit.c                             |   42 +--
 src/cryptsetup/cryptsetup-generator.c       |   62 ++---
 src/efi-boot-generator/efi-boot-generator.c |   71 ++++--
 src/fstab-generator/fstab-generator.c       |  133 ++++--------
 src/gpt-auto-generator/gpt-auto-generator.c |  308 +++++++++++++++++++++-------
 src/login/logind-session.c                  |    2 
 src/shared/generator.c                      |   84 +++++++
 src/shared/generator.h                      |   26 ++
 src/shared/gpt.h                            |   28 ++
 src/shared/unit-name.c                      |   25 --
 src/shared/util.c                           |  162 +++++++-------
 src/shared/util.h                           |    2 
 src/sleep/sleep.c                           |   14 -
 units/systemd-tmpfiles-setup-dev.service.in |    2 
 units/systemd-update-utmp.service.in        |    2 
 21 files changed, 787 insertions(+), 392 deletions(-)

New commits:
commit 0939968c77c7b570da0a4387262f29a83cd0e5d4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 05:03:39 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index 5630c1c..bcaab4a 100644
--- a/TODO
+++ b/TODO
@@ -27,8 +27,10 @@ External:
 
 Features:
 
+* mount generators currently check if /boot, /home, /srv is empty or
+  not, before doing something. This breaks on PID 1 reload.
+
 * gpt-auto-generator:
-  - Properly handle cryptsetup partitions
   - Define new partition type for encrypted swap
   - Make /home automount rather than mount?
   - don't use blkid on every single partition, but on the main disk only
@@ -82,8 +84,6 @@ Features:
   service instances processing the listening socket, and open this up
   for ReusePort=
 
-* add a timelimit to generator invocation
-
 * socket units: support creating sockets in different namespace,
   opening it up for JoinsNamespaceOf=. This would require to fork off
   a tiny process that joins the namespace and creates/binds the socket

commit 965e5c5daff660e13a31bfa5a27af733a707ec4b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:57:16 2014 +0100

    core: include partition label in .device description fields

diff --git a/src/core/device.c b/src/core/device.c
index d17b2df..444286e 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -183,13 +183,85 @@ static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
         return 0;
 }
 
+static int device_make_description(Unit *u, struct udev_device *dev, const char *path) {
+        const char *model;
+
+        assert(u);
+        assert(dev);
+        assert(path);
+
+        model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
+        if (!model)
+                model = udev_device_get_property_value(dev, "ID_MODEL");
+
+        if (model) {
+                const char *label;
+
+                /* Try to concatenate the device model string with a label, if there is one */
+                label = udev_device_get_property_value(dev, "ID_FS_LABEL");
+                if (!label)
+                        label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME");
+                if (!label)
+                        label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER");
+
+                if (label) {
+                        _cleanup_free_ char *j;
+
+                        j = strjoin(model, " ", label, NULL);
+                        if (j)
+                                return unit_set_description(u, j);
+                }
+
+                return unit_set_description(u, model);
+        }
+
+        return unit_set_description(u, path);
+}
+
+static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
+        const char *wants;
+        char *state, *w;
+        size_t l;
+        int r;
+
+        assert(u);
+        assert(dev);
+
+        wants = udev_device_get_property_value(
+                        dev,
+                        u->manager->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS");
+
+        if (!wants)
+                return 0;
+
+        FOREACH_WORD_QUOTED(w, l, wants, state) {
+                _cleanup_free_ char *n = NULL;
+                char e[l+1];
+
+                memcpy(e, w, l);
+                e[l] = 0;
+
+                n = unit_name_mangle(e, MANGLE_NOGLOB);
+                if (!n)
+                        return -ENOMEM;
+
+                r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
 static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
-        const char *sysfs, *model;
+        const char *sysfs;
         Unit *u = NULL;
-        int r;
         bool delete;
+        int r;
 
         assert(m);
+        assert(dev);
+        assert(path);
 
         sysfs = udev_device_get_syspath(dev);
         if (!sysfs)
@@ -242,43 +314,15 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
                         goto fail;
         }
 
-        if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
-            (model = udev_device_get_property_value(dev, "ID_MODEL")))
-                r = unit_set_description(u, model);
-        else
-                r = unit_set_description(u, path);
-        if (r < 0)
-                goto fail;
+        device_make_description(u, dev, path);
 
         if (main) {
-                const char *wants;
-
                 /* The additional systemd udev properties we only
                  * interpret for the main object */
 
-                wants = udev_device_get_property_value(dev, m->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS");
-                if (wants) {
-                        char *state, *w;
-                        size_t l;
-
-                        FOREACH_WORD_QUOTED(w, l, wants, state) {
-                                _cleanup_free_ char *n = NULL;
-                                char e[l+1];
-
-                                memcpy(e, w, l);
-                                e[l] = 0;
-
-                                n = unit_name_mangle(e, MANGLE_NOGLOB);
-                                if (!n) {
-                                        r = -ENOMEM;
-                                        goto fail;
-                                }
-
-                                r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
-                                if (r < 0)
-                                        goto fail;
-                        }
-                }
+                r = device_add_udev_wants(u, dev);
+                if (r < 0)
+                        goto fail;
         }
 
         /* Note that this won't dispatch the load queue, the caller

commit 646e392e10924454576f10b072f78d7676422816
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:52:31 2014 +0100

    logind: fix reference to systemd-user-sessions.service

diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 548f049..3700522 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -490,7 +490,7 @@ static int session_start_scope(Session *s) {
                 if (!scope)
                         return log_oom();
 
-                r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-session.service", &error, &job);
+                r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
                 if (r < 0) {
                         log_error("Failed to start session scope %s: %s %s",
                                   scope, bus_error_message(&error, r), error.name);

commit 1ebab691c7749779072741f71865bd0e055b7ecf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:52:13 2014 +0100

    gpt-auto-generation: set a pretty description string

diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 4f5224f..c4109f3 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -144,6 +144,8 @@ static int add_swap(const char *path, const char *fstype) {
 
         fprintf(f,
                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
+                "[Unit]\n"
+                "Description=Swap Partition\n\n"
                 "[Swap]\n"
                 "What=%s\n",
                 path);

commit 9533ad1f429ec037a155a5793d70ef49e69fbec2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:51:48 2014 +0100

    units: don't use the word 'Reboot' for Startup, but simply 'Boot'

diff --git a/units/systemd-update-utmp.service.in b/units/systemd-update-utmp.service.in
index e7c20a5..da7dda7 100644
--- a/units/systemd-update-utmp.service.in
+++ b/units/systemd-update-utmp.service.in
@@ -6,7 +6,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Update UTMP about System Reboot/Shutdown
+Description=Update UTMP about System Boot/Shutdown
 Documentation=man:systemd-update-utmp.service(8) man:utmp(5)
 DefaultDependencies=no
 RequiresMountsFor=/var/log/wtmp

commit d1a6f44125c31364b02da66216a5f9b3647fd0d7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:51:11 2014 +0100

    units: properly capitalize the unit description

diff --git a/units/systemd-tmpfiles-setup-dev.service.in b/units/systemd-tmpfiles-setup-dev.service.in
index 579e7c6..05b60a1 100644
--- a/units/systemd-tmpfiles-setup-dev.service.in
+++ b/units/systemd-tmpfiles-setup-dev.service.in
@@ -6,7 +6,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Create static device nodes in /dev
+Description=Create Static Device Nodes in /dev
 Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
 DefaultDependencies=no
 Before=sysinit.target local-fs-pre.target systemd-udevd.service

commit 9788205f453178fd0b349d44aac76e0cbf8633dc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:50:19 2014 +0100

    man: bring gpt-auto-generator up to date

diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml
index 95c0c35..7531399 100644
--- a/man/systemd-gpt-auto-generator.xml
+++ b/man/systemd-gpt-auto-generator.xml
@@ -43,7 +43,7 @@
         <refnamediv>
                 <refname>systemd-gpt-auto-generator</refname>
                 <refpurpose>Generator for automatically discovering
-                and mounting <filename>/home</filename> as well as
+                and mounting <filename>/home</filename> and <filename>/srv</filename>, as well as
                 discovering and enabling swap partitions, based on GPT
                 partition type GUIDs.</refpurpose>
         </refnamediv>
@@ -56,16 +56,16 @@
                 <title>Description</title>
 
                 <para><filename>systemd-gpt-auto-generator</filename>
-                is a generator that automatically discovers
-                <filename>/home</filename> and swap partitions and
-                creates mount and swap units for them, based on the
-                the partition type GUIDs of GUID partition tables
-                (GPT). Note that this generator will execute no
-                operation on non-GPT systems, on systems where the
+                is a unit generator that automatically discovers
+                <filename>/home</filename>, <filename>/srv</filename>
+                and swap partitions and creates mount and swap units
+                for them, based on the the partition type GUIDs of
+                GUID partition tables (GPT). Note that this generator
+                has no effect on non-GPT systems, on systems where the
                 units are explicitly configured (for example, listed
                 in
-                <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
-                or where the mount point is non-empty.</para>
+                <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
+                or where the mount points are non-empty.</para>
 
                 <para>This generator will only look for partitions on
                 the same physical disk the root file system is stored
@@ -73,16 +73,63 @@
                 root file system is distributed on multiple disks, for
                 example via btrfs RAID.</para>
 
-                <para>This generator is useful for centralizing file
-                system configuration in the partition table and making
-                manual configuration in
-                <filename>/etc/fstab</filename> or suchlike
+                <para><filename>systemd-gpt-auto-generator</filename>
+                is useful for centralizing file system configuration
+                in the partition table and making manual configuration
+                in <filename>/etc/fstab</filename> or suchlike
                 unnecessary.</para>
 
-                <para>This generator looks for swap partitions using
-                GPT type 0657fd6d-a4ab-43c4-84e50933c84b4f4f. It looks
-                for <filename>/home</filename> partitions using GPT
-                type 933ac7e1-2eb4-4f13-b8440e14e2aef915.</para>
+                <para>This generator looks for the partitions based on
+                their partition type GUID. The following partition
+                type GUIDs are identified:</para>
+
+                <table>
+                        <title>Partition Type GUIDs</title>
+                        <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+                                <colspec colname="guid" />
+                                <colspec colname="location" />
+                                <colspec colname="explanation" />
+                                <thead>
+                                        <row>
+                                                <entry>Partition Type GUID</entry>
+                                                <entry>Location</entry>
+                                                <entry>Explanation</entry>
+                                        </row>
+                                </thead>
+                                <tbody>
+                                        <row>
+                                                <entry>0657fd6d-a4ab-43c4-84e50933c84b4f4f</entry>
+                                                <entry>Swap</entry>
+                                                <entry>All swap partitions are enabled.</entry>
+                                        </row>
+                                        <row>
+                                                <entry>933ac7e1-2eb4-4f13-b8440e14e2aef915</entry>
+                                                <entry><filename>/home</filename></entry>
+                                                <entry>The first home partition on the disk is mounted to <filename>/home</filename>.</entry>
+                                        </row>
+                                        <row>
+                                                <entry>3b8f8425-20e0-4f3b-907f1a25a76f98e8</entry>
+                                                <entry><filename>/srv</filename></entry>
+                                                <entry>The first server data partition on the disk is mounted to <filename>/srv</filename>.</entry>
+                                        </row>
+                                </tbody>
+                        </tgroup>
+                </table>
+
+                <para>The <filename>/home</filename> and
+                <filename>/srv</filename> partitions may be encrypted
+                in LUKS format. In this case a device mapper device is
+                set up under the names
+                <filename>/dev/mapper/home</filename> and
+                <filename>/dev/mapper/srv</filename>. Note that this
+                might create conflicts if the same partition is listed
+                in <filename>/etc/crypttab</filename> with a different
+                device mapper device name.</para>
+
+                <para>Also note that
+                <citerefentry><refentrytitle>systemd-efi-boot-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+                will mount the EFI System Partition to
+                <filename>/boot</filename> is not otherwise mounted.</para>
 
                 <para><filename>systemd-gpt-auto-generator</filename>
                 implements the <ulink
@@ -96,7 +143,10 @@
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd-efi-boot-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>systemd-cryptsetup at .service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>
                 </para>
         </refsect1>

commit 1af7211984a8dba3c5ba40fae794c4c55f5e6bd3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:05:13 2014 +0100

    gpt-auto-generator: properly handle LUKS partitions

diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 6267d9d..4f5224f 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -30,18 +30,19 @@
 #include <linux/btrfs.h>
 #endif
 
+#include "sd-id128.h"
+#include "libudev.h"
 #include "path-util.h"
 #include "util.h"
 #include "mkdir.h"
 #include "missing.h"
-#include "sd-id128.h"
-#include "libudev.h"
 #include "udev-util.h"
 #include "special.h"
 #include "unit-name.h"
 #include "virt.h"
 #include "generator.h"
 #include "gpt.h"
+#include "fileio.h"
 
 static const char *arg_dest = "/tmp";
 
@@ -166,11 +167,134 @@ static int add_swap(const char *path, const char *fstype) {
         return 0;
 }
 
-static int add_mount(const char *what, const char *where, const char *fstype, const char *description) {
-        _cleanup_free_ char *unit = NULL, *lnk = NULL, *p = NULL;
+static int add_cryptsetup(const char *id, const char *what, char **device) {
+        _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        char *from, *ret;
+        int r;
+
+        assert(id);
+        assert(what);
+        assert(device);
+
+        d = unit_name_from_path(what, ".device");
+        if (!d)
+                return log_oom();
+
+        e = unit_name_escape(id);
+        if (!e)
+                return log_oom();
+
+        n = unit_name_build("systemd-cryptsetup", e, ".service");
+        if (!n)
+                return log_oom();
+
+        p = strjoin(arg_dest, "/", n, NULL);
+        if (!n)
+                return log_oom();
+
+        f = fopen(p, "wxe");
+        if (!f) {
+                log_error("Failed to create unit file %s: %m", p);
+                return -errno;
+        }
+
+        fprintf(f,
+                "# Automatically generated by systemd-gpt-auto-generator\n\n"
+                "[Unit]\n"
+                "Description=Cryptography Setup for %%I\n"
+                "Documentation=man:systemd-cryptsetup at .service(8)\n"
+                "DefaultDependencies=no\n"
+                "Conflicts=umount.target\n"
+                "BindsTo=dev-mapper-%%i.device %s\n"
+                "Before=umount.target cryptsetup.target\n"
+                "After=%s\n"
+                "IgnoreOnIsolate=true\n"
+                "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
+                "[Service]\n"
+                "Type=oneshot\n"
+                "RemainAfterExit=yes\n"
+                "TimeoutSec=0\n" /* the binary handles timeouts anyway */
+                "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s'\n"
+                "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
+                d, d,
+                id, what,
+                id);
+
+        fflush(f);
+        if (ferror(f)) {
+                log_error("Failed to write file %s: %m", p);
+                return -errno;
+        }
+
+        from = strappenda("../", n);
+
+        to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
+        if (!to)
+                return log_oom();
+
+        mkdir_parents_label(to, 0755);
+        if (symlink(from, to) < 0) {
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
+
+        free(to);
+        to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
+        if (!to)
+                return log_oom();
+
+        mkdir_parents_label(to, 0755);
+        if (symlink(from, to) < 0) {
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
+
+        free(to);
+        to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
+        if (!to)
+                return log_oom();
+
+        mkdir_parents_label(to, 0755);
+        if (symlink(from, to) < 0) {
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
+
+        free(p);
+        p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
+        if (!p)
+                return log_oom();
+
+        mkdir_parents_label(p, 0755);
+        r = write_string_file(p,
+                        "# Automatically generated by systemd-gpt-auto-generator\n\n"
+                        "[Unit]\n"
+                        "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
+        if (r < 0) {
+                log_error("Failed to write device drop-in: %s", strerror(-r));
+                return r;
+        }
+
+        ret = strappend("/dev/mapper/", id);
+        if (!ret)
+                return log_oom();
+
+        *device = ret;
+        return 0;
+}
+
+static int add_mount(const char *id, const char *what, const char *where, const char *fstype, const char *description) {
+        _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
+        assert(id);
+        assert(what);
+        assert(where);
+        assert(fstype);
+        assert(description);
+
         if (dir_is_empty(where) <= 0) {
                 log_debug("%s already populated, ignoring.", where);
                 return 0;
@@ -178,6 +302,16 @@ static int add_mount(const char *what, const char *where, const char *fstype, co
 
         log_debug("Adding %s: %s %s", where, what, fstype);
 
+        if (streq(fstype, "crypto_LUKS")) {
+
+                r = add_cryptsetup(id, what, &crypto_what);
+                if (r < 0)
+                        return r;
+
+                what = crypto_what;
+                fstype = NULL;
+        }
+
         unit = unit_name_from_path(where, ".mount");
         if (!unit)
                 return log_oom();
@@ -206,9 +340,14 @@ static int add_mount(const char *what, const char *where, const char *fstype, co
                 "\n"
                 "[Mount]\n"
                 "What=%s\n"
-                "Where=%s\n"
-                "Type=%s\n",
-                what, where, fstype);
+                "Where=%s\n",
+                what, where);
+
+        if (fstype) {
+                fprintf(f,
+                        "Type=%s\n",
+                        fstype);
+        }
 
         fflush(f);
         if (ferror(f)) {
@@ -337,10 +476,10 @@ static int enumerate_partitions(struct udev *udev, dev_t dev) {
         }
 
         if (home && home_fstype)
-                add_mount(home, "/home", home_fstype, "Home Partition");
+                add_mount("home", home, "/home", home_fstype, "Home Partition");
 
         if (srv && srv_fstype)
-                add_mount(srv, "/srv", srv_fstype, "Server Data Partition");
+                add_mount("srv", srv, "/srv", srv_fstype, "Server Data Partition");
 
         return r;
 }

commit 58d081428af6f49c601619c2ee9f9aae24d05fae
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 04:04:58 2014 +0100

    unit-name: modernizations

diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
index 2924c47..e9b0636 100644
--- a/src/shared/unit-name.c
+++ b/src/shared/unit-name.c
@@ -294,7 +294,7 @@ char *unit_name_unescape(const char *f) {
 }
 
 char *unit_name_path_escape(const char *f) {
-        char *p, *e;
+        _cleanup_free_ char *p;
 
         assert(f);
 
@@ -304,15 +304,10 @@ char *unit_name_path_escape(const char *f) {
 
         path_kill_slashes(p);
 
-        if (streq(p, "/") || streq(p, "")) {
-                free(p);
+        if (streq(p, "/") || streq(p, ""))
                 return strdup("-");
-        }
-
-        e = unit_name_escape(p[0] == '/' ? p + 1 : p);
-        free(p);
 
-        return e;
+        return unit_name_escape(p[0] == '/' ? p + 1 : p);
 }
 
 char *unit_name_path_unescape(const char *f) {
@@ -410,7 +405,7 @@ char *unit_name_template(const char *f) {
 }
 
 char *unit_name_from_path(const char *path, const char *suffix) {
-        char *p, *r;
+        _cleanup_free_ char *p = NULL;
 
         assert(path);
         assert(suffix);
@@ -419,14 +414,11 @@ char *unit_name_from_path(const char *path, const char *suffix) {
         if (!p)
                 return NULL;
 
-        r = strappend(p, suffix);
-        free(p);
-
-        return r;
+        return strappend(p, suffix);
 }
 
 char *unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix) {
-        char *p, *r;
+        _cleanup_free_ char *p = NULL;
 
         assert(prefix);
         assert(path);
@@ -436,10 +428,7 @@ char *unit_name_from_path_instance(const char *prefix, const char *path, const c
         if (!p)
                 return NULL;
 
-        r = strjoin(prefix, "@", p, suffix, NULL);
-        free(p);
-
-        return r;
+        return strjoin(prefix, "@", p, suffix, NULL);
 }
 
 char *unit_name_to_path(const char *name) {

commit 744198e92501e9d98047ef6b0f7e8da3597a1f0f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 02:26:52 2014 +0100

    cryptsetup: some fixes

diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 38c746b..d2e0554 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -33,11 +33,9 @@
 static const char *arg_dest = "/tmp";
 static bool arg_enabled = true;
 static bool arg_read_crypttab = true;
-
-static char **arg_disks;
-static char **arg_options;
-static char *arg_keyfile;
-
+static char **arg_disks = NULL;
+static char **arg_options = NULL;
+static char *arg_keyfile = NULL;
 
 static bool has_option(const char *haystack, const char *needle) {
         const char *f = haystack;
@@ -74,9 +72,11 @@ static int create_disk(
                 const char *password,
                 const char *options) {
 
-        _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
+        _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         bool noauto, nofail, tmp, swap;
+        char *from;
+        int r;
 
         assert(name);
         assert(device);
@@ -91,7 +91,11 @@ static int create_disk(
                 return -EINVAL;
         }
 
-        n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
+        e = unit_name_escape(name);
+        if (!e)
+                return log_oom();
+
+        n = unit_name_build("systemd-cryptsetup", e, ".service");
         if (!n)
                 return log_oom();
 
@@ -119,8 +123,8 @@ static int create_disk(
                 "Description=Cryptography Setup for %I\n"
                 "Documentation=man:systemd-cryptsetup at .service(8) man:crypttab(5)\n"
                 "SourcePath=/etc/crypttab\n"
-                "Conflicts=umount.target\n"
                 "DefaultDependencies=no\n"
+                "Conflicts=umount.target\n"
                 "BindsTo=dev-mapper-%i.device\n"
                 "IgnoreOnIsolate=true\n"
                 "After=systemd-readahead-collect.service systemd-readahead-replay.service\n",
@@ -131,19 +135,20 @@ static int create_disk(
                         "Before=cryptsetup.target\n");
 
         if (password) {
-                if (streq(password, "/dev/urandom") ||
-                    streq(password, "/dev/random") ||
-                    streq(password, "/dev/hw_random"))
+                if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random"))
                         fputs("After=systemd-random-seed.service\n", f);
-
                 else if (!streq(password, "-") && !streq(password, "none")) {
-                        _cleanup_free_ char *uu = fstab_node_to_udev_node(password);
-                        if (uu == NULL)
+                        _cleanup_free_ char *uu;
+
+                        uu = fstab_node_to_udev_node(password);
+                        if (!uu)
                                 return log_oom();
 
                         if (is_device_path(uu)) {
-                                _cleanup_free_ char *dd = unit_name_from_path(uu, ".device");
-                                if (dd == NULL)
+                                _cleanup_free_ char *dd;
+
+                                dd = unit_name_from_path(uu, ".device");
+                                if (!dd)
                                         return log_oom();
 
                                 fprintf(f, "After=%1$s\nRequires=%1$s\n", dd);
@@ -184,14 +189,12 @@ static int create_disk(
                         name);
 
         fflush(f);
-
         if (ferror(f)) {
                 log_error("Failed to write file %s: %m", p);
                 return -errno;
         }
 
-        if (asprintf(&from, "../%s", n) < 0)
-                return log_oom();
+        from = strappenda("../", n);
 
         if (!noauto) {
 
@@ -220,10 +223,6 @@ static int create_disk(
                 }
         }
 
-        e = unit_name_escape(name);
-        if (!e)
-                return log_oom();
-
         free(to);
         to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
         if (!to)
@@ -236,20 +235,21 @@ static int create_disk(
         }
 
         if (!noauto && !nofail) {
-                int r;
+
                 free(p);
                 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
                 if (!p)
                         return log_oom();
 
                 mkdir_parents_label(p, 0755);
-
                 r = write_string_file(p,
                                 "# Automatically generated by systemd-cryptsetup-generator\n\n"
                                 "[Unit]\n"
                                 "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
-                if (r)
+                if (r < 0) {
+                        log_error("Failed to write device drop-in: %s", strerror(-r));
                         return r;
+                }
         }
 
         return 0;
@@ -509,13 +509,9 @@ next:
                                 k = sscanf(s, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
                                 if (k == 2) {
                                         if (streq(proc_uuid, device + 5)) {
-                                                if (options)
-                                                        free(options);
-                                                options = strdup(proc_options);
-                                                if (!options) {
-                                                        log_oom();
-                                                        goto cleanup;
-                                                }
+                                                free(options);
+                                                options = proc_options;
+                                                proc_options = NULL;
                                         }
                                 } else if (!options) {
                                         /*

commit bd44e61b0480712ec5585ff7b0295362a5f9dd36
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 02:19:42 2014 +0100

    core: correctly unregister PIDs from PID hashtables

diff --git a/src/core/unit.c b/src/core/unit.c
index 2437ee3..85250ca 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1704,11 +1704,11 @@ int unit_watch_pid(Unit *u, pid_t pid) {
         /* Watch a specific PID. We only support one or two units
          * watching each PID for now, not more. */
 
-        r = hashmap_ensure_allocated(&u->manager->watch_pids1, trivial_hash_func, trivial_compare_func);
+        r = set_ensure_allocated(&u->pids, trivial_hash_func, trivial_compare_func);
         if (r < 0)
                 return r;
 
-        r = set_ensure_allocated(&u->pids, trivial_hash_func, trivial_compare_func);
+        r = hashmap_ensure_allocated(&u->manager->watch_pids1, trivial_hash_func, trivial_compare_func);
         if (r < 0)
                 return r;
 
@@ -1737,7 +1737,17 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
         set_remove(u->pids, LONG_TO_PTR(pid));
 }
 
-static int watch_pids_in_path(Unit *u, const char *path) {
+void unit_unwatch_all_pids(Unit *u) {
+        assert(u);
+
+        while (!set_isempty(u->pids))
+                unit_unwatch_pid(u, PTR_TO_LONG(set_first(u->pids)));
+
+        set_free(u->pids);
+        u->pids = NULL;
+}
+
+static int unit_watch_pids_in_path(Unit *u, const char *path) {
         _cleanup_closedir_ DIR *d = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int ret = 0, r;
@@ -1775,7 +1785,7 @@ static int watch_pids_in_path(Unit *u, const char *path) {
                         if (!p)
                                 return -ENOMEM;
 
-                        r = watch_pids_in_path(u, p);
+                        r = unit_watch_pids_in_path(u, p);
                         if (r < 0 && ret >= 0)
                                 ret = r;
                 }
@@ -1788,31 +1798,15 @@ static int watch_pids_in_path(Unit *u, const char *path) {
         return ret;
 }
 
-
 int unit_watch_all_pids(Unit *u) {
         assert(u);
 
-        if (!u->cgroup_path)
-                return -ENOENT;
-
         /* Adds all PIDs from our cgroup to the set of PIDs we watch */
 
-        return watch_pids_in_path(u, u->cgroup_path);
-}
-
-void unit_unwatch_all_pids(Unit *u) {
-        Iterator i;
-        void *e;
-
-        assert(u);
-
-        SET_FOREACH(e, u->pids, i) {
-                hashmap_remove_value(u->manager->watch_pids1, e, u);
-                hashmap_remove_value(u->manager->watch_pids2, e, u);
-        }
+        if (!u->cgroup_path)
+                return -ENOENT;
 
-        set_free(u->pids);
-        u->pids = NULL;
+        return unit_watch_pids_in_path(u, u->cgroup_path);
 }
 
 void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
@@ -1830,7 +1824,7 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
                         continue;
 
                 if (!pid_is_unwaited(pid))
-                        set_remove(u->pids, e);
+                        unit_unwatch_pid(u, pid);
         }
 }
 

commit aa62a8936f5983770e90b791083d55107659f7a1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 6 02:19:06 2014 +0100

    util: add timeout to generator execution

diff --git a/src/core/manager.c b/src/core/manager.c
index e4d0368..27a1cc6 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2657,7 +2657,7 @@ void manager_run_generators(Manager *m) {
         argv[4] = NULL;
 
         RUN_WITH_UMASK(0022)
-                execute_directory(generator_path, d, (char**) argv);
+                execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv);
 
 finish:
         trim_generator_dir(m, &m->generator_unit_path);
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index c751030..7ef671a 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -368,7 +368,7 @@ int main(int argc, char *argv[]) {
         arguments[0] = NULL;
         arguments[1] = arg_verb;
         arguments[2] = NULL;
-        execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
+        execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
 
         if (!in_container && !in_initrd() &&
             access("/run/initramfs/shutdown", X_OK) == 0) {
diff --git a/src/shared/util.c b/src/shared/util.c
index 8c7cfbd..588b1f5 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -3684,111 +3684,123 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
         return endswith(de->d_name, suffix);
 }
 
-void execute_directory(const char *directory, DIR *d, char *argv[]) {
-        DIR *_d = NULL;
-        struct dirent *de;
-        Hashmap *pids = NULL;
+void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) {
+        pid_t executor_pid;
+        int r;
 
         assert(directory);
 
-        /* Executes all binaries in a directory in parallel and
-         * waits for them to finish. */
+        /* Executes all binaries in a directory in parallel and waits
+         * for them to finish. Optionally a timeout is applied. */
 
-        if (!d) {
-                if (!(_d = opendir(directory))) {
+        executor_pid = fork();
+        if (executor_pid < 0) {
+                log_error("Failed to fork: %m");
+                return;
 
-                        if (errno == ENOENT)
-                                return;
+        } else if (executor_pid == 0) {
+                _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
+                _cleanup_closedir_ DIR *_d = NULL;
+                struct dirent *de;
+                sigset_t ss;
 
-                        log_error("Failed to enumerate directory %s: %m", directory);
-                        return;
-                }
+                /* We fork this all off from a child process so that
+                 * we can somewhat cleanly make use of SIGALRM to set
+                 * a time limit */
 
-                d = _d;
-        }
+                reset_all_signal_handlers();
 
-        if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
-                log_error("Failed to allocate set.");
-                goto finish;
-        }
+                assert_se(sigemptyset(&ss) == 0);
+                assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0);
 
-        while ((de = readdir(d))) {
-                char *path;
-                pid_t pid;
-                int k;
+                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
 
-                if (!dirent_is_file(de))
-                        continue;
+                if (!d) {
+                        d = _d = opendir(directory);
+                        if (!d) {
+                                if (errno == ENOENT)
+                                        _exit(EXIT_SUCCESS);
 
-                if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
-                        log_oom();
-                        continue;
+                                log_error("Failed to enumerate directory %s: %m", directory);
+                                _exit(EXIT_FAILURE);
+                        }
                 }
 
-                if ((pid = fork()) < 0) {
-                        log_error("Failed to fork: %m");
-                        free(path);
-                        continue;
+                pids = hashmap_new(NULL, NULL);
+                if (!pids) {
+                        log_oom();
+                        _exit(EXIT_FAILURE);
                 }
 
-                if (pid == 0) {
-                        char *_argv[2];
-                        /* Child */
+                FOREACH_DIRENT(de, d, break) {
+                        _cleanup_free_ char *path = NULL;
+                        pid_t pid;
 
-                        if (!argv) {
-                                _argv[0] = path;
-                                _argv[1] = NULL;
-                                argv = _argv;
-                        } else
-                                argv[0] = path;
+                        if (!dirent_is_file(de))
+                                continue;
 
-                        execv(path, argv);
+                        if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
+                                log_oom();
+                                _exit(EXIT_FAILURE);
+                        }
 
-                        log_error("Failed to execute %s: %m", path);
-                        _exit(EXIT_FAILURE);
-                }
+                        pid = fork();
+                        if (pid < 0) {
+                                log_error("Failed to fork: %m");
+                                continue;
+                        } else if (pid == 0) {
+                                char *_argv[2];
 
-                log_debug("Spawned %s as %lu", path, (unsigned long) pid);
+                                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
 
-                if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
-                        log_error("Failed to add PID to set: %s", strerror(-k));
-                        free(path);
-                }
-        }
+                                if (!argv) {
+                                        _argv[0] = path;
+                                        _argv[1] = NULL;
+                                        argv = _argv;
+                                } else
+                                        argv[0] = path;
 
-        while (!hashmap_isempty(pids)) {
-                pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
-                siginfo_t si = {};
-                char *path;
+                                execv(path, argv);
+                                log_error("Failed to execute %s: %m", path);
+                                _exit(EXIT_FAILURE);
+                        }
 
-                if (waitid(P_PID, pid, &si, WEXITED) < 0) {
 
-                        if (errno == EINTR)
-                                continue;
+                        log_debug("Spawned %s as " PID_FMT ".", path, pid);
 
-                        log_error("waitid() failed: %m");
-                        goto finish;
+                        r = hashmap_put(pids, UINT_TO_PTR(pid), path);
+                        if (r < 0) {
+                                log_oom();
+                                _exit(EXIT_FAILURE);
+                        }
+
+                        path = NULL;
                 }
 
-                if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
-                        if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
-                                if (si.si_code == CLD_EXITED)
-                                        log_error("%s exited with exit status %i.", path, si.si_status);
-                                else
-                                        log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
-                        } else
-                                log_debug("%s exited successfully.", path);
+                /* Abort execution of this process after the
+                 * timout. We simply rely on SIGALRM as default action
+                 * terminating the process, and turn on alarm(). */
+
+                if (timeout != (usec_t) -1)
+                        alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
+
+                while (!hashmap_isempty(pids)) {
+                        _cleanup_free_ char *path = NULL;
+                        pid_t pid;
+
+                        pid = PTR_TO_UINT(hashmap_first_key(pids));
+                        assert(pid > 0);
 
-                        free(path);
+                        path = hashmap_remove(pids, UINT_TO_PTR(pid));
+                        assert(path);
+
+                        wait_for_terminate_and_warn(path, pid);
                 }
-        }
 
-finish:
-        if (_d)
-                closedir(_d);
+                _exit(EXIT_SUCCESS);
+        }
 
-        if (pids)
-                hashmap_free_free(pids);
+        wait_for_terminate_and_warn(directory, executor_pid);
 }
 
 int kill_and_sigcont(pid_t pid, int sig) {
diff --git a/src/shared/util.h b/src/shared/util.h
index e430071..51b1caf 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -481,7 +481,7 @@ bool tty_is_console(const char *tty) _pure_;
 int vtnr_from_tty(const char *tty);
 const char *default_term_for_tty(const char *tty);
 
-void execute_directory(const char *directory, DIR *_d, char *argv[]);
+void execute_directory(const char *directory, DIR *_d, usec_t timeout, char *argv[]);
 
 int kill_and_sigcont(pid_t pid, int sig);
 
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 8da050c..94bcb29 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -25,14 +25,15 @@
 #include <string.h>
 #include <getopt.h>
 
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 #include "log.h"
 #include "util.h"
 #include "strv.h"
 #include "fileio.h"
 #include "build.h"
 #include "sleep-config.h"
+#include "def.h"
 
 static char* arg_verb = NULL;
 
@@ -41,9 +42,12 @@ static int write_mode(char **modes) {
         char **mode;
 
         STRV_FOREACH(mode, modes) {
-                int k = write_string_file("/sys/power/disk", *mode);
+                int k;
+
+                k = write_string_file("/sys/power/disk", *mode);
                 if (k == 0)
                         return 0;
+
                 log_debug("Failed to write '%s' to /sys/power/disk: %s",
                           *mode, strerror(-k));
                 if (r == 0)
@@ -106,7 +110,7 @@ static int execute(char **modes, char **states) {
         arguments[1] = (char*) "pre";
         arguments[2] = arg_verb;
         arguments[3] = NULL;
-        execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
+        execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
 
         log_struct(LOG_INFO,
                    MESSAGE_ID(SD_MESSAGE_SLEEP_START),
@@ -125,7 +129,7 @@ static int execute(char **modes, char **states) {
                    NULL);
 
         arguments[1] = (char*) "post";
-        execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
+        execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
 
         return r;
 }

commit 6a3f892a23db71544d0439355f96c44350dafa8f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Mar 5 22:31:03 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index dbfe48e..5630c1c 100644
--- a/TODO
+++ b/TODO
@@ -27,6 +27,13 @@ External:
 
 Features:
 
+* gpt-auto-generator:
+  - Properly handle cryptsetup partitions
+  - Define new partition type for encrypted swap
+  - Make /home automount rather than mount?
+  - don't use blkid on every single partition, but on the main disk only
+  - automatically find root disk in initrd
+
 * improve journalctl performance by loading journal files
   lazily. Encode just enough information in the file name, so that we
   don't have to open it to know that it is not interesting for us, for
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index f34cd03..6267d9d 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -43,14 +43,6 @@
 #include "generator.h"
 #include "gpt.h"
 
-/* TODO:
- *
- * - Properly handle cryptsetup partitions
- * - Define new partition type for encrypted swap
- * - Make /home automount rather than mount
- *
- */
-
 static const char *arg_dest = "/tmp";
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);

commit e48fdd84432bbf9c2ecc339183258c7c33116032
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Mar 5 22:26:10 2014 +0100

    generators: rework mount generators
    
    - Add support for finding and mounting /srv based on GPT data, similar
      to how we already handly /home.
    
    - Share the fsck logic between GPT, EFI and fstab generators
    
    - Make sure we never run the EFI generator inside containers
    
    - Drop DefaultDependencies=no from EFI mount units
    
    - Other fixes

diff --git a/Makefile.am b/Makefile.am
index f99cef7..6cc8316 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -792,7 +792,10 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/condition-util.c \
 	src/shared/condition-util.h \
 	src/shared/bus-label.c \
-	src/shared/bus-label.h
+	src/shared/bus-label.h \
+	src/shared/gpt.h \
+	src/shared/generator.h \
+	src/shared/generator.c
 
 nodist_libsystemd_shared_la_SOURCES = \
 	src/shared/errno-from-name.h \
diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c
index 606d35b..270dc22 100644
--- a/src/efi-boot-generator/efi-boot-generator.c
+++ b/src/efi-boot-generator/efi-boot-generator.c
@@ -27,15 +27,18 @@
 #include "util.h"
 #include "mkdir.h"
 #include "unit-name.h"
+#include "virt.h"
+#include "generator.h"
+#include "special.h"
 
 static const char *arg_dest = "/tmp";
 
 int main(int argc, char *argv[]) {
+        _cleanup_free_ char *what = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
         int r = EXIT_SUCCESS;
         sd_id128_t id;
-        _cleanup_free_ char *what = NULL, *fsck = NULL;
         char *name;
-        _cleanup_fclose_ FILE *f = NULL, *f2 = NULL;
 
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
@@ -51,16 +54,30 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (!is_efi_boot())
+        if (in_initrd()) {
+                log_debug("In initrd, exiting.");
                 return EXIT_SUCCESS;
+        }
+        if (detect_container(NULL) > 0) {
+                log_debug("In a container, exiting.");
+                return EXIT_SUCCESS;
+        }
 
-        if (dir_is_empty("/boot") <= 0)
+        if (!is_efi_boot()) {
+                log_debug("Not an EFI boot, exiting.");
                 return EXIT_SUCCESS;
+        }
+
+        if (dir_is_empty("/boot") <= 0) {
+                log_debug("/boot already populated, exiting.");
+                return EXIT_SUCCESS;
+        }
 
         r = efi_loader_get_device_part_uuid(&id);
-        if (r == -ENOENT)
+        if (r == -ENOENT) {
+                log_debug("EFI loader partition unknown exiting.");
                 return EXIT_SUCCESS;
-        if (r < 0) {
+        } else if (r < 0) {
                 log_error("Failed to read ESP partition UUID: %s", strerror(-r));
                 return EXIT_FAILURE;
         }
@@ -80,28 +97,34 @@ int main(int argc, char *argv[]) {
                 return EXIT_FAILURE;
         }
 
-        fsck = unit_name_from_path_instance("systemd-fsck", what, ".service");
-        if (!fsck) {
-                log_oom();
-                return EXIT_FAILURE;
-        }
-
         fprintf(f,
                 "# Automatially generated by systemd-efi-boot-generator\n\n"
                 "[Unit]\n"
-                "Description=EFI System Partition\n"
-                "Requires=%s\n"
-                "After=%s\n"
+                "Description=EFI System Partition\n");
+
+        r = generator_write_fsck_deps(f, arg_dest, what, "/boot", "vfat");
+        if (r < 0)
+                return EXIT_FAILURE;
+
+        fprintf(f,
                 "\n"
                 "[Mount]\n"
-                "Where=/boot\n"
                 "What=%s\n"
+                "Where=/boot\n"
+                "Type=vfat\n"
                 "Options=umask=0077,noauto\n",
-                fsck, fsck, what);
+                what);
+
+        fflush(f);
+        if (ferror(f)) {
+                log_error("Failed to write mount unit file: %m");
+                return EXIT_FAILURE;
+        }
 
         name = strappenda(arg_dest, "/boot.automount");
-        f2 = fopen(name, "wxe");
-        if (!f2) {
+        fclose(f);
+        f = fopen(name, "wxe");
+        if (!f) {
                 log_error("Failed to create automount unit file %s: %m", name);
                 return EXIT_FAILURE;
         }
@@ -110,9 +133,15 @@ int main(int argc, char *argv[]) {
               "[Unit]\n"
               "Description=EFI System Partition Automount\n\n"
               "[Automount]\n"
-              "Where=/boot\n", f2);
+              "Where=/boot\n", f);
+
+        fflush(f);
+        if (ferror(f)) {
+                log_error("Failed to write automount unit file: %m");
+                return EXIT_FAILURE;
+        }
 
-        name = strappenda(arg_dest, "/local-fs.target.wants/boot.automount");
+        name = strappenda(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/boot.automount");
         mkdir_parents(name, 0755);
 
         if (symlink("../boot.automount", name) < 0) {
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 5521a86..aac1a43 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -33,9 +33,10 @@
 #include "special.h"
 #include "mkdir.h"
 #include "fileio.h"
+#include "generator.h"
 
 static const char *arg_dest = "/tmp";
-static bool arg_enabled = true;
+static bool arg_fstab_enabled = true;
 
 static int mount_find_pri(struct mntent *me, int *ret) {
         char *end, *pri;
@@ -146,57 +147,6 @@ static bool mount_in_initrd(struct mntent *me) {
                 streq(me->mnt_dir, "/usr");
 }
 
-static int add_fsck(FILE *f, const char *what, const char *where, const char *type, int passno) {
-        assert(f);
-
-        if (passno == 0)
-                return 0;
-
-        if (!is_device_path(what)) {
-                log_warning("Checking was requested for \"%s\", but it is not a device.", what);
-                return 0;
-        }
-
-        if (type && !streq(type, "auto")) {
-                int r;
-                const char *checker;
-
-                checker = strappenda("/sbin/fsck.", type);
-                r = access(checker, X_OK);
-                if (r < 0) {
-                        log_warning("Checking was requested for %s, but %s cannot be used: %m", what, checker);
-
-                        /* treat missing check as essentially OK */
-                        return errno == ENOENT ? 0 : -errno;
-                }
-        }
-
-        if (streq(where, "/")) {
-                char *lnk;
-
-                lnk = strappenda(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service");
-                mkdir_parents_label(lnk, 0755);
-                if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0) {
-                        log_error("Failed to create symlink %s: %m", lnk);
-                        return -errno;
-                }
-        } else {
-                _cleanup_free_ char *fsck = NULL;
-
-                fsck = unit_name_from_path_instance("systemd-fsck", what, ".service");
-                if (!fsck)
-                        return log_oom();
-
-                fprintf(f,
-                        "RequiresOverridable=%s\n"
-                        "After=%s\n",
-                        fsck,
-                        fsck);
-        }
-
-        return 0;
-}
-
 static int add_mount(
                 const char *what,
                 const char *where,
@@ -208,6 +158,7 @@ static int add_mount(
                 bool automount,
                 const char *post,
                 const char *source) {
+
         _cleanup_free_ char
                 *name = NULL, *unit = NULL, *lnk = NULL,
                 *automount_name = NULL, *automount_unit = NULL;
@@ -232,6 +183,12 @@ static int add_mount(
             mount_point_ignore(where))
                 return 0;
 
+        if (path_equal(where, "/")) {
+                automount = false;
+                noauto = false;
+                nofail = false;
+        }
+
         name = unit_name_from_path(where, ".mount");
         if (!name)
                 return log_oom();
@@ -260,9 +217,11 @@ static int add_mount(
                         "Before=%s\n",
                         post);
 
-        r = add_fsck(f, what, where, type, passno);
-        if (r < 0)
-                return r;
+        if (passno != 0) {
+                r = generator_write_fsck_deps(f, arg_dest, what, where, type);
+                if (r < 0)
+                        return r;
+        }
 
         fprintf(f,
                 "\n"
@@ -274,8 +233,7 @@ static int add_mount(
                 where,
                 type);
 
-        if (!isempty(opts) &&
-            !streq(opts, "defaults"))
+        if (!isempty(opts) && !streq(opts, "defaults"))
                 fprintf(f,
                         "Options=%s\n",
                         opts);
@@ -300,7 +258,7 @@ static int add_mount(
                 }
         }
 
-        if (automount && !path_equal(where, "/")) {
+        if (automount) {
                 automount_name = unit_name_from_path(where, ".automount");
                 if (!automount_name)
                         return log_oom();
@@ -324,7 +282,7 @@ static int add_mount(
 
                 if (post)
                         fprintf(f,
-                                "Before= %s\n",
+                                "Before=%s\n",
                                 post);
 
                 fprintf(f,
@@ -353,19 +311,19 @@ static int add_mount(
         return 0;
 }
 
-static int parse_fstab(const char *prefix, bool initrd) {
-        char *fstab_path;
+static int parse_fstab(bool initrd) {
         _cleanup_endmntent_ FILE *f;
-        int r = 0;
+        const char *fstab_path;
         struct mntent *me;
+        int r = 0;
 
-        fstab_path = strappenda(strempty(prefix), "/etc/fstab");
-        f = setmntent(fstab_path, "r");
+        fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab";
+        f = setmntent(fstab_path, "re");
         if (!f) {
                 if (errno == ENOENT)
                         return 0;
 
-                log_error("Failed to open %s/etc/fstab: %m", strempty(prefix));
+                log_error("Failed to open %s: %m", fstab_path);
                 return -errno;
         }
 
@@ -377,8 +335,11 @@ static int parse_fstab(const char *prefix, bool initrd) {
                         continue;
 
                 what = fstab_node_to_udev_node(me->mnt_fsname);
-                where = strjoin(strempty(prefix), me->mnt_dir, NULL);
-                if (!what || !where)
+                if (!what)
+                        return log_oom();
+
+                where = initrd ? strappend("/sysroot/", me->mnt_dir) : strdup(me->mnt_dir);
+                if (!where)
                         return log_oom();
 
                 if (is_path(where))
@@ -398,15 +359,14 @@ static int parse_fstab(const char *prefix, bool initrd) {
                                   hasmntopt(me, "comment=systemd.automount") ||
                                   hasmntopt(me, "x-systemd.automount");
 
-                        if (initrd) {
+                        if (initrd)
                                 post = SPECIAL_INITRD_FS_TARGET;
-                        } else if (mount_in_initrd(me)) {
+                        else if (mount_in_initrd(me))
                                 post = SPECIAL_INITRD_ROOT_FS_TARGET;
-                        } else if (mount_is_network(me)) {
+                        else if (mount_is_network(me))
                                 post = SPECIAL_REMOTE_FS_TARGET;
-                        } else {
+                        else
                                 post = SPECIAL_LOCAL_FS_TARGET;
-                        }
 
                         k = add_mount(what, where, me->mnt_type, me->mnt_opts,
                                       me->mnt_passno, noauto, nofail, automount,
@@ -505,11 +465,12 @@ static int parse_proc_cmdline_word(const char *word) {
         int r;
 
         if (startswith(word, "fstab=")) {
+
                 r = parse_boolean(word + 6);
                 if (r < 0)
                         log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6);
                 else
-                        arg_enabled = r;
+                        arg_fstab_enabled = r;
 
         } else if (startswith(word, "rd.fstab=")) {
 
@@ -518,7 +479,7 @@ static int parse_proc_cmdline_word(const char *word) {
                         if (r < 0)
                                 log_warning("Failed to parse fstab switch %s. Ignoring.", word + 9);
                         else
-                                arg_enabled = r;
+                                arg_fstab_enabled = r;
                 }
 
         } else if (startswith(word, "fstab.") ||
@@ -531,7 +492,7 @@ static int parse_proc_cmdline_word(const char *word) {
 }
 
 int main(int argc, char *argv[]) {
-        int r = 0, k, l = 0;
+        int r = 0;
 
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
@@ -550,16 +511,26 @@ int main(int argc, char *argv[]) {
         if (parse_proc_cmdline(parse_proc_cmdline_word) < 0)
                 return EXIT_FAILURE;
 
+        /* Always honour root= in the kernel command line if we are in an initrd */
         if (in_initrd())
                 r = parse_new_root_from_proc_cmdline();
 
-        if (!arg_enabled)
-                return (r < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+        /* Honour /etc/fstab only when that's enabled */
+        if (arg_fstab_enabled) {
+                int k;
 
-        k = parse_fstab(NULL, false);
+                /* Parse the local /etc/fstab, possibly from the initrd */
+                k = parse_fstab(false);
+                if (k < 0)
+                        r = k;
 
-        if (in_initrd())
-                l = parse_fstab("/sysroot", true);
+                /* If running in the initrd also parse the /etc/fstab from the host */
+                if (in_initrd()) {
+                        k = parse_fstab(true);
+                        if (k < 0)
+                                r = k;
+                }
+        }
 
-        return (r < 0) || (k < 0) || (l < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 05934da..f34cd03 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -40,6 +40,8 @@
 #include "special.h"
 #include "unit-name.h"
 #include "virt.h"
+#include "generator.h"
+#include "gpt.h"
 
 /* TODO:
  *
@@ -49,9 +51,6 @@
  *
  */
 
-#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)
-#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15)
-
 static const char *arg_dest = "/tmp";
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
@@ -152,10 +151,6 @@ static int add_swap(const char *path, const char *fstype) {
 
         fprintf(f,
                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
-                "[Unit]\n"
-                "DefaultDependencies=no\n"
-                "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
-                "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_SWAP_TARGET "\n\n"
                 "[Swap]\n"
                 "What=%s\n",
                 path);
@@ -179,42 +174,49 @@ static int add_swap(const char *path, const char *fstype) {
         return 0;
 }
 
-static int add_home(const char *path, const char *fstype) {
-        _cleanup_free_ char *unit = NULL, *lnk = NULL, *fsck = NULL;
+static int add_mount(const char *what, const char *where, const char *fstype, const char *description) {
+        _cleanup_free_ char *unit = NULL, *lnk = NULL, *p = NULL;
         _cleanup_fclose_ FILE *f = NULL;
+        int r;
 
-        if (dir_is_empty("/home") <= 0)
+        if (dir_is_empty(where) <= 0) {
+                log_debug("%s already populated, ignoring.", where);
                 return 0;
+        }
 
-        log_debug("Adding home: %s %s", path, fstype);
+        log_debug("Adding %s: %s %s", where, what, fstype);
 
-        unit = strappend(arg_dest, "/home.mount");
+        unit = unit_name_from_path(where, ".mount");
         if (!unit)
                 return log_oom();
 
-        f = fopen(unit, "wxe");
+        p = strjoin(arg_dest, "/", unit, NULL);
+        if (!p)
+                return log_oom();
+
+        f = fopen(p, "wxe");
         if (!f) {
                 log_error("Failed to create unit file %s: %m", unit);
                 return -errno;
         }
 
-        fsck = unit_name_from_path_instance("systemd-fsck", path, ".service");
-        if (!fsck)
-                return log_oom();
-
         fprintf(f,
                 "# Automatically generated by systemd-gpt-auto-generator\n\n"
                 "[Unit]\n"
-                "DefaultDependencies=no\n"
-                "Requires=%s\n"
-                "After=" SPECIAL_LOCAL_FS_PRE_TARGET " %s\n"
-                "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
-                "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_LOCAL_FS_TARGET "\n\n"
+                "Description=%s\n",
+                description);
+
+        r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
+        if (r < 0)
+                return r;
+
+        fprintf(f,
+                "\n"
                 "[Mount]\n"
                 "What=%s\n"
-                "Where=/home\n"
+                "Where=%s\n"
                 "Type=%s\n",
-                fsck, fsck, path, fstype);
+                what, where, fstype);
 
         fflush(f);
         if (ferror(f)) {
@@ -222,7 +224,7 @@ static int add_home(const char *path, const char *fstype) {
                 return -errno;
         }
 
-        lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/home.mount", NULL);
+        lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/", unit, NULL);
         if (!lnk)
                 return log_oom();
 
@@ -236,12 +238,12 @@ static int add_home(const char *path, const char *fstype) {
 }
 
 static int enumerate_partitions(struct udev *udev, dev_t dev) {
-        struct udev_device *parent = NULL;
         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+        _cleanup_free_ char *home = NULL, *home_fstype = NULL, *srv = NULL, *srv_fstype = NULL;
+        unsigned home_nr = (unsigned) -1, srv_nr = (unsigned )-1;
         struct udev_list_entry *first, *item;
-        unsigned home_nr = (unsigned) -1;
-        _cleanup_free_ char *home = NULL, *home_fstype = NULL;
+        struct udev_device *parent = NULL;
         int r;
 
         e = udev_enumerate_new(udev);
@@ -266,16 +268,15 @@ static int enumerate_partitions(struct udev *udev, dev_t dev) {
 
         r = udev_enumerate_scan_devices(e);
         if (r < 0) {
-                log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s",
-                          major(dev), minor(dev), strerror(-r));
+                log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s", major(dev), minor(dev), strerror(-r));
                 return r;
         }
 
         first = udev_enumerate_get_list_entry(e);
         udev_list_entry_foreach(item, first) {
+                _cleanup_udev_device_unref_ struct udev_device *q;
                 _cleanup_free_ char *fstype = NULL;
                 const char *node = NULL;
-                _cleanup_udev_device_unref_ struct udev_device *q;
                 sd_id128_t type_id;
                 unsigned nr;
 
@@ -298,8 +299,7 @@ static int enumerate_partitions(struct udev *udev, dev_t dev) {
                         /* skip child devices which are not detected properly */
                         if (r == -EBADSLT)
                                 continue;
-                        log_error("Failed to verify GPT partition %s: %s",
-                                  node, strerror(-r));
+                        log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
                         return r;
                 }
                 if (r == 0)
@@ -307,24 +307,48 @@ static int enumerate_partitions(struct udev *udev, dev_t dev) {
 
                 if (sd_id128_equal(type_id, GPT_SWAP))
                         add_swap(node, fstype);
+
                 else if (sd_id128_equal(type_id, GPT_HOME)) {
-                        if (!home || nr < home_nr) {
-                                free(home);
-                                home = strdup(node);
-                                if (!home)
-                                        return log_oom();
-
-                                home_nr = nr;
-
-                                free(home_fstype);
-                                home_fstype = fstype;
-                                fstype = NULL;
-                        }
+
+                        /* We only care for the first /home partition */
+                        if (home && nr >= home_nr)
+                                continue;
+
+                        home_nr = nr;
+
+                        free(home);
+                        home = strdup(node);
+                        if (!home)
+                                return log_oom();
+
+                        free(home_fstype);
+                        home_fstype = fstype;
+                        fstype = NULL;
+
+                } else if (sd_id128_equal(type_id, GPT_SRV)) {
+
+                        /* We only care for the first /srv partition */
+                        if (srv && nr >= srv_nr)
+                                continue;
+
+                        srv_nr = nr;
+
+                        free(srv);
+                        srv = strdup(node);
+                        if (!srv)
+                                return log_oom();
+
+                        free(srv_fstype);
+                        srv_fstype = fstype;
+                        fstype = NULL;
                 }
         }
 
         if (home && home_fstype)
-                add_home(home, home_fstype);
+                add_mount(home, "/home", home_fstype, "Home Partition");
+
+        if (srv && srv_fstype)
+                add_mount(srv, "/srv", srv_fstype, "Server Data Partition");
 
         return r;
 }
@@ -384,7 +408,7 @@ static int get_block_device(const char *path, dev_t *dev) {
         assert(path);
         assert(dev);
 
-        if (lstat("/", &st))
+        if (lstat(path, &st))
                 return -errno;
 
         if (major(st.st_dev) != 0) {
@@ -392,7 +416,7 @@ static int get_block_device(const char *path, dev_t *dev) {
                 return 1;
         }
 
-        if (statfs("/", &sfs) < 0)
+        if (statfs(path, &sfs) < 0)
                 return -errno;
 
         if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
@@ -423,15 +447,14 @@ static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_free_ char *node = NULL;
         _cleanup_udev_unref_ struct udev *udev = NULL;
+        _cleanup_free_ char *node = NULL;
         dev_t devno;
         int r = 0;
 
         if (argc > 1 && argc != 4) {
                 log_error("This program takes three or no arguments.");
-                r = -EINVAL;
-                goto finish;
+                return EXIT_FAILURE;
         }
 
         if (argc > 1)
@@ -445,34 +468,33 @@ int main(int argc, char *argv[]) {
 
         if (in_initrd()) {
                 log_debug("In initrd, exiting.");
-                goto finish;
+                return EXIT_SUCCESS;
         }
 
         if (detect_container(NULL) > 0) {
                 log_debug("In a container, exiting.");
-                goto finish;
+                return EXIT_SUCCESS;
         }
 
         r = get_block_device("/", &devno);
         if (r < 0) {
                 log_error("Failed to determine block device of root file system: %s", strerror(-r));
-                goto finish;
-        }
-        if (r == 0) {
+                return EXIT_FAILURE;
+        } else if (r == 0) {
                 log_debug("Root file system not on a (single) block device.");
-                goto finish;
+                return EXIT_SUCCESS;
         }
 
         udev = udev_new();
         if (!udev) {
-                r = log_oom();
-                goto finish;
+                log_oom();
+                return EXIT_FAILURE;
         }
 
         r = devno_to_devnode(udev, devno, &node);
         if (r < 0) {
                 log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
-                goto finish;
+                return EXIT_FAILURE;
         }
 
         log_debug("Root device %s.", node);
@@ -480,13 +502,16 @@ int main(int argc, char *argv[]) {
         r = verify_gpt_partition(node, NULL, NULL, NULL);
         if (r < 0) {
                 log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
-                goto finish;
+                return EXIT_FAILURE;
+        }
+        if (r == 0) {
+                log_debug("Not a GPT disk, exiting.");
+                return EXIT_SUCCESS;
         }
-        if (r == 0)
-                goto finish;
 
         r = enumerate_partitions(udev, devno);
+        if (r < 0)
+                return EXIT_FAILURE;
 
-finish:
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return EXIT_SUCCESS;
 }
diff --git a/src/shared/generator.c b/src/shared/generator.c
new file mode 100644
index 0000000..49647c1
--- /dev/null
+++ b/src/shared/generator.c
@@ -0,0 +1,84 @@
+/*-*- 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 <unistd.h>
+
+#include "util.h"
+#include "special.h"
+#include "mkdir.h"
+#include "unit-name.h"
+#include "generator.h"
+
+int generator_write_fsck_deps(
+                FILE *f,
+                const char *dest,
+                const char *what,
+                const char *where,
+                const char *type) {
+
+        assert(f);
+
+        if (!is_device_path(what)) {
+                log_warning("Checking was requested for \"%s\", but it is not a device.", what);
+                return 0;
+        }
+
+        if (type && !streq(type, "auto")) {
+                const char *checker;
+                int r;
+
+                checker = strappenda("/sbin/fsck.", type);
+                r = access(checker, X_OK);
+                if (r < 0) {
+                        log_warning("Checking was requested for %s, but %s cannot be used: %m", what, checker);
+
+                        /* treat missing check as essentially OK */
+                        return errno == ENOENT ? 0 : -errno;
+                }
+        }
+
+        if (streq(where, "/")) {
+                char *lnk;
+
+                lnk = strappenda(dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service");
+
+                mkdir_parents(lnk, 0755);
+                if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0) {
+                        log_error("Failed to create symlink %s: %m", lnk);
+                        return -errno;
+                }
+
+        } else {
+                _cleanup_free_ char *fsck = NULL;
+
+                fsck = unit_name_from_path_instance("systemd-fsck", what, ".service");
+                if (!fsck)
+                        return log_oom();
+
+                fprintf(f,
+                        "RequiresOverridable=%s\n"
+                        "After=%s\n",
+                        fsck,
+                        fsck);
+        }
+
+        return 0;
+}
diff --git a/src/shared/generator.h b/src/shared/generator.h
new file mode 100644
index 0000000..0140aa9
--- /dev/null
+++ b/src/shared/generator.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  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 <stdio.h>
+
+int generator_write_fsck_deps(FILE *f, const char *dest, const char *what, const char *where, const char *type);
diff --git a/src/shared/gpt.h b/src/shared/gpt.h
new file mode 100644
index 0000000..2956377
--- /dev/null
+++ b/src/shared/gpt.h
@@ -0,0 +1,28 @@
+/*-*- 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-id128.h"
+
+#define GPT_ESP  SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b)
+#define GPT_ROOT SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09)
+#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)
+#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15)
+#define GPT_SRV  SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8)



More information about the systemd-commits mailing list