~vcs-imports/busybox/trunk

« back to all changes in this revision

Viewing changes to libbb/time.c

  • Committer: Denys Vlasenko
  • Author(s): Christian Franke
  • Date: 2023-11-13 10:32:35 UTC
  • Revision ID: git-v1:a63b60bdd6fa26b867c80d44074118babbae7ffd
Cygwin: regenerate defconfig

Signed-off-by: Christian Franke <christian.franke@t-online.de>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 */
9
9
#include "libbb.h"
10
10
 
11
 
void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
 
11
/* Returns 0 if the time structure contains an absolute UTC time which
 
12
 * should not be subject to DST adjustment by the caller. */
 
13
int FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
12
14
{
13
15
        char end = '\0';
 
16
        time_t t;
 
17
#if ENABLE_DESKTOP
 
18
/*
 
19
 * strptime is BIG: ~1k in uclibc, ~10k in glibc
 
20
 * We need it for 'month_name d HH:MM:SS YYYY', supported by GNU date,
 
21
 * but if we've linked it we might as well use it for everything.
 
22
 */
 
23
        static const char fmt_str[] ALIGN1 =
 
24
                "%R" "\0"               /* HH:MM */
 
25
                "%T" "\0"               /* HH:MM:SS */
 
26
                "%m.%d-%R" "\0"         /* mm.dd-HH:MM */
 
27
                "%m.%d-%T" "\0"         /* mm.dd-HH:MM:SS */
 
28
                "%Y.%m.%d-%R" "\0"      /* yyyy.mm.dd-HH:MM */
 
29
                "%Y.%m.%d-%T" "\0"      /* yyyy.mm.dd-HH:MM:SS */
 
30
                "%b %d %T %Y" "\0"      /* month_name d HH:MM:SS YYYY */
 
31
                "%Y-%m-%d %R" "\0"      /* yyyy-mm-dd HH:MM */
 
32
                "%Y-%m-%d %T" "\0"      /* yyyy-mm-dd HH:MM:SS */
 
33
# if ENABLE_FEATURE_TIMEZONE
 
34
                "%Y-%m-%d %R %z" "\0"   /* yyyy-mm-dd HH:MM TZ */
 
35
                "%Y-%m-%d %T %z" "\0"   /* yyyy-mm-dd HH:MM:SS TZ */
 
36
# endif
 
37
                "%Y-%m-%d %H" "\0"      /* yyyy-mm-dd HH */
 
38
                "%Y-%m-%d" "\0"         /* yyyy-mm-dd */
 
39
                /* extra NUL */;
 
40
        struct tm save;
 
41
        const char *fmt;
 
42
        char *endp;
 
43
 
 
44
        save = *ptm;
 
45
        fmt = fmt_str;
 
46
        while (*fmt) {
 
47
                endp = strptime(date_str, fmt, ptm);
 
48
                if (endp && *endp == '\0') {
 
49
# if ENABLE_FEATURE_TIMEZONE
 
50
                        if (strchr(fmt, 'z')) {
 
51
                                /* we have timezone offset: obtain Unix time_t */
 
52
                                ptm->tm_sec -= ptm->tm_gmtoff;
 
53
                                ptm->tm_isdst = 0;
 
54
                                t = timegm(ptm);
 
55
                                if (t == (time_t)-1)
 
56
                                        break;
 
57
                                /* convert Unix time_t to struct tm in user's locale */
 
58
                                goto localise;
 
59
                        }
 
60
# endif
 
61
                        return 1;
 
62
                }
 
63
                *ptm = save;
 
64
                while (*++fmt)
 
65
                        continue;
 
66
                ++fmt;
 
67
        }
 
68
#else
14
69
        const char *last_colon = strrchr(date_str, ':');
15
70
 
16
71
        if (last_colon != NULL) {
17
72
                /* Parse input and assign appropriately to ptm */
18
 
#if ENABLE_DESKTOP
19
 
                const char *endp;
20
 
#endif
21
73
 
22
74
                /* HH:MM */
23
75
                if (sscanf(date_str, "%u:%u%c",
50
102
                        ptm->tm_year -= 1900; /* Adjust years */
51
103
                        ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
52
104
                } else
53
 
#if ENABLE_DESKTOP  /* strptime is BIG: ~1k in uclibc, ~10k in glibc */
54
 
                /* month_name d HH:MM:SS YYYY. Supported by GNU date */
55
 
                if ((endp = strptime(date_str, "%b %d %T %Y", ptm)) != NULL
56
 
                 && *endp == '\0'
57
 
                ) {
58
 
                        return; /* don't fall through to end == ":" check */
59
 
                } else
60
 
#endif
61
105
                {
62
106
                        bb_error_msg_and_die(bb_msg_invalid_date, date_str);
63
107
                }
89
133
                ptm->tm_year -= 1900; /* Adjust years */
90
134
                ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
91
135
        } else
 
136
#endif /* ENABLE_DESKTOP */
92
137
        if (date_str[0] == '@') {
93
 
                time_t t = bb_strtol(date_str + 1, NULL, 10);
 
138
                if (sizeof(t) <= sizeof(long))
 
139
                        t = bb_strtol(date_str + 1, NULL, 10);
 
140
                else /* time_t is 64 bits but longs are smaller */
 
141
                        t = bb_strtoll(date_str + 1, NULL, 10);
94
142
                if (!errno) {
95
 
                        struct tm *lt = localtime(&t);
 
143
                        struct tm *lt;
 
144
 IF_FEATURE_TIMEZONE(localise:)
 
145
                        lt = localtime(&t);
96
146
                        if (lt) {
97
147
                                *ptm = *lt;
98
 
                                return;
 
148
                                return 0;
99
149
                        }
100
150
                }
101
151
                end = '1';
212
262
        if (end != '\0') {
213
263
                bb_error_msg_and_die(bb_msg_invalid_date, date_str);
214
264
        }
 
265
        return 1;
215
266
}
216
267
 
217
268
time_t FAST_FUNC validate_tm_time(const char *date_str, struct tm *ptm)
246
297
 
247
298
#if ENABLE_MONOTONIC_SYSCALL
248
299
 
249
 
#include <sys/syscall.h>
250
300
/* Old glibc (< 2.3.4) does not provide this constant. We use syscall
251
301
 * directly so this definition is safe. */
252
302
#ifndef CLOCK_MONOTONIC
288
338
unsigned long long FAST_FUNC monotonic_ns(void)
289
339
{
290
340
        struct timeval tv;
291
 
        gettimeofday(&tv, NULL);
 
341
        xgettimeofday(&tv);
292
342
        return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
293
343
}
294
344
unsigned long long FAST_FUNC monotonic_us(void)
295
345
{
296
346
        struct timeval tv;
297
 
        gettimeofday(&tv, NULL);
 
347
        xgettimeofday(&tv);
298
348
        return tv.tv_sec * 1000000ULL + tv.tv_usec;
299
349
}
300
350
unsigned long long FAST_FUNC monotonic_ms(void)
301
351
{
302
352
        struct timeval tv;
303
 
        gettimeofday(&tv, NULL);
 
353
        xgettimeofday(&tv);
304
354
        return tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
305
355
}
306
356
unsigned FAST_FUNC monotonic_sec(void)