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} |