📄 time.c
字号:
static char *read_TZ_file(char *buf){ int fd; ssize_t r; size_t todo; char *p = NULL; if ((fd = open(_PATH_TZ, O_RDONLY)) >= 0) { todo = TZ_BUFLEN; p = buf; do { if ((r = read(fd, p, todo)) < 0) { goto ERROR; } if (r == 0) { break; } p += r; todo -= r; } while (todo); if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline. */ p[-1] = 0; p = buf;#ifdef __TIME_TZ_FILE_ONCE ++TZ_file_read;#endif /* __TIME_TZ_FILE_ONCE */ } else { ERROR: p = NULL; } close(fd); } return p;}#endif /* __TIME_TZ_FILE */void tzset(void){ register const char *e; register char *s; long off; short *p; rule_struct new_rules[2]; int n, count, f; char c;#ifdef __TIME_TZ_FILE char buf[TZ_BUFLEN];#endif /* __TIME_TZ_FILE */#ifdef __TIME_TZ_OPT_SPEED static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */#endif /* __TIME_TZ_OPT_SPEED */ TZLOCK; e = getenv(TZ); /* TZ env var always takes precedence. */#ifdef __TIME_TZ_FILE_ONCE /* Put this inside the lock to prevent the possiblity of two different * timezones being used in a threaded app. */ if (e != NULL) { TZ_file_read = 0; /* Reset if the TZ env var is set. */ } else if (TZ_file_read > 0) { goto FAST_DONE; }#endif /* __TIME_TZ_FILE_ONCE */ /* Warning!!! Since uClibc doesn't do lib locking, the following is * potentially unsafe in a multi-threaded program since it is remotely * possible that another thread could call setenv() for TZ and overwrite * the string being parsed. So, don't do that... */ if ((!e /* TZ env var not set... */#ifdef __TIME_TZ_FILE && !(e = read_TZ_file(buf)) /* and no file or invalid file */#endif /* __TIME_TZ_FILE */ ) || !*e) { /* or set to empty string. */ ILLEGAL: /* TODO: Clean up the following... */#ifdef __TIME_TZ_OPT_SPEED *oldval = 0; /* Set oldval tonnn empty string. */#endif /* __TIME_TZ_OPT_SPEED */ s = _time_tzinfo[0].tzname; *s = 'U'; *++s = 'T'; *++s = 'C'; *++s = *_time_tzinfo[1].tzname = 0; _time_tzinfo[0].gmt_offset = 0; goto DONE; } if (*e == ':') { /* Ignore leading ':'. */ ++e; }#ifdef __TIME_TZ_OPT_SPEED if (strcmp(e, oldval) == 0) { /* Same string as last time... */ goto FAST_DONE; /* So nothing to do. */ } /* Make a copy of the TZ env string. It won't be nul-terminated if * it is too long, but it that case it will be illegal and will be reset * to the empty string anyway. */ strncpy(oldval, e, TZ_BUFLEN);#endif /* __TIME_TZ_OPT_SPEED */ count = 0; new_rules[1].tzname[0] = 0; LOOP: /* Get std or dst name. */ c = 0; if (*e == '<') { ++e; c = '>'; } s = new_rules[count].tzname; n = 0; while (*e && isascii(*e) /* SUSv3 requires char in portable char set. */ && (isalpha(*e) || (c && (isalnum(*e) || (*e == '+') || (*e == '-')))) ) { *s++ = *e++; if (++n > TZNAME_MAX) { goto ILLEGAL; } } *s = 0; if ((n < 3) /* Check for minimum length. */ || (c && (*e++ != c)) /* Match any quoting '<'. */ ) { goto ILLEGAL; } /* Get offset */ s = (char *) e; if ((*e != '-') && (*e != '+')) { if (count && !isdigit(*e)) { off -= 3600; /* Default to 1 hour ahead of std. */ goto SKIP_OFFSET; } --e; } ++e; if (!(e = getoffset(e, &off))) { goto ILLEGAL; } if (*s == '-') { off = -off; /* Save off in case needed for dst default. */ } SKIP_OFFSET: new_rules[count].gmt_offset = off; if (!count) { if (*e) { ++count; goto LOOP; } } else { /* OK, we have dst, so get some rules. */ count = 0; if (!*e) { /* No rules so default to US rules. */ e = DEFAULT_RULES; } do { if (*e++ != ',') { goto ILLEGAL; } n = 365; s = (char *) RULE; if ((c = *e++) == 'M') { n = 12; } else if (c == 'J') { s += 8; } else { --e; c = 0; s += 6; } *(p = &new_rules[count].rule_type) = c; if (c != 'M') { p -= 2; } do { ++s; if (!(e = getnumber(e, &f)) || (((unsigned int)(f - s[1])) > n) || (*s && (*e++ != *s)) ) { goto ILLEGAL; } *--p = f; } while ((n = *(s += 2)) > 0); off = 2 * 60 * 60; /* Default to 2:00:00 */ if (*e == '/') { ++e; if (!(e = getoffset(e, &off))) { goto ILLEGAL; } } new_rules[count].dst_offset = off; } while (++count < 2); if (*e) { goto ILLEGAL; } } memcpy(_time_tzinfo, new_rules, sizeof(new_rules)); DONE: tzname[0] = _time_tzinfo[0].tzname; tzname[1] = _time_tzinfo[1].tzname; daylight = !!_time_tzinfo[1].tzname[0]; timezone = _time_tzinfo[0].gmt_offset; FAST_DONE: TZUNLOCK;}#endif/**********************************************************************//* #ifdef L_utime *//* utime is a syscall in both linux and elks. *//* int utime(const char *path, const struct utimbuf *times) *//* #endif *//**********************************************************************//* Non-SUSv3 *//**********************************************************************/#ifdef L_utimes#ifndef __BCC__#error The uClibc version of utimes is in sysdeps/linux/common.#endif#include <utime.h>#include <sys/time.h>int utimes(const char *filename, register const struct timeval *tvp){ register struct utimbuf *p = NULL; struct utimbuf utb; if (tvp) { p = &utb; p->actime = tvp[0].tv_sec; p->modtime = tvp[1].tv_sec; } return utime(filename, p);}#endif/**********************************************************************/#ifdef L__time_t2tmstatic const uint16_t vals[] = { 60, 60, 24, 7 /* special */, 36524, 1461, 365, 0};static const unsigned char days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */ 29,};/* Notes: * If time_t is 32 bits, then no overflow is possible. * It time_t is > 32 bits, this needs to be adjusted to deal with overflow. *//* Note: offset is the correction in _days_ to *timer! */struct tm *_time_t2tm(const time_t *__restrict timer, int offset, struct tm *__restrict result){ register int *p; time_t t1, t, v; int wday=0; /* Note: wday can be uninitialized. */ { register const uint16_t *vp; t = *timer; p = (int *) result; p[7] = 0; vp = vals; do { if ((v = *vp) == 7) { /* Overflow checking, assuming time_t is long int... */#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L)#if (INT_MAX == 2147483647L) && (LONG_MAX == 9223372036854775807L) /* Valid range for t is [-784223472856L, 784223421720L]. * Outside of this range, the tm_year field will overflow. */ if (((unsigned long)(t + offset- -784223472856L)) > (784223421720L - -784223472856L) ) { return NULL; }#else#error overflow conditions unknown#endif#endif /* We have days since the epoch, so caluclate the weekday. */#if defined(__BCC__) && TIME_T_IS_UNSIGNED wday = (t + 4) % (*vp); /* t is unsigned */#else wday = ((int)((t % (*vp)) + 11)) % ((int)(*vp)); /* help bcc */#endif /* Set divisor to days in 400 years. Be kind to bcc... */ v = ((time_t)(vp[1])) << 2; ++v; /* Change to days since 1/1/1601 so that for 32 bit time_t * values, we'll have t >= 0. This should be changed for * archs with larger time_t types. * Also, correct for offset since a multiple of 7. */ /* TODO: Does this still work on archs with time_t > 32 bits? */ t += (135140L - 366) + offset; /* 146097 - (365*30 + 7) -366 */ }#if defined(__BCC__) && TIME_T_IS_UNSIGNED t -= ((t1 = t / v) * v);#else if ((t -= ((t1 = t / v) * v)) < 0) { t += v; --t1; }#endif if ((*vp == 7) && (t == v-1)) { --t; /* Correct for 400th year leap case */ ++p[4]; /* Stash the extra day... */ }#if defined(__BCC__) && 0 *p = t1; if (v <= 60) { *p = t; t = t1; } ++p;#else if (v <= 60) { *p++ = t; t = t1; } else { *p++ = t1; }#endif } while (*++vp); } if (p[-1] == 4) { --p[-1]; t = 365; } *p += ((int) t); /* result[7] .. tm_yday */ p -= 2; /* at result[5] */#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L) /* Protect against overflow. TODO: Unecessary if int arith wraps? */ *p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + (p[1] - 299); /* tm_year */#else *p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + p[1] - 299; /* tm_year */#endif p[1] = wday; /* result[6] .. tm_wday */ { register const unsigned char *d = days; wday = 1900 + *p; if (__isleap(wday)) { d += 11; } wday = p[2] + 1; /* result[7] .. tm_yday */ *--p = 0; /* at result[4] .. tm_mon */ while (wday > *d) { wday -= *d; if (*d == 29) { d -= 11; /* Backup to non-leap Feb. */ } ++d; ++*p; /* Increment tm_mon. */ } p[-1] = wday; /* result[3] .. tm_mday */ } /* TODO -- should this be 0? */ p[4] = 0; /* result[8] .. tm_isdst */ return result;}#endif/**********************************************************************/#ifdef L___time_tmstruct tm __time_tm; /* Global shared by gmtime() and localtime(). */#endif/**********************************************************************/#ifdef L__time_mktimestatic const unsigned char vals[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */ 29,};time_t _time_mktime(struct tm *timeptr, int store_on_success){#ifdef __BCC__ long days, secs;#else long long secs;#endif time_t t; struct tm x; /* 0:sec 1:min 2:hour 3:mday 4:mon 5:year 6:wday 7:yday 8:isdst */ register int *p = (int *) &x; register const unsigned char *s; int d; tzset(); memcpy(p, timeptr, sizeof(struct tm)); d = 400; p[5] = (p[5] - ((p[6] = p[5]/d) * d)) + (p[7] = p[4]/12); if ((p[4] -= 12 * p[7]) < 0) { p[4] += 12; --p[5]; } s = vals; d = (p[5] += 1900); /* Correct year. Now between 1900 and 2300. */ if (__isleap(d)) { s += 11; } p[7] = 0; d = p[4]; while (d) { p[7] += *s; if (*s == 29) { s -= 11; /* Backup to non-leap Feb. */ } ++s; --d; }#ifdef __BCC__ d = p[5] - 1; days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]); secs = p[0] + 60*( p[1] + 60*((long)(p[2])) ) + _time_tzinfo[timeptr->tm_isdst > 0].gmt_offset; if (secs < 0) { secs += 120009600L; days -= 1389; } if ( ((unsigned long)(days + secs/86400L)) > 49710L) { return -1; } secs += (days * 86400L);#else TZLOCK; d = p[5] - 1; d = -719163L + d*365 + (d/4) - (d/100) + (d/400); secs = p[0] + _time_tzinfo[timeptr->tm_isdst > 0].gmt_offset + 60*( p[1] + 60*(p[2] + 24*(((146073L * ((long long)(p[6])) + d) + p[3]) + p[7]))); TZUNLOCK; if (((unsigned long long)(secs - LONG_MIN)) > (((unsigned long long)LONG_MAX) - LONG_MIN) ) { return -1; }#endif t = secs; localtime_r(&t, (struct tm *)p); if (t < 0) { return -1; } if (store_on_success) { memcpy(timeptr, p, sizeof(struct tm)); } return t;}#endif/**********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -