Commit 36c7c208191a0fd34cf48bdfb4af66b4ab0ec594

Authored by Jay Berkenbilt
1 parent 8971443e

Fix timezone portability issue (fixes #515)

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 &quot;no&quot; &gt;&amp;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 &quot;$BUILDRULES&quot; != &quot;msvc&quot;; 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  
... ...