diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/eval.c | 10 | ||||
-rw-r--r-- | src/log.c | 17 | ||||
-rw-r--r-- | src/os/time.c | 25 | ||||
-rw-r--r-- | src/os/time.h | 11 | ||||
-rw-r--r-- | src/undo.c | 9 |
5 files changed, 51 insertions, 21 deletions
diff --git a/src/eval.c b/src/eval.c index df11174898..fba95789ac 100644 --- a/src/eval.c +++ b/src/eval.c @@ -65,6 +65,7 @@ #include "os/job.h" #include "os/rstream.h" #include "os/rstream_defs.h" +#include "os/time.h" #if defined(FEAT_FLOAT) # include <math.h> @@ -14163,7 +14164,6 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv) static void f_strftime(typval_T *argvars, typval_T *rettv) { char_u result_buf[256]; - struct tm *curtime; time_t seconds; char_u *p; @@ -14174,9 +14174,11 @@ static void f_strftime(typval_T *argvars, typval_T *rettv) seconds = time(NULL); else seconds = (time_t)get_tv_number(&argvars[1]); - curtime = localtime(&seconds); + + struct tm curtime; + struct tm *curtime_ptr = os_localtime_r(&seconds, &curtime); /* MSVC returns NULL for an invalid value of seconds. */ - if (curtime == NULL) + if (curtime_ptr == NULL) rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)")); else { vimconv_T conv; @@ -14189,7 +14191,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv) p = string_convert(&conv, p, NULL); if (p != NULL) (void)strftime((char *)result_buf, sizeof(result_buf), - (char *)p, curtime); + (char *)p, curtime_ptr); else result_buf[0] = NUL; @@ -11,6 +11,7 @@ #include "misc1.h" #include "types.h" #include "os/os.h" +#include "os/time.h" #define USR_LOG_FILE "$HOME/.nvimlog" @@ -117,23 +118,13 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL); // format current timestamp in local time - struct timeval tv; - if (gettimeofday(&tv, NULL) < 0) { + struct tm local_time; + if (os_get_localtime(&local_time) == NULL) { return false; } -#ifdef UNIX - // localtime() is not thread-safe. POSIX provides localtime_r() as a - // thread-safe version. - struct tm local_time_allocated; - struct tm *local_time = localtime_r(&tv.tv_sec, &local_time_allocated); -#else - // Windows version of localtime() is thread-safe. - // See http://msdn.microsoft.com/en-us/library/bf12f0hc%28VS.80%29.aspx - struct tm *local_time = localtime(&tv.tv_sec); // NOLINT -#endif char date_time[20]; if (strftime(date_time, sizeof(date_time), "%Y/%m/%d %H:%M:%S", - local_time) == 0) { + &local_time) == 0) { return false; } diff --git a/src/os/time.c b/src/os/time.c index 0f7c990e23..1dc7ca68d4 100644 --- a/src/os/time.c +++ b/src/os/time.c @@ -1,5 +1,6 @@ #include <stdint.h> #include <stdbool.h> +#include <sys/time.h> #include <uv.h> @@ -59,3 +60,27 @@ static void microdelay(uint64_t microseconds) uv_mutex_unlock(&delay_mutex); } + +struct tm *os_localtime_r(const time_t *clock, struct tm *result) +{ +#ifdef UNIX + // POSIX provides localtime_r() as a thread-safe version of localtime(). + return localtime_r(clock, result); +#else + // Windows version of localtime() is thread-safe. + // See http://msdn.microsoft.com/en-us/library/bf12f0hc%28VS.80%29.aspx + struct tm *local_time = localtime(clock); // NOLINT + *result = *local_time; +return result; +#endif +} + +struct tm *os_get_localtime(struct tm *result) +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) { + return NULL; + } + + return os_localtime_r(&tv.tv_sec, result); +} diff --git a/src/os/time.h b/src/os/time.h index 42feaa3eba..ef795d03be 100644 --- a/src/os/time.h +++ b/src/os/time.h @@ -19,6 +19,17 @@ void os_delay(uint64_t milliseconds, bool ignoreinput); /// @param ignoreinput If true, allow a SIGINT to interrupt us void os_microdelay(uint64_t microseconds, bool ignoreinput); +/// Portable version of POSIX localtime_r() +/// +/// @return NULL in case of error +struct tm *os_localtime_r(const time_t *clock, struct tm *result); + +/// Obtains the current UNIX timestamp and adjusts it to local time +/// +/// @param result Pointer to a 'struct tm' where the result should be placed +/// @return A pointer to a 'struct tm' in the current time zone (the 'result' +/// argument) or NULL in case of error +struct tm *os_get_localtime(struct tm *result); #endif // NEOVIM_OS_TIME_H diff --git a/src/undo.c b/src/undo.c index 243d865513..5e00d58d77 100644 --- a/src/undo.c +++ b/src/undo.c @@ -103,6 +103,7 @@ #include "screen.h" #include "sha256.h" #include "os/os.h" +#include "os/time.h" static long get_undolevel(void); static void u_unch_branch(u_header_T *uhp); @@ -2455,16 +2456,16 @@ void ex_undolist(exarg_T *eap) */ static void u_add_time(char_u *buf, size_t buflen, time_t tt) { - struct tm *curtime; + struct tm curtime; if (time(NULL) - tt >= 100) { - curtime = localtime(&tt); + os_localtime_r(&tt, &curtime); if (time(NULL) - tt < (60L * 60L * 12L)) /* within 12 hours */ - (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime); + (void)strftime((char *)buf, buflen, "%H:%M:%S", &curtime); else /* longer ago */ - (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime); + (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", &curtime); } else vim_snprintf((char *)buf, buflen, _("%" PRId64 " seconds ago"), (int64_t)(time(NULL) - tt)); |