[7666] in Athena Bugs

home help back first fref pref prev next nref lref last post

rm

daemon@ATHENA.MIT.EDU (John Carr)
Sat Jun 15 09:17:58 1991

To: bugs@ATHENA.MIT.EDU
Date: Sat, 15 Jun 91 09:17:42 EDT
From: John Carr <jfc@ATHENA.MIT.EDU>


I've made some changes to rm:

	don't dump core if a directory is modified while being processed

	new option "-q": don't ask for confirmation but do print errors

	If -q or -f is used, try to remove a file before calling stat to
	see if it is a directory.  This improves performance because most
	files are not directories.  (rm was probably written when it was
	unsafe to call unlink() on a directory)

	Print more useful error messages

*** /source/bsd-4.3/common/bin/rm.c	Thu Aug  6 14:20:21 1987
--- rm.c	Sat Jun 15 09:08:43 1991
***************
*** 9,31 ****
  #include <sys/stat.h>
  #include <sys/dir.h>
  #include <sys/file.h>
  
  int	fflg;		/* -f force - supress error messages */
  int	iflg;		/* -i interrogate user on each file */
  int	rflg;		/* -r recurse */
  
  int	errcode;	/* true if errors occured */
  
! char	*strcpy(), *malloc(), *realloc();
  
  main(argc, argv)
  	char *argv[];
  {
  	register char *arg;
  
! 	fflg = !isatty(0);
! 	iflg = 0;
! 	rflg = 0;
  	while (argc > 1 && argv[1][0] == '-') {
  		arg = *++argv;
  		argc--;
--- 9,39 ----
  #include <sys/stat.h>
  #include <sys/dir.h>
  #include <sys/file.h>
+ #include <sys/errno.h>
+ #include <strings.h>
  
  int	fflg;		/* -f force - supress error messages */
  int	iflg;		/* -i interrogate user on each file */
  int	rflg;		/* -r recurse */
+ int	qflg;		/* -q don't prompt for confirmation */
  
  int	errcode;	/* true if errors occured */
  
! char	*malloc(), *realloc();
  
+ static int dotname(), rm();
+ static void append();
+ 
+ #ifndef strerror
+ #define	strerror(err) ((err) < sys_nerr ? sys_errlist[err] : "Unknown error")
+ #endif
+ 
  main(argc, argv)
  	char *argv[];
  {
  	register char *arg;
  
! 	qflg = !isatty(0);
  	while (argc > 1 && argv[1][0] == '-') {
  		arg = *++argv;
  		argc--;
***************
*** 33,39 ****
  		/*
  		 *  all files following a null option are considered file names
  		 */
! 		if (arg[1] == '\0')
  			break;
  
  		while (*++arg != '\0')
--- 41,47 ----
  		/*
  		 *  all files following a null option are considered file names
  		 */
! 		if (arg[1] == '\0' || arg[1] == '-')
  			break;
  
  		while (*++arg != '\0')
***************
*** 43,51 ****
  				break;
  
  			case 'i':
! 				iflg++;
  				break;
  
  			case 'R':
  			case 'r':
  				rflg++;
--- 51,65 ----
  				break;
  
  			case 'i':
! 				iflg = 1;
! 				qflg = 0;
  				break;
  
+ 			case 'q':
+ 				iflg = 0;
+ 				qflg = 1;
+ 				break;
+ 
  			case 'R':
  			case 'r':
  				rflg++;
***************
*** 52,64 ****
  				break;
  
  			default:
! 				fprintf(stderr, "usage: rm [-rif] file ...\n");
  				exit(1);
  			}
  	}
  
  	if (argc < 2 && !fflg) {
! 		fprintf(stderr, "usage: rm [-rif] file ...\n");
  		exit(1);
  	}
  
--- 66,78 ----
  				break;
  
  			default:
! 				fprintf(stderr, "usage: rm [-rifq] file ...\n");
  				exit(1);
  			}
  	}
  
  	if (argc < 2 && !fflg) {
! 		fprintf(stderr, "usage: rm [-rifq] file ...\n");
  		exit(1);
  	}
  
***************
*** 75,81 ****
  /*
   * Return TRUE if sucessful. Recursive with -r (rflg)
   */
! rm(arg, level)
  	char arg[];
  {
  	int ok;				/* true if recursive rm succeeded */
--- 89,95 ----
  /*
   * Return TRUE if sucessful. Recursive with -r (rflg)
   */
! static int rm(arg, level)
  	char arg[];
  {
  	int ok;				/* true if recursive rm succeeded */
***************
*** 85,90 ****
--- 99,117 ----
  	char prevname[MAXNAMLEN + 1];	/* previous name for -r */
  	char *cp;
  
+ 	if (fflg || qflg)
+ 		if (unlink(arg) == -1) {
+ 			if (errno == ENOENT) {
+ 				if (!fflg) {
+ 					fprintf(stderr, "rm: %s nonexistent\n", arg);
+ 				errcode++;
+ 				}
+ 				return 0;
+ 			} 
+ 		} else /* unlink succeeded */ {
+ 			return 1;
+ 		}
+ 
  	if (dotname(arg)) {
  		if (!fflg) 
  			fprintf(stderr, "rm: cannot remove `.' or `..'\n");
***************
*** 92,98 ****
  	}
  	if (lstat(arg, &buf)) {
  		if (!fflg) {
! 			fprintf(stderr, "rm: %s nonexistent\n", arg);
  			errcode++;
  		}
  		return (0);		/* error */
--- 119,129 ----
  	}
  	if (lstat(arg, &buf)) {
  		if (!fflg) {
! 			if(errno == ENOENT)
! 				fprintf(stderr, "rm: %s nonexistent\n", arg);
! 			else
! 				fprintf(stderr, "rm: %s: %s\n", arg,
! 					strerror(errno));
  			errcode++;
  		}
  		return (0);		/* error */
***************
*** 111,120 ****
  				return (0);	/* didn't remove everything */
  		}
  		if (access(arg, R_OK|W_OK|X_OK) != 0) {
  			if (rmdir(arg) == 0)
  				return (1);	/* salvaged: removed empty dir */
  			if (!fflg) {
! 				fprintf(stderr, "rm: %s not changed\n", arg);
  				errcode++;
  			}
  			return (0);		/* error */
--- 142,153 ----
  				return (0);	/* didn't remove everything */
  		}
  		if (access(arg, R_OK|W_OK|X_OK) != 0) {
+ 			int save_errno = errno;
  			if (rmdir(arg) == 0)
  				return (1);	/* salvaged: removed empty dir */
  			if (!fflg) {
! 				fprintf(stderr, "rm: %s not changed: %s\n",
! 					arg, strerror(save_errno));
  				errcode++;
  			}
  			return (0);		/* error */
***************
*** 157,168 ****
  			/* skip the one we just failed to delete */
  			if (!ok) {
  				dp = readdir(dirp);
! 				if (dp != NULL && strcmp(cp, dp->d_name)) {
! 					fprintf(stderr,
! 			"rm: internal synchronization error: %s, %s, %s\n",
! 						arg, cp, dp->d_name);
  				}
- 				strcpy(prevname, dp->d_name);
  			}
  		}
  		closedir(dirp);
--- 190,202 ----
  			/* skip the one we just failed to delete */
  			if (!ok) {
  				dp = readdir(dirp);
! 				if (dp != NULL) {
! 					if (strcmp(cp, dp->d_name)) {
! 						fprintf(stderr, "rm: internal synchronization error: %s, %s, %s\n",
! 							arg, cp, dp->d_name);
! 					}
! 					strcpy(prevname, dp->d_name);
  				}
  			}
  		}
  		closedir(dirp);
***************
*** 177,183 ****
  		}
  		if (rmdir(arg) < 0) {
  			if (!fflg || iflg) {
! 				fprintf(stderr, "rm: %s not removed\n", arg);
  				errcode++;
  			}
  			return (0);
--- 211,218 ----
  		}
  		if (rmdir(arg) < 0) {
  			if (!fflg || iflg) {
! 				fprintf(stderr, "rm: %s not removed: %s\n",
! 					arg, strerror(errno));
  				errcode++;
  			}
  			return (0);
***************
*** 189,195 ****
  		printf("rm: remove %s? ", arg);
  		if (!yes())
  			return (0);
! 	} else if (!fflg) {
  		if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, W_OK) < 0) {
  			printf("rm: override protection %o for %s? ",
  				buf.st_mode&0777, arg);
--- 224,230 ----
  		printf("rm: remove %s? ", arg);
  		if (!yes())
  			return (0);
! 	} else if (!fflg && !qflg) {
  		if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, W_OK) < 0) {
  			printf("rm: override protection %o for %s? ",
  				buf.st_mode&0777, arg);
***************
*** 199,205 ****
  	}
  	if (unlink(arg) < 0) {
  		if (!fflg || iflg) {
! 			fprintf(stderr, "rm: %s not removed\n", arg);
  			errcode++;
  		}
  		return (0);
--- 234,241 ----
  	}
  	if (unlink(arg) < 0) {
  		if (!fflg || iflg) {
! 			fprintf(stderr, "rm: %s not removed: %s\n", 
! 				arg, strerror(errno));
  			errcode++;
  		}
  		return (0);
***************
*** 210,216 ****
  /*
   * boolean: is it "." or ".." ?
   */
! dotname(s)
  	char *s;
  {
  	if (s[0] == '.')
--- 246,252 ----
  /*
   * boolean: is it "." or ".." ?
   */
! static int dotname(s)
  	char *s;
  {
  	if (s[0] == '.')
***************
*** 240,246 ****
  /*
   * Append 'name' to 'path'.
   */
! append(name)
  	char *name;
  {
  	register int n;
--- 276,282 ----
  /*
   * Append 'name' to 'path'.
   */
! static void append(name)
  	char *name;
  {
  	register int n;

home help back first fref pref prev next nref lref last post