forked from aniani/vim
patch 8.1.1567: localtime_r() does not respond to $TZ changes
Problem: Localtime_r() does not respond to $TZ changes. Solution: If $TZ changes then call tzset(). (Tom Ryder)
This commit is contained in:
2
src/auto/configure
vendored
2
src/auto/configure
vendored
@@ -12569,7 +12569,7 @@ for ac_func in fchdir fchown fchmod fsync getcwd getpseudotty \
|
|||||||
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
||||||
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
||||||
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
||||||
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
|
strnicmp strpbrk strtol tgetent towlower towupper iswupper tzset \
|
||||||
usleep utime utimes mblen ftruncate unsetenv posix_openpt
|
usleep utime utimes mblen ftruncate unsetenv posix_openpt
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
|
@@ -217,6 +217,7 @@
|
|||||||
#undef HAVE_TOWLOWER
|
#undef HAVE_TOWLOWER
|
||||||
#undef HAVE_TOWUPPER
|
#undef HAVE_TOWUPPER
|
||||||
#undef HAVE_ISWUPPER
|
#undef HAVE_ISWUPPER
|
||||||
|
#undef HAVE_TZSET
|
||||||
#undef HAVE_UNSETENV
|
#undef HAVE_UNSETENV
|
||||||
#undef HAVE_USLEEP
|
#undef HAVE_USLEEP
|
||||||
#undef HAVE_UTIME
|
#undef HAVE_UTIME
|
||||||
|
@@ -3742,7 +3742,7 @@ AC_CHECK_FUNCS(fchdir fchown fchmod fsync getcwd getpseudotty \
|
|||||||
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
|
||||||
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
|
||||||
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
|
||||||
strnicmp strpbrk strtol tgetent towlower towupper iswupper \
|
strnicmp strpbrk strtol tgetent towlower towupper iswupper tzset \
|
||||||
usleep utime utimes mblen ftruncate unsetenv posix_openpt)
|
usleep utime utimes mblen ftruncate unsetenv posix_openpt)
|
||||||
AC_FUNC_SELECT_ARGTYPES
|
AC_FUNC_SELECT_ARGTYPES
|
||||||
AC_FUNC_FSEEKO
|
AC_FUNC_FSEEKO
|
||||||
|
@@ -13188,9 +13188,7 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
|
|||||||
f_strftime(typval_T *argvars, typval_T *rettv)
|
f_strftime(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
char_u result_buf[256];
|
char_u result_buf[256];
|
||||||
# ifdef HAVE_LOCALTIME_R
|
|
||||||
struct tm tmval;
|
struct tm tmval;
|
||||||
# endif
|
|
||||||
struct tm *curtime;
|
struct tm *curtime;
|
||||||
time_t seconds;
|
time_t seconds;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@@ -13202,11 +13200,7 @@ f_strftime(typval_T *argvars, typval_T *rettv)
|
|||||||
seconds = time(NULL);
|
seconds = time(NULL);
|
||||||
else
|
else
|
||||||
seconds = (time_t)tv_get_number(&argvars[1]);
|
seconds = (time_t)tv_get_number(&argvars[1]);
|
||||||
# ifdef HAVE_LOCALTIME_R
|
curtime = vim_localtime(&seconds, &tmval);
|
||||||
curtime = localtime_r(&seconds, &tmval);
|
|
||||||
# else
|
|
||||||
curtime = localtime(&seconds);
|
|
||||||
# endif
|
|
||||||
/* MSVC returns NULL for an invalid value of seconds. */
|
/* MSVC returns NULL for an invalid value of seconds. */
|
||||||
if (curtime == NULL)
|
if (curtime == NULL)
|
||||||
rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
|
rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
|
||||||
|
@@ -2081,6 +2081,48 @@ get_b0_dict(char_u *fname, dict_T *d)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache of the current timezone name as retrieved from TZ, or an empty string
|
||||||
|
* where unset, up to 64 octets long including trailing null byte.
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_LOCALTIME_R) && defined(HAVE_TZSET)
|
||||||
|
static char tz_cache[64];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call either localtime(3) or localtime_r(3) from POSIX libc time.h, with the
|
||||||
|
* latter version preferred for reentrancy.
|
||||||
|
*
|
||||||
|
* If we use localtime_r(3) and we have tzset(3) available, check to see if the
|
||||||
|
* environment variable TZ has changed since the last run, and call tzset(3) to
|
||||||
|
* update the global timezone variables if it has. This is because the POSIX
|
||||||
|
* standard doesn't require localtime_r(3) implementations to do that as it
|
||||||
|
* does with localtime(3), and we don't want to call tzset(3) every time.
|
||||||
|
*/
|
||||||
|
struct tm *
|
||||||
|
vim_localtime(
|
||||||
|
const time_t *timep, // timestamp for local representation
|
||||||
|
struct tm *result) // pointer to caller return buffer
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LOCALTIME_R
|
||||||
|
# ifdef HAVE_TZSET
|
||||||
|
char *tz; // pointer for TZ environment var
|
||||||
|
|
||||||
|
tz = (char *)mch_getenv((char_u *)"TZ");
|
||||||
|
if (tz == NULL)
|
||||||
|
tz = "";
|
||||||
|
if (STRNCMP(tz_cache, tz, sizeof(tz_cache) - 1) != 0)
|
||||||
|
{
|
||||||
|
tzset();
|
||||||
|
vim_strncpy((char_u *)tz_cache, (char_u *)tz, sizeof(tz_cache) - 1);
|
||||||
|
}
|
||||||
|
# endif // HAVE_TZSET
|
||||||
|
return localtime_r(timep, result);
|
||||||
|
#else
|
||||||
|
return localtime(timep);
|
||||||
|
#endif // HAVE_LOCALTIME_R
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replacement for ctime(), which is not safe to use.
|
* Replacement for ctime(), which is not safe to use.
|
||||||
* Requires strftime(), otherwise returns "(unknown)".
|
* Requires strftime(), otherwise returns "(unknown)".
|
||||||
@@ -2093,16 +2135,10 @@ get_ctime(time_t thetime, int add_newline)
|
|||||||
{
|
{
|
||||||
static char buf[50];
|
static char buf[50];
|
||||||
#ifdef HAVE_STRFTIME
|
#ifdef HAVE_STRFTIME
|
||||||
# ifdef HAVE_LOCALTIME_R
|
|
||||||
struct tm tmval;
|
struct tm tmval;
|
||||||
# endif
|
|
||||||
struct tm *curtime;
|
struct tm *curtime;
|
||||||
|
|
||||||
# ifdef HAVE_LOCALTIME_R
|
curtime = vim_localtime(&thetime, &tmval);
|
||||||
curtime = localtime_r(&thetime, &tmval);
|
|
||||||
# else
|
|
||||||
curtime = localtime(&thetime);
|
|
||||||
# endif
|
|
||||||
/* MSVC returns NULL for an invalid value of seconds. */
|
/* MSVC returns NULL for an invalid value of seconds. */
|
||||||
if (curtime == NULL)
|
if (curtime == NULL)
|
||||||
vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1);
|
vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1);
|
||||||
|
@@ -13,6 +13,7 @@ void ml_recover(int checkext);
|
|||||||
int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
|
int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
|
||||||
char_u *make_percent_swname(char_u *dir, char_u *name);
|
char_u *make_percent_swname(char_u *dir, char_u *name);
|
||||||
void get_b0_dict(char_u *fname, dict_T *d);
|
void get_b0_dict(char_u *fname, dict_T *d);
|
||||||
|
struct tm *vim_localtime(const time_t *timep, struct tm *result);
|
||||||
char *get_ctime(time_t thetime, int add_newline);
|
char *get_ctime(time_t thetime, int add_newline);
|
||||||
void ml_sync_all(int check_file, int check_char);
|
void ml_sync_all(int check_file, int check_char);
|
||||||
void ml_preserve(buf_T *buf, int message);
|
void ml_preserve(buf_T *buf, int message);
|
||||||
|
@@ -187,6 +187,30 @@ func Test_strftime()
|
|||||||
|
|
||||||
call assert_fails('call strftime([])', 'E730:')
|
call assert_fails('call strftime([])', 'E730:')
|
||||||
call assert_fails('call strftime("%Y", [])', 'E745:')
|
call assert_fails('call strftime("%Y", [])', 'E745:')
|
||||||
|
|
||||||
|
" Check that the time changes after we change the timezone
|
||||||
|
" Save previous timezone value, if any
|
||||||
|
if exists('$TZ')
|
||||||
|
let tz = $TZ
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Force EST and then UTC, save the current hour (24-hour clock) for each
|
||||||
|
let $TZ = 'EST' | let est = strftime('%H')
|
||||||
|
let $TZ = 'UTC' | let utc = strftime('%H')
|
||||||
|
|
||||||
|
" Those hours should be two bytes long, and should not be the same; if they
|
||||||
|
" are, a tzset(3) call may have failed somewhere
|
||||||
|
call assert_equal(strlen(est), 2)
|
||||||
|
call assert_equal(strlen(utc), 2)
|
||||||
|
call assert_notequal(est, utc)
|
||||||
|
|
||||||
|
" If we cached a timezone value, put it back, otherwise clear it
|
||||||
|
if exists('tz')
|
||||||
|
let $TZ = tz
|
||||||
|
else
|
||||||
|
unlet $TZ
|
||||||
|
endif
|
||||||
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_resolve_unix()
|
func Test_resolve_unix()
|
||||||
|
@@ -3111,18 +3111,12 @@ ex_undolist(exarg_T *eap UNUSED)
|
|||||||
u_add_time(char_u *buf, size_t buflen, time_t tt)
|
u_add_time(char_u *buf, size_t buflen, time_t tt)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_STRFTIME
|
#ifdef HAVE_STRFTIME
|
||||||
# ifdef HAVE_LOCALTIME_R
|
|
||||||
struct tm tmval;
|
struct tm tmval;
|
||||||
# endif
|
|
||||||
struct tm *curtime;
|
struct tm *curtime;
|
||||||
|
|
||||||
if (vim_time() - tt >= 100)
|
if (vim_time() - tt >= 100)
|
||||||
{
|
{
|
||||||
# ifdef HAVE_LOCALTIME_R
|
curtime = vim_localtime(&tt, &tmval);
|
||||||
curtime = localtime_r(&tt, &tmval);
|
|
||||||
# else
|
|
||||||
curtime = localtime(&tt);
|
|
||||||
# endif
|
|
||||||
if (vim_time() - tt < (60L * 60L * 12L))
|
if (vim_time() - tt < (60L * 60L * 12L))
|
||||||
/* within 12 hours */
|
/* within 12 hours */
|
||||||
(void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
|
(void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
|
||||||
|
@@ -777,6 +777,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1567,
|
||||||
/**/
|
/**/
|
||||||
1566,
|
1566,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user