From: Evan Hunt Date: Wed, 15 Jan 2014 07:12:17 +0000 (-0800) Subject: [master] portable strptime/timegm X-Git-Tag: v9.10.0a2~89 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a147de10fe5e19e593d42152ffd6879eca69860d;p=thirdparty%2Fbind9.git [master] portable strptime/timegm 3709. [port] Use built-in versions of strptime() and timegm() on all platforms to avoid portability issues. [RT #35183] --- diff --git a/CHANGES b/CHANGES index b5600676d5b..a7de036e47f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3709. [port] Use built-in versions of strptime() and timegm() + on all platforms to avoid portability issues. + [RT #35183] + 3708. [bug] Address a portentry locking issue in dispatch.c. [RT #35128] diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 1d5fc4dd0a8..6da9e3c1125 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -66,7 +66,8 @@ OBJS = @ISC_EXTRA_OBJS@ \ rwlock.@O@ \ safe.@O@ serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \ string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \ - timer.@O@ version.@O@ ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} + tm.@O@ timer.@O@ version.@O@ \ + ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} SYMTBLOBJS = backtrace-emptytbl.@O@ # Alphabetically @@ -82,7 +83,7 @@ SRCS = @ISC_EXTRA_SRCS@ \ ratelimiter.c refcount.c region.c regex.c result.c rwlock.c \ safe.c serial.c sha1.c sha2.c sockaddr.c stats.c string.c \ strtoul.c symtab.c symtbl-empty.c task.c taskpool.c timer.c \ - version.c + tm.c version.c LIBS = @LIBS@ diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in index 2da5845cd69..e01e1030212 100644 --- a/lib/isc/include/isc/Makefile.in +++ b/lib/isc/include/isc/Makefile.in @@ -31,16 +31,15 @@ HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ eventclass.h file.h formatcheck.h fsaccess.h \ hash.h heap.h hex.h hmacmd5.h hmacsha.h \ httpd.h \ - interfaceiter.h @ISC_IPV6_H@ iterated_hash.h json.h lang.h lex.h \ - lfsr.h lib.h list.h log.h \ + interfaceiter.h @ISC_IPV6_H@ iterated_hash.h json.h \ + lang.h lex.h lfsr.h lib.h list.h log.h \ magic.h md5.h mem.h msgcat.h msgs.h mutexblock.h \ netaddr.h ondestroy.h os.h parseint.h \ print.h quota.h radix.h random.h ratelimiter.h \ refcount.h regex.h region.h resource.h \ result.h resultclass.h rwlock.h safe.h serial.h sha1.h sha2.h \ - sockaddr.h socket.h stdio.h stdlib.h string.h \ - symtab.h \ - task.h taskpool.h timer.h types.h util.h version.h \ + sockaddr.h socket.h stdio.h stdlib.h string.h symtab.h \ + task.h taskpool.h timer.h tm.h types.h util.h version.h \ xml.h SUBDIRS = diff --git a/lib/isc/include/isc/tm.h b/lib/isc/include/isc/tm.h new file mode 100644 index 00000000000..43e2aa34dd8 --- /dev/null +++ b/lib/isc/include/isc/tm.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ISC_TM_H +#define ISC_TM_H 1 + +/*! \file isc/tm.h + * Provides portable conversion routines for struct tm. + */ + +#include + +ISC_LANG_BEGINDECLS + +time_t +isc_tm_timegm(struct tm *tm); +/* + * Convert a tm structure to time_t, using UTC rather than the local + * time zone. + */ + +char * +isc_tm_strptime(const char *buf, const char *fmt, struct tm *tm); +/* + * Parse a formatted date string into struct tm. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_TIMER_H */ diff --git a/lib/isc/win32/strptime.c b/lib/isc/tm.c similarity index 80% rename from lib/isc/win32/strptime.c rename to lib/isc/tm.c index 10dcec1ec17..4f058a6c7c8 100644 --- a/lib/isc/win32/strptime.c +++ b/lib/isc/tm.c @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. @@ -33,11 +49,20 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + #include #include #include #include +/* + * Portable conversion routines for struct tm, replacing + * timegm() and strptime(), which are not available on all + * platforms and don't always behave the same way when they + * are. + */ + /* * We do not implement alternate representations. However, we always * check whether a given modifier is allowed for a certain conversion. @@ -50,8 +75,6 @@ #define TM_YEAR_BASE 1900 #endif -static int conv_num(const char **, int *, int, int); - static const char *day[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" @@ -71,8 +94,57 @@ static const char *am_pm[2] = { "AM", "PM" }; -static char * -strptime(const char *buf, const char *fmt, struct tm *tm) { +static int +conv_num(const char **buf, int *dest, int llim, int ulim) { + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && + rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} + +time_t +isc_tm_timegm(struct tm *tm) { + time_t ret; + int i, yday = 0, leapday; + int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; + + leapday = ((((tm->tm_year + 1900 ) % 4) == 0 && + ((tm->tm_year + 1900 ) % 100) != 0) || + ((tm->tm_year + 1900 ) % 400) == 0) ? 1 : 0; + mdays[1] += leapday; + + yday = tm->tm_mday - 1; + for (i = 1; i <= tm->tm_mon; i++) + yday += mdays[i - 1]; + ret = tm->tm_sec + + (60 * tm->tm_min) + + (3600 * tm->tm_hour) + + (86400 * (yday + + ((tm->tm_year - 70) * 365) + + ((tm->tm_year - 69) / 4) - + ((tm->tm_year - 1) / 100) + + ((tm->tm_year + 299) / 400))); + return (ret); +} + +char * +isc_tm_strptime(const char *buf, const char *fmt, struct tm *tm) { char c; const char *bp; size_t len = 0; @@ -123,43 +195,43 @@ literal: */ case 'c': /* Date and time, using the locale's format. */ LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%x %X", tm))) + if (!(bp = isc_tm_strptime(bp, "%x %X", tm))) return (0); break; case 'D': /* The date as "%m/%d/%y". */ LEGAL_ALT(0); - if (!(bp = strptime(bp, "%m/%d/%y", tm))) + if (!(bp = isc_tm_strptime(bp, "%m/%d/%y", tm))) return (0); break; case 'R': /* The time as "%H:%M". */ LEGAL_ALT(0); - if (!(bp = strptime(bp, "%H:%M", tm))) + if (!(bp = isc_tm_strptime(bp, "%H:%M", tm))) return (0); break; case 'r': /* The time in 12-hour clock representation. */ LEGAL_ALT(0); - if (!(bp = strptime(bp, "%I:%M:%S %p", tm))) + if (!(bp = isc_tm_strptime(bp, "%I:%M:%S %p", tm))) return (0); break; case 'T': /* The time as "%H:%M:%S". */ LEGAL_ALT(0); - if (!(bp = strptime(bp, "%H:%M:%S", tm))) + if (!(bp = isc_tm_strptime(bp, "%H:%M:%S", tm))) return (0); break; case 'X': /* The time, using the locale's format. */ LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%H:%M:%S", tm))) + if (!(bp = isc_tm_strptime(bp, "%H:%M:%S", tm))) return (0); break; case 'x': /* The date, using the locale's format. */ LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%m/%d/%y", tm))) + if (!(bp = isc_tm_strptime(bp, "%m/%d/%y", tm))) return (0); break; @@ -366,27 +438,3 @@ literal: /* LINTED functional specification */ return ((char *)bp); } - -static int -conv_num(const char **buf, int *dest, int llim, int ulim) { - int result = 0; - - /* The limit also determines the number of valid digits. */ - int rulim = ulim; - - if (**buf < '0' || **buf > '9') - return (0); - - do { - result *= 10; - result += *(*buf)++ - '0'; - rulim /= 10; - } while ((result * 10 <= ulim) && - rulim && **buf >= '0' && **buf <= '9'); - - if (result < llim || result > ulim) - return (0); - - *dest = result; - return (1); -} diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c index 9039b06a880..890b9192ba5 100644 --- a/lib/isc/unix/time.c +++ b/lib/isc/unix/time.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #define NS_PER_S 1000000000 /*%< Nanoseconds per second. */ @@ -408,31 +409,6 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { INSIST(flen < len); } -static time_t -timetfromtm(struct tm *tm) { - time_t ret; - int i, yday = 0, leapday; - int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; - - leapday = ((((tm->tm_year + 1900 ) % 4) == 0 && - ((tm->tm_year + 1900 ) % 100) != 0) || - ((tm->tm_year + 1900 ) % 400) == 0) ? 1 : 0; - mdays[1] += leapday; - - yday = tm->tm_mday - 1; - for (i = 1; i <= tm->tm_mon; i++) - yday += mdays[i - 1]; - ret = tm->tm_sec + - (60 * tm->tm_min) + - (3600 * tm->tm_hour) + - (86400 * (yday + - ((tm->tm_year - 70) * 365) + - ((tm->tm_year - 69) / 4) - - ((tm->tm_year - 1) / 100) + - ((tm->tm_year + 299) / 400))); - return (ret); -} - isc_result_t isc_time_parsehttptimestamp(char *buf, isc_time_t *t) { struct tm t_tm; @@ -441,10 +417,10 @@ isc_time_parsehttptimestamp(char *buf, isc_time_t *t) { REQUIRE(buf != NULL); REQUIRE(t != NULL); - p = strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm); + p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm); if (p == NULL) return (ISC_R_UNEXPECTED); - when = timetfromtm(&t_tm); + when = isc_tm_timegm(&t_tm); if (when == -1) return (ISC_R_UNEXPECTED); isc_time_set(t, when, 0); diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index de504c39261..d236307e61b 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -605,6 +605,8 @@ isc_timer_touch isc_timermgr_create isc_timermgr_destroy isc_timermgr_poke +isc_tm_timegm +isc_tm_strptime isc_win32os_majorversion isc_win32os_minorversion isc_win32os_servicepackmajor diff --git a/lib/isc/win32/libisc.dsp.in b/lib/isc/win32/libisc.dsp.in index f6ea61721da..08fe918c4c0 100644 --- a/lib/isc/win32/libisc.dsp.in +++ b/lib/isc/win32/libisc.dsp.in @@ -597,6 +597,10 @@ SOURCE=..\include\isc\timer.h # End Source File # Begin Source File +SOURCE=..\include\isc\tm.h +# End Source File +# Begin Source File + SOURCE=.\include\isc\win32os.h # End Source File # Begin Source File @@ -855,6 +859,10 @@ SOURCE=..\taskpool.c SOURCE=..\timer.c # End Source File +# Begin Source File + +SOURCE=..\tm.c +# End Source File # End Group @IF ATOMIC # Begin Source File diff --git a/lib/isc/win32/libisc.mak.in b/lib/isc/win32/libisc.mak.in index 8ea2bd74917..554429a3436 100644 --- a/lib/isc/win32/libisc.mak.in +++ b/lib/isc/win32/libisc.mak.in @@ -194,6 +194,7 @@ CLEAN : -@erase "$(INTDIR)\thread.obj" -@erase "$(INTDIR)\time.obj" -@erase "$(INTDIR)\timer.obj" + -@erase "$(INTDIR)\tm.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\version.obj" -@erase "$(INTDIR)\win32os.obj" @@ -301,6 +302,7 @@ LINK32_OBJS= \ "$(INTDIR)\task.obj" \ "$(INTDIR)\taskpool.obj" \ "$(INTDIR)\timer.obj" \ + "$(INTDIR)\tm.obj" \ "$(INTDIR)\parseint.obj" \ "$(INTDIR)\pool.obj" \ "$(INTDIR)\portset.obj" \ @@ -485,6 +487,8 @@ CLEAN : -@erase "$(INTDIR)\time.sbr" -@erase "$(INTDIR)\timer.obj" -@erase "$(INTDIR)\timer.sbr" + -@erase "$(INTDIR)\tm.obj" + -@erase "$(INTDIR)\tm.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(INTDIR)\version.obj" @@ -589,6 +593,7 @@ BSC32_SBRS= \ "$(INTDIR)\task.sbr" \ "$(INTDIR)\taskpool.sbr" \ "$(INTDIR)\timer.sbr" \ + "$(INTDIR)\tm.sbr" \ "$(INTDIR)\parseint.sbr" \ "$(INTDIR)\pool.sbr" \ "$(INTDIR)\portset.sbr" \ @@ -686,6 +691,7 @@ LINK32_OBJS= \ "$(INTDIR)\task.obj" \ "$(INTDIR)\taskpool.obj" \ "$(INTDIR)\timer.obj" \ + "$(INTDIR)\tm.obj" \ "$(INTDIR)\parseint.obj" \ "$(INTDIR)\pool.obj" \ "$(INTDIR)\portset.obj" \ @@ -2167,6 +2173,24 @@ SOURCE=..\timer.c $(CPP) $(CPP_PROJ) $(SOURCE) +!ENDIF + +SOURCE=..\tm.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\tm.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\tm.obj" "$(INTDIR)\tm.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + !ENDIF diff --git a/lib/isc/win32/libisc.vcxproj.filters.in b/lib/isc/win32/libisc.vcxproj.filters.in index 281b0df975e..8b25ec4534e 100644 --- a/lib/isc/win32/libisc.vcxproj.filters.in +++ b/lib/isc/win32/libisc.vcxproj.filters.in @@ -245,6 +245,9 @@ Library Header Files + + Library Header Files + Library Header Files @@ -593,5 +596,8 @@ Library Source Files + + Library Source Files + - \ No newline at end of file + diff --git a/lib/isc/win32/libisc.vcxproj.in b/lib/isc/win32/libisc.vcxproj.in index 09fcaddc274..84f0db1236c 100644 --- a/lib/isc/win32/libisc.vcxproj.in +++ b/lib/isc/win32/libisc.vcxproj.in @@ -332,6 +332,7 @@ copy /Y @VCREDIST_PATH@ ..\Build\Release\ + @@ -426,6 +427,7 @@ copy /Y @VCREDIST_PATH@ ..\Build\Release\ + @@ -455,4 +457,4 @@ copy /Y @VCREDIST_PATH@ ..\Build\Release\ - \ No newline at end of file + diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c index 6c38e25a555..d6993f937e4 100644 --- a/lib/isc/win32/time.c +++ b/lib/isc/win32/time.c @@ -30,6 +30,7 @@ #include #include +#include #include /* @@ -318,32 +319,6 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { } } -static time_t -timetfromtm(struct tm *tm) { - time_t ret; - int i, yday = 0, leapday; - int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; - - leapday = ((((tm->tm_year + 1900 ) % 4) == 0 && - ((tm->tm_year + 1900 ) % 100) != 0) || - ((tm->tm_year + 1900 ) % 400) == 0) ? 1 : 0; - mdays[1] += leapday; - - yday = tm->tm_mday - 1; - for (i = 1; i <= tm->tm_mon; i++) - yday += mdays[i - 1]; - ret = tm->tm_sec + - (60 * tm->tm_min) + - (3600 * tm->tm_hour) + - (86400 * (yday + - ((tm->tm_year - 70) * 365) + - ((tm->tm_year - 69) / 4) - - ((tm->tm_year - 1) / 100) + - ((tm->tm_year + 299) / 400))); - return (ret); -} - -#include "strptime.c" isc_result_t isc_time_parsehttptimestamp(char *buf, isc_time_t *t) { struct tm t_tm; @@ -352,10 +327,10 @@ isc_time_parsehttptimestamp(char *buf, isc_time_t *t) { REQUIRE(buf != NULL); REQUIRE(t != NULL); - p = strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm); + p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm); if (p == NULL) return (ISC_R_UNEXPECTED); - when = timetfromtm(&t_tm); + when = isc_tm_timegm(&t_tm); if (when == -1) return (ISC_R_UNEXPECTED); isc_time_set(t, when, 0);