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
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 /*
31 * Rmdir(1) removes directory.
32 * If -p option is used, rmdir(1) tries to remove the directory
33 * and it's parent directories. It exits with code 0 if the WHOLE
34 * given path is removed and 2 if part of path remains.
35 * Results are printed except when -s is used.
36 */
37
38 #include <stdio.h>
39 #include <libgen.h>
40 #include <errno.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <locale.h>
45
46
47 int
main(int argc,char ** argv)48 main(int argc, char **argv)
49 {
50
51 char *prog;
52 int c, pflag, sflag, errflg, rc;
53 char *ptr, *remain, *msg, *path;
54 unsigned int pathlen;
55
56 prog = argv[0];
57 pflag = sflag = 0;
58 errflg = 0;
59 (void) setlocale(LC_ALL, "");
60 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
61 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
62 #endif
63 (void) textdomain(TEXT_DOMAIN);
64
65 while ((c = getopt(argc, argv, "ps")) != EOF)
66 switch (c) {
67 case 'p':
68 pflag++;
69 break;
70 case 's':
71 sflag++;
72 break;
73 case '?':
74 errflg++;
75 break;
76 }
77 if (argc < 2 || errflg) {
78 (void) fprintf(stderr, gettext("Usage: %s [-ps] dirname ...\n"),
79 prog);
80 exit(2);
81 }
82 errno = 0;
83 argc -= optind;
84 argv = &argv[optind];
85 while (argc--) {
86 ptr = *argv++;
87 /*
88 * -p option. Remove directory and parents.
89 * Prints results of removing
90 */
91 if (pflag) {
92 pathlen = (unsigned)strlen(ptr);
93 if ((path = (char *)malloc(pathlen + 4)) == NULL ||
94 (remain = (char *)malloc(pathlen + 4)) == NULL) {
95 perror(prog);
96 exit(2);
97 }
98 (void) strcpy(path, ptr);
99
100 /*
101 * rmdirp removes directory and parents
102 * rc != 0 implies only part of path removed
103 */
104
105 if (((rc = rmdirp(path, remain)) != 0) && !sflag) {
106 switch (rc) {
107 case -1:
108 if (errno == EEXIST)
109 msg = gettext(
110 "Directory not empty");
111 else
112 msg = strerror(errno);
113 break;
114 case -2:
115 errno = EINVAL;
116 msg = gettext("Can not remove . or ..");
117 break;
118 case -3:
119 errno = EINVAL;
120 msg = gettext(
121 "Can not remove current directory");
122 break;
123 }
124 (void) fprintf(stderr, gettext("%s: directory"
125 " \"%s\": %s not removed; %s\n"),
126 prog, ptr, remain, msg);
127 }
128 free(path);
129 free(remain);
130 continue;
131 }
132
133 /* No -p option. Remove only one directory */
134
135 if (rmdir(ptr) == -1) {
136 switch (errno) {
137 case EEXIST:
138 msg = gettext("Directory not empty");
139 break;
140 case ENOTDIR:
141 msg = gettext("Path component not a directory");
142 break;
143 case ENOENT:
144 msg = gettext("Directory does not exist");
145 break;
146 case EACCES:
147 msg = gettext(
148 "Search or write permission needed");
149 break;
150 case EBUSY:
151 msg = gettext(
152 "Directory is a mount point or in use");
153 break;
154 case EROFS:
155 msg = gettext("Read-only file system");
156 break;
157 case EIO:
158 msg = gettext(
159 "I/O error accessing file system");
160 break;
161 case EINVAL:
162 msg = gettext(
163 "Can't remove current directory or ..");
164 break;
165 case EFAULT:
166 default:
167 msg = strerror(errno);
168 break;
169 }
170 (void) fprintf(stderr,
171 gettext("%s: directory \"%s\": %s\n"),
172 prog, ptr, msg);
173 continue;
174 }
175 }
176 return (errno ? 2 : 0);
177 }
178