Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/bin/getfacl/getfacl.c
39536 views
1
/*-
2
* Copyright (c) 1999, 2001, 2002 Robert N M Watson
3
* All rights reserved.
4
*
5
* This software was developed by Robert Watson for the TrustedBSD Project.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
/*
29
* getfacl -- POSIX.1e utility to extract ACLs from files and directories
30
* and send the results to stdout
31
*/
32
33
#include <sys/types.h>
34
#include <sys/param.h>
35
#include <sys/acl.h>
36
#include <sys/stat.h>
37
38
#include <err.h>
39
#include <errno.h>
40
#include <getopt.h>
41
#include <grp.h>
42
#include <pwd.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
47
48
static int more_than_one = 0;
49
50
static const struct option long_options[] =
51
{
52
{ "default", no_argument, NULL, 'd' },
53
{ "numeric", no_argument, NULL, 'n' },
54
{ "omit-header", no_argument, NULL, 'q' },
55
{ "skip-base", no_argument, NULL, 's' },
56
{ NULL, no_argument, NULL, 0 },
57
};
58
59
static void
60
usage(void)
61
{
62
63
fprintf(stderr, "getfacl [-dhnqv] [file ...]\n");
64
}
65
66
static char *
67
getuname(uid_t uid)
68
{
69
struct passwd *pw;
70
static char uids[10];
71
72
if ((pw = getpwuid(uid)) == NULL) {
73
(void)snprintf(uids, sizeof(uids), "%u", uid);
74
return (uids);
75
} else
76
return (pw->pw_name);
77
}
78
79
static char *
80
getgname(gid_t gid)
81
{
82
struct group *gr;
83
static char gids[10];
84
85
if ((gr = getgrgid(gid)) == NULL) {
86
(void)snprintf(gids, sizeof(gids), "%u", gid);
87
return (gids);
88
} else
89
return (gr->gr_name);
90
}
91
92
static int
93
print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag,
94
int qflag, int vflag, int sflag)
95
{
96
struct stat sb;
97
acl_t acl;
98
char *acl_text;
99
int error, flags = 0, ret;
100
101
if (hflag)
102
error = lstat(path, &sb);
103
else
104
error = stat(path, &sb);
105
if (error == -1) {
106
warn("%s: stat() failed", path);
107
return(-1);
108
}
109
110
if (hflag)
111
ret = lpathconf(path, _PC_ACL_NFS4);
112
else
113
ret = pathconf(path, _PC_ACL_NFS4);
114
if (ret > 0) {
115
if (type == ACL_TYPE_DEFAULT) {
116
warnx("%s: there are no default entries in NFSv4 ACLs",
117
path);
118
return (-1);
119
}
120
type = ACL_TYPE_NFS4;
121
} else if (ret < 0 && errno != EINVAL) {
122
warn("%s: pathconf(..., _PC_ACL_NFS4) failed", path);
123
return (-1);
124
}
125
126
if (hflag)
127
acl = acl_get_link_np(path, type);
128
else
129
acl = acl_get_file(path, type);
130
131
if (!acl && errno != EOPNOTSUPP) {
132
warn("%s", path);
133
return(-1);
134
}
135
136
if (sflag) {
137
int trivial;
138
139
/*
140
* With the -s flag, we shouldn't synthesize a trivial ACL if
141
* they aren't supported as we do below.
142
*/
143
if (!acl)
144
return(0);
145
146
/*
147
* We also shouldn't render anything for this path if it's a
148
* trivial ACL. If we error out, we'll issue a warning but
149
* proceed with this file to err on the side of caution.
150
*/
151
error = acl_is_trivial_np(acl, &trivial);
152
if (error != 0) {
153
warn("%s: acl_is_trivial_np failed", path);
154
} else if (trivial) {
155
(void)acl_free(acl);
156
return(0);
157
}
158
}
159
160
if (more_than_one)
161
printf("\n");
162
else
163
more_than_one++;
164
if (!qflag)
165
printf("# file: %s\n# owner: %s\n# group: %s\n", path,
166
getuname(sb.st_uid), getgname(sb.st_gid));
167
168
if (!acl) {
169
if (type == ACL_TYPE_DEFAULT)
170
return(0);
171
acl = acl_from_mode_np(sb.st_mode);
172
if (!acl) {
173
warn("%s: acl_from_mode() failed", path);
174
return(-1);
175
}
176
}
177
178
if (iflag)
179
flags |= ACL_TEXT_APPEND_ID;
180
181
if (nflag)
182
flags |= ACL_TEXT_NUMERIC_IDS;
183
184
if (vflag)
185
flags |= ACL_TEXT_VERBOSE;
186
187
acl_text = acl_to_text_np(acl, 0, flags);
188
if (!acl_text) {
189
warn("%s: acl_to_text_np() failed", path);
190
(void)acl_free(acl);
191
return(-1);
192
}
193
194
printf("%s", acl_text);
195
196
(void)acl_free(acl);
197
(void)acl_free(acl_text);
198
199
return(0);
200
}
201
202
static int
203
print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag,
204
int qflag, int vflag, int sflag)
205
{
206
char *p, pathname[PATH_MAX];
207
int carried_error = 0;
208
209
while (fgets(pathname, (int)sizeof(pathname), stdin)) {
210
if ((p = strchr(pathname, '\n')) != NULL)
211
*p = '\0';
212
if (print_acl(pathname, type, hflag, iflag, nflag,
213
qflag, vflag, sflag) == -1) {
214
carried_error = -1;
215
}
216
}
217
218
return(carried_error);
219
}
220
221
int
222
main(int argc, char *argv[])
223
{
224
acl_type_t type = ACL_TYPE_ACCESS;
225
int carried_error = 0;
226
int ch, error, i;
227
int hflag, iflag, qflag, nflag, sflag, vflag;
228
229
hflag = 0;
230
iflag = 0;
231
qflag = 0;
232
nflag = 0;
233
sflag = 0;
234
vflag = 0;
235
while ((ch = getopt_long(argc, argv, "+dhinqsv", long_options,
236
NULL)) != -1)
237
switch(ch) {
238
case 'd':
239
type = ACL_TYPE_DEFAULT;
240
break;
241
case 'h':
242
hflag = 1;
243
break;
244
case 'i':
245
iflag = 1;
246
break;
247
case 'n':
248
nflag = 1;
249
break;
250
case 'q':
251
qflag = 1;
252
break;
253
case 's':
254
sflag = 1;
255
break;
256
case 'v':
257
vflag = 1;
258
break;
259
default:
260
usage();
261
return(-1);
262
}
263
argc -= optind;
264
argv += optind;
265
266
if (argc == 0) {
267
error = print_acl_from_stdin(type, hflag, iflag, nflag,
268
qflag, vflag, sflag);
269
return(error ? 1 : 0);
270
}
271
272
for (i = 0; i < argc; i++) {
273
if (!strcmp(argv[i], "-")) {
274
error = print_acl_from_stdin(type, hflag, iflag, nflag,
275
qflag, vflag, sflag);
276
if (error == -1)
277
carried_error = -1;
278
} else {
279
error = print_acl(argv[i], type, hflag, iflag, nflag,
280
qflag, vflag, sflag);
281
if (error == -1)
282
carried_error = -1;
283
}
284
}
285
286
return(carried_error ? 1 : 0);
287
}
288
289