[PATCH] /bin/rm Add "all" interactive option

Matthew Dillon dillon at apollo.backplane.com
Sat Dec 18 12:47:33 PST 2004


    I think this goes a bit beyond what 'rm' should be used for, and into
    what 'find' should be used for.

					-Matt
					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>


:This patch adds an "all" option to the rm utility's interactive mode as 
:described below.
:
:
:The following is true in recursive mode:
:
:If "all" is specified to a directory, only that directory and everything 
:in it is removed. If "all" is specified to a file, all the files in the 
:same directory are deleted. If "all" is specified for a file on the 
:command line, all files listed on the command line are deleted. If "all" 
:is specified for a directory on the command line, only that directory 
:and everything in it is removed.
:
:
:The following is true when NOT in recursive mode:
:
:If "all" is specified to one of the files or directories listed on the 
:command line, all the files and directories listed will be deleted 
:(directories have to be empty to be deleted when in NOT in recursive mode).
:
:
:The follwing is true when the -I flag is specified:
:
:If "all" is specified, -f is assumed.
:
:
:
:- Jason
:
:--------------090304040006040702060209
:Content-Type: text/plain;
: name="rm.c.diff"
:Content-Transfer-Encoding: 7bit
:Content-Disposition: inline;
: filename="rm.c.diff"
:
:--- rm.c.orig	Sat Dec 18 13:39:18 2004
:+++ rm.c	Sat Dec 18 14:04:15 2004
:@@ -50,10 +50,13 @@
: #include <sysexits.h>
: #include <unistd.h>
: 
:-int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
:-int rflag, Iflag;
:-uid_t uid;
:+static int dflag, fflag, Iflag, iflag, Pflag, rflag, vflag, Wflag;
:+static int eval;
:+static int removeAll;
:+static int stdin_ok;
:+static uid_t uid;
: 
:+static int  rm_get_answeer(void);
: static int	check(const char *, const char *, struct stat *);
: static int	check2(char **);
: static void	checkdot(char **);
:@@ -164,6 +167,7 @@
: 	int needstat;
: 	int flags;
: 	int rval;
:+	int removeLevel;
: 
: 	/*
: 	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
:@@ -184,6 +188,7 @@
: 		flags |= FTS_WHITEOUT;
: 	if (!(fts = fts_open(argv, flags, NULL)))
: 		err(1, NULL);
:+	removeLevel = -1;
: 	while ((p = fts_read(fts)) != NULL) {
: 		switch (p->fts_info) {
: 		case FTS_DNR:
:@@ -209,18 +214,35 @@
: 			}
: 			continue;
: 		case FTS_D:
:-			/* Pre-order: give user chance to skip. */
:+			/*
:+			 * Stop removing everything when we go to another
:+			 * directory at the same level or higher up in the
:+			 * directory hierarchy.
:+			 */
:+			if (removeAll && removeLevel >= p->fts_level) {
:+				removeAll = 0;
:+				removeLevel = -1;
:+			}
:+
: 			if (!fflag && !check(p->fts_path, p->fts_accpath,
: 			    p->fts_statp)) {
: 				fts_set(fts, p, FTS_SKIP);
: 				p->fts_number = SKIPPED;
:+			} else {
:+				/*
:+				 * Check if the user has just asked for everything
:+				 * in this directory to be removed.
:+				 */
:+				if (removeAll && removeLevel == -1)
:+					removeLevel = p->fts_level;
:+
:+				if (!uid
:+					&& (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE))
:+					&& !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE))
:+					&& chflags(p->fts_accpath,
:+						p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
:+					goto err;
: 			}
:-			else if (!uid &&
:-				 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
:-				 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
:-				 chflags(p->fts_accpath,
:-					 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
:-				goto err;
: 			continue;
: 		case FTS_DP:
: 			/* Post-order: see if user skipped. */
:@@ -228,9 +250,27 @@
: 				continue;
: 			break;
: 		default:
:+			/*
:+			 * Stop removing everything when we go from
:+			 * directories to files at the same level, and
:+			 * when we go to files higher up in the directory
:+			 * hierarchy.
:+			 */
:+			if (removeAll && removeLevel >= p->fts_level) {
:+				removeAll = 0;
:+				removeLevel = -1;
:+			}
:+
: 			if (!fflag &&
: 			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
: 				continue;
:+
:+			/*
:+			 * Check if the user has just asked for every file
:+			 * at this directory level to be removed.
:+			 */
:+			if (removeAll && removeLevel == -1)
:+				removeLevel = p->fts_level - 1;
: 		}
: 
: 		rval = 0;
:@@ -425,16 +465,33 @@
: 	return (0);
: }
: 
:+static int
:+rm_get_answeer(void)
:+{
:+	int c;
:+	int answeer;
:+
:+	answeer = getchar();
:+
:+	c = answeer;
:+	while (c != '\n' && c != EOF)
:+		c = getchar();
:+
:+	return answeer;
:+}
: 
: static int
: check(const char *path, const char *name, struct stat *sp)
: {
:-	int ch, first;
:+	int answeer;
: 	char modep[15], *flagsp;
: 
:+	if (removeAll)
:+		return 1;
:+
: 	/* Check -i first. */
: 	if (iflag)
:-		fprintf(stderr, "remove %s? ", path);
:+		fprintf(stderr, "remove %s? [y/n/a]: ", path);
: 	else {
: 		/*
: 		 * If it's not a symbolic link and it's unwritable and we're
:@@ -453,7 +510,7 @@
: 		strmode(sp->st_mode, modep);
: 		if ((flagsp = fflagstostr(sp->st_flags)) == NULL)
: 			err(1, NULL);
:-		fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
:+		fprintf(stderr, "override %s%s%s/%s %s%sfor %s? [y/n/a]: ",
: 		    modep + 1, modep[9] == ' ' ? "" : " ",
: 		    user_from_uid(sp->st_uid, 0),
: 		    group_from_gid(sp->st_gid, 0),
:@@ -463,18 +520,20 @@
: 	}
: 	fflush(stderr);
: 
:-	first = ch = getchar();
:-	while (ch != '\n' && ch != EOF)
:-		ch = getchar();
:-	return (first == 'y' || first == 'Y');
:+	answeer = rm_get_answeer();
:+	if (answeer == 'a' || answeer == 'A') {
:+		removeAll = 1;
:+		return 1;
:+	} else if (answeer == 'y' || answeer == 'Y')
:+		return 1;
:+	return 0;
: }
: 
: static int
: check2(char **argv)
: {
: 	struct stat st;
:-	int first;
:-	int ch;
:+	int answeer;
: 	int fcount = 0;
: 	int dcount = 0;
: 	int i;
:@@ -490,8 +549,7 @@
: 			}
: 		}
: 	}
:-	first = 0;
:-	while (first != 'n' && first != 'N' && first != 'y' && first != 'Y') {
:+	for (;;) {
: 		if (dcount && rflag) {
: 			fprintf(stderr, "recursively remove");
: 			if (dcount == 1)
:@@ -507,16 +565,27 @@
: 		} else {
: 			return(1);
: 		}
:-		fprintf(stderr, "? ");
:+		fprintf(stderr, "? [y/n/a]: ");
: 		fflush(stderr);
: 
:-		first = ch = getchar();
:-		while (ch != '\n' && ch != EOF)
:-			ch = getchar();
:-		if (ch == EOF)
:+		answeer = rm_get_answeer();
:+		if (answeer == EOF)
:+			break;
:+		if (answeer == 'n' || answeer == 'N')
: 			break;
:+		if (answeer == 'y' || answeer == 'Y')
:+			return 1;
:+		if (answeer == 'a' || answeer == 'A') {
:+			/*
:+			 * Since the user specified the -I flag and answeered
:+			 * "all" to this question, do not prompt them for
:+			 * confirmation again.
:+			 */
:+			fflag = 1;
:+			return 1;
:+		}
: 	}
:-	return (first == 'y' || first == 'Y');
:+	return 0;
: }
: 
: #define ISDOT(a)	((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
:
:--------------090304040006040702060209--
:






More information about the Submit mailing list