This refactoring removes a hidden extern and shrinks static state a bit.
* time/tzfile.c (__use_tzfile): Remove static var. All uses removed.
(__tzfile_read): Use (tzfile_mtime != 0) instead of __use_tzfile.
Return bool. Caller changed.
* time/tzset.c (tzset_internal): Accept and return bool.
All callers changed. Use old_tz instead of is_initialized to test
whether we are initialized, removing the need for the is_initialized
static. New static use_tzfile instead, which means what the old
__use_tzfile meant.
---
time/tzfile.c | 23 +++++-----
time/tzset.c | 117 +++++++++++++++++++++++++-------------------------
time/tzset.h | 4 +-
3 files changed, 69 insertions(+), 75 deletions(-)
@@ -33,7 +33,6 @@
#include <timezone/tzfile.h>
-bool __use_tzfile;
static dev_t tzfile_dev;
static ino64_t tzfile_ino;
static __time64_t tzfile_mtime;
@@ -138,7 +137,7 @@ decode64 (const void *ptr)
}
-void
+bool
__tzfile_read (const char *file)
{
static const char default_tzdir[] = TZDIR;
@@ -147,15 +146,12 @@ __tzfile_read (const char *file)
union { struct tzhead tzhead; tzidx tzidx_aligned; } u;
tzidx charcnt;
tzidx i;
- bool was_using_tzfile = __use_tzfile;
int trans_width = 4;
char *new = NULL;
_Static_assert (sizeof (__time64_t) == 8,
"__time64_t must be eight bytes");
- __use_tzfile = false;
-
/* We must not allow to read an arbitrary file in a setuid
program. So we fail for any file which is not in the
directory hierarchy starting at TZDIR
@@ -187,7 +183,7 @@ __tzfile_read (const char *file)
/* If we were already using tzfile, check whether the file changed. */
struct __stat64_t64 st;
- if (was_using_tzfile
+ if (tzfile_mtime != 0
&& __stat64_time64 (file, &st) == 0
&& tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
&& tzfile_mtime == st.st_mtime)
@@ -207,11 +203,6 @@ __tzfile_read (const char *file)
free (transitions);
transitions = NULL;
- /* Remember the inode and device number and modification time. */
- tzfile_dev = st.st_dev;
- tzfile_ino = st.st_ino;
- tzfile_mtime = st.st_mtime;
-
/* No threads reading this stream. */
__fsetlocking (f, FSETLOCKING_BYCALLER);
@@ -565,10 +556,14 @@ __tzfile_read (const char *file)
__daylight = daylight_saved;
__timezone = -rule_stdoff;
+ /* Remember the inode and device number and modification time. */
+ tzfile_dev = st.st_dev;
+ tzfile_ino = st.st_ino;
+ tzfile_mtime = st.st_mtime;
+
done:
free (new);
- __use_tzfile = true;
- return;
+ return true;
lose:
fclose (f);
@@ -576,6 +571,8 @@ __tzfile_read (const char *file)
free (new);
free (transitions);
transitions = NULL;
+ tzfile_mtime = 0;
+ return false;
}
void
@@ -65,7 +65,6 @@ static tz_rule tz_rules[2];
static void compute_change (tz_rule *rule, long long int year) __THROW;
-static void tzset_internal (int always);
/* List of buffers containing time zone strings. */
struct tzstring_l
@@ -379,66 +378,67 @@ __tzset_parse_tz (const char *tz)
return ok;
}
-/* Interpret the TZ envariable. */
-static void
-tzset_internal (int always)
+/* Interpret the TZ envariable. If ALWAYS, always do so; otherwise do
+ so only if TZ has changed. Return true if TZ stands for a TZif file. */
+static bool
+tzset_internal (bool always)
{
- static int is_initialized;
- const char *tz;
-
- if (is_initialized && !always)
- return;
- is_initialized = 1;
-
- /* Examine the TZ environment variable. */
- tz = getenv ("TZ");
-
- if (tz == NULL)
- /* No user specification; use the site-wide default. */
- tz = TZDEFAULT;
-
- /* A leading colon means "implementation defined syntax".
- We ignore the colon and always use the same algorithm:
- try a data file, and if none exists parse the 1003.1 syntax. */
- if (*tz == ':')
- ++tz;
-
- /* Check whether the value changed since the last run. */
- if (old_tz != NULL && strcmp (tz, old_tz) == 0)
- {
- /* No change, simply update external vars. */
- update_vars ();
- return;
- }
-
- /* Save the value of `tz'. */
- free (old_tz);
- old_tz = __strdup (tz);
+ static bool use_tzfile;
- /* Try to read a data file. */
- __tzfile_read (tz);
- if (__use_tzfile)
+ if (old_tz == NULL || always)
{
- /* Save equivalent of 'daylight' for later use by update_vars.
- Although the other external variables have unspecified values
- and so need not be saved in the usual case, save them anyway,
- as POSIX requires this for the rare case of file-backed proleptic
- TZ strings like "EST5EDT", and it is more likely to match user
- expectations for geographical TZ strings. */
- enum tz_rule_type some_DST = J0; /* anything but NO_DST */
- tz_rules[1].type = NO_DST + __daylight * (some_DST - NO_DST);
- tz_rules[0].offset = -__timezone;
- tz_rules[0].name = __tzname[0];
- tz_rules[1].name = __tzname[1];
- return;
+ /* Examine the TZ environment variable. */
+ char const *tz = getenv ("TZ");
+
+ if (tz == NULL)
+ /* No user specification; use the site-wide default. */
+ tz = TZDEFAULT;
+
+ /* A leading colon means "implementation defined syntax".
+ We ignore the colon and always use the same algorithm:
+ try a data file, and if none exists parse the 1003.1 syntax. */
+ if (*tz == ':')
+ ++tz;
+
+ /* If the value changed has not since the last run,
+ simply update internal vars. */
+ if (old_tz != NULL && strcmp (tz, old_tz) == 0)
+ update_vars ();
+ else
+ {
+ /* Save the value of 'tz'. */
+ free (old_tz);
+ old_tz = __strdup (tz);
+
+ /* Try to read a data file. */
+ use_tzfile = __tzfile_read (tz);
+ if (use_tzfile)
+ {
+ /* Save equivalent of 'daylight' for later use by update_vars.
+ Although the other external variables have unspecified values
+ and so need not be saved in the usual case, save them anyway,
+ as POSIX requires this for rare file-backed proleptic
+ TZ strings like "EST5EDT", and it is more likely to match user
+ expectations for geographical TZ strings. */
+ enum tz_rule_type some_DST = J0; /* anything but NO_DST */
+ tz_rules[1].type = NO_DST + __daylight * (some_DST - NO_DST);
+ tz_rules[0].offset = -__timezone;
+ tz_rules[0].name = __tzname[0];
+ tz_rules[1].name = __tzname[1];
+ }
+ else
+ {
+ /* No data file found. Default to UTC without leap seconds if
+ TZDEFAULT is broken. */
+ if (strcmp (tz, TZDEFAULT) == 0)
+ tz = "";
+
+ __tzset_parse_tz (tz);
+ }
+ }
}
- /* No data file found. Default to UTC without leap seconds if
- TZDEFAULT is broken. */
- if (strcmp (tz, TZDEFAULT) == 0)
- tz = "";
-
- __tzset_parse_tz (tz);
+ return use_tzfile;
}
/* Figure out the exact time (as a __time64_t) in YEAR
@@ -558,7 +558,7 @@ __tz_compute (__time64_t timer, struct tm *tm)
void
__tzset_unlocked (void)
{
- tzset_internal (1);
+ tzset_internal (true);
}
void
@@ -587,9 +587,8 @@ __tz_convert (__time64_t timer, int use_localtime, struct tm *tp)
/* Update internal database according to current TZ setting.
POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
This is a good idea since this allows at least a bit more parallelism. */
- tzset_internal (tp == &_tmbuf && use_localtime);
- if (__use_tzfile)
+ if (tzset_internal (tp == &_tmbuf && use_localtime))
__tzfile_compute (timer, use_localtime, &leap_correction,
&leap_extra_sec, tp);
else
@@ -8,9 +8,7 @@
/* Defined in tzset.c. */
extern char *__tzstring (const char *string) attribute_hidden;
-extern bool __use_tzfile attribute_hidden;
-
-extern void __tzfile_read (const char *file) attribute_hidden;
+extern bool __tzfile_read (const char *file) attribute_hidden;
extern void __tzfile_compute (__time64_t timer, int use_localtime,
int *leap_correct, bool *leap_hit,
struct tm *tp) attribute_hidden;