getfacl.c revision 74465
1/*-
2 * Copyright (c) 1999-2001 Robert N M Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: head/bin/getfacl/getfacl.c 74465 2001-03-19 18:09:25Z rwatson $
27 */
28/*
29 * getfacl -- POSIX.1e utility to extract ACLs from files and directories
30 * and send the results to stdout
31 */
32
33#include <sys/types.h>
34#include <sys/param.h>
35#include <sys/acl.h>
36#include <sys/stat.h>
37#include <err.h>
38#include <errno.h>
39#include <stdio.h>
40#include <unistd.h>
41
42int	more_than_one = 0;
43
44static void
45usage(void)
46{
47
48	fprintf(stderr, "getfacl [-d] [files ...]\n");
49}
50
51static acl_t
52acl_from_stat(struct stat sb)
53{
54	acl_t acl;
55
56	acl = acl_init(3);
57	if (!acl)
58		return(NULL);
59
60	acl->acl_entry[0].ae_tag = ACL_USER_OBJ;
61	acl->acl_entry[0].ae_id  = sb.st_uid;
62	acl->acl_entry[0].ae_perm = 0;
63	if (sb.st_mode & S_IRUSR)
64		acl->acl_entry[0].ae_perm |= ACL_PERM_READ;
65	if (sb.st_mode & S_IWUSR)
66		acl->acl_entry[0].ae_perm |= ACL_PERM_WRITE;
67	if (sb.st_mode & S_IXUSR)
68		acl->acl_entry[0].ae_perm |= ACL_PERM_EXEC;
69
70	acl->acl_entry[1].ae_tag = ACL_GROUP_OBJ;
71	acl->acl_entry[1].ae_id  = sb.st_gid;
72	acl->acl_entry[1].ae_perm = 0;
73	if (sb.st_mode & S_IRGRP)
74		acl->acl_entry[1].ae_perm |= ACL_PERM_READ;
75	if (sb.st_mode & S_IWGRP)
76		acl->acl_entry[1].ae_perm |= ACL_PERM_WRITE;
77	if (sb.st_mode & S_IXGRP)
78		acl->acl_entry[1].ae_perm |= ACL_PERM_EXEC;
79
80	acl->acl_entry[2].ae_tag = ACL_OTHER_OBJ;
81	acl->acl_entry[2].ae_id  = 0;
82	acl->acl_entry[2].ae_perm = 0;
83	if (sb.st_mode & S_IROTH)
84		acl->acl_entry[2].ae_perm |= ACL_PERM_READ;
85	if (sb.st_mode & S_IWOTH)
86		acl->acl_entry[2].ae_perm |= ACL_PERM_WRITE;
87	if (sb.st_mode & S_IXOTH)
88		acl->acl_entry[2].ae_perm |= ACL_PERM_EXEC;
89
90	acl->acl_cnt = 3;
91
92	return(acl);
93}
94
95static int
96print_acl(char *path, acl_type_t type)
97{
98	struct stat	sb;
99	acl_t	acl;
100	char	*acl_text;
101	int	error;
102
103	error = stat(path, &sb);
104	if (error == -1) {
105		perror(path);
106		return(-1);
107	}
108
109	if (more_than_one)
110		printf("\n");
111	else
112		more_than_one++;
113
114	printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid);
115
116	acl = acl_get_file(path, type);
117	if (!acl) {
118		if (errno != EOPNOTSUPP) {
119			warn("%s", path);
120			return(-1);
121		}
122		errno = 0;
123		if (type != ACL_TYPE_ACCESS)
124			return(0);
125		acl = acl_from_stat(sb);
126		if (!acl) {
127			perror("acl_from_stat()");
128			return(-1);
129		}
130	}
131
132	acl_text = acl_to_text(acl, 0);
133	if (!acl_text) {
134		perror(path);
135		return(-1);
136	}
137
138	printf("%s", acl_text);
139
140	acl_free(acl);
141	acl_free(acl_text);
142
143	return(0);
144}
145
146static int
147print_acl_from_stdin(acl_type_t type)
148{
149	char	pathname[PATH_MAX];
150	int	carried_error = 0;
151
152	pathname[sizeof(pathname) - 1] = '\0';
153	while (fgets(pathname, sizeof(pathname), stdin)) {
154		/* remove the \n */
155		pathname[strlen(pathname) - 1] = '\0';
156		if (print_acl(pathname, type) == -1) {
157			carried_error = -1;
158		}
159	}
160
161	return(carried_error);
162}
163
164int
165main(int argc, char *argv[])
166{
167	acl_type_t	type = ACL_TYPE_ACCESS;
168	int	carried_error = 0;
169	int	ch, error, i;
170
171	while ((ch = getopt(argc, argv, "d")) != -1)
172		switch(ch) {
173		case 'd':
174			type = ACL_TYPE_DEFAULT;
175			break;
176		default:
177			usage();
178			return(-1);
179		}
180	argc -= optind;
181	argv += optind;
182
183	if (argc == 0) {
184		error = print_acl_from_stdin(type);
185		return(error);
186	}
187
188	for (i = 0; i < argc; i++) {
189		if (!strcmp(argv[i], "-")) {
190			error = print_acl_from_stdin(type);
191			if (error == -1)
192				carried_error = -1;
193		} else {
194			error = print_acl(argv[i], type);
195			if (error == -1)
196				carried_error = -1;
197		}
198	}
199
200	return(carried_error);
201}
202