Rizin
unix-like reverse engineering framework and cli tools
time.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2007-2020 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2007-2020 thestr4ng3r <info@florianmaerkl.de>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_util.h>
6 
7 #define TIME_HFS_SINCE_1970 2082844800u // Mac HFS/HFS+ constant to convert timestamp to epoch
8 #define TIME_W32_SINCE_1970 0x2b6109100ull // The number of seconds from the Windows Runtime epoch to January 1, 1970.
9 
10 #if __linux__
11 #include <time.h>
12 #elif __APPLE__ && !defined(MAC_OS_X_VERSION_10_12)
13 #include <mach/mach_time.h>
14 #elif __WINDOWS__
15 #include <rz_windows.h>
16 #endif
17 
18 #ifdef _MSC_VER
29 RZ_API int rz_time_gettimeofday(struct timeval *p, struct timezone *tz) {
30  // ULARGE_INTEGER ul; // As specified on MSDN.
31  ut64 ul = 0;
32  static int tzflag = 0;
33  FILETIME ft;
34  if (p) {
35  // Returns a 64-bit value representing the number of
36  // 100-nanosecond intervals since January 1, 1601 (UTC).
37  GetSystemTimeAsFileTime(&ft);
38  // Fill ULARGE_INTEGER low and high parts.
39  // ul.LowPart = ft.dwLowDateTime;
40  // ul.HighPart = ft.dwHighDateTime;
41  ul |= ft.dwHighDateTime;
42  ul <<= 32;
43  ul |= ft.dwLowDateTime;
44  // Convert to microseconds.
45  // ul.QuadPart /= 10ULL;
46  ul /= 10;
47  // Remove Windows to UNIX Epoch delta.
48  // ul.QuadPart -= 11644473600000000ULL;
49  ul -= 11644473600000000ULL;
50  // Modulo to retrieve the microseconds.
51  // p->tv_usec = (long)(ul.QuadPart % 1000000LL);
52  // Divide to retrieve the seconds.
53  // p->tv_sec = (long)(ul.QuadPart / 1000000LL);
54  p->tv_sec = (long)(ul / 1000000LL);
55  p->tv_usec = (long)(ul % 1000000LL);
56  }
57  if (tz) {
58  if (!tzflag) {
59  _tzset();
60  tzflag++;
61  }
62  tz->tz_minuteswest = _timezone / 60;
63  tz->tz_dsttime = _daylight;
64  }
65  return 0;
66 }
67 #else
78 RZ_API int rz_time_gettimeofday(struct timeval *p, struct timezone *tz) {
79  return gettimeofday(p, tz);
80 }
81 #endif
82 
89  ut64 ret;
90  struct timeval now;
92  ret = now.tv_sec * RZ_USEC_PER_SEC;
93  ret += now.tv_usec;
94  return ret;
95 }
96 
103 #if __WINDOWS__
104  LARGE_INTEGER f;
105  if (!QueryPerformanceFrequency(&f)) {
106  return 0;
107  }
108  LARGE_INTEGER v;
109  if (!QueryPerformanceCounter(&v)) {
110  return 0;
111  }
112  v.QuadPart *= 1000000;
113  v.QuadPart /= f.QuadPart;
114  return v.QuadPart;
115 #elif __APPLE__ && !defined(MAC_OS_X_VERSION_10_12)
116  ut64 ticks = mach_absolute_time();
117  mach_timebase_info_data_t tb;
118  mach_timebase_info(&tb);
119  return ((ticks * tb.numer) / tb.denom) / RZ_NSEC_PER_USEC;
120 #else
121  struct timespec now;
122  clock_gettime(CLOCK_MONOTONIC, &now);
123  return now.tv_sec * RZ_USEC_PER_SEC + now.tv_nsec / RZ_NSEC_PER_USEC;
124 #endif
125 }
126 
127 /* Valid only from midnight 31 Dec 1969 until Jan 1970 */
128 static inline long get_seconds_since_12am31Dec1969(struct tm *time) {
129  if (time->tm_mday == 31 && time->tm_mon == 11 && time->tm_year == 69) {
130  return time->tm_hour * 3600 + time->tm_min * 60 + time->tm_sec;
131  } else if (time->tm_mon == 0 && time->tm_year == 70) {
132  return 86400 + (time->tm_mday - 1) * 86400 + time->tm_hour * 3600 + time->tm_min * 60 + time->tm_sec;
133  }
134  return -1;
135 }
136 
144  char timestr_buf[ASCTIME_BUF_MINLEN];
145  time_t ts = (time_t)timestamp;
146  struct tm gmt_tm;
147  rz_gmtime_r(&ts, &gmt_tm);
148  struct tm local_tm;
149  rz_localtime_r(&ts, &local_tm);
150  time_t gmt_time;
151  time_t local_time;
152  long diff;
153  if (gmt_tm.tm_mday == 1 && gmt_tm.tm_mon == 0 && gmt_tm.tm_year == 70) {
154  gmt_time = get_seconds_since_12am31Dec1969(&gmt_tm);
155  local_time = get_seconds_since_12am31Dec1969(&local_tm);
156  diff = local_time - gmt_time;
157  } else {
158  gmt_time = mktime(&gmt_tm);
159  local_time = mktime(&local_tm);
160  diff = (long)difftime(local_time, gmt_time);
161  }
162  bool err = gmt_time == -1 || local_time == -1;
163  char *timestr = rz_ctime_r(&ts, timestr_buf);
164  if (timestr) {
165  rz_str_trim(timestr);
166  long hours = diff / 3600;
167  long minutes = labs(diff % 3600 / 60);
168  long seconds = labs(diff % 3600 % 60);
169  if (err) {
170  timestr = rz_str_newf("%s ERR", timestr);
171  } else if (seconds) {
172  timestr = rz_str_newf("%s UTC%+ld:%ld:%ld", timestr, hours, minutes, seconds);
173  } else if (minutes) {
174  timestr = rz_str_newf("%s UTC%+ld:%ld", timestr, hours, minutes);
175  } else if (hours) {
176  timestr = rz_str_newf("%s UTC%+ld", timestr, hours);
177  } else {
178  timestr = rz_str_newf("%s UTC", timestr);
179  }
180  }
181  return timestr;
182 }
183 
191  ut16 date = timestamp >> 16;
192  ut16 time = timestamp & 0xFFFF;
193 
194  /* Date */
195  ut32 year = ((date & 0xfe00) >> 9) + 1980;
196  ut32 month = (date & 0x01e0) >> 5;
197  ut32 day = date & 0x001f;
198 
199  /* Time */
200  ut32 hour = (time & 0xf800) >> 11;
201  ut32 minutes = (time & 0x07e0) >> 5;
202  ut32 seconds = (time & 0x001f) << 1;
203 
204  /* Convert to epoch */
205  struct tm t = { 0 };
206  t.tm_year = year - 1900;
207  t.tm_mon = month > 0 ? month - 1 : month;
208  t.tm_mday = day > 0 ? day : 1;
209  t.tm_hour = hour;
210  t.tm_min = minutes;
211  t.tm_sec = seconds;
212  t.tm_isdst = -1;
213  time_t epochTime = mktime(&t);
214 
215  return (ut32)epochTime;
216 }
217 
225 RZ_API bool rz_time_stamp_is_dos_format(const ut32 certainPosixTimeStamp, const ut32 possiblePosixOrDosTimeStamp) {
226  /* We assume they're both POSIX timestamp and thus the higher bits would be equal if they're close to each other */
227  if ((certainPosixTimeStamp >> 16) == (possiblePosixOrDosTimeStamp >> 16)) {
228  return false;
229  }
230  return true;
231 }
232 
240  ut32 posix = rz_time_dos_time_stamp_to_posix(timestamp);
241  return rz_time_stamp_to_str(posix);
242 }
243 
251  timestamp += TIME_HFS_SINCE_1970; // add Mac HFS+ epoch
252  return rz_time_stamp_to_str(timestamp);
253 }
254 
262  timestamp /= 10000000ll; // 100 nanoseconds to seconds
263  if (timestamp > TIME_W32_SINCE_1970) {
264  timestamp -= TIME_W32_SINCE_1970;
265  } else {
266  // TODO: this usecase is not handled and defaulted to 0
267  timestamp = 0;
268  }
269  time_t t = (time_t)timestamp;
270  return rz_time_stamp_to_str(t);
271 }
272 
279  ut64 now = rz_time_now();
280  now /= RZ_USEC_PER_SEC;
281  return rz_time_stamp_to_str(now);
282 }
283 
284 RZ_API struct tm *rz_localtime_r(RZ_NONNULL const time_t *time, RZ_NONNULL struct tm *res) {
286 #if __WINDOWS__
287  errno_t err = localtime_s(res, time);
288  return err ? NULL : res;
289 #else
290  return localtime_r(time, res);
291 #endif
292 }
293 
294 RZ_API struct tm *rz_gmtime_r(RZ_NONNULL const time_t *time, RZ_NONNULL struct tm *res) {
296 #if __WINDOWS__
297  errno_t err = gmtime_s(res, time);
298  return err ? NULL : res;
299 #else
300  return gmtime_r(time, res);
301 #endif
302 }
303 
304 RZ_API char *rz_asctime_r(RZ_NONNULL const struct tm *tm, RZ_NONNULL char *buf) {
306 #if __WINDOWS__
307  errno_t err = asctime_s(buf, ASCTIME_BUF_MINLEN, tm);
308  return err ? NULL : buf;
309 #else
310  return asctime_r(tm, buf);
311 #endif
312 }
313 
314 RZ_API char *rz_ctime_r(RZ_NONNULL const time_t *timer, RZ_NONNULL char *buf) {
315  rz_return_val_if_fail(timer && buf, NULL);
316 #if __WINDOWS__
317  errno_t err = ctime_s(buf, ASCTIME_BUF_MINLEN, timer);
318  return err ? NULL : buf;
319 #else
320  return ctime_r(timer, buf);
321 #endif
322 }
static bool err
Definition: armass.c:435
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog gettimeofday
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags long
Definition: sflib.h:79
uint16_t ut16
uint32_t ut32
const char * v
Definition: dsignal.c:12
voidpf void * buf
Definition: ioapi.h:138
void * p
Definition: libc.cpp:67
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190
#define RZ_USEC_PER_SEC
Definition: rz_time.h:9
#define RZ_NSEC_PER_USEC
Definition: rz_time.h:10
#define ASCTIME_BUF_MINLEN
Definition: rz_time.h:13
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
int time_t
Definition: sftypes.h:66
#define f(i)
Definition: sha256.c:46
long tv_nsec
Definition: sftypes.h:90
time_t tv_sec
Definition: sftypes.h:89
long tv_sec
Definition: sftypes.h:84
long tv_usec
Definition: sftypes.h:85
RZ_API RZ_OWN char * rz_time_date_dos_to_string(ut32 timestamp)
Converts a dos date (ut32) and returns the timestamp in string format.
Definition: time.c:239
#define TIME_W32_SINCE_1970
Definition: time.c:8
RZ_API RZ_OWN char * rz_time_date_now_to_string(void)
Returns the timestamp in string format of the current time (now)
Definition: time.c:278
RZ_API struct tm * rz_localtime_r(RZ_NONNULL const time_t *time, RZ_NONNULL struct tm *res)
Definition: time.c:284
RZ_API struct tm * rz_gmtime_r(RZ_NONNULL const time_t *time, RZ_NONNULL struct tm *res)
Definition: time.c:294
RZ_API bool rz_time_stamp_is_dos_format(const ut32 certainPosixTimeStamp, const ut32 possiblePosixOrDosTimeStamp)
Verifies that the timestamp is in dos format.
Definition: time.c:225
RZ_API char * rz_asctime_r(RZ_NONNULL const struct tm *tm, RZ_NONNULL char *buf)
Definition: time.c:304
RZ_API RZ_OWN char * rz_time_date_w32_to_string(ut64 timestamp)
Converts a Win32 date (ut64) and returns the timestamp in string format.
Definition: time.c:261
RZ_API ut64 rz_time_now(void)
Returns the current time in microseconds.
Definition: time.c:88
RZ_API int rz_time_gettimeofday(struct timeval *p, struct timezone *tz)
Get the system current time and the current time zone.
Definition: time.c:78
#define TIME_HFS_SINCE_1970
Definition: time.c:7
RZ_API RZ_OWN char * rz_time_date_hfs_to_string(ut32 timestamp)
Converts a Mac HFS+ date (ut32) and returns the timestamp in string format.
Definition: time.c:250
RZ_API RZ_OWN char * rz_time_stamp_to_str(ut32 timestamp)
Converts an unix epoch timestamp to string.
Definition: time.c:143
static long get_seconds_since_12am31Dec1969(struct tm *time)
Definition: time.c:128
RZ_API char * rz_ctime_r(RZ_NONNULL const time_t *timer, RZ_NONNULL char *buf)
Definition: time.c:314
RZ_API ut64 rz_time_now_mono(void)
Returns the current time in microseconds, using the monotonic clock.
Definition: time.c:102
RZ_API ut32 rz_time_dos_time_stamp_to_posix(ut32 timestamp)
Converts dos timestamp to posix timestamp.
Definition: time.c:190
ut64(WINAPI *w32_GetEnabledXStateFeatures)()