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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1995 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 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * Rmdir(1) removes directory. 35 * If -p option is used, rmdir(1) tries to remove the directory 36 * and it's parent directories. It exits with code 0 if the WHOLE 37 * given path is removed and 2 if part of path remains. 38 * Results are printed except when -s is used. 39 */ 40 41 #include <stdio.h> 42 #include <libgen.h> 43 #include <errno.h> 44 #include <string.h> 45 #include <unistd.h> 46 #include <stdlib.h> 47 #include <locale.h> 48 49 50 int 51 main(int argc, char **argv) 52 { 53 54 char *prog; 55 int c, pflag, sflag, errflg, rc; 56 char *ptr, *remain, *msg, *path; 57 unsigned int pathlen; 58 59 prog = argv[0]; 60 pflag = sflag = 0; 61 errflg = 0; 62 /* set effective uid, euid, to be same as real */ 63 /* uid, ruid. Rmdir(2) checks search & write */ 64 /* permissions for euid, but for compatibility */ 65 /* the check must be done using ruid. */ 66 67 (void) setlocale(LC_ALL, ""); 68 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 69 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 70 #endif 71 (void) textdomain(TEXT_DOMAIN); 72 73 if (setuid(getuid()) == -1) { 74 char buf[80]; 75 76 (void) sprintf(buf, gettext("%s: setuid(2) failed"), prog); 77 perror(buf); 78 exit(1); 79 } 80 81 while ((c = getopt(argc, argv, "ps")) != EOF) 82 switch (c) { 83 case 'p': 84 pflag++; 85 break; 86 case 's': 87 sflag++; 88 break; 89 case '?': 90 errflg++; 91 break; 92 } 93 if (argc < 2 || errflg) { 94 (void) fprintf(stderr, gettext("Usage: %s [-ps] dirname ...\n"), 95 prog); 96 exit(2); 97 } 98 errno = 0; 99 argc -= optind; 100 argv = &argv[optind]; 101 while (argc--) { 102 ptr = *argv++; 103 /* 104 * -p option. Remove directory and parents. 105 * Prints results of removing 106 */ 107 if (pflag) { 108 pathlen = (unsigned)strlen(ptr); 109 if ((path = (char *)malloc(pathlen + 4)) == NULL || 110 (remain = (char *)malloc(pathlen + 4)) == NULL) { 111 perror(prog); 112 exit(2); 113 } 114 (void) strcpy(path, ptr); 115 116 /* 117 * rmdirp removes directory and parents 118 * rc != 0 implies only part of path removed 119 */ 120 121 if (((rc = rmdirp(path, remain)) != 0) && !sflag) { 122 switch (rc) { 123 case -1: 124 if (errno == EEXIST) 125 msg = gettext( 126 "Directory not empty"); 127 else 128 msg = strerror(errno); 129 break; 130 case -2: 131 errno = EINVAL; 132 msg = gettext("Can not remove . or .."); 133 break; 134 case -3: 135 errno = EINVAL; 136 msg = gettext( 137 "Can not remove current directory"); 138 break; 139 } 140 (void) fprintf(stderr, gettext("%s: directory" 141 " \"%s\": %s not removed; %s\n"), 142 prog, ptr, remain, msg); 143 } 144 free(path); 145 free(remain); 146 continue; 147 } 148 149 /* No -p option. Remove only one directory */ 150 151 if (rmdir(ptr) == -1) { 152 switch (errno) { 153 case EEXIST: 154 msg = gettext("Directory not empty"); 155 break; 156 case ENOTDIR: 157 msg = gettext("Path component not a directory"); 158 break; 159 case ENOENT: 160 msg = gettext("Directory does not exist"); 161 break; 162 case EACCES: 163 msg = gettext( 164 "Search or write permission needed"); 165 break; 166 case EBUSY: 167 msg = gettext( 168 "Directory is a mount point or in use"); 169 break; 170 case EROFS: 171 msg = gettext("Read-only file system"); 172 break; 173 case EIO: 174 msg = gettext( 175 "I/O error accessing file system"); 176 break; 177 case EINVAL: 178 msg = gettext( 179 "Can't remove current directory or .."); 180 break; 181 case EFAULT: 182 default: 183 msg = strerror(errno); 184 break; 185 } 186 (void) fprintf(stderr, 187 gettext("%s: directory \"%s\": %s\n"), 188 prog, ptr, msg); 189 continue; 190 } 191 } 192 return (errno ? 2 : 0); 193 } 194