merge.c revision 87259
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 87259 2001-12-03 01:20:52Z jedgar $ 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 36#include "setfacl.h" 37 38/* 39 * merge an ACL into existing file's ACL 40 */ 41int 42merge_acl(acl_t acl, acl_t *prev_acl) 43{ 44 acl_entry_t entry, entry_new; 45 acl_permset_t permset; 46 acl_t acl_new; 47 acl_tag_t tag, tag_new; 48 int entry_id, entry_id_new, have_entry; 49 uid_t *id, *id_new; 50 51 if (acl_type == ACL_TYPE_ACCESS) 52 acl_new = acl_dup(prev_acl[ACCESS_ACL]); 53 else 54 acl_new = acl_dup(prev_acl[DEFAULT_ACL]); 55 if (acl_new == NULL) 56 err(1, "acl_dup() failed"); 57 58 entry_id = ACL_FIRST_ENTRY; 59 60 while (acl_get_entry(acl, entry_id, &entry) == 1) { 61 entry_id = ACL_NEXT_ENTRY; 62 have_entry = 0; 63 64 /* keep track of existing ACL_MASK entries */ 65 if (acl_get_tag_type(entry, &tag) == -1) 66 err(1, "acl_get_tag_type() failed - invalid ACL entry"); 67 if (tag == ACL_MASK) 68 have_mask = 1; 69 70 /* check against the existing ACL entries */ 71 entry_id_new = ACL_FIRST_ENTRY; 72 while (have_entry == 0 && 73 acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) { 74 entry_id_new = ACL_NEXT_ENTRY; 75 76 if (acl_get_tag_type(entry, &tag) == -1) 77 err(1, "acl_get_tag_type() failed"); 78 if (acl_get_tag_type(entry_new, &tag_new) == -1) 79 err(1, "acl_get_tag_type() failed"); 80 if (tag != tag_new) 81 continue; 82 83 switch(tag) { 84 case ACL_USER: 85 case ACL_GROUP: 86 id = acl_get_qualifier(entry); 87 if (id == NULL) 88 err(1, "acl_get_qualifier() failed"); 89 id_new = acl_get_qualifier(entry_new); 90 if (id_new == NULL) 91 err(1, "acl_get_qualifier() failed"); 92 if (*id == *id_new) { 93 /* any other matches */ 94 if (acl_get_permset(entry, &permset) 95 == -1) 96 err(1, 97 "acl_get_permset() failed"); 98 if (acl_set_permset(entry_new, permset) 99 == -1) 100 err(1, 101 "acl_set_permset() failed"); 102 have_entry = 1; 103 } 104 acl_free(id); 105 acl_free(id_new); 106 if (have_entry == 0) 107 break; 108 /* FALLTHROUGH */ 109 case ACL_USER_OBJ: 110 case ACL_GROUP_OBJ: 111 case ACL_OTHER: 112 case ACL_MASK: 113 if (acl_get_permset(entry, &permset) == -1) 114 err(1, "acl_get_permset() failed"); 115 if (acl_set_permset(entry_new, permset) == -1) 116 err(1, "acl_set_permset() failed"); 117 have_entry = 1; 118 break; 119 default: 120 /* should never be here */ 121 errx(1, "Invalid tag type: %i", tag); 122 break; 123 } 124 } 125 126 /* if this entry has not been found, it must be new */ 127 if (have_entry == 0) { 128 if (acl_create_entry(&acl_new, &entry_new) == -1) { 129 acl_free(acl_new); 130 return (-1); 131 } 132 if (acl_copy_entry(entry_new, entry) == -1) 133 err(1, "acl_copy_entry() failed"); 134 } 135 } 136 137 138 if (acl_type == ACL_TYPE_ACCESS) { 139 acl_free(prev_acl[ACCESS_ACL]); 140 prev_acl[ACCESS_ACL] = acl_new; 141 } else { 142 acl_free(prev_acl[DEFAULT_ACL]); 143 prev_acl[DEFAULT_ACL] = acl_new; 144 } 145 146 147 return (0); 148} 149