summaryrefslogtreecommitdiffstats
path: root/bin/setfacl/setfacl.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/setfacl/setfacl.c')
-rw-r--r--bin/setfacl/setfacl.c191
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);
OpenPOWER on IntegriCloud