Deleted Added
sdiff udiff text old ( 182813 ) new ( 196936 )
full compact
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 $");
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 <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include "setfacl.h"
43
44static void add_filename(const char *filename);
45static acl_t *get_file_acls(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
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
99 fprintf(stderr, "usage: setfacl [-bdhkn] [-m entries] [-M file] "
100 "[-x entries] [-X file] [file ...]\n");
101 exit(1);
102}
103
104int
105main(int argc, char *argv[])
106{
107 acl_t *acl, final_acl;
108 char filename[PATH_MAX];
109 int local_error, carried_error, ch, i;
110 struct sf_file *file;
111 struct sf_entry *entry;
112 const char *fn_dup;
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
121 while ((ch = getopt(argc, argv, "M:X: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)
127 err(1, "get_acl_from_file() failed");
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;
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));
166 entry->acl = acl_from_text(optarg);
167 if (entry->acl == NULL)
168 err(1, "%s", optarg);
169 entry->op = OP_REMOVE_ACL;
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) {
202 /* get our initial access and default ACL's */
203 acl = get_file_acls(file->filename);
204 if (acl == NULL)
205 continue;
206 if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) {
207 warnx("Default ACL not valid for %s", file->filename);
208 continue;
209 }
210
211 local_error = 0;
212
213 /* cycle through each option */
214 TAILQ_FOREACH(entry, &entrylist, next) {
215 if (local_error)
216 continue;
217
218 switch(entry->op) {
219 case OP_MERGE_ACL:
220 local_error += merge_acl(entry->acl, acl);
221 need_mask = 1;
222 break;
223 case OP_REMOVE_EXT:
224 remove_ext(acl);
225 need_mask = 0;
226 break;
227 case OP_REMOVE_DEF:
228 if (acl_delete_def_file(file->filename) == -1) {
229 warn("acl_delete_def_file() failed");
230 local_error++;
231 }
232 local_error += remove_default(acl);
233 need_mask = 0;
234 break;
235 case OP_REMOVE_ACL:
236 local_error += remove_acl(entry->acl, acl);
237 need_mask = 1;
238 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
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);
258 carried_error++;
259 } else if (h_flag) {
260 if (acl_set_link_np(file->filename, acl_type,
261 final_acl) == -1) {
262 carried_error++;
263 warn("acl_set_link_np() failed for %s",
264 file->filename);
265 }
266 } else {
267 if (acl_set_file(file->filename, acl_type,
268 final_acl) == -1) {
269 carried_error++;
270 warn("acl_set_file() failed for %s",
271 file->filename);
272 }
273 }
274
275 acl_free(final_acl);
276 free(acl);
277 }
278
279 return (carried_error);
280}