o POSIX.2c Userland tool support for POSIX.1e ACLs -- getfacl retrieves ACLs
from files and directories, and setfacl sets ACLs on files and directories. Submitted by: jedgar Obtained from: TrustedBSD Project
This commit is contained in:
parent
f74abb9b6e
commit
43960f159d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=74465
100
bin/getfacl/getfacl.1
Normal file
100
bin/getfacl/getfacl.1
Normal file
@ -0,0 +1,100 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 2000 Robert N. M. Watson
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 30, 2000
|
||||
.Dt GETFACL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm getfacl
|
||||
.Nd Get ACL Information
|
||||
.Sh SYNOPSIS
|
||||
.Nm getfacl
|
||||
.Op Fl d
|
||||
.Op Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility writes discretionary access control information associated with
|
||||
the specified file(s) to standard output.
|
||||
If the
|
||||
.Xr getconf 8
|
||||
utility indicates that
|
||||
.Va {_POSIX_ACL_EXTENDED}
|
||||
is not in effect for a
|
||||
.Ar file
|
||||
then the standard discretionary access permissions are interpreted as
|
||||
an ACL containing only the required ACL entries.
|
||||
.Pp
|
||||
The following option is available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl d
|
||||
The operation applies to the default ACL of a directory instead of the
|
||||
access ACL.
|
||||
An error shall be generated if a default ACL cannot be associated with
|
||||
.Op Ar file .
|
||||
.El
|
||||
.Pp
|
||||
The following operand is available:
|
||||
.Bl -tag -width indent
|
||||
.It Ar file
|
||||
A pathname of a file whose ACL shall be retrieved.
|
||||
If
|
||||
.Op Ar file
|
||||
is not specified, or a
|
||||
.Op Ar file
|
||||
is specified as "-", then
|
||||
.Nm
|
||||
shall read a list of pathnames, each terminated by one <newline> character,
|
||||
from the standard input.
|
||||
.El
|
||||
.Pp
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
.Dl getfacl /
|
||||
.Pp
|
||||
Retrieve ACL for the directory "/".
|
||||
.Pp
|
||||
.Dl getfacl -d /
|
||||
.Pp
|
||||
Retrieve the default ACL for the directory "/", if any.
|
||||
.Sh SEE ALSO
|
||||
.Xr setfacl 1 ,
|
||||
.Xr acl 3 ,
|
||||
.Xr getextattr 8 ,
|
||||
.Xr setextattr 8 ,
|
||||
.Xr acl 9 ,
|
||||
.Xr extattr 9
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be IEEE Std 1003.2c compliant.
|
||||
.Sh HISTORY
|
||||
Extended Attribute and Access Control List support was developed as part
|
||||
of the TrustedBSD Project and introduced in
|
||||
.Fx 5.0
|
||||
.Sh AUTHORS
|
||||
Robert N M Watson
|
201
bin/getfacl/getfacl.c
Normal file
201
bin/getfacl/getfacl.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*-
|
||||
* Copyright (c) 1999-2001 Robert N M Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
* getfacl -- POSIX.1e utility to extract ACLs from files and directories
|
||||
* and send the results to stdout
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int more_than_one = 0;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "getfacl [-d] [files ...]\n");
|
||||
}
|
||||
|
||||
static acl_t
|
||||
acl_from_stat(struct stat sb)
|
||||
{
|
||||
acl_t acl;
|
||||
|
||||
acl = acl_init(3);
|
||||
if (!acl)
|
||||
return(NULL);
|
||||
|
||||
acl->acl_entry[0].ae_tag = ACL_USER_OBJ;
|
||||
acl->acl_entry[0].ae_id = sb.st_uid;
|
||||
acl->acl_entry[0].ae_perm = 0;
|
||||
if (sb.st_mode & S_IRUSR)
|
||||
acl->acl_entry[0].ae_perm |= ACL_PERM_READ;
|
||||
if (sb.st_mode & S_IWUSR)
|
||||
acl->acl_entry[0].ae_perm |= ACL_PERM_WRITE;
|
||||
if (sb.st_mode & S_IXUSR)
|
||||
acl->acl_entry[0].ae_perm |= ACL_PERM_EXEC;
|
||||
|
||||
acl->acl_entry[1].ae_tag = ACL_GROUP_OBJ;
|
||||
acl->acl_entry[1].ae_id = sb.st_gid;
|
||||
acl->acl_entry[1].ae_perm = 0;
|
||||
if (sb.st_mode & S_IRGRP)
|
||||
acl->acl_entry[1].ae_perm |= ACL_PERM_READ;
|
||||
if (sb.st_mode & S_IWGRP)
|
||||
acl->acl_entry[1].ae_perm |= ACL_PERM_WRITE;
|
||||
if (sb.st_mode & S_IXGRP)
|
||||
acl->acl_entry[1].ae_perm |= ACL_PERM_EXEC;
|
||||
|
||||
acl->acl_entry[2].ae_tag = ACL_OTHER_OBJ;
|
||||
acl->acl_entry[2].ae_id = 0;
|
||||
acl->acl_entry[2].ae_perm = 0;
|
||||
if (sb.st_mode & S_IROTH)
|
||||
acl->acl_entry[2].ae_perm |= ACL_PERM_READ;
|
||||
if (sb.st_mode & S_IWOTH)
|
||||
acl->acl_entry[2].ae_perm |= ACL_PERM_WRITE;
|
||||
if (sb.st_mode & S_IXOTH)
|
||||
acl->acl_entry[2].ae_perm |= ACL_PERM_EXEC;
|
||||
|
||||
acl->acl_cnt = 3;
|
||||
|
||||
return(acl);
|
||||
}
|
||||
|
||||
static int
|
||||
print_acl(char *path, acl_type_t type)
|
||||
{
|
||||
struct stat sb;
|
||||
acl_t acl;
|
||||
char *acl_text;
|
||||
int error;
|
||||
|
||||
error = stat(path, &sb);
|
||||
if (error == -1) {
|
||||
perror(path);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (more_than_one)
|
||||
printf("\n");
|
||||
else
|
||||
more_than_one++;
|
||||
|
||||
printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid);
|
||||
|
||||
acl = acl_get_file(path, type);
|
||||
if (!acl) {
|
||||
if (errno != EOPNOTSUPP) {
|
||||
warn("%s", path);
|
||||
return(-1);
|
||||
}
|
||||
errno = 0;
|
||||
if (type != ACL_TYPE_ACCESS)
|
||||
return(0);
|
||||
acl = acl_from_stat(sb);
|
||||
if (!acl) {
|
||||
perror("acl_from_stat()");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
acl_text = acl_to_text(acl, 0);
|
||||
if (!acl_text) {
|
||||
perror(path);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
printf("%s", acl_text);
|
||||
|
||||
acl_free(acl);
|
||||
acl_free(acl_text);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
print_acl_from_stdin(acl_type_t type)
|
||||
{
|
||||
char pathname[PATH_MAX];
|
||||
int carried_error = 0;
|
||||
|
||||
pathname[sizeof(pathname) - 1] = '\0';
|
||||
while (fgets(pathname, sizeof(pathname), stdin)) {
|
||||
/* remove the \n */
|
||||
pathname[strlen(pathname) - 1] = '\0';
|
||||
if (print_acl(pathname, type) == -1) {
|
||||
carried_error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return(carried_error);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
acl_type_t type = ACL_TYPE_ACCESS;
|
||||
int carried_error = 0;
|
||||
int ch, error, i;
|
||||
|
||||
while ((ch = getopt(argc, argv, "d")) != -1)
|
||||
switch(ch) {
|
||||
case 'd':
|
||||
type = ACL_TYPE_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return(-1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0) {
|
||||
error = print_acl_from_stdin(type);
|
||||
return(error);
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-")) {
|
||||
error = print_acl_from_stdin(type);
|
||||
if (error == -1)
|
||||
carried_error = -1;
|
||||
} else {
|
||||
error = print_acl(argv[i], type);
|
||||
if (error == -1)
|
||||
carried_error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return(carried_error);
|
||||
}
|
11
bin/setfacl/Makefile
Normal file
11
bin/setfacl/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
CFLAGS+= -g ${BDECFLAGS}
|
||||
|
||||
PROG= setfacl
|
||||
SRCS= file.c mask.c merge.c remove.c setfacl.c util.c
|
||||
LDADD= -lposix1e
|
||||
|
||||
NOSHARED= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
74
bin/setfacl/file.c
Normal file
74
bin/setfacl/file.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Chris D. Faulhaber
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/acl.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
/* read acl text from a file and return the corresponding acl */
|
||||
acl_t
|
||||
get_acl_from_file(const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (!filename)
|
||||
err(EX_USAGE, "(null) filename in get_acl_from_file()");
|
||||
|
||||
bzero(&buf, sizeof(buf));
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
if (have_stdin)
|
||||
err(EX_USAGE, "cannot specify more than one stdin");
|
||||
file = stdin;
|
||||
have_stdin = 1;
|
||||
} else {
|
||||
file = fopen(filename, "r");
|
||||
if (!file)
|
||||
err(EX_OSERR, "fopen() %s failed", filename);
|
||||
}
|
||||
|
||||
fread(buf, sizeof(buf), 1, file);
|
||||
if (ferror(file)) {
|
||||
fclose(file);
|
||||
err(EX_USAGE, "error reading from %s", filename);
|
||||
} else if (!feof(file)) {
|
||||
fclose(file);
|
||||
errx(EX_USAGE, "line too long in %s", filename);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return acl_from_text(buf);
|
||||
}
|
100
bin/setfacl/mask.c
Normal file
100
bin/setfacl/mask.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Chris D. Faulhaber
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
/* set the appropriate mask the given ACL's */
|
||||
int
|
||||
set_acl_mask(acl_t prev_acl)
|
||||
{
|
||||
acl_t acl;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* ... if a mask entry is specified, then the permissions of the mask
|
||||
* entry in the resulting ACL shall be set to the permissions in the
|
||||
* specified ACL mask entry.
|
||||
*/
|
||||
if (have_mask)
|
||||
return 0;
|
||||
|
||||
acl = acl_dup(prev_acl);
|
||||
if (!acl)
|
||||
err(EX_OSERR, "acl_dup() failed");
|
||||
|
||||
if (!n_flag) {
|
||||
/*
|
||||
* If no mask entry is specified and the -n option is not
|
||||
* specified, then the permissions of the resulting ACL mask
|
||||
* entry shall be set to the union of the permissions
|
||||
* associated with all entries which belong to the file group
|
||||
* class in the resulting ACL
|
||||
*/
|
||||
if (acl_calc_mask(&acl)) {
|
||||
warn("acl_calc_mask() failed");
|
||||
acl_free(acl);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If no mask entry is specified and the -n option is
|
||||
* specified, then the permissions of the resulting ACL
|
||||
* mask entry shall remain unchanged ...
|
||||
*/
|
||||
for (i = 0; i < acl->acl_cnt; i++)
|
||||
if (acl->acl_entry[i].ae_tag == ACL_MASK) {
|
||||
acl_free(acl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no mask entry is specified, the -n option is specified,
|
||||
* and no ACL mask entry exists in the ACL associated with the
|
||||
* file, then write an error message to standard error and
|
||||
* continue with the next file.
|
||||
*/
|
||||
warnx("warning: no mask entry");
|
||||
acl_free(acl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*prev_acl = *acl;
|
||||
acl_free(acl);
|
||||
|
||||
return 0;
|
||||
}
|
113
bin/setfacl/merge.c
Normal file
113
bin/setfacl/merge.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Chris D. Faulhaber
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
/* merge acl into existing file's ACL */
|
||||
int
|
||||
merge_acl(acl_t acl, acl_t *prev_acl)
|
||||
{
|
||||
acl_t acl_new;
|
||||
int blank_acl_user, blank_acl_group, have_entry, i, j;
|
||||
struct stat sb;
|
||||
|
||||
blank_acl_user = blank_acl_group = 0;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
acl_new = acl_dup(prev_acl[0]);
|
||||
else
|
||||
acl_new = acl_dup(prev_acl[1]);
|
||||
if (!acl_new)
|
||||
err(EX_OSERR, "acl_dup() failed");
|
||||
|
||||
/* step through new ACL entries */
|
||||
for (i = 0; i < acl->acl_cnt; i++) {
|
||||
have_entry = 0;
|
||||
|
||||
/* oh look, we have an ACL_MASK entry */
|
||||
if (acl->acl_entry[i].ae_tag == ACL_MASK)
|
||||
have_mask = 1;
|
||||
|
||||
/* check against the existing ACL entries */
|
||||
for (j = 0; j < acl_new->acl_cnt && !have_entry; j++) {
|
||||
if (acl_new->acl_entry[j].ae_tag ==
|
||||
acl->acl_entry[i].ae_tag) {
|
||||
switch(acl->acl_entry[i].ae_tag) {
|
||||
case ACL_USER_OBJ:
|
||||
acl_new->acl_entry[j].ae_perm =
|
||||
acl->acl_entry[i].ae_perm;
|
||||
acl_new->acl_entry[j].ae_id = sb.st_uid;
|
||||
have_entry = 1;
|
||||
break;
|
||||
case ACL_GROUP_OBJ:
|
||||
acl_new->acl_entry[j].ae_perm =
|
||||
acl->acl_entry[i].ae_perm;
|
||||
acl_new->acl_entry[j].ae_id = sb.st_gid;
|
||||
have_entry = 1;
|
||||
break;
|
||||
default:
|
||||
if (acl_new->acl_entry[j].ae_id ==
|
||||
acl->acl_entry[i].ae_id) {
|
||||
/* any other matches */
|
||||
acl_new->acl_entry[j].ae_perm =
|
||||
acl->acl_entry[i].ae_perm;
|
||||
have_entry = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if this entry has not been found, it must be new */
|
||||
if (!have_entry) {
|
||||
if (acl_new->acl_cnt == ACL_MAX_ENTRIES) {
|
||||
warn("too many ACL entries");
|
||||
acl_free(acl_new);
|
||||
return -1;
|
||||
}
|
||||
acl_new->acl_entry[acl_new->acl_cnt++] =
|
||||
acl->acl_entry[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
*prev_acl[0] = *acl_new;
|
||||
else
|
||||
*prev_acl[1] = *acl_new;
|
||||
acl_free(acl_new);
|
||||
|
||||
return 0;
|
||||
}
|
155
bin/setfacl/remove.c
Normal file
155
bin/setfacl/remove.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Chris D. Faulhaber
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
/* remove ACL entries from an ACL */
|
||||
int
|
||||
remove_acl(acl_t acl, acl_t *prev_acl)
|
||||
{
|
||||
acl_t acl_new;
|
||||
int carried_error, i;
|
||||
|
||||
carried_error = 0;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
acl_new = acl_dup(prev_acl[0]);
|
||||
else
|
||||
acl_new = acl_dup(prev_acl[1]);
|
||||
if (!acl_new)
|
||||
err(EX_OSERR, "acl_dup() failed");
|
||||
|
||||
/* find and delete the entry */
|
||||
for (i = 0; i < acl->acl_cnt; i++) {
|
||||
if (acl->acl_entry[i].ae_tag == ACL_MASK)
|
||||
have_mask++;
|
||||
if (acl_delete_entry(acl_new, &acl->acl_entry[i]) == -1) {
|
||||
carried_error++;
|
||||
warnx("cannot remove non-existent acl entry");
|
||||
}
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS) {
|
||||
acl_free(prev_acl[0]);
|
||||
prev_acl[0] = acl_new;
|
||||
} else {
|
||||
acl_free(prev_acl[1]);
|
||||
prev_acl[1] = acl_new;
|
||||
}
|
||||
|
||||
if (carried_error)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* remove default entries */
|
||||
int
|
||||
remove_default(acl_t *prev_acl)
|
||||
{
|
||||
|
||||
if (prev_acl[1]) {
|
||||
bzero(prev_acl[1], sizeof(struct acl));
|
||||
prev_acl[1]->acl_cnt = 0;
|
||||
} else {
|
||||
warn("cannot remove default ACL");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* remove extended entries */
|
||||
void
|
||||
remove_ext(acl_t *prev_acl)
|
||||
{
|
||||
acl_t acl_new, acl_old;
|
||||
acl_perm_t group_perm, mask_perm;
|
||||
int have_mask_entry, i;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
acl_old = acl_dup(prev_acl[0]);
|
||||
else
|
||||
acl_old = acl_dup(prev_acl[1]);
|
||||
if (!acl_old)
|
||||
err(EX_OSERR, "acl_dup() failed");
|
||||
|
||||
group_perm = mask_perm = 0;
|
||||
have_mask_entry = 0;
|
||||
acl_new = acl_init(ACL_MAX_ENTRIES);
|
||||
if (!acl_new)
|
||||
err(EX_OSERR, "%s", "acl_init() failed");
|
||||
|
||||
/* only save the default user/group/other entries */
|
||||
for (i = 0; i < acl_old->acl_cnt; i++)
|
||||
switch(acl_old->acl_entry[i].ae_tag) {
|
||||
case ACL_USER_OBJ:
|
||||
acl_new->acl_entry[0] = acl_old->acl_entry[i];
|
||||
break;
|
||||
case ACL_GROUP_OBJ:
|
||||
acl_new->acl_entry[1] = acl_old->acl_entry[i];
|
||||
group_perm = acl_old->acl_entry[i].ae_perm;
|
||||
break;
|
||||
case ACL_OTHER_OBJ:
|
||||
acl_new->acl_entry[2] = acl_old->acl_entry[i];
|
||||
break;
|
||||
case ACL_MASK:
|
||||
mask_perm = acl_old->acl_entry[i].ae_perm;
|
||||
have_mask_entry = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If the ACL contains a mask entry, then the permissions associated
|
||||
* with the owning group entry in the resulting ACL shall be set to
|
||||
* only those permissions associated with both the owning group entry
|
||||
* and the mask entry of the current ACL.
|
||||
*/
|
||||
if (have_mask_entry)
|
||||
acl_new->acl_entry[1].ae_perm = group_perm & mask_perm;
|
||||
acl_new->acl_cnt = 3;
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS) {
|
||||
acl_free(prev_acl[0]);
|
||||
prev_acl[0] = acl_new;
|
||||
} else {
|
||||
acl_free(prev_acl[1]);
|
||||
prev_acl[1] = acl_new;
|
||||
}
|
||||
|
||||
have_mask = 0;
|
||||
}
|
229
bin/setfacl/setfacl.1
Normal file
229
bin/setfacl/setfacl.1
Normal file
@ -0,0 +1,229 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Chris D. Faulhaber
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 7, 2001
|
||||
.Dt SETFACL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm setfacl
|
||||
.Nd Set ACL Information
|
||||
.Sh SYNOPSIS
|
||||
.Nm setfacl
|
||||
.Op Fl bdkn
|
||||
.Op Fl m Ar entries
|
||||
.Op Fl M Ar file1
|
||||
.Op Fl x Ar entries
|
||||
.Op Fl X Ar file1
|
||||
.Op Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility sets discretionary access control information on
|
||||
the specified file(s).
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl b
|
||||
Remove all ACL entries except for the three required entries.
|
||||
.It Fl d
|
||||
The operations apply to the default ACL entries instead of
|
||||
access ACL entries. Currently only directories may have
|
||||
default ACL's.
|
||||
.It Fl k
|
||||
Delete any default ACL entries on the specified files. It
|
||||
is not considered an error if the specified files do not have
|
||||
any default ACL entries. An error will be reported if any of
|
||||
the specified files cannot have a default entry (i.e.
|
||||
non-directories).
|
||||
.It Fl m Ar entries
|
||||
Modify the ACL entries on the specified files by adding new
|
||||
entries and modifying existing ACL entries with the ACL entries
|
||||
specified in
|
||||
.Ar entries .
|
||||
.It Fl M Ar file
|
||||
Modify the ACL entries on the specified files by adding new
|
||||
ACL entries and modifying existing ACL entries with the ACL
|
||||
entries specified in the file
|
||||
.Ar file .
|
||||
If
|
||||
.Ar file
|
||||
is "-", the input is taken from stdin.
|
||||
.It Fl n
|
||||
Do not recalculate the permissions associated with the ACL
|
||||
mask entry.
|
||||
.It Fl x Ar entries
|
||||
Remove the ACL entries specified in
|
||||
.Ar entries
|
||||
from the access or default ACL of the specified files.
|
||||
.It Fl X Ar file
|
||||
Remove the ACL entries specified in the file
|
||||
.Ar file
|
||||
from the access or default ACL of the specified files.
|
||||
.El
|
||||
.Pp
|
||||
The above options are evaluated in the order specified
|
||||
on the command-line.
|
||||
.Pp
|
||||
Multiple ACL entries specified on the command line shall be
|
||||
separated by commas.
|
||||
.Sh ACL ENTRIES
|
||||
An ACL entry shall contain three colon-separated fields:
|
||||
an ACL tag, an ACL qualifier, and discretionary access
|
||||
permissions:
|
||||
.Pp
|
||||
.Bl -tag -width indent
|
||||
.It Ar ACL tag
|
||||
The ACL tag specifies the ACL entry type and shall consist of
|
||||
one of the following: ``user'' or ``u'' specifying the access
|
||||
granted to the owner of the file or a specified user; ``group''
|
||||
or ``g'' specifying the access granted to the file owning group
|
||||
or a specified group; ``other'' or ``o'' specifying the access
|
||||
granted to any process that does not match any user or group
|
||||
ACL entry; ``mask'' or ``m'' specifying the maximum access
|
||||
granted to any ACL entry except the
|
||||
.Ar user
|
||||
ACL entry for the file owner and the
|
||||
.Ar other
|
||||
ACL entry.
|
||||
.Pp
|
||||
.It Ar ACL qualifier
|
||||
The ACL qualifier field describes the user or group associated with
|
||||
the ACL entry. It may consist of one of the following: uid or
|
||||
user name, gid or group name, or empty. For
|
||||
.Ar user
|
||||
ACL entries, an empty field shall specify access granted to the
|
||||
file owner. For
|
||||
.Ar group
|
||||
ACL entries, an empty field shall specify access granted to the
|
||||
file owning group.
|
||||
.Ar mask
|
||||
and
|
||||
.Ar other
|
||||
ACL entries do not use this field.
|
||||
.Pp
|
||||
.It Ar access permissions
|
||||
The access permissions field shall contain up to one of each of
|
||||
the following: ``r'', ``w'', and ``x'' to set read, write, and
|
||||
execute permissions, respectively. Each of these may be excluded
|
||||
or replaced with a ``-'' character to indicate no access.
|
||||
.El
|
||||
.Pp
|
||||
A
|
||||
.Ar mask
|
||||
ACL entry is required on a file with any ACL entries other than
|
||||
the default
|
||||
.Ar user ,
|
||||
.Ar group ,
|
||||
and
|
||||
.Ar other
|
||||
ACL entries. If the
|
||||
.Fl n
|
||||
option is not specified and no
|
||||
.Ar mask
|
||||
ACL entry was specified, the
|
||||
.Nm
|
||||
utility
|
||||
will apply a
|
||||
.Ar mask
|
||||
ACL entry consisting of the union of the permissions associated
|
||||
with all
|
||||
.Ar group
|
||||
ACL entries in the resulting ACL.
|
||||
.Pp
|
||||
ACL entries applied from a file using the
|
||||
.Fl M
|
||||
or
|
||||
.Fl X
|
||||
options shall be of the following form: one ACL entry per line, as
|
||||
previously specified; whitespace is ignored; any text after a # is
|
||||
ignored (comments).
|
||||
.Pp
|
||||
When ACL entries are evaluated, the access check algorithm checks
|
||||
the ACL entries in the following order: file owner,
|
||||
.Ar user
|
||||
ACL entries, file owning group,
|
||||
.Ar group
|
||||
ACL entries, and
|
||||
.Ar other
|
||||
ACL entry.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Nm
|
||||
utility returns 0 on success and > 0 if an error occurs.
|
||||
.Sh EXAMPLES
|
||||
.Dl setfacl -m u::rwx,g:mail:rw file
|
||||
.Pp
|
||||
Sets read, write, and execute permissions for the
|
||||
.Pa file
|
||||
owner's ACL entry and read and write permissions for group mail on
|
||||
.Pa file .
|
||||
.Pp
|
||||
.Dl setfacl -M file1 file2
|
||||
.Pp
|
||||
Sets/updates the ACL entries contained in
|
||||
.Pa file1
|
||||
on
|
||||
.Pa file2 .
|
||||
.Pp
|
||||
.Dl setfacl -x g:mail:rw file
|
||||
.Pp
|
||||
Remove the group mail ACL entry containing read/write permissions
|
||||
from
|
||||
.Pa file.
|
||||
.Pp
|
||||
.Dl setfacl -b file
|
||||
.Pp
|
||||
Remove all ACL entries except for the three required
|
||||
entries from
|
||||
.Pa file .
|
||||
.Pp
|
||||
.Dl getfacl file1 | setfacl -b -n -M - file2
|
||||
.Pp
|
||||
Copy ACL entries from
|
||||
.Pa file1
|
||||
to
|
||||
.Pa file2 .
|
||||
.Sh SEE ALSO
|
||||
.Xr getfacl 1 ,
|
||||
.Xr acl 3 ,
|
||||
.Xr getextattr 8 ,
|
||||
.Xr setextattr 8 ,
|
||||
.Xr acl 9 ,
|
||||
.Xr extattr 9 .
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be IEEE Std 1003.2c compliant.
|
||||
.Sh HISTORY
|
||||
Extended Attribute and Access Control List support was developed
|
||||
as part of the TrustedBSD Project and introduced in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Chris D. Faulhaber Aq jedgar@fxp.org .
|
254
bin/setfacl/setfacl.c
Normal file
254
bin/setfacl/setfacl.c
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Chris D. Faulhaber
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
struct sf_file *file;
|
||||
|
||||
if (strlen(filename) > PATH_MAX - 1) {
|
||||
warn("illegal filename");
|
||||
return;
|
||||
}
|
||||
file = zmalloc(sizeof(struct sf_file));
|
||||
file->filename = filename;
|
||||
STAILQ_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);
|
||||
acl[0] = acl_get_file(filename, ACL_TYPE_ACCESS);
|
||||
if (!acl[0])
|
||||
err(EX_OSERR, "acl_get_file() failed");
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
acl[1] = acl_get_file(filename, ACL_TYPE_DEFAULT);
|
||||
if (!acl[1])
|
||||
err(EX_OSERR, "acl_get_file() failed");
|
||||
} else
|
||||
acl[1] = NULL;
|
||||
|
||||
return acl;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: setfacl [-bdknv] [-m entries] [-M file1] "
|
||||
"[-x entries] [-X file2] [file ...]\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
acl_t *acl, final_acl;
|
||||
char filename[PATH_MAX];
|
||||
int local_error, carried_error, ch, i;
|
||||
struct sf_file *file;
|
||||
struct sf_entry *entry;
|
||||
|
||||
acl_type = ACL_TYPE_ACCESS;
|
||||
carried_error = local_error = 0;
|
||||
have_mask = have_stdin = n_flag = need_mask = 0;
|
||||
|
||||
STAILQ_INIT(&entrylist);
|
||||
STAILQ_INIT(&filelist);
|
||||
|
||||
while ((ch = getopt(argc, argv, "M:X:bdkm:nx:")) != -1)
|
||||
switch(ch) {
|
||||
case 'M':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->acl = get_acl_from_file(optarg);
|
||||
if (!entry->acl)
|
||||
err(EX_OSERR, "get_acl_from_file() failed");
|
||||
entry->op = OP_MERGE_ACL;
|
||||
STAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'X':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->acl = get_acl_from_file(optarg);
|
||||
entry->op = OP_REMOVE_ACL;
|
||||
STAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'b':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->op = OP_REMOVE_EXT;
|
||||
STAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'd':
|
||||
acl_type = ACL_TYPE_DEFAULT;
|
||||
break;
|
||||
case 'k':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->op = OP_REMOVE_DEF;
|
||||
STAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'm':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->acl = acl_from_text(optarg);
|
||||
if (!entry->acl)
|
||||
err(EX_USAGE, "acl_from_text() failed");
|
||||
entry->op = OP_MERGE_ACL;
|
||||
STAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
case 'n':
|
||||
n_flag++;
|
||||
break;
|
||||
case 'x':
|
||||
entry = zmalloc(sizeof(struct sf_entry));
|
||||
entry->acl = acl_from_text(optarg);
|
||||
if (!entry->acl)
|
||||
err(EX_USAGE, "acl_from_text() failed");
|
||||
entry->op = OP_REMOVE_ACL;
|
||||
STAILQ_INSERT_TAIL(&entrylist, entry, next);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (STAILQ_EMPTY(&entrylist))
|
||||
usage();
|
||||
|
||||
/* take list of files from stdin */
|
||||
if (argc == 0 || !strcmp(argv[0], "-")) {
|
||||
if (have_stdin)
|
||||
err(EX_USAGE, "cannot have more than one stdin");
|
||||
have_stdin = 1;
|
||||
bzero(&filename, sizeof(filename));
|
||||
while (fgets(filename, sizeof(filename), stdin)) {
|
||||
/* remove the \n */
|
||||
filename[strlen(filename) - 1] = '\0';
|
||||
add_filename(filename);
|
||||
}
|
||||
} else
|
||||
for (i = 0; i < argc; i++)
|
||||
add_filename(argv[i]);
|
||||
|
||||
/* cycle through each file */
|
||||
STAILQ_FOREACH(file, &filelist, next) {
|
||||
/* get our initial access and default ACL's */
|
||||
acl = get_file_acls(file->filename);
|
||||
if (!acl)
|
||||
continue;
|
||||
if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) {
|
||||
warnx("Default ACL not valid for %s", file->filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
local_error = 0;
|
||||
|
||||
/* cycle through each option */
|
||||
STAILQ_FOREACH(entry, &entrylist, next) {
|
||||
if (local_error)
|
||||
continue;
|
||||
|
||||
switch(entry->op) {
|
||||
case OP_MERGE_ACL:
|
||||
local_error += merge_acl(entry->acl, acl);
|
||||
need_mask = 1;
|
||||
break;
|
||||
case OP_REMOVE_EXT:
|
||||
remove_ext(acl);
|
||||
need_mask = 0;
|
||||
break;
|
||||
case OP_REMOVE_DEF:
|
||||
if (acl_delete_def_file(file->filename) == -1) {
|
||||
warn("acl_delete_def_file() failed");
|
||||
local_error++;
|
||||
}
|
||||
local_error += remove_default(acl);
|
||||
need_mask = 0;
|
||||
break;
|
||||
case OP_REMOVE_ACL:
|
||||
local_error += remove_acl(entry->acl, acl);
|
||||
need_mask = 1;
|
||||
break;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
/* don't bother setting the ACL if something is broken */
|
||||
if (local_error) {
|
||||
carried_error++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (acl_type == ACL_TYPE_ACCESS)
|
||||
final_acl = acl[0];
|
||||
else
|
||||
final_acl = acl[1];
|
||||
|
||||
if (need_mask && (set_acl_mask(final_acl) == -1)) {
|
||||
warnx("failed to set ACL mask on %s", file->filename);
|
||||
carried_error++;
|
||||
} else if (acl_set_file(file->filename, acl_type,
|
||||
final_acl) == -1) {
|
||||
carried_error++;
|
||||
warn("acl_set_file() failed for %s", file->filename);
|
||||
}
|
||||
|
||||
acl_free(acl[0]);
|
||||
acl_free(acl[1]);
|
||||
free(acl);
|
||||
}
|
||||
|
||||
return carried_error;
|
||||
}
|
47
bin/setfacl/util.c
Normal file
47
bin/setfacl/util.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Chris D. Faulhaber
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "setfacl.h"
|
||||
|
||||
void *
|
||||
zmalloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = malloc(size);
|
||||
if (!ptr)
|
||||
err(EX_OSERR, "malloc() failed");
|
||||
bzero(ptr, size);
|
||||
|
||||
return ptr;
|
||||
}
|
Loading…
Reference in New Issue
Block a user