getfacl: implement --skip-base (-s)

This skips files that only have a trivial ACL, which is useful for
callers that want to examine files with more unique ACLs.

While we're here, don't issue the file name/ownership header if we're
just going to error out on the file; this adds extra noise for little
gain.

Reviewed by:	markj, olce
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D40603
This commit is contained in:
Kyle Evans 2025-04-20 22:57:45 -05:00
parent ec8e79c4e4
commit 8bf37c868f
2 changed files with 56 additions and 22 deletions

View file

@ -75,6 +75,11 @@ Ignored for POSIX.1e ACLs.
Do not write commented information about file name and ownership.
This is
useful when dealing with filenames with unprintable characters.
.It Fl s , Fl -skip-base
Skip files that only have a trivial ACL, as defined by
.Xr acl_is_trivial_np 3 .
Notably, files with POSIX.1e ACLs that only represent the owner, group and other
to match the mode of the file will be skipped.
.It Fl v
For NFSv4 ACLs, display access mask and flags in a verbose form.
Ignored for POSIX.1e ACLs.

View file

@ -52,6 +52,7 @@ static const struct option long_options[] =
{ "default", no_argument, NULL, 'd' },
{ "numeric", no_argument, NULL, 'n' },
{ "omit-header", no_argument, NULL, 'q' },
{ "skip-base", no_argument, NULL, 's' },
{ NULL, no_argument, NULL, 0 },
};
@ -90,7 +91,7 @@ getgname(gid_t gid)
static int
print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag,
int qflag, int vflag)
int qflag, int vflag, int sflag)
{
struct stat sb;
acl_t acl;
@ -122,25 +123,49 @@ print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag,
return (-1);
}
if (more_than_one)
printf("\n");
else
more_than_one++;
if (!qflag)
printf("# file: %s\n# owner: %s\n# group: %s\n", path,
getuname(sb.st_uid), getgname(sb.st_gid));
if (hflag)
acl = acl_get_link_np(path, type);
else
acl = acl_get_file(path, type);
if (!acl) {
if (errno != EOPNOTSUPP) {
warn("%s", path);
return(-1);
if (!acl && errno != EOPNOTSUPP) {
warn("%s", path);
return(-1);
}
if (sflag) {
int trivial;
/*
* With the -s flag, we shouldn't synthesize a trivial ACL if
* they aren't supported as we do below.
*/
if (!acl)
return(0);
/*
* We also shouldn't render anything for this path if it's a
* trivial ACL. If we error out, we'll issue a warning but
* proceed with this file to err on the side of caution.
*/
error = acl_is_trivial_np(acl, &trivial);
if (error != 0) {
warn("%s: acl_is_trivial_np failed", path);
} else if (trivial) {
(void)acl_free(acl);
return(0);
}
errno = 0;
}
if (more_than_one)
printf("\n");
else
more_than_one++;
if (!qflag)
printf("# file: %s\n# owner: %s\n# group: %s\n", path,
getuname(sb.st_uid), getgname(sb.st_gid));
if (!acl) {
if (type == ACL_TYPE_DEFAULT)
return(0);
acl = acl_from_mode_np(sb.st_mode);
@ -176,7 +201,7 @@ print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag,
static int
print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag,
int qflag, int vflag)
int qflag, int vflag, int sflag)
{
char *p, pathname[PATH_MAX];
int carried_error = 0;
@ -185,7 +210,7 @@ print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag,
if ((p = strchr(pathname, '\n')) != NULL)
*p = '\0';
if (print_acl(pathname, type, hflag, iflag, nflag,
qflag, vflag) == -1) {
qflag, vflag, sflag) == -1) {
carried_error = -1;
}
}
@ -199,14 +224,15 @@ main(int argc, char *argv[])
acl_type_t type = ACL_TYPE_ACCESS;
int carried_error = 0;
int ch, error, i;
int hflag, iflag, qflag, nflag, vflag;
int hflag, iflag, qflag, nflag, sflag, vflag;
hflag = 0;
iflag = 0;
qflag = 0;
nflag = 0;
sflag = 0;
vflag = 0;
while ((ch = getopt_long(argc, argv, "+dhinqv", long_options,
while ((ch = getopt_long(argc, argv, "+dhinqsv", long_options,
NULL)) != -1)
switch(ch) {
case 'd':
@ -224,6 +250,9 @@ main(int argc, char *argv[])
case 'q':
qflag = 1;
break;
case 's':
sflag = 1;
break;
case 'v':
vflag = 1;
break;
@ -236,19 +265,19 @@ main(int argc, char *argv[])
if (argc == 0) {
error = print_acl_from_stdin(type, hflag, iflag, nflag,
qflag, vflag);
qflag, vflag, sflag);
return(error ? 1 : 0);
}
for (i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-")) {
error = print_acl_from_stdin(type, hflag, iflag, nflag,
qflag, vflag);
qflag, vflag, sflag);
if (error == -1)
carried_error = -1;
} else {
error = print_acl(argv[i], type, hflag, iflag, nflag,
qflag, vflag);
qflag, vflag, sflag);
if (error == -1)
carried_error = -1;
}