2 * Copyright (c) 2001 Chris D. Faulhaber
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
31 #include <sys/param.h>
34 #include <sys/queue.h>
44 static void add_filename(const char *filename);
45 static acl_t *get_file_acls(const char *filename);
46 static void usage(void);
49 add_filename(const char *filename)
53 if (strlen(filename) > PATH_MAX - 1) {
54 warn("illegal filename");
57 file = zmalloc(sizeof(struct sf_file));
58 file->filename = filename;
59 TAILQ_INSERT_TAIL(&filelist, file, next);
63 get_file_acls(const char *filename)
68 if (stat(filename, &sb) == -1) {
69 warn("stat() of %s failed", filename);
73 acl = zmalloc(sizeof(acl_t) * 2);
75 acl[ACCESS_ACL] = acl_get_link_np(filename, ACL_TYPE_ACCESS);
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)) {
82 acl[DEFAULT_ACL] = acl_get_link_np(filename,
85 acl[DEFAULT_ACL] = acl_get_file(filename,
87 if (acl[DEFAULT_ACL] == NULL)
88 err(1, "acl_get_file() failed");
90 acl[DEFAULT_ACL] = NULL;
99 fprintf(stderr, "usage: setfacl [-bdhkn] [-m entries] [-M file] "
100 "[-x entries] [-X file] [file ...]\n");
105 main(int argc, char *argv[])
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;
114 acl_type = ACL_TYPE_ACCESS;
115 carried_error = local_error = 0;
116 h_flag = have_mask = have_stdin = n_flag = need_mask = 0;
118 TAILQ_INIT(&entrylist);
119 TAILQ_INIT(&filelist);
121 while ((ch = getopt(argc, argv, "M:X:bdhkm:nx:")) != -1)
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);
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);
138 entry = zmalloc(sizeof(struct sf_entry));
139 entry->op = OP_REMOVE_EXT;
140 TAILQ_INSERT_TAIL(&entrylist, entry, next);
143 acl_type = ACL_TYPE_DEFAULT;
149 entry = zmalloc(sizeof(struct sf_entry));
150 entry->op = OP_REMOVE_DEF;
151 TAILQ_INSERT_TAIL(&entrylist, entry, next);
154 entry = zmalloc(sizeof(struct sf_entry));
155 entry->acl = acl_from_text(optarg);
156 if (entry->acl == NULL)
157 err(1, "%s", optarg);
158 entry->op = OP_MERGE_ACL;
159 TAILQ_INSERT_TAIL(&entrylist, entry, next);
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);
179 if (n_flag == 0 && TAILQ_EMPTY(&entrylist))
182 /* take list of files from stdin */
183 if (argc == 0 || strcmp(argv[0], "-") == 0) {
185 err(1, "cannot have more than one stdin");
187 bzero(&filename, sizeof(filename));
188 while (fgets(filename, (int)sizeof(filename), stdin)) {
190 filename[strlen(filename) - 1] = '\0';
191 fn_dup = strdup(filename);
193 err(1, "strdup() failed");
194 add_filename(fn_dup);
197 for (i = 0; i < argc; i++)
198 add_filename(argv[i]);
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);
206 if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) {
207 warnx("Default ACL not valid for %s", file->filename);
213 /* cycle through each option */
214 TAILQ_FOREACH(entry, &entrylist, next) {
220 local_error += merge_acl(entry->acl, acl);
228 if (acl_delete_def_file(file->filename) == -1) {
229 warn("acl_delete_def_file() failed");
232 local_error += remove_default(acl);
236 local_error += remove_acl(entry->acl, acl);
242 /* don't bother setting the ACL if something is broken */
248 if (acl_type == ACL_TYPE_ACCESS)
249 final_acl = acl[ACCESS_ACL];
251 final_acl = acl[DEFAULT_ACL];
253 if (need_mask && (set_acl_mask(&final_acl) == -1)) {
254 warnx("failed to set ACL mask on %s", file->filename);
257 if (acl_set_link_np(file->filename, acl_type,
260 warn("acl_set_link_np() failed for %s",
264 if (acl_set_file(file->filename, acl_type,
267 warn("acl_set_file() failed for %s",
272 acl_free(acl[ACCESS_ACL]);
273 acl_free(acl[DEFAULT_ACL]);
277 return (carried_error);