delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2005/10/12/17:24:24

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
To: ericblake AT comcast DOT net (Eric Blake)
Cc: bug-coreutils AT gnu DOT org, cygwin AT cygwin DOT com
Subject: Re: mkdir -p and EROFS
References: <101220051447 DOT 16978 DOT 434D21E5000D25EB0000425222007610640A050E040D0C079D0A AT comcast DOT net>
From: Paul Eggert <eggert AT CS DOT UCLA DOT EDU>
Date: Wed, 12 Oct 2005 14:24:09 -0700
In-Reply-To: <101220051447.16978.434D21E5000D25EB0000425222007610640A050E040D0C079D0A@comcast.net> (Eric Blake's message of "Wed, 12 Oct 2005 14:47:01 +0000")
Message-ID: <87r7aqqvie.fsf@penguin.cs.ucla.edu>
User-Agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)
MIME-Version: 1.0

ericblake AT comcast DOT net (Eric Blake) writes:

> The algorithm change between 5.3.0 and 5.90 in lib/mkdir-p.c to
> try mkdir() first instead of stat(), and key off of EEXIST, breaks
> when mkdir() fails with EROFS on an intermediate directory when
> the writable directory has been mounted inside a read-only tree.

Thanks for reporting this.  It is indeed a bug in
coreutils/lib/mkdir-p.c.  It can be triggered by other errors too.
This is hard to write a test case for, but I'd like to fix things.
Does the following patch work for you?

Jim, if this works for Eric, is it OK to install this patch at this late
date?

2005-10-12  Paul Eggert  <eggert AT cs DOT ucla DOT edu>

	* mkdir-p.c (make_dir_parents): Don't fail if an intervening mkdir
	fails due to EROFS, or due to EEXIST or other reasons for that matter.
	Problem reported by Eric Blake.
	(ENOSYS): Remove; no longer needed.

--- mkdir-p.c.~1.11.~	2005-09-21 22:42:26.000000000 -0700
+++ mkdir-p.c	2005-10-12 14:21:22.000000000 -0700
@@ -45,10 +45,6 @@
 #include "quote.h"
 #include "stat-macros.h"
 
-#ifndef ENOSYS
-# define ENOSYS EEXIST
-#endif
-
 #define WX_USR (S_IWUSR | S_IXUSR)
 
 /* Ensure that the directory ARG exists.
@@ -175,6 +171,9 @@ make_dir_parents (char const *arg,
 
       while (true)
 	{
+	  bool dir_known_to_exist;
+	  int mkdir_errno;
+
 	  /* slash points to the leftmost unprocessed component of dir.  */
 	  basename_dir = slash;
 
@@ -188,7 +187,10 @@ make_dir_parents (char const *arg,
 	    basename_dir = dir;
 
 	  *slash = '\0';
-	  if (mkdir (basename_dir, tmp_mode) == 0)
+	  dir_known_to_exist = (mkdir (basename_dir, tmp_mode) == 0);
+	  mkdir_errno = errno;
+
+	  if (dir_known_to_exist)
 	    {
 	      if (verbose_fmt_string)
 		error (0, 0, verbose_fmt_string, quote (dir));
@@ -215,29 +217,30 @@ make_dir_parents (char const *arg,
 		  leading_dirs = new;
 		}
 	    }
-	  else if (errno == EEXIST || errno == ENOSYS)
-	    {
-	      /* A file is already there.  Perhaps it is a directory.
-		 If not, it will be diagnosed later.
-
-		 The ENOSYS is for Solaris 8 NFS clients, which can
-		 fail with errno == ENOSYS if mkdir is invoked on an
-		 NFS mount point.  */
-	    }
-	  else
-	    {
-	      error (0, errno, _("cannot create directory %s"), quote (dir));
-	      retval = false;
-	      break;
-	    }
 
 	  /* If we were able to save the initial working directory,
 	     then we can use chdir to change into each directory before
 	     creating an entry in that directory.  This avoids making
 	     mkdir process O(n^2) file name components.  */
-	  if (do_chdir && chdir (basename_dir) < 0)
+	  if (do_chdir)
+	    {
+	      if (chdir (basename_dir) == 0)
+		dir_known_to_exist = true;
+	      else if (dir_known_to_exist)
+		{
+		  error (0, errno, _("cannot chdir to directory %s"),
+			 quote (dir));
+		  retval = false;
+		  break;
+		}
+	    }
+	  else if (!dir_known_to_exist)
+	    dir_known_to_exist = (stat (basename_dir, &stats) == 0
+				  && S_ISDIR (stats.st_mode));
+
+	  if (!dir_known_to_exist)
 	    {
-	      error (0, errno, _("cannot chdir to directory %s"),
+	      error (0, mkdir_errno, _("cannot create directory %s"),
 		     quote (dir));
 	      retval = false;
 	      break;

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019