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

From: Collin Funk <[email-masked]>
Date: Mon, 21 Jul 2025 23:10:09 -0700

Hi Lauri,

Lauri Tirkkonen via GNU coreutils Bug Reports <[email-masked]>
writes:

> saw this on coreutils 9.7 on Alpine Linux, but it also reproduces on
> commit 027855dcad52d718927c3405bc7d605143e2a625.
>
> 	# mount -t tmpfs -o ro none /mnt
> 	# ./src/ginstall -d /mnt/foo
> 	ginstall: cannot change permissions of ‘/mnt/foo’: No such file or directory
>
> I would expect the error to be EROFS for creating the directory, not
> changing permissions of the directory that was not able to be created.
> strace confirms mkdir() returns EROFS, but install tries to open() and
> stat() the not-created directory afterward.

Thanks for the report.

It looks like the Gnulib mkdir-p module does not fail when 'mkdir' fails
with EROFS. And it looks like it has always behaved this way.

Paul, you are certainly more familiar with gnulib's mkdir-p and savewd
modules than I am. Can you check that the attached patch is correct
before I commit it?

Here is the new error based on Lauri's example:

    $ ./src/ginstall -d /mnt/foo
    ginstall: cannot create directory ‘/mnt/foo’: Read-only file system

Thanks,
Collin

>From 822da07feb7862acbade9cb9aa5a9f5fa9cc6458 Mon Sep 17 00:00:00 2001
Message-ID: <822d[email-masked]>
From: Collin Funk <[email-masked]>
Date: Mon, 21 Jul 2025 23:02:55 -0700
Subject: [PATCH] mkdir-p: Diagnose read-only file systems.

* lib/mkdir-p.c (make_dir_parents): Check for 'mkdir' failing on a
read-only file system.
---
 ChangeLog     | 4 ++++
 lib/mkdir-p.c | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 99ca126183..3948326827 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2025-07-21  Collin Funk  <[email-masked]>
 
+	mkdir-p: Diagnose read-only file systems.
+	* lib/mkdir-p.c (make_dir_parents): Check for 'mkdir' failing on a
+	read-only file system.
+
 	sys_un-h: Make sure that the 'sys' subdirectory is created.
 	* modules/sys_un-h (Makefile.am): Make the 'sys' subdirectory. Remove
 	@NMD@ that is not applicable to subdirectories.
diff --git a/lib/mkdir-p.c b/lib/mkdir-p.c
index f5df9843e4..fc83434655 100644
--- a/lib/mkdir-p.c
+++ b/lib/mkdir-p.c
@@ -182,8 +182,8 @@ make_dir_parents (char *dir,
                     return true;
 
                   if (mkdir_errno == 0
-                      || (mkdir_errno != ENOENT && make_ancestor
-                          && errno != ENOTDIR))
+                      || (mkdir_errno != ENOENT && mkdir_errno != EROFS
+                          && make_ancestor && errno != ENOTDIR))
                     {
                       error (0, errno,
                              _(keep_owner
-- 
2.50.1