[tz] [PROPOSED] Fix bug with 'zic -d /a/b/c' if /a is unwriteable

Paul Eggert eggert at cs.ucla.edu
Fri Aug 12 07:30:35 UTC 2022


If the directory /a/b already exists, it is not an error if /a is
unwritable when you invoke zic -d /a/b/c.  Problem found on
Solaris 10, where mkdir("/a", ...) can fail with EACCES in this
situation, which POSIX allows.
* NEWS: Mention the fix.
* private.h (ELOOP) [!ELOOP]: Define to EINVAL.
* zic.c (mkdirs): Do not fail merely because mkdir fails
with errno == EACCES, as the parent directory may already
exist but be unwritable.  For example
---
 NEWS      | 2 ++
 private.h | 3 +++
 zic.c     | 9 +++++++--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 7291030a..af99e2b7 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ Unreleased, experimental changes
     Work around a bug in macOS 'awk' that broke commands like 'make
     traditional_tarballs'.  (Problem reported by Deborah Goldsmith.)
 
+    Fix bug with 'zic -d /a/b/c' when /a is unwritable but the
+    directory /a/b already exists.
 
 Release 2022b - 2022-08-10 15:38:32 -0700
 
diff --git a/private.h b/private.h
index 9b9389f3..9c31ec54 100644
--- a/private.h
+++ b/private.h
@@ -168,6 +168,9 @@
 # define EINVAL ERANGE
 #endif
 
+#ifndef ELOOP
+# define ELOOP EINVAL
+#endif
 #ifndef ENAMETOOLONG
 # define ENAMETOOLONG EINVAL
 #endif
diff --git a/zic.c b/zic.c
index a29f6792..ff047937 100644
--- a/zic.c
+++ b/zic.c
@@ -3670,9 +3670,14 @@ mkdirs(char const *argname, bool ancestors)
 			   some other process might have made the directory
 			   in the meantime.  Likewise for ENOSYS, because
 			   Solaris 10 mkdir fails with ENOSYS if the
-			   directory is an automounted mount point.  */
+			   directory is an automounted mount point.
+			   Likewise for EACCES, since mkdir can fail
+			   with EACCES merely because the parent directory
+			   is unwritable.  Likewise for most other error
+			   numbers.  */
 			int err = errno;
-			if (err != EEXIST && err != ENOSYS) {
+			if (err == ELOOP || err == ENAMETOOLONG
+			    || err == ENOENT || err == ENOTDIR) {
 				error(_("%s: Can't create directory %s: %s"),
 				      progname, name, strerror(err));
 				exit(EXIT_FAILURE);
-- 
2.34.1



More information about the tz mailing list