aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-04-18 00:12:55 +0200
committerJay Berkenbilt <ejb@ql.org>2021-04-18 00:12:55 +0200
commit36c7c208191a0fd34cf48bdfb4af66b4ab0ec594 (patch)
treeb9a0afe891c01222e1c844e1d3bb0b85fc724f12
parent8971443e4680fc1c0babe56da58cc9070a9dae2e (diff)
downloadqpdf-36c7c208191a0fd34cf48bdfb4af66b4ab0ec594.tar.zst
Fix timezone portability issue (fixes #515)
-rw-r--r--ChangeLog7
-rw-r--r--autofiles.sums4
-rwxr-xr-xconfigure72
-rw-r--r--configure.ac29
-rw-r--r--libqpdf/QUtil.cc13
-rw-r--r--libqpdf/qpdf/qpdf-config.h.in6
6 files changed, 128 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index f720fa24..8b2f6867 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
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 <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"
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 <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"
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<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;
@@ -899,13 +900,23 @@ QUtil::get_current_qpdf_time()
#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),
static_cast<int>(ltime.tm_mday),
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
}
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 <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