summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-04-29 17:17:18 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-04-29 17:17:18 +0200
commit87327f43e4ea65d63ceab0985cf814e22940579a (patch)
tree3241c8376e431c8bd4e02618a030aaafc1580fba
parentf26c5f6952ce9bf8edec9c1571c47addb1bcc442 (diff)
optional /etc/localtime support
This patch teaches uclibc to use /etc/localtime. This is possible since recent TZif2 file format contains TZ-like ASCII string at the end. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--extra/Configs/Config.in11
-rw-r--r--libc/misc/time/time.c44
2 files changed, 52 insertions, 3 deletions
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 21c14acf4..680365980 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -848,6 +848,17 @@ config UCLIBC_TZ_FILE_PATH
Most people will use the default of '/etc/TZ'.
+config UCLIBC_FALLBACK_TO_ETC_LOCALTIME
+ bool "Use /etc/localtime as a fallback"
+ depends on UCLIBC_HAS_TZ_FILE
+ default y
+ help
+ Answer Y to try to use /etc/localtime file.
+ On glibc systems this file (if it is in TZif2 format)
+ contains timezone string at the end.
+
+ Most people will answer Y.
+
endmenu
menu "Advanced Library Settings"
diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
index dfa8c0daf..f80104ee1 100644
--- a/libc/misc/time/time.c
+++ b/libc/misc/time/time.c
@@ -1804,12 +1804,12 @@ static smallint TZ_file_read; /* Let BSS initialization set this to 0. */
static char *read_TZ_file(char *buf)
{
+ int r;
int fd;
char *p = NULL;
fd = open(__UCLIBC_TZ_FILE_PATH__, O_RDONLY);
if (fd >= 0) {
- ssize_t r;
#if 0
/* TZ are small *files*. On files, short reads
* only occur on EOF (unlike, say, pipes).
@@ -1829,13 +1829,12 @@ static char *read_TZ_file(char *buf)
todo -= r;
} while (todo);
#else
- /* Shorter, and does one less read syscall */
+ /* Shorter, and does one fewer read syscall */
r = read(fd, buf, TZ_BUFLEN);
if (r < 0)
goto ERROR;
p = buf + r;
#endif
-
if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline */
p[-1] = 0;
p = buf;
@@ -1848,6 +1847,45 @@ ERROR:
}
close(fd);
}
+#ifdef __UCLIBC_FALLBACK_TO_ETC_LOCALTIME__
+ else {
+ fd = open("/etc/localtime", O_RDONLY);
+ if (fd >= 0) {
+ r = read(fd, buf, TZ_BUFLEN);
+ if (r != TZ_BUFLEN
+ || strncmp(buf, "TZif", 4) != 0
+ || (unsigned char)buf[4] < 2
+ || lseek(fd, -TZ_BUFLEN, SEEK_END) < 0
+ ) {
+ goto ERROR;
+ }
+ /* tzfile.h from tzcode database says about TZif2+ files:
+ **
+ ** 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).
+ */
+ r = read(fd, buf, TZ_BUFLEN);
+ if (r <= 0 || buf[--r] != '\n')
+ goto ERROR;
+ buf[r] = 0;
+ while (r != 0) {
+ if (buf[--r] == '\n') {
+ p = buf + r + 1;
+#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__
+ TZ_file_read = 1;
+#endif
+ break;
+ }
+ } /* else ('\n' not found): p remains NULL */
+ close(fd);
+ }
+ }
+#endif /* __UCLIBC_FALLBACK_TO_ETC_LOCALTIME__ */
return p;
}