Subject: bin/1157: mkdir -p doesn't ignore existing directories
To: None <gnats-admin@sun-lamp.pc.cs.cmu.edu>
From: Greg Hudson <ghudson@mit.edu>
List: netbsd-bugs
Date: 06/25/1995 17:05:04
>Number:         1157
>Category:       bin
>Synopsis:       mkdir -p doesn't ignore existing directories
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 25 17:05:01 1995
>Originator:     Greg Hudson
>Organization:
	MIT SIPB
>Release:        June 25, 1995
>Environment:
	
System: NetBSD glacier 1.0A NetBSD 1.0A (GLACIER) #1: Fri May 5 10:55:51 EDT 1995 ghudson@glacier:/afs/sipb.mit.edu/project/netbsd/dev/current-source/src/sys/arch/i386/compile/GLACIER i386


>Description:
	According to POSIX 1003.2-1992 (as amended by 1003.2a-1992, I
	guess), section 4.41.3, mkdir -p is supposed to ignore arguments
	which name existing directories:

		"Each dir operand that names an existing directory shall
		be ignored without error."

	NetBSD's mkdir -p gives an error message if you give "mkdir -p"
	an existing directory argument.
>How-To-Repeat:
	mkdir -p /tmp
>Fix:
	Here is a sample fix which applies the same logic to the last path
	component as it does to the internal path components.  It might be
	possible to simplify the logic of the loop somewhat.

*** 1.1	1995/06/25 20:16:44
--- mkdir.c	1995/06/25 20:30:20
***************
*** 133,145 ****
  {
  	struct stat sb;
  	register char *slash;
  
! 	/* skip leading slashes */
! 	slash = path;
! 	while (*slash == '/')
! 		slash++;
  
! 	while ((slash = strchr(slash, '/')) != NULL) {
  		*slash = '\0';
  
  		if (stat(path, &sb)) {
--- 133,146 ----
  {
  	struct stat sb;
  	register char *slash;
+ 	int done = 0;
  
! 	/* Find first slash after leading slash. */
! 	slash = path + strspn(path, "/");
! 	slash += strcspn(slash, "/");
  
! 	while (!done) {
! 		done = (*slash == '\0');
  		*slash = '\0';
  
  		if (stat(path, &sb)) {
***************
*** 152,166 ****
  			return 1;
  		}
  		    
! 		/* skip multiple slashes */
! 		*slash++ = '/';
! 		while (*slash == '/')
! 			slash++;
! 	}
! 
! 	if (mkdir (path, mode)) {
! 		warn("%s", path);
! 		return 1;
  	}
  
  	return(0);
--- 153,164 ----
  			return 1;
  		}
  		    
! 		/* skip multiple slashes, and find next slash (or the end) */
! 		if (!done) {
! 			*slash++ = '/';
! 			slash += strspn(slash, "/");
! 			slash += strcspn(slash, "/");
! 		}
  	}
  
  	return(0);
>Audit-Trail:
>Unformatted: