diff --git a/bin/getfacl/getfacl.1 b/bin/getfacl/getfacl.1 index b2b6294c46de..475c86e275bc 100644 --- a/bin/getfacl/getfacl.1 +++ b/bin/getfacl/getfacl.1 @@ -1,135 +1,140 @@ .\"- .\" Copyright (c) 2000, 2001, 2002 Robert N. M. Watson .\" All rights reserved. .\" .\" This software was developed by Robert Watson for the TrustedBSD Project. .\" .\" 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. .\" .\" Developed by the TrustedBSD Project. .\" Support for POSIX.1e access control lists. .\" .Dd June 19, 2023 .Dt GETFACL 1 .Os .Sh NAME .Nm getfacl .Nd get ACL information .Sh SYNOPSIS .Nm .Op Fl dhinqv .Op Ar .Sh DESCRIPTION The .Nm utility writes discretionary access control information associated with the specified file(s) to standard output. If the .Xr getconf 1 utility indicates that .Brq 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 , Fl -default The operation applies to the default ACL of a directory instead of the access ACL. An error is generated if a default ACL cannot be associated with .Ar file . This option is not valid for NFSv4 ACLs. .It Fl h If the target of the operation is a symbolic link, return the ACL from the symbolic link itself rather than following the link. .It Fl i For NFSv4 ACLs, append numerical ID at the end of each entry containing user or group name. Ignored for POSIX.1e ACLs. .It Fl n , Fl -numeric Display user and group IDs numerically rather than converting to a user or group name. Ignored for POSIX.1e ACLs. .It Fl q , Fl -omit-header 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. .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 .Ar file is not specified, or a .Ar file is specified as .Fl , then .Nm reads a list of pathnames, each terminated by one newline character, from the standard input. .El .Pp For an explanation of the ACL syntax, see the .Xr setfacl 1 manual page. .Sh EXIT STATUS .Ex -std .Sh EXAMPLES .Dl getfacl / .Pp Retrieve ACL for the directory .Pa / . .Pp .Dl getfacl -d / .Pp Retrieve the default ACL for the directory .Pa / , 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 .Tn IEEE Std 1003.2c compliant. .Sh HISTORY Extended Attribute and Access Control List support was developed as part of the .Tn TrustedBSD Project and introduced in .Fx 5.0 . .Sh AUTHORS .An Robert N M Watson diff --git a/bin/getfacl/getfacl.c b/bin/getfacl/getfacl.c index 2b98f923d618..5f55819c81a1 100644 --- a/bin/getfacl/getfacl.c +++ b/bin/getfacl/getfacl.c @@ -1,258 +1,287 @@ /*- * Copyright (c) 1999, 2001, 2002 Robert N M Watson * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * 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. */ /* * getfacl -- POSIX.1e utility to extract ACLs from files and directories * and send the results to stdout */ #include #include #include #include #include #include #include #include #include #include #include #include #include static int more_than_one = 0; 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 }, }; static void usage(void) { fprintf(stderr, "getfacl [-dhnqv] [file ...]\n"); } static char * getuname(uid_t uid) { struct passwd *pw; static char uids[10]; if ((pw = getpwuid(uid)) == NULL) { (void)snprintf(uids, sizeof(uids), "%u", uid); return (uids); } else return (pw->pw_name); } static char * getgname(gid_t gid) { struct group *gr; static char gids[10]; if ((gr = getgrgid(gid)) == NULL) { (void)snprintf(gids, sizeof(gids), "%u", gid); return (gids); } else return (gr->gr_name); } 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; char *acl_text; int error, flags = 0, ret; if (hflag) error = lstat(path, &sb); else error = stat(path, &sb); if (error == -1) { warn("%s: stat() failed", path); return(-1); } if (hflag) ret = lpathconf(path, _PC_ACL_NFS4); else ret = pathconf(path, _PC_ACL_NFS4); if (ret > 0) { if (type == ACL_TYPE_DEFAULT) { warnx("%s: there are no default entries in NFSv4 ACLs", path); return (-1); } type = ACL_TYPE_NFS4; } else if (ret < 0 && errno != EINVAL) { warn("%s: pathconf(..., _PC_ACL_NFS4) failed", path); return (-1); } + if (hflag) + acl = acl_get_link_np(path, type); + else + acl = acl_get_file(path, type); + + 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); + } + } + 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); - } - errno = 0; if (type == ACL_TYPE_DEFAULT) return(0); acl = acl_from_mode_np(sb.st_mode); if (!acl) { warn("%s: acl_from_mode() failed", path); return(-1); } } if (iflag) flags |= ACL_TEXT_APPEND_ID; if (nflag) flags |= ACL_TEXT_NUMERIC_IDS; if (vflag) flags |= ACL_TEXT_VERBOSE; acl_text = acl_to_text_np(acl, 0, flags); if (!acl_text) { warn("%s: acl_to_text_np() failed", path); (void)acl_free(acl); return(-1); } printf("%s", acl_text); (void)acl_free(acl); (void)acl_free(acl_text); return(0); } 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; while (fgets(pathname, (int)sizeof(pathname), stdin)) { 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; } } return(carried_error); } int 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': type = ACL_TYPE_DEFAULT; break; case 'h': hflag = 1; break; case 'i': iflag = 1; break; case 'n': nflag = 1; break; case 'q': qflag = 1; break; + case 's': + sflag = 1; + break; case 'v': vflag = 1; break; default: usage(); return(-1); } argc -= optind; argv += optind; 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; } } return(carried_error ? 1 : 0); }