[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