1 /* radare - LGPL - Copyright 2007-2020 - pancake, thestr4ng3r */
2
3 #include <r_util.h>
4 #include <r_util/r_print.h>
5
6 #if __linux__
7 #include <time.h>
8 #elif __APPLE__ && !defined(MAC_OS_X_VERSION_10_12)
9 #include <mach/mach_time.h>
10 #endif
11
r_time_now(void)12 R_API ut64 r_time_now(void) {
13 ut64 ret;
14 struct timeval now;
15 gettimeofday (&now, NULL);
16 ret = now.tv_sec * R_USEC_PER_SEC;
17 ret += now.tv_usec;
18 return ret;
19 }
20
r_time_now_mono(void)21 R_API ut64 r_time_now_mono(void) {
22 #if __WINDOWS__
23 LARGE_INTEGER f;
24 if (!QueryPerformanceFrequency (&f)) {
25 return 0;
26 }
27 LARGE_INTEGER v;
28 if (!QueryPerformanceCounter (&v)) {
29 return 0;
30 }
31 v.QuadPart *= 1000000;
32 v.QuadPart /= f.QuadPart;
33 return v.QuadPart;
34 #elif __APPLE__ && !defined(MAC_OS_X_VERSION_10_12)
35 ut64 ticks = mach_absolute_time ();
36 static mach_timebase_info_data_t tb;
37 mach_timebase_info (&tb);
38 return ((ticks * tb.numer) / tb.denom) / R_NSEC_PER_USEC;
39 #else
40 struct timespec now;
41 clock_gettime (CLOCK_MONOTONIC, &now);
42 return now.tv_sec * R_USEC_PER_SEC
43 + now.tv_nsec / R_NSEC_PER_USEC;
44 #endif
45 }
46
r_time_stamp_to_str(ut32 timeStamp)47 R_API char *r_time_stamp_to_str(ut32 timeStamp) {
48 #ifdef _MSC_VER
49 time_t rawtime;
50 struct tm *tminfo;
51 rawtime = (time_t)timeStamp;
52 tminfo = localtime (&rawtime);
53 //tminfo = gmtime (&rawtime);
54 return r_str_trim_dup (asctime (tminfo));
55 #else
56 struct my_timezone {
57 int tz_minuteswest; /* minutes west of Greenwich */
58 int tz_dsttime; /* type of DST correction */
59 } tz;
60 struct timeval tv;
61 int gmtoff;
62 time_t ts = (time_t) timeStamp;
63 gettimeofday (&tv, (void*) &tz);
64 gmtoff = (int) (tz.tz_minuteswest * 60); // in seconds
65 ts += (time_t)gmtoff;
66 char *res = malloc(ASCTIME_BUF_MINLEN);
67 if (res) {
68 ctime_r (&ts, res);
69 r_str_trim (res); // XXX we probably need an r_str_trim_dup()
70 }
71 return res;
72 #endif
73 }
74
r_time_dos_time_stamp_to_posix(ut32 timeStamp)75 R_API ut32 r_time_dos_time_stamp_to_posix(ut32 timeStamp) {
76 ut16 date = timeStamp >> 16;
77 ut16 time = timeStamp & 0xFFFF;
78
79 /* Date */
80 ut32 year = ((date & 0xfe00) >> 9) + 1980;
81 ut32 month = (date & 0x01e0) >> 5;
82 ut32 day = date & 0x001f;
83
84 /* Time */
85 ut32 hour = (time & 0xf800) >> 11;
86 ut32 minutes = (time & 0x07e0) >> 5;
87 ut32 seconds = (time & 0x001f) << 1;
88
89 /* Convert to epoch */
90 struct tm t = {0};
91 t.tm_year = year - 1900;
92 t.tm_mon = month > 0 ? month - 1 : month;
93 t.tm_mday = day > 0 ? day : 1;
94 t.tm_hour = hour;
95 t.tm_min = minutes;
96 t.tm_sec = seconds;
97 t.tm_isdst = -1;
98 time_t epochTime = mktime (&t);
99
100 return (ut32) epochTime;
101 }
102
r_time_stamp_is_dos_format(const ut32 certainPosixTimeStamp,const ut32 possiblePosixOrDosTimeStamp)103 R_API bool r_time_stamp_is_dos_format(const ut32 certainPosixTimeStamp, const ut32 possiblePosixOrDosTimeStamp) {
104 /* We assume they're both POSIX timestamp and thus the higher bits would be equal if they're close to each other */
105 if ((certainPosixTimeStamp >> 16) == (possiblePosixOrDosTimeStamp >> 16)) {
106 return false;
107 }
108 return true;
109 }
110
111
r_print_date_dos(RPrint * p,const ut8 * buf,int len)112 R_API int r_print_date_dos(RPrint *p, const ut8 *buf, int len) {
113 if(len < 4) {
114 return 0;
115 }
116
117 ut32 dt = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
118 char *s = r_time_stamp_to_str (r_time_dos_time_stamp_to_posix (dt));
119 if (!s) {
120 return 0;
121 }
122 p->cb_printf ("%s\n", s);
123 free (s);
124 return 4;
125 }
126
r_print_date_hfs(RPrint * p,const ut8 * buf,int len)127 R_API int r_print_date_hfs(RPrint *p, const ut8 *buf, int len) {
128 const int hfs_unix_delta = 2082844800;
129 time_t t = 0;
130 int ret = 0;
131
132 if (p && len >= sizeof (ut32)) {
133 t = r_read_ble32 (buf, p->big_endian);
134 if (p->datefmt[0]) {
135 t += p->datezone * (60*60);
136 t += hfs_unix_delta;
137
138 p->cb_printf ("%s\n", r_time_stamp_to_str (t));
139 ret = sizeof (time_t);
140 }
141 }
142 return ret;
143 }
144
r_print_date_unix(RPrint * p,const ut8 * buf,int len)145 R_API int r_print_date_unix(RPrint *p, const ut8 *buf, int len) {
146 time_t t = 0;
147 int ret = 0;
148
149 if (p && len >= sizeof (ut32)) {
150 t = r_read_ble32 (buf, p->big_endian);
151 if (p->datefmt[0]) {
152 t += p->datezone * (60*60);
153 char *datestr = r_time_stamp_to_str (t);
154 if (datestr) {
155 p->cb_printf ("%s\n", datestr);
156 free (datestr);
157 }
158 ret = sizeof (time_t);
159 }
160 }
161 return ret;
162 }
163
r_print_date_get_now(RPrint * p,char * str)164 R_API int r_print_date_get_now(RPrint *p, char *str) {
165 int ret = 0;
166 time_t l;
167
168 *str = 0;
169 l = time(0);
170
171 str = r_time_stamp_to_str (l);
172 p->cb_printf ("%s\n", str);
173 ret = sizeof (time_t);
174 return ret;
175 }
176
r_print_date_w32(RPrint * p,const ut8 * buf,int len)177 R_API int r_print_date_w32(RPrint *p, const ut8 *buf, int len) {
178 ut64 l, L = 0x2b6109100LL;
179 time_t t;
180 int ret = 0;
181
182 if (p && len >= sizeof (ut64)) {
183 l = r_read_ble64 (buf, p->big_endian);
184 l /= 10000000; // 100ns to s
185 l = (l > L ? l-L : 0); // isValidUnixTime?
186 t = (time_t) l; // TODO limit above!
187 if (p->datefmt[0]) {
188 p->cb_printf ("%s\n", r_time_stamp_to_str (t));
189 ret = sizeof (time_t);
190 }
191 }
192
193 return ret;
194 }
195
r_time_to_string(ut64 ts)196 R_API const char *r_time_to_string (ut64 ts) {
197 time_t l;
198 l = ts >> 20;
199 return r_time_stamp_to_str (l);
200 }
201
r_asctime_r(const struct tm * tm,char * buf)202 R_API char *r_asctime_r(const struct tm *tm, char *buf) {
203 #if __WINDOWS__
204 errno_t err = asctime_s (buf, ASCTIME_BUF_MINLEN, tm);
205 return err? NULL: buf;
206 #else
207 return asctime_r (tm, buf);
208 #endif
209 }
210
r_ctime_r(const time_t * timer,char * buf)211 R_API char *r_ctime_r(const time_t *timer, char *buf) {
212 #if __WINDOWS__
213 errno_t err = ctime_s (buf, ASCTIME_BUF_MINLEN, timer);
214 return err? NULL: buf;
215 #else
216 return ctime_r (timer, buf);
217 #endif
218 }
219