From ef00272e2ffb8ffcf03e740f74691fecb682060d Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 15 May 2014 01:18:52 +0100 Subject: add helpers for time_t reading/writing --- content/llcache.c | 62 +++++++++++++++++++++++++++++++----------------------- utils/config.h | 10 +++++---- utils/time.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++ utils/utils.c | 63 ++++++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 141 insertions(+), 47 deletions(-) create mode 100644 utils/time.h diff --git a/content/llcache.c b/content/llcache.c index 5137b2240..8c1cc3df6 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -35,7 +35,6 @@ #include #include -#include #include #include "utils/config.h" @@ -45,6 +44,7 @@ #include "utils/messages.h" #include "utils/nsurl.h" #include "utils/utils.h" +#include "utils/time.h" #include "desktop/gui_factory.h" #include "content/fetch.h" @@ -1105,7 +1105,6 @@ llcache_serialise_metadata(llcache_object *object, char *op; unsigned int hloop; int use; - struct tm *ltm; allocsize = 10 + 1; /* object length */ @@ -1133,22 +1132,30 @@ llcache_serialise_metadata(llcache_object *object, datasize = allocsize; /* the url, used for checking for collisions */ - use = snprintf(op, datasize, "%s%c", nsurl_access(object->url), 0); - if (use > datasize) + use = snprintf(op, datasize, "%s", nsurl_access(object->url)); + if (use < 0) { + goto operror; + } + use++; /* does not count the null */ + if (use > datasize) { goto overflow; + } op += use; datasize -= use; /* object size */ - use = snprintf(op, datasize, "%zu%c", object->source_len, 0); + use = snprintf(op, datasize, "%zu", object->source_len); + if (use < 0) { + goto operror; + } + use++; /* does not count the null */ if (use > datasize) goto overflow; op += use; datasize -= use; /* Time of request */ - ltm = localtime(&object->cache.req_time); - use = strftime(op, datasize, "%s", ltm); + use = nsc_sntimet(op, datasize, &object->cache.req_time); if (use == 0) goto overflow; use++; /* does not count the null */ @@ -1156,8 +1163,7 @@ llcache_serialise_metadata(llcache_object *object, datasize -= use; /* Time of response */ - ltm = localtime(&object->cache.res_time); - use = strftime(op, datasize, "%s", ltm); + use = nsc_sntimet(op, datasize, &object->cache.res_time); if (use == 0) goto overflow; use++; /* does not count the null */ @@ -1165,8 +1171,7 @@ llcache_serialise_metadata(llcache_object *object, datasize -= use; /* Time of completion */ - ltm = localtime(&object->cache.fin_time); - use = strftime(op, datasize, "%s", ltm); + use = nsc_sntimet(op, datasize, &object->cache.fin_time); if (use == 0) goto overflow; use++; /* does not count the null */ @@ -1174,7 +1179,11 @@ llcache_serialise_metadata(llcache_object *object, datasize -= use; /* number of headers */ - use = snprintf(op, datasize, "%zu%c", object->num_headers, 0); + use = snprintf(op, datasize, "%zu", object->num_headers); + if (use < 0) { + goto operror; + } + use++; /* does not count the null */ if (use > datasize) goto overflow; op += use; @@ -1183,10 +1192,13 @@ llcache_serialise_metadata(llcache_object *object, /* headers */ for (hloop = 0 ; hloop < object->num_headers ; hloop++) { use = snprintf(op, datasize, - "%s:%s%c", + "%s:%s", object->headers[hloop].name, - object->headers[hloop].value, - 0); + object->headers[hloop].value); + if (use < 0) { + goto operror; + } + use++; /* does not count the null */ if (use > datasize) goto overflow; op += use; @@ -1205,6 +1217,12 @@ overflow: LOG(("Overflowed metadata buffer")); free(data); return NSERROR_INVALID; + +operror: + /* output error */ + LOG(("Output error")); + free(data); + return NSERROR_INVALID; } /** @@ -1223,7 +1241,6 @@ llcache_process_metadata(llcache_object *object) int lnsize; size_t num_headers; size_t hloop; - struct tm ltm; enum backing_store_flags flags = BACKING_STORE_META; LOG(("Retriving metadata")); @@ -1290,31 +1307,24 @@ llcache_process_metadata(llcache_object *object) ln += lnsize + 1; lnsize = strlen(ln); - if ((lnsize < 1) || - (strptime(ln, "%s", <m) == NULL)) + if (nsc_snptimet(ln, lnsize, &object->cache.req_time) != NSERROR_OK) goto format_error; - object->cache.req_time = mktime(<m); /* metadata line 4 is the time of response */ line = 4; ln += lnsize + 1; lnsize = strlen(ln); - if ((lnsize < 1) || - (strptime(ln, "%s", <m) == NULL)) + if (nsc_snptimet(ln, lnsize, &object->cache.res_time) != NSERROR_OK) goto format_error; - object->cache.res_time = mktime(<m); /* metadata line 5 is the time of request completion */ line = 5; ln += lnsize + 1; lnsize = strlen(ln); - if ((lnsize < 1) || - (strptime(ln, "%s", <m) == NULL)) + if (nsc_snptimet(ln, lnsize, &object->cache.fin_time) != NSERROR_OK) goto format_error; - object->cache.fin_time = mktime(<m); - /* metadata line 6 is the number of headers */ line = 6; diff --git a/utils/config.h b/utils/config.h index cc4f75191..c0a3c0d1b 100644 --- a/utils/config.h +++ b/utils/config.h @@ -38,13 +38,15 @@ char *strndup(const char *s, size_t n); char *strcasestr(const char *haystack, const char *needle); #endif -#if (defined(riscos) || defined(_WIN32)) +/* Although these platforms might have strftime or strptime they + * appear not to support the time_t seconds format specifier. + */ +#if (defined(_WIN32) || defined(riscos) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__)) #undef HAVE_STRPTIME -#define strptime nsc_time_strptime -struct tm; -char *nsc_time_strptime(const char *s, const char *format, struct tm *tm); +#undef HAVE_STRFTIME #else #define HAVE_STRPTIME +#define HAVE_STRFTIME #endif /* For some reason, UnixLib defines this unconditionally. diff --git a/utils/time.h b/utils/time.h new file mode 100644 index 000000000..bde2ff66a --- /dev/null +++ b/utils/time.h @@ -0,0 +1,53 @@ +/* + * Copyright 2014 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file utils/time.h + * \brief Interface to time operations. + */ + +#ifndef _NETSURF_UTILS_TIME_H_ +#define _NETSURF_UTILS_TIME_H_ + +#include + +/** + * Write the time in seconds since epoch to a buffer. + * + * This is provided as strftime is not generally portable. + * + * @param str The destination buffer. + * @param size The length of the destination buffer. + * @param timep The pointer to the time to write. + * @return The length of the string written. + */ +int nsc_sntimet(char *str, size_t size, time_t *timep); + +/** + * Parse time in seconds since epoc. + * + * This is provided as strptime is not generally portable. + * + * @param str The source buffer. + * @param size The length of the source buffer. + * @param timep Pointer to result. + * @return NSERROR_OK on success or error code on faliure. + */ +nserror nsc_snptimet(char *str, size_t size, time_t *timep); + +#endif diff --git a/utils/utils.c b/utils/utils.c index 953cc5cad..6199a8451 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -35,6 +35,7 @@ #include "utils/config.h" #include "utils/messages.h" #include "utils/utf8.h" +#include "utils/time.h" #include "utils/utils.h" /* exported interface documented in utils/utils.h */ @@ -566,29 +567,57 @@ int inet_pton(int af, const char *src, void *dst) #endif -#ifndef HAVE_STRPTIME +/* exported function documented in utils/time.h */ +int nsc_sntimet(char *str, size_t size, time_t *timep) +{ +#ifndef HAVE_STRFTIME + long long val; + val = (long long)*timep; -/** - * naff strptime implementation for risc os and windows. - * - * @warning only supports %s format - */ -char *nsc_time_strptime(const char *s, const char *format, struct tm *tm) + return snprintf(str, size, "%lld", val); +#else + struct tm *ltm; + + ltm = localtime(timep); + if (ltm == NULL) { + return -1; + } + + return strftime(str, size, "%s", ltm); +#endif +} + +nserror nsc_snptimet(char *str, size_t size, time_t *timep) { - time_t esecs; - struct tm *gtm; - char *endptr; + time_t time_out; - if ((format[0] != '%') || (format[1] != 's')) { - return NULL; +#ifndef HAVE_STRPTIME + + if (size < 1) { + return NSERROR_BAD_PARAMETER; } - esecs = (time_t)strtoll(s, &endptr, 10); + time_out = (time_t)strtoll(str, NULL, 10); - gtm = gmtime(esecs); - *tm = *gtm; + if (time_out == 0) { + return NSERROR_BAD_PARAMETER; + } - return endptr; -} +#else + struct tm ltm; + + if (size < 1) { + return NSERROR_BAD_PARAMETER; + } + + if (strptime(str, "%s", <m) == NULL) { + return NSERROR_BAD_PARAMETER; + } + + time_out = mktime(<m); #endif + *timep = time_out; + + return NSERROR_OK; +} -- cgit v1.2.3