[systemd-commits] 3 commits - Makefile.am TODO man/localtime.xml man/timezone.xml src/shared src/timedate units/systemd-timedated.service.in

Lennart Poettering lennart at kemper.freedesktop.org
Fri Sep 14 11:04:39 PDT 2012


 Makefile.am                        |    2 
 TODO                               |    4 +
 man/localtime.xml                  |   93 +++++++++++++++++++++++++++++++++++++
 man/timezone.xml                   |   90 -----------------------------------
 src/shared/path-util.c             |   12 ++--
 src/shared/path-util.h             |    2 
 src/shared/util.c                  |   58 ++---------------------
 src/shared/util.h                  |    4 -
 src/timedate/timedated.c           |   81 ++++++++++++++++----------------
 units/systemd-timedated.service.in |    2 
 10 files changed, 156 insertions(+), 192 deletions(-)

New commits:
commit 424a19f8a2061c6b058283228734010b2fa24db4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 20:02:52 2012 +0200

    timedate: assorted improvements
    
    - Make writing/reading of /etc/timezone dependendent of HAVE_SYSV_COMPAT
    
    - Introduce symlink_atomic() after all, and use it
    
    - Use relative symlink for /etc/localtime

diff --git a/TODO b/TODO
index 887d684..78da717 100644
--- a/TODO
+++ b/TODO
@@ -53,6 +53,10 @@ Bugfixes:
 
 Features:
 
+* hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
+
+* after deserializing sockets in socket.c we should reapply sockopts and things
+
 * journald: warn if we drop messages we forward to the syslog socket
 
 * does vasprintf advance the struct vaargs? http://pastie.org/pastes/4712773/text
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
index b51a68d..70c8a8a 100644
--- a/src/shared/path-util.c
+++ b/src/shared/path-util.c
@@ -264,12 +264,12 @@ char *path_kill_slashes(char *path) {
         return path;
 }
 
-bool path_startswith(const char *path, const char *prefix) {
+char* path_startswith(const char *path, const char *prefix) {
         assert(path);
         assert(prefix);
 
         if ((path[0] == '/') != (prefix[0] == '/'))
-                return false;
+                return NULL;
 
         for (;;) {
                 size_t a, b;
@@ -278,19 +278,19 @@ bool path_startswith(const char *path, const char *prefix) {
                 prefix += strspn(prefix, "/");
 
                 if (*prefix == 0)
-                        return true;
+                        return (char*) path;
 
                 if (*path == 0)
-                        return false;
+                        return NULL;
 
                 a = strcspn(path, "/");
                 b = strcspn(prefix, "/");
 
                 if (a != b)
-                        return false;
+                        return NULL;
 
                 if (memcmp(path, prefix, a) != 0)
-                        return false;
+                        return NULL;
 
                 path += a;
                 prefix += b;
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
index a441783..e81821a 100644
--- a/src/shared/path-util.h
+++ b/src/shared/path-util.h
@@ -32,7 +32,7 @@ bool path_is_absolute(const char *p);
 char *path_make_absolute(const char *p, const char *prefix);
 char *path_make_absolute_cwd(const char *p);
 char *path_kill_slashes(char *path);
-bool path_startswith(const char *path, const char *prefix);
+char *path_startswith(const char *path, const char *prefix);
 bool path_equal(const char *a, const char *b);
 
 char **path_strv_make_absolute_cwd(char **l);
diff --git a/src/shared/util.c b/src/shared/util.c
index 6a40cf1..add3fdc 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -4644,49 +4644,9 @@ int copy_file(const char *from, const char *to) {
         return 0;
 }
 
-int symlink_or_copy(const char *from, const char *to) {
-        char *pf = NULL, *pt = NULL;
-        struct stat a, b;
-        int r;
-
-        assert(from);
-        assert(to);
-
-        if (path_get_parent(from, &pf) < 0 ||
-            path_get_parent(to, &pt) < 0) {
-                r = -ENOMEM;
-                goto finish;
-        }
-
-        if (stat(pf, &a) < 0 ||
-            stat(pt, &b) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        if (a.st_dev != b.st_dev) {
-                free(pf);
-                free(pt);
-
-                return copy_file(from, to);
-        }
-
-        if (symlink(from, to) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        r = 0;
-
-finish:
-        free(pf);
-        free(pt);
-
-        return r;
-}
-
-int symlink_or_copy_atomic(const char *from, const char *to) {
-        char *t, *x;
+int symlink_atomic(const char *from, const char *to) {
+        char *x;
+        _cleanup_free_ char *t;
         const char *fn;
         size_t k;
         unsigned long long ull;
@@ -4714,22 +4674,16 @@ int symlink_or_copy_atomic(const char *from, const char *to) {
 
         *x = 0;
 
-        r = symlink_or_copy(from, t);
-        if (r < 0) {
-                unlink(t);
-                free(t);
-                return r;
-        }
+        if (symlink(from, t) < 0)
+                return -errno;
 
         if (rename(t, to) < 0) {
                 r = -errno;
                 unlink(t);
-                free(t);
                 return r;
         }
 
-        free(t);
-        return r;
+        return 0;
 }
 
 bool display_is_local(const char *display) {
diff --git a/src/shared/util.h b/src/shared/util.h
index a3f825b..2b75ba6 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -430,8 +430,8 @@ int terminal_vhangup(const char *name);
 int vt_disallocate(const char *name);
 
 int copy_file(const char *from, const char *to);
-int symlink_or_copy(const char *from, const char *to);
-int symlink_or_copy_atomic(const char *from, const char *to);
+
+int symlink_atomic(const char *from, const char *to);
 
 int fchmod_umask(int fd, mode_t mode);
 
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 9ca2eec..acfb507 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -34,6 +34,7 @@
 #include "def.h"
 #include "hwclock.h"
 #include "conf-files.h"
+#include "path-util.h"
 
 #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
 #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
@@ -76,9 +77,6 @@
         BUS_GENERIC_INTERFACES_LIST             \
         "org.freedesktop.timedate1\0"
 
-/* Must start and end with '/' */
-#define ZONEINFO_PATH "/usr/share/zoneinfo/"
-
 const char timedate_interface[] _introspect_("timedate1") = INTERFACE;
 
 typedef struct TZ {
@@ -132,7 +130,7 @@ static bool valid_timezone(const char *name) {
         if (slash)
                 return false;
 
-        t = strappend(ZONEINFO_PATH, name);
+        t = strappend("/usr/share/zoneinfo/", name);
         if (!t)
                 return false;
 
@@ -148,56 +146,29 @@ static bool valid_timezone(const char *name) {
         return true;
 }
 
-static void verify_timezone(void) {
-        char *p, *a = NULL, *b = NULL;
-        size_t l, q;
-        int j, k;
-
-        if (!tz.zone)
-                return;
-
-        p = strappend(ZONEINFO_PATH, tz.zone);
-        if (!p) {
-                log_oom();
-                return;
-        }
-
-        k = read_full_file(p, &b, &q);
-        free(p);
-
-        j = read_full_file("/etc/localtime", &a, &l);
-
-        if (j < 0 || k < 0 || l != q || memcmp(a, b, l)) {
-                log_warning("/etc/localtime and /etc/timezone out of sync.");
-                free(tz.zone);
-                tz.zone = NULL;
-        }
-
-        free(a);
-        free(b);
-}
-
 static int read_data(void) {
         int r;
-        char *t = NULL;
+        _cleanup_free_ char *t = NULL;
 
         free_data();
 
         r = readlink_malloc("/etc/localtime", &t);
         if (r < 0) {
                 if (r == -EINVAL)
-                        log_warning("/etc/localtime should be a symbolic link to a timezone data file in " ZONEINFO_PATH);
+                        log_warning("/etc/localtime should be a symbolic link to a timezone data file in /usr/share/zoneinfo/.");
                 else
-                        log_warning("Failed to get target of %s: %s", "/etc/localtime", strerror(-r));
+                        log_warning("Failed to get target of /etc/localtime: %s", strerror(-r));
         } else {
-                /* we only support the trivial relative link of (/etc/)..$ABSOLUTE */
-                int rel_link_offset = startswith(t, "..") ? strlen("..") : 0;
+                const char *e;
 
-                if (!startswith(t + rel_link_offset, ZONEINFO_PATH))
-                        log_warning("/etc/localtime should be a symbolic link to a timezone data file in " ZONEINFO_PATH);
+                e = path_startswith(t, "/usr/share/zoneinfo/");
+                if (!e)
+                        e = path_startswith(t, "../usr/share/zoneinfo/");
+
+                if (!e)
+                        log_warning("/etc/localtime should be a symbolic link to a timezone data file in /usr/share/zoneinfo/.");
                 else {
-                        tz.zone = strdup(t + rel_link_offset + strlen(ZONEINFO_PATH));
-                        free(t);
+                        tz.zone = strdup(e);
                         if (!tz.zone)
                                 return log_oom();
 
@@ -205,8 +176,7 @@ static int read_data(void) {
                 }
         }
 
-        free(t);
-
+#ifdef HAVE_SYSV_COMPAT
         r = read_one_line_file("/etc/timezone", &tz.zone);
         if (r < 0) {
                 if (r != -ENOENT)
@@ -221,6 +191,7 @@ static int read_data(void) {
                         log_warning("Failed to read /etc/sysconfig/clock: %s", strerror(-r));
 #endif
         }
+#endif
 
 have_timezone:
         if (isempty(tz.zone)) {
@@ -228,8 +199,6 @@ have_timezone:
                 tz.zone = NULL;
         }
 
-        verify_timezone();
-
         tz.local_rtc = hwclock_is_localtime() > 0;
 
         return 0;
@@ -237,34 +206,36 @@ have_timezone:
 
 static int write_data_timezone(void) {
         int r = 0;
-        char *p;
+        _cleanup_free_ char *p = NULL;
         struct stat st;
 
         if (!tz.zone) {
-                if (unlink("/etc/timezone") < 0 && errno != ENOENT)
+                if (unlink("/etc/localtime") < 0 && errno != ENOENT)
                         r = -errno;
 
-                if (unlink("/etc/localtime") < 0 && errno != ENOENT)
+#ifdef HAVE_SYSV_COMPAT
+                if (unlink("/etc/timezone") < 0 && errno != ENOENT)
                         r = -errno;
+#endif
 
                 return r;
         }
 
-        p = strappend(ZONEINFO_PATH, tz.zone);
+        p = strappend("../usr/share/zoneinfo/", tz.zone);
         if (!p)
                 return log_oom();
 
-        r = symlink(p, "/etc/localtime");
-        free(p);
-
+        r = symlink_atomic(p, "/etc/localtime");
         if (r < 0)
-                return -errno;
+                return r;
 
+#ifdef HAVE_SYSV_COMPAT
         if (stat("/etc/timezone", &st) == 0 && S_ISREG(st.st_mode)) {
                 r = write_one_line_file_atomic("/etc/timezone", tz.zone);
                 if (r < 0)
                         return r;
         }
+#endif
 
         return 0;
 }

commit 608da9e9b56be83ac394ea7a19cbdacab94f6642
Author: Shawn Landden <shawnlandden at gmail.com>
Date:   Tue Aug 21 23:11:27 2012 -0700

    man: remove timezone(5) and add localtime(5)

diff --git a/Makefile.am b/Makefile.am
index 5674f10..12c2d2e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -471,7 +471,7 @@ MANPAGES = \
 	man/systemd.conf.5 \
 	man/tmpfiles.d.5 \
 	man/hostname.5 \
-	man/timezone.5 \
+	man/localtime.5 \
 	man/machine-id.5 \
 	man/locale.conf.5 \
 	man/os-release.5 \
diff --git a/man/localtime.xml b/man/localtime.xml
new file mode 100644
index 0000000..09df161
--- /dev/null
+++ b/man/localtime.xml
@@ -0,0 +1,93 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2012 Shawn Landden
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="localtime">
+        <refentryinfo>
+                <title>/etc/localtime</title>
+                <productname>systemd</productname>
+
+                <authorgroup>
+                        <author>
+                                <contrib>Developer</contrib>
+                                <firstname>Lennart</firstname>
+                                <surname>Poettering</surname>
+                                <email>lennart at poettering.net</email>
+                        </author>
+                        <author>
+                                <contrib>Developer</contrib>
+                                <firstname>Shawn</firstname>
+                                <surname>Landden</surname>
+                                <email>shawnlandden at gmail.com</email>
+                        </author>
+                </authorgroup>
+        </refentryinfo>
+
+        <refmeta>
+                <refentrytitle>localtime</refentrytitle>
+                <manvolnum>5</manvolnum>
+        </refmeta>
+
+        <refnamediv>
+                <refname>localtime</refname>
+                <refpurpose>Local time zone configuration file</refpurpose>
+        </refnamediv>
+
+        <refsynopsisdiv>
+                <para><filename>/etc/localtime</filename> -> <filename>/usr/share/zoneinfo/…</filename></para>
+        </refsynopsisdiv>
+
+        <refsect1>
+                <title>Description</title>
+
+                <para>The <filename>/etc/localtime</filename> file
+                configures the system-wide time zone of the local
+                system that is used by applications for presentation
+                to the user. It should be an absolute symbolic link
+                with a destination of <filename>/usr/share/zoneinfo/</filename>,
+                fallowed by a time zone identifier such as
+                <literal>Europe/Berlin</literal> or <literal>Etc/UTC</literal>.
+                The resulting link should point to the corresponding binary
+                <citerefentry><refentrytitle>tzfile</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+                time zone data for the configured time zone.</para>
+
+                <para>As the time zone identifier is extracted from the name of
+                the target of <filename>/etc/localtime</filename> this file may
+                not be a normal file or hardlink.</para>
+
+                <para>The time zone may be overridden for individual
+                programs by using the TZ environment variable. See
+                <citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+        </refsect1>
+
+        <refsect1>
+                  <title>See Also</title>
+                  <para>
+                          <citerefentry><refentrytitle>tzset</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                          <citerefentry><refentrytitle>localtime</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                          <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                  </para>
+        </refsect1>
+
+</refentry>
diff --git a/man/timezone.xml b/man/timezone.xml
deleted file mode 100644
index dedb7d9..0000000
--- a/man/timezone.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<!--
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
--->
-
-<refentry id="timezone">
-        <refentryinfo>
-                <title>/etc/timezone</title>
-                <productname>systemd</productname>
-
-                <authorgroup>
-                        <author>
-                                <contrib>Developer</contrib>
-                                <firstname>Lennart</firstname>
-                                <surname>Poettering</surname>
-                                <email>lennart at poettering.net</email>
-                        </author>
-                </authorgroup>
-        </refentryinfo>
-
-        <refmeta>
-                <refentrytitle>timezone</refentrytitle>
-                <manvolnum>5</manvolnum>
-        </refmeta>
-
-        <refnamediv>
-                <refname>timezone</refname>
-                <refpurpose>Local time zone configuration file</refpurpose>
-        </refnamediv>
-
-        <refsynopsisdiv>
-                <para><filename>/etc/timezone</filename></para>
-        </refsynopsisdiv>
-
-        <refsect1>
-                <title>Description</title>
-
-                <para>The <filename>/etc/timezone</filename> file
-                configures the system-wide time zone of the local
-                system that is used by applications for presentation
-                to the user. It should contain a single
-                newline-terminated line consisting of a time zone
-                identifier such as
-                <literal>Europe/Berlin</literal>. The file
-                <filename>/etc/localtime</filename> corresponds with
-                <filename>/etc/timezone</filename> and contains the
-                binary time zone data for the time zone. These files
-                should always be changed simultaneously and kept in
-                sync.</para>
-
-                <para>The time zone may be overridden for individual
-                programs by using the TZ environment variable. See
-                <citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
-        </refsect1>
-
-        <refsect1>
-                <title>History</title>
-
-                <para>The simple configuration file format of
-                <filename>/etc/timezone</filename> originates from
-                Debian GNU/Linux.</para>
-        </refsect1>
-
-        <refsect1>
-                  <title>See Also</title>
-                  <para>
-                          <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-                  </para>
-        </refsect1>
-
-</refentry>
diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in
index 1944a71..dd3eb1b 100644
--- a/units/systemd-timedated.service.in
+++ b/units/systemd-timedated.service.in
@@ -7,7 +7,7 @@
 
 [Unit]
 Description=Time & Date Service
-Documentation=man:systemd-timedated.service(8) man:timezone(5)
+Documentation=man:systemd-timedated.service(8) man:localtime(5)
 Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated
 
 [Service]

commit 92c4ef2d357baeef78b6f82f119b92f7ed12ac77
Author: Shawn Landden <shawnlandden at gmail.com>
Date:   Tue Aug 21 23:11:26 2012 -0700

    timedated: gather timezone from /etc/localtime sym target
    
    /etc/localtime -> /usr/share/zoneinfo/...
    
    or
    
    /etc/localtime -> ../usr/share/zoneinfo/...
    
    (note, ../usr is not the same if /etc is a symlink, as this isn't
    using canonicalize_file_name())
    
    keep other method for now, consider dropping later.
    
    Supporting relative links here are problematic as timezones in
    /usr/share/zoneinfo are often themselves symlinks (and symlinks to
    symlinks), so this implamentation only supports absolute symlinks
    "/usr/share/zoneinfo/" and relative symlinks starting with
    "../usr/share/zoneinfo/"
    
    >From TODO (kay sievers):
    * kill /etc/timezone handling entirely? What does it provide?
      - /etc/localtime carries the same information already:
          $ ls -l /etc/localtime; cat /etc/timezone
          lrwxrwxrwx 1 root root 33 Jul 27 09:55 /etc/localtime -> /usr/share/zoneinfo/Europe/Berlin
          Europe/Berlin
      - systemd enforces /usr to be available at bootup, so we can
        enforce the use of the symlink

diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 34d287b..9ca2eec 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -76,6 +76,9 @@
         BUS_GENERIC_INTERFACES_LIST             \
         "org.freedesktop.timedate1\0"
 
+/* Must start and end with '/' */
+#define ZONEINFO_PATH "/usr/share/zoneinfo/"
+
 const char timedate_interface[] _introspect_("timedate1") = INTERFACE;
 
 typedef struct TZ {
@@ -129,7 +132,7 @@ static bool valid_timezone(const char *name) {
         if (slash)
                 return false;
 
-        t = strappend("/usr/share/zoneinfo/", name);
+        t = strappend(ZONEINFO_PATH, name);
         if (!t)
                 return false;
 
@@ -153,17 +156,17 @@ static void verify_timezone(void) {
         if (!tz.zone)
                 return;
 
-        p = strappend("/usr/share/zoneinfo/", tz.zone);
+        p = strappend(ZONEINFO_PATH, tz.zone);
         if (!p) {
                 log_oom();
                 return;
         }
 
-        j = read_full_file("/etc/localtime", &a, &l);
         k = read_full_file(p, &b, &q);
-
         free(p);
 
+        j = read_full_file("/etc/localtime", &a, &l);
+
         if (j < 0 || k < 0 || l != q || memcmp(a, b, l)) {
                 log_warning("/etc/localtime and /etc/timezone out of sync.");
                 free(tz.zone);
@@ -176,9 +179,34 @@ static void verify_timezone(void) {
 
 static int read_data(void) {
         int r;
+        char *t = NULL;
 
         free_data();
 
+        r = readlink_malloc("/etc/localtime", &t);
+        if (r < 0) {
+                if (r == -EINVAL)
+                        log_warning("/etc/localtime should be a symbolic link to a timezone data file in " ZONEINFO_PATH);
+                else
+                        log_warning("Failed to get target of %s: %s", "/etc/localtime", strerror(-r));
+        } else {
+                /* we only support the trivial relative link of (/etc/)..$ABSOLUTE */
+                int rel_link_offset = startswith(t, "..") ? strlen("..") : 0;
+
+                if (!startswith(t + rel_link_offset, ZONEINFO_PATH))
+                        log_warning("/etc/localtime should be a symbolic link to a timezone data file in " ZONEINFO_PATH);
+                else {
+                        tz.zone = strdup(t + rel_link_offset + strlen(ZONEINFO_PATH));
+                        free(t);
+                        if (!tz.zone)
+                                return log_oom();
+
+                        goto have_timezone;
+                }
+        }
+
+        free(t);
+
         r = read_one_line_file("/etc/timezone", &tz.zone);
         if (r < 0) {
                 if (r != -ENOENT)
@@ -194,6 +222,7 @@ static int read_data(void) {
 #endif
         }
 
+have_timezone:
         if (isempty(tz.zone)) {
                 free(tz.zone);
                 tz.zone = NULL;
@@ -209,6 +238,7 @@ static int read_data(void) {
 static int write_data_timezone(void) {
         int r = 0;
         char *p;
+        struct stat st;
 
         if (!tz.zone) {
                 if (unlink("/etc/timezone") < 0 && errno != ENOENT)
@@ -220,19 +250,21 @@ static int write_data_timezone(void) {
                 return r;
         }
 
-        p = strappend("/usr/share/zoneinfo/", tz.zone);
+        p = strappend(ZONEINFO_PATH, tz.zone);
         if (!p)
                 return log_oom();
 
-        r = symlink_or_copy_atomic(p, "/etc/localtime");
+        r = symlink(p, "/etc/localtime");
         free(p);
 
         if (r < 0)
-                return r;
+                return -errno;
 
-        r = write_one_line_file_atomic("/etc/timezone", tz.zone);
-        if (r < 0)
-                return r;
+        if (stat("/etc/timezone", &st) == 0 && S_ISREG(st.st_mode)) {
+                r = write_one_line_file_atomic("/etc/timezone", tz.zone);
+                if (r < 0)
+                        return r;
+        }
 
         return 0;
 }



More information about the systemd-commits mailing list