merge.c revision 75928
1160040Smarcel/* 2160040Smarcel * Copyright (c) 2001 Chris D. Faulhaber 3160040Smarcel * All rights reserved. 4160040Smarcel * 5160040Smarcel * Redistribution and use in source and binary forms, with or without 6160040Smarcel * modification, are permitted provided that the following conditions 7160040Smarcel * are met: 8160040Smarcel * 1. Redistributions of source code must retain the above copyright 9160040Smarcel * notice, this list of conditions and the following disclaimer. 10160040Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11160040Smarcel * notice, this list of conditions and the following disclaimer in the 12160040Smarcel * documentation and/or other materials provided with the distribution. 13160040Smarcel * 14160040Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15160040Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16160040Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17160040Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE 18160040Smarcel * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19160040Smarcel * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20160040Smarcel * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21160040Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22160040Smarcel * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23160040Smarcel * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24160040Smarcel * POSSIBILITY OF SUCH DAMAGE. 25160040Smarcel * 26160040Smarcel * $FreeBSD: head/bin/setfacl/merge.c 75928 2001-04-24 22:45:41Z jedgar $ 27160040Smarcel */ 28160040Smarcel 29160040Smarcel#include <sys/types.h> 30160040Smarcel#include <sys/acl.h> 31160040Smarcel#include <sys/stat.h> 32160040Smarcel 33160040Smarcel#include <err.h> 34160040Smarcel#include <stdio.h> 35160040Smarcel#include <sysexits.h> 36160040Smarcel 37160040Smarcel#include "setfacl.h" 38160040Smarcel 39160040Smarcel/* merge acl into existing file's ACL */ 40160040Smarcelint 41160040Smarcelmerge_acl(acl_t acl, acl_t *prev_acl) 42160040Smarcel{ 43160040Smarcel acl_entry_t entry, entry_new; 44160040Smarcel acl_permset_t permset; 45160040Smarcel acl_t acl_new; 46160040Smarcel acl_tag_t tag, tag_new; 47160040Smarcel int entry_id, entry_id_new, have_entry; 48160040Smarcel uid_t *id, *id_new; 49160040Smarcel 50160040Smarcel if (acl_type == ACL_TYPE_ACCESS) 51160040Smarcel acl_new = acl_dup(prev_acl[0]); 52160040Smarcel else 53160040Smarcel acl_new = acl_dup(prev_acl[1]); 54160040Smarcel if (!acl_new) 55160040Smarcel err(EX_OSERR, "acl_dup() failed"); 56160040Smarcel 57160040Smarcel entry_id = ACL_FIRST_ENTRY; 58160040Smarcel 59160040Smarcel while (acl_get_entry(acl, entry_id, &entry) == 1) { 60160040Smarcel entry_id = ACL_NEXT_ENTRY; 61160040Smarcel have_entry = 0; 62160040Smarcel 63160040Smarcel /* keep track of existing ACL_MASK entries */ 64160040Smarcel if (acl_get_tag_type(entry, &tag) == -1) 65160040Smarcel err(EX_OSERR, 66160040Smarcel "acl_get_tag_type() failed - invalid ACL entry"); 67160040Smarcel if (tag == ACL_MASK) 68160040Smarcel have_mask = 1; 69160040Smarcel 70160040Smarcel /* check against the existing ACL entries */ 71160040Smarcel entry_id_new = ACL_FIRST_ENTRY; 72160040Smarcel while (!have_entry && 73160040Smarcel acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) { 74160040Smarcel entry_id_new = ACL_NEXT_ENTRY; 75160040Smarcel 76160040Smarcel if (acl_get_tag_type(entry, &tag) == -1) 77160040Smarcel err(EX_OSERR, "acl_get_tag_type() failed"); 78160040Smarcel if (acl_get_tag_type(entry_new, &tag_new) == -1) 79160040Smarcel err(EX_OSERR, "acl_get_tag_type() failed"); 80160040Smarcel if (tag != tag_new) 81160040Smarcel continue; 82160040Smarcel 83160040Smarcel switch(tag) { 84160040Smarcel case ACL_USER: 85160040Smarcel case ACL_GROUP: 86160040Smarcel id = acl_get_qualifier(entry); 87160040Smarcel if (id == NULL) 88160040Smarcel err(EX_OSERR, 89160040Smarcel "acl_get_qualifier() failed"); 90 id_new = acl_get_qualifier(entry_new); 91 if (id_new == NULL) 92 err(EX_OSERR, 93 "acl_get_qualifier() failed"); 94 if (*id == *id_new) { 95 /* any other matches */ 96 if (acl_get_permset(entry, &permset) 97 == -1) 98 err(EX_OSERR, 99 "acl_get_permset() failed"); 100 if (acl_set_permset(entry_new, permset) 101 == -1) 102 err(EX_OSERR, 103 "acl_set_permset() failed"); 104 have_entry = 1; 105 } 106 acl_free(id); 107 acl_free(id_new); 108 if (!have_entry) 109 break; 110 /* FALLTHROUGH */ 111 case ACL_USER_OBJ: 112 case ACL_GROUP_OBJ: 113 case ACL_OTHER: 114 case ACL_MASK: 115 if (acl_get_permset(entry, &permset) == -1) 116 err(EX_OSERR, 117 "acl_get_permset() failed"); 118 if (acl_set_permset(entry_new, permset) == -1) 119 err(EX_OSERR, 120 "acl_set_permset() failed"); 121 have_entry = 1; 122 break; 123 default: 124 /* should never be here */ 125 errx(EX_OSERR, "Invalid tag type: %i", tag); 126 break; 127 } 128 } 129 130 /* if this entry has not been found, it must be new */ 131 if (!have_entry) { 132 if (acl_create_entry(&acl_new, &entry_new) == -1) { 133 acl_free(acl_new); 134 return -1; 135 } 136 if (acl_copy_entry(entry_new, entry) == -1) 137 err(EX_OSERR, "acl_copy_entry() failed"); 138 } 139 } 140 141 142 if (acl_type == ACL_TYPE_ACCESS) { 143 acl_free(prev_acl[0]); 144 prev_acl[0] = acl_new; 145 } else { 146 acl_free(prev_acl[1]); 147 prev_acl[1] = acl_new; 148 } 149 150 151 return 0; 152} 153