[git commit master] optional /etc/localtime support

Denys Vlasenko vda.linux at googlemail.com
Thu Apr 29 15:17:18 UTC 2010


commit: http://git.uclibc.org/uClibc/commit/?id=87327f43e4ea65d63ceab0985cf814e22940579a
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/master

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 at googlemail.com>
---
 extra/Configs/Config.in |   11 +++++++++++
 libc/misc/time/time.c   |   44 +++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 21c14ac..6803659 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 dfa8c0d..f80104e 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;
 }
 
-- 
1.6.3.3



More information about the uClibc-cvs mailing list