getfacl.c revision 75491
154359Sroberto/*-
254359Sroberto * Copyright (c) 1999-2001 Robert N M Watson
354359Sroberto * All rights reserved.
454359Sroberto *
582498Sroberto * Redistribution and use in source and binary forms, with or without
654359Sroberto * modification, are permitted provided that the following conditions
754359Sroberto * are met:
854359Sroberto * 1. Redistributions of source code must retain the above copyright
954359Sroberto *    notice, this list of conditions and the following disclaimer.
1054359Sroberto * 2. Redistributions in binary form must reproduce the above copyright
1154359Sroberto *    notice, this list of conditions and the following disclaimer in the
1254359Sroberto *    documentation and/or other materials provided with the distribution.
1354359Sroberto *
1454359Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1554359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1654359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1754359Sroberto * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1854359Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1954359Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2054359Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2154359Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2254359Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2354359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2454359Sroberto * SUCH DAMAGE.
2554359Sroberto *
2654359Sroberto *	$FreeBSD: head/bin/getfacl/getfacl.c 75491 2001-04-13 19:24:28Z jedgar $
2754359Sroberto */
2854359Sroberto/*
2954359Sroberto * getfacl -- POSIX.1e utility to extract ACLs from files and directories
3054359Sroberto * and send the results to stdout
3154359Sroberto */
3254359Sroberto
3354359Sroberto#include <sys/types.h>
3454359Sroberto#include <sys/param.h>
3554359Sroberto#include <sys/acl.h>
3654359Sroberto#include <sys/stat.h>
3754359Sroberto#include <err.h>
3854359Sroberto#include <errno.h>
3954359Sroberto#include <stdio.h>
4054359Sroberto#include <stdlib.h>
4154359Sroberto#include <unistd.h>
4254359Sroberto
4354359Srobertoint	more_than_one = 0;
4454359Sroberto
4554359Srobertostatic void
4654359Srobertousage(void)
4754359Sroberto{
4854359Sroberto
4954359Sroberto	fprintf(stderr, "getfacl [-d] [files ...]\n");
5054359Sroberto}
5154359Sroberto
5254359Sroberto/*
53290000Sglebius * return an ACL corresponding to the permissions
54290000Sglebius * contained in struct stat
55290000Sglebius */
56290000Sglebiusstatic acl_t
57290000Sglebiusacl_from_stat(struct stat sb)
58290000Sglebius{
59290000Sglebius	acl_t acl;
60290000Sglebius	acl_entry_t entry;
61290000Sglebius	acl_permset_t perms;
62290000Sglebius
63290000Sglebius	/* create the ACL */
64290000Sglebius	acl = acl_init(3);
65290000Sglebius	if (!acl)
66290000Sglebius		return NULL;
67290000Sglebius
6854359Sroberto	/* First entry: ACL_USER_OBJ */
6954359Sroberto	if (acl_create_entry(&acl, &entry) == -1)
7054359Sroberto		return NULL;
71290000Sglebius	if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1)
7254359Sroberto		return NULL;
7354359Sroberto
74290000Sglebius	if (acl_get_permset(entry, &perms) == -1)
75200576Sroberto		return NULL;
76200576Sroberto	if (acl_clear_perms(perms) == -1)
77200576Sroberto		return NULL;
78200576Sroberto
79200576Sroberto	/* calculate user mode */
80132451Sroberto	if (sb.st_mode & S_IRUSR)
81132451Sroberto		if (acl_add_perm(perms, ACL_READ) == -1)
8254359Sroberto			return NULL;
8354359Sroberto	if (sb.st_mode & S_IWUSR)
8454359Sroberto		if (acl_add_perm(perms, ACL_WRITE) == -1)
8554359Sroberto			return NULL;
8654359Sroberto	if (sb.st_mode & S_IXUSR)
8754359Sroberto		if (acl_add_perm(perms, ACL_EXECUTE) == -1)
8854359Sroberto			return NULL;
8954359Sroberto	if (acl_set_permset(entry, perms) == -1)
90290000Sglebius		return NULL;
91290000Sglebius
92290000Sglebius	/* Second entry: ACL_GROUP_OBJ */
93290000Sglebius	if (acl_create_entry(&acl, &entry) == -1)
94290000Sglebius		return NULL;
9554359Sroberto	if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1)
9654359Sroberto		return NULL;
9754359Sroberto
9854359Sroberto	if (acl_get_permset(entry, &perms) == -1)
9954359Sroberto		return NULL;
10054359Sroberto	if (acl_clear_perms(perms) == -1)
10154359Sroberto		return NULL;
10254359Sroberto
10354359Sroberto	/* calculate group mode */
10454359Sroberto	if (sb.st_mode & S_IRGRP)
10554359Sroberto		if (acl_add_perm(perms, ACL_READ) == -1)
10654359Sroberto			return NULL;
10754359Sroberto	if (sb.st_mode & S_IWGRP)
10854359Sroberto		if (acl_add_perm(perms, ACL_WRITE) == -1)
10954359Sroberto			return NULL;
110290000Sglebius	if (sb.st_mode & S_IXGRP)
11154359Sroberto		if (acl_add_perm(perms, ACL_EXECUTE) == -1)
112132451Sroberto			return NULL;
113132451Sroberto	if (acl_set_permset(entry, perms) == -1)
114132451Sroberto		return NULL;
115132451Sroberto
116132451Sroberto	/* Third entry: ACL_OTHER */
117132451Sroberto	if (acl_create_entry(&acl, &entry) == -1)
118290000Sglebius		return NULL;
119290000Sglebius	if (acl_set_tag_type(entry, ACL_OTHER) == -1)
120290000Sglebius		return NULL;
121132451Sroberto
122132451Sroberto	if (acl_get_permset(entry, &perms) == -1)
123132451Sroberto		return NULL;
124132451Sroberto	if (acl_clear_perms(perms) == -1)
125290000Sglebius		return NULL;
126290000Sglebius
127290000Sglebius	/* calculate other mode */
128290000Sglebius	if (sb.st_mode & S_IROTH)
129290000Sglebius		if (acl_add_perm(perms, ACL_READ) == -1)
13054359Sroberto			return NULL;
131290000Sglebius	if (sb.st_mode & S_IWOTH)
132290000Sglebius		if (acl_add_perm(perms, ACL_WRITE) == -1)
133290000Sglebius			return NULL;
134290000Sglebius	if (sb.st_mode & S_IXOTH)
135290000Sglebius		if (acl_add_perm(perms, ACL_EXECUTE) == -1)
136290000Sglebius			return NULL;
137290000Sglebius	if (acl_set_permset(entry, perms) == -1)
138290000Sglebius		return NULL;
139290000Sglebius
140290000Sglebius	return(acl);
141290000Sglebius}
142290000Sglebius
143290000Sglebiusstatic int
144290000Sglebiusprint_acl(char *path, acl_type_t type)
145290000Sglebius{
146290000Sglebius	struct stat	sb;
147290000Sglebius	acl_t	acl;
148290000Sglebius	char	*acl_text;
149290000Sglebius	int	error;
150290000Sglebius
151290000Sglebius	error = stat(path, &sb);
152290000Sglebius	if (error == -1) {
153290000Sglebius		perror(path);
154290000Sglebius		return(-1);
155290000Sglebius	}
156290000Sglebius
157290000Sglebius	if (more_than_one)
158290000Sglebius		printf("\n");
159290000Sglebius	else
160290000Sglebius		more_than_one++;
161290000Sglebius
162290000Sglebius	printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid);
163290000Sglebius
164290000Sglebius	acl = acl_get_file(path, type);
165290000Sglebius	if (!acl) {
166290000Sglebius		if (errno != EOPNOTSUPP) {
167290000Sglebius			warn("%s", path);
168290000Sglebius			return(-1);
169290000Sglebius		}
170290000Sglebius		errno = 0;
171290000Sglebius		if (type != ACL_TYPE_ACCESS)
172290000Sglebius			return(0);
173290000Sglebius		acl = acl_from_stat(sb);
174290000Sglebius		if (!acl) {
175290000Sglebius			perror("acl_from_stat()");
176290000Sglebius			return(-1);
177290000Sglebius		}
178290000Sglebius	}
179290000Sglebius
180290000Sglebius	acl_text = acl_to_text(acl, 0);
181290000Sglebius	if (!acl_text) {
182290000Sglebius		perror(path);
183290000Sglebius		return(-1);
184290000Sglebius	}
185290000Sglebius
186290000Sglebius	printf("%s", acl_text);
187290000Sglebius
188290000Sglebius	acl_free(acl);
189290000Sglebius	acl_free(acl_text);
190290000Sglebius
191290000Sglebius	return(0);
192290000Sglebius}
193290000Sglebius
194290000Sglebiusstatic int
195290000Sglebiusprint_acl_from_stdin(acl_type_t type)
196290000Sglebius{
197290000Sglebius	char	pathname[PATH_MAX];
198290000Sglebius	int	carried_error = 0;
199290000Sglebius
200290000Sglebius	pathname[sizeof(pathname) - 1] = '\0';
201290000Sglebius	while (fgets(pathname, sizeof(pathname), stdin)) {
202290000Sglebius		/* remove the \n */
203290000Sglebius		pathname[strlen(pathname) - 1] = '\0';
204290000Sglebius		if (print_acl(pathname, type) == -1) {
205290000Sglebius			carried_error = -1;
206290000Sglebius		}
207290000Sglebius	}
208290000Sglebius
209290000Sglebius	return(carried_error);
210290000Sglebius}
211290000Sglebius
212290000Sglebiusint
213290000Sglebiusmain(int argc, char *argv[])
214290000Sglebius{
215290000Sglebius	acl_type_t	type = ACL_TYPE_ACCESS;
216290000Sglebius	int	carried_error = 0;
217290000Sglebius	int	ch, error, i;
218290000Sglebius
219290000Sglebius	while ((ch = getopt(argc, argv, "d")) != -1)
220290000Sglebius		switch(ch) {
221290000Sglebius		case 'd':
222290000Sglebius			type = ACL_TYPE_DEFAULT;
223290000Sglebius			break;
224290000Sglebius		default:
225290000Sglebius			usage();
226290000Sglebius			return(-1);
227290000Sglebius		}
228290000Sglebius	argc -= optind;
229290000Sglebius	argv += optind;
230290000Sglebius
231290000Sglebius	if (argc == 0) {
232290000Sglebius		error = print_acl_from_stdin(type);
233290000Sglebius		return(error);
234290000Sglebius	}
235290000Sglebius
236290000Sglebius	for (i = 0; i < argc; i++) {
237290000Sglebius		if (!strcmp(argv[i], "-")) {
238290000Sglebius			error = print_acl_from_stdin(type);
239290000Sglebius			if (error == -1)
240290000Sglebius				carried_error = -1;
241290000Sglebius		} else {
242290000Sglebius			error = print_acl(argv[i], type);
243290000Sglebius			if (error == -1)
244290000Sglebius				carried_error = -1;
245290000Sglebius		}
246290000Sglebius	}
247290000Sglebius
248290000Sglebius	return(carried_error);
249290000Sglebius}
250290000Sglebius