summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-08-18 17:22:00 +0200
committerThomas Haller <thaller@redhat.com>2023-08-21 08:53:43 +0200
commit471188abdb9b2ed15bcea512bc50f12e5cea3505 (patch)
treec3b84575ede65268054709cd6f51fef8e342f3f4
parent5ffc23605c0708759054ee4ef7e7178cf51ce229 (diff)
downloadglib-471188abdb9b2ed15bcea512bc50f12e5cea3505.tar.gz
gdate: add internal helper function _g_localtime() for localtime()/localtime_r()
The point of to be able to call localtime()/localtime_r() from another place inside glib (without reimplementing the #ifdef). - also handles failures from localtime_r(). It is documented that it might fail, so detect the failure. - in case of failures of localtime(), still initialize the GDate. Previously, we may error out with a g_critical() assertion before. However, now that failures from localtime_r() are also caught, I think we should make an effort to initialize the GDate to something. It either way it not supposed to happen.
-rw-r--r--glib/gdate.c69
-rw-r--r--glib/gutilsprivate.h4
2 files changed, 49 insertions, 24 deletions
diff --git a/glib/gdate.c b/glib/gdate.c
index 85892ec9b..f60ec0cbf 100644
--- a/glib/gdate.c
+++ b/glib/gdate.c
@@ -53,6 +53,7 @@
#include "gtestutils.h"
#include "gthread.h"
#include "gunicode.h"
+#include "gutilsprivate.h"
#ifdef G_OS_WIN32
#include "garray.h"
@@ -1403,6 +1404,33 @@ g_date_set_parse (GDate *d,
G_UNLOCK (g_date_global);
}
+gboolean
+_g_localtime (time_t timet, struct tm *out_tm)
+{
+ gboolean success = TRUE;
+
+#ifdef HAVE_LOCALTIME_R
+ if (!localtime_r (&timet, out_tm))
+ success = FALSE;
+#else
+ {
+ struct tm *ptm = localtime (&timet);
+
+ if (ptm == NULL)
+ {
+ /* Happens at least in Microsoft's C library if you pass a
+ * negative time_t.
+ */
+ success = FALSE;
+ }
+ else
+ memcpy (out_tm, ptm, sizeof (struct tm));
+ }
+#endif
+
+ return success;
+}
+
/**
* g_date_set_time_t:
* @date: a #GDate
@@ -1427,33 +1455,21 @@ g_date_set_time_t (GDate *date,
time_t timet)
{
struct tm tm;
-
+ gboolean success;
+
g_return_if_fail (date != NULL);
-
-#ifdef HAVE_LOCALTIME_R
- localtime_r (&timet, &tm);
-#else
- {
- struct tm *ptm = localtime (&timet);
- if (ptm == NULL)
- {
- /* Happens at least in Microsoft's C library if you pass a
- * negative time_t. Use 2000-01-01 as default date.
- */
-#ifndef G_DISABLE_CHECKS
- g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "ptm != NULL");
-#endif
+ success = _g_localtime (timet, &tm);
+ if (!success)
+ {
+ /* Still set a default date, 2000-01-01.
+ *
+ * We may assert out below. */
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_year = 100;
+ }
- tm.tm_mon = 0;
- tm.tm_mday = 1;
- tm.tm_year = 100;
- }
- else
- memcpy ((void *) &tm, (void *) ptm, sizeof(struct tm));
- }
-#endif
-
date->julian = FALSE;
date->month = tm.tm_mon + 1;
@@ -1463,6 +1479,11 @@ g_date_set_time_t (GDate *date,
g_return_if_fail (g_date_valid_dmy (date->day, date->month, date->year));
date->dmy = TRUE;
+
+#ifndef G_DISABLE_CHECKS
+ if (!success)
+ g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "localtime() == NULL");
+#endif
}
diff --git a/glib/gutilsprivate.h b/glib/gutilsprivate.h
index 24c199305..b4f1b984a 100644
--- a/glib/gutilsprivate.h
+++ b/glib/gutilsprivate.h
@@ -26,6 +26,8 @@
#include "gtypes.h"
#include "gtestutils.h"
+#include <time.h>
+
G_BEGIN_DECLS
void g_set_user_dirs (const gchar *first_dir_type,
@@ -55,6 +57,8 @@ g_nearest_pow (gsize num)
void _g_unset_cached_tmp_dir (void);
+gboolean _g_localtime (time_t timet, struct tm *tm);
+
G_END_DECLS
#endif /* __G_UTILS_PRIVATE_H__ */