diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-12-27 17:47:37 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2021-01-30 17:13:33 +0000 |
commit | b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch) | |
tree | 6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libcmd/common/rm.c | |
parent | df36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff) | |
download | illumos-joyent-b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f.tar.gz |
13405 ksh93 update to 2012-08-01
13434 sh: mishandles backslash as last character of a block of input
11750 ksh mkdir builtin doesn't honor special file permissions
9199 ksh93 builtin *grep -v mishandles blank lines, blows up libgcrypt-config
6756 sh (and ksh) have issues with ${1+"$@"}
6520 ksh: sleep could wait forever
4860 ksh93: core in printf
3791 /bin/sh's builtin 'rm' busted: 'rm -f' without arguments returns error
1047 ksh overwrites child core files
880 ksh93 coredumps on 'unset'
499 "interrupted system call" when using "tee" builtin in ksh
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Reviewed by: Dominik Hassler <hadfl@omnios.org>
Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libcmd/common/rm.c')
-rw-r--r-- | usr/src/lib/libcmd/common/rm.c | 424 |
1 files changed, 0 insertions, 424 deletions
diff --git a/usr/src/lib/libcmd/common/rm.c b/usr/src/lib/libcmd/common/rm.c deleted file mode 100644 index dfcb13f3fc..0000000000 --- a/usr/src/lib/libcmd/common/rm.c +++ /dev/null @@ -1,424 +0,0 @@ -/*********************************************************************** -* * -* This software is part of the ast package * -* Copyright (c) 1992-2010 AT&T Intellectual Property * -* and is licensed under the * -* Common Public License, Version 1.0 * -* by AT&T Intellectual Property * -* * -* A copy of the License is available at * -* http://www.opensource.org/licenses/cpl1.0.txt * -* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * -* * -* Information and Software Systems Research * -* AT&T Research * -* Florham Park NJ * -* * -* Glenn Fowler <gsf@research.att.com> * -* David Korn <dgk@research.att.com> * -* * -***********************************************************************/ -#pragma prototyped -/* - * Glenn Fowler - * AT&T Research - * - * rm [-fir] [file ...] - */ - -static const char usage[] = -"[-?\n@(#)$Id: rm (AT&T Research) 2009-06-18 $\n]" -USAGE_LICENSE -"[+NAME?rm - remove files]" -"[+DESCRIPTION?\brm\b removes the named \afile\a arguments. By default it" -" does not remove directories. If a file is unwritable, the" -" standard input is a terminal, and the \b--force\b option is not" -" given, \brm\b prompts the user for whether to remove the file." -" An affirmative response (\by\b or \bY\b) removes the file, a quit" -" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and" -" all other responses skip the current file.]" - -"[c|F:clear|clobber?Clear the contents of each file before removing by" -" writing a 0 filled buffer the same size as the file, executing" -" \bfsync\b(2) and closing before attempting to remove. Implemented" -" only on systems that support \bfsync\b(2).]" -"[d:directory?\bremove\b(3) (or \bunlink\b(2)) directories rather than" -" \brmdir\b(2), and don't require that they be empty before removal." -" The caller requires sufficient privilege, not to mention a strong" -" constitution, to use this option. Even though the directory must" -" not be empty, \brm\b still attempts to empty it before removal.]" -"[f:force?Ignore nonexistent files and never prompt the user.]" -"[i:interactive|prompt?Prompt whether to remove each file." -" An affirmative response (\by\b or \bY\b) removes the file, a quit" -" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and" -" all other responses skip the current file.]" -"[r|R:recursive?Remove the contents of directories recursively.]" -"[u:unconditional?If \b--recursive\b and \b--force\b are also enabled then" -" the owner read, write and execute modes are enabled (if not already" -" enabled) for each directory before attempting to remove directory" -" contents.]" -"[v:verbose?Print the name of each file before removing it.]" - -"\n" -"\nfile ...\n" -"\n" - -"[+SEE ALSO?\bmv\b(1), \brmdir\b(2), \bunlink\b(2), \bremove\b(3)]" -; - -#include <cmd.h> -#include <ls.h> -#include <fts_fix.h> -#include <fs3d.h> - -#define RM_ENTRY 1 - -#define beenhere(f) (((f)->fts_number>>1)==(f)->fts_statp->st_nlink) -#define isempty(f) (!((f)->fts_number&RM_ENTRY)) -#define nonempty(f) ((f)->fts_parent->fts_number|=RM_ENTRY) -#define pathchunk(n) roundof(n,1024) -#define retry(f) ((f)->fts_number=((f)->fts_statp->st_nlink<<1)) - -typedef struct State_s /* program state */ -{ - void* context; /* builtin context */ - int clobber; /* clear out file data first */ - int directory; /* remove(dir) not rmdir(dir) */ - int force; /* force actions */ - int fs3d; /* 3d enabled */ - int interactive; /* prompt for approval */ - int recursive; /* remove subtrees too */ - int terminal; /* attached to terminal */ - int uid; /* caller uid */ - int unconditional; /* enable dir rwx on preorder */ - int verbose; /* display each file */ -#if _lib_fsync - char buf[SF_BUFSIZE];/* clobber buffer */ -#endif -} State_t; - -/* - * remove a single file - */ - -static int -rm(State_t* state, register FTSENT* ent) -{ - register char* path; - register int n; - int v; - struct stat st; - - if (ent->fts_info == FTS_NS || ent->fts_info == FTS_ERR || ent->fts_info == FTS_SLNONE) - { - if (!state->force) - error(2, "%s: not found", ent->fts_path); - } - else if (state->fs3d && iview(ent->fts_statp)) - fts_set(NiL, ent, FTS_SKIP); - else switch (ent->fts_info) - { - case FTS_DNR: - case FTS_DNX: - if (state->unconditional) - { - if (!chmod(ent->fts_name, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU)) - { - fts_set(NiL, ent, FTS_AGAIN); - break; - } - error_info.errors++; - } - else if (!state->force) - error(2, "%s: cannot %s directory", ent->fts_path, (ent->fts_info & FTS_NR) ? "read" : "search"); - else - error_info.errors++; - fts_set(NiL, ent, FTS_SKIP); - nonempty(ent); - break; - case FTS_D: - case FTS_DC: - path = ent->fts_name; - if (path[0] == '.' && (!path[1] || path[1] == '.' && !path[2]) && (ent->fts_level > 0 || path[1])) - { - fts_set(NiL, ent, FTS_SKIP); - if (!state->force) - error(2, "%s: cannot remove", ent->fts_path); - else - error_info.errors++; - break; - } - if (!state->recursive) - { - fts_set(NiL, ent, FTS_SKIP); - error(2, "%s: directory", ent->fts_path); - break; - } - if (!beenhere(ent)) - { - if (state->unconditional && (ent->fts_statp->st_mode ^ S_IRWXU)) - chmod(path, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU); - if (ent->fts_level > 0) - { - char* s; - - if (ent->fts_accpath == ent->fts_name || !(s = strrchr(ent->fts_accpath, '/'))) - v = !stat(".", &st); - else - { - path = ent->fts_accpath; - *s = 0; - v = !stat(path, &st); - *s = '/'; - } - if (v) - v = st.st_nlink <= 2 || st.st_ino == ent->fts_parent->fts_statp->st_ino && st.st_dev == ent->fts_parent->fts_statp->st_dev || strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'l'); - } - else - v = 1; - if (v) - { - if (state->interactive) - { - if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0 || sh_checksig(state->context)) - return -1; - if (v > 0) - { - fts_set(NiL, ent, FTS_SKIP); - nonempty(ent); - } - } - if (ent->fts_info == FTS_D) - break; - } - else - { - ent->fts_info = FTS_DC; - error(1, "%s: hard link to directory", ent->fts_path); - } - } - else if (ent->fts_info == FTS_D) - break; - /*FALLTHROUGH*/ - case FTS_DP: - if (isempty(ent) || state->directory) - { - path = ent->fts_name; - if (path[0] != '.' || path[1]) - { - path = ent->fts_accpath; - if (state->verbose) - sfputr(sfstdout, ent->fts_path, '\n'); - if ((ent->fts_info == FTS_DC || state->directory) ? remove(path) : rmdir(path)) - switch (errno) - { - case ENOENT: - break; - case EEXIST: -#if defined(ENOTEMPTY) && (ENOTEMPTY) != (EEXIST) - case ENOTEMPTY: -#endif - if (ent->fts_info == FTS_DP && !beenhere(ent)) - { - retry(ent); - fts_set(NiL, ent, FTS_AGAIN); - break; - } - /*FALLTHROUGH*/ - default: - nonempty(ent); - if (!state->force) - error(ERROR_SYSTEM|2, "%s: directory not removed", ent->fts_path); - else - error_info.errors++; - break; - } - } - else if (!state->force) - error(2, "%s: cannot remove", ent->fts_path); - else - error_info.errors++; - } - else - { - nonempty(ent); - if (!state->force) - error(2, "%s: directory not removed", ent->fts_path); - else - error_info.errors++; - } - break; - default: - path = ent->fts_accpath; - if (state->verbose) - sfputr(sfstdout, ent->fts_path, '\n'); - if (state->interactive) - { - if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0 || sh_checksig(state->context)) - return -1; - if (v > 0) - { - nonempty(ent); - break; - } - } - else if (!state->force && state->terminal && S_ISREG(ent->fts_statp->st_mode)) - { - if ((n = open(path, O_RDWR)) < 0) - { - if ( -#ifdef ENOENT - errno != ENOENT && -#endif -#ifdef EROFS - errno != EROFS && -#endif - (v = astquery(-1, "override protection %s for %s? ", -#ifdef ETXTBSY - errno == ETXTBSY ? "``running program''" : -#endif - ent->fts_statp->st_uid != state->uid ? "``not owner''" : - fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0 || - sh_checksig(state->context)) - return -1; - if (v > 0) - { - nonempty(ent); - break; - } - } - else - close(n); - } -#if _lib_fsync - if (state->clobber && S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_size > 0) - { - if ((n = open(path, O_WRONLY)) < 0) - error(ERROR_SYSTEM|2, "%s: cannot clear data", ent->fts_path); - else - { - off_t c = ent->fts_statp->st_size; - - for (;;) - { - if (write(n, state->buf, sizeof(state->buf)) != sizeof(state->buf)) - { - error(ERROR_SYSTEM|2, "%s: data clear error", ent->fts_path); - break; - } - if (c <= sizeof(state->buf)) - break; - c -= sizeof(state->buf); - } - fsync(n); - close(n); - } - } -#endif - if (remove(path)) - { - nonempty(ent); - switch (errno) - { - case ENOENT: - break; - default: - if (!state->force || state->interactive) - error(ERROR_SYSTEM|2, "%s: not removed", ent->fts_path); - else - error_info.errors++; - break; - } - } - break; - } - return 0; -} - -int -b_rm(int argc, register char** argv, void* context) -{ - State_t state; - FTS* fts; - FTSENT* ent; - int set3d; - - cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY); - memset(&state, 0, sizeof(state)); - state.context = context; - state.fs3d = fs3d(FS3D_TEST); - state.terminal = isatty(0); - for (;;) - { - switch (optget(argv, usage)) - { - case 'd': - state.directory = 1; - continue; - case 'f': - state.force = 1; - state.interactive = 0; - continue; - case 'i': - state.interactive = 1; - state.force = 0; - continue; - case 'r': - case 'R': - state.recursive = 1; - continue; - case 'F': -#if _lib_fsync - state.clobber = 1; -#else - error(1, "%s not implemented on this system", opt_info.name); -#endif - continue; - case 'u': - state.unconditional = 1; - continue; - case 'v': - state.verbose = 1; - continue; - case '?': - error(ERROR_USAGE|4, "%s", opt_info.arg); - continue; - case ':': - error(2, "%s", opt_info.arg); - continue; - } - break; - } - argv += opt_info.index; - if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--")) - argv++; - if (error_info.errors || !*argv) - error(ERROR_USAGE|4, "%s", optusage(NiL)); - - /* - * do it - */ - - if (state.interactive) - state.verbose = 0; - state.uid = geteuid(); - state.unconditional = state.unconditional && state.recursive && state.force; - if (state.recursive && state.fs3d) - { - set3d = state.fs3d; - state.fs3d = 0; - fs3d(0); - } - else - set3d = 0; - if (fts = fts_open(argv, FTS_PHYSICAL, NiL)) - { - while (!sh_checksig(context) && (ent = fts_read(fts)) && !rm(&state, ent)); - fts_close(fts); - } - else if (!state.force) - error(ERROR_SYSTEM|2, "%s: cannot remove", argv[0]); - if (set3d) - fs3d(set3d); - return error_info.errors != 0; -} |