merge.c revision 75928
174465Srwatson/* 274465Srwatson * Copyright (c) 2001 Chris D. Faulhaber 374465Srwatson * All rights reserved. 474465Srwatson * 574465Srwatson * Redistribution and use in source and binary forms, with or without 674465Srwatson * modification, are permitted provided that the following conditions 774465Srwatson * are met: 874465Srwatson * 1. Redistributions of source code must retain the above copyright 974465Srwatson * notice, this list of conditions and the following disclaimer. 1074465Srwatson * 2. Redistributions in binary form must reproduce the above copyright 1174465Srwatson * notice, this list of conditions and the following disclaimer in the 1274465Srwatson * documentation and/or other materials provided with the distribution. 1374465Srwatson * 1474465Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1574465Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1674465Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1774465Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE 1874465Srwatson * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1974465Srwatson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2074465Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2174465Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2274465Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2374465Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2474465Srwatson * POSSIBILITY OF SUCH DAMAGE. 2574465Srwatson * 2674465Srwatson * $FreeBSD: head/bin/setfacl/merge.c 75928 2001-04-24 22:45:41Z jedgar $ 2774465Srwatson */ 2874465Srwatson 2974465Srwatson#include <sys/types.h> 3074465Srwatson#include <sys/acl.h> 3174465Srwatson#include <sys/stat.h> 3274465Srwatson 3374465Srwatson#include <err.h> 3474465Srwatson#include <stdio.h> 3574465Srwatson#include <sysexits.h> 3674465Srwatson 3774465Srwatson#include "setfacl.h" 3874465Srwatson 3974465Srwatson/* merge acl into existing file's ACL */ 4074465Srwatsonint 4174465Srwatsonmerge_acl(acl_t acl, acl_t *prev_acl) 4274465Srwatson{ 4375928Sjedgar acl_entry_t entry, entry_new; 4475928Sjedgar acl_permset_t permset; 4574465Srwatson acl_t acl_new; 4675928Sjedgar acl_tag_t tag, tag_new; 4775928Sjedgar int entry_id, entry_id_new, have_entry; 4875928Sjedgar uid_t *id, *id_new; 4974465Srwatson 5074465Srwatson if (acl_type == ACL_TYPE_ACCESS) 5174465Srwatson acl_new = acl_dup(prev_acl[0]); 5274465Srwatson else 5374465Srwatson acl_new = acl_dup(prev_acl[1]); 5474465Srwatson if (!acl_new) 5574465Srwatson err(EX_OSERR, "acl_dup() failed"); 5674465Srwatson 5775928Sjedgar entry_id = ACL_FIRST_ENTRY; 5875928Sjedgar 5975928Sjedgar while (acl_get_entry(acl, entry_id, &entry) == 1) { 6075928Sjedgar entry_id = ACL_NEXT_ENTRY; 6174465Srwatson have_entry = 0; 6274465Srwatson 6375928Sjedgar /* keep track of existing ACL_MASK entries */ 6475928Sjedgar if (acl_get_tag_type(entry, &tag) == -1) 6575928Sjedgar err(EX_OSERR, 6675928Sjedgar "acl_get_tag_type() failed - invalid ACL entry"); 6775928Sjedgar if (tag == ACL_MASK) 6874465Srwatson have_mask = 1; 6974465Srwatson 7074465Srwatson /* check against the existing ACL entries */ 7175928Sjedgar entry_id_new = ACL_FIRST_ENTRY; 7275928Sjedgar while (!have_entry && 7375928Sjedgar acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) { 7475928Sjedgar entry_id_new = ACL_NEXT_ENTRY; 7575928Sjedgar 7675928Sjedgar if (acl_get_tag_type(entry, &tag) == -1) 7775928Sjedgar err(EX_OSERR, "acl_get_tag_type() failed"); 7875928Sjedgar if (acl_get_tag_type(entry_new, &tag_new) == -1) 7975928Sjedgar err(EX_OSERR, "acl_get_tag_type() failed"); 8075928Sjedgar if (tag != tag_new) 8175928Sjedgar continue; 8275928Sjedgar 8375928Sjedgar switch(tag) { 8475928Sjedgar case ACL_USER: 8575928Sjedgar case ACL_GROUP: 8675928Sjedgar id = acl_get_qualifier(entry); 8775928Sjedgar if (id == NULL) 8875928Sjedgar err(EX_OSERR, 8975928Sjedgar "acl_get_qualifier() failed"); 9075928Sjedgar id_new = acl_get_qualifier(entry_new); 9175928Sjedgar if (id_new == NULL) 9275928Sjedgar err(EX_OSERR, 9375928Sjedgar "acl_get_qualifier() failed"); 9475928Sjedgar if (*id == *id_new) { 9575928Sjedgar /* any other matches */ 9675928Sjedgar if (acl_get_permset(entry, &permset) 9775928Sjedgar == -1) 9875928Sjedgar err(EX_OSERR, 9975928Sjedgar "acl_get_permset() failed"); 10075928Sjedgar if (acl_set_permset(entry_new, permset) 10175928Sjedgar == -1) 10275928Sjedgar err(EX_OSERR, 10375928Sjedgar "acl_set_permset() failed"); 10474465Srwatson have_entry = 1; 10575928Sjedgar } 10675928Sjedgar acl_free(id); 10775928Sjedgar acl_free(id_new); 10875928Sjedgar if (!have_entry) 10974465Srwatson break; 11075928Sjedgar /* FALLTHROUGH */ 11175928Sjedgar case ACL_USER_OBJ: 11275928Sjedgar case ACL_GROUP_OBJ: 11375928Sjedgar case ACL_OTHER: 11475928Sjedgar case ACL_MASK: 11575928Sjedgar if (acl_get_permset(entry, &permset) == -1) 11675928Sjedgar err(EX_OSERR, 11775928Sjedgar "acl_get_permset() failed"); 11875928Sjedgar if (acl_set_permset(entry_new, permset) == -1) 11975928Sjedgar err(EX_OSERR, 12075928Sjedgar "acl_set_permset() failed"); 12175928Sjedgar have_entry = 1; 12275928Sjedgar break; 12375928Sjedgar default: 12475928Sjedgar /* should never be here */ 12575928Sjedgar errx(EX_OSERR, "Invalid tag type: %i", tag); 12675928Sjedgar break; 12774465Srwatson } 12874465Srwatson } 12974465Srwatson 13074465Srwatson /* if this entry has not been found, it must be new */ 13174465Srwatson if (!have_entry) { 13275928Sjedgar if (acl_create_entry(&acl_new, &entry_new) == -1) { 13374465Srwatson acl_free(acl_new); 13474465Srwatson return -1; 13574465Srwatson } 13675928Sjedgar if (acl_copy_entry(entry_new, entry) == -1) 13775928Sjedgar err(EX_OSERR, "acl_copy_entry() failed"); 13874465Srwatson } 13974465Srwatson } 14074465Srwatson 14174465Srwatson 14275928Sjedgar if (acl_type == ACL_TYPE_ACCESS) { 14375928Sjedgar acl_free(prev_acl[0]); 14475928Sjedgar prev_acl[0] = acl_new; 14575928Sjedgar } else { 14675928Sjedgar acl_free(prev_acl[1]); 14775928Sjedgar prev_acl[1] = acl_new; 14875928Sjedgar } 14975928Sjedgar 15075928Sjedgar 15174465Srwatson return 0; 15274465Srwatson} 153