rm.c (ff2b18550948b1149db5d915293d7c25db25bba4) rm.c (014a7923f9b48f6ab3ba1a38049a3dacddc587cb)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 4 unchanged lines hidden (view full) ---

13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 4 unchanged lines hidden (view full) ---

13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22/* All Rights Reserved */
23
21
24
25/*
26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
22/*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28/* All Rights Reserved */
29
30#pragma ident "%Z%%M% %I% %E% SMI"
31
32/*
33 * rm [-fiRr] file ...
34 */
35
36#include <stdio.h>
37#include <fcntl.h>
38#include <string.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <dirent.h>
42#include <limits.h>
43#include <locale.h>
44#include <langinfo.h>
45#include <unistd.h>
46#include <stdlib.h>
47#include <errno.h>
48#include <sys/resource.h>
30#pragma ident "%Z%%M% %I% %E% SMI"
31
32/*
33 * rm [-fiRr] file ...
34 */
35
36#include <stdio.h>
37#include <fcntl.h>
38#include <string.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <dirent.h>
42#include <limits.h>
43#include <locale.h>
44#include <langinfo.h>
45#include <unistd.h>
46#include <stdlib.h>
47#include <errno.h>
48#include <sys/resource.h>
49#include <sys/avl.h>
50#include <libcmdutils.h>
49
50#define ARGCNT 5 /* Number of arguments */
51#define CHILD 0
52#define DIRECTORY ((buffer.st_mode&S_IFMT) == S_IFDIR)
53#define SYMLINK ((buffer.st_mode&S_IFMT) == S_IFLNK)
54#define FAIL -1
55#define MAXFORK 100 /* Maximum number of forking attempts */
56#define NAMESIZE MAXNAMLEN + 1 /* "/" + (file name size) */

--- 25 unchanged lines hidden (view full) ---

82static void check_homedir(void);
83static void cleanup(void);
84
85static char *cwd; /* pathname of home dir, from getcwd() */
86static rlim_t maxfiles; /* maximum number of open files */
87static int first_dir = 1; /* flag set when first trying to remove a dir */
88 /* flag set when can't get dev/inode of a parent dir */
89static int parent_err = 0;
51
52#define ARGCNT 5 /* Number of arguments */
53#define CHILD 0
54#define DIRECTORY ((buffer.st_mode&S_IFMT) == S_IFDIR)
55#define SYMLINK ((buffer.st_mode&S_IFMT) == S_IFLNK)
56#define FAIL -1
57#define MAXFORK 100 /* Maximum number of forking attempts */
58#define NAMESIZE MAXNAMLEN + 1 /* "/" + (file name size) */

--- 25 unchanged lines hidden (view full) ---

84static void check_homedir(void);
85static void cleanup(void);
86
87static char *cwd; /* pathname of home dir, from getcwd() */
88static rlim_t maxfiles; /* maximum number of open files */
89static int first_dir = 1; /* flag set when first trying to remove a dir */
90 /* flag set when can't get dev/inode of a parent dir */
91static int parent_err = 0;
92static avl_tree_t *tree; /* tree to keep track of nodes visited */
90
91struct dir_id {
92 dev_t dev;
93 ino_t inode;
94 struct dir_id *next;
95};
96
97 /*

--- 65 unchanged lines hidden (view full) ---

163
164 if (getrlimit(RLIMIT_NOFILE, &rl)) {
165 perror("getrlimit");
166 exit(2);
167 } else
168 maxfiles = rl.rlim_cur - 2;
169
170 while (argc-- > 0) {
93
94struct dir_id {
95 dev_t dev;
96 ino_t inode;
97 struct dir_id *next;
98};
99
100 /*

--- 65 unchanged lines hidden (view full) ---

166
167 if (getrlimit(RLIMIT_NOFILE, &rl)) {
168 perror("getrlimit");
169 exit(2);
170 } else
171 maxfiles = rl.rlim_cur - 2;
172
173 while (argc-- > 0) {
174 tree = NULL;
171 rm(*argv, 1);
172 argv++;
175 rm(*argv, 1);
176 argv++;
177 destroy_tree(tree);
173 }
178 }
174
175 cleanup();
176 return (errcode ? 2 : 0);
177 /* NOTREACHED */
178}
179
180static void
181rm(char *path, int first)
182{

--- 51 unchanged lines hidden (view full) ---

234 if (first_dir) {
235 check_homedir();
236 first_dir = 0;
237 }
238
239 undir(path, first, buffer.st_dev, buffer.st_ino);
240 return;
241 }
179 cleanup();
180 return (errcode ? 2 : 0);
181 /* NOTREACHED */
182}
183
184static void
185rm(char *path, int first)
186{

--- 51 unchanged lines hidden (view full) ---

238 if (first_dir) {
239 check_homedir();
240 first_dir = 0;
241 }
242
243 undir(path, first, buffer.st_dev, buffer.st_ino);
244 return;
245 }
242
243 filepath = get_filename(path);
244
245 /*
246 * If interactive, ask for acknowledgement.
247 *
248 * TRANSLATION_NOTE - The following message will contain the
249 * first character of the strings for "yes" and "no" defined
250 * in the file "nl_langinfo.po". After substitution, the

--- 73 unchanged lines hidden (view full) ---

324
325static void
326undir(char *path, int first, dev_t dev, ino_t ino)
327{
328 char *newpath;
329 DIR *name;
330 struct dirent *direct;
331 int ismypath;
246 filepath = get_filename(path);
247
248 /*
249 * If interactive, ask for acknowledgement.
250 *
251 * TRANSLATION_NOTE - The following message will contain the
252 * first character of the strings for "yes" and "no" defined
253 * in the file "nl_langinfo.po". After substitution, the

--- 73 unchanged lines hidden (view full) ---

327
328static void
329undir(char *path, int first, dev_t dev, ino_t ino)
330{
331 char *newpath;
332 DIR *name;
333 struct dirent *direct;
334 int ismypath;
335 int ret;
332 int chdir_failed = 0;
333 size_t len;
334
335 push_name(path, first);
336
337 /*
338 * If interactive and this file isn't in the path of the
339 * current working directory, ask for acknowledgement.

--- 41 unchanged lines hidden (view full) ---

381 pop_name(first);
382 return;
383 }
384 }
385 }
386#endif
387
388 /*
336 int chdir_failed = 0;
337 size_t len;
338
339 push_name(path, first);
340
341 /*
342 * If interactive and this file isn't in the path of the
343 * current working directory, ask for acknowledgement.

--- 41 unchanged lines hidden (view full) ---

385 pop_name(first);
386 return;
387 }
388 }
389 }
390#endif
391
392 /*
393 * Add this node to the search tree so we don't
394 * get into a endless loop. If the add fails then
395 * we have visited this node before.
396 */
397 ret = add_tnode(&tree, dev, ino);
398 if (ret != 1) {
399 if (ret == 0) {
400 (void) fprintf(stderr,
401 gettext("rm: cycle detected for %s\n"),
402 fullpath);
403 } else if (ret == -1) {
404 perror("rm");
405 }
406 errcode++;
407 pop_name(first);
408 return;
409 }
410
411 /*
389 * Open the directory for reading.
390 */
391 if ((name = opendir(path)) == NULL) {
392 int saveerrno = errno;
393
394 /*
395 * If interactive, ask for acknowledgement.
396 */

--- 316 unchanged lines hidden (view full) ---

713 }
714 curlen = strlen(fullpath);
715}
716
717static void
718pop_name(int first)
719{
720 char *slash;
412 * Open the directory for reading.
413 */
414 if ((name = opendir(path)) == NULL) {
415 int saveerrno = errno;
416
417 /*
418 * If interactive, ask for acknowledgement.
419 */

--- 316 unchanged lines hidden (view full) ---

736 }
737 curlen = strlen(fullpath);
738}
739
740static void
741pop_name(int first)
742{
743 char *slash;
721
722 if (first) {
723 *fullpath = '\0';
724 return;
725 }
726 slash = strrchr(fullpath, '/');
727 if (slash)
728 *slash = '\0';
729 else

--- 206 unchanged lines hidden (view full) ---

936/*
937 * cleanup the dynamically-allocated list of device numbers and inodes,
938 * if any. If homedir was never used, it is external and static so
939 * it is guaranteed initialized to zero, thus homedir.next would be NULL.
940 */
941
942static void
943cleanup(void) {
744 if (first) {
745 *fullpath = '\0';
746 return;
747 }
748 slash = strrchr(fullpath, '/');
749 if (slash)
750 *slash = '\0';
751 else

--- 206 unchanged lines hidden (view full) ---

958/*
959 * cleanup the dynamically-allocated list of device numbers and inodes,
960 * if any. If homedir was never used, it is external and static so
961 * it is guaranteed initialized to zero, thus homedir.next would be NULL.
962 */
963
964static void
965cleanup(void) {
944
945 struct dir_id *lastdir, *curdir;
946
947 curdir = homedir.next;
948
949 while (curdir != NULL) {
950 lastdir = curdir;
951 curdir = curdir->next;
952 free(lastdir);
953 }
954}
966 struct dir_id *lastdir, *curdir;
967
968 curdir = homedir.next;
969
970 while (curdir != NULL) {
971 lastdir = curdir;
972 curdir = curdir->next;
973 free(lastdir);
974 }
975}