From a0f747067d87c94cc6fedccc0ebad6011362c327 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Sat, 3 Jan 2009 19:21:46 +0000 Subject: [PATCH] Add functions to load/set leap second table --- src/libiso8601/000_TopSource.c | 3 ++ src/libiso8601/100_leap.c | 74 ++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/libiso8601/000_TopSource.c b/src/libiso8601/000_TopSource.c index 087d455..9a7e9a7 100644 --- a/src/libiso8601/000_TopSource.c +++ b/src/libiso8601/000_TopSource.c @@ -10,9 +10,12 @@ /* Below are all the includes used throughout the library. */ #include #include +#include #include #include #include +#include +#include #include /* Useful define to alleviate typos */ diff --git a/src/libiso8601/100_leap.c b/src/libiso8601/100_leap.c index 3c7349c..9257976 100644 --- a/src/libiso8601/100_leap.c +++ b/src/libiso8601/100_leap.c @@ -73,6 +73,80 @@ int iso8601_leap_elapsed(const struct iso8601_date* start, const struct iso8601_ +void iso8601_leap_table_set(int* new_table, int new_size) +{ + leap_second_days = new_table; + leap_second_days_num = new_size; +} + + + +static const char* leap_table_signature = "/O9PdPZI"; + + + +int iso8601_leap_table_load(const char* fname) +{ + struct stat st; + int fd, saved_errno, i, new_size, * days = 0; + char buf[12]; + + if(stat(fname, &st)) return -1; + if(st.st_size < 12) { + errno = EINVAL; + return -1; + } + + fd = open(fname, O_RDONLY); + if(fd == -1) return -1; + + if(TEMP_FAILURE_RETRY( read(fd, buf, 12) ) != 12) goto outerr; + if(memcmp(buf, leap_table_signature, 8)) { + errno = EINVAL; + return -1; + } + +#define GET_UINT32(_from) ( \ + ( ((uint8_t*)_from)[0] << 24 ) | \ + ( ((uint8_t*)_from)[1] << 16 ) | \ + ( ((uint8_t*)_from)[2] << 8 ) | \ + ( ((uint8_t*)_from)[3] ) \ +) + + new_size = GET_UINT32(buf + 8); + if((12 + new_size * 4) != st.st_size) { + errno = EINVAL; + goto outerr; + } + + days = malloc(sizeof(int) * new_size); + if(!days) goto outerr; + + for(i = 0; i < new_size; ++i) { + if(TEMP_FAILURE_RETRY( read(fd, buf, 4) ) != 4) goto outerr; + days[i] = GET_UINT32(buf); + if(i && days[i] <= days[i - 1]) { + errno = EINVAL; + goto outerr; + } + } + + TEMP_FAILURE_RETRY( close(fd) ); + iso8601_leap_table_set(days, new_size); + return 0; + +#undef GET_UINT32 + + outerr: + saved_errno = errno; + free(days); + TEMP_FAILURE_RETRY( close(fd) ); + errno = saved_errno; + return -1; +} + + + /* options for text editors kate: replace-trailing-space-save true; space-indent true; tab-width 4; vim: expandtab:ts=4:sw=4