diff options
author | trasz <trasz@FreeBSD.org> | 2009-09-07 16:19:32 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2009-09-07 16:19:32 +0000 |
commit | 365d19e2c3d1e6500b74bd65ba5a1a89bd987999 (patch) | |
tree | 4446fd2ed5aacce2cb2f6bf981a090397df53767 /bin/setfacl/setfacl.c | |
parent | 7b97612b07db3b51448e286a27728cdfeab64b1c (diff) | |
download | FreeBSD-src-365d19e2c3d1e6500b74bd65ba5a1a89bd987999.zip FreeBSD-src-365d19e2c3d1e6500b74bd65ba5a1a89bd987999.tar.gz |
Add NFSv4 support to setfacl(1).
Reviewed by: rwatson
Diffstat (limited to 'bin/setfacl/setfacl.c')
-rw-r--r-- | bin/setfacl/setfacl.c | 191 |
1 files changed, 118 insertions, 73 deletions
diff --git a/bin/setfacl/setfacl.c b/bin/setfacl/setfacl.c index 2286efb..2835ba8 100644 --- a/bin/setfacl/setfacl.c +++ b/bin/setfacl/setfacl.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/queue.h> #include <err.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -41,9 +42,8 @@ __FBSDID("$FreeBSD$"); #include "setfacl.h" -static void add_filename(const char *filename); -static acl_t *get_file_acls(const char *filename); -static void usage(void); +static void add_filename(const char *filename); +static void usage(void); static void add_filename(const char *filename) @@ -59,57 +59,28 @@ add_filename(const char *filename) TAILQ_INSERT_TAIL(&filelist, file, next); } -static acl_t * -get_file_acls(const char *filename) -{ - acl_t *acl; - struct stat sb; - - if (stat(filename, &sb) == -1) { - warn("stat() of %s failed", filename); - return (NULL); - } - - acl = zmalloc(sizeof(acl_t) * 2); - if (h_flag) - acl[ACCESS_ACL] = acl_get_link_np(filename, ACL_TYPE_ACCESS); - else - acl[ACCESS_ACL] = acl_get_file(filename, ACL_TYPE_ACCESS); - if (acl[ACCESS_ACL] == NULL) - err(1, "acl_get_file() failed"); - if (S_ISDIR(sb.st_mode)) { - if (h_flag) - acl[DEFAULT_ACL] = acl_get_link_np(filename, - ACL_TYPE_DEFAULT); - else - acl[DEFAULT_ACL] = acl_get_file(filename, - ACL_TYPE_DEFAULT); - if (acl[DEFAULT_ACL] == NULL) - err(1, "acl_get_file() failed"); - } else - acl[DEFAULT_ACL] = NULL; - - return (acl); -} - static void usage(void) { - fprintf(stderr, "usage: setfacl [-bdhkn] [-m entries] [-M file] " - "[-x entries] [-X file] [file ...]\n"); + fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] " + "[-m entries] [-M file] [-x entries] [-X file] [file ...]\n"); exit(1); } int main(int argc, char *argv[]) { - acl_t *acl, final_acl; + acl_t acl; + acl_type_t acl_type; char filename[PATH_MAX]; - int local_error, carried_error, ch, i; + int local_error, carried_error, ch, i, entry_number, ret; + int h_flag; struct sf_file *file; struct sf_entry *entry; const char *fn_dup; + char *end; + struct stat sb; acl_type = ACL_TYPE_ACCESS; carried_error = local_error = 0; @@ -118,13 +89,13 @@ main(int argc, char *argv[]) TAILQ_INIT(&entrylist); TAILQ_INIT(&filelist); - while ((ch = getopt(argc, argv, "M:X:bdhkm:nx:")) != -1) + while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1) switch(ch) { case 'M': entry = zmalloc(sizeof(struct sf_entry)); entry->acl = get_acl_from_file(optarg); if (entry->acl == NULL) - err(1, "get_acl_from_file() failed"); + err(1, "%s: get_acl_from_file() failed", optarg); entry->op = OP_MERGE_ACL; TAILQ_INSERT_TAIL(&entrylist, entry, next); break; @@ -134,6 +105,25 @@ main(int argc, char *argv[]) entry->op = OP_REMOVE_ACL; TAILQ_INSERT_TAIL(&entrylist, entry, next); break; + case 'a': + entry = zmalloc(sizeof(struct sf_entry)); + + entry_number = strtol(optarg, &end, 10); + if (end - optarg != (int)strlen(optarg)) + errx(1, "%s: invalid entry number", optarg); + if (entry_number < 0) + errx(1, "%s: entry number cannot be less than zero", optarg); + entry->entry_number = entry_number; + + if (argv[optind] == NULL) + errx(1, "missing ACL"); + entry->acl = acl_from_text(argv[optind]); + if (entry->acl == NULL) + err(1, "%s", argv[optind]); + optind++; + entry->op = OP_ADD_ACL; + TAILQ_INSERT_TAIL(&entrylist, entry, next); + break; case 'b': entry = zmalloc(sizeof(struct sf_entry)); entry->op = OP_REMOVE_EXT; @@ -163,10 +153,18 @@ main(int argc, char *argv[]) break; case 'x': entry = zmalloc(sizeof(struct sf_entry)); - entry->acl = acl_from_text(optarg); - if (entry->acl == NULL) - err(1, "%s", optarg); - entry->op = OP_REMOVE_ACL; + entry_number = strtol(optarg, &end, 10); + if (end - optarg == (int)strlen(optarg)) { + if (entry_number < 0) + errx(1, "%s: entry number cannot be less than zero", optarg); + entry->entry_number = entry_number; + entry->op = OP_REMOVE_BY_NUMBER; + } else { + entry->acl = acl_from_text(optarg); + if (entry->acl == NULL) + err(1, "%s", optarg); + entry->op = OP_REMOVE_ACL; + } TAILQ_INSERT_TAIL(&entrylist, entry, next); break; default: @@ -199,16 +197,51 @@ main(int argc, char *argv[]) /* cycle through each file */ TAILQ_FOREACH(file, &filelist, next) { - /* get our initial access and default ACL's */ - acl = get_file_acls(file->filename); - if (acl == NULL) + local_error = 0; + + if (stat(file->filename, &sb) == -1) { + warn("%s: stat() failed", file->filename); continue; - if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) { - warnx("Default ACL not valid for %s", file->filename); + } + + if (acl_type == ACL_TYPE_DEFAULT && S_ISDIR(sb.st_mode) == 0) { + warnx("%s: default ACL may only be set on a directory", + file->filename); continue; } - local_error = 0; + if (h_flag) + ret = lpathconf(file->filename, _PC_ACL_NFS4); + else + ret = pathconf(file->filename, _PC_ACL_NFS4); + if (ret > 0) { + if (acl_type == ACL_TYPE_DEFAULT) { + warnx("%s: there are no default entries " + "in NFSv4 ACLs", file->filename); + continue; + } + acl_type = ACL_TYPE_NFS4; + } else if (ret == 0) { + if (acl_type == ACL_TYPE_NFS4) + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("%s: pathconf(..., _PC_ACL_NFS4) failed", + file->filename); + } + + if (h_flag) + acl = acl_get_link_np(file->filename, acl_type); + else + acl = acl_get_file(file->filename, acl_type); + if (acl == NULL) { + if (h_flag) + warn("%s: acl_get_link_np() failed", + file->filename); + else + warn("%s: acl_get_file() failed", + file->filename); + continue; + } /* cycle through each option */ TAILQ_FOREACH(entry, &entrylist, next) { @@ -216,24 +249,44 @@ main(int argc, char *argv[]) continue; switch(entry->op) { + case OP_ADD_ACL: + local_error += add_acl(entry->acl, + entry->entry_number, &acl, file->filename); + break; case OP_MERGE_ACL: - local_error += merge_acl(entry->acl, acl); + local_error += merge_acl(entry->acl, &acl, + file->filename); need_mask = 1; break; case OP_REMOVE_EXT: - remove_ext(acl); + remove_ext(&acl, file->filename); need_mask = 0; break; case OP_REMOVE_DEF: + if (acl_type == ACL_TYPE_NFS4) { + warnx("%s: there are no default entries in NFSv4 ACLs; " + "cannot remove", file->filename); + local_error++; + break; + } if (acl_delete_def_file(file->filename) == -1) { - warn("acl_delete_def_file() failed"); + warn("%s: acl_delete_def_file() failed", + file->filename); local_error++; } - local_error += remove_default(acl); + if (acl_type == ACL_TYPE_DEFAULT) + local_error += remove_default(&acl, + file->filename); need_mask = 0; break; case OP_REMOVE_ACL: - local_error += remove_acl(entry->acl, acl); + local_error += remove_acl(entry->acl, &acl, + file->filename); + need_mask = 1; + break; + case OP_REMOVE_BY_NUMBER: + local_error += remove_by_number(entry->entry_number, + &acl, file->filename); need_mask = 1; break; } @@ -245,35 +298,27 @@ main(int argc, char *argv[]) continue; } - if (acl_type == ACL_TYPE_ACCESS) { - final_acl = acl[ACCESS_ACL]; - acl_free(acl[DEFAULT_ACL]); - } else { - final_acl = acl[DEFAULT_ACL]; - acl_free(acl[ACCESS_ACL]); - } - - if (need_mask && (set_acl_mask(&final_acl) == -1)) { - warnx("failed to set ACL mask on %s", file->filename); + if (acl_type != ACL_TYPE_NFS4 && need_mask && + set_acl_mask(&acl, file->filename) == -1) { + warnx("%s: failed to set ACL mask", file->filename); carried_error++; } else if (h_flag) { if (acl_set_link_np(file->filename, acl_type, - final_acl) == -1) { + acl) == -1) { carried_error++; - warn("acl_set_link_np() failed for %s", + warn("%s: acl_set_link_np() failed", file->filename); } } else { if (acl_set_file(file->filename, acl_type, - final_acl) == -1) { + acl) == -1) { carried_error++; - warn("acl_set_file() failed for %s", + warn("%s: acl_set_file() failed", file->filename); } } - acl_free(final_acl); - free(acl); + acl_free(acl); } return (carried_error); |