xref: /freebsd/bin/getfacl/getfacl.c (revision fab912df88a4abeb6b7d0ee5a83b299d5d2ceb1d)
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