143960f15SRobert Watson /*- 243960f15SRobert Watson * Copyright (c) 1999-2001 Robert N M Watson 343960f15SRobert Watson * All rights reserved. 443960f15SRobert Watson * 543960f15SRobert Watson * Redistribution and use in source and binary forms, with or without 643960f15SRobert Watson * modification, are permitted provided that the following conditions 743960f15SRobert Watson * are met: 843960f15SRobert Watson * 1. Redistributions of source code must retain the above copyright 943960f15SRobert Watson * notice, this list of conditions and the following disclaimer. 1043960f15SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 1143960f15SRobert Watson * notice, this list of conditions and the following disclaimer in the 1243960f15SRobert Watson * documentation and/or other materials provided with the distribution. 1343960f15SRobert Watson * 1443960f15SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1543960f15SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1643960f15SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1743960f15SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1843960f15SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1943960f15SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2043960f15SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2143960f15SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2243960f15SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2343960f15SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2443960f15SRobert Watson * SUCH DAMAGE. 2543960f15SRobert Watson * 2643960f15SRobert Watson * $FreeBSD$ 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> 3743960f15SRobert Watson #include <err.h> 3843960f15SRobert Watson #include <errno.h> 3943960f15SRobert Watson #include <stdio.h> 407a832d43SChris D. Faulhaber #include <stdlib.h> 4143960f15SRobert Watson #include <unistd.h> 4243960f15SRobert Watson 4343960f15SRobert Watson int more_than_one = 0; 4443960f15SRobert Watson 4543960f15SRobert Watson static void 4643960f15SRobert Watson usage(void) 4743960f15SRobert Watson { 4843960f15SRobert Watson 4943960f15SRobert Watson fprintf(stderr, "getfacl [-d] [files ...]\n"); 5043960f15SRobert Watson } 5143960f15SRobert Watson 527a832d43SChris D. Faulhaber /* 537a832d43SChris D. Faulhaber * return an ACL corresponding to the permissions 547a832d43SChris D. Faulhaber * contained in struct stat 557a832d43SChris D. Faulhaber */ 5643960f15SRobert Watson static acl_t 5743960f15SRobert Watson acl_from_stat(struct stat sb) 5843960f15SRobert Watson { 5943960f15SRobert Watson acl_t acl; 607a832d43SChris D. Faulhaber acl_entry_t entry; 617a832d43SChris D. Faulhaber acl_permset_t perms; 6243960f15SRobert Watson 637a832d43SChris D. Faulhaber /* create the ACL */ 6443960f15SRobert Watson acl = acl_init(3); 6543960f15SRobert Watson if (!acl) 667a832d43SChris D. Faulhaber return NULL; 6743960f15SRobert Watson 687a832d43SChris D. Faulhaber /* First entry: ACL_USER_OBJ */ 697a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 707a832d43SChris D. Faulhaber return NULL; 717a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1) 727a832d43SChris D. Faulhaber return NULL; 737a832d43SChris D. Faulhaber 747a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 757a832d43SChris D. Faulhaber return NULL; 767a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 777a832d43SChris D. Faulhaber return NULL; 787a832d43SChris D. Faulhaber 797a832d43SChris D. Faulhaber /* calculate user mode */ 8043960f15SRobert Watson if (sb.st_mode & S_IRUSR) 817a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 827a832d43SChris D. Faulhaber return NULL; 8343960f15SRobert Watson if (sb.st_mode & S_IWUSR) 847a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 857a832d43SChris D. Faulhaber return NULL; 8643960f15SRobert Watson if (sb.st_mode & S_IXUSR) 877a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 887a832d43SChris D. Faulhaber return NULL; 897a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 907a832d43SChris D. Faulhaber return NULL; 9143960f15SRobert Watson 927a832d43SChris D. Faulhaber /* Second entry: ACL_GROUP_OBJ */ 937a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 947a832d43SChris D. Faulhaber return NULL; 957a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1) 967a832d43SChris D. Faulhaber return NULL; 977a832d43SChris D. Faulhaber 987a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 997a832d43SChris D. Faulhaber return NULL; 1007a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 1017a832d43SChris D. Faulhaber return NULL; 1027a832d43SChris D. Faulhaber 1037a832d43SChris D. Faulhaber /* calculate group mode */ 10443960f15SRobert Watson if (sb.st_mode & S_IRGRP) 1057a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 1067a832d43SChris D. Faulhaber return NULL; 10743960f15SRobert Watson if (sb.st_mode & S_IWGRP) 1087a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 1097a832d43SChris D. Faulhaber return NULL; 11043960f15SRobert Watson if (sb.st_mode & S_IXGRP) 1117a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 1127a832d43SChris D. Faulhaber return NULL; 1137a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 1147a832d43SChris D. Faulhaber return NULL; 11543960f15SRobert Watson 1167a832d43SChris D. Faulhaber /* Third entry: ACL_OTHER */ 1177a832d43SChris D. Faulhaber if (acl_create_entry(&acl, &entry) == -1) 1187a832d43SChris D. Faulhaber return NULL; 1197a832d43SChris D. Faulhaber if (acl_set_tag_type(entry, ACL_OTHER) == -1) 1207a832d43SChris D. Faulhaber return NULL; 1217a832d43SChris D. Faulhaber 1227a832d43SChris D. Faulhaber if (acl_get_permset(entry, &perms) == -1) 1237a832d43SChris D. Faulhaber return NULL; 1247a832d43SChris D. Faulhaber if (acl_clear_perms(perms) == -1) 1257a832d43SChris D. Faulhaber return NULL; 1267a832d43SChris D. Faulhaber 1277a832d43SChris D. Faulhaber /* calculate other mode */ 12843960f15SRobert Watson if (sb.st_mode & S_IROTH) 1297a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_READ) == -1) 1307a832d43SChris D. Faulhaber return NULL; 13143960f15SRobert Watson if (sb.st_mode & S_IWOTH) 1327a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_WRITE) == -1) 1337a832d43SChris D. Faulhaber return NULL; 13443960f15SRobert Watson if (sb.st_mode & S_IXOTH) 1357a832d43SChris D. Faulhaber if (acl_add_perm(perms, ACL_EXECUTE) == -1) 1367a832d43SChris D. Faulhaber return NULL; 1377a832d43SChris D. Faulhaber if (acl_set_permset(entry, perms) == -1) 1387a832d43SChris D. Faulhaber return NULL; 13943960f15SRobert Watson 14043960f15SRobert Watson return(acl); 14143960f15SRobert Watson } 14243960f15SRobert Watson 14343960f15SRobert Watson static int 14443960f15SRobert Watson print_acl(char *path, acl_type_t type) 14543960f15SRobert Watson { 14643960f15SRobert Watson struct stat sb; 14743960f15SRobert Watson acl_t acl; 14843960f15SRobert Watson char *acl_text; 14943960f15SRobert Watson int error; 15043960f15SRobert Watson 15143960f15SRobert Watson error = stat(path, &sb); 15243960f15SRobert Watson if (error == -1) { 15343960f15SRobert Watson perror(path); 15443960f15SRobert Watson return(-1); 15543960f15SRobert Watson } 15643960f15SRobert Watson 15743960f15SRobert Watson if (more_than_one) 15843960f15SRobert Watson printf("\n"); 15943960f15SRobert Watson else 16043960f15SRobert Watson more_than_one++; 16143960f15SRobert Watson 16243960f15SRobert Watson printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid); 16343960f15SRobert Watson 16443960f15SRobert Watson acl = acl_get_file(path, type); 16543960f15SRobert Watson if (!acl) { 16643960f15SRobert Watson if (errno != EOPNOTSUPP) { 16743960f15SRobert Watson warn("%s", path); 16843960f15SRobert Watson return(-1); 16943960f15SRobert Watson } 17043960f15SRobert Watson errno = 0; 17143960f15SRobert Watson if (type != ACL_TYPE_ACCESS) 17243960f15SRobert Watson return(0); 17343960f15SRobert Watson acl = acl_from_stat(sb); 17443960f15SRobert Watson if (!acl) { 17543960f15SRobert Watson perror("acl_from_stat()"); 17643960f15SRobert Watson return(-1); 17743960f15SRobert Watson } 17843960f15SRobert Watson } 17943960f15SRobert Watson 18043960f15SRobert Watson acl_text = acl_to_text(acl, 0); 18143960f15SRobert Watson if (!acl_text) { 18243960f15SRobert Watson perror(path); 18343960f15SRobert Watson return(-1); 18443960f15SRobert Watson } 18543960f15SRobert Watson 18643960f15SRobert Watson printf("%s", acl_text); 18743960f15SRobert Watson 18843960f15SRobert Watson acl_free(acl); 18943960f15SRobert Watson acl_free(acl_text); 19043960f15SRobert Watson 19143960f15SRobert Watson return(0); 19243960f15SRobert Watson } 19343960f15SRobert Watson 19443960f15SRobert Watson static int 19543960f15SRobert Watson print_acl_from_stdin(acl_type_t type) 19643960f15SRobert Watson { 19743960f15SRobert Watson char pathname[PATH_MAX]; 19843960f15SRobert Watson int carried_error = 0; 19943960f15SRobert Watson 20043960f15SRobert Watson pathname[sizeof(pathname) - 1] = '\0'; 20143960f15SRobert Watson while (fgets(pathname, sizeof(pathname), stdin)) { 20243960f15SRobert Watson /* remove the \n */ 20343960f15SRobert Watson pathname[strlen(pathname) - 1] = '\0'; 20443960f15SRobert Watson if (print_acl(pathname, type) == -1) { 20543960f15SRobert Watson carried_error = -1; 20643960f15SRobert Watson } 20743960f15SRobert Watson } 20843960f15SRobert Watson 20943960f15SRobert Watson return(carried_error); 21043960f15SRobert Watson } 21143960f15SRobert Watson 21243960f15SRobert Watson int 21343960f15SRobert Watson main(int argc, char *argv[]) 21443960f15SRobert Watson { 21543960f15SRobert Watson acl_type_t type = ACL_TYPE_ACCESS; 21643960f15SRobert Watson int carried_error = 0; 21743960f15SRobert Watson int ch, error, i; 21843960f15SRobert Watson 21943960f15SRobert Watson while ((ch = getopt(argc, argv, "d")) != -1) 22043960f15SRobert Watson switch(ch) { 22143960f15SRobert Watson case 'd': 22243960f15SRobert Watson type = ACL_TYPE_DEFAULT; 22343960f15SRobert Watson break; 22443960f15SRobert Watson default: 22543960f15SRobert Watson usage(); 22643960f15SRobert Watson return(-1); 22743960f15SRobert Watson } 22843960f15SRobert Watson argc -= optind; 22943960f15SRobert Watson argv += optind; 23043960f15SRobert Watson 23143960f15SRobert Watson if (argc == 0) { 23243960f15SRobert Watson error = print_acl_from_stdin(type); 23343960f15SRobert Watson return(error); 23443960f15SRobert Watson } 23543960f15SRobert Watson 23643960f15SRobert Watson for (i = 0; i < argc; i++) { 23743960f15SRobert Watson if (!strcmp(argv[i], "-")) { 23843960f15SRobert Watson error = print_acl_from_stdin(type); 23943960f15SRobert Watson if (error == -1) 24043960f15SRobert Watson carried_error = -1; 24143960f15SRobert Watson } else { 24243960f15SRobert Watson error = print_acl(argv[i], type); 24343960f15SRobert Watson if (error == -1) 24443960f15SRobert Watson carried_error = -1; 24543960f15SRobert Watson } 24643960f15SRobert Watson } 24743960f15SRobert Watson 24843960f15SRobert Watson return(carried_error); 24943960f15SRobert Watson } 250