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

看板DFBSD_submit作者時間21年前 (2004/12/19 03:32), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/7 (看更多)
This is a multi-part message in MIME format. --------------090304040006040702060209 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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--
文章代碼(AID): #11n8N500 (DFBSD_submit)
討論串 (同標題文章)
文章代碼(AID): #11n8N500 (DFBSD_submit)