diff options
author | delphij <delphij@FreeBSD.org> | 2004-10-28 08:25:30 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2004-10-28 08:25:30 +0000 |
commit | 169dc919b8eccc8395d3b89e0bccdb8dfc61b13c (patch) | |
tree | a070af7791626abd13bcf3d6db2a57b1889e86ca /bin/rm | |
parent | 5a159b2d78bc926a669b419529f653f247d76c37 (diff) | |
download | FreeBSD-src-169dc919b8eccc8395d3b89e0bccdb8dfc61b13c.zip FreeBSD-src-169dc919b8eccc8395d3b89e0bccdb8dfc61b13c.tar.gz |
Add -I, an option that asks for confirmation once if recursively
removing directories or if more than 3 files are listed in the
command line.
This feature is intended to provide a safe net but not being too
annoying like having "rm -i" for every deleting operations, and
is generally good for both newbies and power users, preventing
them from being so easily run into ``rm -rf /'', ``rm -rf *''
and so forth.
Originally implemented by Matthew Dillon for DragonFly, plus
some improvements done by various DragonFly contributors.
Approved by: murray (mentor; the original dillon's version)
Discussed with: des
Obtained from: DragonFly's bin/rm/
rm.c rev. 1.4 - 1.8
rm.1 rev. 1.3 - 1.4
MFC After: 1 month
Diffstat (limited to 'bin/rm')
-rw-r--r-- | bin/rm/rm.1 | 10 | ||||
-rw-r--r-- | bin/rm/rm.c | 65 |
2 files changed, 70 insertions, 5 deletions
diff --git a/bin/rm/rm.1 b/bin/rm/rm.1 index c31ecaa..5fb6f05 100644 --- a/bin/rm/rm.1 +++ b/bin/rm/rm.1 @@ -31,7 +31,7 @@ .\" @(#)rm.1 8.5 (Berkeley) 12/5/94 .\" $FreeBSD$ .\" -.Dd October 4, 2004 +.Dd October 28, 2004 .Dt RM 1 .Os .Sh NAME @@ -40,7 +40,7 @@ .Nd remove directory entries .Sh SYNOPSIS .Nm -.Op Fl dfiPRrvW +.Op Fl dfiIPRrvW .Ar .Nm unlink .Ar file @@ -76,6 +76,12 @@ The option overrides any previous .Fl f options. +.It Fl I +Request confirmation once if more then three files are being removed or if a +directory is being recursively removed. This is a far less intrusive option +than +.Fl i +yet provides almost the same level of protection against mistakes. .It Fl P Overwrite regular files before deleting them. Files are overwritten three times, first with the byte pattern 0xff, diff --git a/bin/rm/rm.c b/bin/rm/rm.c index c313282..52ead50 100644 --- a/bin/rm/rm.c +++ b/bin/rm/rm.c @@ -58,9 +58,11 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; +int rflag, Iflag; uid_t uid; int check(char *, char *, struct stat *); +int check2(char **); void checkdot(char **); void checkslash(char **); void rm_file(char **); @@ -78,7 +80,7 @@ void usage(void); int main(int argc, char *argv[]) { - int ch, rflag; + int ch; char *p; /* @@ -102,7 +104,7 @@ main(int argc, char *argv[]) } Pflag = rflag = 0; - while ((ch = getopt(argc, argv, "dfiPRrvW")) != -1) + while ((ch = getopt(argc, argv, "dfiIPRrvW")) != -1) switch(ch) { case 'd': dflag = 1; @@ -115,6 +117,9 @@ main(int argc, char *argv[]) fflag = 0; iflag = 1; break; + case 'I': + Iflag = 1; + break; case 'P': Pflag = 1; break; @@ -148,6 +153,10 @@ main(int argc, char *argv[]) if (*argv) { stdin_ok = isatty(STDIN_FILENO); + if (Iflag) { + if (check2(argv) == 0) + exit (1); + } if (rflag) rm_tree(argv); else @@ -489,6 +498,56 @@ checkslash(char **argv) } } +int +check2(char **argv) +{ + struct stat st; + int first; + int ch; + int fcount = 0; + int dcount = 0; + int i; + const char *dname = NULL; + + for (i = 0; argv[i]; ++i) { + if (lstat(argv[i], &st) == 0) { + if (S_ISDIR(st.st_mode)) { + ++dcount; + dname = argv[i]; /* only used if 1 dir */ + } else { + ++fcount; + } + } + } + first = 0; + while (first != 'n' && first != 'N' && first != 'y' && first != 'Y') { + if (dcount && rflag) { + fprintf(stderr, "recursively remove"); + if (dcount == 1) + fprintf(stderr, " %s", dname); + else + fprintf(stderr, " %d dirs", dcount); + if (fcount == 1) + fprintf(stderr, " and 1 file"); + else if (fcount > 1) + fprintf(stderr, " and %d files", fcount); + } else if (dcount + fcount > 3) { + fprintf(stderr, "remove %d files", dcount + fcount); + } else { + return(1); + } + fprintf(stderr, "? "); + fflush(stderr); + + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + if (ch == EOF) + break; + } + return (first == 'y' || first == 'Y'); +} + #define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) void checkdot(char **argv) @@ -519,7 +578,7 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n", - "usage: rm [-f | -i] [-dPRrvW] file ...", + "usage: rm [-f | -i] [-dIPRrvW] file ...", " unlink file"); exit(EX_USAGE); } |