1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include <inttypes.h>
5 #include <stdbool.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <time.h>
10 
11 typedef uint64_t usec_t;
12 typedef uint64_t nsec_t;
13 
14 #define PRI_NSEC PRIu64
15 #define PRI_USEC PRIu64
16 #define NSEC_FMT "%" PRI_NSEC
17 #define USEC_FMT "%" PRI_USEC
18 
19 #include "macro.h"
20 
21 typedef struct dual_timestamp {
22         usec_t realtime;
23         usec_t monotonic;
24 } dual_timestamp;
25 
26 typedef struct triple_timestamp {
27         usec_t realtime;
28         usec_t monotonic;
29         usec_t boottime;
30 } triple_timestamp;
31 
32 typedef enum TimestampStyle {
33         TIMESTAMP_PRETTY,
34         TIMESTAMP_US,
35         TIMESTAMP_UTC,
36         TIMESTAMP_US_UTC,
37         TIMESTAMP_UNIX,
38         _TIMESTAMP_STYLE_MAX,
39         _TIMESTAMP_STYLE_INVALID = -EINVAL,
40 } TimestampStyle;
41 
42 #define USEC_INFINITY ((usec_t) UINT64_MAX)
43 #define NSEC_INFINITY ((nsec_t) UINT64_MAX)
44 
45 #define MSEC_PER_SEC  1000ULL
46 #define USEC_PER_SEC  ((usec_t) 1000000ULL)
47 #define USEC_PER_MSEC ((usec_t) 1000ULL)
48 #define NSEC_PER_SEC  ((nsec_t) 1000000000ULL)
49 #define NSEC_PER_MSEC ((nsec_t) 1000000ULL)
50 #define NSEC_PER_USEC ((nsec_t) 1000ULL)
51 
52 #define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC))
53 #define NSEC_PER_MINUTE ((nsec_t) (60ULL*NSEC_PER_SEC))
54 #define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE))
55 #define NSEC_PER_HOUR ((nsec_t) (60ULL*NSEC_PER_MINUTE))
56 #define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR))
57 #define NSEC_PER_DAY ((nsec_t) (24ULL*NSEC_PER_HOUR))
58 #define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY))
59 #define NSEC_PER_WEEK ((nsec_t) (7ULL*NSEC_PER_DAY))
60 #define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC))
61 #define NSEC_PER_MONTH ((nsec_t) (2629800ULL*NSEC_PER_SEC))
62 #define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
63 #define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC))
64 
65 /* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this
66  * to 6. Let's rely on that. */
67 #define FORMAT_TIMESTAMP_MAX (3U+1U+10U+1U+8U+1U+6U+1U+6U+1U)
68 #define FORMAT_TIMESTAMP_WIDTH 28U /* when outputting, assume this width */
69 #define FORMAT_TIMESTAMP_RELATIVE_MAX 256U
70 #define FORMAT_TIMESPAN_MAX 64U
71 
72 #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
73 
74 #define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
75 #define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
76 
77 usec_t now(clockid_t clock);
78 nsec_t now_nsec(clockid_t clock);
79 
80 usec_t map_clock_usec(usec_t from, clockid_t from_clock, clockid_t to_clock);
81 
82 dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
83 dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
84 dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
85 dual_timestamp* dual_timestamp_from_boottime(dual_timestamp *ts, usec_t u);
86 
87 triple_timestamp* triple_timestamp_get(triple_timestamp *ts);
88 triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u);
89 
90 #define DUAL_TIMESTAMP_HAS_CLOCK(clock)                               \
91         IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC)
92 
93 #define TRIPLE_TIMESTAMP_HAS_CLOCK(clock)                               \
94         IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
95 
timestamp_is_set(usec_t timestamp)96 static inline bool timestamp_is_set(usec_t timestamp) {
97         return timestamp > 0 && timestamp != USEC_INFINITY;
98 }
99 
dual_timestamp_is_set(const dual_timestamp * ts)100 static inline bool dual_timestamp_is_set(const dual_timestamp *ts) {
101         return timestamp_is_set(ts->realtime) ||
102                timestamp_is_set(ts->monotonic);
103 }
104 
triple_timestamp_is_set(const triple_timestamp * ts)105 static inline bool triple_timestamp_is_set(const triple_timestamp *ts) {
106         return timestamp_is_set(ts->realtime) ||
107                timestamp_is_set(ts->monotonic) ||
108                timestamp_is_set(ts->boottime);
109 }
110 
111 usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
112 
113 usec_t timespec_load(const struct timespec *ts) _pure_;
114 nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
115 struct timespec* timespec_store(struct timespec *ts, usec_t u);
116 struct timespec* timespec_store_nsec(struct timespec *ts, nsec_t n);
117 
118 #define TIMESPEC_STORE(u) timespec_store(&(struct timespec) {}, (u))
119 
120 usec_t timeval_load(const struct timeval *tv) _pure_;
121 struct timeval* timeval_store(struct timeval *tv, usec_t u);
122 
123 #define TIMEVAL_STORE(u) timeval_store(&(struct timeval) {}, (u))
124 
125 char* format_timestamp_style(char *buf, size_t l, usec_t t, TimestampStyle style) _warn_unused_result_;
126 char* format_timestamp_relative(char *buf, size_t l, usec_t t) _warn_unused_result_;
127 char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) _warn_unused_result_;
128 
129 _warn_unused_result_
format_timestamp(char * buf,size_t l,usec_t t)130 static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
131         return format_timestamp_style(buf, l, t, TIMESTAMP_PRETTY);
132 }
133 
134 /* Note: the lifetime of the compound literal is the immediately surrounding block,
135  * see C11 §6.5.2.5, and
136  * https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
137 #define FORMAT_TIMESTAMP(t) format_timestamp((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t)
138 #define FORMAT_TIMESTAMP_RELATIVE(t)                                    \
139         format_timestamp_relative((char[FORMAT_TIMESTAMP_RELATIVE_MAX]){}, FORMAT_TIMESTAMP_RELATIVE_MAX, t)
140 #define FORMAT_TIMESPAN(t, accuracy) format_timespan((char[FORMAT_TIMESPAN_MAX]){}, FORMAT_TIMESPAN_MAX, t, accuracy)
141 #define FORMAT_TIMESTAMP_STYLE(t, style) \
142         format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t, style)
143 
144 int parse_timestamp(const char *t, usec_t *usec);
145 
146 int parse_sec(const char *t, usec_t *usec);
147 int parse_sec_fix_0(const char *t, usec_t *usec);
148 int parse_sec_def_infinity(const char *t, usec_t *usec);
149 int parse_time(const char *t, usec_t *usec, usec_t default_unit);
150 int parse_nsec(const char *t, nsec_t *nsec);
151 
152 int get_timezones(char ***l);
153 int verify_timezone(const char *name, int log_level);
timezone_is_valid(const char * name,int log_level)154 static inline bool timezone_is_valid(const char *name, int log_level) {
155         return verify_timezone(name, log_level) >= 0;
156 }
157 
158 bool clock_supported(clockid_t clock);
159 
160 usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to);
161 
162 int get_timezone(char **timezone);
163 
164 time_t mktime_or_timegm(struct tm *tm, bool utc);
165 struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
166 
167 uint32_t usec_to_jiffies(usec_t usec);
168 usec_t jiffies_to_usec(uint32_t jiffies);
169 
170 bool in_utc_timezone(void);
171 
usec_add(usec_t a,usec_t b)172 static inline usec_t usec_add(usec_t a, usec_t b) {
173         /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output,
174          * and doesn't overflow. */
175 
176         if (a > USEC_INFINITY - b) /* overflow check */
177                 return USEC_INFINITY;
178 
179         return a + b;
180 }
181 
usec_sub_unsigned(usec_t timestamp,usec_t delta)182 static inline usec_t usec_sub_unsigned(usec_t timestamp, usec_t delta) {
183         if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */
184                 return USEC_INFINITY;
185         if (timestamp < delta)
186                 return 0;
187 
188         return timestamp - delta;
189 }
190 
usec_sub_signed(usec_t timestamp,int64_t delta)191 static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
192         if (delta < 0)
193                 return usec_add(timestamp, (usec_t) (-delta));
194         else
195                 return usec_sub_unsigned(timestamp, (usec_t) delta);
196 }
197 
198 #if SIZEOF_TIME_T == 8
199   /* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit
200    * year territory. However, since we want to stay away from this in all timezones we take one day off. */
201 #  define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 253402214399000000)
202 #elif SIZEOF_TIME_T == 4
203 /* With a 32bit time_t we can't go beyond 2038... */
204 #  define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000)
205 #else
206 #  error "Yuck, time_t is neither 4 nor 8 bytes wide?"
207 #endif
208 
209 int time_change_fd(void);
210 
211 const char* timestamp_style_to_string(TimestampStyle t) _const_;
212 TimestampStyle timestamp_style_from_string(const char *s) _pure_;
213