On Tue, Mar 24, 2015 at 07:04:11AM -0700, Kay Sievers wrote: > Makefile.am | 2 > src/shared/time-dst.c | 329 > --------------------------------------------- > src/shared/time-dst.h | 26 --- > src/timedate/timedatectl.c | 56 ------- > 4 files changed, 413 deletions(-) > > New commits: > commit 16c6ea29348ddac73998f339166f863bee0dfef6 > Author: Kay Sievers <[email protected]> > Date: Tue Mar 24 13:52:04 2015 +0100 > > timedate: remove daylight saving time handling and tzfile parser > > We planned to support (the conceptually broken) daylight saving > time/local time features in the kernel, SCSI, networking, FAT > filesystem, but it turned out to be a race we cannot win and do > not want to get involved. Systemd should not fiddle with daylight > saving time or parse timezone information itself. > > Leave everything to glibc or tools like date(1) and do not make any > promises or raise expectations that systemd should handle anything > like this.
That just doesn't make sense. This was *extremely* useful functionality. Zbyszek > > diff --git a/Makefile.am b/Makefile.am > index 29cfec5..93fdbc2 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -843,8 +843,6 @@ libsystemd_shared_la_SOURCES = \ > src/shared/spawn-polkit-agent.h \ > src/shared/clock-util.c \ > src/shared/clock-util.h \ > - src/shared/time-dst.c \ > - src/shared/time-dst.h \ > src/shared/calendarspec.c \ > src/shared/calendarspec.h \ > src/shared/fileio.c \ > diff --git a/src/shared/time-dst.c b/src/shared/time-dst.c > deleted file mode 100644 > index 2797d1a..0000000 > --- a/src/shared/time-dst.c > +++ /dev/null > @@ -1,329 +0,0 @@ > -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ > - > -/*** > - This file is part of systemd. > - > - Timezone file reading code from glibc 2.16. > - > - Copyright (C) 1991-2012 Free Software Foundation, Inc. > - Copyright 2012 Kay Sievers > - > - systemd is free software; you can redistribute it and/or modify it > - under the terms of the GNU Lesser General Public License as published by > - the Free Software Foundation; either version 2.1 of the License, or > - (at your option) any later version. > - > - systemd is distributed in the hope that it will be useful, but > - WITHOUT ANY WARRANTY; without even the implied warranty of > - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - Lesser General Public License for more details. > - > - You should have received a copy of the GNU Lesser General Public License > - along with systemd; If not, see <http://www.gnu.org/licenses/>. > -***/ > -#include <errno.h> > -#include <stddef.h> > -#include <stdio.h> > -#include <string.h> > -#include <time.h> > -#include <endian.h> > -#include <stdint.h> > -#include <stdbool.h> > -#include <sys/stat.h> > - > -#include "time-dst.h" > -#include "util.h" > - > -/* > - * If tzh_version is '2' or greater, the above is followed by a second > instance > - * of tzhead and a second instance of the data in which each coded transition > - * time uses 8 rather than 4 chars, then a > POSIX-TZ-environment-variable-style > - * string for use in handling instants after the last transition time stored > in > - * the file * (with nothing between the newlines if there is no POSIX > - * representation for such instants). > - */ > -#define TZ_MAGIC "TZif" > -struct tzhead { > - char tzh_magic[4]; /* TZ_MAGIC */ > - char tzh_version[1]; /* '\0' or '2' as of 2005 */ > - char tzh_reserved[15]; /* reserved--must be zero */ > - char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ > - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ > - char tzh_leapcnt[4]; /* coded number of leap seconds */ > - char tzh_timecnt[4]; /* coded number of transition times */ > - char tzh_typecnt[4]; /* coded number of local time types */ > - char tzh_charcnt[4]; /* coded number of abbr. chars */ > -}; > - > -struct ttinfo { > - long int offset; /* Seconds east of GMT. */ > - unsigned char isdst; /* Used to set tm_isdst. */ > - unsigned char idx; /* Index into `zone_names'. */ > - unsigned char isstd; /* Transition times are in standard time. */ > - unsigned char isgmt; /* Transition times are in GMT. */ > -}; > - > -struct leap { > - time_t transition; /* Time the transition takes effect. */ > - long int change; /* Seconds of correction to apply. */ > -}; > - > -static inline int decode(const void *ptr) { > - return be32toh(*(int *)ptr); > -} > - > -static inline int64_t decode64(const void *ptr) { > - return be64toh(*(int64_t *)ptr); > -} > - > -int time_get_dst(time_t date, const char *tzfile, > - time_t *switch_cur, char **zone_cur, bool *dst_cur, > - time_t *switch_next, int *delta_next, char **zone_next, > bool *dst_next) { > - unsigned char *type_idxs = 0; > - size_t num_types = 0; > - struct ttinfo *types = NULL; > - char *zone_names = NULL; > - struct stat st; > - size_t num_isstd, num_isgmt; > - struct tzhead tzhead; > - size_t chars; > - size_t i; > - size_t total_size; > - size_t types_idx; > - int trans_width = 4; > - size_t tzspec_len; > - size_t num_leaps; > - size_t lo, hi; > - size_t num_transitions = 0; > - _cleanup_free_ time_t *transitions = NULL; > - _cleanup_fclose_ FILE *f; > - > - f = fopen(tzfile, "re"); > - if (f == NULL) > - return -errno; > - > - if (fstat(fileno(f), &st) < 0) > - return -errno; > - > -read_again: > - if (fread((void *)&tzhead, sizeof(tzhead), 1, f) != 1 || > - memcmp(tzhead.tzh_magic, TZ_MAGIC, sizeof(tzhead.tzh_magic)) != > 0) > - return -EINVAL; > - > - num_transitions = (size_t)decode(tzhead.tzh_timecnt); > - num_types = (size_t)decode(tzhead.tzh_typecnt); > - chars = (size_t)decode(tzhead.tzh_charcnt); > - num_leaps = (size_t)decode(tzhead.tzh_leapcnt); > - num_isstd = (size_t)decode(tzhead.tzh_ttisstdcnt); > - num_isgmt = (size_t)decode(tzhead.tzh_ttisgmtcnt); > - > - /* For platforms with 64-bit time_t we use the new format if > available. */ > - if (sizeof(time_t) == 8 && trans_width == 4 && tzhead.tzh_version[0] > != '\0') { > - size_t to_skip; > - > - /* We use the 8-byte format. */ > - trans_width = 8; > - > - /* Position the stream before the second header. */ > - to_skip = (num_transitions * (4 + 1) > - + num_types * 6 > - + chars > - + num_leaps * 8 + num_isstd + num_isgmt); > - if (fseek(f, to_skip, SEEK_CUR) != 0) > - return -EINVAL; > - > - goto read_again; > - } > - > - if (num_transitions > ((SIZE_MAX - (__alignof__(struct ttinfo) - 1)) > / (sizeof(time_t) + 1))) > - return -EINVAL; > - > - total_size = num_transitions * (sizeof(time_t) + 1); > - total_size = ((total_size + __alignof__(struct ttinfo) - 1) & > ~(__alignof__(struct ttinfo) - 1)); > - types_idx = total_size; > - if (num_leaps > (SIZE_MAX - total_size) / sizeof(struct ttinfo)) > - return -EINVAL; > - > - total_size += num_types * sizeof(struct ttinfo); > - if (chars > SIZE_MAX - total_size) > - return -EINVAL; > - > - total_size += chars; > - if (__alignof__(struct leap) - 1 > SIZE_MAX - total_size) > - return -EINVAL; > - > - total_size = ((total_size + __alignof__(struct leap) - 1) & > ~(__alignof__(struct leap) - 1)); > - if (num_leaps > (SIZE_MAX - total_size) / sizeof(struct leap)) > - return -EINVAL; > - > - total_size += num_leaps * sizeof(struct leap); > - tzspec_len = 0; > - if (sizeof(time_t) == 8 && trans_width == 8) { > - off_t rem = st.st_size - ftello(f); > - > - if (rem < 0 || (size_t) rem < (num_transitions * (8 + 1) + > num_types * 6 + chars)) > - return -EINVAL; > - tzspec_len = (size_t) rem - (num_transitions * (8 + 1) + > num_types * 6 + chars); > - if (num_leaps > SIZE_MAX / 12 || tzspec_len < num_leaps * 12) > - return -EINVAL; > - tzspec_len -= num_leaps * 12; > - if (tzspec_len < num_isstd) > - return -EINVAL; > - tzspec_len -= num_isstd; > - if (tzspec_len == 0 || tzspec_len - 1 < num_isgmt) > - return -EINVAL; > - tzspec_len -= num_isgmt + 1; > - if (SIZE_MAX - total_size < tzspec_len) > - return -EINVAL; > - } > - > - /* leave space for additional zone_names zero terminator */ > - transitions = malloc0(total_size + tzspec_len + 1); > - if (transitions == NULL) > - return -EINVAL; > - > - type_idxs = (unsigned char *)transitions + (num_transitions > - * sizeof(time_t)); > - types = (struct ttinfo *)((char *)transitions + types_idx); > - zone_names = (char *)types + num_types * sizeof(struct ttinfo); > - > - if (sizeof(time_t) == 4 || trans_width == 8) { > - if (fread(transitions, trans_width + 1, num_transitions, f) > != num_transitions) > - return -EINVAL; > - } else { > - if (fread(transitions, 4, num_transitions, f) != > num_transitions || > - fread(type_idxs, 1, num_transitions, f) != > num_transitions) > - return -EINVAL; > - } > - > - /* Check for bogus indices in the data file, so we can hereafter > - safely use type_idxs[T] as indices into `types' and never crash. > */ > - for (i = 0; i < num_transitions; ++i) > - if (type_idxs[i] >= num_types) > - return -EINVAL; > - > - if (__BYTE_ORDER == __BIG_ENDIAN ? sizeof(time_t) == 8 && > trans_width == 4 > - : sizeof(time_t) == 4 || > trans_width == 4) { > - /* Decode the transition times, stored as 4-byte integers in > - network (big-endian) byte order. We work from the end of > - the array so as not to clobber the next element to be > - processed when sizeof (time_t) > 4. */ > - i = num_transitions; > - while (i-- > 0) > - transitions[i] = decode((char *)transitions + i * 4); > - } else if (__BYTE_ORDER != __BIG_ENDIAN && sizeof(time_t) == 8) { > - /* Decode the transition times, stored as 8-byte integers in > - network (big-endian) byte order. */ > - for (i = 0; i < num_transitions; ++i) > - transitions[i] = decode64((char *)transitions + i * > 8); > - } > - > - for (i = 0; i < num_types; ++i) { > - unsigned char x[4]; > - int c; > - > - if (fread(x, 1, sizeof(x), f) != sizeof(x)) > - return -EINVAL; > - c = getc(f); > - if ((unsigned int)c > 1u) > - return -EINVAL; > - types[i].isdst = c; > - c = getc(f); > - if ((size_t) c > chars) > - /* Bogus index in data file. */ > - return -EINVAL; > - types[i].idx = c; > - types[i].offset = (long int)decode(x); > - } > - > - if (fread(zone_names, 1, chars, f) != chars) > - return -EINVAL; > - > - zone_names[chars] = '\0'; > - > - for (i = 0; i < num_isstd; ++i) { > - int c = getc(f); > - if (c == EOF) > - return -EINVAL; > - types[i].isstd = c != 0; > - } > - > - while (i < num_types) > - types[i++].isstd = 0; > - > - for (i = 0; i < num_isgmt; ++i) { > - int c = getc(f); > - if (c == EOF) > - return -EINVAL; > - types[i].isgmt = c != 0; > - } > - > - while (i < num_types) > - types[i++].isgmt = 0; > - > - if (num_transitions == 0) > - return -EINVAL; > - > - if (date < transitions[0] || date >= transitions[num_transitions - > 1]) > - return -EINVAL; > - > - /* Find the first transition after TIMER, and > - then pick the type of the transition before it. */ > - lo = 0; > - hi = num_transitions - 1; > - > - /* Assume that DST is changing twice a year and guess initial > - search spot from it. > - Half of a gregorian year has on average 365.2425 * 86400 / 2 > - = 15778476 seconds. */ > - i = (transitions[num_transitions - 1] - date) / 15778476; > - if (i < num_transitions) { > - i = num_transitions - 1 - i; > - if (date < transitions[i]) { > - if (i < 10 || date >= transitions[i - 10]) { > - /* Linear search. */ > - while (date < transitions[i - 1]) > - i--; > - goto found; > - } > - hi = i - 10; > - } else { > - if (i + 10 >= num_transitions || date < > transitions[i + 10]) { > - /* Linear search. */ > - while (date >= transitions[i]) > - i++; > - goto found; > - } > - lo = i + 10; > - } > - } > - > - /* Binary search. */ > - while (lo + 1 < hi) { > - i = (lo + hi) / 2; > - if (date < transitions[i]) > - hi = i; > - else > - lo = i; > - } > - i = hi; > - > -found: > - if (switch_cur) > - *switch_cur = transitions[i-1]; > - if (zone_cur) > - *zone_cur = strdup(&zone_names[types[type_idxs[i - 1]].idx]); > - if (dst_cur) > - *dst_cur = types[type_idxs[i-1]].isdst; > - > - if (switch_next) > - *switch_next = transitions[i]; > - if (delta_next) > - *delta_next = (types[type_idxs[i]].offset - > types[type_idxs[i-1]].offset) / 60; > - if (zone_next) > - *zone_next = strdup(&zone_names[types[type_idxs[i]].idx]); > - if (dst_next) > - *dst_next = types[type_idxs[i]].isdst; > - > - return 0; > -} > diff --git a/src/shared/time-dst.h b/src/shared/time-dst.h > deleted file mode 100644 > index 536b6bb..0000000 > --- a/src/shared/time-dst.h > +++ /dev/null > @@ -1,26 +0,0 @@ > -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ > - > -#pragma once > - > -/*** > - This file is part of systemd. > - > - Copyright 2012 Kay Sievers > - > - 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/>. > -***/ > - > -int time_get_dst(time_t date, const char *tzfile, > - time_t *switch_cur, char **zone_cur, bool *dst_cur, > - time_t *switch_next, int *delta_next, char **zone_next, > bool *dst_next); > diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c > index 44d329e..ab5c8a1 100644 > --- a/src/timedate/timedatectl.c > +++ b/src/timedate/timedatectl.c > @@ -33,7 +33,6 @@ > #include "build.h" > #include "strv.h" > #include "pager.h" > -#include "time-dst.h" > > static bool arg_no_pager = false; > static bool arg_ask_password = true; > @@ -73,33 +72,12 @@ typedef struct StatusInfo { > bool ntp_synced; > } StatusInfo; > > -static const char *jump_str(int delta_minutes, char *s, size_t size) { > - if (delta_minutes == 60) > - return "one hour forward"; > - if (delta_minutes == -60) > - return "one hour backwards"; > - if (delta_minutes < 0) { > - snprintf(s, size, "%i minutes backwards", -delta_minutes); > - return s; > - } > - if (delta_minutes > 0) { > - snprintf(s, size, "%i minutes forward", delta_minutes); > - return s; > - } > - return ""; > -} > - > static void print_status_info(const StatusInfo *i) { > char a[FORMAT_TIMESTAMP_MAX]; > - char b[FORMAT_TIMESTAMP_MAX]; > - char s[32]; > struct tm tm; > time_t sec; > bool have_time = false; > _cleanup_free_ char *zc = NULL, *zn = NULL; > - time_t t, tc, tn; > - int dn = 0; > - bool is_dstc = false, is_dstn = false; > int r; > > assert(i); > @@ -158,40 +136,6 @@ static void print_status_info(const StatusInfo *i) { > yes_no(i->ntp_synced), > yes_no(i->rtc_local)); > > - if (have_time) { > - r = time_get_dst(sec, "/etc/localtime", > - &tc, &zc, &is_dstc, > - &tn, &dn, &zn, &is_dstn); > - if (r < 0) > - printf(" DST active: %s\n", "n/a"); > - else { > - printf(" DST active: %s\n", yes_no(is_dstc)); > - > - t = tc - 1; > - 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(&tc, &tm)); > - printf(" Last DST change: DST %s at\n" > - " %.*s\n" > - " %.*s\n", > - is_dstc ? "began" : "ended", > - (int) sizeof(a), a, > - (int) sizeof(b), b); > - > - t = tn - 1; > - 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)), > - (int) sizeof(a), a, > - (int) sizeof(b), b); > - } > - } else > - printf(" DST active: %s\n", yes_no(is_dstc)); > - > if (i->rtc_local) > fputs("\n" ANSI_HIGHLIGHT_ON > "Warning: The system is configured to read the RTC > time in the local time zone. This\n" > > _______________________________________________ > systemd-commits mailing list > [email protected] > http://lists.freedesktop.org/mailman/listinfo/systemd-commits _______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
