]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/getfacl.c
Add output of effective rights to getfacl
[newlib-cygwin.git] / winsup / utils / getfacl.c
1 /* getfacl.c
2
3 Copyright 2000, 2001, 2002, 2003, 2004, 2009, 2011, 2014, 2015 Red Hat Inc.
4
5 Written by Corinna Vinschen <vinschen@redhat.com>
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 details. */
12
13 #include <pwd.h>
14 #include <grp.h>
15 #include <stdio.h>
16 #include <unistd.h>
17 #include <getopt.h>
18 #include <sys/types.h>
19 #include <sys/acl.h>
20 #include <sys/stat.h>
21 #include <cygwin/version.h>
22 #include <string.h>
23 #include <errno.h>
24
25 static char *prog_name;
26
27 char *
28 permstr (mode_t perm)
29 {
30 static char pbuf[4];
31
32 pbuf[0] = (perm & S_IROTH) ? 'r' : '-';
33 pbuf[1] = (perm & S_IWOTH) ? 'w' : '-';
34 pbuf[2] = (perm & S_IXOTH) ? 'x' : '-';
35 pbuf[3] = '\0';
36 return pbuf;
37 }
38
39 const char *
40 username (uid_t uid)
41 {
42 static char ubuf[256];
43 struct passwd *pw;
44
45 if ((pw = getpwuid (uid)))
46 strcpy (ubuf, pw->pw_name);
47 else
48 sprintf (ubuf, "%lu <unknown>", (unsigned long)uid);
49 return ubuf;
50 }
51
52 const char *
53 groupname (gid_t gid)
54 {
55 static char gbuf[256];
56 struct group *gr;
57
58 if ((gr = getgrgid (gid)))
59 strcpy (gbuf, gr->gr_name);
60 else
61 sprintf (gbuf, "%lu <unknown>", (unsigned long)gid);
62 return gbuf;
63 }
64
65 static void
66 usage (FILE * stream)
67 {
68 fprintf (stream, "Usage: %s [-adn] FILE [FILE2...]\n"
69 "\n"
70 "Display file and directory access control lists (ACLs).\n"
71 "\n"
72 " -a, --access display the file access control list only\n"
73 " -d, --default display the default access control list only\n"
74 " -c, --omit-header do not display the comment header\n"
75 " -e, --all-effective print all effective rights\n"
76 " -E, --no-effective print no effective rights\n"
77 " -n, --numeric print numeric user/group identifiers\n"
78 " -V, --version print version and exit\n"
79 " -h, --help this help text\n"
80 "\n"
81 "When multiple files are specified on the command line, a blank\n"
82 "line separates the ACLs for each file.\n", prog_name);
83 if (stream == stdout)
84 {
85 fprintf (stream, ""
86 "For each argument that is a regular file, special file or\n"
87 "directory, getfacl displays the owner, the group, and the ACL.\n"
88 "For directories getfacl displays additionally the default ACL.\n"
89 "\n"
90 "With no options specified, getfacl displays the filename, the\n"
91 "owner, the group, the setuid (s), setgid (s), and sticky (t)\n"
92 "bits if available, and both the ACL and the default ACL, if it\n"
93 "exists.\n"
94 "\n"
95 "The format for ACL output is as follows:\n"
96 " # file: filename\n"
97 " # owner: name or uid\n"
98 " # group: name or uid\n"
99 " # flags: sst\n"
100 " user::perm\n"
101 " user:name or uid:perm\n"
102 " group::perm\n"
103 " group:name or gid:perm\n"
104 " mask:perm\n"
105 " other:perm\n"
106 " default:user::perm\n"
107 " default:user:name or uid:perm\n"
108 " default:group::perm\n"
109 " default:group:name or gid:perm\n"
110 " default:mask:perm\n"
111 " default:other:perm\n"
112 "\n");
113 }
114 }
115
116 struct option longopts[] = {
117 {"access", no_argument, NULL, 'a'},
118 {"all", no_argument, NULL, 'a'},
119 {"omit-header", no_argument, NULL, 'c'},
120 {"all-effective", no_argument, NULL, 'e'},
121 {"no-effective", no_argument, NULL, 'E'},
122 {"default", no_argument, NULL, 'd'},
123 {"dir", no_argument, NULL, 'd'},
124 {"help", no_argument, NULL, 'h'},
125 {"noname", no_argument, NULL, 'n'}, /* Backward compat */
126 {"numeric", no_argument, NULL, 'n'},
127 {"version", no_argument, NULL, 'V'},
128 {0, no_argument, NULL, 0}
129 };
130 const char *opts = "acdeEhnV";
131
132 static void
133 print_version ()
134 {
135 printf ("getfacl (cygwin) %d.%d.%d\n"
136 "Get POSIX ACL information\n"
137 "Copyright (C) 2000 - %s Red Hat, Inc.\n"
138 "This is free software; see the source for copying conditions. There is NO\n"
139 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
140 CYGWIN_VERSION_DLL_MAJOR / 1000,
141 CYGWIN_VERSION_DLL_MAJOR % 1000,
142 CYGWIN_VERSION_DLL_MINOR,
143 strrchr (__DATE__, ' ') + 1);
144 }
145
146 int
147 main (int argc, char **argv)
148 {
149 int c;
150 int ret = 0;
151 int aopt = 0;
152 int copt = 0;
153 int eopt = 0;
154 int dopt = 0;
155 int nopt = 0;
156 int istty = isatty (fileno (stdout));
157 struct stat st;
158 aclent_t acls[MAX_ACL_ENTRIES];
159
160 prog_name = program_invocation_short_name;
161
162 while ((c = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
163 switch (c)
164 {
165 case 'a':
166 aopt = 1;
167 break;
168 case 'c':
169 copt = 1;
170 break;
171 case 'd':
172 dopt = 1;
173 break;
174 case 'e':
175 eopt = 1;
176 break;
177 case 'E':
178 eopt = -1;
179 break;
180 case 'h':
181 usage (stdout);
182 return 0;
183 case 'n':
184 nopt = 1;
185 break;
186 case 'V':
187 print_version ();
188 return 0;
189 default:
190 fprintf (stderr, "Try `%s --help' for more information.\n", prog_name);
191 return 1;
192 }
193 if (optind > argc - 1)
194 {
195 usage (stderr);
196 return 1;
197 }
198 for (; optind < argc; ++optind)
199 {
200 int i, num_acls;
201 mode_t mask = S_IRWXO, def_mask = S_IRWXO;
202
203 if (stat (argv[optind], &st)
204 || (num_acls = acl (argv[optind], GETACL, MAX_ACL_ENTRIES, acls)) < 0)
205 {
206 fprintf (stderr, "%s: %s: %s\n",
207 prog_name, argv[optind], strerror (errno));
208 ret = 2;
209 continue;
210 }
211 if (!copt)
212 {
213 printf ("# file: %s\n", argv[optind]);
214 if (nopt)
215 {
216 printf ("# owner: %lu\n", (unsigned long)st.st_uid);
217 printf ("# group: %lu\n", (unsigned long)st.st_gid);
218 }
219 else
220 {
221 printf ("# owner: %s\n", username (st.st_uid));
222 printf ("# group: %s\n", groupname (st.st_gid));
223 }
224 if (st.st_mode & (S_ISUID | S_ISGID | S_ISVTX))
225 printf ("# flags: %c%c%c\n", (st.st_mode & S_ISUID) ? 's' : '-',
226 (st.st_mode & S_ISGID) ? 's' : '-',
227 (st.st_mode & S_ISVTX) ? 't' : '-');
228 }
229 for (i = 0; i < num_acls; ++i)
230 {
231 if (acls[i].a_type == CLASS_OBJ)
232 mask = acls[i].a_perm;
233 else if (acls[i].a_type == DEF_CLASS_OBJ)
234 def_mask = acls[i].a_perm;
235 }
236 for (i = 0; i < num_acls; ++i)
237 {
238 int n = 0;
239 int print_effective = 0;
240 mode_t effective = acls[i].a_perm;
241
242 if (acls[i].a_type & ACL_DEFAULT)
243 {
244 if (aopt)
245 continue;
246 n += printf ("default:");
247 }
248 else if (dopt)
249 continue;
250 switch (acls[i].a_type & ~ACL_DEFAULT)
251 {
252 case USER_OBJ:
253 printf ("user::");
254 break;
255 case USER:
256 if (nopt)
257 n += printf ("user:%lu:", (unsigned long)acls[i].a_id);
258 else
259 n += printf ("user:%s:", username (acls[i].a_id));
260 break;
261 case GROUP_OBJ:
262 n += printf ("group::");
263 break;
264 case GROUP:
265 if (nopt)
266 n += printf ("group:%lu:", (unsigned long)acls[i].a_id);
267 else
268 n += printf ("group:%s:", groupname (acls[i].a_id));
269 break;
270 case CLASS_OBJ:
271 printf ("mask:");
272 break;
273 case OTHER_OBJ:
274 printf ("other:");
275 break;
276 }
277 n += printf ("%s", permstr (acls[i].a_perm));
278 switch (acls[i].a_type)
279 {
280 case USER:
281 case GROUP_OBJ:
282 case GROUP:
283 effective = acls[i].a_perm & mask;
284 print_effective = 1;
285 break;
286 case DEF_USER:
287 case DEF_GROUP_OBJ:
288 case DEF_GROUP:
289 effective = acls[i].a_perm & def_mask;
290 print_effective = 1;
291 break;
292 }
293 if (print_effective && eopt >= 0
294 && (eopt > 0 || effective != acls[i].a_perm))
295 {
296 if (istty)
297 {
298 n = 40 - n;
299 if (n <= 0)
300 n = 1;
301 printf ("%*s", n, " ");
302 }
303 else
304 putchar ('\t');
305 printf ("#effective:%s", permstr (effective));
306 }
307 putchar ('\n');
308 }
309 putchar ('\n');
310 }
311 return ret;
312 }
This page took 0.048693 seconds and 6 git commands to generate.