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 * $FreeBSD$ 2943960f15SRobert Watson */ 3043960f15SRobert Watson /* 3143960f15SRobert Watson * getfacl -- POSIX.1e utility to extract ACLs from files and directories 3243960f15SRobert Watson * and send the results to stdout 3343960f15SRobert Watson */ 3443960f15SRobert Watson 3543960f15SRobert Watson #include <sys/types.h> 3643960f15SRobert Watson #include <sys/param.h> 3743960f15SRobert Watson #include <sys/acl.h> 3843960f15SRobert Watson #include <sys/stat.h> 3943960f15SRobert Watson #include <err.h> 4043960f15SRobert Watson #include <errno.h> 4143960f15SRobert Watson #include <stdio.h> 427a832d43SChris D. Faulhaber #include <stdlib.h> 4328bf3202SKris Kennaway #include <string.h> 4443960f15SRobert Watson #include <unistd.h> 4543960f15SRobert Watson 4643960f15SRobert Watson int more_than_one = 0; 4743960f15SRobert Watson 4843960f15SRobert Watson static void 4943960f15SRobert Watson usage(void) 5043960f15SRobert Watson { 5143960f15SRobert Watson 5243960f15SRobert Watson fprintf(stderr, "getfacl [-d] [files ...]\n"); 5343960f15SRobert Watson } 5443960f15SRobert Watson 557a832d43SChris D. Faulhaber /* 567a832d43SChris D. Faulhaber * return an ACL corresponding to the permissions 577a832d43SChris D. Faulhaber * contained in struct stat 587a832d43SChris D. Faulhaber */ 5943960f15SRobert Watson static acl_t 6043960f15SRobert Watson acl_from_stat(struct stat sb) 6143960f15SRobert Watson { 6243960f15SRobert Watson acl_t acl; 637a832d43SChris D. Faulhaber acl_entry_t entry; 647a832d43SChris D. Faulhaber acl_permset_t perms; 6543960f15SRobert Watson 667a832d43SChris D. Faulhaber /* create the ACL */ 6743960f15SRobert Watson acl = acl_init(3); 6843960f15SRobert Watson if (!acl) 697a832d43SChris D. Faulhaber return NULL; 7043960f15SRobert Watson 717a832d43SChris D. Faulhaber /* First entry: ACL_USER_OBJ */ 727a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 737a832d43SChris D. Faulhaber return NULL; 747a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1) 757a832d43SChris D. Faulhaber return NULL; 767a832d43SChris D. Faulhaber 777a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 787a832d43SChris D. Faulhaber return NULL; 797a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 807a832d43SChris D. Faulhaber return NULL; 817a832d43SChris D. Faulhaber 827a832d43SChris D. Faulhaber /* calculate user mode */ 8343960f15SRobert Watson if (sb.st_mode & S_IRUSR) 847a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 857a832d43SChris D. Faulhaber return NULL; 8643960f15SRobert Watson if (sb.st_mode & S_IWUSR) 877a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 887a832d43SChris D. Faulhaber return NULL; 8943960f15SRobert Watson if (sb.st_mode & S_IXUSR) 907a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 917a832d43SChris D. Faulhaber return NULL; 927a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 937a832d43SChris D. Faulhaber return NULL; 9443960f15SRobert Watson 957a832d43SChris D. Faulhaber /* Second entry: ACL_GROUP_OBJ */ 967a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 977a832d43SChris D. Faulhaber return NULL; 987a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1) 997a832d43SChris D. Faulhaber return NULL; 1007a832d43SChris D. Faulhaber 1017a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 1027a832d43SChris D. Faulhaber return NULL; 1037a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 1047a832d43SChris D. Faulhaber return NULL; 1057a832d43SChris D. Faulhaber 1067a832d43SChris D. Faulhaber /* calculate group mode */ 10743960f15SRobert Watson if (sb.st_mode & S_IRGRP) 1087a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 1097a832d43SChris D. Faulhaber return NULL; 11043960f15SRobert Watson if (sb.st_mode & S_IWGRP) 1117a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 1127a832d43SChris D. Faulhaber return NULL; 11343960f15SRobert Watson if (sb.st_mode & S_IXGRP) 1147a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 1157a832d43SChris D. Faulhaber return NULL; 1167a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 1177a832d43SChris D. Faulhaber return NULL; 11843960f15SRobert Watson 1197a832d43SChris D. Faulhaber /* Third entry: ACL_OTHER */ 1207a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 1217a832d43SChris D. Faulhaber return NULL; 1227a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_OTHER) == -1) 1237a832d43SChris D. Faulhaber return NULL; 1247a832d43SChris D. Faulhaber 1257a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 1267a832d43SChris D. Faulhaber return NULL; 1277a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 1287a832d43SChris D. Faulhaber return NULL; 1297a832d43SChris D. Faulhaber 1307a832d43SChris D. Faulhaber /* calculate other mode */ 13143960f15SRobert Watson if (sb.st_mode & S_IROTH) 1327a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 1337a832d43SChris D. Faulhaber return NULL; 13443960f15SRobert Watson if (sb.st_mode & S_IWOTH) 1357a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 1367a832d43SChris D. Faulhaber return NULL; 13743960f15SRobert Watson if (sb.st_mode & S_IXOTH) 1387a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 1397a832d43SChris D. Faulhaber return NULL; 1407a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 1417a832d43SChris D. Faulhaber return NULL; 14243960f15SRobert Watson 14343960f15SRobert Watson return(acl); 14443960f15SRobert Watson } 14543960f15SRobert Watson 14643960f15SRobert Watson static int 14743960f15SRobert Watson print_acl(char *path, acl_type_t type) 14843960f15SRobert Watson { 14943960f15SRobert Watson struct stat sb; 15043960f15SRobert Watson acl_t acl; 15143960f15SRobert Watson char *acl_text; 15243960f15SRobert Watson int error; 15343960f15SRobert Watson 15443960f15SRobert Watson error = stat(path, &sb); 15543960f15SRobert Watson if (error == -1) { 15643960f15SRobert Watson perror(path); 15743960f15SRobert Watson return(-1); 15843960f15SRobert Watson } 15943960f15SRobert Watson 16043960f15SRobert Watson if (more_than_one) 16143960f15SRobert Watson printf("\n"); 16243960f15SRobert Watson else 16343960f15SRobert Watson more_than_one++; 16443960f15SRobert Watson 16543960f15SRobert Watson printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid); 16643960f15SRobert Watson 16743960f15SRobert Watson acl = acl_get_file(path, type); 16843960f15SRobert Watson if (!acl) { 16943960f15SRobert Watson if (errno != EOPNOTSUPP) { 17043960f15SRobert Watson warn("%s", path); 17143960f15SRobert Watson return(-1); 17243960f15SRobert Watson } 17343960f15SRobert Watson errno = 0; 17443960f15SRobert Watson if (type != ACL_TYPE_ACCESS) 17543960f15SRobert Watson return(0); 17643960f15SRobert Watson acl = acl_from_stat(sb); 17743960f15SRobert Watson if (!acl) { 17843960f15SRobert Watson perror("acl_from_stat()"); 17943960f15SRobert Watson return(-1); 18043960f15SRobert Watson } 18143960f15SRobert Watson } 18243960f15SRobert Watson 18343960f15SRobert Watson acl_text = acl_to_text(acl, 0); 18443960f15SRobert Watson if (!acl_text) { 18543960f15SRobert Watson perror(path); 18643960f15SRobert Watson return(-1); 18743960f15SRobert Watson } 18843960f15SRobert Watson 18943960f15SRobert Watson printf("%s", acl_text); 19043960f15SRobert Watson 191fab912dfSMark Murray (void)acl_free(acl); 192fab912dfSMark Murray (void)acl_free(acl_text); 19343960f15SRobert Watson 19443960f15SRobert Watson return(0); 19543960f15SRobert Watson } 19643960f15SRobert Watson 19743960f15SRobert Watson static int 19843960f15SRobert Watson print_acl_from_stdin(acl_type_t type) 19943960f15SRobert Watson { 20043960f15SRobert Watson char pathname[PATH_MAX]; 20143960f15SRobert Watson int carried_error = 0; 20243960f15SRobert Watson 20343960f15SRobert Watson pathname[sizeof(pathname) - 1] = '\0'; 20428bf3202SKris Kennaway while (fgets(pathname, (int)sizeof(pathname), stdin)) { 20543960f15SRobert Watson /* remove the \n */ 20643960f15SRobert Watson pathname[strlen(pathname) - 1] = '\0'; 20743960f15SRobert Watson if (print_acl(pathname, type) == -1) { 20843960f15SRobert Watson carried_error = -1; 20943960f15SRobert Watson } 21043960f15SRobert Watson } 21143960f15SRobert Watson 21243960f15SRobert Watson return(carried_error); 21343960f15SRobert Watson } 21443960f15SRobert Watson 21543960f15SRobert Watson int 21643960f15SRobert Watson main(int argc, char *argv[]) 21743960f15SRobert Watson { 21843960f15SRobert Watson acl_type_t type = ACL_TYPE_ACCESS; 21943960f15SRobert Watson int carried_error = 0; 22043960f15SRobert Watson int ch, error, i; 22143960f15SRobert Watson 22243960f15SRobert Watson while ((ch = getopt(argc, argv, "d")) != -1) 22343960f15SRobert Watson switch(ch) { 22443960f15SRobert Watson case 'd': 22543960f15SRobert Watson type = ACL_TYPE_DEFAULT; 22643960f15SRobert Watson break; 22743960f15SRobert Watson default: 22843960f15SRobert Watson usage(); 22943960f15SRobert Watson return(-1); 23043960f15SRobert Watson } 23143960f15SRobert Watson argc -= optind; 23243960f15SRobert Watson argv += optind; 23343960f15SRobert Watson 23443960f15SRobert Watson if (argc == 0) { 23543960f15SRobert Watson error = print_acl_from_stdin(type); 23643960f15SRobert Watson return(error); 23743960f15SRobert Watson } 23843960f15SRobert Watson 23943960f15SRobert Watson for (i = 0; i < argc; i++) { 24043960f15SRobert Watson if (!strcmp(argv[i], "-")) { 24143960f15SRobert Watson error = print_acl_from_stdin(type); 24243960f15SRobert Watson if (error == -1) 24343960f15SRobert Watson carried_error = -1; 24443960f15SRobert Watson } else { 24543960f15SRobert Watson error = print_acl(argv[i], type); 24643960f15SRobert Watson if (error == -1) 24743960f15SRobert Watson carried_error = -1; 24843960f15SRobert Watson } 24943960f15SRobert Watson } 25043960f15SRobert Watson 25143960f15SRobert Watson return(carried_error); 25243960f15SRobert Watson } 253