[systemd-commits] 8 commits - man/custom-html.xsl man/systemd-nspawn.xml src/core src/fsck src/journal src/journal-remote src/libsystemd src/libsystemd-terminal src/shared src/timedate src/tmpfiles units/systemd-backlight at .service.in units/systemd-journal-catalog-update.service.in units/systemd-journal-flush.service.in

Zbigniew Jędrzejewski-Szmek zbyszek at kemper.freedesktop.org
Sun Feb 1 14:28:53 PST 2015


 man/custom-html.xsl                             |   12 ++++
 man/systemd-nspawn.xml                          |    4 +
 src/core/automount.c                            |   12 +---
 src/core/job.c                                  |    1 
 src/core/load-fragment.c                        |    9 ++-
 src/core/main.c                                 |    7 +-
 src/core/selinux-access.c                       |   14 ++--
 src/core/unit.c                                 |    1 
 src/fsck/fsck.c                                 |    5 -
 src/journal-remote/journal-remote.c             |    4 -
 src/journal-remote/journal-upload-journal.c     |    2 
 src/journal/journal-send.c                      |   18 ++----
 src/journal/journald-console.c                  |    9 +--
 src/journal/journald-kmsg.c                     |    9 +--
 src/journal/journald-server.c                   |    2 
 src/journal/journald-stream.c                   |    4 -
 src/journal/journald-syslog.c                   |    9 +--
 src/journal/sd-journal.c                        |    3 -
 src/libsystemd-terminal/subterm.c               |    8 +-
 src/libsystemd/sd-bus/bus-control.c             |    6 +-
 src/libsystemd/sd-bus/bus-socket.c              |    8 +-
 src/shared/capability.c                         |   33 +++++------
 src/shared/log.c                                |   26 +++-----
 src/shared/spawn-polkit-agent.c                 |    5 -
 src/shared/switch-root.c                        |    1 
 src/shared/util.h                               |   14 ++++
 src/timedate/timedatectl.c                      |   67 +++++++++-------------
 src/tmpfiles/tmpfiles.c                         |   72 ++++++++++++++++--------
 units/systemd-backlight at .service.in             |    1 
 units/systemd-journal-catalog-update.service.in |    1 
 units/systemd-journal-flush.service.in          |    1 
 31 files changed, 192 insertions(+), 176 deletions(-)

New commits:
commit 74a6d87d0cd1f2213869e168b6ca55eded6f4ae8
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Feb 1 16:05:56 2015 -0500

    man: switch yum to dnf for Fedora
    
    The dnf name is here to stay, we might as well adjust.

diff --git a/man/custom-html.xsl b/man/custom-html.xsl
index 8bcc5f9..32299db 100644
--- a/man/custom-html.xsl
+++ b/man/custom-html.xsl
@@ -60,6 +60,18 @@
   </a>
 </xsl:template>
 
+<xsl:template match="citerefentry[@project='mankier']">
+  <a>
+    <xsl:attribute name="href">
+      <xsl:text>https://www.mankier.com/</xsl:text>
+      <xsl:value-of select="manvolnum"/>
+      <xsl:text>/</xsl:text>
+      <xsl:value-of select="refentrytitle"/>
+    </xsl:attribute>
+    <xsl:call-template name="inline.charseq"/>
+  </a>
+</xsl:template>
+
 <xsl:template match="citerefentry[@project='archlinux']">
   <a>
     <xsl:attribute name="href">
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index b0f7aa3..4b7ec1d 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -103,6 +103,7 @@
                 in a container.</para>
 
                 <para>Use a tool like
+                <citerefentry project='mankier'><refentrytitle>dnf</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                 <citerefentry project='die-net'><refentrytitle>yum</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                 <citerefentry project='die-net'><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                 or
@@ -861,7 +862,7 @@
                 <example>
                         <title>Build and boot a minimal Fedora distribution in a container</title>
 
-                        <programlisting># yum -y --releasever=21 --nogpg --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal
+                        <programlisting># dnf -y --releasever=21 --nogpg --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora install systemd passwd dnf fedora-release vim-minimal
 # systemd-nspawn -bD /srv/mycontainer</programlisting>
 
                         <para>This installs a minimal Fedora distribution into
@@ -926,6 +927,7 @@
                 <para>
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
                         <citerefentry project='man-pages'><refentrytitle>chroot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+                        <citerefentry project='mankier'><refentrytitle>dnf</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry project='die-net'><refentrytitle>yum</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry project='die-net'><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry project='archlinux'><refentrytitle>pacman</refentrytitle><manvolnum>8</manvolnum></citerefentry>,

commit 7d328b544621d4b1bec936dec612947ad8bfb65a
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Feb 1 15:26:46 2015 -0500

    shared/capability: go frugal on space for caps

diff --git a/src/shared/capability.c b/src/shared/capability.c
index dcf7ce1..3f2f27e 100644
--- a/src/shared/capability.c
+++ b/src/shared/capability.c
@@ -269,11 +269,12 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
                 return log_oom();
 
         if (keep_capabilities) {
-                cap_value_t bits[sizeof(keep_capabilities)*8];
+                cap_value_t bits[log2u64(keep_capabilities)];
 
-                for (i = 0; i < sizeof(keep_capabilities)*8; i++)
+                for (i = 0; i < ELEMENTSOF(bits); i++)
                         if (keep_capabilities & (1ULL << i))
                                 bits[j++] = i;
+                assert((keep_capabilities & (~1ULL << i)) == 0);
 
                 if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 ||
                     cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0) {
diff --git a/src/shared/util.h b/src/shared/util.h
index 5312422..410ce65 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -860,7 +860,7 @@ static inline unsigned u32ctz(uint32_t n) {
 #endif
 }
 
-static inline int log2i(int x) {
+static inline unsigned log2i(int x) {
         assert(x > 0);
 
         return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1;
@@ -872,6 +872,16 @@ static inline unsigned log2u(unsigned x) {
         return sizeof(unsigned) * 8 - __builtin_clz(x) - 1;
 }
 
+static inline unsigned log2u64(uint64_t x) {
+        assert(x > 0);
+
+#if __SIZEOF_LONG_LONG__ == 8
+        return 64 - __builtin_clzll(x) - 1;
+#else
+#error "Wut?"
+#endif
+}
+
 static inline unsigned log2u_round_up(unsigned x) {
         assert(x > 0);
 

commit 51ddf61540976fc7b09ce5ace707b27f3acc3871
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Feb 1 14:33:10 2015 -0500

    Fix dropping of all capabilities
    
    From fd.o bug 88898:
    
    systemd-resolved fails to start:
    Failed to drop capabilities: Operation not permitted
    
    Broken in f11943c53ec181829a821c6b27acf828bab71caa.
    
    Drop all capabilities:
    1. prctl(PR_SET_KEEPCAPS, keep_capabilities != 0) // 0 when we drop all
    capabilities
    2. setresuid() // bye bye capabilities
    3. Add CAP_SETPCAP // fails because we have no capabilities
    4. Reduce capability bounding set
    5. Drop capabilities
    6. prctl(PR_SET_KEEPCAPS, 0)
    
    Capabilites should always be kept after setresuid() so that the capability
    bounding set can be reduced.
    
    Based-on-a-patch-by: mustrumr97 at gmail.com
    
    https://bugs.freedesktop.org/show_bug.cgi?id=88898
    
    We must be careful not to leave PR_SET_KEEPCAPS on. We could use the
    setresuid() call to drop capabilities, but the rules when capabilities
    are dropped are fairly complex, since a transition to non-zero uid must
    happen. Let's instead keep the capabilities during setresuid(), and drop
    them later.

diff --git a/src/shared/capability.c b/src/shared/capability.c
index b39e8e2..dcf7ce1 100644
--- a/src/shared/capability.c
+++ b/src/shared/capability.c
@@ -230,7 +230,6 @@ int capability_bounding_set_drop_usermode(uint64_t drop) {
 }
 
 int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
-        cap_value_t bits[sizeof(keep_capabilities)*8];
         _cleanup_cap_free_ cap_t d = NULL;
         unsigned i, j = 0;
         int r;
@@ -248,8 +247,8 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
         if (setgroups(0, NULL) < 0)
                 return log_error_errno(errno, "Failed to drop auxiliary groups list: %m");
 
-        /* Ensure we keep the permitted caps across the setresuid(), if we need them */
-        if (prctl(PR_SET_KEEPCAPS, keep_capabilities != 0) < 0)
+        /* Ensure we keep the permitted caps across the setresuid() */
+        if (prctl(PR_SET_KEEPCAPS, 1) < 0)
                 return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
 
         r = setresuid(uid, uid, uid);
@@ -264,26 +263,27 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
         if (r < 0)
                 return log_error_errno(r, "Failed to drop capabilities: %m");
 
-        if (keep_capabilities == 0) /* All is gone, we can exit early */
-                return 0;
-
         /* Now upgrade the permitted caps we still kept to effective caps */
         d = cap_init();
         if (!d)
                 return log_oom();
 
-        for (i = 0; i < sizeof(keep_capabilities)*8; i++)
-                if (keep_capabilities & (1ULL << i))
-                        bits[j++] = i;
+        if (keep_capabilities) {
+                cap_value_t bits[sizeof(keep_capabilities)*8];
 
-        if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 ||
-            cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0) {
-                log_error_errno(errno, "Failed to enable capabilities bits: %m");
-                return -errno;
-        }
+                for (i = 0; i < sizeof(keep_capabilities)*8; i++)
+                        if (keep_capabilities & (1ULL << i))
+                                bits[j++] = i;
 
-        if (cap_set_proc(d) < 0)
-                return log_error_errno(errno, "Failed to increase capabilities: %m");
+                if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 ||
+                    cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0) {
+                        log_error_errno(errno, "Failed to enable capabilities bits: %m");
+                        return -errno;
+                }
+
+                if (cap_set_proc(d) < 0)
+                        return log_error_errno(errno, "Failed to increase capabilities: %m");
+        }
 
         return 0;
 }

commit 615938651d3a4fd9253b08da00db22d451a8cef8
Author: Michael Olbrich <m.olbrich at pengutronix.de>
Date:   Fri Jan 30 09:49:55 2015 +0100

    config_parse_set_status: put signals in the correct set
    
    This was broken when the code was rearranged in "1e2fd62d70ff
    core/load-fragment.c: correct argument sign and split up long lines"

diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 98794bf..90bf563 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3150,6 +3150,7 @@ int config_parse_set_status(
         FOREACH_WORD(word, l, rvalue, state) {
                 _cleanup_free_ char *temp;
                 int val;
+                Set **set;
 
                 temp = strndup(word, l);
                 if (!temp)
@@ -3162,21 +3163,23 @@ int config_parse_set_status(
                         if (val <= 0) {
                                 log_syntax(unit, LOG_ERR, filename, line, -val,
                                            "Failed to parse value, ignoring: %s", word);
-                                return 0;
+                                continue;
                         }
+                        set = &status_set->signal;
                 } else {
                         if (val < 0 || val > 255) {
                                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
                                            "Value %d is outside range 0-255, ignoring", val);
                                 continue;
                         }
+                        set = &status_set->status;
                 }
 
-                r = set_ensure_allocated(&status_set->status, NULL);
+                r = set_ensure_allocated(set, NULL);
                 if (r < 0)
                         return log_oom();
 
-                r = set_put(status_set->status, INT_TO_PTR(val));
+                r = set_put(*set, INT_TO_PTR(val));
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, -r,
                                    "Unable to store: %s", word);

commit 5ffa8c818120e35c89becd938d160235c069dd12
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Tue Jan 27 08:00:11 2015 -0500

    Add a snprinf wrapper which checks that the buffer was big enough
    
    If we scale our buffer to be wide enough for the format string, we
    should expect that the calculation was correct.
    
    char_array_0() invocations are removed, since snprintf nul-terminates
    the output in any case.
    
    A similar wrapper is used for strftime calls, but only in timedatectl.c.

diff --git a/src/core/automount.c b/src/core/automount.c
index d47e6fa..9f6bd84 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -449,7 +449,9 @@ int automount_send_ready(Automount *a, int status) {
 static void automount_enter_waiting(Automount *a) {
         _cleanup_close_ int ioctl_fd = -1;
         int p[2] = { -1, -1 };
-        char name[32], options[128];
+        char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
+        char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
+                     + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
         bool mounted = false;
         int r, dev_autofs_fd;
         struct stat st;
@@ -477,12 +479,8 @@ static void automount_enter_waiting(Automount *a) {
                 goto fail;
         }
 
-        snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
-        char_array_0(options);
-
-        snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
-        char_array_0(name);
-
+        xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
+        xsprintf(name, "systemd-"PID_FMT, getpid());
         if (mount(name, a->where, "autofs", 0, options) < 0) {
                 r = -errno;
                 goto fail;
diff --git a/src/core/job.c b/src/core/job.c
index 2129773..4740ff1 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -764,7 +764,6 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
         snprintf(buf, sizeof(buf), format, unit_description(u));
-        char_array_0(buf);
         REENABLE_WARNING;
 
         if (t == JOB_START) {
diff --git a/src/core/main.c b/src/core/main.c
index 0df1f64..02b7c37 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1883,7 +1883,7 @@ finish:
                 args = newa(const char*, args_size);
 
                 if (!switch_root_init) {
-                        char sfd[16];
+                        char sfd[DECIMAL_STR_MAX(int) + 1];
 
                         /* First try to spawn ourselves with the right
                          * path, and with full serialization. We do
@@ -1893,8 +1893,7 @@ finish:
                         assert(arg_serialization);
                         assert(fds);
 
-                        snprintf(sfd, sizeof(sfd), "%i", fileno(arg_serialization));
-                        char_array_0(sfd);
+                        xsprintf(sfd, "%i", fileno(arg_serialization));
 
                         i = 0;
                         args[i++] = SYSTEMD_BINARY_PATH;
@@ -1995,7 +1994,7 @@ finish:
                 assert(command_line[pos] == NULL);
                 env_block = strv_copy(environ);
 
-                snprintf(log_level, sizeof(log_level), "%d", log_get_max_level());
+                xsprintf(log_level, "%d", log_get_max_level());
 
                 switch (log_get_target()) {
                 case LOG_TARGET_KMSG:
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index f638958..1888874 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -64,16 +64,16 @@ static int audit_callback(
         const struct audit_info *audit = auditdata;
         uid_t uid = 0, login_uid = 0;
         gid_t gid = 0;
-        char login_uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a";
-        char uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a";
-        char gid_buf[DECIMAL_STR_MAX(gid_t)] = "n/a";
+        char login_uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a";
+        char uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a";
+        char gid_buf[DECIMAL_STR_MAX(gid_t) + 1] = "n/a";
 
         if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0)
-                snprintf(login_uid_buf, sizeof(login_uid_buf), UID_FMT, login_uid);
+                xsprintf(login_uid_buf, UID_FMT, login_uid);
         if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0)
-                snprintf(uid_buf, sizeof(uid_buf), UID_FMT, uid);
+                xsprintf(uid_buf, UID_FMT, uid);
         if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0)
-                snprintf(gid_buf, sizeof(gid_buf), GID_FMT, gid);
+                xsprintf(gid_buf, GID_FMT, gid);
 
         snprintf(msgbuf, msgbufsize,
                  "auid=%s uid=%s gid=%s%s%s%s%s%s%s",
@@ -81,8 +81,6 @@ static int audit_callback(
                  audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "",
                  audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : "");
 
-        msgbuf[msgbufsize-1] = 0;
-
         return 0;
 }
 
diff --git a/src/core/unit.c b/src/core/unit.c
index 23ad7c1..c3433b2 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1399,7 +1399,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
         snprintf(buf, sizeof(buf), format, unit_description(u));
-        char_array_0(buf);
         REENABLE_WARNING;
 
         mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING :
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 20b7940..78ceeb6 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -222,7 +222,7 @@ int main(int argc, char *argv[]) {
         const char *device, *type;
         bool root_directory;
         int progress_pipe[2] = { -1, -1 };
-        char dash_c[2+10+1];
+        char dash_c[sizeof("-C")-1 + DECIMAL_STR_MAX(int) + 1];
         struct stat st;
 
         if (argc > 2) {
@@ -336,8 +336,7 @@ int main(int argc, char *argv[]) {
                 cmdline[i++] = "-f";
 
         if (progress_pipe[1] >= 0) {
-                snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]);
-                char_array_0(dash_c);
+                xsprintf(dash_c, "-C%i", progress_pipe[1]);
                 cmdline[i++] = dash_c;
         }
 
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 244d83d..f1c409c 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -406,7 +406,7 @@ static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
 static int add_raw_socket(RemoteServer *s, int fd) {
         int r;
         _cleanup_close_ int fd_ = fd;
-        char name[strlen("raw-socket-") + DECIMAL_STR_MAX(int)];
+        char name[sizeof("raw-socket-")-1 + DECIMAL_STR_MAX(int) + 1];
 
         assert(fd >= 0);
 
@@ -416,7 +416,7 @@ static int add_raw_socket(RemoteServer *s, int fd) {
         if (r < 0)
                 return r;
 
-        snprintf(name, sizeof(name), "raw-socket-%d", fd);
+        xsprintf(name, "raw-socket-%d", fd);
 
         r = sd_event_source_set_description(s->listen_event, name);
         if (r < 0)
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index 942320c..5fd639a 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -104,7 +104,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
 
                         r = snprintf(buf + pos, size - pos,
                                      "_BOOT_ID=%s\n", sd_id128_to_string(boot_id, sid));
-                        if (r + pos> size)
+                        if (r + pos > size)
                                 /* not enough space */
                                 return pos;
 
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 65fefd2..1e3a463 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -90,18 +90,17 @@ _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
         /* FIXME: Instead of limiting things to LINE_MAX we could do a
            C99 variable-length array on the stack here in a loop. */
 
-        char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
+        char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1];
+        struct iovec iov[2];
 
         assert_return(priority >= 0, -EINVAL);
         assert_return(priority <= 7, -EINVAL);
         assert_return(format, -EINVAL);
 
-        snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
-        char_array_0(p);
+        xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
 
         memcpy(buffer, "MESSAGE=", 8);
         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
-        char_array_0(buffer);
 
         zero(iov);
         IOVEC_SET_STRING(iov[0], buffer);
@@ -372,7 +371,7 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
                 errno = 0;
                 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
                 if (errno == 0) {
-                        char error[6 + 10 + 1]; /* for a 32bit value */
+                        char error[sizeof("ERRNO=")-1 + DECIMAL_STR_MAX(int) + 1];
 
                         if (j != buffer + 8 + k)
                                 memmove(buffer + 8 + k, j, strlen(j)+1);
@@ -384,8 +383,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=%i", _saved_errno_);
-                        char_array_0(error);
+                        xsprintf(error, "ERRNO=%i", _saved_errno_);
 
                         IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
                         IOVEC_SET_STRING(iov[skip+1], buffer);
@@ -474,7 +472,7 @@ _public_ int sd_journal_print_with_location(int priority, const char *file, cons
 }
 
 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
-        char buffer[8 + LINE_MAX], p[11];
+        char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1];
         struct iovec iov[5];
         char *f;
 
@@ -482,12 +480,10 @@ _public_ int sd_journal_printv_with_location(int priority, const char *file, con
         assert_return(priority <= 7, -EINVAL);
         assert_return(format, -EINVAL);
 
-        snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
-        char_array_0(p);
+        xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
 
         memcpy(buffer, "MESSAGE=", 8);
         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
-        char_array_0(buffer);
 
         /* func is initialized from __func__ which is not a macro, but
          * a static const char[], hence cannot easily be prefixed with
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 4afa6ef..5363aaa 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -51,9 +51,9 @@ void server_forward_console(
                 const struct ucred *ucred) {
 
         struct iovec iovec[5];
-        char header_pid[16];
         struct timespec ts;
-        char tbuf[4 + DECIMAL_STR_MAX(ts.tv_sec) + DECIMAL_STR_MAX(ts.tv_nsec)-3 + 1];
+        char tbuf[sizeof("[] ")-1 + DECIMAL_STR_MAX(ts.tv_sec) + DECIMAL_STR_MAX(ts.tv_nsec)-3 + 1];
+        char header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t)];
         int n = 0, fd;
         _cleanup_free_ char *ident_buf = NULL;
         const char *tty;
@@ -67,7 +67,7 @@ void server_forward_console(
         /* First: timestamp */
         if (prefix_timestamp()) {
                 assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
-                snprintf(tbuf, sizeof(tbuf), "[%5"PRI_TIME".%06ld] ",
+                xsprintf(tbuf, "[%5"PRI_TIME".%06ld] ",
                          ts.tv_sec,
                          ts.tv_nsec / 1000);
                 IOVEC_SET_STRING(iovec[n++], tbuf);
@@ -80,8 +80,7 @@ void server_forward_console(
                         identifier = ident_buf;
                 }
 
-                snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", ucred->pid);
-                char_array_0(header_pid);
+                xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid);
 
                 if (identifier)
                         IOVEC_SET_STRING(iovec[n++], identifier);
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index aca4571..0b02eff 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -40,7 +40,8 @@ void server_forward_kmsg(
         const struct ucred *ucred) {
 
         struct iovec iovec[5];
-        char header_priority[6], header_pid[16];
+        char header_priority[4],
+             header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t) + 1];
         int n = 0;
         char *ident_buf = NULL;
 
@@ -60,8 +61,7 @@ void server_forward_kmsg(
         priority = syslog_fixup_facility(priority);
 
         /* First: priority field */
-        snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
-        char_array_0(header_priority);
+        xsprintf(header_priority, "<%i>", priority);
         IOVEC_SET_STRING(iovec[n++], header_priority);
 
         /* Second: identifier and PID */
@@ -71,8 +71,7 @@ void server_forward_kmsg(
                         identifier = ident_buf;
                 }
 
-                snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", ucred->pid);
-                char_array_0(header_pid);
+                xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid);
 
                 if (identifier)
                         IOVEC_SET_STRING(iovec[n++], identifier);
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 87b459b..aecf859 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -837,12 +837,10 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
         va_start(ap, format);
         vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
         va_end(ap);
-        char_array_0(buffer);
         IOVEC_SET_STRING(iovec[n++], buffer);
 
         if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
                 snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id));
-                char_array_0(mid);
                 IOVEC_SET_STRING(iovec[n++], mid);
         }
 
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index eabe019..942a857 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -223,7 +223,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
         struct iovec iovec[N_IOVEC_META_FIELDS + 5];
         int priority;
         char syslog_priority[] = "PRIORITY=\0";
-        char syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(priority)];
+        char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
         _cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
         unsigned n = 0;
         char *label = NULL;
@@ -258,7 +258,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
         IOVEC_SET_STRING(iovec[n++], syslog_priority);
 
         if (priority & LOG_FACMASK) {
-                snprintf(syslog_facility, sizeof(syslog_facility), "SYSLOG_FACILITY=%i", LOG_FAC(priority));
+                xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
                 IOVEC_SET_STRING(iovec[n++], syslog_facility);
         }
 
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 21bc967..ba6e331 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -124,7 +124,8 @@ static void forward_syslog_raw(Server *s, int priority, const char *buffer, cons
 
 void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv) {
         struct iovec iovec[5];
-        char header_priority[6], header_time[64], header_pid[16];
+        char header_priority[4], header_time[64],
+             header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t) + 1];
         int n = 0;
         time_t t;
         struct tm *tm;
@@ -139,8 +140,7 @@ void server_forward_syslog(Server *s, int priority, const char *identifier, cons
                 return;
 
         /* First: priority field */
-        snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
-        char_array_0(header_priority);
+        xsprintf(header_priority, "<%i>", priority);
         IOVEC_SET_STRING(iovec[n++], header_priority);
 
         /* Second: timestamp */
@@ -159,8 +159,7 @@ void server_forward_syslog(Server *s, int priority, const char *identifier, cons
                         identifier = ident_buf;
                 }
 
-                snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", ucred->pid);
-                char_array_0(header_pid);
+                xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid);
 
                 if (identifier)
                         IOVEC_SET_STRING(iovec[n++], identifier);
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 9bc426f..9dea547 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -1178,8 +1178,7 @@ static bool file_type_wanted(int flags, const char *filename) {
         if (flags & SD_JOURNAL_CURRENT_USER) {
                 char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1];
 
-                assert_se(snprintf(prefix, sizeof(prefix), "user-"UID_FMT, getuid())
-                          < (int) sizeof(prefix));
+                xsprintf(prefix, "user-"UID_FMT, getuid());
 
                 if (file_has_type_prefix(prefix, filename))
                         return true;
diff --git a/src/libsystemd-terminal/subterm.c b/src/libsystemd-terminal/subterm.c
index 7c119ac..63cd2a5 100644
--- a/src/libsystemd-terminal/subterm.c
+++ b/src/libsystemd-terminal/subterm.c
@@ -161,16 +161,14 @@ static int output_write(Output *o, const void *buf, size_t size) {
 
 _printf_(3,0)
 static int output_vnprintf(Output *o, size_t max, const char *format, va_list args) {
-        char buf[4096];
+        char buf[max];
         int r;
 
         assert_return(o, -EINVAL);
         assert_return(format, -EINVAL);
-        assert_return(max <= sizeof(buf), -EINVAL);
+        assert_return(max <= 4096, -EINVAL);
 
-        r = vsnprintf(buf, max, format, args);
-        if (r > (ssize_t)max)
-                r = max;
+        r = MIN(vsnprintf(buf, max, format, args), (int) max);
 
         return output_write(o, buf, r);
 }
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index babfed8..8d12c25 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%i", c->type - BUS_MATCH_ARG);
+                        xsprintf(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%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
+                        xsprintf(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%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
+                        xsprintf(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-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index d02994e..d3eb834 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -359,8 +359,7 @@ static int bus_socket_auth_write_ok(sd_bus *b) {
 
         assert(b);
 
-        snprintf(t, sizeof(t), "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
-        char_array_0(t);
+        xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
 
         return bus_socket_auth_write(b, t);
 }
@@ -644,12 +643,11 @@ static int bus_socket_start_auth_client(sd_bus *b) {
                 l = 9;
                 b->auth_buffer = hexmem("anonymous", l);
         } else {
-                char text[20 + 1]; /* enough space for a 64bit integer plus NUL */
+                char text[DECIMAL_STR_MAX(uid_t) + 1];
 
                 auth_prefix = "\0AUTH EXTERNAL ";
 
-                snprintf(text, sizeof(text), UID_FMT, geteuid());
-                char_array_0(text);
+                xsprintf(text, UID_FMT, geteuid());
 
                 l = strlen(text);
                 b->auth_buffer = hexmem(text, l);
diff --git a/src/shared/log.c b/src/shared/log.c
index a870415..9c01560 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -331,7 +331,6 @@ static int write_to_console(
 
         if (show_location) {
                 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
-                char_array_0(location);
                 IOVEC_SET_STRING(iovec[n++], location);
         }
 
@@ -375,7 +374,9 @@ static int write_to_syslog(
                 const char *object,
                 const char *buffer) {
 
-        char header_priority[1 + DECIMAL_STR_MAX(int) + 2], header_time[64], header_pid[1 + DECIMAL_STR_MAX(pid_t) + 4];
+        char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
+             header_time[64],
+             header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
         struct iovec iovec[5] = {};
         struct msghdr msghdr = {
                 .msg_iov = iovec,
@@ -387,8 +388,7 @@ static int write_to_syslog(
         if (syslog_fd < 0)
                 return 0;
 
-        snprintf(header_priority, sizeof(header_priority), "<%i>", level);
-        char_array_0(header_priority);
+        xsprintf(header_priority, "<%i>", level);
 
         t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
         tm = localtime(&t);
@@ -398,8 +398,7 @@ static int write_to_syslog(
         if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
                 return -EINVAL;
 
-        snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", getpid());
-        char_array_0(header_pid);
+        xsprintf(header_pid, "["PID_FMT"]: ", getpid());
 
         IOVEC_SET_STRING(iovec[0], header_priority);
         IOVEC_SET_STRING(iovec[1], header_time);
@@ -438,17 +437,15 @@ static int write_to_kmsg(
                 const char *object,
                 const char *buffer) {
 
-        char header_priority[1 + DECIMAL_STR_MAX(int) + 2], header_pid[1 + DECIMAL_STR_MAX(pid_t) + 4];
+        char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
+             header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
         struct iovec iovec[5] = {};
 
         if (kmsg_fd < 0)
                 return 0;
 
-        snprintf(header_priority, sizeof(header_priority), "<%i>", level);
-        char_array_0(header_priority);
-
-        snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", getpid());
-        char_array_0(header_pid);
+        xsprintf(header_priority, "<%i>", level);
+        xsprintf(header_pid, "["PID_FMT"]: ", getpid());
 
         IOVEC_SET_STRING(iovec[0], header_priority);
         IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
@@ -497,7 +494,6 @@ static int log_do_header(
                  isempty(object) ? "" : object,
                  isempty(object) ? "" : "\n",
                  program_invocation_short_name);
-        header[size - 1] = '\0';
 
         return 0;
 }
@@ -659,7 +655,6 @@ int log_internalv(
                 errno = error;
 
         vsnprintf(buffer, sizeof(buffer), format, ap);
-        char_array_0(buffer);
 
         return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
 }
@@ -707,7 +702,6 @@ int log_object_internalv(
                 errno = error;
 
         vsnprintf(buffer, sizeof(buffer), format, ap);
-        char_array_0(buffer);
 
         return log_dispatch(level, error, file, line, func, object_field, object, buffer);
 }
@@ -749,7 +743,6 @@ static void log_assert(
         snprintf(buffer, sizeof(buffer), format, text, file, line, func);
         REENABLE_WARNING;
 
-        char_array_0(buffer);
         log_abort_msg = buffer;
 
         log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
@@ -875,7 +868,6 @@ int log_struct_internal(
                 va_copy(aq, ap);
                 vsnprintf(buf, sizeof(buf), format, aq);
                 va_end(aq);
-                char_array_0(buf);
 
                 if (startswith(buf, "MESSAGE=")) {
                         found = true;
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index e7419b5..006ad53 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -39,7 +39,7 @@ static pid_t agent_pid = 0;
 int polkit_agent_open(void) {
         int r;
         int pipe_fd[2];
-        char notify_fd[10 + 1];
+        char notify_fd[DECIMAL_STR_MAX(int) + 1];
 
         if (agent_pid > 0)
                 return 0;
@@ -52,8 +52,7 @@ int polkit_agent_open(void) {
         if (pipe2(pipe_fd, 0) < 0)
                 return -errno;
 
-        snprintf(notify_fd, sizeof(notify_fd), "%i", pipe_fd[1]);
-        char_array_0(notify_fd);
+        xsprintf(notify_fd, "%i", pipe_fd[1]);
 
         r = fork_agent(&agent_pid,
                        &pipe_fd[1], 1,
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index ca38756..e8cedc6 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -72,7 +72,6 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot,
                 struct stat sb;
 
                 snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i);
-                char_array_0(new_mount);
 
                 mkdir_p_label(new_mount, 0755);
 
diff --git a/src/shared/util.h b/src/shared/util.h
index ca0c2e5..5312422 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -481,6 +481,8 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus);
 int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
 int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
 
+#define xsprintf(buf, fmt, ...) assert_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf))
+
 int fd_columns(int fd);
 unsigned columns(void);
 int fd_lines(int fd);
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 74f40b9..1f85536 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -38,6 +38,8 @@
 #include "pager.h"
 #include "time-dst.h"
 
+#define xstrftime(buf, fmt, tm) assert_se(strftime(buf, sizeof(buf), fmt, tm) > 0)
+
 static bool arg_no_pager = false;
 static bool arg_ask_password = true;
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
@@ -123,15 +125,11 @@ static void print_status_info(const StatusInfo *i) {
                 fprintf(stderr, "Warning: Could not get time from timedated and not operating locally.\n\n");
 
         if (have_time) {
-                zero(tm);
-                assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
-                char_array_0(a);
-                printf("      Local time: %s\n", a);
-
-                zero(tm);
-                assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
-                char_array_0(a);
-                printf("  Universal time: %s\n", a);
+                xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
+                printf("      Local time: %.*s\n", (int) sizeof(a), a);
+
+                xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
+                printf("  Universal time: %.*s\n", (int) sizeof(a), a);
         } else {
                 printf("      Local time: %s\n", "n/a");
                 printf("  Universal time: %s\n", "n/a");
@@ -141,24 +139,19 @@ static void print_status_info(const StatusInfo *i) {
                 time_t rtc_sec;
 
                 rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC);
-                zero(tm);
-                assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)) > 0);
-                char_array_0(a);
-                printf("        RTC time: %s\n", a);
+                xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
+                printf("        RTC time: %.*s\n", (int) sizeof(a), a);
         } else
                 printf("        RTC time: %s\n", "n/a");
 
-        if (have_time) {
-                zero(tm);
-                assert_se(strftime(a, sizeof(a), "%Z, %z", localtime_r(&sec, &tm)) > 0);
-                char_array_0(a);
-        }
+        if (have_time)
+                xstrftime(a, "%Z, %z", localtime_r(&sec, &tm));
 
-        printf("       Time zone: %s (%s)\n"
+        printf("       Time zone: %s (%.*s)\n"
                "     NTP enabled: %s\n"
                "NTP synchronized: %s\n"
                " RTC in local TZ: %s\n",
-               strna(i->timezone), have_time ? a : "n/a",
+               strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a",
                i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
                yes_no(i->ntp_synced),
                yes_no(i->rtc_local));
@@ -173,30 +166,26 @@ static void print_status_info(const StatusInfo *i) {
                         printf("      DST active: %s\n", yes_no(is_dstc));
 
                         t = tc - 1;
-                        zero(tm);
-                        assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
-                        char_array_0(a);
+                        xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
 
-                        zero(tm);
-                        assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)) > 0);
-                        char_array_0(b);
+                        xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm));
                         printf(" Last DST change: DST %s at\n"
-                               "                  %s\n"
-                               "                  %s\n",
-                               is_dstc ? "began" : "ended", a, b);
+                               "                  %.*s\n"
+                               "                  %.*s\n",
+                               is_dstc ? "began" : "ended",
+                               (int) sizeof(a), a,
+                               (int) sizeof(b), b);
 
                         t = tn - 1;
-                        zero(tm);
-                        assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
-                        char_array_0(a);
-
-                        zero(tm);
-                        assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)) > 0);
-                        char_array_0(b);
+                        xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm));
+                        xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm));
                         printf(" Next DST change: DST %s (the clock jumps %s) at\n"
-                               "                  %s\n"
-                               "                  %s\n",
-                               is_dstn ? "begins" : "ends", jump_str(dn, s, sizeof(s)), a, b);
+                               "                  %.*s\n"
+                               "                  %.*s\n",
+                               is_dstn ? "begins" : "ends",
+                               jump_str(dn, s, sizeof(s)),
+                               (int) sizeof(a), a,
+                               (int) sizeof(b), b);
                 }
         } else
                 printf("      DST active: %s\n", yes_no(is_dstc));

commit 294929f8916ca37d89ccb1757868d22f8068c56b
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sun Feb 1 12:29:27 2015 -0500

    tmpfiles: accurately report creation results

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index e816bed..0e1bd86 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -903,9 +903,28 @@ static int glob_item(Item *i, action_t action, bool recursive) {
         return r;
 }
 
+typedef enum {
+        CREATION_NORMAL,
+        CREATION_EXISTING,
+        CREATION_FORCE,
+} CreationMode;
+
+static const char* creation_verb(CreationMode mode) {
+        switch(mode) {
+        case CREATION_NORMAL:
+                return "Created";
+        case CREATION_EXISTING:
+                return "Found existing";
+        case CREATION_FORCE:
+                return "Created replacement";
+        }
+        assert_not_reached("Bad creation");
+}
+
 static int create_item(Item *i) {
         struct stat st;
         int r = 0;
+        CreationMode creation;
 
         assert(i);
 
@@ -990,8 +1009,11 @@ static int create_item(Item *i) {
                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
                                 return 0;
                         }
-                }
-                log_debug("Created directory \"%s\".", i->path);
+
+                        creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s directory \"%s\".", creation_verb(creation), i->path);
 
                 r = path_set_perms(i, i->path);
                 if (r < 0)
@@ -1026,13 +1048,16 @@ static int create_item(Item *i) {
 
                                         if (r < 0)
                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
+                                        creation = CREATION_FORCE;
                                 } else {
                                         log_debug("%s is not a fifo.", i->path);
                                         return 0;
                                 }
-                        }
-                }
-                log_debug("Created fifo \"%s\".", i->path);
+                        } else
+                                creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s fifo \"%s\".", creation_verb(creation), i->path);
 
                 r = path_set_perms(i, i->path);
                 if (r < 0)
@@ -1062,13 +1087,16 @@ static int create_item(Item *i) {
 
                                         if (r < 0)
                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
+                                        creation = CREATION_FORCE;
                                 } else {
                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
                                         return 0;
                                 }
-                        }
-                }
-                log_debug("Created symlink \"%s\".", i->path);
+                        } else
+                                creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s symlink \"%s\".", creation_verb(creation), i->path);
 
                 break;
 
@@ -1118,14 +1146,18 @@ static int create_item(Item *i) {
                                         }
 
                                         if (r < 0)
-                                                return log_error_errno(r, "Failed to create device node %s: %m", i->path);
+                                                return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
+                                        creation = CREATION_FORCE;
                                 } else {
                                         log_debug("%s is not a device node.", i->path);
                                         return 0;
                                 }
-                        }
-                }
-                log_debug("Created %s device node \"%s\" %u:%u.",
+                        } else
+                                creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s %s device node \"%s\" %u:%u.",
+                          creation_verb(creation),
                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
                           i->path, major(i->mode), minor(i->mode));
 

commit 612532206c531ab2aafd398338d5dd44cb6d3553
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sat Jan 31 01:03:09 2015 -0500

    tmpfiles: remove dead branch
    
    In the test, p is a path to a directory, always absolute. dent->d_name
    is a single path component, so they cannot be equal. The comparison
    was wrong also for other reasons: D type supports globs, so direct
    comparisons using streq are not enough.

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 473c511..e816bed 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -465,18 +465,12 @@ static int dir_cleanup(
                                 continue;
                         }
 
-                        if (i->type == IGNORE_DIRECTORY_PATH && streq(dent->d_name, p))
-                                log_debug("Ignoring directory \"%s\"", sub_path);
-                        else {
-                                log_debug("Removing directory \"%s\".", sub_path);
-
-                                if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
-                                        if (errno != ENOENT && errno != ENOTEMPTY) {
-                                                log_error_errno(errno, "rmdir(%s): %m", sub_path);
-                                                r = -errno;
-                                        }
+                        log_debug("Removing directory \"%s\".", sub_path);
+                        if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
+                                if (errno != ENOENT && errno != ENOTEMPTY) {
+                                        log_error_errno(errno, "rmdir(%s): %m", sub_path);
+                                        r = -errno;
                                 }
-                        }
 
                 } else {
                         /* Skip files for which the sticky bit is

commit 0775b9b61120f8be99cd45a7df907b828188cb47
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Fri Jan 30 23:54:21 2015 -0500

    units: set TimeoutSec on some oneshot services
    
    Services which are not crucial to system bootup, and have Type=oneshot
    can effectively "hang" the system if they fail to complete for whatever
    reason. To allow the boot to continue, kill them after a timeout.
    
    In case of systemd-journal-flush the flush will continue in the background,
    and in the other two cases the job will be aborted, but this should not
    result in any permanent problem.

diff --git a/units/systemd-backlight at .service.in b/units/systemd-backlight at .service.in
index ecf3de4..19d640b 100644
--- a/units/systemd-backlight at .service.in
+++ b/units/systemd-backlight at .service.in
@@ -19,3 +19,4 @@ Type=oneshot
 RemainAfterExit=yes
 ExecStart=@rootlibexecdir@/systemd-backlight load %i
 ExecStop=@rootlibexecdir@/systemd-backlight save %i
+TimeoutSec=2min
diff --git a/units/systemd-journal-catalog-update.service.in b/units/systemd-journal-catalog-update.service.in
index bfa5e6b..9667310 100644
--- a/units/systemd-journal-catalog-update.service.in
+++ b/units/systemd-journal-catalog-update.service.in
@@ -18,3 +18,4 @@ ConditionNeedsUpdate=/etc
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=@rootbindir@/journalctl --update-catalog
+TimeoutSec=2min
diff --git a/units/systemd-journal-flush.service.in b/units/systemd-journal-flush.service.in
index 98c91b4..53a6f30 100644
--- a/units/systemd-journal-flush.service.in
+++ b/units/systemd-journal-flush.service.in
@@ -19,3 +19,4 @@ RequiresMountsFor=/var/log/journal
 ExecStart=@rootbindir@/journalctl --flush
 Type=oneshot
 RemainAfterExit=yes
+TimeoutSec=2min



More information about the systemd-commits mailing list