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