diff --git a/ChangeLog b/ChangeLog index f720fa24..8b2f6867 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2021-04-17 Jay Berkenbilt + + * 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 * When adding a page, if the page already exists, make a shallow diff --git a/autofiles.sums b/autofiles.sums index 151dacd2..0e0e38e8 100644 --- a/autofiles.sums +++ b/autofiles.sums @@ -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 diff --git a/configure b/configure index 55c59a92..daac3f5a 100755 --- a/configure +++ b/configure @@ -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 + +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 + #include + +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" diff --git a/configure.ac b/configure.ac index 7cf58123..a1c4e5fb 100644 --- a/configure.ac +++ b/configure.ac @@ -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 + ]],[[ + 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 + #include + ]],[[ + 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" diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc index 17b163f5..f45468a0 100644 --- a/libqpdf/QUtil.cc +++ b/libqpdf/QUtil.cc @@ -889,6 +889,7 @@ QUtil::get_current_qpdf_time() static_cast(ltime.wHour), static_cast(ltime.wMinute), static_cast(ltime.wSecond), + // tzinfo.Bias is minutes before UTC static_cast(tzinfo.Bias)); #else struct tm ltime; @@ -898,6 +899,16 @@ QUtil::get_current_qpdf_time() localtime_r(&now, <ime); #else ltime = *localtime(&now); +#endif +#if HAVE_TM_GMTOFF + // tm_gmtoff is seconds after UTC + int tzoff = -static_cast(ltime.tm_gmtoff / 60); +#elif HAVE_EXTERN_LONG_TIMEZONE + // timezone is seconds before UTC, not adjusted for daylight saving time + int tzoff = static_cast(timezone / 60); +#else + // Don't know how to get timezone on this platform + int tzoff = 0; #endif return QPDFTime(static_cast(ltime.tm_year + 1900), static_cast(ltime.tm_mon + 1), @@ -905,7 +916,7 @@ QUtil::get_current_qpdf_time() static_cast(ltime.tm_hour), static_cast(ltime.tm_min), static_cast(ltime.tm_sec), - static_cast(timezone / 60)); + tzoff); #endif } diff --git a/libqpdf/qpdf/qpdf-config.h.in b/libqpdf/qpdf/qpdf-config.h.in index 78ebc86d..d0e42fbd 100644 --- a/libqpdf/qpdf/qpdf-config.h.in +++ b/libqpdf/qpdf/qpdf-config.h.in @@ -12,6 +12,9 @@ /* Define to 1 if you have the 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 header file. */ #undef HAVE_SYS_TYPES_H +/* Whether struct tm has tm_gmtoff */ +#undef HAVE_TM_GMTOFF + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H