Deleted Added
full compact
setfacl.c (182813) setfacl.c (196936)
1/*-
2 * Copyright (c) 2001 Chris D. Faulhaber
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Chris D. Faulhaber
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/bin/setfacl/setfacl.c 182813 2008-09-06 13:17:35Z trasz $");
28__FBSDID("$FreeBSD: head/bin/setfacl/setfacl.c 196936 2009-09-07 16:19:32Z trasz $");
29
30#include <sys/types.h>
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <sys/acl.h>
34#include <sys/queue.h>
35
36#include <err.h>
29
30#include <sys/types.h>
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <sys/acl.h>
34#include <sys/queue.h>
35
36#include <err.h>
37#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include "setfacl.h"
43
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#include "setfacl.h"
44
44static void add_filename(const char *filename);
45static acl_t *get_file_acls(const char *filename);
46static void usage(void);
45static void add_filename(const char *filename);
46static void usage(void);
47
48static void
49add_filename(const char *filename)
50{
51 struct sf_file *file;
52
53 if (strlen(filename) > PATH_MAX - 1) {
54 warn("illegal filename");
55 return;
56 }
57 file = zmalloc(sizeof(struct sf_file));
58 file->filename = filename;
59 TAILQ_INSERT_TAIL(&filelist, file, next);
60}
61
47
48static void
49add_filename(const char *filename)
50{
51 struct sf_file *file;
52
53 if (strlen(filename) > PATH_MAX - 1) {
54 warn("illegal filename");
55 return;
56 }
57 file = zmalloc(sizeof(struct sf_file));
58 file->filename = filename;
59 TAILQ_INSERT_TAIL(&filelist, file, next);
60}
61
62static acl_t *
63get_file_acls(const char *filename)
64{
65 acl_t *acl;
66 struct stat sb;
67
68 if (stat(filename, &sb) == -1) {
69 warn("stat() of %s failed", filename);
70 return (NULL);
71 }
72
73 acl = zmalloc(sizeof(acl_t) * 2);
74 if (h_flag)
75 acl[ACCESS_ACL] = acl_get_link_np(filename, ACL_TYPE_ACCESS);
76 else
77 acl[ACCESS_ACL] = acl_get_file(filename, ACL_TYPE_ACCESS);
78 if (acl[ACCESS_ACL] == NULL)
79 err(1, "acl_get_file() failed");
80 if (S_ISDIR(sb.st_mode)) {
81 if (h_flag)
82 acl[DEFAULT_ACL] = acl_get_link_np(filename,
83 ACL_TYPE_DEFAULT);
84 else
85 acl[DEFAULT_ACL] = acl_get_file(filename,
86 ACL_TYPE_DEFAULT);
87 if (acl[DEFAULT_ACL] == NULL)
88 err(1, "acl_get_file() failed");
89 } else
90 acl[DEFAULT_ACL] = NULL;
91
92 return (acl);
93}
94
95static void
96usage(void)
97{
98
62static void
63usage(void)
64{
65
99 fprintf(stderr, "usage: setfacl [-bdhkn] [-m entries] [-M file] "
100 "[-x entries] [-X file] [file ...]\n");
66 fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] "
67 "[-m entries] [-M file] [-x entries] [-X file] [file ...]\n");
101 exit(1);
102}
103
104int
105main(int argc, char *argv[])
106{
68 exit(1);
69}
70
71int
72main(int argc, char *argv[])
73{
107 acl_t *acl, final_acl;
74 acl_t acl;
75 acl_type_t acl_type;
108 char filename[PATH_MAX];
76 char filename[PATH_MAX];
109 int local_error, carried_error, ch, i;
77 int local_error, carried_error, ch, i, entry_number, ret;
78 int h_flag;
110 struct sf_file *file;
111 struct sf_entry *entry;
112 const char *fn_dup;
79 struct sf_file *file;
80 struct sf_entry *entry;
81 const char *fn_dup;
82 char *end;
83 struct stat sb;
113
114 acl_type = ACL_TYPE_ACCESS;
115 carried_error = local_error = 0;
116 h_flag = have_mask = have_stdin = n_flag = need_mask = 0;
117
118 TAILQ_INIT(&entrylist);
119 TAILQ_INIT(&filelist);
120
84
85 acl_type = ACL_TYPE_ACCESS;
86 carried_error = local_error = 0;
87 h_flag = have_mask = have_stdin = n_flag = need_mask = 0;
88
89 TAILQ_INIT(&entrylist);
90 TAILQ_INIT(&filelist);
91
121 while ((ch = getopt(argc, argv, "M:X:bdhkm:nx:")) != -1)
92 while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1)
122 switch(ch) {
123 case 'M':
124 entry = zmalloc(sizeof(struct sf_entry));
125 entry->acl = get_acl_from_file(optarg);
126 if (entry->acl == NULL)
93 switch(ch) {
94 case 'M':
95 entry = zmalloc(sizeof(struct sf_entry));
96 entry->acl = get_acl_from_file(optarg);
97 if (entry->acl == NULL)
127 err(1, "get_acl_from_file() failed");
98 err(1, "%s: get_acl_from_file() failed", optarg);
128 entry->op = OP_MERGE_ACL;
129 TAILQ_INSERT_TAIL(&entrylist, entry, next);
130 break;
131 case 'X':
132 entry = zmalloc(sizeof(struct sf_entry));
133 entry->acl = get_acl_from_file(optarg);
134 entry->op = OP_REMOVE_ACL;
135 TAILQ_INSERT_TAIL(&entrylist, entry, next);
136 break;
99 entry->op = OP_MERGE_ACL;
100 TAILQ_INSERT_TAIL(&entrylist, entry, next);
101 break;
102 case 'X':
103 entry = zmalloc(sizeof(struct sf_entry));
104 entry->acl = get_acl_from_file(optarg);
105 entry->op = OP_REMOVE_ACL;
106 TAILQ_INSERT_TAIL(&entrylist, entry, next);
107 break;
108 case 'a':
109 entry = zmalloc(sizeof(struct sf_entry));
110
111 entry_number = strtol(optarg, &end, 10);
112 if (end - optarg != (int)strlen(optarg))
113 errx(1, "%s: invalid entry number", optarg);
114 if (entry_number < 0)
115 errx(1, "%s: entry number cannot be less than zero", optarg);
116 entry->entry_number = entry_number;
117
118 if (argv[optind] == NULL)
119 errx(1, "missing ACL");
120 entry->acl = acl_from_text(argv[optind]);
121 if (entry->acl == NULL)
122 err(1, "%s", argv[optind]);
123 optind++;
124 entry->op = OP_ADD_ACL;
125 TAILQ_INSERT_TAIL(&entrylist, entry, next);
126 break;
137 case 'b':
138 entry = zmalloc(sizeof(struct sf_entry));
139 entry->op = OP_REMOVE_EXT;
140 TAILQ_INSERT_TAIL(&entrylist, entry, next);
141 break;
142 case 'd':
143 acl_type = ACL_TYPE_DEFAULT;
144 break;

--- 13 unchanged lines hidden (view full) ---

158 entry->op = OP_MERGE_ACL;
159 TAILQ_INSERT_TAIL(&entrylist, entry, next);
160 break;
161 case 'n':
162 n_flag++;
163 break;
164 case 'x':
165 entry = zmalloc(sizeof(struct sf_entry));
127 case 'b':
128 entry = zmalloc(sizeof(struct sf_entry));
129 entry->op = OP_REMOVE_EXT;
130 TAILQ_INSERT_TAIL(&entrylist, entry, next);
131 break;
132 case 'd':
133 acl_type = ACL_TYPE_DEFAULT;
134 break;

--- 13 unchanged lines hidden (view full) ---

148 entry->op = OP_MERGE_ACL;
149 TAILQ_INSERT_TAIL(&entrylist, entry, next);
150 break;
151 case 'n':
152 n_flag++;
153 break;
154 case 'x':
155 entry = zmalloc(sizeof(struct sf_entry));
166 entry->acl = acl_from_text(optarg);
167 if (entry->acl == NULL)
168 err(1, "%s", optarg);
169 entry->op = OP_REMOVE_ACL;
156 entry_number = strtol(optarg, &end, 10);
157 if (end - optarg == (int)strlen(optarg)) {
158 if (entry_number < 0)
159 errx(1, "%s: entry number cannot be less than zero", optarg);
160 entry->entry_number = entry_number;
161 entry->op = OP_REMOVE_BY_NUMBER;
162 } else {
163 entry->acl = acl_from_text(optarg);
164 if (entry->acl == NULL)
165 err(1, "%s", optarg);
166 entry->op = OP_REMOVE_ACL;
167 }
170 TAILQ_INSERT_TAIL(&entrylist, entry, next);
171 break;
172 default:
173 usage();
174 break;
175 }
176 argc -= optind;
177 argv += optind;

--- 16 unchanged lines hidden (view full) ---

194 add_filename(fn_dup);
195 }
196 } else
197 for (i = 0; i < argc; i++)
198 add_filename(argv[i]);
199
200 /* cycle through each file */
201 TAILQ_FOREACH(file, &filelist, next) {
168 TAILQ_INSERT_TAIL(&entrylist, entry, next);
169 break;
170 default:
171 usage();
172 break;
173 }
174 argc -= optind;
175 argv += optind;

--- 16 unchanged lines hidden (view full) ---

192 add_filename(fn_dup);
193 }
194 } else
195 for (i = 0; i < argc; i++)
196 add_filename(argv[i]);
197
198 /* cycle through each file */
199 TAILQ_FOREACH(file, &filelist, next) {
202 /* get our initial access and default ACL's */
203 acl = get_file_acls(file->filename);
204 if (acl == NULL)
200 local_error = 0;
201
202 if (stat(file->filename, &sb) == -1) {
203 warn("%s: stat() failed", file->filename);
205 continue;
204 continue;
206 if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) {
207 warnx("Default ACL not valid for %s", file->filename);
205 }
206
207 if (acl_type == ACL_TYPE_DEFAULT && S_ISDIR(sb.st_mode) == 0) {
208 warnx("%s: default ACL may only be set on a directory",
209 file->filename);
208 continue;
209 }
210
210 continue;
211 }
212
211 local_error = 0;
213 if (h_flag)
214 ret = lpathconf(file->filename, _PC_ACL_NFS4);
215 else
216 ret = pathconf(file->filename, _PC_ACL_NFS4);
217 if (ret > 0) {
218 if (acl_type == ACL_TYPE_DEFAULT) {
219 warnx("%s: there are no default entries "
220 "in NFSv4 ACLs", file->filename);
221 continue;
222 }
223 acl_type = ACL_TYPE_NFS4;
224 } else if (ret == 0) {
225 if (acl_type == ACL_TYPE_NFS4)
226 acl_type = ACL_TYPE_ACCESS;
227 } else if (ret < 0 && errno != EINVAL) {
228 warn("%s: pathconf(..., _PC_ACL_NFS4) failed",
229 file->filename);
230 }
212
231
232 if (h_flag)
233 acl = acl_get_link_np(file->filename, acl_type);
234 else
235 acl = acl_get_file(file->filename, acl_type);
236 if (acl == NULL) {
237 if (h_flag)
238 warn("%s: acl_get_link_np() failed",
239 file->filename);
240 else
241 warn("%s: acl_get_file() failed",
242 file->filename);
243 continue;
244 }
245
213 /* cycle through each option */
214 TAILQ_FOREACH(entry, &entrylist, next) {
215 if (local_error)
216 continue;
217
218 switch(entry->op) {
246 /* cycle through each option */
247 TAILQ_FOREACH(entry, &entrylist, next) {
248 if (local_error)
249 continue;
250
251 switch(entry->op) {
252 case OP_ADD_ACL:
253 local_error += add_acl(entry->acl,
254 entry->entry_number, &acl, file->filename);
255 break;
219 case OP_MERGE_ACL:
256 case OP_MERGE_ACL:
220 local_error += merge_acl(entry->acl, acl);
257 local_error += merge_acl(entry->acl, &acl,
258 file->filename);
221 need_mask = 1;
222 break;
223 case OP_REMOVE_EXT:
259 need_mask = 1;
260 break;
261 case OP_REMOVE_EXT:
224 remove_ext(acl);
262 remove_ext(&acl, file->filename);
225 need_mask = 0;
226 break;
227 case OP_REMOVE_DEF:
263 need_mask = 0;
264 break;
265 case OP_REMOVE_DEF:
266 if (acl_type == ACL_TYPE_NFS4) {
267 warnx("%s: there are no default entries in NFSv4 ACLs; "
268 "cannot remove", file->filename);
269 local_error++;
270 break;
271 }
228 if (acl_delete_def_file(file->filename) == -1) {
272 if (acl_delete_def_file(file->filename) == -1) {
229 warn("acl_delete_def_file() failed");
273 warn("%s: acl_delete_def_file() failed",
274 file->filename);
230 local_error++;
231 }
275 local_error++;
276 }
232 local_error += remove_default(acl);
277 if (acl_type == ACL_TYPE_DEFAULT)
278 local_error += remove_default(&acl,
279 file->filename);
233 need_mask = 0;
234 break;
235 case OP_REMOVE_ACL:
280 need_mask = 0;
281 break;
282 case OP_REMOVE_ACL:
236 local_error += remove_acl(entry->acl, acl);
283 local_error += remove_acl(entry->acl, &acl,
284 file->filename);
237 need_mask = 1;
238 break;
285 need_mask = 1;
286 break;
287 case OP_REMOVE_BY_NUMBER:
288 local_error += remove_by_number(entry->entry_number,
289 &acl, file->filename);
290 need_mask = 1;
291 break;
239 }
240 }
241
242 /* don't bother setting the ACL if something is broken */
243 if (local_error) {
244 carried_error++;
245 continue;
246 }
247
292 }
293 }
294
295 /* don't bother setting the ACL if something is broken */
296 if (local_error) {
297 carried_error++;
298 continue;
299 }
300
248 if (acl_type == ACL_TYPE_ACCESS) {
249 final_acl = acl[ACCESS_ACL];
250 acl_free(acl[DEFAULT_ACL]);
251 } else {
252 final_acl = acl[DEFAULT_ACL];
253 acl_free(acl[ACCESS_ACL]);
254 }
255
256 if (need_mask && (set_acl_mask(&final_acl) == -1)) {
257 warnx("failed to set ACL mask on %s", file->filename);
301 if (acl_type != ACL_TYPE_NFS4 && need_mask &&
302 set_acl_mask(&acl, file->filename) == -1) {
303 warnx("%s: failed to set ACL mask", file->filename);
258 carried_error++;
259 } else if (h_flag) {
260 if (acl_set_link_np(file->filename, acl_type,
304 carried_error++;
305 } else if (h_flag) {
306 if (acl_set_link_np(file->filename, acl_type,
261 final_acl) == -1) {
307 acl) == -1) {
262 carried_error++;
308 carried_error++;
263 warn("acl_set_link_np() failed for %s",
309 warn("%s: acl_set_link_np() failed",
264 file->filename);
265 }
266 } else {
267 if (acl_set_file(file->filename, acl_type,
310 file->filename);
311 }
312 } else {
313 if (acl_set_file(file->filename, acl_type,
268 final_acl) == -1) {
314 acl) == -1) {
269 carried_error++;
315 carried_error++;
270 warn("acl_set_file() failed for %s",
316 warn("%s: acl_set_file() failed",
271 file->filename);
272 }
273 }
274
317 file->filename);
318 }
319 }
320
275 acl_free(final_acl);
276 free(acl);
321 acl_free(acl);
277 }
278
279 return (carried_error);
280}
322 }
323
324 return (carried_error);
325}