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