diff options
Diffstat (limited to 'usr/src/cmd/rm/rm.c')
-rw-r--r-- | usr/src/cmd/rm/rm.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/usr/src/cmd/rm/rm.c b/usr/src/cmd/rm/rm.c index bbdbadf588..bd53d48b75 100644 --- a/usr/src/cmd/rm/rm.c +++ b/usr/src/cmd/rm/rm.c @@ -18,15 +18,15 @@ * * CDDL HEADER END */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ - /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + #pragma ident "%Z%%M% %I% %E% SMI" /* @@ -46,6 +46,8 @@ #include <stdlib.h> #include <errno.h> #include <sys/resource.h> +#include <sys/avl.h> +#include <libcmdutils.h> #define ARGCNT 5 /* Number of arguments */ #define CHILD 0 @@ -87,6 +89,7 @@ static rlim_t maxfiles; /* maximum number of open files */ static int first_dir = 1; /* flag set when first trying to remove a dir */ /* flag set when can't get dev/inode of a parent dir */ static int parent_err = 0; +static avl_tree_t *tree; /* tree to keep track of nodes visited */ struct dir_id { dev_t dev; @@ -168,10 +171,11 @@ main(int argc, char *argv[]) maxfiles = rl.rlim_cur - 2; while (argc-- > 0) { + tree = NULL; rm(*argv, 1); argv++; + destroy_tree(tree); } - cleanup(); return (errcode ? 2 : 0); /* NOTREACHED */ @@ -239,7 +243,6 @@ rm(char *path, int first) undir(path, first, buffer.st_dev, buffer.st_ino); return; } - filepath = get_filename(path); /* @@ -329,6 +332,7 @@ undir(char *path, int first, dev_t dev, ino_t ino) DIR *name; struct dirent *direct; int ismypath; + int ret; int chdir_failed = 0; size_t len; @@ -386,6 +390,25 @@ undir(char *path, int first, dev_t dev, ino_t ino) #endif /* + * Add this node to the search tree so we don't + * get into a endless loop. If the add fails then + * we have visited this node before. + */ + ret = add_tnode(&tree, dev, ino); + if (ret != 1) { + if (ret == 0) { + (void) fprintf(stderr, + gettext("rm: cycle detected for %s\n"), + fullpath); + } else if (ret == -1) { + perror("rm"); + } + errcode++; + pop_name(first); + return; + } + + /* * Open the directory for reading. */ if ((name = opendir(path)) == NULL) { @@ -718,7 +741,6 @@ static void pop_name(int first) { char *slash; - if (first) { *fullpath = '\0'; return; @@ -941,7 +963,6 @@ check_homedir(void) static void cleanup(void) { - struct dir_id *lastdir, *curdir; curdir = homedir.next; |