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