diff options
Diffstat (limited to 'bin/rm')
| -rw-r--r-- | bin/rm/Makefile | 7 | ||||
| -rw-r--r-- | bin/rm/rm.1 | 137 | ||||
| -rw-r--r-- | bin/rm/rm.c | 294 |
3 files changed, 438 insertions, 0 deletions
diff --git a/bin/rm/Makefile b/bin/rm/Makefile new file mode 100644 index 000000000000..f34f55214399 --- /dev/null +++ b/bin/rm/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 5.3 (Berkeley) 12/8/90 + +PROG= rm +LDADD= -lutil +DPADD= ${LIBUTIL} + +.include <bsd.prog.mk> diff --git a/bin/rm/rm.1 b/bin/rm/rm.1 new file mode 100644 index 000000000000..ed4b10995fdd --- /dev/null +++ b/bin/rm/rm.1 @@ -0,0 +1,137 @@ +.\" Copyright (c) 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rm.1 6.9 (Berkeley) 7/27/91 +.\" +.Dd July 27, 1991 +.Dt RM 1 +.Os +.Sh NAME +.Nm rm +.Nd Remove directory entries. +.Sh SYNOPSIS +.Nm rm +.Op Fl f | Fl i +.Op Fl dRr +.Ar file ... +.Sh DESCRIPTION +The +.Nm rm +utility attempts to remove the non-directory type files specified on the +command line. +If the permissions of the file do not permit writing, and the standard +input device is a terminal, the user is prompted (on the standard error +output) for confirmation. +.Pp +The options are as follows: +.Bl -tag -width flag +.It Fl d +Attempt to remove directories as well as other types of files. +.It Fl f +Attempt to remove the files without prompting for confirmation, +regardless of the file's permissions. +If the file does not exist, do not display a diagnostic message or modify +the exit status to reflect an error. +The +.Fl f +option overrides any previous +.Fl i +options. +.It Fl i +Request confirmation before attempting to remove each file, regardless of +the file's permissions, or whether or not the standard input device is a +terminal. +The +.Fl i +option overrides any previous +.Fl f +options. +.It Fl R +Attempt to remove the file hierarchy rooted in each file argument. +The +.Fl R +option implies the +.Fl d +option. +If the +.Fl i +option is specified, the user is prompted for confirmation before +each directory's contents are processed (as well as before the attempt +is made to remove the directory). +If the user does not respond affirmatively, the file hierarchy rooted in +that directory is skipped. +.Pp +.It Fl r +Equivalent to +.Fl R . +.El +.Pp +The +.Nm rm +utility removes symbolic links, not the files referenced by the links. +.Pp +It is an error to attempt to remove the files ``.'' and ``..''. +.Pp +The +.Nm rm +utility exits 0 if all of the named files or file hierarchies were removed, +or if the +.Fl f +option was specified and all of the existing files or file hierarchies were +removed. +If an error occurs, +.Nm rm +exits with a value >0. +.Sh SEE ALSO +.Xr rmdir 1 , +.Xr unlink 2 , +.Xr fts 3 +.Sh COMPATIBILITY +The +.Nm rm +utility differs from historical implementations in that the +.Fl f +option only masks attempts to remove non-existent files instead of +masking a large variety of errors. +.Pp +Also, historical +.Bx +implementations prompted on the standard output, +not the standard error output. +.Sh STANDARDS +The +.Nm rm +command is expected to be +.St -p1003.2 +compatible. diff --git a/bin/rm/rm.c b/bin/rm/rm.c new file mode 100644 index 000000000000..6b65b0ce2842 --- /dev/null +++ b/bin/rm/rm.c @@ -0,0 +1,294 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1990 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rm.c 4.27 (Berkeley) 1/27/92"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/errno.h> +#include <fts.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +int dflag, fflag, iflag, retval, stdin_ok; + +/* + * rm -- + * This rm is different from historic rm's, but is expected to match + * POSIX 1003.2 behavior. The most visible difference is that -f + * has two specific effects now, ignore non-existent files and force + * file removal. + */ + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + int ch, rflag; + + rflag = 0; + while ((ch = getopt(argc, argv, "dfiRr")) != EOF) + switch(ch) { + case 'd': + dflag = 1; + break; + case 'f': + fflag = 1; + iflag = 0; + break; + case 'i': + fflag = 0; + iflag = 1; + break; + case 'R': + case 'r': /* compatibility */ + rflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + checkdot(argv); + if (!*argv) + exit(retval); + + stdin_ok = isatty(STDIN_FILENO); + + if (rflag) + rmtree(argv); + else + rmfile(argv); + exit(retval); +} + +rmtree(argv) + char **argv; +{ + register FTS *fts; + register FTSENT *p; + register int needstat; + struct stat sb; + + /* + * Remove a file hierarchy. If forcing removal (-f), or interactive + * (-i) or can't ask anyway (stdin_ok), don't stat the file. + */ + needstat = !fflag && !iflag && stdin_ok; + + /* + * If the -i option is specified, the user can skip on the pre-order + * visit. The fts_number field flags skipped directories. + */ +#define SKIPPED 1 + + if (!(fts = fts_open(argv, + needstat ? FTS_PHYSICAL : FTS_PHYSICAL|FTS_NOSTAT, + (int (*)())NULL))) { + (void)fprintf(stderr, "rm: %s.\n", strerror(errno)); + exit(1); + } + while (p = fts_read(fts)) { + switch(p->fts_info) { + case FTS_DNR: + case FTS_ERR: + error(p->fts_path, errno); + exit(1); + /* + * FTS_NS: assume that if can't stat the file, it can't be + * unlinked. + */ + case FTS_NS: + if (!needstat) + break; + if (!fflag || errno != ENOENT) + error(p->fts_path, errno); + continue; + /* Pre-order: give user chance to skip. */ + case FTS_D: + if (iflag && !check(p->fts_path, p->fts_accpath, + p->fts_statp)) { + (void)fts_set(fts, p, FTS_SKIP); + p->fts_number = SKIPPED; + } + continue; + /* Post-order: see if user skipped. */ + case FTS_DP: + if (p->fts_number == SKIPPED) + continue; + break; + } + + if (!fflag && + !check(p->fts_path, p->fts_accpath, p->fts_statp)) + continue; + + /* + * If we can't read or search the directory, may still be + * able to remove it. Don't print out the un{read,search}able + * message unless the remove fails. + */ + if (p->fts_info == FTS_DP || p->fts_info == FTS_DNR) { + if (!rmdir(p->fts_accpath)) + continue; + if (errno == ENOENT) { + if (fflag) + continue; + } else if (p->fts_info != FTS_DP) + (void)fprintf(stderr, + "rm: unable to read %s.\n", p->fts_path); + } else if (!unlink(p->fts_accpath) || fflag && errno == ENOENT) + continue; + error(p->fts_path, errno); + } +} + +rmfile(argv) + char **argv; +{ + register int df; + register char *f; + struct stat sb; + + df = dflag; + /* + * Remove a file. POSIX 1003.2 states that, by default, attempting + * to remove a directory is an error, so must always stat the file. + */ + while (f = *argv++) { + /* Assume if can't stat the file, can't unlink it. */ + if (lstat(f, &sb)) { + if (!fflag || errno != ENOENT) + error(f, errno); + continue; + } + if (S_ISDIR(sb.st_mode) && !df) { + (void)fprintf(stderr, "rm: %s: is a directory\n", f); + retval = 1; + continue; + } + if (!fflag && !check(f, f, &sb)) + continue; + if ((S_ISDIR(sb.st_mode) ? rmdir(f) : unlink(f)) && + (!fflag || errno != ENOENT)) + error(f, errno); + } +} + +check(path, name, sp) + char *path, *name; + struct stat *sp; +{ + register int first, ch; + char modep[15], *user_from_uid(), *group_from_gid(); + + /* Check -i first. */ + if (iflag) + (void)fprintf(stderr, "remove %s? ", path); + else { + /* + * If it's not a symbolic link and it's unwritable and we're + * talking to a terminal, ask. Symbolic links are excluded + * because their permissions are meaningless. + */ + if (S_ISLNK(sp->st_mode) || !stdin_ok || !access(name, W_OK)) + return(1); + strmode(sp->st_mode, modep); + (void)fprintf(stderr, "override %s%s%s/%s for %s? ", + modep + 1, modep[9] == ' ' ? "" : " ", + user_from_uid(sp->st_uid, 0), + group_from_gid(sp->st_gid, 0), path); + } + (void)fflush(stderr); + + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + return(first == 'y'); +} + +#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || (a)[1] == '.' && !(a)[2])) +checkdot(argv) + char **argv; +{ + register char *p, **t, **save; + int complained; + + complained = 0; + for (t = argv; *t;) { + if (p = rindex(*t, '/')) + ++p; + else + p = *t; + if (ISDOT(p)) { + if (!complained++) + (void)fprintf(stderr, + "rm: \".\" and \"..\" may not be removed.\n"); + retval = 1; + for (save = t; t[0] = t[1]; ++t); + t = save; + } else + ++t; + } +} + +error(name, val) + char *name; + int val; +{ + (void)fprintf(stderr, "rm: %s: %s.\n", name, strerror(val)); + retval = 1; +} + +usage() +{ + (void)fprintf(stderr, "usage: rm [-dfiRr] file ...\n"); + exit(1); +} |
