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:
parent
f00f5d71c2
commit
24c0f7385b
10
bin/rm/rm.1
10
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,
|
||||
|
65
bin/rm/rm.c
65
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user