2020-08-12 16:54:49 +00:00
|
|
|
/* radare - LGPL - Copyright 2007-2020 - pancake, thestr4ng3r */
|
2009-02-09 11:42:54 +00:00
|
|
|
|
2020-08-12 16:54:49 +00:00
|
|
|
#include <r_util.h>
|
|
|
|
#include <r_util/r_print.h>
|
|
|
|
|
|
|
|
#if __linux__
|
|
|
|
#include <time.h>
|
|
|
|
#elif __APPLE__ && !defined(MAC_OS_X_VERSION_10_12)
|
|
|
|
#include <mach/mach_time.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
R_API ut64 r_time_now(void) {
|
|
|
|
ut64 ret;
|
|
|
|
struct timeval now;
|
|
|
|
gettimeofday (&now, NULL);
|
|
|
|
ret = now.tv_sec * R_USEC_PER_SEC;
|
|
|
|
ret += now.tv_usec;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API ut64 r_time_now_mono(void) {
|
|
|
|
#if __WINDOWS__
|
|
|
|
LARGE_INTEGER f;
|
|
|
|
if (!QueryPerformanceFrequency (&f)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
LARGE_INTEGER v;
|
|
|
|
if (!QueryPerformanceCounter (&v)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
v.QuadPart *= 1000000;
|
|
|
|
v.QuadPart /= f.QuadPart;
|
|
|
|
return v.QuadPart;
|
|
|
|
#elif __APPLE__ && !defined(MAC_OS_X_VERSION_10_12)
|
|
|
|
ut64 ticks = mach_absolute_time ();
|
|
|
|
static mach_timebase_info_data_t tb;
|
|
|
|
mach_timebase_info (&tb);
|
|
|
|
return ((ticks * tb.numer) / tb.denom) / R_NSEC_PER_USEC;
|
|
|
|
#else
|
|
|
|
struct timespec now;
|
|
|
|
clock_gettime (CLOCK_MONOTONIC, &now);
|
|
|
|
return now.tv_sec * R_USEC_PER_SEC
|
|
|
|
+ now.tv_nsec / R_NSEC_PER_USEC;
|
|
|
|
#endif
|
|
|
|
}
|
2019-01-16 20:47:44 +00:00
|
|
|
|
|
|
|
R_API char *r_time_stamp_to_str(ut32 timeStamp) {
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
time_t rawtime;
|
|
|
|
struct tm *tminfo;
|
|
|
|
rawtime = (time_t)timeStamp;
|
|
|
|
tminfo = localtime (&rawtime);
|
|
|
|
//tminfo = gmtime (&rawtime);
|
2019-06-16 18:58:40 +00:00
|
|
|
return r_str_trim_dup (asctime (tminfo));
|
2019-01-16 20:47:44 +00:00
|
|
|
#else
|
|
|
|
struct my_timezone {
|
|
|
|
int tz_minuteswest; /* minutes west of Greenwich */
|
|
|
|
int tz_dsttime; /* type of DST correction */
|
|
|
|
} tz;
|
|
|
|
struct timeval tv;
|
|
|
|
int gmtoff;
|
|
|
|
time_t ts = (time_t) timeStamp;
|
|
|
|
gettimeofday (&tv, (void*) &tz);
|
|
|
|
gmtoff = (int) (tz.tz_minuteswest * 60); // in seconds
|
|
|
|
ts += (time_t)gmtoff;
|
2019-06-16 18:58:40 +00:00
|
|
|
char *res = strdup (ctime (&ts));
|
|
|
|
if (res) {
|
|
|
|
r_str_trim (res); // XXX we probably need an r_str_trim_dup()
|
|
|
|
}
|
|
|
|
return res;
|
2019-01-16 20:47:44 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-08-12 16:54:49 +00:00
|
|
|
R_API ut32 r_time_dos_time_stamp_to_posix(ut32 timeStamp) {
|
2020-08-28 10:52:20 +00:00
|
|
|
ut16 date = timeStamp >> 16;
|
2020-08-12 16:54:49 +00:00
|
|
|
ut16 time = timeStamp & 0xFFFF;
|
2020-08-28 10:52:20 +00:00
|
|
|
|
2020-08-12 16:54:49 +00:00
|
|
|
/* Date */
|
|
|
|
ut32 year = ((date & 0xfe00) >> 9) + 1980;
|
|
|
|
ut32 month = (date & 0x01e0) >> 5;
|
|
|
|
ut32 day = date & 0x001f;
|
2020-08-28 10:52:20 +00:00
|
|
|
|
2020-08-12 16:54:49 +00:00
|
|
|
/* Time */
|
2020-08-28 10:52:20 +00:00
|
|
|
ut32 hour = (time & 0xf800) >> 11;
|
2020-08-12 16:54:49 +00:00
|
|
|
ut32 minutes = (time & 0x07e0) >> 5;
|
|
|
|
ut32 seconds = (time & 0x001f) << 1;
|
2019-01-16 20:47:44 +00:00
|
|
|
|
|
|
|
/* Convert to epoch */
|
|
|
|
struct tm t = {0};
|
|
|
|
t.tm_year = year - 1900;
|
|
|
|
t.tm_mon = month > 0 ? month - 1 : month;
|
|
|
|
t.tm_mday = day > 0 ? day : 1;
|
|
|
|
t.tm_hour = hour;
|
|
|
|
t.tm_min = minutes;
|
|
|
|
t.tm_sec = seconds;
|
|
|
|
t.tm_isdst = -1;
|
|
|
|
time_t epochTime = mktime (&t);
|
|
|
|
|
|
|
|
return (ut32) epochTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API bool r_time_stamp_is_dos_format(const ut32 certainPosixTimeStamp, const ut32 possiblePosixOrDosTimeStamp) {
|
|
|
|
/* We assume they're both POSIX timestamp and thus the higher bits would be equal if they're close to each other */
|
|
|
|
if ((certainPosixTimeStamp >> 16) == (possiblePosixOrDosTimeStamp >> 16)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-02-09 11:42:54 +00:00
|
|
|
|
2018-02-19 12:30:32 +00:00
|
|
|
R_API int r_print_date_dos(RPrint *p, const ut8 *buf, int len) {
|
2019-01-16 20:47:44 +00:00
|
|
|
if(len < 4) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ut32 dt = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
|
2020-08-12 16:54:49 +00:00
|
|
|
char *s = r_time_stamp_to_str (r_time_dos_time_stamp_to_posix (dt));
|
|
|
|
if (!s) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
p->cb_printf ("%s\n", s);
|
|
|
|
free (s);
|
2009-03-12 00:42:32 +00:00
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2017-02-26 22:01:49 +00:00
|
|
|
R_API int r_print_date_hfs(RPrint *p, const ut8 *buf, int len) {
|
|
|
|
const int hfs_unix_delta = 2082844800;
|
|
|
|
time_t t = 0;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (p && len >= sizeof (ut32)) {
|
|
|
|
t = r_read_ble32 (buf, p->big_endian);
|
|
|
|
if (p->datefmt[0]) {
|
|
|
|
t += p->datezone * (60*60);
|
|
|
|
t += hfs_unix_delta;
|
2019-01-16 20:47:44 +00:00
|
|
|
|
|
|
|
p->cb_printf ("%s\n", r_time_stamp_to_str (t));
|
|
|
|
ret = sizeof (time_t);
|
2017-02-26 22:01:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-04-15 23:48:03 +00:00
|
|
|
R_API int r_print_date_unix(RPrint *p, const ut8 *buf, int len) {
|
2015-05-01 05:33:14 +00:00
|
|
|
time_t t = 0;
|
2013-04-15 23:48:03 +00:00
|
|
|
int ret = 0;
|
2009-03-12 00:42:32 +00:00
|
|
|
|
2017-02-26 22:01:49 +00:00
|
|
|
if (p && len >= sizeof (ut32)) {
|
2016-04-26 09:09:15 +00:00
|
|
|
t = r_read_ble32 (buf, p->big_endian);
|
2014-03-08 06:41:22 +00:00
|
|
|
if (p->datefmt[0]) {
|
2019-10-03 13:38:33 +00:00
|
|
|
t += p->datezone * (60*60);
|
|
|
|
char *datestr = r_time_stamp_to_str (t);
|
|
|
|
if (datestr) {
|
|
|
|
p->cb_printf ("%s\n", datestr);
|
|
|
|
free (datestr);
|
|
|
|
}
|
2019-01-16 20:47:44 +00:00
|
|
|
ret = sizeof (time_t);
|
2009-03-12 00:42:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2009-02-09 11:42:54 +00:00
|
|
|
}
|
|
|
|
|
2013-04-15 23:48:03 +00:00
|
|
|
R_API int r_print_date_get_now(RPrint *p, char *str) {
|
2009-03-12 00:42:32 +00:00
|
|
|
int ret = 0;
|
2009-02-09 11:42:54 +00:00
|
|
|
time_t l;
|
|
|
|
|
2015-12-05 18:57:06 +00:00
|
|
|
*str = 0;
|
2009-02-09 11:42:54 +00:00
|
|
|
l = time(0);
|
2019-01-16 20:47:44 +00:00
|
|
|
|
|
|
|
str = r_time_stamp_to_str (l);
|
|
|
|
p->cb_printf ("%s\n", str);
|
|
|
|
ret = sizeof (time_t);
|
2009-03-12 00:42:32 +00:00
|
|
|
return ret;
|
2009-02-09 11:42:54 +00:00
|
|
|
}
|
|
|
|
|
2013-04-15 23:48:03 +00:00
|
|
|
R_API int r_print_date_w32(RPrint *p, const ut8 *buf, int len) {
|
2009-07-08 11:49:55 +00:00
|
|
|
ut64 l, L = 0x2b6109100LL;
|
2009-03-12 00:42:32 +00:00
|
|
|
time_t t;
|
|
|
|
int ret = 0;
|
2009-02-09 11:42:54 +00:00
|
|
|
|
2014-07-30 20:13:55 +00:00
|
|
|
if (p && len >= sizeof (ut64)) {
|
2016-04-26 09:09:15 +00:00
|
|
|
l = r_read_ble64 (buf, p->big_endian);
|
2009-03-12 00:42:32 +00:00
|
|
|
l /= 10000000; // 100ns to s
|
|
|
|
l = (l > L ? l-L : 0); // isValidUnixTime?
|
|
|
|
t = (time_t) l; // TODO limit above!
|
2014-07-28 16:12:18 +00:00
|
|
|
if (p->datefmt[0]) {
|
2019-01-16 20:47:44 +00:00
|
|
|
p->cb_printf ("%s\n", r_time_stamp_to_str (t));
|
|
|
|
ret = sizeof (time_t);
|
2009-03-12 00:42:32 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-09 11:42:54 +00:00
|
|
|
|
2009-03-12 00:42:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2018-10-31 00:52:08 +00:00
|
|
|
|
|
|
|
R_API const char *r_time_to_string (ut64 ts) {
|
2019-01-16 20:47:44 +00:00
|
|
|
time_t l;
|
|
|
|
l = ts >> 20;
|
|
|
|
return r_time_stamp_to_str (l);
|
2018-10-31 00:52:08 +00:00
|
|
|
}
|