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> 4443960f15SRobert Watson #include <stdio.h> 457a832d43SChris D. Faulhaber #include <stdlib.h> 4628bf3202SKris Kennaway #include <string.h> 4743960f15SRobert Watson #include <unistd.h> 4843960f15SRobert Watson 4943960f15SRobert Watson int more_than_one = 0; 5043960f15SRobert Watson 5143960f15SRobert Watson static void 5243960f15SRobert Watson usage(void) 5343960f15SRobert Watson { 5443960f15SRobert Watson 55f9a86e37SRobert Watson fprintf(stderr, "getfacl [-dhq] [file ...]\n"); 5643960f15SRobert Watson } 5743960f15SRobert Watson 587a832d43SChris D. Faulhaber /* 597a832d43SChris D. Faulhaber * return an ACL corresponding to the permissions 607a832d43SChris D. Faulhaber * contained in struct stat 617a832d43SChris D. Faulhaber */ 6243960f15SRobert Watson static acl_t 6343960f15SRobert Watson acl_from_stat(struct stat sb) 6443960f15SRobert Watson { 6543960f15SRobert Watson acl_t acl; 667a832d43SChris D. Faulhaber acl_entry_t entry; 677a832d43SChris D. Faulhaber acl_permset_t perms; 6843960f15SRobert Watson 697a832d43SChris D. Faulhaber /* create the ACL */ 7043960f15SRobert Watson acl = acl_init(3); 7143960f15SRobert Watson if (!acl) 727a832d43SChris D. Faulhaber return NULL; 7343960f15SRobert Watson 747a832d43SChris D. Faulhaber /* First entry: ACL_USER_OBJ */ 757a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 767a832d43SChris D. Faulhaber return NULL; 777a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1) 787a832d43SChris D. Faulhaber return NULL; 797a832d43SChris D. Faulhaber 807a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 817a832d43SChris D. Faulhaber return NULL; 827a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 837a832d43SChris D. Faulhaber return NULL; 847a832d43SChris D. Faulhaber 857a832d43SChris D. Faulhaber /* calculate user mode */ 8643960f15SRobert Watson if (sb.st_mode & S_IRUSR) 877a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 887a832d43SChris D. Faulhaber return NULL; 8943960f15SRobert Watson if (sb.st_mode & S_IWUSR) 907a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 917a832d43SChris D. Faulhaber return NULL; 9243960f15SRobert Watson if (sb.st_mode & S_IXUSR) 937a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 947a832d43SChris D. Faulhaber return NULL; 957a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 967a832d43SChris D. Faulhaber return NULL; 9743960f15SRobert Watson 987a832d43SChris D. Faulhaber /* Second entry: ACL_GROUP_OBJ */ 997a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 1007a832d43SChris D. Faulhaber return NULL; 1017a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1) 1027a832d43SChris D. Faulhaber return NULL; 1037a832d43SChris D. Faulhaber 1047a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 1057a832d43SChris D. Faulhaber return NULL; 1067a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 1077a832d43SChris D. Faulhaber return NULL; 1087a832d43SChris D. Faulhaber 1097a832d43SChris D. Faulhaber /* calculate group mode */ 11043960f15SRobert Watson if (sb.st_mode & S_IRGRP) 1117a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 1127a832d43SChris D. Faulhaber return NULL; 11343960f15SRobert Watson if (sb.st_mode & S_IWGRP) 1147a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 1157a832d43SChris D. Faulhaber return NULL; 11643960f15SRobert Watson if (sb.st_mode & S_IXGRP) 1177a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 1187a832d43SChris D. Faulhaber return NULL; 1197a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 1207a832d43SChris D. Faulhaber return NULL; 12143960f15SRobert Watson 1227a832d43SChris D. Faulhaber /* Third entry: ACL_OTHER */ 1237a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 1247a832d43SChris D. Faulhaber return NULL; 1257a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_OTHER) == -1) 1267a832d43SChris D. Faulhaber return NULL; 1277a832d43SChris D. Faulhaber 1287a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 1297a832d43SChris D. Faulhaber return NULL; 1307a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 1317a832d43SChris D. Faulhaber return NULL; 1327a832d43SChris D. Faulhaber 1337a832d43SChris D. Faulhaber /* calculate other mode */ 13443960f15SRobert Watson if (sb.st_mode & S_IROTH) 1357a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 1367a832d43SChris D. Faulhaber return NULL; 13743960f15SRobert Watson if (sb.st_mode & S_IWOTH) 1387a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 1397a832d43SChris D. Faulhaber return NULL; 14043960f15SRobert Watson if (sb.st_mode & S_IXOTH) 1417a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 1427a832d43SChris D. Faulhaber return NULL; 1437a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 1447a832d43SChris D. Faulhaber return NULL; 14543960f15SRobert Watson 14643960f15SRobert Watson return(acl); 14743960f15SRobert Watson } 14843960f15SRobert Watson 14943960f15SRobert Watson static int 150f9a86e37SRobert Watson print_acl(char *path, acl_type_t type, int hflag, int qflag) 15143960f15SRobert Watson { 15243960f15SRobert Watson struct stat sb; 15343960f15SRobert Watson acl_t acl; 15443960f15SRobert Watson char *acl_text; 15543960f15SRobert Watson int error; 15643960f15SRobert Watson 1578051fddeSRobert Watson if (hflag) 1588051fddeSRobert Watson error = lstat(path, &sb); 1598051fddeSRobert Watson else 16043960f15SRobert Watson error = stat(path, &sb); 16143960f15SRobert Watson if (error == -1) { 1624e65ab95STim J. Robbins warn("%s", path); 16343960f15SRobert Watson return(-1); 16443960f15SRobert Watson } 16543960f15SRobert Watson 16643960f15SRobert Watson if (more_than_one) 16743960f15SRobert Watson printf("\n"); 16843960f15SRobert Watson else 16943960f15SRobert Watson more_than_one++; 17043960f15SRobert Watson 171f9a86e37SRobert Watson if (!qflag) 172f9a86e37SRobert Watson printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, 173f9a86e37SRobert Watson sb.st_gid); 17443960f15SRobert Watson 1758051fddeSRobert Watson if (hflag) 1768051fddeSRobert Watson acl = acl_get_link_np(path, type); 1778051fddeSRobert Watson else 17843960f15SRobert Watson acl = acl_get_file(path, type); 17943960f15SRobert Watson if (!acl) { 18043960f15SRobert Watson if (errno != EOPNOTSUPP) { 18143960f15SRobert Watson warn("%s", path); 18243960f15SRobert Watson return(-1); 18343960f15SRobert Watson } 18443960f15SRobert Watson errno = 0; 18543960f15SRobert Watson if (type != ACL_TYPE_ACCESS) 18643960f15SRobert Watson return(0); 18743960f15SRobert Watson acl = acl_from_stat(sb); 18843960f15SRobert Watson if (!acl) { 1894e65ab95STim J. Robbins warn("acl_from_stat()"); 19043960f15SRobert Watson return(-1); 19143960f15SRobert Watson } 19243960f15SRobert Watson } 19343960f15SRobert Watson 19443960f15SRobert Watson acl_text = acl_to_text(acl, 0); 19543960f15SRobert Watson if (!acl_text) { 1964e65ab95STim J. Robbins warn("%s", path); 19743960f15SRobert Watson return(-1); 19843960f15SRobert Watson } 19943960f15SRobert Watson 20043960f15SRobert Watson printf("%s", acl_text); 20143960f15SRobert Watson 202fab912dfSMark Murray (void)acl_free(acl); 203fab912dfSMark Murray (void)acl_free(acl_text); 20443960f15SRobert Watson 20543960f15SRobert Watson return(0); 20643960f15SRobert Watson } 20743960f15SRobert Watson 20843960f15SRobert Watson static int 209f9a86e37SRobert Watson print_acl_from_stdin(acl_type_t type, int hflag, int qflag) 21043960f15SRobert Watson { 2114e65ab95STim J. Robbins char *p, pathname[PATH_MAX]; 21243960f15SRobert Watson int carried_error = 0; 21343960f15SRobert Watson 21428bf3202SKris Kennaway while (fgets(pathname, (int)sizeof(pathname), stdin)) { 2154e65ab95STim J. Robbins if ((p = strchr(pathname, '\n')) != NULL) 2164e65ab95STim J. Robbins *p = '\0'; 217f9a86e37SRobert Watson if (print_acl(pathname, type, hflag, qflag) == -1) { 21843960f15SRobert Watson carried_error = -1; 21943960f15SRobert Watson } 22043960f15SRobert Watson } 22143960f15SRobert Watson 22243960f15SRobert Watson return(carried_error); 22343960f15SRobert Watson } 22443960f15SRobert Watson 22543960f15SRobert Watson int 22643960f15SRobert Watson main(int argc, char *argv[]) 22743960f15SRobert Watson { 22843960f15SRobert Watson acl_type_t type = ACL_TYPE_ACCESS; 22943960f15SRobert Watson int carried_error = 0; 23043960f15SRobert Watson int ch, error, i; 231f9a86e37SRobert Watson int hflag, qflag; 23243960f15SRobert Watson 2338051fddeSRobert Watson hflag = 0; 234f9a86e37SRobert Watson qflag = 0; 235f9a86e37SRobert Watson while ((ch = getopt(argc, argv, "dhq")) != -1) 23643960f15SRobert Watson switch(ch) { 23743960f15SRobert Watson case 'd': 23843960f15SRobert Watson type = ACL_TYPE_DEFAULT; 23943960f15SRobert Watson break; 2408051fddeSRobert Watson case 'h': 2418051fddeSRobert Watson hflag = 1; 2428051fddeSRobert Watson break; 243f9a86e37SRobert Watson case 'q': 244f9a86e37SRobert Watson qflag = 1; 245f9a86e37SRobert Watson break; 24643960f15SRobert Watson default: 24743960f15SRobert Watson usage(); 24843960f15SRobert Watson return(-1); 24943960f15SRobert Watson } 25043960f15SRobert Watson argc -= optind; 25143960f15SRobert Watson argv += optind; 25243960f15SRobert Watson 25343960f15SRobert Watson if (argc == 0) { 254f9a86e37SRobert Watson error = print_acl_from_stdin(type, hflag, qflag); 2554e65ab95STim J. Robbins return(error ? 1 : 0); 25643960f15SRobert Watson } 25743960f15SRobert Watson 25843960f15SRobert Watson for (i = 0; i < argc; i++) { 25943960f15SRobert Watson if (!strcmp(argv[i], "-")) { 260f9a86e37SRobert Watson error = print_acl_from_stdin(type, hflag, qflag); 26143960f15SRobert Watson if (error == -1) 26243960f15SRobert Watson carried_error = -1; 26343960f15SRobert Watson } else { 264f9a86e37SRobert Watson error = print_acl(argv[i], type, hflag, qflag); 26543960f15SRobert Watson if (error == -1) 26643960f15SRobert Watson carried_error = -1; 26743960f15SRobert Watson } 26843960f15SRobert Watson } 26943960f15SRobert Watson 2704e65ab95STim J. Robbins return(carried_error ? 1 : 0); 27143960f15SRobert Watson } 272