remove.c revision 74465
1/*
2 * Copyright (c) 2001 Chris D. Faulhaber
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 THE VOICES IN HIS HEAD BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/bin/setfacl/remove.c 74465 2001-03-19 18:09:25Z rwatson $
27 */
28
29#include <sys/types.h>
30#include <sys/acl.h>
31#include <sys/stat.h>
32
33#include <err.h>
34#include <stdio.h>
35#include <string.h>
36#include <sysexits.h>
37
38#include "setfacl.h"
39
40/* remove ACL entries from an ACL */
41int
42remove_acl(acl_t acl, acl_t *prev_acl)
43{
44	acl_t acl_new;
45	int carried_error, i;
46
47	carried_error = 0;
48
49	if (acl_type == ACL_TYPE_ACCESS)
50		acl_new = acl_dup(prev_acl[0]);
51	else
52		acl_new = acl_dup(prev_acl[1]);
53	if (!acl_new)
54		err(EX_OSERR, "acl_dup() failed");
55
56	/* find and delete the entry */
57	for (i = 0; i < acl->acl_cnt; i++) {
58		if (acl->acl_entry[i].ae_tag == ACL_MASK)
59			have_mask++;
60		if (acl_delete_entry(acl_new, &acl->acl_entry[i]) == -1) {
61			carried_error++;
62			warnx("cannot remove non-existent acl entry");
63		}
64	}
65
66	if (acl_type == ACL_TYPE_ACCESS) {
67		acl_free(prev_acl[0]);
68		prev_acl[0] = acl_new;
69	} else {
70		acl_free(prev_acl[1]);
71		prev_acl[1] = acl_new;
72	}
73
74	if (carried_error)
75		return -1;
76
77	return 0;
78}
79
80/* remove default entries */
81int
82remove_default(acl_t *prev_acl)
83{
84
85	if (prev_acl[1]) {
86		bzero(prev_acl[1], sizeof(struct acl));
87		prev_acl[1]->acl_cnt = 0;
88	} else {
89		warn("cannot remove default ACL");
90		return -1;
91	}
92	return 0;
93}
94
95/* remove extended entries */
96void
97remove_ext(acl_t *prev_acl)
98{
99	acl_t acl_new, acl_old;
100	acl_perm_t group_perm, mask_perm;
101	int have_mask_entry, i;
102
103	if (acl_type == ACL_TYPE_ACCESS)
104		acl_old = acl_dup(prev_acl[0]);
105	else
106		acl_old = acl_dup(prev_acl[1]);
107	if (!acl_old)
108		err(EX_OSERR, "acl_dup() failed");
109
110	group_perm = mask_perm = 0;
111	have_mask_entry = 0;
112	acl_new = acl_init(ACL_MAX_ENTRIES);
113	if (!acl_new)
114		err(EX_OSERR, "%s", "acl_init() failed");
115
116	/* only save the default user/group/other entries */
117	for (i = 0; i < acl_old->acl_cnt; i++)
118		switch(acl_old->acl_entry[i].ae_tag) {
119		case ACL_USER_OBJ:
120			acl_new->acl_entry[0] = acl_old->acl_entry[i];
121			break;
122		case ACL_GROUP_OBJ:
123			acl_new->acl_entry[1] = acl_old->acl_entry[i];
124			group_perm = acl_old->acl_entry[i].ae_perm;
125			break;
126		case ACL_OTHER_OBJ:
127			acl_new->acl_entry[2] = acl_old->acl_entry[i];
128			break;
129		case ACL_MASK:
130			mask_perm = acl_old->acl_entry[i].ae_perm;
131			have_mask_entry = 1;
132			break;
133		default:
134			break;
135		}
136	/*
137	 * If the ACL contains a mask entry, then the permissions associated
138	 * with the owning group entry in the resulting ACL shall be set to
139	 * only those permissions associated with both the owning group entry
140	 * and the mask entry of the current ACL.
141	 */
142	if (have_mask_entry)
143		acl_new->acl_entry[1].ae_perm = group_perm & mask_perm;
144	acl_new->acl_cnt = 3;
145
146	if (acl_type == ACL_TYPE_ACCESS) {
147		acl_free(prev_acl[0]);
148		prev_acl[0] = acl_new;
149	} else {
150		acl_free(prev_acl[1]);
151		prev_acl[1] = acl_new;
152	}
153
154	have_mask = 0;
155}
156