143960f15SRobert Watson /*-
28051fddeSRobert Watson * Copyright (c) 1999, 2001, 2002 Robert N M Watson
343960f15SRobert Watson * All rights reserved.
443960f15SRobert Watson *
59331ef53SRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project.
69331ef53SRobert Watson *
743960f15SRobert Watson * Redistribution and use in source and binary forms, with or without
843960f15SRobert Watson * modification, are permitted provided that the following conditions
943960f15SRobert Watson * are met:
1043960f15SRobert Watson * 1. Redistributions of source code must retain the above copyright
1143960f15SRobert Watson * notice, this list of conditions and the following disclaimer.
1243960f15SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
1343960f15SRobert Watson * notice, this list of conditions and the following disclaimer in the
1443960f15SRobert Watson * documentation and/or other materials provided with the distribution.
1543960f15SRobert Watson *
1643960f15SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1743960f15SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1843960f15SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1943960f15SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2043960f15SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2143960f15SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2243960f15SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2343960f15SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2443960f15SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2543960f15SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2643960f15SRobert Watson * SUCH DAMAGE.
2743960f15SRobert Watson */
2843960f15SRobert Watson /*
2943960f15SRobert Watson * getfacl -- POSIX.1e utility to extract ACLs from files and directories
3043960f15SRobert Watson * and send the results to stdout
3143960f15SRobert Watson */
3243960f15SRobert Watson
3343960f15SRobert Watson #include <sys/types.h>
3443960f15SRobert Watson #include <sys/param.h>
3543960f15SRobert Watson #include <sys/acl.h>
3643960f15SRobert Watson #include <sys/stat.h>
375eb43ac2SDavid E. O'Brien
3843960f15SRobert Watson #include <err.h>
3943960f15SRobert Watson #include <errno.h>
40c5771451SKevin Lo #include <grp.h>
41c5771451SKevin Lo #include <pwd.h>
4243960f15SRobert Watson #include <stdio.h>
437a832d43SChris D. Faulhaber #include <stdlib.h>
4428bf3202SKris Kennaway #include <string.h>
4543960f15SRobert Watson #include <unistd.h>
4643960f15SRobert Watson
47ae824d80SEd Schouten static int more_than_one = 0;
4843960f15SRobert Watson
4943960f15SRobert Watson static void
usage(void)5043960f15SRobert Watson usage(void)
5143960f15SRobert Watson {
5243960f15SRobert Watson
5383bd4cd0SEdward Tomasz Napierala fprintf(stderr, "getfacl [-dhnqv] [file ...]\n");
5443960f15SRobert Watson }
5543960f15SRobert Watson
56c5771451SKevin Lo static char *
getuname(uid_t uid)57c5771451SKevin Lo getuname(uid_t uid)
58c5771451SKevin Lo {
59c5771451SKevin Lo struct passwd *pw;
60c5771451SKevin Lo static char uids[10];
61c5771451SKevin Lo
62c5771451SKevin Lo if ((pw = getpwuid(uid)) == NULL) {
63c5771451SKevin Lo (void)snprintf(uids, sizeof(uids), "%u", uid);
64c5771451SKevin Lo return (uids);
65c5771451SKevin Lo } else
66c5771451SKevin Lo return (pw->pw_name);
67c5771451SKevin Lo }
68c5771451SKevin Lo
69c5771451SKevin Lo static char *
getgname(gid_t gid)70c5771451SKevin Lo getgname(gid_t gid)
71c5771451SKevin Lo {
72c5771451SKevin Lo struct group *gr;
73c5771451SKevin Lo static char gids[10];
74c5771451SKevin Lo
75c5771451SKevin Lo if ((gr = getgrgid(gid)) == NULL) {
76c5771451SKevin Lo (void)snprintf(gids, sizeof(gids), "%u", gid);
77c5771451SKevin Lo return (gids);
78c5771451SKevin Lo } else
79c5771451SKevin Lo return (gr->gr_name);
80c5771451SKevin Lo }
81c5771451SKevin Lo
8243960f15SRobert Watson static int
print_acl(char * path,acl_type_t type,int hflag,int iflag,int nflag,int qflag,int vflag)8383bd4cd0SEdward Tomasz Napierala print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag,
8483bd4cd0SEdward Tomasz Napierala int qflag, int vflag)
8543960f15SRobert Watson {
8643960f15SRobert Watson struct stat sb;
8743960f15SRobert Watson acl_t acl;
8843960f15SRobert Watson char *acl_text;
8983bd4cd0SEdward Tomasz Napierala int error, flags = 0, ret;
9043960f15SRobert Watson
918051fddeSRobert Watson if (hflag)
928051fddeSRobert Watson error = lstat(path, &sb);
938051fddeSRobert Watson else
9443960f15SRobert Watson error = stat(path, &sb);
9543960f15SRobert Watson if (error == -1) {
9683bd4cd0SEdward Tomasz Napierala warn("%s: stat() failed", path);
9783bd4cd0SEdward Tomasz Napierala return(-1);
9883bd4cd0SEdward Tomasz Napierala }
9983bd4cd0SEdward Tomasz Napierala
10083bd4cd0SEdward Tomasz Napierala if (hflag)
10183bd4cd0SEdward Tomasz Napierala ret = lpathconf(path, _PC_ACL_NFS4);
10283bd4cd0SEdward Tomasz Napierala else
10383bd4cd0SEdward Tomasz Napierala ret = pathconf(path, _PC_ACL_NFS4);
10483bd4cd0SEdward Tomasz Napierala if (ret > 0) {
10583bd4cd0SEdward Tomasz Napierala if (type == ACL_TYPE_DEFAULT) {
10683bd4cd0SEdward Tomasz Napierala warnx("%s: there are no default entries in NFSv4 ACLs",
10783bd4cd0SEdward Tomasz Napierala path);
10883bd4cd0SEdward Tomasz Napierala return (-1);
10983bd4cd0SEdward Tomasz Napierala }
11083bd4cd0SEdward Tomasz Napierala type = ACL_TYPE_NFS4;
11183bd4cd0SEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) {
11283bd4cd0SEdward Tomasz Napierala warn("%s: pathconf(..., _PC_ACL_NFS4) failed", path);
11343960f15SRobert Watson return (-1);
11443960f15SRobert Watson }
11543960f15SRobert Watson
11643960f15SRobert Watson if (more_than_one)
11743960f15SRobert Watson printf("\n");
11843960f15SRobert Watson else
11943960f15SRobert Watson more_than_one++;
12043960f15SRobert Watson
121f9a86e37SRobert Watson if (!qflag)
122c5771451SKevin Lo printf("# file: %s\n# owner: %s\n# group: %s\n", path,
123c5771451SKevin Lo getuname(sb.st_uid), getgname(sb.st_gid));
12443960f15SRobert Watson
1258051fddeSRobert Watson if (hflag)
1268051fddeSRobert Watson acl = acl_get_link_np(path, type);
1278051fddeSRobert Watson else
12843960f15SRobert Watson acl = acl_get_file(path, type);
12943960f15SRobert Watson if (!acl) {
13043960f15SRobert Watson if (errno != EOPNOTSUPP) {
13143960f15SRobert Watson warn("%s", path);
13243960f15SRobert Watson return(-1);
13343960f15SRobert Watson }
13443960f15SRobert Watson errno = 0;
13583bd4cd0SEdward Tomasz Napierala if (type == ACL_TYPE_DEFAULT)
13643960f15SRobert Watson return(0);
137fcef0684SGleb Popov acl = acl_from_mode_np(sb.st_mode);
13843960f15SRobert Watson if (!acl) {
139caeb270eSGleb Popov warn("%s: acl_from_mode() failed", path);
14043960f15SRobert Watson return(-1);
14143960f15SRobert Watson }
14243960f15SRobert Watson }
14343960f15SRobert Watson
14483bd4cd0SEdward Tomasz Napierala if (iflag)
14583bd4cd0SEdward Tomasz Napierala flags |= ACL_TEXT_APPEND_ID;
14683bd4cd0SEdward Tomasz Napierala
14783bd4cd0SEdward Tomasz Napierala if (nflag)
14883bd4cd0SEdward Tomasz Napierala flags |= ACL_TEXT_NUMERIC_IDS;
14983bd4cd0SEdward Tomasz Napierala
15083bd4cd0SEdward Tomasz Napierala if (vflag)
15183bd4cd0SEdward Tomasz Napierala flags |= ACL_TEXT_VERBOSE;
15283bd4cd0SEdward Tomasz Napierala
15383bd4cd0SEdward Tomasz Napierala acl_text = acl_to_text_np(acl, 0, flags);
15443960f15SRobert Watson if (!acl_text) {
15583bd4cd0SEdward Tomasz Napierala warn("%s: acl_to_text_np() failed", path);
156*781624caSKyle Evans (void)acl_free(acl);
15743960f15SRobert Watson return(-1);
15843960f15SRobert Watson }
15943960f15SRobert Watson
16043960f15SRobert Watson printf("%s", acl_text);
16143960f15SRobert Watson
162fab912dfSMark Murray (void)acl_free(acl);
163fab912dfSMark Murray (void)acl_free(acl_text);
16443960f15SRobert Watson
16543960f15SRobert Watson return(0);
16643960f15SRobert Watson }
16743960f15SRobert Watson
16843960f15SRobert Watson static int
print_acl_from_stdin(acl_type_t type,int hflag,int iflag,int nflag,int qflag,int vflag)16983bd4cd0SEdward Tomasz Napierala print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag,
17083bd4cd0SEdward Tomasz Napierala int qflag, int vflag)
17143960f15SRobert Watson {
1724e65ab95STim J. Robbins char *p, pathname[PATH_MAX];
17343960f15SRobert Watson int carried_error = 0;
17443960f15SRobert Watson
17528bf3202SKris Kennaway while (fgets(pathname, (int)sizeof(pathname), stdin)) {
1764e65ab95STim J. Robbins if ((p = strchr(pathname, '\n')) != NULL)
1774e65ab95STim J. Robbins *p = '\0';
17883bd4cd0SEdward Tomasz Napierala if (print_acl(pathname, type, hflag, iflag, nflag,
17983bd4cd0SEdward Tomasz Napierala qflag, vflag) == -1) {
18043960f15SRobert Watson carried_error = -1;
18143960f15SRobert Watson }
18243960f15SRobert Watson }
18343960f15SRobert Watson
18443960f15SRobert Watson return(carried_error);
18543960f15SRobert Watson }
18643960f15SRobert Watson
18743960f15SRobert Watson int
main(int argc,char * argv[])18843960f15SRobert Watson main(int argc, char *argv[])
18943960f15SRobert Watson {
19043960f15SRobert Watson acl_type_t type = ACL_TYPE_ACCESS;
19143960f15SRobert Watson int carried_error = 0;
19243960f15SRobert Watson int ch, error, i;
19383bd4cd0SEdward Tomasz Napierala int hflag, iflag, qflag, nflag, vflag;
19443960f15SRobert Watson
1958051fddeSRobert Watson hflag = 0;
19683bd4cd0SEdward Tomasz Napierala iflag = 0;
197f9a86e37SRobert Watson qflag = 0;
19883bd4cd0SEdward Tomasz Napierala nflag = 0;
19983bd4cd0SEdward Tomasz Napierala vflag = 0;
20083bd4cd0SEdward Tomasz Napierala while ((ch = getopt(argc, argv, "dhinqv")) != -1)
20143960f15SRobert Watson switch(ch) {
20243960f15SRobert Watson case 'd':
20343960f15SRobert Watson type = ACL_TYPE_DEFAULT;
20443960f15SRobert Watson break;
2058051fddeSRobert Watson case 'h':
2068051fddeSRobert Watson hflag = 1;
2078051fddeSRobert Watson break;
20883bd4cd0SEdward Tomasz Napierala case 'i':
20983bd4cd0SEdward Tomasz Napierala iflag = 1;
21083bd4cd0SEdward Tomasz Napierala break;
21183bd4cd0SEdward Tomasz Napierala case 'n':
21283bd4cd0SEdward Tomasz Napierala nflag = 1;
21383bd4cd0SEdward Tomasz Napierala break;
214f9a86e37SRobert Watson case 'q':
215f9a86e37SRobert Watson qflag = 1;
216f9a86e37SRobert Watson break;
21783bd4cd0SEdward Tomasz Napierala case 'v':
21883bd4cd0SEdward Tomasz Napierala vflag = 1;
21983bd4cd0SEdward Tomasz Napierala break;
22043960f15SRobert Watson default:
22143960f15SRobert Watson usage();
22243960f15SRobert Watson return(-1);
22343960f15SRobert Watson }
22443960f15SRobert Watson argc -= optind;
22543960f15SRobert Watson argv += optind;
22643960f15SRobert Watson
22743960f15SRobert Watson if (argc == 0) {
22883bd4cd0SEdward Tomasz Napierala error = print_acl_from_stdin(type, hflag, iflag, nflag,
22983bd4cd0SEdward Tomasz Napierala qflag, vflag);
2304e65ab95STim J. Robbins return(error ? 1 : 0);
23143960f15SRobert Watson }
23243960f15SRobert Watson
23343960f15SRobert Watson for (i = 0; i < argc; i++) {
23443960f15SRobert Watson if (!strcmp(argv[i], "-")) {
23583bd4cd0SEdward Tomasz Napierala error = print_acl_from_stdin(type, hflag, iflag, nflag,
23683bd4cd0SEdward Tomasz Napierala qflag, vflag);
23743960f15SRobert Watson if (error == -1)
23843960f15SRobert Watson carried_error = -1;
23943960f15SRobert Watson } else {
24083bd4cd0SEdward Tomasz Napierala error = print_acl(argv[i], type, hflag, iflag, nflag,
24183bd4cd0SEdward Tomasz Napierala qflag, vflag);
24243960f15SRobert Watson if (error == -1)
24343960f15SRobert Watson carried_error = -1;
24443960f15SRobert Watson }
24543960f15SRobert Watson }
24643960f15SRobert Watson
2474e65ab95STim J. Robbins return(carried_error ? 1 : 0);
24843960f15SRobert Watson }
249