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
This commit is contained in:
Xin LI 2004-10-28 08:25:30 +00:00
parent f00f5d71c2
commit 24c0f7385b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=137009
2 changed files with 70 additions and 5 deletions

View File

@ -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,

View File

@ -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);
}