rm.c revision 014a7923f9b48f6ab3ba1a38049a3dacddc587cb
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * CDDL HEADER START
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * The contents of this file are subject to the terms of the
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * Common Development and Distribution License (the "License").
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * You may not use this file except in compliance with the License.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * See the License for the specific language governing permissions
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * and limitations under the License.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * When distributing Covered Code, include this CDDL HEADER in each
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * If applicable, add the following below this CDDL HEADER, with the
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * fields enclosed by brackets "[]" replaced with your own identifying
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * information: Portions Copyright [yyyy] [name of copyright owner]
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * CDDL HEADER END
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * Use is subject to license terms.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson/* All Rights Reserved */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#pragma ident "%Z%%M% %I% %E% SMI"
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * rm [-fiRr] file ...
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#define DIRECTORY ((buffer.st_mode&S_IFMT) == S_IFDIR)
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#define SYMLINK ((buffer.st_mode&S_IFMT) == S_IFLNK)
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#define MAXFORK 100 /* Maximum number of forking attempts */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#define NAMESIZE MAXNAMLEN + 1 /* "/" + (file name size) */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic int interactive, recursive, silent; /* flags for command line options */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic void rm(char *, int);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic int yes(void);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic void force_chdir(char *);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic void ch_dir(char *);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic void chdir_home(void);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic void check_homedir(void);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic void cleanup(void);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic char *cwd; /* pathname of home dir, from getcwd() */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic rlim_t maxfiles; /* maximum number of open files */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic int first_dir = 1; /* flag set when first trying to remove a dir */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson /* flag set when can't get dev/inode of a parent dir */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic int parent_err = 0;
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilsonstatic avl_tree_t *tree; /* tree to keep track of nodes visited */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * homedir is the first of a linked list of structures
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * containing unique identifying device and inode numbers for
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * each directory, from the home dir up to the root.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson while ((c = getopt(argc, argv, "frRi")) != EOF)
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * For BSD compatibility allow '-' to delimit the end
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * of options. However, if options were already explicitly
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * terminated with '--', then treat '-' literally: otherwise,
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * "rm -- -" won't remove '-'.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson while (argc-- > 0) {
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson /* NOTREACHED */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * Check file to see if it exists.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson /* prevent removal of / but allow removal of sym-links */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson if (!S_ISLNK(buffer.st_mode) && realpath(path, resolved_path) != NULL &&
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson gettext("rm of %s is not allowed\n"), resolved_path);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson /* prevent removal of . or .. (directly) */
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson if (strcmp(".", p) == 0 || strcmp("..", p) == 0) {
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * If it's a directory, remove its contents.
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * If "-r" wasn't specified, trying to remove directories
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson * is an error.
if (interactive) {
if (!yes()) {
} else if (!silent) {
(void) printf(
if (!yes()) {
#ifndef XPG4
#ifndef XPG4
++errcode;
char *newpath;
int ismypath;
int ret;
int chdir_failed = 0;
if (interactive) {
if (!yes()) {
#ifdef XPG4
if (!silent) {
if (!yes()) {
if (ret == 0) {
fullpath);
errcode++;
if (interactive) {
fullpath);
if (!yes()) {
++errcode;
if (interactive) {
fullpath);
fullpath);
++errcode;
if (chdir_failed) {
cleanup();
if (!chdir_failed) {
if (!chdir_failed)
fullpath);
cleanup();
* one level at a time and remove files/directories.
if (!chdir_failed) {
if (first)
chdir_home();
fullpath);
cleanup();
switch (ismypath) {
++errcode;
++errcode;
if (interactive) {
if (!yes()) {
fullpath);
++errcode;
yes(void)
b = getchar();
ans[i] = 0;
if (i < SCHAR_MAX)
ans[i] = b;
if (i >= SCHAR_MAX) {
i = SCHAR_MAX;
if (parent_err) {
#ifndef XPG4
#ifndef XPG4
static int maxlen;
static int curlen;
char *path;
cleanup();
cleanup();
return (path);
int namelen;
if (first) {
char *slash;
if (first) {
if (slash)
cleanup();
while (mp) {
*tp = 0;
tp++;
cleanup();
chdir_home(void)
cleanup();
check_homedir(void)
NULL) {
cleanup();
chdir_home();
cleanup(void) {