Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 5 Oct 2004 18:57:16 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        freebsd-hackers@freebsd.org
Subject:   rm -I patch (Re: Protection from the dreaded "rm -fr /")
Message-ID:  <200410060157.i961vGTF048095@apollo.backplane.com>
References:  <20041002081928.GA21439@gothmog.gr> <200410021123.59811.max@love2party.net> <20041002083336.GA10355@k7.mavetju> <20041002101842.GA23272@gothmog.gr> <200410060131.i961V0pw047974@apollo.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help
    I think I'll commit something like this to DragonFly (you might
    get patch errors w/ FreeBSD but this is the basic idea).

					-Matt


Index: rm.1
===================================================================
RCS file: /cvs/src/bin/rm/rm.1,v
retrieving revision 1.2
diff -u -r1.2 rm.1
--- rm.1	17 Jun 2003 04:22:50 -0000	1.2
+++ rm.1	6 Oct 2004 01:34:12 -0000
@@ -81,6 +81,11 @@
 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 less intrusive dumb-user
+option then
+.Fl i
 .It Fl P
 Overwrite regular files before deleting them.
 Files are overwritten three times, first with the byte pattern 0xff,
Index: rm.c
===================================================================
RCS file: /cvs/src/bin/rm/rm.c,v
retrieving revision 1.3
diff -u -r1.3 rm.c
--- rm.c	30 Aug 2004 19:27:21 -0000	1.3
+++ rm.c	6 Oct 2004 01:52:46 -0000
@@ -51,9 +51,11 @@
 #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	rm_file(char **);
 void	rm_overwrite(char *, struct stat *);
@@ -70,7 +72,7 @@
 int
 main(int argc, char *argv[])
 {
-	int ch, rflag;
+	int ch;
 	char *p;
 
 	/*
@@ -94,7 +96,7 @@
 	}
 
 	Pflag = rflag = 0;
-	while ((ch = getopt(argc, argv, "dfiPRrvW")) != -1)
+	while ((ch = getopt(argc, argv, "dfiIPRrvW")) != -1)
 		switch(ch) {
 		case 'd':
 			dflag = 1;
@@ -107,6 +109,9 @@
 			fflag = 0;
 			iflag = 1;
 			break;
+		case 'I':
+			Iflag = 1;
+			break;
 		case 'P':
 			Pflag = 1;
 			break;
@@ -138,6 +143,10 @@
 	if (*argv) {
 		stdin_ok = isatty(STDIN_FILENO);
 
+		if (Iflag) {
+			if (check2(argv) == 0)
+				exit (1);
+		}
 		if (rflag)
 			rm_tree(argv);
 		else
@@ -442,6 +451,47 @@
 	return (first == 'y' || first == 'Y');
 }
 
+int
+check2(char **argv)
+{
+	struct stat st;
+	int first;
+	int ch;
+	int fcount = 0;
+	int dcount = 0;
+	int i;
+
+	for (i = 0; argv[i]; ++i) {
+		if (lstat(argv[i], &st) == 0) {
+			if (S_ISDIR(st.st_mode))
+				++dcount;
+			else
+				++fcount;
+		}
+	}
+	first = 0;
+	while (first != 'n' && first != 'N' && first != 'y' && first != 'Y') {
+		if (dcount && fcount && rflag) {
+			fprintf(stderr, 
+			    "recursively remove %d dirs and %d files? ",
+			    dcount, fcount);
+		} else if (dcount && rflag) {
+			fprintf(stderr, 
+			    "recursively remove %d dirs? ", dcount);
+		} else if (dcount + fcount > 3) {
+			fprintf(stderr, "remove %d files? ", dcount + fcount);
+		} else {
+			return(1);
+		}
+		fflush(stderr);
+
+		first = ch = getchar();
+		while (ch != '\n' && ch != EOF)
+			ch = getchar();
+	}
+	return (first == 'y' || first == 'Y');
+}
+
 #define ISDOT(a)	((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
 void
 checkdot(char **argv)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200410060157.i961vGTF048095>