mkdir -p <path> fails if a directory in <path> is on a read-only fs. It tries to create every directory <subdir> in <path>, and ignores EEXIST and EISDIR errors, if <subdir> is a directory. But it treats EROFS as an error and exits. Noticed it while trying to build a port in a jail, where the jails / was read-only union mounted in the directory containing the jails /var. Fix: Treat EROFS like EISDIR and EEXIST. Patch attached with submission follows: How-To-Repeat: Assuming a read-only root, and /var mounted writable: mkdir -p /var/db/ports/openldap24 fails.
Hi, On 2008-10-08, Till Toenges wrote: > Treat EROFS like EISDIR and EEXIST. > > > > --- /usr/src/bin/mkdir/mkdir.c 2006-10-10 22:18:20.000000000 +0200 > +++ /root/mkdir/mkdir.c 2008-10-08 01:44:22.000000000 +0200 > @@ -177,7 +177,7 @@ > if (last) > (void)umask(oumask); > if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) { > - if (errno == EEXIST || errno == EISDIR) { > + if (errno == EEXIST || errno == EISDIR || errno == EROFS) { > if (stat(path, &sb) < 0) { > warn("%s", path); > retval = 0; This has patch has a problem. Patched mkdir(1) gives a bogus error message if a directory creation fails on read-only file system. $ mkdir -p foo (unpatched) mkdir: foo: Read-only file system $ mkdir -p foo (patched) mkdir: foo: No such file or directory The latter error message is very misleading because the real reason for the failure is read-only file system. Maybe save the original error number and if stat(2) fails in EROFS case then use it instead of the error from stat(2). Something like this: %%% Index: bin/mkdir/mkdir.c =================================================================== --- bin/mkdir/mkdir.c (revision 183921) +++ bin/mkdir/mkdir.c (working copy) @@ -140,7 +140,7 @@ build(char *path, mode_t omode) { struct stat sb; mode_t numask, oumask; - int first, last, retval; + int first, last, retval, serrno; char *p; p = path; @@ -177,8 +177,12 @@ build(char *path, mode_t omode) if (last) (void)umask(oumask); if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) { - if (errno == EEXIST || errno == EISDIR) { + if (errno == EEXIST || errno == EISDIR || + errno == EROFS) { + serrno = errno; if (stat(path, &sb) < 0) { + if (serrno == EROFS) + errno = EROFS; warn("%s", path); retval = 0; break; %%% -- Jaakko
State Changed From-To: open->feedback I was unable to reproduce the problem. I don't see how mkdir(2) could return EROFS if the file exists (even on read-only file system). Thus I don't see the need to patch mkdir(1). Can you still reproduce the problem?
Responsible Changed From-To: freebsd-bugs->jh Track.
State Changed From-To: feedback->analyzed Now I see how this can happen with unionfs: unionfs_lookup() returns EROFS for CREATE namei operation when unionfs is mounted as read-only even if the file exists. I consider this a kernel (unionfs) problem and I don't think it's sensible to patch mkdir(1).
Responsible Changed From-To: jh->freebsd-bugs Back to pool.
For bugs matching the following conditions: - Status == In Progress - Assignee == "bugs@FreeBSD.org" - Last Modified Year <= 2017 Do - Set Status to "Open"