[7666] in Athena Bugs
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;