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