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 335eb43ac2SDavid E. O'Brien 345eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 355eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 365eb43ac2SDavid E. O'Brien 3743960f15SRobert Watson #include <sys/types.h> 3843960f15SRobert Watson #include <sys/param.h> 3943960f15SRobert Watson #include <sys/acl.h> 4043960f15SRobert Watson #include <sys/stat.h> 415eb43ac2SDavid E. O'Brien 4243960f15SRobert Watson #include <err.h> 4343960f15SRobert Watson #include <errno.h> 44c5771451SKevin Lo #include <grp.h> 45c5771451SKevin Lo #include <pwd.h> 4643960f15SRobert Watson #include <stdio.h> 477a832d43SChris D. Faulhaber #include <stdlib.h> 4828bf3202SKris Kennaway #include <string.h> 4943960f15SRobert Watson #include <unistd.h> 5043960f15SRobert Watson 51ae824d80SEd Schouten static int more_than_one = 0; 5243960f15SRobert Watson 5343960f15SRobert Watson static void 5443960f15SRobert Watson usage(void) 5543960f15SRobert Watson { 5643960f15SRobert Watson 5783bd4cd0SEdward Tomasz Napierala fprintf(stderr, "getfacl [-dhnqv] [file ...]\n"); 5843960f15SRobert Watson } 5943960f15SRobert Watson 60c5771451SKevin Lo static char * 61c5771451SKevin Lo getuname(uid_t uid) 62c5771451SKevin Lo { 63c5771451SKevin Lo struct passwd *pw; 64c5771451SKevin Lo static char uids[10]; 65c5771451SKevin Lo 66c5771451SKevin Lo if ((pw = getpwuid(uid)) == NULL) { 67c5771451SKevin Lo (void)snprintf(uids, sizeof(uids), "%u", uid); 68c5771451SKevin Lo return (uids); 69c5771451SKevin Lo } else 70c5771451SKevin Lo return (pw->pw_name); 71c5771451SKevin Lo } 72c5771451SKevin Lo 73c5771451SKevin Lo static char * 74c5771451SKevin Lo getgname(gid_t gid) 75c5771451SKevin Lo { 76c5771451SKevin Lo struct group *gr; 77c5771451SKevin Lo static char gids[10]; 78c5771451SKevin Lo 79c5771451SKevin Lo if ((gr = getgrgid(gid)) == NULL) { 80c5771451SKevin Lo (void)snprintf(gids, sizeof(gids), "%u", gid); 81c5771451SKevin Lo return (gids); 82c5771451SKevin Lo } else 83c5771451SKevin Lo return (gr->gr_name); 84c5771451SKevin Lo } 85c5771451SKevin Lo 8643960f15SRobert Watson static int 8783bd4cd0SEdward Tomasz Napierala print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag, 8883bd4cd0SEdward Tomasz Napierala int qflag, int vflag) 8943960f15SRobert Watson { 9043960f15SRobert Watson struct stat sb; 9143960f15SRobert Watson acl_t acl; 9243960f15SRobert Watson char *acl_text; 9383bd4cd0SEdward Tomasz Napierala int error, flags = 0, ret; 9443960f15SRobert Watson 958051fddeSRobert Watson if (hflag) 968051fddeSRobert Watson error = lstat(path, &sb); 978051fddeSRobert Watson else 9843960f15SRobert Watson error = stat(path, &sb); 9943960f15SRobert Watson if (error == -1) { 10083bd4cd0SEdward Tomasz Napierala warn("%s: stat() failed", path); 10183bd4cd0SEdward Tomasz Napierala return(-1); 10283bd4cd0SEdward Tomasz Napierala } 10383bd4cd0SEdward Tomasz Napierala 10483bd4cd0SEdward Tomasz Napierala if (hflag) 10583bd4cd0SEdward Tomasz Napierala ret = lpathconf(path, _PC_ACL_NFS4); 10683bd4cd0SEdward Tomasz Napierala else 10783bd4cd0SEdward Tomasz Napierala ret = pathconf(path, _PC_ACL_NFS4); 10883bd4cd0SEdward Tomasz Napierala if (ret > 0) { 10983bd4cd0SEdward Tomasz Napierala if (type == ACL_TYPE_DEFAULT) { 11083bd4cd0SEdward Tomasz Napierala warnx("%s: there are no default entries in NFSv4 ACLs", 11183bd4cd0SEdward Tomasz Napierala path); 11283bd4cd0SEdward Tomasz Napierala return (-1); 11383bd4cd0SEdward Tomasz Napierala } 11483bd4cd0SEdward Tomasz Napierala type = ACL_TYPE_NFS4; 11583bd4cd0SEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 11683bd4cd0SEdward Tomasz Napierala warn("%s: pathconf(..., _PC_ACL_NFS4) failed", path); 11743960f15SRobert Watson return (-1); 11843960f15SRobert Watson } 11943960f15SRobert Watson 12043960f15SRobert Watson if (more_than_one) 12143960f15SRobert Watson printf("\n"); 12243960f15SRobert Watson else 12343960f15SRobert Watson more_than_one++; 12443960f15SRobert Watson 125f9a86e37SRobert Watson if (!qflag) 126c5771451SKevin Lo printf("# file: %s\n# owner: %s\n# group: %s\n", path, 127c5771451SKevin Lo getuname(sb.st_uid), getgname(sb.st_gid)); 12843960f15SRobert Watson 1298051fddeSRobert Watson if (hflag) 1308051fddeSRobert Watson acl = acl_get_link_np(path, type); 1318051fddeSRobert Watson else 13243960f15SRobert Watson acl = acl_get_file(path, type); 13343960f15SRobert Watson if (!acl) { 13443960f15SRobert Watson if (errno != EOPNOTSUPP) { 13543960f15SRobert Watson warn("%s", path); 13643960f15SRobert Watson return(-1); 13743960f15SRobert Watson } 13843960f15SRobert Watson errno = 0; 13983bd4cd0SEdward Tomasz Napierala if (type == ACL_TYPE_DEFAULT) 14043960f15SRobert Watson return(0); 141fcef0684SGleb Popov acl = acl_from_mode_np(sb.st_mode); 14243960f15SRobert Watson if (!acl) { 143caeb270eSGleb Popov warn("%s: acl_from_mode() failed", path); 14443960f15SRobert Watson return(-1); 14543960f15SRobert Watson } 14643960f15SRobert Watson } 14743960f15SRobert Watson 14883bd4cd0SEdward Tomasz Napierala if (iflag) 14983bd4cd0SEdward Tomasz Napierala flags |= ACL_TEXT_APPEND_ID; 15083bd4cd0SEdward Tomasz Napierala 15183bd4cd0SEdward Tomasz Napierala if (nflag) 15283bd4cd0SEdward Tomasz Napierala flags |= ACL_TEXT_NUMERIC_IDS; 15383bd4cd0SEdward Tomasz Napierala 15483bd4cd0SEdward Tomasz Napierala if (vflag) 15583bd4cd0SEdward Tomasz Napierala flags |= ACL_TEXT_VERBOSE; 15683bd4cd0SEdward Tomasz Napierala 15783bd4cd0SEdward Tomasz Napierala acl_text = acl_to_text_np(acl, 0, flags); 15843960f15SRobert Watson if (!acl_text) { 15983bd4cd0SEdward Tomasz Napierala warn("%s: acl_to_text_np() failed", path); 16043960f15SRobert Watson return(-1); 16143960f15SRobert Watson } 16243960f15SRobert Watson 16343960f15SRobert Watson printf("%s", acl_text); 16443960f15SRobert Watson 165fab912dfSMark Murray (void)acl_free(acl); 166fab912dfSMark Murray (void)acl_free(acl_text); 16743960f15SRobert Watson 16843960f15SRobert Watson return(0); 16943960f15SRobert Watson } 17043960f15SRobert Watson 17143960f15SRobert Watson static int 17283bd4cd0SEdward Tomasz Napierala print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag, 17383bd4cd0SEdward Tomasz Napierala int qflag, int vflag) 17443960f15SRobert Watson { 1754e65ab95STim J. Robbins char *p, pathname[PATH_MAX]; 17643960f15SRobert Watson int carried_error = 0; 17743960f15SRobert Watson 17828bf3202SKris Kennaway while (fgets(pathname, (int)sizeof(pathname), stdin)) { 1794e65ab95STim J. Robbins if ((p = strchr(pathname, '\n')) != NULL) 1804e65ab95STim J. Robbins *p = '\0'; 18183bd4cd0SEdward Tomasz Napierala if (print_acl(pathname, type, hflag, iflag, nflag, 18283bd4cd0SEdward Tomasz Napierala qflag, vflag) == -1) { 18343960f15SRobert Watson carried_error = -1; 18443960f15SRobert Watson } 18543960f15SRobert Watson } 18643960f15SRobert Watson 18743960f15SRobert Watson return(carried_error); 18843960f15SRobert Watson } 18943960f15SRobert Watson 19043960f15SRobert Watson int 19143960f15SRobert Watson main(int argc, char *argv[]) 19243960f15SRobert Watson { 19343960f15SRobert Watson acl_type_t type = ACL_TYPE_ACCESS; 19443960f15SRobert Watson int carried_error = 0; 19543960f15SRobert Watson int ch, error, i; 19683bd4cd0SEdward Tomasz Napierala int hflag, iflag, qflag, nflag, vflag; 19743960f15SRobert Watson 1988051fddeSRobert Watson hflag = 0; 19983bd4cd0SEdward Tomasz Napierala iflag = 0; 200f9a86e37SRobert Watson qflag = 0; 20183bd4cd0SEdward Tomasz Napierala nflag = 0; 20283bd4cd0SEdward Tomasz Napierala vflag = 0; 20383bd4cd0SEdward Tomasz Napierala while ((ch = getopt(argc, argv, "dhinqv")) != -1) 20443960f15SRobert Watson switch(ch) { 20543960f15SRobert Watson case 'd': 20643960f15SRobert Watson type = ACL_TYPE_DEFAULT; 20743960f15SRobert Watson break; 2088051fddeSRobert Watson case 'h': 2098051fddeSRobert Watson hflag = 1; 2108051fddeSRobert Watson break; 21183bd4cd0SEdward Tomasz Napierala case 'i': 21283bd4cd0SEdward Tomasz Napierala iflag = 1; 21383bd4cd0SEdward Tomasz Napierala break; 21483bd4cd0SEdward Tomasz Napierala case 'n': 21583bd4cd0SEdward Tomasz Napierala nflag = 1; 21683bd4cd0SEdward Tomasz Napierala break; 217f9a86e37SRobert Watson case 'q': 218f9a86e37SRobert Watson qflag = 1; 219f9a86e37SRobert Watson break; 22083bd4cd0SEdward Tomasz Napierala case 'v': 22183bd4cd0SEdward Tomasz Napierala vflag = 1; 22283bd4cd0SEdward Tomasz Napierala break; 22343960f15SRobert Watson default: 22443960f15SRobert Watson usage(); 22543960f15SRobert Watson return(-1); 22643960f15SRobert Watson } 22743960f15SRobert Watson argc -= optind; 22843960f15SRobert Watson argv += optind; 22943960f15SRobert Watson 23043960f15SRobert Watson if (argc == 0) { 23183bd4cd0SEdward Tomasz Napierala error = print_acl_from_stdin(type, hflag, iflag, nflag, 23283bd4cd0SEdward Tomasz Napierala qflag, vflag); 2334e65ab95STim J. Robbins return(error ? 1 : 0); 23443960f15SRobert Watson } 23543960f15SRobert Watson 23643960f15SRobert Watson for (i = 0; i < argc; i++) { 23743960f15SRobert Watson if (!strcmp(argv[i], "-")) { 23883bd4cd0SEdward Tomasz Napierala error = print_acl_from_stdin(type, hflag, iflag, nflag, 23983bd4cd0SEdward Tomasz Napierala qflag, vflag); 24043960f15SRobert Watson if (error == -1) 24143960f15SRobert Watson carried_error = -1; 24243960f15SRobert Watson } else { 24383bd4cd0SEdward Tomasz Napierala error = print_acl(argv[i], type, hflag, iflag, nflag, 24483bd4cd0SEdward Tomasz Napierala qflag, vflag); 24543960f15SRobert Watson if (error == -1) 24643960f15SRobert Watson carried_error = -1; 24743960f15SRobert Watson } 24843960f15SRobert Watson } 24943960f15SRobert Watson 2504e65ab95STim J. Robbins return(carried_error ? 1 : 0); 25143960f15SRobert Watson } 252