Add functions to load/set leap second table
This commit is contained in:
parent
e908febba2
commit
a0f747067d
|
@ -10,9 +10,12 @@
|
||||||
/* Below are all the includes used throughout the library. */
|
/* Below are all the includes used throughout the library. */
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
/* Useful define to alleviate typos */
|
/* Useful define to alleviate typos */
|
||||||
|
|
|
@ -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
|
/* options for text editors
|
||||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||||
vim: expandtab:ts=4:sw=4
|
vim: expandtab:ts=4:sw=4
|
||||||
|
|
Loading…
Reference in New Issue