+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]
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
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@
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 =
--- /dev/null
+/*
+ * 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 <time.h>
+
+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 */
+/*
+ * 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.
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <config.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+/*
+ * 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.
#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"
"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;
*/
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;
/* 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);
-}
#include <isc/strerror.h>
#include <isc/string.h>
#include <isc/time.h>
+#include <isc/tm.h>
#include <isc/util.h>
#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
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;
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);
isc_timermgr_create
isc_timermgr_destroy
isc_timermgr_poke
+isc_tm_timegm
+isc_tm_strptime
isc_win32os_majorversion
isc_win32os_minorversion
isc_win32os_servicepackmajor
# 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
SOURCE=..\timer.c
# End Source File
+# Begin Source File
+
+SOURCE=..\tm.c
+# End Source File
# End Group
@IF ATOMIC
# Begin Source File
-@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"
"$(INTDIR)\task.obj" \
"$(INTDIR)\taskpool.obj" \
"$(INTDIR)\timer.obj" \
+ "$(INTDIR)\tm.obj" \
"$(INTDIR)\parseint.obj" \
"$(INTDIR)\pool.obj" \
"$(INTDIR)\portset.obj" \
-@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"
"$(INTDIR)\task.sbr" \
"$(INTDIR)\taskpool.sbr" \
"$(INTDIR)\timer.sbr" \
+ "$(INTDIR)\tm.sbr" \
"$(INTDIR)\parseint.sbr" \
"$(INTDIR)\pool.sbr" \
"$(INTDIR)\portset.sbr" \
"$(INTDIR)\task.obj" \
"$(INTDIR)\taskpool.obj" \
"$(INTDIR)\timer.obj" \
+ "$(INTDIR)\tm.obj" \
"$(INTDIR)\parseint.obj" \
"$(INTDIR)\pool.obj" \
"$(INTDIR)\portset.obj" \
$(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
<ClInclude Include="..\include\isc\timer.h">\r
<Filter>Library Header Files</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\include\isc\tm.h">\r
+ <Filter>Library Header Files</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\include\isc\types.h">\r
<Filter>Library Header Files</Filter>\r
</ClInclude>\r
<ClCompile Include="..\timer.c">\r
<Filter>Library Source Files</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\tm.c">\r
+ <Filter>Library Source Files</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
<ClInclude Include="..\include\isc\task.h" />\r
<ClInclude Include="..\include\isc\taskpool.h" />\r
<ClInclude Include="..\include\isc\timer.h" />\r
+ <ClInclude Include="..\include\isc\tm.h" />\r
<ClInclude Include="..\include\isc\types.h" />\r
<ClInclude Include="..\include\isc\util.h" />\r
<ClInclude Include="..\include\isc\version.h" />\r
<ClCompile Include="..\task.c" />\r
<ClCompile Include="..\taskpool.c" />\r
<ClCompile Include="..\timer.c" />\r
+ <ClCompile Include="..\tm.c" />\r
<ClCompile Include="app.c" />\r
<ClCompile Include="condition.c" />\r
<ClCompile Include="dir.c" />\r
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
<ImportGroup Label="ExtensionTargets">\r
</ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
#include <isc/assertions.h>
#include <isc/time.h>
+#include <isc/tm.h>
#include <isc/util.h>
/*
}
}
-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;
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);