merge.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/merge.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 <sysexits.h>
36
37#include "setfacl.h"
38
39/* merge acl into existing file's ACL */
40int
41merge_acl(acl_t acl, acl_t *prev_acl)
42{
43	acl_t acl_new;
44	int blank_acl_user, blank_acl_group, have_entry, i, j;
45	struct stat sb;
46
47	blank_acl_user = blank_acl_group = 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	/* step through new ACL entries */
57	for (i = 0; i < acl->acl_cnt; i++) {
58		have_entry = 0;
59
60		/* oh look, we have an ACL_MASK entry */
61		if (acl->acl_entry[i].ae_tag == ACL_MASK)
62			have_mask = 1;
63
64		/* check against the existing ACL entries */
65		for (j = 0; j < acl_new->acl_cnt && !have_entry; j++) {
66			if (acl_new->acl_entry[j].ae_tag ==
67			    acl->acl_entry[i].ae_tag) {
68				switch(acl->acl_entry[i].ae_tag) {
69				case ACL_USER_OBJ:
70					acl_new->acl_entry[j].ae_perm =
71					    acl->acl_entry[i].ae_perm;
72					acl_new->acl_entry[j].ae_id = sb.st_uid;
73					have_entry = 1;
74					break;
75				case ACL_GROUP_OBJ:
76					acl_new->acl_entry[j].ae_perm =
77					    acl->acl_entry[i].ae_perm;
78					acl_new->acl_entry[j].ae_id = sb.st_gid;
79					have_entry = 1;
80					break;
81				default:
82					if (acl_new->acl_entry[j].ae_id ==
83					    acl->acl_entry[i].ae_id) {
84						/* any other matches */
85						acl_new->acl_entry[j].ae_perm =
86						    acl->acl_entry[i].ae_perm;
87						have_entry = 1;
88					}
89					break;
90				}
91			}
92		}
93
94		/* if this entry has not been found, it must be new */
95		if (!have_entry) {
96			if (acl_new->acl_cnt == ACL_MAX_ENTRIES) {
97				warn("too many ACL entries");
98				acl_free(acl_new);
99				return -1;
100			}
101			acl_new->acl_entry[acl_new->acl_cnt++] =
102			    acl->acl_entry[i];
103		}
104	}
105
106	if (acl_type == ACL_TYPE_ACCESS)
107		*prev_acl[0] = *acl_new;
108	else
109		*prev_acl[1] = *acl_new;
110	acl_free(acl_new);
111
112	return 0;
113}
114