[systemd-commits] 20 commits - catalog/systemd.pt_BR.catalog configure.ac Makefile.am man/tmpfiles.d.xml man/vconsole.conf.xml README src/bus-proxyd src/core src/hwdb src/journal src/journal-remote src/libsystemd src/libsystemd-network src/libudev src/locale src/login src/shared src/systemctl src/sysv-generator src/test src/tmpfiles src/udev test/test-functions tmpfiles.d/systemd.conf.m4 TODO

Zbigniew Jędrzejewski-Szmek zbyszek at kemper.freedesktop.org
Wed Jan 21 22:23:17 PST 2015


 Makefile.am                               |    5 
 README                                    |   11 
 TODO                                      |    2 
 catalog/systemd.pt_BR.catalog             |   10 
 configure.ac                              |    1 
 man/tmpfiles.d.xml                        |   76 ++-
 man/vconsole.conf.xml                     |    2 
 src/bus-proxyd/bus-xml-policy.c           |    4 
 src/core/automount.c                      |    2 
 src/core/dbus-manager.c                   |    2 
 src/core/manager.c                        |    2 
 src/hwdb/hwdb.c                           |    2 
 src/journal-remote/journal-remote-parse.c |   10 
 src/journal-remote/journal-remote.c       |    2 
 src/journal-remote/journal-upload.c       |    8 
 src/journal/compress.c                    |    8 
 src/journal/coredump.c                    |    6 
 src/journal/journal-file.c                |    4 
 src/journal/journal-send.c                |    2 
 src/journal/journalctl.c                  |    6 
 src/journal/journald-audit.c              |    2 
 src/journal/journald-server.c             |    5 
 src/libsystemd-network/sd-dhcp-client.c   |    2 
 src/libsystemd/libsystemd.sym.m4          |    3 
 src/libsystemd/sd-bus/bus-control.c       |    6 
 src/libsystemd/sd-bus/bus-dump.c          |    4 
 src/libsystemd/sd-hwdb/sd-hwdb.c          |    2 
 src/libsystemd/sd-rtnl/rtnl-message.c     |    4 
 src/libudev/libudev-device.c              |    2 
 src/libudev/libudev-monitor.c             |    6 
 src/locale/kbd-model-map                  |    4 
 src/login/logind-acl.c                    |    2 
 src/login/logind-seat.c                   |    2 
 src/login/pam_systemd.c                   |    4 
 src/login/test-inhibit.c                  |    2 
 src/shared/acl-util.c                     |  189 ++++++++-
 src/shared/acl-util.h                     |   21 -
 src/shared/cgroup-show.c                  |   50 --
 src/shared/install-printf.c               |    2 
 src/shared/log.c                          |    4 
 src/shared/sleep-config.c                 |    6 
 src/shared/util.h                         |    9 
 src/systemctl/systemctl.c                 |    4 
 src/sysv-generator/sysv-generator.c       |    6 
 src/test/test-strxcpyx.c                  |    2 
 src/test/test-util.c                      |    2 
 src/tmpfiles/tmpfiles.c                   |  589 ++++++++++++++++++------------
 src/udev/udev-builtin-blkid.c             |    2 
 src/udev/udev-builtin-input_id.c          |    2 
 src/udev/udev-builtin-keyboard.c          |   22 -
 src/udev/udev-builtin-net_id.c            |    8 
 src/udev/udev-ctrl.c                      |    4 
 src/udev/udev-event.c                     |   20 -
 src/udev/udev-node.c                      |    2 
 src/udev/udevadm-hwdb.c                   |    2 
 src/udev/udevadm-info.c                   |    6 
 src/udev/udevd.c                          |   25 -
 test/test-functions                       |    1 
 tmpfiles.d/systemd.conf.m4                |    8 
 59 files changed, 756 insertions(+), 445 deletions(-)

New commits:
commit 534644b7be7b240eb0fbbe06e20cbecbe8206767
Author: Mindaugas Baranauskas <embar at super.lt>
Date:   Thu Jan 22 01:07:24 2015 -0500

    kbd-model-map: add more mappings for Slovak, Lithuanian, and Khmer
    
    https://bugs.freedesktop.org/show_bug.cgi?id=88545

diff --git a/src/locale/kbd-model-map b/src/locale/kbd-model-map
index f39d991..8fa984f 100644
--- a/src/locale/kbd-model-map
+++ b/src/locale/kbd-model-map
@@ -52,6 +52,7 @@ ro-cedilla		ro	pc105		cedilla		terminate:ctrl_alt_bksp
 ie			ie	pc105		-		terminate:ctrl_alt_bksp
 et			ee	pc105		-		terminate:ctrl_alt_bksp
 sk-qwerty		sk	pc105		-		terminate:ctrl_alt_bksp,qwerty
+sk-qwertz		sk	pc105		-		terminate:ctrl_alt_bksp
 fr-latin9		fr	pc105		latin9		terminate:ctrl_alt_bksp
 fr_CH-latin1		ch	pc105		fr		terminate:ctrl_alt_bksp
 cf			ca	pc105		-		terminate:ctrl_alt_bksp
@@ -61,4 +62,7 @@ gr			gr,us	pc105		-		terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
 by			by,us	pc105		-		terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
 il			il	pc105		-		terminate:ctrl_alt_bksp
 kazakh			kz,us	pc105		-		terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+lt.baltic		lt	pc105		-		terminate:ctrl_alt_bksp
+lt.l4                  lt	pc105		-		terminate:ctrl_alt_bksp
 lt			lt	pc105		-		terminate:ctrl_alt_bksp
+khmer			kh,us	pc105		-		terminate:ctrl_alt_bksp

commit 25b47f96d9601ff566257b2a31bfb5f4bd25d661
Author: Marko Myllynen <myllynen at redhat.com>
Date:   Thu Jan 15 14:44:17 2015 +0200

    Use eurlatgr as the example console font
    
    See https://fedoraproject.org/wiki/Changes/NewDefaultConsoleFont
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1182529

diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml
index 09a4776..02df2e8 100644
--- a/man/vconsole.conf.xml
+++ b/man/vconsole.conf.xml
@@ -127,7 +127,7 @@
                         <para><filename>/etc/vconsole.conf</filename>:</para>
 
                         <programlisting>KEYMAP=de-latin1
-FONT=latarcyrheb-sun16</programlisting>
+FONT=eurlatgr</programlisting>
                 </example>
 
         </refsect1>
diff --git a/test/test-functions b/test/test-functions
index dac0dcc..4fa0c59 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -272,6 +272,7 @@ install_keymaps() {
 
 install_fonts() {
     for i in \
+        /usr/lib/kbd/consolefonts/eurlatgr* \
         /usr/lib/kbd/consolefonts/latarcyrheb-sun16*; do
             [[ -f $i ]] || continue
             inst $i

commit 0814f65ec6feba5efcf0f5b14c054f3c40e4cd8f
Author: Cristian Rodríguez <crrodriguez at opensuse.org>
Date:   Wed Jan 14 02:51:41 2015 -0300

    sysv-generator: only allow regular files in enumerate_sysv()
    
    Otherwise, if the directory contains other directories we fail
    at fopen in load_sysv() with EISDIR.

diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 3279c7f..b8b77aa 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -752,8 +752,10 @@ static int enumerate_sysv(LookupPaths lp, Hashmap *all_services) {
                         struct stat st;
                         int r;
 
-                        if (hidden_file(de->d_name))
-                                continue;
+                        dirent_ensure_type(d, de);
+
+                        if (!dirent_is_file(de))
+                            continue;
 
                         if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
                                 log_warning_errno(errno, "stat() failed on %s/%s: %m", *path, de->d_name);

commit 3a5afdec90a08b1eb6dfeab667783849204ee8bd
Author: Lucas De Marchi <lucas.de.marchi at gmail.com>
Date:   Wed Jan 21 22:59:45 2015 -0200

    build: export symbols to integrate mainloops

diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4
index 19a49f4..41418b9 100644
--- a/src/libsystemd/libsystemd.sym.m4
+++ b/src/libsystemd/libsystemd.sym.m4
@@ -382,6 +382,9 @@ global:
         sd_event_add_child;
         sd_event_add_defer;
         sd_event_add_exit;
+        sd_event_wait;
+        sd_event_prepare;
+        sd_event_dispatch;
         sd_event_run;
         sd_event_loop;
         sd_event_exit;

commit 614cc34f3a2a7c64a21c3f5256f2e2b2c1de1d51
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Jan 18 18:28:17 2015 -0500

    TODO: tmpfiles

diff --git a/TODO b/TODO
index 7be3c24..2c01b2c 100644
--- a/TODO
+++ b/TODO
@@ -680,6 +680,8 @@ Features:
 
 * tmpfiles:
   - apply "x" on "D" too (see patch from William Douglas)
+  - replace F with f+.
+  - instead of ignoring unknown fields, reject them.
 
 * for services: do not set $HOME in services unless requested
 

commit dd4105b0a90c3c146a01e5a7734ee76c3a9aa1cd
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Jan 18 18:22:27 2015 -0500

    shared/acl-util: add mask only when needed, always add base ACLs
    
    For ACLs to be valid, a set of entries for user, group, and other
    must be always present. Always add those entries.
    
    While at it, only add the mask ACL if it is actually required, i.e.
    when at least on ACL for non-owner group or user exists.

diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 957910d..8815bf9 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -306,16 +306,16 @@
           <term><varname>a</varname></term>
           <term><varname>a+</varname></term>
           <listitem><para>Set POSIX ACLs (access control lists). If
-          suffixed with <varname>+</varname>, specified mask will be
-          added to existing
-          entries. <command>systemd-tmpfiles</command> does not
-          automatically add the required base entries for user and
-          group to the specified mask, so they must be specified
-          explicitly if <varname>+</varname> is not used. The
-          mask will be added if not specified explicitly.
-          Lines of this type accept shell-style globs in place
-          of normal path names. This can be useful for allowing
-          additional access to certain files.  </para></listitem>
+          suffixed with <varname>+</varname>, specified entries will
+          be added to the existing set.
+          <command>systemd-tmpfiles</command> will automatically add
+          the required base entries for user and group based on the
+          access mode of the file, unless base entries already exist
+          or are explictly specified. The mask will be added if not
+          specified explicitly or already present. Lines of this type
+          accept shell-style globs in place of normal path names. This
+          can be useful for allowing additional access to certain
+          files.</para></listitem>
         </varlistentry>
 
         <varlistentry>
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 950f472..a4ff1ab 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -29,14 +29,14 @@
 
 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
         acl_entry_t i;
-        int found;
+        int r;
 
         assert(acl);
         assert(entry);
 
-        for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
-             found > 0;
-             found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
+        for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
+             r > 0;
+             r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
 
                 acl_tag_t tag;
                 uid_t *u;
@@ -60,8 +60,7 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
                         return 1;
                 }
         }
-
-        if (found < 0)
+        if (r < 0)
                 return -errno;
 
         return 0;
@@ -69,14 +68,13 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
 
 int calc_acl_mask_if_needed(acl_t *acl_p) {
         acl_entry_t i;
-        int found;
+        int r;
 
         assert(acl_p);
 
-        for (found = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
-             found > 0;
-             found = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
-
+        for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
+             r > 0;
+             r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
                 acl_tag_t tag;
 
                 if (acl_get_tag_type(i, &tag) < 0)
@@ -84,14 +82,80 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
 
                 if (tag == ACL_MASK)
                         return 0;
+                if (IN_SET(tag, ACL_USER, ACL_GROUP))
+                        goto calc;
         }
-
-        if (found < 0)
+        if (r < 0)
                 return -errno;
+        return 0;
 
+calc:
         if (acl_calc_mask(acl_p) < 0)
                 return -errno;
+        return 1;
+}
+
+int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
+        acl_entry_t i;
+        int r;
+        bool have_user_obj = false, have_group_obj = false, have_other = false;
+        struct stat st;
+        _cleanup_(acl_freep) acl_t basic = NULL;
+
+        assert(acl_p);
+
+        for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
+             r > 0;
+             r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
+                acl_tag_t tag;
+
+                if (acl_get_tag_type(i, &tag) < 0)
+                        return -errno;
+
+                if (tag == ACL_USER_OBJ)
+                        have_user_obj = true;
+                else if (tag == ACL_GROUP_OBJ)
+                        have_group_obj = true;
+                else if (tag == ACL_OTHER)
+                        have_other = true;
+                if (have_user_obj && have_group_obj && have_other)
+                        return 0;
+        }
+        if (r < 0)
+                return -errno;
 
+        r = stat(path, &st);
+        if (r < 0)
+                return -errno;
+
+        basic = acl_from_mode(st.st_mode);
+        if (!basic)
+                return -errno;
+
+        for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i);
+             r > 0;
+             r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
+                acl_tag_t tag;
+                acl_entry_t dst;
+
+                if (acl_get_tag_type(i, &tag) < 0)
+                        return -errno;
+
+                if ((tag == ACL_USER_OBJ && have_user_obj) ||
+                    (tag == ACL_GROUP_OBJ && have_group_obj) ||
+                    (tag == ACL_OTHER && have_other))
+                        continue;
+
+                r = acl_create_entry(acl_p, &dst);
+                if (r < 0)
+                        return -errno;
+
+                r = acl_copy_entry(dst, i);
+                if (r < 0)
+                        return -errno;
+        }
+        if (r < 0)
+                return -errno;
         return 0;
 }
 
@@ -221,15 +285,15 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask)
 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
         _cleanup_(acl_freep) acl_t old;
         acl_entry_t i;
-        int found, r;
+        int r;
 
         old = acl_get_file(path, type);
         if (!old)
                 return -errno;
 
-        for (found = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
-             found > 0;
-             found = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
+        for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
+             r > 0;
+             r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
 
                 acl_entry_t j;
 
@@ -239,10 +303,8 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
                 if (acl_copy_entry(j, i) < 0)
                         return -errno;
         }
-
-        r = calc_acl_mask_if_needed(&old);
         if (r < 0)
-                return r;
+                return -errno;
 
         *acl = old;
         old = NULL;
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index 1ad4a2e..90e88ff 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -31,6 +31,7 @@
 
 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
 int calc_acl_mask_if_needed(acl_t *acl_p);
+int add_base_acls_if_needed(acl_t *acl_p, const char *path);
 int search_acl_groups(char*** dst, const char* path, bool* belong);
 int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask);
 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 3c8993e..7edeeb7 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -614,22 +614,35 @@ static int get_acls_from_arg(Item *item) {
 }
 
 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
-        _cleanup_(acl_freep) acl_t cleanme = NULL;
+        _cleanup_(acl_freep) acl_t dup = NULL;
         int r;
 
         if (modify) {
-                r = acls_for_file(path, type, acl, &cleanme);
+                r = acls_for_file(path, type, acl, &dup);
                 if (r < 0)
                         return r;
-                acl = cleanme;
-        };
 
-        r = acl_set_file(path, type, acl);
+                r = calc_acl_mask_if_needed(&dup);
+                if (r < 0)
+                        return r;
+        } else {
+                dup = acl_dup(acl);
+                if (!dup)
+                        return -errno;
+
+                /* the mask was already added earlier if needed */
+        }
+
+        r = add_base_acls_if_needed(&dup, path);
+        if (r < 0)
+                return r;
+
+        r = acl_set_file(path, type, dup);
         if (r < 0) {
                 _cleanup_(acl_free_charpp) char *t;
 
                 r = -errno;
-                t = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE);
+                t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
                 log_error_errno(r,
                                 "Setting %s ACL \"%s\" on %s failed: %m",
                                 type == ACL_TYPE_ACCESS ? "access" : "default",

commit a48a62a1af02aec4473c9deed98dd5b89d210f93
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Jan 18 15:05:40 2015 -0500

    tmpfiles: use ACL magic on journal directories

diff --git a/README b/README
index fa95433..c722092 100644
--- a/README
+++ b/README
@@ -178,14 +178,9 @@ USERS AND GROUPS:
         During runtime, the journal daemon requires the
         "systemd-journal" system group to exist. New journal files will
         be readable by this group (but not writable), which may be used
-        to grant specific users read access.
-
-        It is also recommended to grant read access to all journal
-        files to the system groups "wheel" and "adm" with a command
-        like the following in the post installation script of the
-        package:
-
-        # setfacl -nm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/
+        to grant specific users read access. In addition, system
+        groups "wheel" and "adm" will be given read-only access to
+        journal files using systemd-tmpfiles.service.
 
         The journal gateway daemon requires the
         "systemd-journal-gateway" system user and group to
diff --git a/configure.ac b/configure.ac
index 18a439e..6bd095c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -666,6 +666,7 @@ if test "x${have_acl}" != xno ; then
         if test "x$have_acl" = xyes ; then
                 ACL_LIBS="-lacl"
                 AC_DEFINE(HAVE_ACL, 1, [ACL available])
+                M4_DEFINES="$M4_DEFINES -DHAVE_ACL"
         else
                 have_acl=no
         fi
diff --git a/tmpfiles.d/systemd.conf.m4 b/tmpfiles.d/systemd.conf.m4
index ad05f43..b447b01 100644
--- a/tmpfiles.d/systemd.conf.m4
+++ b/tmpfiles.d/systemd.conf.m4
@@ -26,9 +26,17 @@ d /run/log 0755 root root -
 
 z /run/log/journal 2755 root systemd-journal - -
 Z /run/log/journal/%m ~2750 root systemd-journal - -
+m4_ifdef(`HAVE_ACL',``
+a+ /run/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x
+A+ /run/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
+'')m4_dnl
 
 z /var/log/journal 2755 root systemd-journal - -
 z /var/log/journal/%m 2755 root systemd-journal - -
+m4_ifdef(`HAVE_ACL',``
+a+ /var/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x
+A+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
+'')m4_dnl
 
 d /var/lib/systemd 0755 root root -
 d /var/lib/systemd/coredump 0755 root root 3d

commit 50d9e46dbb8400d4570781728c63b151d9ca982b
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Jan 18 05:02:47 2015 -0500

    tmpfiles: implement augmenting of existing ACLs
    
    This is much more useful in practice (equivalent to setfacl -m).

diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index ee33afc..957910d 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -234,7 +234,7 @@
           to exclude paths from clean-up as controlled with the Age
           parameter. Note that lines of this type do not influence the
           effect of <varname>r</varname> or <varname>R</varname>
-          lines.  Lines of this type accept shell-style globs in place
+          lines. Lines of this type accept shell-style globs in place
           of normal path names.  </para></listitem>
         </varlistentry>
 
@@ -246,7 +246,7 @@
           not exclude the content if path is a directory, but only
           directory itself. Note that lines of this type do not
           influence the effect of <varname>r</varname> or
-          <varname>R</varname> lines.  Lines of this type accept
+          <varname>R</varname> lines. Lines of this type accept
           shell-style globs in place of normal path names.
           </para></listitem>
         </varlistentry>
@@ -304,19 +304,25 @@
 
         <varlistentry>
           <term><varname>a</varname></term>
-          <listitem><para>Set POSIX ACLs (access control lists).
-          Lines of this type accept shell-style globs in
-          place of normal path names. This can be useful for
-          allowing additional access to certain files.
-          </para></listitem>
+          <term><varname>a+</varname></term>
+          <listitem><para>Set POSIX ACLs (access control lists). If
+          suffixed with <varname>+</varname>, specified mask will be
+          added to existing
+          entries. <command>systemd-tmpfiles</command> does not
+          automatically add the required base entries for user and
+          group to the specified mask, so they must be specified
+          explicitly if <varname>+</varname> is not used. The
+          mask will be added if not specified explicitly.
+          Lines of this type accept shell-style globs in place
+          of normal path names. This can be useful for allowing
+          additional access to certain files.  </para></listitem>
         </varlistentry>
 
         <varlistentry>
           <term><varname>A</varname></term>
-          <listitem><para>Recursively set POSIX ACLs. Lines of this
-          type accept shell-style globs in place of normal path
-          names. This can be useful for allowing additional access to
-          certain files.</para></listitem>
+          <term><varname>A+</varname></term>
+          <listitem><para>Same as <varname>a</varname> and
+          <varname>a+</varname>, but recursive.</para></listitem>
         </varlistentry>
       </variablelist>
 
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 22bb844..950f472 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -150,7 +150,7 @@ int search_acl_groups(char*** dst, const char* path, bool* belong) {
         return 0;
 }
 
-int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) {
+int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
         _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
         _cleanup_strv_free_ char **split;
         char **entry;
@@ -187,9 +187,11 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) {
                 if (!a_acl)
                         return -EINVAL;
 
-                r = calc_acl_mask_if_needed(&a_acl);
-                if (r < 0)
-                        return r;
+                if (want_mask) {
+                        r = calc_acl_mask_if_needed(&a_acl);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         if (!strv_isempty(d)) {
@@ -203,9 +205,11 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) {
                 if (!d_acl)
                         return -EINVAL;
 
-                r = calc_acl_mask_if_needed(&d_acl);
-                if (r < 0)
-                        return r;
+                if (want_mask) {
+                        r = calc_acl_mask_if_needed(&d_acl);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         *acl_access = a_acl;
@@ -213,3 +217,34 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) {
         a_acl = d_acl = NULL;
         return 0;
 }
+
+int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
+        _cleanup_(acl_freep) acl_t old;
+        acl_entry_t i;
+        int found, r;
+
+        old = acl_get_file(path, type);
+        if (!old)
+                return -errno;
+
+        for (found = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
+             found > 0;
+             found = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
+
+                acl_entry_t j;
+
+                if (acl_create_entry(&old, &j) < 0)
+                        return -errno;
+
+                if (acl_copy_entry(j, i) < 0)
+                        return -errno;
+        }
+
+        r = calc_acl_mask_if_needed(&old);
+        if (r < 0)
+                return r;
+
+        *acl = old;
+        old = NULL;
+        return 0;
+}
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index 4133214..1ad4a2e 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -32,7 +32,8 @@
 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
 int calc_acl_mask_if_needed(acl_t *acl_p);
 int search_acl_groups(char*** dst, const char* path, bool* belong);
-int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default);
+int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask);
+int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl);
 
 /* acl_free takes multiple argument types.
  * Multiple cleanup functions are necessary. */
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 44a0878..3c8993e 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -600,7 +600,9 @@ static int get_acls_from_arg(Item *item) {
 
         assert(item);
 
-        r = parse_acl(item->argument, &item->acl_access, &item->acl_default);
+        /* If force (= modify) is set, we will not modify the acl
+         * afterwards, so the mask can be added now if necessary. */
+        r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
         if (r < 0)
                 log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
                                   item->argument);
@@ -611,6 +613,32 @@ static int get_acls_from_arg(Item *item) {
         return 0;
 }
 
+static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
+        _cleanup_(acl_freep) acl_t cleanme = NULL;
+        int r;
+
+        if (modify) {
+                r = acls_for_file(path, type, acl, &cleanme);
+                if (r < 0)
+                        return r;
+                acl = cleanme;
+        };
+
+        r = acl_set_file(path, type, acl);
+        if (r < 0) {
+                _cleanup_(acl_free_charpp) char *t;
+
+                r = -errno;
+                t = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE);
+                log_error_errno(r,
+                                "Setting %s ACL \"%s\" on %s failed: %m",
+                                type == ACL_TYPE_ACCESS ? "access" : "default",
+                                strna(t), path);
+        }
+
+        return r;
+}
+
 static int path_set_acls(Item *item, const char *path) {
 #ifdef HAVE_ACL
         int r;
@@ -619,27 +647,15 @@ static int path_set_acls(Item *item, const char *path) {
         assert(path);
 
         if (item->acl_access) {
-                r = acl_set_file(path, ACL_TYPE_ACCESS, item->acl_access);
-                if (r < 0) {
-                        _cleanup_(acl_free_charpp) char *t;
-
-                        t = acl_to_any_text(item->acl_access, NULL, ',', TEXT_ABBREVIATE);
-                        return log_error_errno(errno,
-                                               "Setting access ACL \"%s\" on %s failed: %m",
-                                               strna(t), path);
-                }
+                r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
+                if (r < 0)
+                        return r;
         }
 
         if (item->acl_default) {
-                r = acl_set_file(path, ACL_TYPE_DEFAULT, item->acl_default);
-                if (r < 0) {
-                        _cleanup_(acl_free_charpp) char *t;
-
-                        t = acl_to_any_text(item->acl_default, NULL, ',', TEXT_ABBREVIATE);
-                        return log_error_errno(errno,
-                                               "Setting default ACL \"%s\" on %s failed: %m",
-                                               strna(t), path);
-                }
+                r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
+                if (r < 0)
+                        return r;
         }
 #endif
 

commit b705ab6a838937f947216af7b2d1fffb00f8b0dc
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Jan 18 02:10:00 2015 -0500

    tmpfiles: make t and a globby, add their recursive versions T and A
    
    For types which adapt existing files it is generally more useful to accept
    globs.
    
    In analogy to z and Z, add recursive versions using uppercase letters.
    
    Technically, making a accept globs is backwards incompatible, but in
    practice it probably isn't yet widely used and we can assume that most
    people don't create files with wildcards in names.
    
    Functions which are used as callbacks, but not directly on items, are
    renamed not to have "item_" prefix.

diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 7c1ef42..ee33afc 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -273,7 +273,7 @@
           <listitem><para>Adjust the access mode, group and user, and
           restore the SELinux security context of a file or directory,
           if it exists. Lines of this type accept shell-style globs in
-          place of normal path names.  </para></listitem>
+          place of normal path names.</para></listitem>
         </varlistentry>
 
         <varlistentry>
@@ -288,16 +288,35 @@
 
         <varlistentry>
           <term><varname>t</varname></term>
-          <listitem><para>Set extended attributes on the specified
-          path. This can be useful for setting SMACK labels.
+          <listitem><para>Set extended attributes. Lines of this type
+          accept shell-style globs in place of normal path names.
+          This can be useful for setting SMACK labels.
+          </para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>T</varname></term>
+          <listitem><para>Recursively set extended attributes. Lines
+          of this type accept shell-style globs in place of normal
+          path names.  This can be useful for setting SMACK labels.
           </para></listitem>
         </varlistentry>
 
         <varlistentry>
           <term><varname>a</varname></term>
-          <listitem><para>Set POSIX ACLs (access control lists) on the
-          specified path. This can be useful for allowing aditional
-          access to certain files.</para></listitem>
+          <listitem><para>Set POSIX ACLs (access control lists).
+          Lines of this type accept shell-style globs in
+          place of normal path names. This can be useful for
+          allowing additional access to certain files.
+          </para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>A</varname></term>
+          <listitem><para>Recursively set POSIX ACLs. Lines of this
+          type accept shell-style globs in place of normal path
+          names. This can be useful for allowing additional access to
+          certain files.</para></listitem>
         </varlistentry>
       </variablelist>
 
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index d563989..44a0878 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -76,10 +76,12 @@ typedef enum ItemType {
         CREATE_CHAR_DEVICE = 'c',
         CREATE_BLOCK_DEVICE = 'b',
         COPY_FILES = 'C',
-        SET_XATTR = 't',
-        SET_ACL = 'a',
 
         /* These ones take globs */
+        SET_XATTR = 't',
+        RECURSIVE_SET_XATTR = 'T',
+        SET_ACL = 'a',
+        RECURSIVE_SET_ACL = 'A',
         WRITE_FILE = 'w',
         IGNORE_PATH = 'x',
         IGNORE_DIRECTORY_PATH = 'X',
@@ -151,7 +153,11 @@ static bool needs_glob(ItemType t) {
                       RECURSIVE_REMOVE_PATH,
                       ADJUST_MODE,
                       RELABEL_PATH,
-                      RECURSIVE_RELABEL_PATH);
+                      RECURSIVE_RELABEL_PATH,
+                      SET_XATTR,
+                      RECURSIVE_SET_XATTR,
+                      SET_ACL,
+                      RECURSIVE_SET_ACL);
 }
 
 static bool takes_ownership(ItemType t) {
@@ -486,7 +492,7 @@ finish:
         return r;
 }
 
-static int item_set_perms(Item *i, const char *path) {
+static int path_set_perms(Item *i, const char *path) {
         struct stat st;
         bool st_valid;
 
@@ -568,7 +574,7 @@ static int get_xattrs_from_arg(Item *i) {
         return r;
 }
 
-static int item_set_xattrs(Item *i, const char *path) {
+static int path_set_xattrs(Item *i, const char *path) {
         char **name, **value;
 
         assert(i);
@@ -605,7 +611,7 @@ static int get_acls_from_arg(Item *item) {
         return 0;
 }
 
-static int item_set_acl(Item *item, const char *path) {
+static int path_set_acls(Item *item, const char *path) {
 #ifdef HAVE_ACL
         int r;
 
@@ -693,7 +699,7 @@ static int write_one_file(Item *i, const char *path) {
                 return -EEXIST;
         }
 
-        r = item_set_perms(i, path);
+        r = path_set_perms(i, path);
         if (r < 0)
                 return r;
 
@@ -817,7 +823,7 @@ static int create_item(Item *i) {
                         }
                 }
 
-                r = item_set_perms(i, i->path);
+                r = path_set_perms(i, i->path);
                 if (r < 0)
                         return r;
 
@@ -861,7 +867,7 @@ static int create_item(Item *i) {
                         }
                 }
 
-                r = item_set_perms(i, i->path);
+                r = path_set_perms(i, i->path);
                 if (r < 0)
                         return r;
 
@@ -901,7 +907,7 @@ static int create_item(Item *i) {
                         }
                 }
 
-                r = item_set_perms(i, i->path);
+                r = path_set_perms(i, i->path);
                 if (r < 0)
                         return r;
 
@@ -992,7 +998,7 @@ static int create_item(Item *i) {
                         }
                 }
 
-                r = item_set_perms(i, i->path);
+                r = path_set_perms(i, i->path);
                 if (r < 0)
                         return r;
 
@@ -1001,29 +1007,40 @@ static int create_item(Item *i) {
 
         case ADJUST_MODE:
         case RELABEL_PATH:
-
-                r = glob_item(i, item_set_perms, false);
+                r = glob_item(i, path_set_perms, false);
                 if (r < 0)
                         return r;
                 break;
 
         case RECURSIVE_RELABEL_PATH:
-
-                r = glob_item(i, item_set_perms, true);
+                r = glob_item(i, path_set_perms, true);
                 if (r < 0)
                         return r;
                 break;
 
         case SET_XATTR:
-                r = item_set_xattrs(i, i->path);
+                r = glob_item(i, path_set_xattrs, false);
+                if (r < 0)
+                        return r;
+                break;
+
+        case RECURSIVE_SET_XATTR:
+                r = glob_item(i, path_set_xattrs, true);
                 if (r < 0)
                         return r;
                 break;
 
         case SET_ACL:
-                r = item_set_acl(i, i->path);
+                r = glob_item(i, path_set_acls, false);
                 if (r < 0)
                         return r;
+                break;
+
+        case RECURSIVE_SET_ACL:
+                r = glob_item(i, path_set_acls, true);
+                if (r < 0)
+                        return r;
+                break;
         }
 
         log_debug("%s created successfully.", i->path);
@@ -1054,7 +1071,9 @@ static int remove_item_instance(Item *i, const char *instance) {
         case WRITE_FILE:
         case COPY_FILES:
         case SET_XATTR:
+        case RECURSIVE_SET_XATTR:
         case SET_ACL:
+        case RECURSIVE_SET_ACL:
                 break;
 
         case REMOVE_PATH:
@@ -1100,7 +1119,9 @@ static int remove_item(Item *i) {
         case WRITE_FILE:
         case COPY_FILES:
         case SET_XATTR:
+        case RECURSIVE_SET_XATTR:
         case SET_ACL:
+        case RECURSIVE_SET_ACL:
                 break;
 
         case REMOVE_PATH:
@@ -1444,6 +1465,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         }
 
         case SET_XATTR:
+        case RECURSIVE_SET_XATTR:
                 if (!i.argument) {
                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
                         return -EBADMSG;
@@ -1454,6 +1476,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 break;
 
         case SET_ACL:
+        case RECURSIVE_SET_ACL:
                 if (!i.argument) {
                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
                         return -EBADMSG;

commit 081043cf06cc67a327f55806039639c55acdd439
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Jan 18 01:33:39 2015 -0500

    tmpfiles: make recursive operation generic

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 7081b4d..d563989 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -700,7 +700,9 @@ static int write_one_file(Item *i, const char *path) {
         return 0;
 }
 
-static int item_set_perms_children(Item *i, const char *path) {
+typedef int (*action_t)(Item *, const char *);
+
+static int item_do_children(Item *i, const char *path, action_t action) {
         _cleanup_closedir_ DIR *d;
         int r = 0;
 
@@ -735,12 +737,12 @@ static int item_set_perms_children(Item *i, const char *path) {
                 if (!p)
                         return -ENOMEM;
 
-                q = item_set_perms(i, p);
+                q = action(i, p);
                 if (q < 0 && q != -ENOENT && r == 0)
                         r = q;
 
                 if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
-                        q = item_set_perms_children(i, p);
+                        q = item_do_children(i, p, action);
                         if (q < 0 && r == 0)
                                 r = q;
                 }
@@ -749,42 +751,26 @@ static int item_set_perms_children(Item *i, const char *path) {
         return r;
 }
 
-static int item_set_perms_recursive(Item *i, const char *path) {
-        int r, q;
-
-        assert(i);
-        assert(path);
-
-        r = item_set_perms(i, path);
-        if (r < 0)
-                return r;
-
-        q = item_set_perms_children(i, path);
-        if (q < 0 && r == 0)
-                r = q;
-
-        return r;
-}
-
-static int glob_item(Item *i, int (*action)(Item *, const char *)) {
+static int glob_item(Item *i, action_t action, bool recursive) {
         _cleanup_globfree_ glob_t g = {};
         int r = 0, k;
         char **fn;
 
         errno = 0;
         k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-        if (k != 0 && k != GLOB_NOMATCH) {
-                if (errno == 0)
-                        errno = EIO;
-
-                log_error_errno(errno, "glob(%s) failed: %m", i->path);
-                return -errno;
-        }
+        if (k != 0 && k != GLOB_NOMATCH)
+                return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
 
         STRV_FOREACH(fn, g.gl_pathv) {
                 k = action(i, *fn);
                 if (k < 0 && r == 0)
                         r = k;
+
+                if (recursive) {
+                        k = item_do_children(i, *fn, action);
+                        if (k < 0 && r == 0)
+                                r = k;
+                }
         }
 
         return r;
@@ -838,7 +824,7 @@ static int create_item(Item *i) {
                 break;
 
         case WRITE_FILE:
-                r = glob_item(i, write_one_file);
+                r = glob_item(i, write_one_file, false);
                 if (r < 0)
                         return r;
 
@@ -1016,14 +1002,14 @@ static int create_item(Item *i) {
         case ADJUST_MODE:
         case RELABEL_PATH:
 
-                r = glob_item(i, item_set_perms);
+                r = glob_item(i, item_set_perms, false);
                 if (r < 0)
                         return r;
                 break;
 
         case RECURSIVE_RELABEL_PATH:
 
-                r = glob_item(i, item_set_perms_recursive);
+                r = glob_item(i, item_set_perms, true);
                 if (r < 0)
                         return r;
                 break;
@@ -1120,7 +1106,7 @@ static int remove_item(Item *i) {
         case REMOVE_PATH:
         case TRUNCATE_DIRECTORY:
         case RECURSIVE_REMOVE_PATH:
-                r = glob_item(i, remove_item_instance);
+                r = glob_item(i, remove_item_instance, false);
                 break;
         }
 
@@ -1187,7 +1173,7 @@ static int clean_item(Item *i) {
                 clean_item_instance(i, i->path);
                 break;
         case IGNORE_DIRECTORY_PATH:
-                r = glob_item(i, clean_item_instance);
+                r = glob_item(i, clean_item_instance, false);
                 break;
         default:
                 break;

commit f8eeeaf9b783ebbab30672629abf3920db286811
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sat Jan 17 23:27:39 2015 -0500

    tmpfiles: add 'a' type to set ACLs

diff --git a/Makefile.am b/Makefile.am
index e86075f..440ba88 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2193,6 +2193,11 @@ systemd_tmpfiles_LDADD = \
 	libsystemd-internal.la \
 	libsystemd-shared.la
 
+if HAVE_ACL
+systemd_tmpfiles_LDADD += \
+	libsystemd-acl.la
+endif
+
 rootbin_PROGRAMS += \
 	systemd-tmpfiles
 
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 8d806a4..7c1ef42 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -292,6 +292,13 @@
           path. This can be useful for setting SMACK labels.
           </para></listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term><varname>a</varname></term>
+          <listitem><para>Set POSIX ACLs (access control lists) on the
+          specified path. This can be useful for allowing aditional
+          access to certain files.</para></listitem>
+        </varlistentry>
       </variablelist>
 
       <para>If the exclamation mark is used, this line is only safe of
@@ -374,8 +381,8 @@
       if omitted or when set to <literal>-</literal>, the file access
       mode will not be modified. This parameter is ignored for
       <varname>x</varname>, <varname>r</varname>,
-      <varname>R</varname>, <varname>L</varname>, <varname>t</varname>
-      lines.</para>
+      <varname>R</varname>, <varname>L</varname>, <varname>t</varname>,
+      and <varname>a</varname> lines.</para>
 
       <para>Optionally, if prefixed with <literal>~</literal>, the
       access mode is masked based on the already set access bits for
@@ -397,11 +404,12 @@
       may either be a numeric user/group ID or a user or group
       name. If omitted or when set to <literal>-</literal>, the
       default 0 (root) is used. For <varname>z</varname>,
-      <varname>Z</varname> lines, when omitted or when set to -, the
-      file ownership will not be modified. These parameters are
-      ignored for <varname>x</varname>, <varname>r</varname>,
-      <varname>R</varname>, <varname>L</varname>, <varname>t</varname>
-      lines.</para>
+      <varname>Z</varname> lines, when omitted or when set to
+      <literal>-</literal>, the file ownership will not be
+      modified. These parameters are ignored for <varname>x</varname>,
+      <varname>r</varname>, <varname>R</varname>,
+      <varname>L</varname>, <varname>t</varname>, and
+      <varname>a</varname> lines.</para>
     </refsect2>
 
     <refsect2>
@@ -458,7 +466,8 @@
       is written to the file, suffixed by a newline. For
       <varname>C</varname>, specifies the source file or
       directory. For <varname>t</varname> determines extended
-      attributes to be set. Ignored for all other lines.</para>
+      attributes to be set. For <varname>a</varname> determines
+      ACL attributes to be set. Ignored for all other lines.</para>
     </refsect2>
 
   </refsect1>
@@ -489,7 +498,12 @@
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-tmpfiles</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-delta</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>attr</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>getfattr</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>setfattr</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>setfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>getfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     </para>
   </refsect1>
 
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index a37e5eb..d322e79 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -49,11 +49,7 @@
 #include "path-util.h"
 #include "compress.h"
 #include "coredump-vacuum.h"
-
-#ifdef HAVE_ACL
-#  include <sys/acl.h>
-#  include "acl-util.h"
-#endif
+#include "acl-util.h"
 
 /* The maximum size up to which we process coredumps */
 #define PROCESS_SIZE_MAX ((off_t) (2LLU*1024LLU*1024LLU*1024LLU))
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 27a6187..c17cf55 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -37,17 +37,13 @@
 #include <sys/inotify.h>
 #include <linux/fs.h>
 
-#ifdef HAVE_ACL
-#include <sys/acl.h>
-#include "acl-util.h"
-#endif
-
 #include "sd-journal.h"
 #include "sd-bus.h"
 
 #include "log.h"
 #include "logs-show.h"
 #include "util.h"
+#include "acl-util.h"
 #include "path-util.h"
 #include "fileio.h"
 #include "build.h"
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 5999724..87b459b 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -52,12 +52,7 @@
 #include "journald-native.h"
 #include "journald-audit.h"
 #include "journald-server.h"
-
-#ifdef HAVE_ACL
-#include <sys/acl.h>
-#include <acl/libacl.h>
 #include "acl-util.h"
-#endif
 
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index f7c6f3a..5856f90 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -22,8 +22,6 @@
 #include <assert.h>
 #include <errno.h>
 #include <string.h>
-#include <sys/acl.h>
-#include <acl/libacl.h>
 
 #include "util.h"
 #include "acl-util.h"
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index c93f58a..22bb844 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -20,8 +20,6 @@
 ***/
 
 #include <assert.h>
-#include <sys/acl.h>
-#include <acl/libacl.h>
 #include <errno.h>
 #include <stdbool.h>
 
@@ -151,3 +149,67 @@ int search_acl_groups(char*** dst, const char* path, bool* belong) {
 
         return 0;
 }
+
+int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) {
+        _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
+        _cleanup_strv_free_ char **split;
+        char **entry;
+        int r = -EINVAL;
+        _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
+
+        split = strv_split(text, ",");
+        if (!split)
+                return log_oom();
+
+        STRV_FOREACH(entry, split) {
+                char *p;
+
+                p = startswith(*entry, "default:");
+                if (!p)
+                        p = startswith(*entry, "d:");
+
+                if (p)
+                        r = strv_push(&d, p);
+                else
+                        r = strv_push(&a, *entry);
+        }
+        if (r < 0)
+                return r;
+
+        if (!strv_isempty(a)) {
+                _cleanup_free_ char *join;
+
+                join = strv_join(a, ",");
+                if (!join)
+                        return -ENOMEM;
+
+                a_acl = acl_from_text(join);
+                if (!a_acl)
+                        return -EINVAL;
+
+                r = calc_acl_mask_if_needed(&a_acl);
+                if (r < 0)
+                        return r;
+        }
+
+        if (!strv_isempty(d)) {
+                _cleanup_free_ char *join;
+
+                join = strv_join(d, ",");
+                if (!join)
+                        return -ENOMEM;
+
+                d_acl = acl_from_text(join);
+                if (!d_acl)
+                        return -EINVAL;
+
+                r = calc_acl_mask_if_needed(&d_acl);
+                if (r < 0)
+                        return r;
+        }
+
+        *acl_access = a_acl;
+        *acl_default = d_acl;
+        a_acl = d_acl = NULL;
+        return 0;
+}
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index a753ad1..4133214 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -21,16 +21,23 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#ifdef HAVE_ACL
+
 #include <stdbool.h>
+#include <sys/acl.h>
+#include <acl/libacl.h>
+
+#include "macro.h"
 
 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
 int calc_acl_mask_if_needed(acl_t *acl_p);
 int search_acl_groups(char*** dst, const char* path, bool* belong);
+int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default);
 
-static inline void acl_freep(acl_t *acl) {
-
-        if (!*acl)
-                return;
+/* acl_free takes multiple argument types.
+ * Multiple cleanup functions are necessary. */
+DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free);
+#define acl_free_charp acl_free
+DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp);
 
-        acl_free(*acl);
-}
+#endif
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index c44dfaf..7081b4d 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -57,6 +57,7 @@
 #include "copy.h"
 #include "selinux-util.h"
 #include "btrfs-util.h"
+#include "acl-util.h"
 
 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
  * them in the file system. This is intended to be used to create
@@ -76,6 +77,7 @@ typedef enum ItemType {
         CREATE_BLOCK_DEVICE = 'b',
         COPY_FILES = 'C',
         SET_XATTR = 't',
+        SET_ACL = 'a',
 
         /* These ones take globs */
         WRITE_FILE = 'w',
@@ -94,6 +96,10 @@ typedef struct Item {
         char *path;
         char *argument;
         char **xattrs;
+#ifdef HAVE_ACL
+        acl_t acl_access;
+        acl_t acl_default;
+#endif
         uid_t uid;
         gid_t gid;
         mode_t mode;
@@ -581,6 +587,59 @@ static int item_set_xattrs(Item *i, const char *path) {
         return 0;
 }
 
+static int get_acls_from_arg(Item *item) {
+#ifdef HAVE_ACL
+        int r;
+        _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
+
+        assert(item);
+
+        r = parse_acl(item->argument, &item->acl_access, &item->acl_default);
+        if (r < 0)
+                log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
+                                  item->argument);
+#else
+        log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
+#endif
+
+        return 0;
+}
+
+static int item_set_acl(Item *item, const char *path) {
+#ifdef HAVE_ACL
+        int r;
+
+        assert(item);
+        assert(path);
+
+        if (item->acl_access) {
+                r = acl_set_file(path, ACL_TYPE_ACCESS, item->acl_access);
+                if (r < 0) {
+                        _cleanup_(acl_free_charpp) char *t;
+
+                        t = acl_to_any_text(item->acl_access, NULL, ',', TEXT_ABBREVIATE);
+                        return log_error_errno(errno,
+                                               "Setting access ACL \"%s\" on %s failed: %m",
+                                               strna(t), path);
+                }
+        }
+
+        if (item->acl_default) {
+                r = acl_set_file(path, ACL_TYPE_DEFAULT, item->acl_default);
+                if (r < 0) {
+                        _cleanup_(acl_free_charpp) char *t;
+
+                        t = acl_to_any_text(item->acl_default, NULL, ',', TEXT_ABBREVIATE);
+                        return log_error_errno(errno,
+                                               "Setting default ACL \"%s\" on %s failed: %m",
+                                               strna(t), path);
+                }
+        }
+#endif
+
+        return 0;
+}
+
 static int write_one_file(Item *i, const char *path) {
         _cleanup_close_ int fd = -1;
         int flags, r = 0;
@@ -974,6 +1033,11 @@ static int create_item(Item *i) {
                 if (r < 0)
                         return r;
                 break;
+
+        case SET_ACL:
+                r = item_set_acl(i, i->path);
+                if (r < 0)
+                        return r;
         }
 
         log_debug("%s created successfully.", i->path);
@@ -1004,6 +1068,7 @@ static int remove_item_instance(Item *i, const char *instance) {
         case WRITE_FILE:
         case COPY_FILES:
         case SET_XATTR:
+        case SET_ACL:
                 break;
 
         case REMOVE_PATH:
@@ -1049,6 +1114,7 @@ static int remove_item(Item *i) {
         case WRITE_FILE:
         case COPY_FILES:
         case SET_XATTR:
+        case SET_ACL:
                 break;
 
         case REMOVE_PATH:
@@ -1190,6 +1256,11 @@ static void item_free_contents(Item *i) {
         free(i->path);
         free(i->argument);
         strv_free(i->xattrs);
+
+#ifdef HAVE_ACL
+        acl_free(i->acl_access);
+        acl_free(i->acl_default);
+#endif
 }
 
 static void item_array_free(ItemArray *a) {
@@ -1396,6 +1467,16 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                         return r;
                 break;
 
+        case SET_ACL:
+                if (!i.argument) {
+                        log_error("[%s:%u] Set ACLs requires argument.", fname, line);
+                        return -EBADMSG;
+                }
+                r = get_acls_from_arg(&i);
+                if (r < 0)
+                        return r;
+                break;
+
         default:
                 log_error("[%s:%u] Unknown command type '%c'.", fname, line, i.type);
                 return -EBADMSG;

commit 3f93da987961c139215d3a55fd25496310537d1b
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Fri Jan 9 02:00:37 2015 -0500

    tmpfiles: attach an array of items to each path
    
    The data structure used by tmpfiles is changed: instead of hashmaps
    mapping {path → Item*} we now have hashmaps containing
    {path -> ItemArray}, where ItemArray contains a pointer
    to an array of Items.
    
    For current code it doesn't matter much, but when we add new types it
    is easier to simply add a new Item for a given path, then to coalesce
    multiple lines into one Item.
    
    In the future, this change will also make it possible to remember the
    file and line where each Item originates, and use that in reporting
    errors. Currently this is not possible, since each Item can be created
    from multiple lines.

diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 9fd5913..8d806a4 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -288,16 +288,9 @@
 
         <varlistentry>
           <term><varname>t</varname></term>
-          <listitem><para>Set extended attributes on item. It may be
-          used in conjunction with other types (only
-          <varname>d</varname>, <varname>D</varname>,
-          <varname>f</varname>, <varname>F</varname>,
-          <varname>L</varname>, <varname>p</varname>,
-          <varname>c</varname>, <varname>b</varname>, makes sense).
-          If used as a standalone line, then
-          <command>systemd-tmpfiles</command> will try to set extended
-          attributes on specified path.  This can be especially used
-          to set SMACK labels.  </para></listitem>
+          <listitem><para>Set extended attributes on the specified
+          path. This can be useful for setting SMACK labels.
+          </para></listitem>
         </varlistentry>
       </variablelist>
 
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 84d778a..c44dfaf 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -4,6 +4,7 @@
   This file is part of systemd.
 
   Copyright 2010 Lennart Poettering, Kay Sievers
+  Copyright 2015 Zbigniew Jędrzejewski-Szmek
 
   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
@@ -113,6 +114,12 @@ typedef struct Item {
         bool done:1;
 } Item;
 
+typedef struct ItemArray {
+        Item *items;
+        size_t count;
+        size_t size;
+} ItemArray;
+
 static bool arg_create = false;
 static bool arg_clean = false;
 static bool arg_remove = false;
@@ -141,13 +148,40 @@ static bool needs_glob(ItemType t) {
                       RECURSIVE_RELABEL_PATH);
 }
 
+static bool takes_ownership(ItemType t) {
+        return IN_SET(t,
+                      CREATE_FILE,
+                      TRUNCATE_FILE,
+                      CREATE_DIRECTORY,
+                      TRUNCATE_DIRECTORY,
+                      CREATE_SUBVOLUME,
+                      CREATE_FIFO,
+                      CREATE_SYMLINK,
+                      CREATE_CHAR_DEVICE,
+                      CREATE_BLOCK_DEVICE,
+                      COPY_FILES,
+
+                      WRITE_FILE,
+                      IGNORE_PATH,
+                      IGNORE_DIRECTORY_PATH,
+                      REMOVE_PATH,
+                      RECURSIVE_REMOVE_PATH);
+}
+
 static struct Item* find_glob(Hashmap *h, const char *match) {
-        Item *j;
+        ItemArray *j;
         Iterator i;
 
-        HASHMAP_FOREACH(j, h, i)
-                if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
-                        return j;
+        HASHMAP_FOREACH(j, h, i) {
+                unsigned n;
+
+                for (n = 0; n < j->count; n++) {
+                        Item *item = j->items + n;
+
+                        if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
+                                return item;
+                }
+        }
 
         return NULL;
 }
@@ -604,10 +638,6 @@ static int write_one_file(Item *i, const char *path) {
         if (r < 0)
                 return r;
 
-        r = item_set_xattrs(i, i->path);
-        if (r < 0)
-                return r;
-
         return 0;
 }
 
@@ -790,10 +820,6 @@ static int create_item(Item *i) {
                 if (r < 0)
                         return r;
 
-                r = item_set_xattrs(i, i->path);
-                if (r < 0)
-                        return r;
-
                 break;
 
         case CREATE_FIFO:
@@ -834,10 +860,6 @@ static int create_item(Item *i) {
                 if (r < 0)
                         return r;
 
-                r = item_set_xattrs(i, i->path);
-                if (r < 0)
-                        return r;
-
                 break;
 
         case CREATE_SYMLINK:
@@ -869,10 +891,6 @@ static int create_item(Item *i) {
                         }
                 }
 
-                r = item_set_xattrs(i, i->path);
-                if (r < 0)
-                       return r;
-
                 break;
 
         case CREATE_BLOCK_DEVICE:
@@ -933,10 +951,6 @@ static int create_item(Item *i) {
                 if (r < 0)
                         return r;
 
-                r = item_set_xattrs(i, i->path);
-                if (r < 0)
-                        return r;
-
                 break;
         }
 
@@ -994,7 +1008,7 @@ static int remove_item_instance(Item *i, const char *instance) {
 
         case REMOVE_PATH:
                 if (remove(instance) < 0 && errno != ENOENT)
-                        return log_error_errno(errno, "remove(%s): %m", instance);
+                        return log_error_errno(errno, "rm(%s): %m", instance);
 
                 break;
 
@@ -1116,6 +1130,8 @@ static int clean_item(Item *i) {
         return r;
 }
 
+static int process_item_array(ItemArray *array);
+
 static int process_item(Item *i) {
         int r, q, p, t = 0;
         _cleanup_free_ char *prefix = NULL;
@@ -1132,13 +1148,13 @@ static int process_item(Item *i) {
                 return log_oom();
 
         PATH_FOREACH_PREFIX(prefix, i->path) {
-                Item *j;
+                ItemArray *j;
 
                 j = hashmap_get(items, prefix);
                 if (j) {
                         int s;
 
-                        s = process_item(j);
+                        s = process_item_array(j);
                         if (s < 0 && t == 0)
                                 t = s;
                 }
@@ -1154,57 +1170,66 @@ static int process_item(Item *i) {
                 p;
 }
 
-static void item_free(Item *i) {
+static int process_item_array(ItemArray *array) {
+        unsigned n;
+        int r = 0, k;
 
-        if (!i)
-                return;
+        assert(array);
+
+        for (n = 0; n < array->count; n++) {
+                k = process_item(array->items + n);
+                if (k < 0 && r == 0)
+                        r = k;
+        }
+
+        return r;
+}
 
+static void item_free_contents(Item *i) {
+        assert(i);
         free(i->path);
         free(i->argument);
         strv_free(i->xattrs);
-        free(i);
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
+static void item_array_free(ItemArray *a) {
+        unsigned n;
+
+        if (!a)
+                return;
+
+        for (n = 0; n < a->count; n++)
+                item_free_contents(a->items + n);
+        free(a->items);
+        free(a);
+}
 
-static bool item_equal(Item *a, Item *b) {
+static bool item_compatible(Item *a, Item *b) {
         assert(a);
         assert(b);
+        assert(streq(a->path, b->path));
 
-        if (!streq_ptr(a->path, b->path))
-                return false;
+        if (takes_ownership(a->type) && takes_ownership(b->type))
+                /* check if the items are the same */
+                return  streq_ptr(a->argument, b->argument) &&
 
-        if (a->type != b->type)
-                return false;
+                        a->uid_set == b->uid_set &&
+                        a->uid == b->uid &&
 
-        if (a->uid_set != b->uid_set ||
-            (a->uid_set && a->uid != b->uid))
-            return false;
+                        a->gid_set == b->gid_set &&
+                        a->gid == b->gid &&
 
-        if (a->gid_set != b->gid_set ||
-            (a->gid_set && a->gid != b->gid))
-            return false;
+                        a->mode_set == b->mode_set &&
+                        a->mode == b->mode &&
 
-        if (a->mode_set != b->mode_set ||
-            (a->mode_set && a->mode != b->mode))
-            return false;
+                        a->age_set == b->age_set &&
+                        a->age == b->age &&
 
-        if (a->age_set != b->age_set ||
-            (a->age_set && a->age != b->age))
-            return false;
+                        a->mask_perms == b->mask_perms &&
 
-        if ((a->type == CREATE_FILE ||
-             a->type == TRUNCATE_FILE ||
-             a->type == WRITE_FILE ||
-             a->type == CREATE_SYMLINK ||
-             a->type == COPY_FILES) &&
-            !streq_ptr(a->argument, b->argument))
-                return false;
+                        a->keep_first_level == b->keep_first_level &&
 
-        if ((a->type == CREATE_CHAR_DEVICE ||
-             a->type == CREATE_BLOCK_DEVICE) &&
-            a->major_minor != b->major_minor)
-                return false;
+                        a->major_minor == b->major_minor;
 
         return true;
 }
@@ -1236,10 +1261,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         };
 
         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
-        _cleanup_(item_freep) Item *i = NULL;
-        Item *existing;
+        _cleanup_(item_free_contents) Item i = {};
+        ItemArray *existing;
         Hashmap *h;
-        int r, n = -1, pos;
+        int r, c = -1, pos;
         bool force = false, boot = false;
 
         assert(fname);
@@ -1254,7 +1279,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                    &user,
                    &group,
                    &age,
-                   &n);
+                   &c);
         if (r < 2) {
                 log_error("[%s:%u] Syntax error.", fname, line);
                 return -EIO;
@@ -1280,29 +1305,25 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         if (boot && !arg_boot)
                 return 0;
 
-        i = new0(Item, 1);
-        if (!i)
-                return log_oom();
-
-        i->type = action[0];
-        i->force = force;
+        i.type = action[0];
+        i.force = force;
 
-        r = specifier_printf(path, specifier_table, NULL, &i->path);
+        r = specifier_printf(path, specifier_table, NULL, &i.path);
         if (r < 0) {
                 log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
                 return r;
         }
 
-        if (n >= 0)  {
-                n += strspn(buffer+n, WHITESPACE);
-                if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
-                        i->argument = unquote(buffer+n, "\"");
-                        if (!i->argument)
+        if (c >= 0)  {
+                c += strspn(buffer+c, WHITESPACE);
+                if (buffer[c] != 0 && (buffer[c] != '-' || buffer[c+1] != 0)) {
+                        i.argument = unquote(buffer+c, "\"");
+                        if (!i.argument)
                                 return log_oom();
                 }
         }
 
-        switch (i->type) {
+        switch (i.type) {
 
         case CREATE_FILE:
         case TRUNCATE_FILE:
@@ -1320,109 +1341,109 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 break;
 
         case CREATE_SYMLINK:
-                if (!i->argument) {
-                        i->argument = strappend("/usr/share/factory/", i->path);
-                        if (!i->argument)
+                if (!i.argument) {
+                        i.argument = strappend("/usr/share/factory/", i.path);
+                        if (!i.argument)
                                 return log_oom();
                 }
                 break;
 
         case WRITE_FILE:
-                if (!i->argument) {
+                if (!i.argument) {
                         log_error("[%s:%u] Write file requires argument.", fname, line);
                         return -EBADMSG;
                 }
                 break;
 
         case COPY_FILES:
-                if (!i->argument) {
-                        i->argument = strappend("/usr/share/factory/", i->path);
-                        if (!i->argument)
+                if (!i.argument) {
+                        i.argument = strappend("/usr/share/factory/", i.path);
+                        if (!i.argument)
                                 return log_oom();
-                } else if (!path_is_absolute(i->argument)) {
+                } else if (!path_is_absolute(i.argument)) {
                         log_error("[%s:%u] Source path is not absolute.", fname, line);
                         return -EBADMSG;
                 }
 
-                path_kill_slashes(i->argument);
+                path_kill_slashes(i.argument);
                 break;
 
         case CREATE_CHAR_DEVICE:
         case CREATE_BLOCK_DEVICE: {
                 unsigned major, minor;
 
-                if (!i->argument) {
+                if (!i.argument) {
                         log_error("[%s:%u] Device file requires argument.", fname, line);
                         return -EBADMSG;
                 }
 
-                if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
-                        log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
+                if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
+                        log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
                         return -EBADMSG;
                 }
 
-                i->major_minor = makedev(major, minor);
+                i.major_minor = makedev(major, minor);
                 break;
         }
 
         case SET_XATTR:
-                if (!i->argument) {
+                if (!i.argument) {
                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
                         return -EBADMSG;
                 }
-                r = get_xattrs_from_arg(i);
+                r = get_xattrs_from_arg(&i);
                 if (r < 0)
                         return r;
                 break;
 
         default:
-                log_error("[%s:%u] Unknown command type '%c'.", fname, line, i->type);
+                log_error("[%s:%u] Unknown command type '%c'.", fname, line, i.type);
                 return -EBADMSG;
         }
 
-        if (!path_is_absolute(i->path)) {
-                log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
+        if (!path_is_absolute(i.path)) {
+                log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
                 return -EBADMSG;
         }
 
-        path_kill_slashes(i->path);
+        path_kill_slashes(i.path);
 
-        if (!should_include_path(i->path))
+        if (!should_include_path(i.path))
                 return 0;
 
         if (arg_root) {
                 char *p;
 
-                p = strappend(arg_root, i->path);
+                p = strappend(arg_root, i.path);
                 if (!p)
                         return log_oom();
 
-                free(i->path);
-                i->path = p;
+                free(i.path);
+                i.path = p;
         }
 
         if (user && !streq(user, "-")) {
                 const char *u = user;
 
-                r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
+                r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
                 if (r < 0) {
                         log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
                         return r;
                 }
 
-                i->uid_set = true;
+                i.uid_set = true;
         }
 
         if (group && !streq(group, "-")) {
                 const char *g = group;
 
-                r = get_group_creds(&g, &i->gid);
+                r = get_group_creds(&g, &i.gid);
                 if (r < 0) {
                         log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
                         return r;
                 }
 
-                i->gid_set = true;
+                i.gid_set = true;
         }
 
         if (mode && !streq(mode, "-")) {
@@ -1430,7 +1451,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 unsigned m;
 
                 if (*mm == '~') {
-                        i->mask_perms = true;
+                        i.mask_perms = true;
                         mm++;
                 }
 
@@ -1439,66 +1460,51 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                         return -ENOENT;
                 }
 
-                i->mode = m;
-                i->mode_set = true;
+                i.mode = m;
+                i.mode_set = true;
         } else
-                i->mode =
-                        i->type == CREATE_DIRECTORY ||
-                        i->type == CREATE_SUBVOLUME ||
-                        i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
+                i.mode = IN_SET(i.type, CREATE_DIRECTORY, CREATE_SUBVOLUME, TRUNCATE_DIRECTORY)
+                        ? 0755 : 0644;
 
         if (age && !streq(age, "-")) {
                 const char *a = age;
 
                 if (*a == '~') {
-                        i->keep_first_level = true;
+                        i.keep_first_level = true;
                         a++;
                 }
 
-                if (parse_sec(a, &i->age) < 0) {
+                if (parse_sec(a, &i.age) < 0) {
                         log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
                         return -EBADMSG;
                 }
 
-                i->age_set = true;
+                i.age_set = true;
         }
 
-        h = needs_glob(i->type) ? globs : items;
+        h = needs_glob(i.type) ? globs : items;
 
-        existing = hashmap_get(h, i->path);
+        existing = hashmap_get(h, i.path);
         if (existing) {
-                if (i->type == SET_XATTR) {
-                        r = strv_extend_strv(&existing->xattrs, i->xattrs);
-                        if (r < 0)
-                                return log_oom();
-                        return 0;
-                } else if (existing->type == SET_XATTR) {
-                        r = strv_extend_strv(&i->xattrs, existing->xattrs);
-                        if (r < 0)
-                                return log_oom();
-                        r = hashmap_replace(h, i->path, i);
-                        if (r < 0) {
-                                log_error("Failed to replace item for %s.", i->path);
-                                return r;
-                        }
-                        item_free(existing);
-                } else {
-                        /* Two identical items are fine */
-                        if (!item_equal(existing, i))
+                unsigned n;
+
+                for (n = 0; n < existing->count; n++) {
+                        if (!item_compatible(existing->items + n, &i))
                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
-                                            fname, line, i->path);
-                        return 0;
+                                            fname, line, i.path);
                 }
         } else {
-                r = hashmap_put(h, i->path, i);
-                if (r < 0) {
-                        log_error("Failed to insert item %s: %s", i->path, strerror(-r));
-                        return r;
-                }
+                existing = new0(ItemArray, 1);
+                r = hashmap_put(h, i.path, existing);
+                if (r < 0)
+                        return log_oom();
         }
 
-        i = NULL; /* avoid cleanup */
+        if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
+                return log_oom();
 
+        memcpy(existing->items + existing->count++, &i, sizeof(i));
+        zero(i);
         return 0;
 }
 
@@ -1683,7 +1689,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
 
 int main(int argc, char *argv[]) {
         int r, k;
-        Item *i;
+        ItemArray *a;
         Iterator iterator;
 
         r = parse_argv(argc, argv);
@@ -1734,24 +1740,24 @@ int main(int argc, char *argv[]) {
                 }
         }
 
-        HASHMAP_FOREACH(i, globs, iterator) {
-                k = process_item(i);
+        HASHMAP_FOREACH(a, globs, iterator) {
+                k = process_item_array(a);
                 if (k < 0 && r == 0)
                         r = k;
         }
 
-        HASHMAP_FOREACH(i, items, iterator) {
-                k = process_item(i);
+        HASHMAP_FOREACH(a, items, iterator) {
+                k = process_item_array(a);
                 if (k < 0 && r == 0)
                         r = k;
         }
 
 finish:
-        while ((i = hashmap_steal_first(items)))
-                item_free(i);
+        while ((a = hashmap_steal_first(items)))
+                item_array_free(a);
 
-        while ((i = hashmap_steal_first(globs)))
-                item_free(i);
+        while ((a = hashmap_steal_first(globs)))
+                item_array_free(a);
 
         hashmap_free(items);
         hashmap_free(globs);

commit 222c47f47615a275b9a9862a45f9b91b01eb8be5
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Fri Jan 9 01:27:31 2015 -0500

    tmpfiles: make sure not to concatenate non-absolute path
    
    If the path is absolute was only checked later.
    Also do not check if path if absolute if we just
    specified it starting with a slash.

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 8811f27..84d778a 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1321,7 +1321,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
 
         case CREATE_SYMLINK:
                 if (!i->argument) {
-                        i->argument = strappend("/usr/share/factory", i->path);
+                        i->argument = strappend("/usr/share/factory/", i->path);
                         if (!i->argument)
                                 return log_oom();
                 }
@@ -1336,12 +1336,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
 
         case COPY_FILES:
                 if (!i->argument) {
-                        i->argument = strappend("/usr/share/factory", i->path);
+                        i->argument = strappend("/usr/share/factory/", i->path);
                         if (!i->argument)
                                 return log_oom();
-                }
-
-                if (!path_is_absolute(i->argument)) {
+                } else if (!path_is_absolute(i->argument)) {
                         log_error("[%s:%u] Source path is not absolute.", fname, line);
                         return -EBADMSG;
                 }

commit 5f255144ae1ca7162b15e712a79d2eb9d83015f7
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Fri Jan 9 01:11:01 2015 -0500

    tmpfiles: detect all combinations of + and !
    
    The same algorithm as with - and @ in ExecStart= is used.

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 91ae62d..8811f27 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1238,9 +1238,9 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
         _cleanup_(item_freep) Item *i = NULL;
         Item *existing;
-        char type;
         Hashmap *h;
-        int r, n = -1;
+        int r, n = -1, pos;
+        bool force = false, boot = false;
 
         assert(fname);
         assert(line >= 1);
@@ -1265,21 +1265,27 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 return -EINVAL;
         }
 
-        if (strlen(action) > 1 && !in_charset(action+1, "!+")) {
-                log_error("[%s:%u] Unknown modifiers in command '%s'", fname, line, action);
-                return -EINVAL;
+        for (pos = 1; action[pos]; pos++) {
+                if (action[pos] == '!' && !boot)
+                        boot = true;
+                else if (action[pos] == '+' && !force)
+                        force = true;
+                else {
+                        log_error("[%s:%u] Unknown modifiers in command '%s'",
+                                  fname, line, action);
+                        return -EINVAL;
+                }
         }
 
-        if (strchr(action+1, '!') && !arg_boot)
+        if (boot && !arg_boot)
                 return 0;
 
-        type = action[0];
-
         i = new0(Item, 1);
         if (!i)
                 return log_oom();
 
-        i->force = !!strchr(action+1, '+');
+        i->type = action[0];
+        i->force = force;
 
         r = specifier_printf(path, specifier_table, NULL, &i->path);
         if (r < 0) {
@@ -1296,7 +1302,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 }
         }
 
-        switch (type) {
+        switch (i->type) {
 
         case CREATE_FILE:
         case TRUNCATE_FILE:
@@ -1372,12 +1378,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 break;
 
         default:
-                log_error("[%s:%u] Unknown command type '%c'.", fname, line, type);
+                log_error("[%s:%u] Unknown command type '%c'.", fname, line, i->type);
                 return -EBADMSG;
         }
 
-        i->type = type;
-
         if (!path_is_absolute(i->path)) {
                 log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
                 return -EBADMSG;

commit 505ef0e36c218f5c7a0987156a8d5bd5129a6773
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Fri Jan 9 01:10:02 2015 -0500

    tmpfiles: simplification
    
    Certain conditions were checked more than once. Warning message
    is improved.

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 332ddcea..91ae62d 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -23,7 +23,6 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <limits.h>
 #include <dirent.h>
 #include <grp.h>
@@ -34,10 +33,11 @@
 #include <getopt.h>
 #include <stdbool.h>
 #include <time.h>
-#include <sys/types.h>
-#include <sys/param.h>
 #include <glob.h>
 #include <fnmatch.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/xattr.h>
 
 #include "log.h"
@@ -480,11 +480,9 @@ static int item_set_perms(Item *i, const char *path) {
             (i->uid_set || i->gid_set))
                 if (chown(path,
                           i->uid_set ? i->uid : UID_INVALID,
-                          i->gid_set ? i->gid : GID_INVALID) < 0) {
+                          i->gid_set ? i->gid : GID_INVALID) < 0)
 
-                        log_error_errno(errno, "chown(%s) failed: %m", path);
-                        return -errno;
-                }
+                        return log_error_errno(errno, "chown(%s) failed: %m", path);
 
         return label_fix(path, false, false);
 }
@@ -495,36 +493,36 @@ static int get_xattrs_from_arg(Item *i) {
         int r;
 
         assert(i);
+        assert(i->argument);
 
-        if (!i->argument) {
-                log_error("%s: Argument can't be empty!", i->path);
-                return -EBADMSG;
-        }
         p = i->argument;
 
         while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
-                _cleanup_free_ char *tmp = NULL, *name = NULL, *value = NULL;
+                _cleanup_free_ char *tmp = NULL, *name = NULL,
+                        *value = NULL, *value2 = NULL, *_xattr = xattr;
+
                 r = split_pair(xattr, "=", &name, &value);
                 if (r < 0) {
                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
-                        free(xattr);
                         continue;
                 }
-                free(xattr);
-                if (streq(name, "") || streq(value, "")) {
-                        log_warning("Malformed xattr found: \"%s=%s\" - ignoring.", name, value);
+
+                if (strempty(name) || strempty(value)) {
+                        log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
                         continue;
                 }
+
                 tmp = unquote(value, "\"");
                 if (!tmp)
                         return log_oom();
-                free(value);
-                value = cunescape(tmp);
-                if (!value)
+
+                value2 = cunescape(tmp);
+                if (!value2)
                         return log_oom();
-                if (strv_consume_pair(&i->xattrs, name, value) < 0)
+
+                if (strv_push_pair(&i->xattrs, name, value2) < 0)
                         return log_oom();
-                name = value = NULL;
+                name = value2 = NULL;
         }
 
         return r;
@@ -536,14 +534,13 @@ static int item_set_xattrs(Item *i, const char *path) {
         assert(i);
         assert(path);
 
-        if (strv_isempty(i->xattrs))
-                return 0;
-
         STRV_FOREACH_PAIR(name, value, i->xattrs) {
                 int n;
+
                 n = strlen(*value);
                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
-                        log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path);
+                        log_error("Setting extended attribute %s=%s on %s failed: %m",
+                                  *name, *value, path);
                         return -errno;
                 }
         }
@@ -771,7 +768,7 @@ static int create_item(Item *i) {
                 } else
                         r = 0;
 
-                if (i->type == CREATE_DIRECTORY || i->type == TRUNCATE_DIRECTORY || r == -ENOTTY) {
+                if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY) {
                         RUN_WITH_UMASK(0000)
                                 r = mkdir_label(i->path, i->mode);
                 }
@@ -1486,7 +1483,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 } else {
                         /* Two identical items are fine */
                         if (!item_equal(existing, i))
-                                log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
+                                log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
+                                            fname, line, i->path);
                         return 0;
                 }
         } else {

commit 158bffeb434c0015e2d6b9e9f15e24a6dc69a493
Author: Rafael Ferreira <rafael.f.f1 at gmail.com>
Date:   Mon Jan 19 12:39:43 2015 -0200

    catalog: update pt_BR translation
    
    Brazilian Portuguese update for CATALOG patch, according to commit
    2057124e7910c4cab7e53d26e0c3749d326ae2bb ("Grammar changes to catalog")
    
    https://bugs.freedesktop.org/show_bug.cgi?id=88588

diff --git a/catalog/systemd.pt_BR.catalog b/catalog/systemd.pt_BR.catalog
index c56fe89..d9716e3 100644
--- a/catalog/systemd.pt_BR.catalog
+++ b/catalog/systemd.pt_BR.catalog
@@ -52,8 +52,8 @@ período de tempo. Mensagens do serviço foram descartadas.
 Note que apenas mensagens de um serviço em questão foram descartadas; outras
 mensagens dos serviços não foram afetadas.
 
-Os limites de quando as mensagens são descartadas pode ser configurado com
-RateLimitInterval= e RateLimitBurst= no
+Os controles de limites de quando as mensagens são descartadas pode ser
+configurado com RateLimitInterval= e RateLimitBurst= no
 /etc/systemd/journald.conf. Veja journald.conf(5) para detalhes.
 
 -- e9bf28e6e834481bb6f48f548ad13606
@@ -86,7 +86,7 @@ Uma nova sessão com o ID @SESSION_ID@ foi criada para o usuário @USER_ID at .
 O processo originador da sessão é @LEADER at .
 
 -- 3354939424b4456d9802ca8333ed424a
-Subject: A sessão @SESSION_ID@ foi terminada
+Subject: Sessão @SESSION_ID@ foi terminada
 Defined-By: systemd
 Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
@@ -102,7 +102,7 @@ Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
 Um novo seat @SEAT_ID@ foi configurado e está disponível.
 
 -- e7852bfe46784ed0accde04bc864c2d5
-Subject: Um seat @SEAT_ID@ foi removido agora
+Subject: Seat @SEAT_ID@ foi removido agora
 Defined-By: systemd
 Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
@@ -224,7 +224,7 @@ Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 
 O processo @EXECUTABLE@ não pôde ser executado e falhou.
 
-O número de erro retornado enquanto executava este processo foi @ERRNO at .
+O número de erro retornado por este processo é @ERRNO at .
 
 -- 0027229ca0644181a76c4e92458afa2e
 Subject: Uma ou mais mensagens não puderam ser encaminhadas para o syslog

commit 3da7a50f847ce5ea6094927cb51bab7eb1818efd
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Tue Jan 20 23:09:58 2015 -0500

    shared/cgroup-show: simplify show_pid_array()
    
    int[] should not be used as pid_t[], even if happens to be same thing.
    Also deduplicating in a quadratic loop right before sorting is unnecessary.
    Remove custom greedy_realloc implementation.

diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index c862ee9..1e14ba6 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -40,30 +40,20 @@ static int compare(const void *a, const void *b) {
         return 0;
 }
 
-static void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
-        unsigned i, m, pid_width;
-        pid_t biggest = 0;
+static void show_pid_array(pid_t pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
+        unsigned i, j, pid_width;
 
-        /* Filter duplicates */
-        m = 0;
-        for (i = 0; i < n_pids; i++) {
-                unsigned j;
-
-                if (pids[i] > biggest)
-                        biggest = pids[i];
-
-                for (j = i+1; j < n_pids; j++)
-                        if (pids[i] == pids[j])
-                                break;
+        assert(n_pids > 0);
+        qsort(pids, n_pids, sizeof(pid_t), compare);
 
-                if (j >= n_pids)
-                        pids[m++] = pids[i];
+        /* Filter duplicates */
+        for (j = 0, i = 1; i < n_pids; i++) {
+                if (pids[i] == pids[j])
+                        continue;
+                pids[++j] = pids[i];
         }
-        n_pids = m;
-        pid_width = DECIMAL_STR_WIDTH(biggest);
-
-        /* And sort */
-        qsort_safe(pids, n_pids, sizeof(pid_t), compare);
+        n_pids = j + 1;
+        pid_width = DECIMAL_STR_WIDTH(pids[j]);
 
         if (flags & OUTPUT_FULL_WIDTH)
                 n_columns = 0;
@@ -83,10 +73,7 @@ static void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsi
                 else
                         printf("%s%s", prefix, draw_special_char(((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)));
 
-                printf("%*lu %s\n",
-                       pid_width,
-                       (unsigned long) pids[i],
-                       strna(t));
+                printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
         }
 }
 
@@ -114,17 +101,8 @@ static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigne
                 if (!kernel_threads && is_kernel_thread(pid) > 0)
                         continue;
 
-                if (n >= n_allocated) {
-                        pid_t *npids;
-
-                        n_allocated = MAX(16U, n*2U);
-
-                        npids = realloc(pids, sizeof(pid_t) * n_allocated);
-                        if (!npids)
-                                return -ENOMEM;
-
-                        pids = npids;
-                }
+                if (!GREEDY_REALLOC(pids, n_allocated, n + 1))
+                        return -ENOMEM;
 
                 assert(n < n_allocated);
                 pids[n++] = pid;
diff --git a/src/shared/util.h b/src/shared/util.h
index 179c961..bfa5633 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -45,12 +45,13 @@
 #include <sys/inotify.h>
 
 #if SIZEOF_PID_T == 4
-#  define PID_FMT "%" PRIi32
+#  define PID_PRI PRIi32
 #elif SIZEOF_PID_T == 2
-#  define PID_FMT "%" PRIi16
+#  define PID_PRI PRIi16
 #else
 #  error Unknown pid_t size
 #endif
+#define PID_FMT "%" PID_PRI
 
 #if SIZEOF_UID_T == 4
 #  define UID_FMT "%" PRIu32

commit 1fa2f38f0f011010bf57522b42fcc168856a7003
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Tue Jan 20 22:22:15 2015 -0500

    Assorted format fixes
    
    Types used for pids and uids in various interfaces are unpredictable.
    Too bad.

diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index f7f3388..f6ac0c0 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -1129,7 +1129,7 @@ static void dump_items(PolicyItem *items, const char *prefix) {
 
                         user = uid_to_name(i->uid);
 
-                        printf("%sUser: %s (%d)\n",
+                        printf("%sUser: %s ("UID_FMT")\n",
                                prefix, strna(user), i->uid);
                 }
 
@@ -1138,7 +1138,7 @@ static void dump_items(PolicyItem *items, const char *prefix) {
 
                         group = gid_to_name(i->gid);
 
-                        printf("%sGroup: %s (%d)\n",
+                        printf("%sGroup: %s ("GID_FMT")\n",
                                prefix, strna(group), i->gid);
                 }
                 printf("%s-\n", prefix);
diff --git a/src/core/automount.c b/src/core/automount.c
index 90beb4d..51f7373 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -758,7 +758,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
 
                         get_process_comm(packet.v5_packet.pid, &p);
                         log_unit_info(UNIT(a)->id,
-                                       "Got automount request for %s, triggered by "PID_FMT" (%s)",
+                                       "Got automount request for %s, triggered by %"PRIu32" (%s)",
                                        a->where, packet.v5_packet.pid, strna(p));
                 } else
                         log_unit_debug(UNIT(a)->id, "Got direct mount request on %s", a->where);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 6181ba8..8ba665d 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -407,7 +407,7 @@ static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *us
 
         u = manager_get_unit_by_pid(m, pid);
         if (!u)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
+                return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
 
         r = mac_selinux_unit_access_check(u, message, "status", error);
         if (r < 0)
diff --git a/src/core/manager.c b/src/core/manager.c
index 64ff464..947d431 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2215,7 +2215,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
 
         m->n_reloading ++;
 
-        fprintf(f, "current-job-id=%i\n", m->current_job_id);
+        fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id);
         fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
         fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
         fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 4fce30d..ff12208 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -420,7 +420,7 @@ static int trie_store(struct trie *trie, const char *filename) {
         }
 
         log_debug("=== trie on-disk ===");
-        log_debug("size:             %8"PRIu64" bytes", size);
+        log_debug("size:             %8"PRIi64" bytes", size);
         log_debug("header:           %8zu bytes", sizeof(struct trie_header_f));
         log_debug("nodes:            %8"PRIu64" bytes (%8"PRIu64")",
                   t.nodes_count * sizeof(struct trie_node_f), t.nodes_count);
diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
index 76407f7..d9dea8d 100644
--- a/src/journal-remote/journal-remote-parse.c
+++ b/src/journal-remote/journal-remote-parse.c
@@ -37,7 +37,7 @@ void source_free(RemoteSource *source) {
         free(source->buf);
         iovw_free_contents(&source->iovw);
 
-        log_debug("Writer ref count %u", source->writer->n_ref);
+        log_debug("Writer ref count %i", source->writer->n_ref);
         writer_unref(source->writer);
 
         sd_event_source_unref(source->event);
@@ -125,8 +125,8 @@ static int get_line(RemoteSource *source, char **line, size_t *size) {
                          source->size - source->filled);
                 if (n < 0) {
                         if (errno != EAGAIN && errno != EWOULDBLOCK)
-                                log_error_errno(errno, "read(%d, ..., %zd): %m", source->fd,
-                                          source->size - source->filled);
+                                log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
+                                                source->size - source->filled);
                         return -errno;
                 } else if (n == 0)
                         return 0;
@@ -186,8 +186,8 @@ static int fill_fixed_size(RemoteSource *source, void **data, size_t size) {
                          source->size - source->filled);
                 if (n < 0) {
                         if (errno != EAGAIN && errno != EWOULDBLOCK)
-                                log_error_errno(errno, "read(%d, ..., %zd): %m", source->fd,
-                                          source->size - source->filled);
+                                log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
+                                                source->size - source->filled);
                         return -errno;
                 } else if (n == 0)
                         return 0;
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 5050616..244d83d 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -1021,7 +1021,7 @@ static int dispatch_raw_source_event(sd_event_source *event,
                 if (remaining > 0)
                         log_warning("Premature EOF. %zu bytes lost.", remaining);
                 remove_source(s, source->fd);
-                log_info("%zd active sources remaining", s->active);
+                log_info("%zu active sources remaining", s->active);
                 return 0;
         } else if (r == -E2BIG) {
                 log_error("Entry too big, skipped");
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index 50332ed..75bb434 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -296,7 +296,7 @@ static size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *user
                 return 0;
 
         r = read(u->input, buf, size * nmemb);
-        log_debug("%s: allowed %zu, read %zu", __func__, size*nmemb, r);
+        log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, r);
 
         if (r > 0)
                 return r;
@@ -505,15 +505,15 @@ static int perform_upload(Uploader *u) {
         }
 
         if (status >= 300) {
-                log_error("Upload to %s failed with code %lu: %s",
+                log_error("Upload to %s failed with code %ld: %s",
                           u->url, status, strna(u->answer));
                 return -EIO;
         } else if (status < 200) {
-                log_error("Upload to %s finished with unexpected code %lu: %s",
+                log_error("Upload to %s finished with unexpected code %ld: %s",
                           u->url, status, strna(u->answer));
                 return -EIO;
         } else
-                log_debug("Upload finished successfully with code %lu: %s",
+                log_debug("Upload finished successfully with code %ld: %s",
                           status, strna(u->answer));
 
         free(u->last_cursor);
diff --git a/src/journal/compress.c b/src/journal/compress.c
index 9440fcd..6923753 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -356,7 +356,7 @@ int compress_stream_xz(int fdf, int fdt, off_t max_bytes) {
 
         ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64);
         if (ret != LZMA_OK) {
-                log_error("Failed to initialize XZ encoder: code %d", ret);
+                log_error("Failed to initialize XZ encoder: code %u", ret);
                 return -EINVAL;
         }
 
@@ -391,7 +391,7 @@ int compress_stream_xz(int fdf, int fdt, off_t max_bytes) {
 
                 ret = lzma_code(&s, action);
                 if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
-                        log_error("Compression failed: code %d", ret);
+                        log_error("Compression failed: code %u", ret);
                         return -EBADMSG;
                 }
 
@@ -512,7 +512,7 @@ int decompress_stream_xz(int fdf, int fdt, off_t max_bytes) {
 
         ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
         if (ret != LZMA_OK) {
-                log_error("Failed to initialize XZ decoder: code %d", ret);
+                log_error("Failed to initialize XZ decoder: code %u", ret);
                 return -ENOMEM;
         }
 
@@ -538,7 +538,7 @@ int decompress_stream_xz(int fdf, int fdt, off_t max_bytes) {
 
                 ret = lzma_code(&s, action);
                 if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
-                        log_error("Decompression failed: code %d", ret);
+                        log_error("Decompression failed: code %u", ret);
                         return -EBADMSG;
                 }
 
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 56a96c5..65fefd2 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -384,7 +384,7 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
                                 memcpy(buffer + 8 + k - 2, ": ", 2);
                         }
 
-                        snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
+                        snprintf(error, sizeof(error), "ERRNO=%i", _saved_errno_);
                         char_array_0(error);
 
                         IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c
index 9d21738..c2f1545 100644
--- a/src/journal/journald-audit.c
+++ b/src/journal/journald-audit.c
@@ -360,7 +360,7 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
         if (!p)
                 return;
 
-        if (sscanf(p, "(%" PRIi64 ".%" PRIi64 ":%" PRIi64 "):%n",
+        if (sscanf(p, "(%" PRIu64 ".%" PRIu64 ":%" PRIu64 "):%n",
                    &seconds,
                    &msec,
                    &id,
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index dbecad4..65e888a 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1613,7 +1613,7 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
 
         r = client_start(client);
         if (r >= 0)
-                log_dhcp_client(client, "STARTED on ifindex %u", client->index);
+                log_dhcp_client(client, "STARTED on ifindex %i", client->index);
 
         return r;
 }
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index afdf52f..8fba7ac 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -69,7 +69,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
 
         if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
                 fprintf(f,
-                        "%s%s%s Type=%s%s%s  Endian=%c  Flags=%u  Version=%u  Priority=%lli",
+                        "%s%s%s Type=%s%s%s  Endian=%c  Flags=%u  Version=%u  Priority=%"PRIi64,
                         m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
                         m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
                         m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
@@ -77,7 +77,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
                         m->header->endian,
                         m->header->flags,
                         m->header->version,
-                        (long long) m->priority);
+                        m->priority);
 
                 /* Display synthetic message serial number in a more readable
                  * format than (uint32_t) -1 */
diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c
index a16807f..61c7b44 100644
--- a/src/libsystemd/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/sd-hwdb/sd-hwdb.c
@@ -324,7 +324,7 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) {
 
         log_debug("=== trie on-disk ===");
         log_debug("tool version:          %"PRIu64, le64toh(hwdb->head->tool_version));
-        log_debug("file size:        %8"PRIu64" bytes", hwdb->st.st_size);
+        log_debug("file size:        %8"PRIi64" bytes", hwdb->st.st_size);
         log_debug("header size       %8"PRIu64" bytes", le64toh(hwdb->head->header_size));
         log_debug("strings           %8"PRIu64" bytes", le64toh(hwdb->head->strings_len));
         log_debug("nodes             %8"PRIu64" bytes", le64toh(hwdb->head->nodes_len));
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 4846133..1f44c34 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -1366,7 +1366,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
                         if (ucred->pid == 0)
                                 auth = true;
                         else
-                                log_debug("rtnl: ignoring message from pid %u", ucred->pid);
+                                log_debug("rtnl: ignoring message from PID "PID_FMT, ucred->pid);
                 } else if (cmsg->cmsg_level == SOL_NETLINK &&
                            cmsg->cmsg_type == NETLINK_PKTINFO &&
                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 825a0e1..a7446bf 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -1686,7 +1686,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
                                 udev_device->id_filename = NULL;
                 } else if (udev_device_get_ifindex(udev_device) > 0) {
                         /* use netdev ifindex -- n3 */
-                        if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0)
+                        if (asprintf(&udev_device->id_filename, "n%i", udev_device_get_ifindex(udev_device)) < 0)
                                 udev_device->id_filename = NULL;
                 } else {
                         /*
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index da2b634..4cfb2f6 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -620,8 +620,8 @@ retry:
                 }
         } else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL) {
                 if (snl.nl.nl_pid > 0) {
-                        log_debug("multicast kernel netlink message from pid %d ignored",
-                             snl.nl.nl_pid);
+                        log_debug("multicast kernel netlink message from PID %"PRIu32" ignored",
+                                  snl.nl.nl_pid);
                         return NULL;
                 }
         }
@@ -634,7 +634,7 @@ retry:
 
         cred = (struct ucred *)CMSG_DATA(cmsg);
         if (cred->uid != 0) {
-                log_debug("sender uid=%d, message ignored", cred->uid);
+                log_debug("sender uid="UID_FMT", message ignored", cred->uid);
                 return NULL;
         }
 
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 8eb5e3e..197138c 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -201,7 +201,7 @@ int seat_preallocate_vts(Seat *s) {
 
                 q = vt_allocate(i);
                 if (q < 0) {
-                        log_error_errno(q, "Failed to preallocate VT %i: %m", i);
+                        log_error_errno(q, "Failed to preallocate VT %u: %m", i);
                         r = q;
                 }
         }
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index d5b29c8..d7a708f 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -344,7 +344,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
         }
 
         if (seat && !streq(seat, "seat0") && vtnr != 0) {
-                pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %d for %s which is not seat0", vtnr, seat);
+                pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat);
                 vtnr = 0;
         }
 
@@ -367,7 +367,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 
         if (debug)
                 pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
-                           "uid=%u pid=%u service=%s type=%s class=%s desktop=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
+                           "uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
                            pw->pw_uid, getpid(),
                            strempty(service),
                            type, class, strempty(desktop),
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index 5379ffc..274687d 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -73,7 +73,7 @@ static void print_inhibitors(sd_bus *bus) {
         assert_se(r >= 0);
 
         while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
-                printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<"UID_FMT"> pid=<"PID_FMT">\n",
+                printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<%"PRIu32"> pid=<%"PRIu32">\n",
                        what, who, why, mode, uid, pid);
 
                 n++;
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index 1ee1243..d853f17 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -103,7 +103,7 @@ static int specifier_user_name(char specifier, void *data, void *userdata, char
                 if (r < 0)
                         return r;
 
-                if (asprintf(&printed, "%d", uid) < 0)
+                if (asprintf(&printed, UID_FMT, uid) < 0)
                         return -ENOMEM;
                 break;
         }}
diff --git a/src/shared/log.c b/src/shared/log.c
index f8c16de..a870415 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -330,7 +330,7 @@ static int write_to_console(
         highlight = LOG_PRI(level) <= LOG_ERR && show_color;
 
         if (show_location) {
-                snprintf(location, sizeof(location), "(%s:%u) ", file, line);
+                snprintf(location, sizeof(location), "(%s:%i) ", file, line);
                 char_array_0(location);
                 IOVEC_SET_STRING(iovec[n++], location);
         }
@@ -1050,7 +1050,7 @@ void log_received_signal(int level, const struct signalfd_siginfo *si) {
                 get_process_comm(si->ssi_pid, &p);
 
                 log_full(level,
-                         "Received SIG%s from PID "PID_FMT" (%s).",
+                         "Received SIG%s from PID %"PRIu32" (%s).",
                          signal_to_string(si->ssi_signo),
                          si->ssi_pid, strna(p));
         } else
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index ae14c6b..1064fd5 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -167,7 +167,7 @@ int can_sleep_disk(char **types) {
 
 static int hibernation_partition_size(size_t *size, size_t *used) {
         _cleanup_fclose_ FILE *f;
-        int i;
+        unsigned i;
 
         assert(size);
         assert(used);
@@ -190,8 +190,8 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
                 k = fscanf(f,
                            "%ms "   /* device/file */
                            "%ms "   /* type of swap */
-                           "%zd "   /* swap size */
-                           "%zd "   /* used */
+                           "%zu "   /* swap size */
+                           "%zu "   /* used */
                            "%*i\n", /* priority */
                            &dev, &type, &size_field, &used_field);
                 if (k != 4) {
diff --git a/src/shared/util.h b/src/shared/util.h
index 2d03ac8..179c961 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -69,7 +69,7 @@
 #endif
 
 #if SIZEOF_TIME_T == 8
-#  define PRI_TIME PRIu64
+#  define PRI_TIME PRIi64
 #elif SIZEOF_TIME_T == 4
 #  define PRI_TIME PRIu32
 #else
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index c02a76c..cdc1a50 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3399,7 +3399,7 @@ static void print_status_info(
                         continue;
 
                 argv = strv_join(p->argv, " ");
-                printf("  Process: %u %s=%s ", p->pid, p->name, strna(argv));
+                printf("  Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
 
                 good = is_clean_exit_lsb(p->code, p->status, NULL);
                 if (!good) {
@@ -4292,7 +4292,7 @@ static int get_unit_dbus_path_by_pid(
                         &reply,
                         "u", pid);
         if (r < 0) {
-                log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
+                log_error("Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
                 return r;
         }
 
diff --git a/src/test/test-strxcpyx.c b/src/test/test-strxcpyx.c
index cb23092..a7c8e12 100644
--- a/src/test/test-strxcpyx.c
+++ b/src/test/test-strxcpyx.c
@@ -48,7 +48,7 @@ static void test_strpcpyf(void) {
         size_t space_left;
 
         space_left = sizeof(target);
-        space_left = strpcpyf(&s, space_left, "space left: %zd. ", space_left);
+        space_left = strpcpyf(&s, space_left, "space left: %zu. ", space_left);
         space_left = strpcpyf(&s, space_left, "foo%s", "bar");
 
         assert_se(streq(target, "space left: 25. foobar"));
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 8471d31..a37316b 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -603,7 +603,7 @@ static void test_get_process_comm(void) {
 
         r = get_process_environ(me, &env);
         assert_se(r >= 0 || r == -EACCES);
-        log_info("self strlen(environ): '%zd'", strlen(env));
+        log_info("self strlen(environ): '%zu'", strlen(env));
 
         if (!detect_container(NULL))
                 assert_se(get_ctty_devnr(1, &h) == -ENOENT);
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index 548985e..03e3dc2 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -273,7 +273,7 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
         if (err < 0)
                 goto out;
 
-        log_debug("probe %s %sraid offset=%"PRIu64,
+        log_debug("probe %s %sraid offset=%"PRIi64,
                   udev_device_get_devnode(dev),
                   noraid ? "no" : "", offset);
 
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 26c7232..46f1c53 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -111,7 +111,7 @@ static void get_cap_mask(struct udev_device *dev,
 
         if (test) {
                 /* printf pattern with the right unsigned long number of hex chars */
-                snprintf(text, sizeof(text), "  bit %%4u: %%0%zilX\n", 2 * sizeof(unsigned long));
+                snprintf(text, sizeof(text), "  bit %%4u: %%0%zulX\n", 2 * sizeof(unsigned long));
                 log_debug("%s decoded bit map:", attr);
                 val = bitmask_size / sizeof (unsigned long);
                 /* skip over leading zeros */
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index 118e797..d8ee4cb 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -28,17 +28,17 @@
 
 #include "udev.h"
 
-static const struct key *keyboard_lookup_key(const char *str, unsigned int len);
+static const struct key *keyboard_lookup_key(const char *str, unsigned len);
 #include "keyboard-keys-from-name.h"
 #include "keyboard-keys-to-name.h"
 
-static int install_force_release(struct udev_device *dev, const unsigned int *release, unsigned int release_count) {
+static int install_force_release(struct udev_device *dev, const unsigned *release, unsigned release_count) {
         struct udev_device *atkbd;
         const char *cur;
         char codes[4096];
         char *s;
         size_t l;
-        unsigned int i;
+        unsigned i;
         int ret;
 
         atkbd = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL);
@@ -57,7 +57,7 @@ static int install_force_release(struct udev_device *dev, const unsigned int *re
 
         /* append new codes */
         for (i = 0; i < release_count; i++)
-                l = strpcpyf(&s, l, ",%d", release[i]);
+                l = strpcpyf(&s, l, ",%u", release[i]);
 
         log_debug("keyboard: updating force-release list with '%s'", codes);
         ret = udev_device_set_sysattr_value(atkbd, "force_release", codes);
@@ -69,16 +69,16 @@ static int install_force_release(struct udev_device *dev, const unsigned int *re
 static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
         struct udev_list_entry *entry;
         struct {
-                unsigned int scan;
-                unsigned int key;
+                unsigned scan;
+                unsigned key;
         } map[1024];
-        unsigned int map_count = 0;
-        unsigned int release[1024];
-        unsigned int release_count = 0;
+        unsigned map_count = 0;
+        unsigned release[1024];
+        unsigned release_count = 0;
 
         udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) {
                 const char *key;
-                unsigned int scancode, keycode_num;
+                unsigned scancode, keycode_num;
                 char *endptr;
                 const char *keycode;
                 const struct key *k;
@@ -130,7 +130,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
         if (map_count > 0 || release_count > 0) {
                 const char *node;
                 int fd;
-                unsigned int i;
+                unsigned i;
 
                 node = udev_device_get_devnode(dev);
                 if (!node) {
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 2e08467..c310111 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -191,12 +191,12 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
         s = names->pci_path;
         l = sizeof(names->pci_path);
         if (domain > 0)
-                l = strpcpyf(&s, l, "P%d", domain);
-        l = strpcpyf(&s, l, "p%ds%d", bus, slot);
+                l = strpcpyf(&s, l, "P%u", domain);
+        l = strpcpyf(&s, l, "p%us%u", bus, slot);
         if (func > 0 || is_pci_multifunction(names->pcidev))
-                l = strpcpyf(&s, l, "f%d", func);
+                l = strpcpyf(&s, l, "f%u", func);
         if (dev_port > 0)
-                l = strpcpyf(&s, l, "d%d", dev_port);
+                l = strpcpyf(&s, l, "d%u", dev_port);
         if (l == 0)
                 names->pci_path[0] = '\0';
 
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index 9cece4a..538b342 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -198,7 +198,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) {
                 goto err;
         }
         if (ucred.uid > 0) {
-                log_error("sender uid=%i, message ignored", ucred.uid);
+                log_error("sender uid="UID_FMT", message ignored", ucred.uid);
                 goto err;
         }
 
@@ -386,7 +386,7 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) {
         }
 
         if (cred->uid != 0) {
-                log_error("sender uid=%i, message ignored", cred->uid);
+                log_error("sender uid="UID_FMT", message ignored", cred->uid);
                 goto err;
         }
 
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 6b18430..beb0943 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -218,14 +218,14 @@ subst:
                 case SUBST_MAJOR: {
                         char num[UTIL_PATH_SIZE];
 
-                        sprintf(num, "%d", major(udev_device_get_devnum(dev)));
+                        sprintf(num, "%u", major(udev_device_get_devnum(dev)));
                         l = strpcpy(&s, l, num);
                         break;
                 }
                 case SUBST_MINOR: {
                         char num[UTIL_PATH_SIZE];
 
-                        sprintf(num, "%d", minor(udev_device_get_devnum(dev)));
+                        sprintf(num, "%u", minor(udev_device_get_devnum(dev)));
                         l = strpcpy(&s, l, num);
                         break;
                 }
@@ -509,7 +509,7 @@ static void spawn_read(struct udev_event *event,
                                                 memcpy(&result[respos], buf, count);
                                                 respos += count;
                                         } else {
-                                                log_error("'%s' ressize %zd too short", cmd, ressize);
+                                                log_error("'%s' ressize %zu too short", cmd, ressize);
                                         }
                                 }
 
@@ -580,7 +580,7 @@ static int spawn_wait(struct udev_event *event,
                         goto out;
                 }
                 if (fdcount == 0) {
-                        log_warning("slow: '%s' [%u]", cmd, pid);
+                        log_warning("slow: '%s' ["PID_FMT"]", cmd, pid);
 
                         fdcount = poll(pfd, 1, timeout);
                         if (fdcount < 0) {
@@ -591,7 +591,7 @@ static int spawn_wait(struct udev_event *event,
                                 goto out;
                         }
                         if (fdcount == 0) {
-                                log_error("timeout: killing '%s' [%u]", cmd, pid);
+                                log_error("timeout: killing '%s' ["PID_FMT"]", cmd, pid);
                                 kill(pid, SIGKILL);
                         }
                 }
@@ -613,20 +613,20 @@ static int spawn_wait(struct udev_event *event,
                                 if (waitpid(pid, &status, WNOHANG) < 0)
                                         break;
                                 if (WIFEXITED(status)) {
-                                        log_debug("'%s' [%u] exit with return code %i", cmd, pid, WEXITSTATUS(status));
+                                        log_debug("'%s' ["PID_FMT"] exit with return code %i", cmd, pid, WEXITSTATUS(status));
                                         if (WEXITSTATUS(status) != 0)
                                                 err = -1;
                                 } else if (WIFSIGNALED(status)) {
-                                        log_error("'%s' [%u] terminated by signal %i (%s)", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
+                                        log_error("'%s' ["PID_FMT"] terminated by signal %i (%s)", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
                                         err = -1;
                                 } else if (WIFSTOPPED(status)) {
-                                        log_error("'%s' [%u] stopped", cmd, pid);
+                                        log_error("'%s' ["PID_FMT"] stopped", cmd, pid);
                                         err = -1;
                                 } else if (WIFCONTINUED(status)) {
-                                        log_error("'%s' [%u] continued", cmd, pid);
+                                        log_error("'%s' ["PID_FMT"] continued", cmd, pid);
                                         err = -1;
                                 } else {
-                                        log_error("'%s' [%u] exit with status 0x%04x", cmd, pid, status);
+                                        log_error("'%s' ["PID_FMT"] exit with status 0x%04x", cmd, pid, status);
                                         err = -1;
                                 }
                                 pid = 0;
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 499feef..793b484 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -341,7 +341,7 @@ void udev_node_add(struct udev_device *dev, bool apply,
         char filename[UTIL_PATH_SIZE];
         struct udev_list_entry *list_entry;
 
-        log_debug("handling device node '%s', devnum=%s, mode=%#o, uid=%d, gid=%d",
+        log_debug("handling device node '%s', devnum=%s, mode=%#o, uid="UID_FMT", gid="GID_FMT,
                   udev_device_get_devnode(dev), udev_device_get_id_filename(dev), mode, uid, gid);
 
         if (node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list) < 0)
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 7a2114a..d65e40c 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -401,7 +401,7 @@ static int trie_store(struct trie *trie, const char *filename) {
         }
 
         log_debug("=== trie on-disk ===");
-        log_debug("size:             %8"PRIu64" bytes", size);
+        log_debug("size:             %8"PRIi64" bytes", size);
         log_debug("header:           %8zu bytes", sizeof(struct trie_header_f));
         log_debug("nodes:            %8"PRIu64" bytes (%8"PRIu64")",
                   t.nodes_count * sizeof(struct trie_node_f), t.nodes_count);
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index f52a03d..0bab01a 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -162,12 +162,12 @@ static int stat_device(const char *name, bool export, const char *prefix) {
         if (export) {
                 if (prefix == NULL)
                         prefix = "INFO_";
-                printf("%sMAJOR=%d\n"
-                       "%sMINOR=%d\n",
+                printf("%sMAJOR=%u\n"
+                       "%sMINOR=%u\n",
                        prefix, major(statbuf.st_dev),
                        prefix, minor(statbuf.st_dev));
         } else
-                printf("%d:%d\n", major(statbuf.st_dev), minor(statbuf.st_dev));
+                printf("%u:%u\n", major(statbuf.st_dev), minor(statbuf.st_dev));
         return 0;
 }
 
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 009e395..009e2fe 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -158,7 +158,7 @@ static void worker_unref(struct worker *worker) {
         worker->refcount--;
         if (worker->refcount > 0)
                 return;
-        log_debug("worker [%u] cleaned up", worker->pid);
+        log_debug("worker ["PID_FMT"] cleaned up", worker->pid);
         worker_cleanup(worker);
 }
 
@@ -414,7 +414,7 @@ out:
                 event->state = EVENT_RUNNING;
                 udev_list_node_append(&worker->node, &worker_list);
                 children++;
-                log_debug("seq %llu forked new worker [%u]", udev_device_get_seqnum(event->dev), pid);
+                log_debug("seq %llu forked new worker ["PID_FMT"]", udev_device_get_seqnum(event->dev), pid);
                 break;
         }
 }
@@ -431,7 +431,8 @@ static void event_run(struct event *event) {
 
                 count = udev_monitor_send_device(monitor, worker->monitor, event->dev);
                 if (count < 0) {
-                        log_error_errno(errno, "worker [%u] did not accept message %zi (%m), kill it", worker->pid, count);
+                        log_error_errno(errno, "worker ["PID_FMT"] did not accept message %zi (%m), kill it",
+                                        worker->pid, count);
                         kill(worker->pid, SIGKILL);
                         worker->state = WORKER_KILLED;
                         continue;
@@ -869,26 +870,26 @@ static void handle_signal(struct udev *udev, int signo) {
 
                                 if (worker->pid != pid)
                                         continue;
-                                log_debug("worker [%u] exit", pid);
+                                log_debug("worker ["PID_FMT"] exit", pid);
 
                                 if (WIFEXITED(status)) {
                                         if (WEXITSTATUS(status) != 0)
-                                                log_error("worker [%u] exit with return code %i",
+                                                log_error("worker ["PID_FMT"] exit with return code %i",
                                                           pid, WEXITSTATUS(status));
                                 } else if (WIFSIGNALED(status)) {
-                                        log_error("worker [%u] terminated by signal %i (%s)",
+                                        log_error("worker ["PID_FMT"] terminated by signal %i (%s)",
                                                   pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
                                 } else if (WIFSTOPPED(status)) {
-                                        log_error("worker [%u] stopped", pid);
+                                        log_error("worker ["PID_FMT"] stopped", pid);
                                 } else if (WIFCONTINUED(status)) {
-                                        log_error("worker [%u] continued", pid);
+                                        log_error("worker ["PID_FMT"] continued", pid);
                                 } else {
-                                        log_error("worker [%u] exit with status 0x%04x", pid, status);
+                                        log_error("worker ["PID_FMT"] exit with status 0x%04x", pid, status);
                                 }
 
                                 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
                                         if (worker->event) {
-                                                log_error("worker [%u] failed while handling '%s'",
+                                                log_error("worker ["PID_FMT"] failed while handling '%s'",
                                                           pid, worker->event->devpath);
                                                 worker->event->exitcode = -32;
                                                 event_queue_delete(worker->event);
@@ -1409,7 +1410,7 @@ int main(int argc, char *argv[]) {
 
                                 if ((ts - worker->event_start_usec) > arg_event_timeout_warn_usec) {
                                         if ((ts - worker->event_start_usec) > arg_event_timeout_usec) {
-                                                log_error("worker [%u] %s timeout; kill it", worker->pid, worker->event->devpath);
+                                                log_error("worker ["PID_FMT"] %s timeout; kill it", worker->pid, worker->event->devpath);
                                                 kill(worker->pid, SIGKILL);
                                                 worker->state = WORKER_KILLED;
 
@@ -1420,7 +1421,7 @@ int main(int argc, char *argv[]) {
                                                 event_queue_delete(worker->event);
                                                 worker->event = NULL;
                                         } else if (!worker->event_warned) {
-                                                log_warning("worker [%u] %s is taking a long time", worker->pid, worker->event->devpath);
+                                                log_warning("worker ["PID_FMT"] %s is taking a long time", worker->pid, worker->event->devpath);
                                                 worker->event_warned = true;
                                         }
                                 }

commit 8facc3498ed037f842891ff55d1f60fe834f4ba0
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Wed Jan 21 23:47:37 2015 -0500

    Fix some format strings for enums, they are signed

diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index c1b5404..ec12e89 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -323,7 +323,7 @@ static int journal_file_verify_header(JournalFile *f) {
                 } else if (state == STATE_ARCHIVED)
                         return -ESHUTDOWN;
                 else if (state != STATE_OFFLINE) {
-                        log_debug("Journal file %s has unknown state %u.", f->path, state);
+                        log_debug("Journal file %s has unknown state %i.", f->path, state);
                         return -EBUSY;
                 }
         }
@@ -2417,7 +2417,7 @@ void journal_file_dump(JournalFile *f) {
                         break;
 
                 default:
-                        printf("Type: unknown (%u)\n", o->object.type);
+                        printf("Type: unknown (%i)\n", o->object.type);
                         break;
                 }
 
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index 5dd2307..babfed8 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1268,7 +1268,7 @@ int bus_add_match_internal_kernel(
                         if (c->type - BUS_MATCH_ARG < 3)
                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
 
-                        snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
+                        snprintf(buf, sizeof(buf), "arg%i", c->type - BUS_MATCH_ARG);
                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
                         using_bloom = true;
                         break;
@@ -1277,7 +1277,7 @@ int bus_add_match_internal_kernel(
                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
 
-                        snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
+                        snprintf(buf, sizeof(buf), "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
                         using_bloom = true;
                         break;
@@ -1286,7 +1286,7 @@ int bus_add_match_internal_kernel(
                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
 
-                        snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
+                        snprintf(buf, sizeof(buf), "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
                         using_bloom = true;
                         break;
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 06a7a4b..4846133 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -1476,7 +1476,7 @@ int socket_read_message(sd_rtnl *rtnl) {
                 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
                 if (r < 0) {
                         if (r == -ENOTSUP)
-                                log_debug("sd-rtnl: ignored message with unknown type: %u",
+                                log_debug("sd-rtnl: ignored message with unknown type: %i",
                                           new_msg->nlmsg_type);
 
                         continue;
diff --git a/src/shared/util.h b/src/shared/util.h
index fa16d52..2d03ac8 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -380,7 +380,7 @@ static inline uint32_t random_u32(void) {
                         if (!s)                                         \
                                 return log_oom();                       \
                 } else {                                                \
-                        r = asprintf(&s, "%u", i);                      \
+                        r = asprintf(&s, "%i", i);                      \
                         if (r < 0)                                      \
                                 return log_oom();                       \
                 }                                                       \

commit 213c305a2ff44c4b2ea7d0c96dd64be010ac797d
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Wed Jan 21 23:35:19 2015 -0500

    shared/util: use signed printf format for PIDs
    
    gcc 5 started warning about this.

diff --git a/src/shared/util.h b/src/shared/util.h
index bb2c101..fa16d52 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -45,9 +45,9 @@
 #include <sys/inotify.h>
 
 #if SIZEOF_PID_T == 4
-#  define PID_FMT "%" PRIu32
+#  define PID_FMT "%" PRIi32
 #elif SIZEOF_PID_T == 2
-#  define PID_FMT "%" PRIu16
+#  define PID_FMT "%" PRIi16
 #else
 #  error Unknown pid_t size
 #endif



More information about the systemd-commits mailing list