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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #ifndef lint 30 static char sccsid[] = "%Z%%M% %I% %E% SMI"; 31 #endif 32 33 /* 34 * getfacl [-ad] file ... 35 * This command displays discretionary information for a file or files. 36 * display format: 37 * # file: filename 38 * # owner: uid 39 * # group: gid 40 * user::perm 41 * user:uid:perm 42 * group::perm 43 * group:gid:perm 44 * mask:perm 45 * other:perm 46 * default:user::perm 47 * default:user:uid:perm 48 * default:group::perm 49 * default:group:gid:perm 50 * default:mask:perm 51 * default:other:perm 52 */ 53 54 #include <stdlib.h> 55 #include <stdio.h> 56 #include <pwd.h> 57 #include <grp.h> 58 #include <locale.h> 59 #include <sys/acl.h> 60 #include <errno.h> 61 62 static char *pruname(uid_t); 63 static char *prgname(gid_t); 64 static char *display(int); 65 static void usage(); 66 67 68 int 69 main(int argc, char *argv[]) 70 { 71 int c; 72 int aflag = 0; 73 int dflag = 0; 74 int errflag = 0; 75 int savecnt; 76 int aclcnt; 77 int mask; 78 aclent_t *aclp; 79 aclent_t *tp; 80 char *permp; 81 82 (void) setlocale(LC_ALL, ""); 83 (void) textdomain(TEXT_DOMAIN); 84 85 if (argc < 2) 86 usage(); 87 88 while ((c = getopt(argc, argv, "ad")) != EOF) { 89 switch (c) { 90 case 'a': 91 aflag++; 92 break; 93 case 'd': 94 dflag++; 95 break; 96 case '?': 97 errflag++; 98 break; 99 } 100 } 101 if (errflag) 102 usage(); 103 104 if (optind >= argc) 105 usage(); 106 107 for (; optind < argc; optind++) { 108 register char *filep; 109 110 filep = argv[optind]; 111 112 /* Get ACL info of the files */ 113 errno = 0; 114 if ((aclcnt = acl(filep, GETACLCNT, 0, NULL)) < 0) { 115 perror(filep); 116 exit(2); 117 } 118 if (aclcnt < MIN_ACL_ENTRIES) { 119 (void) fprintf(stderr, 120 gettext("%d: acl count too small from %s\n"), 121 aclcnt, filep); 122 exit(2); 123 } 124 125 if ((aclp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt)) 126 == NULL) { 127 (void) fprintf(stderr, 128 gettext("Insufficient memory\n")); 129 exit(1); 130 } 131 132 errno = 0; 133 if (acl(filep, GETACL, aclcnt, aclp) < 0) { 134 perror(filep); 135 exit(2); 136 } 137 138 /* display ACL: assume it is sorted. */ 139 (void) printf("\n# file: %s\n", filep); 140 savecnt = aclcnt; 141 for (tp = aclp; aclcnt--; tp++) { 142 if (tp->a_type == USER_OBJ) 143 (void) printf("# owner: %s\n", 144 pruname(tp->a_id)); 145 if (tp->a_type == GROUP_OBJ) 146 (void) printf("# group: %s\n", 147 prgname(tp->a_id)); 148 if (tp->a_type == CLASS_OBJ) 149 mask = tp->a_perm; 150 } 151 aclcnt = savecnt; 152 for (tp = aclp; aclcnt--; tp++) { 153 switch (tp->a_type) { 154 case USER: 155 if (!dflag) { 156 permp = display(tp->a_perm); 157 (void) printf("user:%s:%s\t\t", 158 pruname(tp->a_id), permp); 159 free(permp); 160 permp = display(tp->a_perm & mask); 161 (void) printf( 162 "#effective:%s\n", permp); 163 free(permp); 164 } 165 break; 166 case USER_OBJ: 167 if (!dflag) { 168 /* no need to display uid */ 169 permp = display(tp->a_perm); 170 (void) printf("user::%s\n", permp); 171 free(permp); 172 } 173 break; 174 case GROUP: 175 if (!dflag) { 176 permp = display(tp->a_perm); 177 (void) printf("group:%s:%s\t\t", 178 prgname(tp->a_id), permp); 179 free(permp); 180 permp = display(tp->a_perm & mask); 181 (void) printf( 182 "#effective:%s\n", permp); 183 free(permp); 184 } 185 break; 186 case GROUP_OBJ: 187 if (!dflag) { 188 permp = display(tp->a_perm); 189 (void) printf("group::%s\t\t", permp); 190 free(permp); 191 permp = display(tp->a_perm & mask); 192 (void) printf( 193 "#effective:%s\n", permp); 194 free(permp); 195 } 196 break; 197 case CLASS_OBJ: 198 if (!dflag) { 199 permp = display(tp->a_perm); 200 (void) printf("mask:%s\n", permp); 201 free(permp); 202 } 203 break; 204 case OTHER_OBJ: 205 if (!dflag) { 206 permp = display(tp->a_perm); 207 (void) printf("other:%s\n", permp); 208 free(permp); 209 } 210 break; 211 case DEF_USER: 212 if (!aflag) { 213 permp = display(tp->a_perm); 214 (void) printf("default:user:%s:%s\n", 215 pruname(tp->a_id), permp); 216 free(permp); 217 } 218 break; 219 case DEF_USER_OBJ: 220 if (!aflag) { 221 permp = display(tp->a_perm); 222 (void) printf("default:user::%s\n", 223 permp); 224 free(permp); 225 } 226 break; 227 case DEF_GROUP: 228 if (!aflag) { 229 permp = display(tp->a_perm); 230 (void) printf("default:group:%s:%s\n", 231 prgname(tp->a_id), permp); 232 free(permp); 233 } 234 break; 235 case DEF_GROUP_OBJ: 236 if (!aflag) { 237 permp = display(tp->a_perm); 238 (void) printf("default:group::%s\n", 239 permp); 240 free(permp); 241 } 242 break; 243 case DEF_CLASS_OBJ: 244 if (!aflag) { 245 permp = display(tp->a_perm); 246 (void) printf("default:mask:%s\n", 247 permp); 248 free(permp); 249 } 250 break; 251 case DEF_OTHER_OBJ: 252 if (!aflag) { 253 permp = display(tp->a_perm); 254 (void) printf("default:other:%s\n", 255 permp); 256 free(permp); 257 } 258 break; 259 default: 260 (void) fprintf(stderr, 261 gettext("unrecognized entry\n")); 262 break; 263 } 264 } 265 free(aclp); 266 } 267 return (0); 268 } 269 270 static char * 271 display(int perm) 272 { 273 char *buf; 274 275 buf = malloc(4); 276 if (buf == NULL) { 277 (void) fprintf(stderr, gettext("Insufficient memory\n")); 278 exit(1); 279 } 280 281 if (perm & 4) 282 buf[0] = 'r'; 283 else 284 buf[0] = '-'; 285 if (perm & 2) 286 buf[1] = 'w'; 287 else 288 buf[1] = '-'; 289 if (perm & 1) 290 buf[2] = 'x'; 291 else 292 buf[2] = '-'; 293 buf[3] = '\0'; 294 return (buf); 295 } 296 297 static char * 298 pruname(uid_t uid) 299 { 300 struct passwd *passwdp; 301 static char uidp[10]; /* big enough */ 302 303 passwdp = getpwuid(uid); 304 if (passwdp == (struct passwd *) NULL) { 305 /* could not get passwd information: display uid instead */ 306 (void) sprintf(uidp, "%ld", (long)uid); 307 return (uidp); 308 } else 309 return (passwdp->pw_name); 310 } 311 312 static char * 313 prgname(gid_t gid) 314 { 315 struct group *groupp; 316 static char gidp[10]; /* big enough */ 317 318 groupp = getgrgid(gid); 319 if (groupp == (struct group *) NULL) { 320 /* could not get group information: display gid instead */ 321 (void) sprintf(gidp, "%ld", (long)gid); 322 return (gidp); 323 } else 324 return (groupp->gr_name); 325 } 326 327 static void 328 usage() 329 { 330 (void) fprintf(stderr, 331 gettext("usage: getfacl [-ad] file ... \n")); 332 exit(1); 333 } 334