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
main(int argc,char * argv[])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(7) 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 *
display(int perm)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 *
pruname(uid_t uid)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 *
prgname(gid_t gid)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
usage()330 usage()
331 {
332 (void) fprintf(stderr,
333 gettext("usage: getfacl [-ad] file ... \n"));
334 exit(1);
335 }
336