bug#79072: install -d onto readonly fs prints the wrong error

Paul Eggert <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs,gmane.comp.lib.gnulib.bugs
Organization UCLA Computer Science Department
Message-ID <[email protected]>
Thanks for reporting that inaccurate diagnostic. Sorry about the tricky 
code; it's a tricky situation. Looks like Collin's patch is not quite right.

I installed the attached patches into Gnulib. The first one fixes the 
two cases you mentioned, the second an unlikely bug I discovered in the 
neighborhood. Please give the patches a try. As they fix the bugs for me 
I am boldly closing the Coreutils bug report; we can reopen it if I'm wrong.
0001-mkdir-p-better-diagnostics.patch (text/x-patch, 2.2 KB)
From 27db579667399d9f2cae2552a6f9185ffd10ab23 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Tue, 22 Jul 2025 12:09:28 -0700
Subject: [PATCH 1/2] mkdir-p: better diagnostics
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported by Lauri Tirkkonen <https://bugs.gnu.org/79072>.
* lib/mkdir-p.c (make_dir_parents):
If savewd_chdir fails due to anything other than EACCES, do
not attempt to preserve permissions; instead, fail with mkdir’s
errno if nonzero, and with savewd_chdir’s errno otherwise.
---
 ChangeLog     | 9 +++++++++
 lib/mkdir-p.c | 9 ++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 99ca126183..4841447b88 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2025-07-22  Paul Eggert  <[email protected]>
+
+	mkdir-p: better diagnostics
+	Problem reported by Lauri Tirkkonen <https://bugs.gnu.org/79072>.
+	* lib/mkdir-p.c (make_dir_parents):
+	If savewd_chdir fails due to anything other than EACCES, do
+	not attempt to preserve permissions; instead, fail with mkdir’s
+	errno if nonzero, and with savewd_chdir’s errno otherwise.
+
 2025-07-21  Collin Funk  <[email protected]>
 
 	sys_un-h: Make sure that the 'sys' subdirectory is created.
diff --git a/lib/mkdir-p.c b/lib/mkdir-p.c
index f5df9843e4..fffa58b4eb 100644
--- a/lib/mkdir-p.c
+++ b/lib/mkdir-p.c
@@ -172,7 +172,7 @@ make_dir_parents (char *dir,
                               savewd_chdir_options, open_result);
               if (chdir_result < -1)
                 return true;
-              else
+              else if (chdir_result == 0 || errno == EACCES)
                 {
                   bool chdir_ok = (chdir_result == 0);
                   char const *subdir = (chdir_ok ? "." : dir + prefix_len);
@@ -193,6 +193,13 @@ make_dir_parents (char *dir,
                       return false;
                     }
                 }
+              else
+                {
+                  if (mkdir_errno == 0)
+                    mkdir_errno = errno;
+                  if (0 <= open_result[0])
+                    close (open_result[0]);
+                }
             }
         }
     }
-- 
2.48.1
0002-mkdir-p-ENOENT-ENOTDIR-safety-and-consistency.patch (text/x-patch, 2.1 KB)
From 84ddfc7bd29853ed91cdd65c7ce818072959f974 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Tue, 22 Jul 2025 12:12:22 -0700
Subject: [PATCH 2/2] mkdir-p: ENOENT/ENOTDIR safety and consistency

* lib/mkdir-p.c (make_dir_parents): If mkdir fails with ENOENT or
ENOTDIR, do not attempt anything else since the file does not exist.
Treat ENOENT and ENOTDIR consistently later, too.
---
 ChangeLog     | 5 +++++
 lib/mkdir-p.c | 9 +++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4841447b88..ac20d475da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2025-07-22  Paul Eggert  <[email protected]>
 
+	mkdir-p: ENOENT/ENOTDIR safety and consistency
+	* lib/mkdir-p.c (make_dir_parents): If mkdir fails with ENOENT or
+	ENOTDIR, do not attempt anything else since the file does not exist.
+	Treat ENOENT and ENOTDIR consistently later, too.
+
 	mkdir-p: better diagnostics
 	Problem reported by Lauri Tirkkonen <https://bugs.gnu.org/79072>.
 	* lib/mkdir-p.c (make_dir_parents):
diff --git a/lib/mkdir-p.c b/lib/mkdir-p.c
index fffa58b4eb..7b764f122d 100644
--- a/lib/mkdir-p.c
+++ b/lib/mkdir-p.c
@@ -144,11 +144,13 @@ make_dir_parents (char *dir,
               mkdir_mode = -1;
             }
 
-          if (preserve_existing)
+          if (mkdir_errno == ENOENT || mkdir_errno == ENOTDIR)
+            ;
+          else if (preserve_existing)
             {
               if (mkdir_errno == 0)
                 return true;
-              if (mkdir_errno != ENOENT && make_ancestor)
+              if (make_ancestor)
                 {
                   struct stat st;
                   if (stat (dir + prefix_len, &st) == 0)
@@ -182,8 +184,7 @@ make_dir_parents (char *dir,
                     return true;
 
                   if (mkdir_errno == 0
-                      || (mkdir_errno != ENOENT && make_ancestor
-                          && errno != ENOTDIR))
+                      || (make_ancestor && errno != ENOENT && errno != ENOTDIR))
                     {
                       error (0, errno,
                              _(keep_owner
-- 
2.48.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.