On 2025-10-20 05:00, Manuela Friedrich wrote:
After removing -DHAVE_POSIX_DECLS=0 we got these failures
Instead of removing -DHAVE_POSIX_DECLS=0, please add -DHAVE_DIRECT_H;
this should fix the mkdir part of the problem.
Also, I just now installed the attached patch to address the umask part
of the problem; please give it a try.
Thanks for following up on this.
From 8d65db9786753f3b263087e31c59d191561d63e3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Mon, 20 Oct 2025 09:11:01 -0700
Subject: [PROPOSED] Prefer fdopen to umask in zic
Improve zic by using fdopen instead of umask to create TZif files
with permissions other than the default 0666-modified-by-umask.
Because tzcode predates POSIX.1-1988 (which standardized fdopen)
it used the umask trick instead of fdopen.
However, as demonstrated by Manuela Friedrich in:
https://lists.iana.org/hyperkitty/list/[email protected]/thread/2ASUTQ6MXJJFXDYQPWHWA2SN2E2HOWZX/
and followups, the umask trick is a hassle to port to MS-Windows.
The umask trick also makes it harder to add a reliable -m option
in the style of FreeBSD, whose zic -m has subtle bugs
due to its use of umask.
* NEWS: Mention this.
* zic.c (O_BINARY): Default to 0, as in localtime.c.
(umask): Remove macro and/or decl; no longer used.
(S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH)
(S_IWOTH, S_IXOTH, S_IRWXU, S_IRWXG, S_IRWXO):
Default to POSIX.1-2008+ values; this is cleaner than
using octal numbers everywhere else.
All uses of octal numbers changed.
(CREAT_PERMS): New macro.
(main): Do not call umask.
(open_outfile): Use fdopen with CREAT_MASK rather than relying
on umask. This avoids problems with umask on MS-Windows,
and likely simplifies future improvements.
---
NEWS | 5 ++++
zic.c | 76 +++++++++++++++++++++++++++++++++--------------------------
2 files changed, 47 insertions(+), 34 deletions(-)
diff --git a/NEWS b/NEWS
index 46bf48ed..8253cfb6 100644
--- a/NEWS
+++ b/NEWS
@@ -102,6 +102,11 @@ Unreleased, experimental changes
exceedingly long TZ strings no longer fail merely because they
exceed an arbitrary file name length limit imposed by tzcode.
+ zic now uses the fdopen function, which was standardized by
+ POSIX.1-1988 and is now safe to use in portable code.
+ This replaces its use of the older umask function, which
+ complicated maintenance.
+
Changes to commentary
The leapseconds file contains commentary about the IERS and NIST
diff --git a/zic.c b/zic.c
index b1923438..67bcaa43 100644
--- a/zic.c
+++ b/zic.c
@@ -18,6 +18,10 @@
#include "tzfile.h"
#include <fcntl.h>
+#ifndef O_BINARY
+# define O_BINARY 0 /* MS-Windows */
+#endif
+
#include <locale.h>
#include <signal.h>
#include <stdarg.h>
@@ -50,9 +54,6 @@ enum { FORMAT_LEN_GROWTH_BOUND = 5 };
# ifndef mkdir
# define mkdir(name, mode) _mkdir(name)
# endif
-# ifndef umask
-# define umask(mode) _umask(mode)
-# endif
#endif
#ifndef HAVE_GETRANDOM
@@ -73,23 +74,35 @@ enum { FORMAT_LEN_GROWTH_BOUND = 5 };
# include <sys/stat.h>
#endif
-#ifdef S_IRWXU
+#ifndef S_IRWXU
+# define S_IRUSR 0400
+# define S_IWUSR 0200
+# define S_IXUSR 0100
+# define S_IRGRP 0040
+# define S_IWGRP 0020
+# define S_IXGRP 0010
+# define S_IROTH 0004
+# define S_IWOTH 0002
+# define S_IXOTH 0001
+# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#endif
+
/* All file permission bits. */
-# define ALL_PERMS (S_IRWXU | S_IRWXG | S_IRWXO)
+#define ALL_PERMS (S_IRWXU | S_IRWXG | S_IRWXO)
/* Troublesome file permission bits. */
-# define TROUBLE_PERMS (S_IWGRP | S_IWOTH)
-#else
-# define ALL_PERMS 0777
-# define TROUBLE_PERMS 0022
-#endif
+#define TROUBLE_PERMS (S_IWGRP | S_IWOTH)
/* File permission bits for making directories.
- The initial umask modifies these bits.
- Although the "& ~TROUBLE_PERMS" is redundant because we remove
- TROUBLE_PERMS from the umask early on, the redundancy does not hurt. */
+ The umask modifies these bits. */
#define MKDIR_PERMS (ALL_PERMS & ~TROUBLE_PERMS)
+/* File permission bits for making regular files.
+ The umask modifies these bits. */
+#define CREAT_PERMS (MKDIR_PERMS & ~(S_IXUSR | S_IXGRP | S_IXOTH))
+
/* The minimum alignment of a type, for pre-C23 platforms.
The __SUNPRO_C test is because Oracle Developer Studio 12.6 lacks
@@ -172,9 +185,6 @@ extern int link(const char * target, const char * linkname);
# ifndef mkdir
extern int mkdir(char const *, mode_t);
# endif
-# ifndef umask
-extern mode_t umask(mode_t);
-# endif
extern char * optarg;
extern int optind;
#endif
@@ -1014,10 +1024,6 @@ main(int argc, char **argv)
register ptrdiff_t i, j;
bool timerange_given = false;
- /* Adjust umask so that created files lack troublesome permission bits.
- Needed because regular files are created via fopen not openat. */
- umask(umask(TROUBLE_PERMS) | TROUBLE_PERMS);
-
#if HAVE_GETTEXT
setlocale(LC_ALL, "");
# ifdef TZ_DOMAINDIR
@@ -1401,33 +1407,35 @@ diagslash(char const *filename)
static FILE *
open_outfile(char const **outname, char **tempname)
{
-#if __STDC_VERSION__ < 201112
- static char const fopen_mode[] = "wb";
-#else
- static char const fopen_mode[] = "wbx";
-#endif
-
- FILE *fp;
bool dirs_made = false;
if (!*tempname)
random_dirent(outname, tempname);
- while (! (fp = fopen(*outname, fopen_mode))) {
- int fopen_errno = errno;
- if (fopen_errno == ENOENT && !dirs_made) {
+ while (true) {
+ int oflags = O_WRONLY | O_BINARY | O_CREAT | O_EXCL;
+ int fd = open(*outname, oflags, CREAT_PERMS);
+ int err;
+ if (fd < 0)
+ err = errno;
+ else {
+ FILE *fp = fdopen(fd, "wb");
+ if (fp)
+ return fp;
+ err = errno;
+ close(fd);
+ }
+ if (err == ENOENT && !dirs_made) {
mkdirs(*outname, true);
dirs_made = true;
- } else if (fopen_errno == EEXIST)
+ } else if (err == EEXIST)
random_dirent(outname, tempname);
else {
fprintf(stderr, _("%s: Can't create %s%s%s: %s\n"),
progname, diagdir(*outname), diagslash(*outname), *outname,
- strerror(fopen_errno));
+ strerror(err));
exit(EXIT_FAILURE);
}
}
-
- return fp;
}
/* If TEMPNAME, the result is in the temporary file TEMPNAME even
--
2.51.0