rm.c revision 996aa81675f6b63ed02041243b97e61ee7bd51d2
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * CDDL HEADER START
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * The contents of this file are subject to the terms of the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Common Development and Distribution License (the "License").
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * You may not use this file except in compliance with the License.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * or http://www.opensolaris.org/os/licensing.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * See the License for the specific language governing permissions
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * and limitations under the License.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * When distributing Covered Code, include this CDDL HEADER in each
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If applicable, add the following below this CDDL HEADER, with the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * fields enclosed by brackets "[]" replaced with your own identifying
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * information: Portions Copyright [yyyy] [name of copyright owner]
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * CDDL HEADER END
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Use is subject to license terms.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* All Rights Reserved */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#pragma ident "%Z%%M% %I% %E% SMI"
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * rm [-fiRr] file ...
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <stdio.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <fcntl.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <string.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <sys/types.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <sys/stat.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <dirent.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <limits.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <locale.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <langinfo.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <unistd.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <stdlib.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <errno.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <sys/resource.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <sys/avl.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#include <libcmdutils.h>
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define ARGCNT 5 /* Number of arguments */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define CHILD 0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define DIRECTORY ((buffer.st_mode&S_IFMT) == S_IFDIR)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define SYMLINK ((buffer.st_mode&S_IFMT) == S_IFLNK)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define FAIL -1
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define MAXFORK 100 /* Maximum number of forking attempts */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define NAMESIZE MAXNAMLEN + 1 /* "/" + (file name size) */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define TRUE 1
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define FALSE 0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define WRITE 02
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define SEARCH 07
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int interactive, recursive, silent; /* flags for command line options */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int rm(char *, int);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int undir(char *, int, dev_t, ino_t);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int yes(void);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int mypath(dev_t, ino_t);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char yeschr[SCHAR_MAX + 2];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char nochr[SCHAR_MAX + 2];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char *fullpath;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int initdirfd;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void push_name(char *name, int first);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int pop_name(int first);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void force_chdir(char *);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void ch_dir(char *);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char *get_filename(char *name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void chdir_init(void);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void check_initdir(void);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void cleanup(void);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char *cwd; /* pathname of init dir, from getcwd() */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic rlim_t maxfiles; /* maximum number of open files */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int first_dir = 1; /* flag set when first trying to remove a dir */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* flag set when can't get dev/inode of a parent dir */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int parent_err = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic avl_tree_t *tree; /* tree to keep track of nodes visited */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstruct dir_id {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync dev_t dev;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ino_t inode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct dir_id *next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync};
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * initdir is the first of a linked list of structures
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * containing unique identifying device and inode numbers for
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * each directory, from the initial dir up to the root.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * current_dir is a pointer to the most recent directory pushed
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * on during a recursive rm() call.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic struct dir_id initdir, *current_dir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncint
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncmain(int argc, char *argv[])
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync extern int optind;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int errflg = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int c;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct rlimit rl;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) setlocale(LC_ALL, "");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) textdomain(TEXT_DOMAIN);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while ((c = getopt(argc, argv, "frRi")) != EOF)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync switch (c) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 'f':
b025d5f11836934ade517ff53604078b5aff12e5vboxsync silent = TRUE;
b025d5f11836934ade517ff53604078b5aff12e5vboxsync#ifdef XPG4
b025d5f11836934ade517ff53604078b5aff12e5vboxsync interactive = FALSE;
b025d5f11836934ade517ff53604078b5aff12e5vboxsync#endif
b025d5f11836934ade517ff53604078b5aff12e5vboxsync break;
b025d5f11836934ade517ff53604078b5aff12e5vboxsync case 'i':
b025d5f11836934ade517ff53604078b5aff12e5vboxsync interactive = TRUE;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#ifdef XPG4
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync silent = FALSE;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 'r':
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 'R':
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync recursive = TRUE;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case '?':
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync errflg = 1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * For BSD compatibility allow '-' to delimit the end
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * of options. However, if options were already explicitly
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * terminated with '--', then treat '-' literally: otherwise,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * "rm -- -" won't remove '-'.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (optind < argc &&
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync strcmp(argv[optind], "-") == 0 &&
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync strcmp(argv[optind - 1], "--") != 0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync optind++;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync argc -= optind;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync argv = &argv[optind];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((argc < 1 && !silent) || errflg) {
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("usage: rm [-fiRr] file ...\n"));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (getrlimit(RLIMIT_NOFILE, &rl)) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("getrlimit");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync maxfiles = rl.rlim_cur - 2;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while (argc-- > 0) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync tree = NULL;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Retry if rm() fails due to bad chdir */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while (rm(*argv, 1) < 0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync argv++;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync destroy_tree(tree);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (errcode ? 2 : 0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* NOTREACHED */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncrm(char *path, int first)
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct stat buffer;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char *filepath;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char *p;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char resolved_path[PATH_MAX];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Check file to see if it exists.
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (lstat(path, &buffer) == FAIL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!silent) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror(path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* prevent removal of / but allow removal of sym-links */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!S_ISLNK(buffer.st_mode) && realpath(path, resolved_path) != NULL &&
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync strcmp(resolved_path, "/") == 0) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm of %s is not allowed\n"), resolved_path);
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync errcode++;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* prevent removal of . or .. (directly) */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (p = strrchr(path, '/'))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync p++;
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync else
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync p = path;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (strcmp(".", p) == 0 || strcmp("..", p) == 0) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm of %s is not allowed\n"), path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync errcode++;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync * If it's a directory, remove its contents.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (DIRECTORY) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If "-r" wasn't specified, trying to remove directories
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * is an error.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync if (!recursive) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: %s is a directory\n"), path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync if (first_dir) {
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync check_initdir();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync current_dir = NULL;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync first_dir = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (undir(path, first, buffer.st_dev, buffer.st_ino));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync filepath = get_filename(path);
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync /*
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync * If interactive, ask for acknowledgement.
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync *
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync * TRANSLATION_NOTE - The following message will contain the
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync * first character of the strings for "yes" and "no" defined
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync * in the file "nl_langinfo.po". After substitution, the
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync * message will appear as follows:
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync * rm: remove <filename> (y/n)?
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync * For example, in German, this will appear as
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync * rm: l�schen <filename> (j/n)?
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync * where j=ja, n=nein, <filename>=the file to be removed
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync *
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync */
37bfd8dde815650f55275bc1d9912c6bfcbbe5cdvboxsync
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync if (interactive) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync (void) fprintf(stderr, gettext("rm: remove %s (%s/%s)? "),
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync filepath, yeschr, nochr);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync if (!yes()) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync free(filepath);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return (0);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync } else if (!silent) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync /*
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * If not silent, and stdin is a terminal, and there's
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * no write access, and the file isn't a symbolic link,
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * ask for permission.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync *
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * TRANSLATION_NOTE - The following message will contain the
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * first character of the strings for "yes" and "no" defined
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * in the file "nl_langinfo.po". After substitution, the
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * message will appear as follows:
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * rm: <filename>: override protection XXX (y/n)?
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync * where XXX is the permission mode bits of the file in octal
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * and <filename> is the file to be removed
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync *
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync */
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync if (!SYMLINK && access(path, W_OK) == FAIL &&
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync isatty(fileno(stdin))) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync (void) printf(
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync gettext("rm: %s: override protection %o (%s/%s)? "),
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync filepath, buffer.st_mode & 0777, yeschr, nochr);
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync /*
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * If permission isn't given, skip the file.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync */
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync if (!yes()) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync free(filepath);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return (0);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync /*
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * If the unlink fails, inform the user. For /usr/bin/rm, only inform
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * the user if interactive or not silent.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * If unlink fails with errno = ENOENT because file was removed
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * in between the lstat call and unlink don't inform the user and
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync * don't change errcode.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync */
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync if (unlink(path) == FAIL) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync if (errno == ENOENT) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync free(filepath);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return (0);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync#ifndef XPG4
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync if (!silent || interactive) {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync#endif
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync (void) fprintf(stderr,
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync gettext("rm: %s not removed: "), filepath);
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync perror("");
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync#ifndef XPG4
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync#endif
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync ++errcode;
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync }
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync free(filepath);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return (0);
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync}
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsyncstatic int
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsyncundir(char *path, int first, dev_t dev, ino_t ino)
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync{
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync char *newpath;
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync DIR *name;
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync struct dirent *direct;
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync int ismypath;
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync int ret;
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync int chdir_failed = 0;
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync int bad_chdir = 0;
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync size_t len;
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync push_name(path, first);
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If interactive and this file isn't in the path of the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * current working directory, ask for acknowledgement.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * TRANSLATION_NOTE - The following message will contain the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * first character of the strings for "yes" and "no" defined
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * in the file "nl_langinfo.po". After substitution, the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * message will appear as follows:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * rm: examine files in directory <directoryname> (y/n)?
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * where <directoryname> is the directory to be removed
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ismypath = mypath(dev, ino);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (interactive) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: examine files in directory %s (%s/%s)? "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath, yeschr, nochr);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If the answer is no, skip the directory.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!yes())
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#ifdef XPG4
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * XCU4 and POSIX.2: If not interactive and file is not in the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * path of the current working directory, check to see whether
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * or not directory is readable or writable and if not,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * prompt user for response.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!interactive && !ismypath &&
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (access(path, W_OK|X_OK) == FAIL) && isatty(fileno(stdin))) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!silent) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext(
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "rm: examine files in directory %s (%s/%s)? "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath, yeschr, nochr);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If the answer is no, skip the directory.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!yes())
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Add this node to the search tree so we don't
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * get into a endless loop. If the add fails then
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * we have visited this node before.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ret = add_tnode(&tree, dev, ino);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (ret != 1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (ret == 0) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cycle detected for %s\n"),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else if (ret == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("rm");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync errcode++;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Open the directory for reading.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((name = opendir(path)) == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int saveerrno = errno;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If interactive, ask for acknowledgement.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (interactive) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Print an error message that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * we could not read the directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * as the user wanted to examine
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * files in the directory. Only
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * affect the error status if
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * user doesn't want to remove the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * directory as we still may be able
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * remove the directory successfully.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext(
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "rm: cannot read directory %s: "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync errno = saveerrno;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext(
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "rm: remove %s: (%s/%s)? "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath, yeschr, nochr);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!yes()) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If the directory is empty, we may be able to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * go ahead and remove it.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (rmdir(path) == FAIL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (interactive) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int rmdirerr = errno;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext(
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "rm: Unable to remove directory %s: "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync errno = rmdirerr;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext(
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "rm: cannot read directory %s: "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync errno = saveerrno;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Continue to next file/directory rather than exit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * XCU4 requires that rm -r descend the directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * hierarchy without regard to PATH_MAX. If we can't
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * chdir() do not increment error counter and do not
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * print message.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * However, if we cannot chdir because someone has taken away
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * execute access we may still be able to delete the directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * if it's empty. The old rm could do this.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (chdir(path) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync chdir_failed = 1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Read every directory entry.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while ((direct = readdir(name)) != NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Ignore "." and ".." entries.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (strcmp(direct->d_name, ".") == 0 ||
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync strcmp(direct->d_name, "..") == 0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync continue;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Try to remove the file.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync len = strlen(direct->d_name) + 1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (chdir_failed) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync len += strlen(path) + 2;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync newpath = malloc(len);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (newpath == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Insufficient memory.\n"));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!chdir_failed) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) strcpy(newpath, direct->d_name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) snprintf(newpath, len, "%s/%s",
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync path, direct->d_name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If a spare file descriptor is available, just call the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * "rm" function with the file name; otherwise close the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * directory and reopen it when the child is removed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (name->dd_fd >= maxfiles) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) closedir(name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (rm(newpath, 0) < 0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync bad_chdir = -1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!chdir_failed)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync name = opendir(".");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync else
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync name = opendir(path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (name == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot read directory %s: "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else if (rm(newpath, 0) < 0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync bad_chdir = -1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync free(newpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (bad_chdir)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Close the directory we just finished reading.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) closedir(name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (bad_chdir)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (-1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * The contents of the directory have been removed. If the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * directory itself is in the path of the current working
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * directory, don't try to remove it.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * When the directory itself is the current working directory, mypath()
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * has a return code == 2.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * XCU4: Because we've descended the directory hierarchy in order
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * to avoid PATH_MAX limitation, we must now start ascending
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * one level at a time and remove files/directories.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!chdir_failed) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (first)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync chdir_init();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync else if (chdir("..") == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot change to parent of "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "directory %s: "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync switch (ismypath) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 3:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 2:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Cannot remove any directory in the path "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "of the current working directory\n%s\n"), fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 1:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync case 0:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If interactive, ask for acknowledgement.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (interactive) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext("rm: remove %s: (%s/%s)? "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath, yeschr, nochr);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!yes())
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (rmdir(path) == FAIL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Unable to remove directory %s: "),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ++errcode;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (pop_name(first));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncyes(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int i, b;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char ans[SCHAR_MAX + 1];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (i = 0; ; i++) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync b = getchar();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (b == '\n' || b == '\0' || b == EOF) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ans[i] = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (i < SCHAR_MAX)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ans[i] = b;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (i >= SCHAR_MAX) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync i = SCHAR_MAX;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ans[SCHAR_MAX] = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((i == 0) | (strncmp(yeschr, ans, i)))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncmypath(dev_t dev, ino_t ino)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct dir_id *curdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Check to see if this is our current directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Indicated by return 2;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (dev == initdir.dev && ino == initdir.inode) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir = initdir.next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while (curdir != NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If we find a match, the directory (dev, ino) passed to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * mypath() is an ancestor of ours. Indicated by return 3.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (curdir->dev == dev && curdir->inode == ino)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (3);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir = curdir->next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * parent_err indicates we couldn't stat or chdir to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * one of our parent dirs, so the linked list of dir_id structs
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * is incomplete
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (parent_err) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#ifndef XPG4
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!silent || interactive) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext("rm: cannot determine "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "if this is an ancestor of the current "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "working directory\n%s\n"), fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#ifndef XPG4
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* assume it is. least dangerous */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int maxlen;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int curlen;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncget_filename(char *name)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char *path;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync size_t len;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (fullpath == NULL || *fullpath == '\0') {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync path = strdup(name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (path == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Insufficient memory.\n"));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync len = strlen(fullpath) + strlen(name) + 2;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync path = malloc(len);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (path == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Insufficient memory.\n"));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) snprintf(path, len, "%s/%s", fullpath, name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncpush_name(char *name, int first)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int namelen;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct stat buffer;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct dir_id *newdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync namelen = strlen(name) + 1; /* 1 for "/" */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((curlen + namelen) >= maxlen) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync maxlen += PATH_MAX;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath = (char *)realloc(fullpath, (size_t)(maxlen + 1));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (first) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) strcpy(fullpath, name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) strcat(fullpath, "/");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) strcat(fullpath, name);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curlen = strlen(fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (stat(".", &buffer) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot stat current directory: "));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((newdir = malloc(sizeof (struct dir_id))) == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Insufficient memory.\n"));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync newdir->dev = buffer.st_dev;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync newdir->inode = buffer.st_ino;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync newdir->next = current_dir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync current_dir = newdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncpop_name(int first)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int retval = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char *slash;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct stat buffer;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct dir_id *remove_dir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (first) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *fullpath = '\0';
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync slash = strrchr(fullpath, '/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (slash)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *slash = '\0';
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync else
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *fullpath = '\0';
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curlen = strlen(fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (stat(".", &buffer) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot stat current directory: "));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * For each pop operation, verify that the device and inode numbers
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * of "." match the numbers recorded before the chdir was done into
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * the directory. If they do not match, it is an indication of
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * possible malicious activity and rm has chdir to an unintended
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((current_dir->inode != buffer.st_ino) || (current_dir->dev !=
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync buffer.st_dev)) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext("rm: WARNING: "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "A subdirectory of %s was moved or linked to "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "another directory during the execution of rm\n"),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fullpath);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync retval = -1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync remove_dir = current_dir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync current_dir = current_dir->next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync free(remove_dir);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return (retval);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncforce_chdir(char *dirname)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync char *pathname, *mp, *tp;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* use pathname instead of dirname, so dirname won't be modified */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((pathname = strdup(dirname)) == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr, gettext("rm: strdup: "));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* pathname is an absolute full path from getcwd() */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync mp = pathname;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while (mp) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync tp = strchr(mp, '/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (strlen(mp) >= PATH_MAX) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * after the first iteration through this
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * loop, the below will NULL out the '/'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * which follows the first dir on pathname
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *tp = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync tp++;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (*mp == NULL)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ch_dir("/");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync else
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * mp points to the start of a dirname,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * terminated by NULL, so ch_dir()
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * here will move down one directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ch_dir(mp);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * reset mp to the start of the dirname
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * which follows the one we just chdir'd to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync mp = tp;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync continue; /* probably can remove this */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ch_dir(mp);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync free(pathname);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncch_dir(char *dirname)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (chdir(dirname) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot change to %s directory: "), dirname);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncchdir_init(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Go back to init dir--the dir from where rm was executed--using
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * one of two methods, depending on which method works
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * for the given permissions of the init dir and its
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * parent directories.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (initdirfd != -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (fchdir(initdirfd) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot change to starting "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "directory: "));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (strlen(cwd) < PATH_MAX)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ch_dir(cwd);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync else
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync force_chdir(cwd);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * check_initdir -
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * is only called the first time rm tries to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * remove a directory. It saves the current directory, i.e.,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * init dir, so we can go back to it after traversing elsewhere.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * It also saves all the device and inode numbers of each
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * dir from the initial dir back to the root in a linked list, so we
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * can later check, via mypath(), if we are trying to remove our current
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * dir or an ancestor.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsynccheck_initdir(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync{
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int size; /* size allocated for pathname of init dir (cwd) */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct stat buffer;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct dir_id *lastdir, *curdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * We need to save where we currently are (the "init dir") so
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * we can return after traversing down directories we're
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * removing. Two methods are attempted:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * 1) open() the initial dir so we can use the fd
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * to fchdir() back. This requires read permission
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * on the initial dir.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * 2) getcwd() so we can chdir() to go back. This
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * requires search (x) permission on the init dir,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * and read and search permission on all parent dirs. Also,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * getcwd() will not work if the init dir is > 341
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * directories deep (see open bugid 4033182 - getcwd needs
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * to work for pathnames of any depth).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If neither method works, we can't remove any directories
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * and rm will fail.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * For future enhancement, a possible 3rd option to use
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * would be to fork a process to remove a directory,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * eliminating the need to chdir back to the initial directory
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * and eliminating the permission restrictions on the initial dir
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * or its parent dirs.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync initdirfd = open(".", O_RDONLY);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (initdirfd == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync size = PATH_MAX;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while ((cwd = getcwd(NULL, size)) == NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (errno == ERANGE) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync size = PATH_MAX + size;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync continue;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot open starting "
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync "directory: "));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("pwd");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * since we exit on error here, we're guaranteed to at least
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * have info in the first dir_id struct, initdir
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (stat(".", &buffer) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: cannot stat current directory: "));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync perror("");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(2);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync initdir.dev = buffer.st_dev;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync initdir.inode = buffer.st_ino;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync initdir.next = NULL;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync lastdir = &initdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Starting from current working directory, walk toward the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * root, looking at each directory along the way.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (;;) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (chdir("..") == -1 || lstat(".", &buffer) == -1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync parent_err = 1;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((lastdir->next = malloc(sizeof (struct dir_id))) ==
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (void) fprintf(stderr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync gettext("rm: Insufficient memory.\n"));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cleanup();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir = lastdir->next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir->dev = buffer.st_dev;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir->inode = buffer.st_ino;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir->next = NULL;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Stop when we reach the root; note that chdir("..")
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * at the root dir will stay in root. Get rid of
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * the redundant dir_id struct for root.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (curdir->dev == lastdir->dev && curdir->inode ==
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync lastdir->inode) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync lastdir->next = NULL;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync free(curdir);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync break;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* loop again to go back another level */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync lastdir = curdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* go back to init directory */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync chdir_init();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/*
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * cleanup the dynamically-allocated list of device numbers and inodes,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * if any. If initdir was never used, it is external and static so
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * it is guaranteed initialized to zero, thus initdir.next would be NULL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsynccleanup(void) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync struct dir_id *lastdir, *curdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir = initdir.next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while (curdir != NULL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync lastdir = curdir;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync curdir = curdir->next;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync free(lastdir);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync