xref: /illumos-gate/usr/src/cmd/rmdir/rmdir.c (revision edb348833aaacfa1176e502ad38875fd0b2717ab)
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
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