Fix timezone portability issue (fixes #515)

This commit is contained in:
Jay Berkenbilt 2021-04-17 18:12:55 -04:00
parent 8971443e46
commit 36c7c20819
6 changed files with 128 additions and 3 deletions

View File

@ -1,3 +1,10 @@
2021-04-17 Jay Berkenbilt <ejb@ql.org>
* Portability fix: use tm_gmtoff rather than global timezone
variable if available to get timezone offset. This fixes
compilation on BSD and also results in a daylight saving
time-aware offset for Linux or other GNU systems. Fixes #515.
2021-04-05 Jay Berkenbilt <ejb@ql.org>
* When adding a page, if the page already exists, make a shallow

View File

@ -1,6 +1,6 @@
e98dd9c0e2040a128e0bae722821ca1183bd965405d654fb061474a3bddc2327 configure.ac
04144cd524b4278d6e3c3e0340cf03400daceaf1a241031c1053f8da544d1042 configure.ac
d3f9ee6f6f0846888d9a10fd3dad2e4b1258be84205426cf04d7cef02d61dad7 aclocal.m4
3ed561073f0d5c9899e2120e006a7da5ec6bffb80268da1b962cd4f893b89982 libqpdf/qpdf/qpdf-config.h.in
c12d837479fa9a3fa4c278b6dc7d6b449503d663e0f0d294305595a51ff43f70 libqpdf/qpdf/qpdf-config.h.in
5297971a0ef90bcd5563eb3f7127a032bb76d3ae2af7258bf13479caf8983a60 m4/ax_cxx_compile_stdcxx.m4
35bc5c645dc42d47f2daeea06f8f3e767c8a1aee6a35eb2b4854fd2ce66c3413 m4/ax_random_device.m4
1451e63710701b5f00a668f3a79b435015ef2e63547f0ad0ce8c8c062d53b599 m4/libtool.m4

72
configure vendored
View File

@ -17830,6 +17830,78 @@ $as_echo "no" >&6; }
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for tm_gmtoff in struct tm" >&5
$as_echo_n "checking for tm_gmtoff in struct tm... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <time.h>
int
main ()
{
struct tm tm;
tm.tm_gmtoff = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
qpdf_TM_GMTOFF=1
else
qpdf_TM_GMTOFF=0
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "$qpdf_TM_GMTOFF" = "1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for extern long timezone" >&5
$as_echo_n "checking for extern long timezone... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <time.h>
#include <stdio.h>
int
main ()
{
tzset();
printf("%ld\n", timezone);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
qpdf_EXTERN_LONG_TIMEZONE=1
else
qpdf_EXTERN_LONG_TIMEZONE=0
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
if test "$qpdf_EXTERN_LONG_TIMEZONE" = "1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_EXTERN_LONG_TIMEZONE 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
LL_FMT=""
oCFLAGS=$CFLAGS
CFLAGS="$WFLAGS $CFLAGS"

View File

@ -520,6 +520,35 @@ if test "$BUILDRULES" != "msvc"; then
fi
fi
AC_MSG_CHECKING(for tm_gmtoff in struct tm)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <time.h>
]],[[
struct tm tm;
tm.tm_gmtoff = 1;
]])], [qpdf_TM_GMTOFF=1], [qpdf_TM_GMTOFF=0])
if test "$qpdf_TM_GMTOFF" = "1"; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_TM_GMTOFF], [1], [Whether struct tm has tm_gmtoff])
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(for extern long timezone)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <time.h>
#include <stdio.h>
]],[[
tzset();
printf("%ld\n", timezone);
]])], [qpdf_EXTERN_LONG_TIMEZONE=1], [qpdf_EXTERN_LONG_TIMEZONE=0])
if test "$qpdf_EXTERN_LONG_TIMEZONE" = "1"; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_EXTERN_LONG_TIMEZONE], [1], [Whether extern long timezone is available])
else
AC_MSG_RESULT(no)
fi
LL_FMT=""
oCFLAGS=$CFLAGS
CFLAGS="$WFLAGS $CFLAGS"

View File

@ -889,6 +889,7 @@ QUtil::get_current_qpdf_time()
static_cast<int>(ltime.wHour),
static_cast<int>(ltime.wMinute),
static_cast<int>(ltime.wSecond),
// tzinfo.Bias is minutes before UTC
static_cast<int>(tzinfo.Bias));
#else
struct tm ltime;
@ -898,6 +899,16 @@ QUtil::get_current_qpdf_time()
localtime_r(&now, &ltime);
#else
ltime = *localtime(&now);
#endif
#if HAVE_TM_GMTOFF
// tm_gmtoff is seconds after UTC
int tzoff = -static_cast<int>(ltime.tm_gmtoff / 60);
#elif HAVE_EXTERN_LONG_TIMEZONE
// timezone is seconds before UTC, not adjusted for daylight saving time
int tzoff = static_cast<int>(timezone / 60);
#else
// Don't know how to get timezone on this platform
int tzoff = 0;
#endif
return QPDFTime(static_cast<int>(ltime.tm_year + 1900),
static_cast<int>(ltime.tm_mon + 1),
@ -905,7 +916,7 @@ QUtil::get_current_qpdf_time()
static_cast<int>(ltime.tm_hour),
static_cast<int>(ltime.tm_min),
static_cast<int>(ltime.tm_sec),
static_cast<int>(timezone / 60));
tzoff);
#endif
}

View File

@ -12,6 +12,9 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Whether extern long timezone is available */
#undef HAVE_EXTERN_LONG_TIMEZONE
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#undef HAVE_FSEEKO
@ -51,6 +54,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Whether struct tm has tm_gmtoff */
#undef HAVE_TM_GMTOFF
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H