correction to rmdir.c using catpath (just posted)

forsyth forsyth at minster.UUCP
Wed Jul 30 15:57:12 AEST 1986


Here are some changes from diffc to rmdir.c (7th edition) that use the
catpath function just posted to net.sources (862 at minster.UUCP) to correct the
recently observed bug in rmdir.  (I also changed the Usage message,
and stopped the code from using "" as a file name.)
Similar changes should apply to system V, but beware of the code
in that version, in rmdir(), near the call to `strrchr'.
It was changed from
	if((np = rindex(name, '/')) == NULL)
		np = name;
	else
		np++;
to
	if((np = strrchr(name, '/')) == NULL)
		np = name;
but unfortunately this breaks the protection (weak as it was) against
doing
	(mkdir b; rmdir b/.)
It might be best to put the np++ back in.  In any case, there is still
a problem that `rmdir /' results in `/ unreadable' on systems that
refuse access to "" as a file name.  Given the proposed target and the
nature of the request, perhaps this is just as well.

*** o_rmdir.c	Wed Jul 23 13:49:31 1986
--- rmdir.c	Wed Jul 23 14:04:32 1986
***************
*** 11,16
  char	*rindex();
  char	*strcat();
  char	*strcpy();
  
  main(argc,argv)
  int argc;

--- 11,17 -----
  char	*rindex();
  char	*strcat();
  char	*strcpy();
+ char	*catpath();
  
  main(argc,argv)
  int argc;
***************
*** 18,24
  {
  
  	if(argc < 2) {
! 		fprintf(stderr, "rmdir: arg count\n");
  		exit(1);
  	}
  	while(--argc)

--- 19,25 -----
  {
  
  	if(argc < 2) {
! 		fprintf(stderr, "Usage: rmdir dirname ...\n");
  		exit(1);
  	}
  	while(--argc)
***************
*** 30,36
  char *d;
  {
  	int	fd;
! 	char	*np, name[500];
  	struct	stat	st, cst;
  	struct	direct	dir;
  

--- 31,37 -----
  char *d;
  {
  	int	fd;
! 	char	*np, name[500], *comp[2];
  	struct	stat	st, cst;
  	struct	direct	dir;
  
***************
*** 34,40
  	struct	stat	st, cst;
  	struct	direct	dir;
  
! 	strcpy(name, d);
  	for (np = name+strlen(name); np != name && *--np == '/';)
  		*np = 0;
  	if((np = rindex(name, '/')) == NULL)

--- 35,52 -----
  	struct	stat	st, cst;
  	struct	direct	dir;
  
! 	if(stat(d,&st) < 0) {
! 		fprintf(stderr, "rmdir: %s non-existent\n", d);
! 		++Errors;
! 		return;
! 	}
! 	comp[0] = d;
! 	comp[1] = NULL;
! 	if (catpath(name, sizeof name, comp) == NULL) {
! 		fprintf(stderr, "rmdir: the name %s is too long\n", d);
! 		++Errors;
! 		return;
! 	}
  	for (np = name+strlen(name); np != name && *--np == '/';)
  		*np = 0;
  	if((np = rindex(name, '/')) == NULL)
***************
*** 41,48
  		np = name;
  	else
  		np++;
! 	if(stat(name,&st) < 0) {
! 		fprintf(stderr, "rmdir: %s non-existent\n", name);
  		++Errors;
  		return;
  	}

--- 53,60 -----
  		np = name;
  	else
  		np++;
! 	if (stat(".", &cst) < 0) {
! 		fprintf(stderr, "rmdir: cannot stat \".\"");
  		++Errors;
  		return;
  	}
***************
*** 46,56
  		++Errors;
  		return;
  	}
- 	if (stat("", &cst) < 0) {
- 		fprintf(stderr, "rmdir: cannot stat \"\"");
- 		++Errors;
- 		exit(1);
- 	}
  	if((st.st_mode & S_IFMT) != S_IFDIR) {
  		fprintf(stderr, "rmdir: %s not a directory\n", name);
  		++Errors;

--- 58,63 -----
  		++Errors;
  		return;
  	}
  	if((st.st_mode & S_IFMT) != S_IFDIR) {
  		fprintf(stderr, "rmdir: %s not a directory\n", name);
  		return(1);
***************
*** 53,60
  	}
  	if((st.st_mode & S_IFMT) != S_IFDIR) {
  		fprintf(stderr, "rmdir: %s not a directory\n", name);
! 		++Errors;
! 		return;
  	}
  	if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) {
  		fprintf(stderr, "rmdir: cannot remove current directory\n");

--- 60,66 -----
  	}
  	if((st.st_mode & S_IFMT) != S_IFDIR) {
  		fprintf(stderr, "rmdir: %s not a directory\n", name);
! 		return(1);
  	}
  	if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) {
  		fprintf(stderr, "rmdir: cannot remove current directory\n");
***************
*** 58,63
  	}
  	if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) {
  		fprintf(stderr, "rmdir: cannot remove current directory\n");
  		++Errors;
  		return;
  	}

--- 64,73 -----
  	}
  	if(st.st_ino==cst.st_ino &&st.st_dev==cst.st_dev) {
  		fprintf(stderr, "rmdir: cannot remove current directory\n");
+ 		return(1);
+ 	}
+ 	if(!strcmp(np, ".") || !strcmp(np, "..")) {
+ 		fprintf(stderr, "rmdir: cannot remove . or ..\n");
  		++Errors;
  		return;
  	}
***************
*** 62,68
  		return;
  	}
  	if((fd = open(name,0)) < 0) {
! 		fprintf(stderr, "rmdir: %s unreadable\n", name);
  		++Errors;
  		return;
  	}

--- 72,78 -----
  		return;
  	}
  	if((fd = open(name,0)) < 0) {
! 		fprintf(stderr, "rmdir: %s unreadable\n", d);
  		++Errors;
  		return;
  	}
***************
*** 66,80
  		++Errors;
  		return;
  	}
! 	while(read(fd, (char *)&dir, sizeof dir) == sizeof dir) {
! 		if(dir.d_ino == 0) continue;
! 		if(!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, ".."))
! 			continue;
! 		fprintf(stderr, "rmdir: %s not empty\n", name);
! 		++Errors;
! 		close(fd);
! 		return;
! 	}
  	close(fd);
  	if(!strcmp(np, ".") || !strcmp(np, "..")) {
  		fprintf(stderr, "rmdir: cannot remove . or ..\n");

--- 76,90 -----
  		++Errors;
  		return;
  	}
! 	while(read(fd, (char *)&dir, sizeof dir) == sizeof dir)
! 		if (dir.d_ino != 0 &&
! 		    strcmp(dir.d_name, ".") != 0 &&
! 		    strcmp(dir.d_name, "..") != 0) {
! 			fprintf(stderr, "rmdir: %s not empty\n", d);
! 			++Errors;
! 			close(fd);
! 			return;
! 		}
  	close(fd);
  	strcat(name, "/.");
  	if(access(name, 0) < 0) {		/* name/. non-existent */
***************
*** 76,86
  		return;
  	}
  	close(fd);
- 	if(!strcmp(np, ".") || !strcmp(np, "..")) {
- 		fprintf(stderr, "rmdir: cannot remove . or ..\n");
- 		++Errors;
- 		return;
- 	}
  	strcat(name, "/.");
  	if((access(name, 0)) < 0) {		/* name/. non-existent */
  		strcat(name, ".");

--- 86,91 -----
  			return;
  		}
  	close(fd);
  	strcat(name, "/.");
  	if(access(name, 0) < 0) {		/* name/. non-existent */
  		strcat(name, ".");
***************
*** 82,88
  		return;
  	}
  	strcat(name, "/.");
! 	if((access(name, 0)) < 0) {		/* name/. non-existent */
  		strcat(name, ".");
  		goto unl;
  	}

--- 87,93 -----
  		}
  	close(fd);
  	strcat(name, "/.");
! 	if(access(name, 0) < 0) {		/* name/. non-existent */
  		strcat(name, ".");
  		goto unl;
  	}
***************
*** 87,93
  		goto unl;
  	}
  	strcat(name, ".");
! 	if((access(name, 0)) < 0)		/* name/.. non-existent */
  		goto unl2;
  	if(access(name, 02)) {
  		name[strlen(name)-3] = '\0';

--- 92,98 -----
  		goto unl;
  	}
  	strcat(name, ".");
! 	if(access(name, 0) < 0)		/* name/.. non-existent */
  		goto unl2;
  	if(access(name, 02)) {
  		fprintf(stderr, "rmdir: %s: no permission\n", d);
***************
*** 90,97
  	if((access(name, 0)) < 0)		/* name/.. non-existent */
  		goto unl2;
  	if(access(name, 02)) {
! 		name[strlen(name)-3] = '\0';
! 		fprintf(stderr, "rmdir: %s: no permission\n", name);
  		++Errors;
  		return;
  	}

--- 95,101 -----
  	if(access(name, 0) < 0)		/* name/.. non-existent */
  		goto unl2;
  	if(access(name, 02)) {
! 		fprintf(stderr, "rmdir: %s: no permission\n", d);
  		++Errors;
  		return;
  	}
***************
*** 102,108
  	unlink(name);	/* unlink name/.  */
  	name[strlen(name)-2] = '\0';
  	if (unlink(name) < 0) {
! 		fprintf(stderr, "rmdir: %s not removed\n", name);
  		++Errors;
  	}
  }

--- 106,112 -----
  	unlink(name);	/* unlink name/.  */
  	name[strlen(name)-2] = '\0';
  	if (unlink(name) < 0) {
! 		fprintf(stderr, "rmdir: %s not removed\n", d);
  		++Errors;
  	}
  }



More information about the Net.bugs.v7 mailing list