Commit 36c7c208191a0fd34cf48bdfb4af66b4ab0ec594
1 parent
8971443e
Fix timezone portability issue (fixes #515)
Showing
6 changed files
with
128 additions
and
3 deletions
ChangeLog
| 1 | +2021-04-17 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * Portability fix: use tm_gmtoff rather than global timezone | |
| 4 | + variable if available to get timezone offset. This fixes | |
| 5 | + compilation on BSD and also results in a daylight saving | |
| 6 | + time-aware offset for Linux or other GNU systems. Fixes #515. | |
| 7 | + | |
| 1 | 8 | 2021-04-05 Jay Berkenbilt <ejb@ql.org> |
| 2 | 9 | |
| 3 | 10 | * When adding a page, if the page already exists, make a shallow | ... | ... |
autofiles.sums
| 1 | -e98dd9c0e2040a128e0bae722821ca1183bd965405d654fb061474a3bddc2327 configure.ac | |
| 1 | +04144cd524b4278d6e3c3e0340cf03400daceaf1a241031c1053f8da544d1042 configure.ac | |
| 2 | 2 | d3f9ee6f6f0846888d9a10fd3dad2e4b1258be84205426cf04d7cef02d61dad7 aclocal.m4 |
| 3 | -3ed561073f0d5c9899e2120e006a7da5ec6bffb80268da1b962cd4f893b89982 libqpdf/qpdf/qpdf-config.h.in | |
| 3 | +c12d837479fa9a3fa4c278b6dc7d6b449503d663e0f0d294305595a51ff43f70 libqpdf/qpdf/qpdf-config.h.in | |
| 4 | 4 | 5297971a0ef90bcd5563eb3f7127a032bb76d3ae2af7258bf13479caf8983a60 m4/ax_cxx_compile_stdcxx.m4 |
| 5 | 5 | 35bc5c645dc42d47f2daeea06f8f3e767c8a1aee6a35eb2b4854fd2ce66c3413 m4/ax_random_device.m4 |
| 6 | 6 | 1451e63710701b5f00a668f3a79b435015ef2e63547f0ad0ce8c8c062d53b599 m4/libtool.m4 | ... | ... |
configure
| ... | ... | @@ -17830,6 +17830,78 @@ $as_echo "no" >&6; } |
| 17830 | 17830 | fi |
| 17831 | 17831 | fi |
| 17832 | 17832 | |
| 17833 | +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for tm_gmtoff in struct tm" >&5 | |
| 17834 | +$as_echo_n "checking for tm_gmtoff in struct tm... " >&6; } | |
| 17835 | +cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
| 17836 | +/* end confdefs.h. */ | |
| 17837 | + | |
| 17838 | + #include <time.h> | |
| 17839 | + | |
| 17840 | +int | |
| 17841 | +main () | |
| 17842 | +{ | |
| 17843 | + | |
| 17844 | + struct tm tm; | |
| 17845 | + tm.tm_gmtoff = 1; | |
| 17846 | + | |
| 17847 | + ; | |
| 17848 | + return 0; | |
| 17849 | +} | |
| 17850 | +_ACEOF | |
| 17851 | +if ac_fn_c_try_compile "$LINENO"; then : | |
| 17852 | + qpdf_TM_GMTOFF=1 | |
| 17853 | +else | |
| 17854 | + qpdf_TM_GMTOFF=0 | |
| 17855 | +fi | |
| 17856 | +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
| 17857 | +if test "$qpdf_TM_GMTOFF" = "1"; then | |
| 17858 | + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
| 17859 | +$as_echo "yes" >&6; } | |
| 17860 | + | |
| 17861 | +$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h | |
| 17862 | + | |
| 17863 | +else | |
| 17864 | + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
| 17865 | +$as_echo "no" >&6; } | |
| 17866 | +fi | |
| 17867 | + | |
| 17868 | +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for extern long timezone" >&5 | |
| 17869 | +$as_echo_n "checking for extern long timezone... " >&6; } | |
| 17870 | +cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
| 17871 | +/* end confdefs.h. */ | |
| 17872 | + | |
| 17873 | + #include <time.h> | |
| 17874 | + #include <stdio.h> | |
| 17875 | + | |
| 17876 | +int | |
| 17877 | +main () | |
| 17878 | +{ | |
| 17879 | + | |
| 17880 | + tzset(); | |
| 17881 | + printf("%ld\n", timezone); | |
| 17882 | + | |
| 17883 | + ; | |
| 17884 | + return 0; | |
| 17885 | +} | |
| 17886 | +_ACEOF | |
| 17887 | +if ac_fn_c_try_link "$LINENO"; then : | |
| 17888 | + qpdf_EXTERN_LONG_TIMEZONE=1 | |
| 17889 | +else | |
| 17890 | + qpdf_EXTERN_LONG_TIMEZONE=0 | |
| 17891 | +fi | |
| 17892 | +rm -f core conftest.err conftest.$ac_objext \ | |
| 17893 | + conftest$ac_exeext conftest.$ac_ext | |
| 17894 | +if test "$qpdf_EXTERN_LONG_TIMEZONE" = "1"; then | |
| 17895 | + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
| 17896 | +$as_echo "yes" >&6; } | |
| 17897 | + | |
| 17898 | +$as_echo "#define HAVE_EXTERN_LONG_TIMEZONE 1" >>confdefs.h | |
| 17899 | + | |
| 17900 | +else | |
| 17901 | + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
| 17902 | +$as_echo "no" >&6; } | |
| 17903 | +fi | |
| 17904 | + | |
| 17833 | 17905 | LL_FMT="" |
| 17834 | 17906 | oCFLAGS=$CFLAGS |
| 17835 | 17907 | CFLAGS="$WFLAGS $CFLAGS" | ... | ... |
configure.ac
| ... | ... | @@ -520,6 +520,35 @@ if test "$BUILDRULES" != "msvc"; then |
| 520 | 520 | fi |
| 521 | 521 | fi |
| 522 | 522 | |
| 523 | +AC_MSG_CHECKING(for tm_gmtoff in struct tm) | |
| 524 | +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ | |
| 525 | + #include <time.h> | |
| 526 | + ]],[[ | |
| 527 | + struct tm tm; | |
| 528 | + tm.tm_gmtoff = 1; | |
| 529 | + ]])], [qpdf_TM_GMTOFF=1], [qpdf_TM_GMTOFF=0]) | |
| 530 | +if test "$qpdf_TM_GMTOFF" = "1"; then | |
| 531 | + AC_MSG_RESULT(yes) | |
| 532 | + AC_DEFINE([HAVE_TM_GMTOFF], [1], [Whether struct tm has tm_gmtoff]) | |
| 533 | +else | |
| 534 | + AC_MSG_RESULT(no) | |
| 535 | +fi | |
| 536 | + | |
| 537 | +AC_MSG_CHECKING(for extern long timezone) | |
| 538 | +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ | |
| 539 | + #include <time.h> | |
| 540 | + #include <stdio.h> | |
| 541 | + ]],[[ | |
| 542 | + tzset(); | |
| 543 | + printf("%ld\n", timezone); | |
| 544 | + ]])], [qpdf_EXTERN_LONG_TIMEZONE=1], [qpdf_EXTERN_LONG_TIMEZONE=0]) | |
| 545 | +if test "$qpdf_EXTERN_LONG_TIMEZONE" = "1"; then | |
| 546 | + AC_MSG_RESULT(yes) | |
| 547 | + AC_DEFINE([HAVE_EXTERN_LONG_TIMEZONE], [1], [Whether extern long timezone is available]) | |
| 548 | +else | |
| 549 | + AC_MSG_RESULT(no) | |
| 550 | +fi | |
| 551 | + | |
| 523 | 552 | LL_FMT="" |
| 524 | 553 | oCFLAGS=$CFLAGS |
| 525 | 554 | CFLAGS="$WFLAGS $CFLAGS" | ... | ... |
libqpdf/QUtil.cc
| ... | ... | @@ -889,6 +889,7 @@ QUtil::get_current_qpdf_time() |
| 889 | 889 | static_cast<int>(ltime.wHour), |
| 890 | 890 | static_cast<int>(ltime.wMinute), |
| 891 | 891 | static_cast<int>(ltime.wSecond), |
| 892 | + // tzinfo.Bias is minutes before UTC | |
| 892 | 893 | static_cast<int>(tzinfo.Bias)); |
| 893 | 894 | #else |
| 894 | 895 | struct tm ltime; |
| ... | ... | @@ -899,13 +900,23 @@ QUtil::get_current_qpdf_time() |
| 899 | 900 | #else |
| 900 | 901 | ltime = *localtime(&now); |
| 901 | 902 | #endif |
| 903 | +#if HAVE_TM_GMTOFF | |
| 904 | + // tm_gmtoff is seconds after UTC | |
| 905 | + int tzoff = -static_cast<int>(ltime.tm_gmtoff / 60); | |
| 906 | +#elif HAVE_EXTERN_LONG_TIMEZONE | |
| 907 | + // timezone is seconds before UTC, not adjusted for daylight saving time | |
| 908 | + int tzoff = static_cast<int>(timezone / 60); | |
| 909 | +#else | |
| 910 | + // Don't know how to get timezone on this platform | |
| 911 | + int tzoff = 0; | |
| 912 | +#endif | |
| 902 | 913 | return QPDFTime(static_cast<int>(ltime.tm_year + 1900), |
| 903 | 914 | static_cast<int>(ltime.tm_mon + 1), |
| 904 | 915 | static_cast<int>(ltime.tm_mday), |
| 905 | 916 | static_cast<int>(ltime.tm_hour), |
| 906 | 917 | static_cast<int>(ltime.tm_min), |
| 907 | 918 | static_cast<int>(ltime.tm_sec), |
| 908 | - static_cast<int>(timezone / 60)); | |
| 919 | + tzoff); | |
| 909 | 920 | #endif |
| 910 | 921 | } |
| 911 | 922 | ... | ... |
libqpdf/qpdf/qpdf-config.h.in
| ... | ... | @@ -12,6 +12,9 @@ |
| 12 | 12 | /* Define to 1 if you have the <dlfcn.h> header file. */ |
| 13 | 13 | #undef HAVE_DLFCN_H |
| 14 | 14 | |
| 15 | +/* Whether extern long timezone is available */ | |
| 16 | +#undef HAVE_EXTERN_LONG_TIMEZONE | |
| 17 | + | |
| 15 | 18 | /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ |
| 16 | 19 | #undef HAVE_FSEEKO |
| 17 | 20 | |
| ... | ... | @@ -51,6 +54,9 @@ |
| 51 | 54 | /* Define to 1 if you have the <sys/types.h> header file. */ |
| 52 | 55 | #undef HAVE_SYS_TYPES_H |
| 53 | 56 | |
| 57 | +/* Whether struct tm has tm_gmtoff */ | |
| 58 | +#undef HAVE_TM_GMTOFF | |
| 59 | + | |
| 54 | 60 | /* Define to 1 if you have the <unistd.h> header file. */ |
| 55 | 61 | #undef HAVE_UNISTD_H |
| 56 | 62 | ... | ... |