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.
From 27db579667399d9f2cae2552a6f9185ffd10ab23 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
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 <egg...@cs.ucla.edu>
+
+ 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 <collin.fu...@gmail.com>
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
From 84ddfc7bd29853ed91cdd65c7ce818072959f974 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
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 <egg...@cs.ucla.edu>
+ 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