143960f15SRobert Watson /*- 243960f15SRobert Watson * Copyright (c) 1999-2001 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 5543960f15SRobert Watson fprintf(stderr, "getfacl [-d] [files ...]\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 15043960f15SRobert Watson print_acl(char *path, acl_type_t type) 15143960f15SRobert Watson { 15243960f15SRobert Watson struct stat sb; 15343960f15SRobert Watson acl_t acl; 15443960f15SRobert Watson char *acl_text; 15543960f15SRobert Watson int error; 15643960f15SRobert Watson 15743960f15SRobert Watson error = stat(path, &sb); 15843960f15SRobert Watson if (error == -1) { 15943960f15SRobert Watson perror(path); 16043960f15SRobert Watson return(-1); 16143960f15SRobert Watson } 16243960f15SRobert Watson 16343960f15SRobert Watson if (more_than_one) 16443960f15SRobert Watson printf("\n"); 16543960f15SRobert Watson else 16643960f15SRobert Watson more_than_one++; 16743960f15SRobert Watson 16843960f15SRobert Watson printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid); 16943960f15SRobert Watson 17043960f15SRobert Watson acl = acl_get_file(path, type); 17143960f15SRobert Watson if (!acl) { 17243960f15SRobert Watson if (errno != EOPNOTSUPP) { 17343960f15SRobert Watson warn("%s", path); 17443960f15SRobert Watson return(-1); 17543960f15SRobert Watson } 17643960f15SRobert Watson errno = 0; 17743960f15SRobert Watson if (type != ACL_TYPE_ACCESS) 17843960f15SRobert Watson return(0); 17943960f15SRobert Watson acl = acl_from_stat(sb); 18043960f15SRobert Watson if (!acl) { 18143960f15SRobert Watson perror("acl_from_stat()"); 18243960f15SRobert Watson return(-1); 18343960f15SRobert Watson } 18443960f15SRobert Watson } 18543960f15SRobert Watson 18643960f15SRobert Watson acl_text = acl_to_text(acl, 0); 18743960f15SRobert Watson if (!acl_text) { 18843960f15SRobert Watson perror(path); 18943960f15SRobert Watson return(-1); 19043960f15SRobert Watson } 19143960f15SRobert Watson 19243960f15SRobert Watson printf("%s", acl_text); 19343960f15SRobert Watson 194fab912dfSMark Murray (void)acl_free(acl); 195fab912dfSMark Murray (void)acl_free(acl_text); 19643960f15SRobert Watson 19743960f15SRobert Watson return(0); 19843960f15SRobert Watson } 19943960f15SRobert Watson 20043960f15SRobert Watson static int 20143960f15SRobert Watson print_acl_from_stdin(acl_type_t type) 20243960f15SRobert Watson { 20343960f15SRobert Watson char pathname[PATH_MAX]; 20443960f15SRobert Watson int carried_error = 0; 20543960f15SRobert Watson 20643960f15SRobert Watson pathname[sizeof(pathname) - 1] = '\0'; 20728bf3202SKris Kennaway while (fgets(pathname, (int)sizeof(pathname), stdin)) { 20843960f15SRobert Watson /* remove the \n */ 20943960f15SRobert Watson pathname[strlen(pathname) - 1] = '\0'; 21043960f15SRobert Watson if (print_acl(pathname, type) == -1) { 21143960f15SRobert Watson carried_error = -1; 21243960f15SRobert Watson } 21343960f15SRobert Watson } 21443960f15SRobert Watson 21543960f15SRobert Watson return(carried_error); 21643960f15SRobert Watson } 21743960f15SRobert Watson 21843960f15SRobert Watson int 21943960f15SRobert Watson main(int argc, char *argv[]) 22043960f15SRobert Watson { 22143960f15SRobert Watson acl_type_t type = ACL_TYPE_ACCESS; 22243960f15SRobert Watson int carried_error = 0; 22343960f15SRobert Watson int ch, error, i; 22443960f15SRobert Watson 22543960f15SRobert Watson while ((ch = getopt(argc, argv, "d")) != -1) 22643960f15SRobert Watson switch(ch) { 22743960f15SRobert Watson case 'd': 22843960f15SRobert Watson type = ACL_TYPE_DEFAULT; 22943960f15SRobert Watson break; 23043960f15SRobert Watson default: 23143960f15SRobert Watson usage(); 23243960f15SRobert Watson return(-1); 23343960f15SRobert Watson } 23443960f15SRobert Watson argc -= optind; 23543960f15SRobert Watson argv += optind; 23643960f15SRobert Watson 23743960f15SRobert Watson if (argc == 0) { 23843960f15SRobert Watson error = print_acl_from_stdin(type); 23943960f15SRobert Watson return(error); 24043960f15SRobert Watson } 24143960f15SRobert Watson 24243960f15SRobert Watson for (i = 0; i < argc; i++) { 24343960f15SRobert Watson if (!strcmp(argv[i], "-")) { 24443960f15SRobert Watson error = print_acl_from_stdin(type); 24543960f15SRobert Watson if (error == -1) 24643960f15SRobert Watson carried_error = -1; 24743960f15SRobert Watson } else { 24843960f15SRobert Watson error = print_acl(argv[i], type); 24943960f15SRobert Watson if (error == -1) 25043960f15SRobert Watson carried_error = -1; 25143960f15SRobert Watson } 25243960f15SRobert Watson } 25343960f15SRobert Watson 25443960f15SRobert Watson return(carried_error); 25543960f15SRobert Watson } 256