diff --git a/src/libiso8601/000_TopHeader.h b/src/libiso8601/000_TopHeader.h index 2953dca..0b8290a 100644 --- a/src/libiso8601/000_TopHeader.h +++ b/src/libiso8601/000_TopHeader.h @@ -11,6 +11,7 @@ /* standard includes, or includes needed for type declarations */ #include #include +#include /* options for text editors kate: replace-trailing-space-save true; space-indent true; tab-width 4; diff --git a/src/libiso8601/400_c_library.c b/src/libiso8601/400_c_library.c index 72b56bc..e960c34 100644 --- a/src/libiso8601/400_c_library.c +++ b/src/libiso8601/400_c_library.c @@ -44,6 +44,33 @@ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details) +int iso8601_set_sysclock(const struct iso8601_date* date) +{ + static int use_settimeofday = 0; + struct timeval tv; + struct timespec ts; + + /* not all systems have clock_settime implemented */ + if(use_settimeofday) goto try_settimeofday; + + /* try setting clock */ + iso8601_to_ts(&ts, date); + if(clock_settime(CLOCK_REALTIME, &ts)) { + if(errno == EPERM) return -1; + use_settimeofday = 1; + goto try_settimeofday; + } + + return 0; + + /* fallback using settimeofday() */ + try_settimeofday: + iso8601_to_tv(&tv, date); + return settimeofday(&tv, 0); +} + + + void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts) { ldiv_t qr; @@ -64,6 +91,26 @@ void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date) +void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv) +{ + ldiv_t qr; + + qr = ldiv(tv->tv_sec, 86400); + date->day = EPOCH_GDAY + qr.quot; + date->sec = qr.rem; + date->nsec = tv->tv_usec * 1000; +} + + + +void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date) +{ + tv->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec; + tv->tv_usec = date->nsec / 1000; +} + + + void iso8601_from_time_t(struct iso8601_date* date, const time_t* t) { ldiv_t qr; diff --git a/src/libiso8601/400_c_library.h b/src/libiso8601/400_c_library.h index 45552de..c5e6b59 100644 --- a/src/libiso8601/400_c_library.h +++ b/src/libiso8601/400_c_library.h @@ -29,10 +29,29 @@ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details); +/*! \brief Set the system clock. + +\param date Date to set. +\retval 0 on success. +\retval -1 on error (and see \a errno). + +Attempts to set the system clock using \c clock_settime(), falling back to \c settimeofday(). The +user will need the \c CAP_SYS_TIME capability to set the clock, otherwise \a errno will be set to +\c EPERM. + +*/ +int iso8601_set_sysclock(const struct iso8601_date* date); + + + /*! \brief Convert from a struct timespec. */ void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts); /*! \brief Convert to a struct timespec. */ void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date); +/*! \brief Convert from a struct timeval. */ +void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv); +/*! \brief Convert to a struct timeval. */ +void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date); /*! \brief Convert from a time_t. */ void iso8601_from_time_t(struct iso8601_date* date, const time_t* t); /*! \brief Convert to a time_t. */