Description: add GNU extensions for struct tm. This might be incomplete. Omly localtime() and gmtime() work. Index: b/usr/src/head/iso/time_iso.h =================================================================== --- a/usr/src/head/iso/time_iso.h +++ b/usr/src/head/iso/time_iso.h @@ -44,7 +44,7 @@ #ifndef _ISO_TIME_ISO_H #define _ISO_TIME_ISO_H -#include +#include #ifdef __cplusplus extern "C" { @@ -93,6 +93,13 @@ struct tm { /* see ctime(3) */ int tm_wday; int tm_yday; int tm_isdst; +#if defined (_BSD_SOURCE) + long tm_gmtoff; + const char *tm_zone; +#else + long __tm_gmtoff; + const char *__tm_zone; +#endif }; @@ -102,11 +109,21 @@ extern char *ctime(const time_t *); extern double difftime(time_t, time_t); extern struct tm *gmtime(const time_t *); extern struct tm *localtime(const time_t *); -extern time_t mktime(struct tm *); extern time_t time(time_t *); extern size_t strftime(char *_RESTRICT_KYWD, size_t, const char *_RESTRICT_KYWD, const struct tm *_RESTRICT_KYWD); +#ifndef __IN_LIBC +#ifdef __PRAGMA_REDEFINE_EXTNAME +#pragma redefine_extname mktime __gnu_mktime +extern time_t mktime(struct tm *); +#else +static time_t mktime(struct tm *___tm) { + return __gnu_mktime(___tm); +} +#endif +#endif /* __IN_LIBC */ + #if __cplusplus >= 199711L } #endif /* end of namespace std */ Index: b/usr/src/head/time.h =================================================================== --- a/usr/src/head/time.h +++ b/usr/src/head/time.h @@ -35,7 +35,7 @@ #ifndef _TIME_H #define _TIME_H -#include +#include #include #if (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \ (_POSIX_C_SOURCE > 2) || defined(__EXTENSIONS__) @@ -85,10 +85,27 @@ typedef int timer_t; #if defined(__EXTENSIONS__) || \ (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \ (_POSIX_C_SOURCE - 0 >= 199506L) || defined(_REENTRANT) + +#ifndef __IN_LIBC +#ifdef __PRAGMA_REDEFINE_EXTNAME extern struct tm *gmtime_r(const time_t *_RESTRICT_KYWD, struct tm *_RESTRICT_KYWD); extern struct tm *localtime_r(const time_t *_RESTRICT_KYWD, struct tm *_RESTRICT_KYWD); +#pragma redefine_extname gmtime_r __gnu_gmtime_r +#pragma redefine_extname localtime_r __gnu_localtime_r +#else /* ! __PRAGMA_REDEFINE_EXTNAME */ +static struct tm *gmtime_r(const time_t *_RESTRICT_KYWD __t, + struct tm *_RESTRICT_KYWD __tm) { + return __gnu_gmtime_r(__t, __tm); +} +static struct tm *localtime_r(const time_t *_RESTRICT_KYWD __t, + struct tm *_RESTRICT_KYWD __tm) { + return __gnu_localtime_r(__t, __tm); +} +#endif /* __PRAGMA_REDEFINE_EXTNAME */ +#endif /* __IN_LIBC */ + #endif #if (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \ @@ -183,7 +200,18 @@ extern int daylight; #if (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \ defined(__EXTENSIONS__) + +#ifndef __IN_LIBC +#ifdef __PRAGMA_REDEFINE_EXTNAME extern time_t timegm(struct tm *); +#pragma redefine_extname timegm __gnu_timegm +#else /* ! __PRAGMA_REDEFINE_EXTNAME */ +static time_t timegm(struct tm *__tm) { + return __gnu_timegm(__tm); +} +#endif /* __PRAGMA_REDEFINE_EXTNAME */ +#endif /* __IN_LIBC */ + extern int cftime(char *, char *, const time_t *); extern int ascftime(char *, const char *, const struct tm *); extern long altzone; Index: b/usr/src/lib/libc/port/gen/localtime.c =================================================================== --- a/usr/src/lib/libc/port/gen/localtime.c +++ b/usr/src/lib/libc/port/gen/localtime.c @@ -88,6 +88,8 @@ * Functions that are common to ctime(3C) and cftime(3C) */ + +#define __IN_LIBC #pragma weak _tzset = tzset #undef TZDIR @@ -488,6 +490,14 @@ gmtime_r(const time_t *timep, struct tm return (offtime_u((time_t)*timep, 0L, p_tm)); } +struct tm * +__gnu_gmtime_r(const time_t *timep, struct tm *p_tm) +{ + p_tm->tm_gmtoff = 0; + p_tm->tm_zone = _tz_gmt; + return (offtime_u((time_t)*timep, 0L, p_tm)); +} + /* * Accepts a time_t, returns a tm struct based on it, with * no local timezone adjustment. @@ -507,7 +517,7 @@ gmtime(const time_t *timep) if (p_tm == NULL) /* memory allocation failure */ p_tm = &tm; /* use static buffer and hope for the best */ - return (gmtime_r(timep, p_tm)); + return (__gnu_gmtime_r(timep, p_tm)); } /* @@ -649,6 +659,34 @@ localtime_r(const time_t *timep, struct return (rt); } +struct tm * +__gnu_localtime_r(const time_t *timep, struct tm *p_tm) +{ + long offset; + struct tm *rt; + void *unused; + int my_is_in_dst; + + lmutex_lock(&_time_lock); + unused = ltzset_u(*timep); + if (lclzonep == NULL) { + lmutex_unlock(&_time_lock); + if (unused != NULL) + free(unused); + return (offtime_u(*timep, 0L, p_tm)); + } + my_is_in_dst = is_in_dst; + offset = (my_is_in_dst) ? -altzone : -timezone; + p_tm->tm_gmtoff = offset; + p_tm->tm_zone = tzname[0]; + lmutex_unlock(&_time_lock); + if (unused != NULL) + free(unused); + rt = offtime_u(*timep, offset, p_tm); + p_tm->tm_isdst = my_is_in_dst; + return (rt); +} + /* * Accepts a time_t, returns a tm struct based on it, correcting * for the local timezone. Produces documented side-effects to @@ -673,7 +711,7 @@ localtime(const time_t *timep) if (p_tm == NULL) /* memory allocation failure */ p_tm = &tm; /* use static buffer and hope for the best */ - return (localtime_r(timep, p_tm)); + return (__gnu_localtime_r(timep, p_tm)); } /* @@ -682,7 +720,7 @@ localtime(const time_t *timep) * extern global zone state variables. (See mktime(3C)). */ static time_t -mktime1(struct tm *tmptr, int usetz) +mktime1(struct tm *tmptr, int usetz, int gnu) { struct tm _tm; long long t; /* must hold more than 32-bit time_t */ @@ -823,7 +861,19 @@ mktime1(struct tm *tmptr, int usetz) mketimerrno = EOVERFLOW; t = -1; } else { - *tmptr = _tm; + if (gnu) + *tmptr = _tm; + else { + tmptr->tm_sec = _tm.tm_sec; + tmptr->tm_min = _tm.tm_min; + tmptr->tm_hour = _tm.tm_hour; + tmptr->tm_mday = _tm.tm_mday; + tmptr->tm_mon = _tm.tm_mon; + tmptr->tm_year = _tm.tm_year; + tmptr->tm_wday = _tm.tm_wday; + tmptr->tm_yday = _tm.tm_yday; + tmptr->tm_isdst = _tm.tm_isdst; + } } lmutex_unlock(&_time_lock); @@ -837,15 +887,26 @@ mktime1(struct tm *tmptr, int usetz) time_t mktime(struct tm *tmptr) { - return (mktime1(tmptr, TRUE)); + return (mktime1(tmptr, TRUE, 0)); } time_t timegm(struct tm *tmptr) { - return (mktime1(tmptr, FALSE)); + return (mktime1(tmptr, FALSE, 0)); } +time_t +__gnu_mktime(struct tm *tmptr) +{ + return (mktime1(tmptr, TRUE, 1)); +} + +time_t +__gnu_timegm(struct tm *tmptr) +{ + return (mktime1(tmptr, FALSE, 1)); +} /* * Sets extern global zone state variables based on the current Index: b/usr/src/lib/libc/port/mapfile-vers =================================================================== --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -262,6 +262,10 @@ SYMBOL_VERSION ILLUMOS_0.4 { # Illumos a SYMBOL_VERSION DYSON_1 { global: + __gnu_gmtime_r; + __gnu_localtime_r; + __gnu_mktime; + __gnu_timegm; _so_accept4; cfmakeraw; error;