summaryrefslogtreecommitdiffstats
path: root/src/xplist.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2016-09-19 03:10:04 +0200
committerGravatar Nikias Bassen2016-09-19 03:10:04 +0200
commit8d34de3078469aba636846a15bad08198f66fdc8 (patch)
treedb97f8ccb45f35f28348b7e2bffc070b87297089 /src/xplist.c
parent912cb45928f03355ca162a2f1286ca49eb58155c (diff)
downloadlibplist-8d34de3078469aba636846a15bad08198f66fdc8.tar.gz
libplist-8d34de3078469aba636846a15bad08198f66fdc8.tar.bz2
Use time64 implementation by Michael G Schwern to extend allowed date/time range
The main benefit of this is to allow date/time values outside of the 32bit time_t range which is very important on 32bit platforms. But there are also some other issues that will be fixed with this, for example on macOS, mktime() will not work for dates < 1902 despite time_t being 64bit. In the same run this commit will also use a reentrant version of gmtime64_r that should help in multithreaded scenarios. Original code taken from: https://github.com/evalEmpire/y2038
Diffstat (limited to 'src/xplist.c')
-rw-r--r--src/xplist.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/src/xplist.c b/src/xplist.c
index e55a094..fc665ac 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -41,6 +41,7 @@
41 41
42#include "plist.h" 42#include "plist.h"
43#include "base64.h" 43#include "base64.h"
44#include "time64.h"
44 45
45#define XPLIST_TEXT BAD_CAST("text") 46#define XPLIST_TEXT BAD_CAST("text")
46#define XPLIST_KEY BAD_CAST("key") 47#define XPLIST_KEY BAD_CAST("key")
@@ -258,12 +259,15 @@ static void node_to_xml(node_t* node, void *xml_struct)
258 case PLIST_DATE: 259 case PLIST_DATE:
259 tag = XPLIST_DATE; 260 tag = XPLIST_DATE;
260 { 261 {
261 time_t timev = (time_t)node_data->realval + MAC_EPOCH; 262 Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
262 struct tm *btime = gmtime(&timev); 263 struct TM _btime;
264 struct TM *btime = gmtime64_r(&timev, &_btime);
263 if (btime) { 265 if (btime) {
264 val = (char*)malloc(24); 266 val = (char*)malloc(24);
265 memset(val, 0, 24); 267 memset(val, 0, 24);
266 if (strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) { 268 struct tm _tmcopy;
269 copy_TM64_to_tm(btime, &_tmcopy);
270 if (strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", &_tmcopy) <= 0) {
267 free (val); 271 free (val);
268 val = NULL; 272 val = NULL;
269 } 273 }
@@ -346,7 +350,7 @@ static void node_to_xml(node_t* node, void *xml_struct)
346 return; 350 return;
347} 351}
348 352
349static void parse_date(const char *strval, struct tm *btime) 353static void parse_date(const char *strval, struct TM *btime)
350{ 354{
351 if (!btime) return; 355 if (!btime) return;
352 memset(btime, 0, sizeof(struct tm)); 356 memset(btime, 0, sizeof(struct tm));
@@ -354,7 +358,12 @@ static void parse_date(const char *strval, struct tm *btime)
354#ifdef strptime 358#ifdef strptime
355 strptime((char*)strval, "%Y-%m-%dT%H:%M:%SZ", btime); 359 strptime((char*)strval, "%Y-%m-%dT%H:%M:%SZ", btime);
356#else 360#else
357 sscanf(strval, "%d-%d-%dT%d:%d:%dZ", &btime->tm_year, &btime->tm_mon, &btime->tm_mday, &btime->tm_hour, &btime->tm_min, &btime->tm_sec); 361#ifdef USE_TM64
362 #define PLIST_SSCANF_FORMAT "%lld-%d-%dT%d:%d:%dZ"
363#else
364 #define PLIST_SSCANF_FORMAT "%d-%d-%dT%d:%d:%dZ"
365#endif
366 sscanf(strval, PLIST_SSCANF_FORMAT, &btime->tm_year, &btime->tm_mon, &btime->tm_mday, &btime->tm_hour, &btime->tm_min, &btime->tm_sec);
358 btime->tm_year-=1900; 367 btime->tm_year-=1900;
359 btime->tm_mon--; 368 btime->tm_mon--;
360#endif 369#endif
@@ -453,14 +462,11 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
453 if (!xmlStrcmp(node->name, XPLIST_DATE)) 462 if (!xmlStrcmp(node->name, XPLIST_DATE))
454 { 463 {
455 xmlChar *strval = xmlNodeGetContent(node); 464 xmlChar *strval = xmlNodeGetContent(node);
456 time_t timev = 0; 465 Time64_T timev = 0;
457 if (strlen((const char*)strval) >= 11) { 466 if (strlen((const char*)strval) >= 11) {
458 struct tm btime; 467 struct TM btime;
459 struct tm* tm_utc;
460 parse_date((const char*)strval, &btime); 468 parse_date((const char*)strval, &btime);
461 timev = mktime(&btime); 469 timev = timegm64(&btime);
462 tm_utc = gmtime(&timev);
463 timev -= (mktime(tm_utc) - timev);
464 } 470 }
465 data->realval = (double)(timev - MAC_EPOCH); 471 data->realval = (double)(timev - MAC_EPOCH);
466 data->type = PLIST_DATE; 472 data->type = PLIST_DATE;