bin/127932: mkdir -p PATH fails if a directory in PATH is on a read-only fs

Jaakko Heinonen jh at saunalahti.fi
Fri Oct 31 10:10:05 PDT 2008


The following reply was made to PR bin/127932; it has been noted by GNATS.

From: Jaakko Heinonen <jh at saunalahti.fi>
To: Till Toenges <tt at kyon.de>
Cc: bug-followup at freebsd.org
Subject: Re: bin/127932: mkdir -p PATH fails if a directory in PATH is on a
	read-only fs
Date: Fri, 31 Oct 2008 19:01:13 +0200

 Hi,
 
 On 2008-10-08, Till Toenges wrote:
 > Treat EROFS like EISDIR and EEXIST.
 > 
 > Patch attached with submission follows:
 > 
 > --- /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


More information about the freebsd-bugs mailing list