Re: [systemd-devel] [PATCH v9002 1/2] timedated: gather timezone from /etc/localtime sym target

2012-08-24 Thread shawn
On Thu, 2012-08-23 at 14:21 +0200, Frederic Crozat wrote: 
 Le mardi 21 août 2012 à 23:11 -0700, Shawn Landden a écrit :
 
  @@ -218,19 +248,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);
 
 It doesn't work when /etc/localtime already exists, because symlink
 returns EEXIST. I guess you should put back your symlink_atomic patch..
 
yes, and the other errors like ENOTDIR and EACCESS and ENOENT that can
result from this action would all be after removing it, if using
symlink() directly with a remove, and not a atomic rename. There were
reasons I created symlink_atomic()...
-- 
-Shawn Landden

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH v9002 1/2] timedated: gather timezone from /etc/localtime sym target

2012-08-23 Thread Frederic Crozat
Le mardi 21 août 2012 à 23:11 -0700, Shawn Landden a écrit :

 @@ -218,19 +248,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);

It doesn't work when /etc/localtime already exists, because symlink
returns EEXIST. I guess you should put back your symlink_atomic patch..

-- 
Frederic Crozat fcro...@suse.com
SUSE

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v9002 1/2] timedated: gather timezone from /etc/localtime sym target

2012-08-22 Thread Shawn Landden
/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
---
 src/timedate/timedated.c |   52 +-
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 09fd808..b11acae 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -74,6 +74,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 {
@@ -127,7 +130,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;
 
@@ -151,17 +154,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);
@@ -174,9 +177,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)
@@ -192,6 +220,7 @@ static int read_data(void) {
 #endif
 }
 
+have_timezone:
 if (isempty(tz.zone)) {
 free(tz.zone);
 tz.zone = NULL;
@@ -207,6 +236,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)
@@ -218,19 +248,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;
 }
-- 
1.7.9.5