aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2025-08-21 19:21:17 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2025-08-21 19:21:17 +0000
commit76d3e9d6b36023210e896d00ecef2d19f0acd2d8 (patch)
tree653fb2a62166f99708ff6803cfaece34abe939ac
parentcc325dd8c469265cf9c40616c8087b0ee98a6005 (diff)
-rw-r--r--NEWS29
-rw-r--r--tz-link.html8
-rw-r--r--version2
-rw-r--r--zic.c79
4 files changed, 91 insertions, 27 deletions
diff --git a/NEWS b/NEWS
index a5d7ea89204e..8c0771641ef0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,15 +1,40 @@
News for the tz database
+Release 2025b - 2025-03-22 13:40:46 -0700
+
+ Briefly:
+ New zone for Aysén Region in Chile which moves from -04/-03 to -03.
+
+ Changes to future timestamps
+
+ Chile's Aysén Region moves from -04/-03 to -03 year-round, joining
+ Magallanes Region. The region will not change its clocks on
+ 2025-04-05 at 24:00, diverging from America/Santiago and creating a
+ new zone America/Coyhaique. (Thanks to Yonathan Dossow.) Model
+ this as a change to standard offset effective 2025-03-20.
+
+ Changes to past timestamps
+
+ Iran switched from +04 to +0330 on 1978-11-10 at 24:00, not at
+ year end. (Thanks to Roozbeh Pournader.)
+
+ Changes to code
+
+ 'zic -l TIMEZONE -d . -l /some/other/file/system' no longer
+ attempts to create an incorrect symlink, and no longer has a
+ read buffer underflow. (Problem reported by Evgeniy Gorbanev.)
+
+
Release 2025a - 2025-01-15 10:47:24 -0800
Briefly:
- Paraguay adopts permanent -03 starting spring 2024.
+ Paraguay adopted permanent -03 starting spring 2024.
Improve pre-1991 data for the Philippines.
Etc/Unknown is now reserved.
Changes to future timestamps
- Paraguay will stop changing its clocks after the spring-forward
+ Paraguay stopped changing its clocks after the spring-forward
transition on 2024-10-06, so it is now permanently at -03.
(Thanks to Heitor David Pinto and Even Scharning.)
This affects timestamps starting 2025-03-22, as well as the
diff --git a/tz-link.html b/tz-link.html
index f4f76fdd67e1..ad2cc972a4f9 100644
--- a/tz-link.html
+++ b/tz-link.html
@@ -985,6 +985,14 @@ a Sleep Research Society position statement</a>.
doi:<a href="https://doi.org/10.1093/sleep/zsac236">10.1093/sleep/zsac236</a>.
After reviewing the scientific literature, the Sleep Research Society
advocates permanent standard time due to its health benefits.
+<li>Neumann P, von Blanckenburg K. <a
+href="https://journals.sagepub.com/doi/full/10.1177/0961463X241310562">What
+time will it be? A comprehensive literature review on daylight saving time</a>.
+<em>Time Soc</em>. 2025-01-21.
+doi:<a href="https://doi.org/10.1177/0961463X241310562">10.1177/0961463X241310562</a>.
+This reviews DST's effects on electricity, health, crime, road safety,
+and the economy, focusing on research since 2010, and concludes that
+year-round standard time is preferable overall.
<li>Rishi MA, Cheng JY, Strang AR <em>et al</em>.
<a href="https://jcsm.aasm.org/doi/10.5664/jcsm.10898">Permanent standard time
is the optimal choice for health and safety:
diff --git a/version b/version
index 0846b7f265fa..ef468adcecf9 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-2025a
+2025b
diff --git a/zic.c b/zic.c
index 8a7f83dbb0f4..ef96efe79142 100644
--- a/zic.c
+++ b/zic.c
@@ -652,6 +652,8 @@ close_file(FILE *stream, char const *dir, char const *name,
char const *e = (ferror(stream) ? _("I/O error")
: fclose(stream) != 0 ? strerror(errno) : NULL);
if (e) {
+ if (name && *name == '/')
+ dir = NULL;
fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
dir ? dir : "", dir ? "/" : "",
name ? name : "", name ? ": " : "",
@@ -953,6 +955,9 @@ static const char * lcltime;
static const char * directory;
static const char * tzdefault;
+/* True if DIRECTORY ends in '/'. */
+static bool directory_ends_in_slash;
+
/* -1 if the TZif output file should be slim, 0 if default, 1 if the
output should be fat for backward compatibility. ZIC_BLOAT_DEFAULT
determines the default. */
@@ -1137,6 +1142,7 @@ main(int argc, char **argv)
return EXIT_FAILURE;
associate();
change_directory(directory);
+ directory_ends_in_slash = directory[strlen(directory) - 1] == '/';
catch_signals();
for (i = 0; i < nzones; i = j) {
/*
@@ -1338,6 +1344,20 @@ random_dirent(char const **name, char **namealloc)
}
}
+/* For diagnostics the directory, and file name relative to that
+ directory, respectively. A diagnostic routine can name FILENAME by
+ outputting diagdir(FILENAME), then diagslash(FILENAME), then FILENAME. */
+static char const *
+diagdir(char const *filename)
+{
+ return *filename == '/' ? "" : directory;
+}
+static char const *
+diagslash(char const *filename)
+{
+ return &"/"[*filename == '/' || directory_ends_in_slash];
+}
+
/* Prepare to write to the file *OUTNAME, using *TEMPNAME to store the
name of the temporary file that will eventually be renamed to
*OUTNAME. Assign the temporary file's name to both *OUTNAME and
@@ -1366,8 +1386,9 @@ open_outfile(char const **outname, char **tempname)
} else if (fopen_errno == EEXIST)
random_dirent(outname, tempname);
else {
- fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
- progname, directory, *outname, strerror(fopen_errno));
+ fprintf(stderr, _("%s: Can't create %s%s%s: %s\n"),
+ progname, diagdir(*outname), diagslash(*outname), *outname,
+ strerror(fopen_errno));
exit(EXIT_FAILURE);
}
}
@@ -1385,8 +1406,9 @@ rename_dest(char *tempname, char const *name)
if (rename(tempname, name) != 0) {
int rename_errno = errno;
remove(tempname);
- fprintf(stderr, _("%s: rename to %s/%s: %s\n"),
- progname, directory, name, strerror(rename_errno));
+ fprintf(stderr, _("%s: rename to %s%s%s: %s\n"),
+ progname, diagdir(name), diagslash(name), name,
+ strerror(rename_errno));
exit(EXIT_FAILURE);
}
free(tempname);
@@ -1396,7 +1418,8 @@ rename_dest(char *tempname, char const *name)
/* Create symlink contents suitable for symlinking TARGET to LINKNAME, as a
freshly allocated string. TARGET should be a relative file name, and
is relative to the global variable DIRECTORY. LINKNAME can be either
- relative or absolute. */
+ relative or absolute. Return a null pointer if the symlink contents
+ was not computed because LINKNAME is absolute but DIRECTORY is not. */
static char *
relname(char const *target, char const *linkname)
{
@@ -1409,6 +1432,8 @@ relname(char const *target, char const *linkname)
size_t len = strlen(directory);
size_t lenslash = len + (len && directory[len - 1] != '/');
size_t targetsize = strlen(target) + 1;
+ if (*directory != '/')
+ return NULL;
linksize = size_sum(lenslash, targetsize);
f = result = xmalloc(linksize);
memcpy(result, directory, len);
@@ -1460,8 +1485,9 @@ dolink(char const *target, char const *linkname, bool staysymlink)
return;
else {
char const *e = strerror(errno);
- fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
- progname, directory, linkname, e);
+ fprintf(stderr, _("%s: Can't remove %s%s%s: %s\n"),
+ progname, diagdir(linkname), diagslash(linkname), linkname,
+ e);
exit(EXIT_FAILURE);
}
}
@@ -1504,8 +1530,9 @@ dolink(char const *target, char const *linkname, bool staysymlink)
mkdirs(linkname, true);
linkdirs_made = true;
} else {
- fprintf(stderr, _("%s: Can't link %s/%s to %s/%s: %s\n"),
- progname, directory, target, directory, outname,
+ fprintf(stderr, _("%s: Can't link %s%s%s to %s%s%s: %s\n"),
+ progname, diagdir(target), diagslash(target), target,
+ diagdir(outname), diagslash(outname), outname,
strerror(link_errno));
exit(EXIT_FAILURE);
}
@@ -1514,21 +1541,23 @@ dolink(char const *target, char const *linkname, bool staysymlink)
bool absolute = *target == '/';
char *linkalloc = absolute ? NULL : relname(target, linkname);
char const *contents = absolute ? target : linkalloc;
- int symlink_errno;
+ int symlink_errno = -1;
- while (true) {
- if (symlink(contents, outname) == 0) {
- symlink_errno = 0;
- break;
+ if (contents) {
+ while (true) {
+ if (symlink(contents, outname) == 0) {
+ symlink_errno = 0;
+ break;
+ }
+ symlink_errno = errno;
+ if (symlink_errno == EEXIST)
+ random_dirent(&outname, &tempname);
+ else if (symlink_errno == ENOENT && !linkdirs_made) {
+ mkdirs(linkname, true);
+ linkdirs_made = true;
+ } else
+ break;
}
- symlink_errno = errno;
- if (symlink_errno == EEXIST)
- random_dirent(&outname, &tempname);
- else if (symlink_errno == ENOENT && !linkdirs_made) {
- mkdirs(linkname, true);
- linkdirs_made = true;
- } else
- break;
}
free(linkalloc);
if (symlink_errno == 0) {
@@ -1541,8 +1570,8 @@ dolink(char const *target, char const *linkname, bool staysymlink)
fp = fopen(target, "rb");
if (!fp) {
char const *e = strerror(errno);
- fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
- progname, directory, target, e);
+ fprintf(stderr, _("%s: Can't read %s%s%s: %s\n"),
+ progname, diagdir(target), diagslash(target), target, e);
exit(EXIT_FAILURE);
}
tp = open_outfile(&outname, &tempname);
@@ -1553,6 +1582,8 @@ dolink(char const *target, char const *linkname, bool staysymlink)
if (link_errno != ENOTSUP)
warning(_("copy used because hard link failed: %s"),
strerror(link_errno));
+ else if (symlink_errno < 0)
+ warning(_("copy used because symbolic link not obvious"));
else if (symlink_errno != ENOTSUP)
warning(_("copy used because symbolic link failed: %s"),
strerror(symlink_errno));