1 1.1 christos /* $NetBSD: remove.c,v 1.1 2020/05/16 18:31:45 christos Exp $ */ 2 1.1 christos 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 2001 Chris D. Faulhaber 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that the following conditions 9 1.1 christos * are met: 10 1.1 christos * 1. Redistributions of source code must retain the above copyright 11 1.1 christos * notice, this list of conditions and the following disclaimer. 12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 christos * notice, this list of conditions and the following disclaimer in the 14 1.1 christos * documentation and/or other materials provided with the distribution. 15 1.1 christos * 16 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 christos * SUCH DAMAGE. 27 1.1 christos */ 28 1.1 christos 29 1.1 christos #include <sys/cdefs.h> 30 1.1 christos #if 0 31 1.1 christos __FBSDID("$FreeBSD: head/bin/setfacl/remove.c 333065 2018-04-27 15:25:24Z emaste $"); 32 1.1 christos #else 33 1.1 christos __RCSID("$NetBSD: remove.c,v 1.1 2020/05/16 18:31:45 christos Exp $"); 34 1.1 christos #endif 35 1.1 christos 36 1.1 christos #include <sys/types.h> 37 1.1 christos #include <sys/acl.h> 38 1.1 christos #include <sys/stat.h> 39 1.1 christos 40 1.1 christos #include <err.h> 41 1.1 christos #include <stdio.h> 42 1.1 christos #include <string.h> 43 1.1 christos 44 1.1 christos #include "setfacl.h" 45 1.1 christos 46 1.1 christos /* 47 1.1 christos * remove ACL entries from an ACL 48 1.1 christos */ 49 1.1 christos int 50 1.1 christos remove_acl(acl_t acl, acl_t *prev_acl, const char *filename) 51 1.1 christos { 52 1.1 christos acl_entry_t entry; 53 1.1 christos acl_t acl_new; 54 1.1 christos acl_tag_t tag; 55 1.1 christos int carried_error, entry_id, acl_brand, prev_acl_brand; 56 1.1 christos 57 1.1 christos carried_error = 0; 58 1.1 christos 59 1.1 christos acl_get_brand_np(acl, &acl_brand); 60 1.1 christos acl_get_brand_np(*prev_acl, &prev_acl_brand); 61 1.1 christos 62 1.1 christos if (branding_mismatch(acl_brand, prev_acl_brand)) { 63 1.1 christos warnx("%s: branding mismatch; existing ACL is %s, " 64 1.1 christos "entry to be removed is %s", filename, 65 1.1 christos brand_name(prev_acl_brand), brand_name(acl_brand)); 66 1.1 christos return (-1); 67 1.1 christos } 68 1.1 christos 69 1.1 christos carried_error = 0; 70 1.1 christos 71 1.1 christos acl_new = acl_dup(*prev_acl); 72 1.1 christos if (acl_new == NULL) 73 1.1 christos err(1, "%s: acl_dup() failed", filename); 74 1.1 christos 75 1.1 christos tag = ACL_UNDEFINED_TAG; 76 1.1 christos 77 1.1 christos /* find and delete the entry */ 78 1.1 christos entry_id = ACL_FIRST_ENTRY; 79 1.1 christos while (acl_get_entry(acl, entry_id, &entry) == 1) { 80 1.1 christos entry_id = ACL_NEXT_ENTRY; 81 1.1 christos if (acl_get_tag_type(entry, &tag) == -1) 82 1.1 christos err(1, "%s: acl_get_tag_type() failed", filename); 83 1.1 christos if (tag == ACL_MASK) 84 1.1 christos have_mask = true; 85 1.1 christos if (acl_delete_entry(acl_new, entry) == -1) { 86 1.1 christos carried_error++; 87 1.1 christos warnx("%s: cannot remove non-existent ACL entry", 88 1.1 christos filename); 89 1.1 christos } 90 1.1 christos } 91 1.1 christos 92 1.1 christos acl_free(*prev_acl); 93 1.1 christos *prev_acl = acl_new; 94 1.1 christos 95 1.1 christos if (carried_error) 96 1.1 christos return (-1); 97 1.1 christos 98 1.1 christos return (0); 99 1.1 christos } 100 1.1 christos 101 1.1 christos int 102 1.1 christos remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename) 103 1.1 christos { 104 1.1 christos acl_entry_t entry; 105 1.1 christos acl_t acl_new; 106 1.1 christos acl_tag_t tag; 107 1.1 christos int carried_error, entry_id; 108 1.1 christos uint i; 109 1.1 christos 110 1.1 christos carried_error = 0; 111 1.1 christos 112 1.1 christos acl_new = acl_dup(*prev_acl); 113 1.1 christos if (acl_new == NULL) 114 1.1 christos err(1, "%s: acl_dup() failed", filename); 115 1.1 christos 116 1.1 christos tag = ACL_UNDEFINED_TAG; 117 1.1 christos 118 1.1 christos /* 119 1.1 christos * Find out whether we're removing the mask entry, 120 1.1 christos * to behave the same as the routine above. 121 1.1 christos * 122 1.1 christos * XXX: Is this loop actually needed? 123 1.1 christos */ 124 1.1 christos entry_id = ACL_FIRST_ENTRY; 125 1.1 christos i = 0; 126 1.1 christos while (acl_get_entry(acl_new, entry_id, &entry) == 1) { 127 1.1 christos entry_id = ACL_NEXT_ENTRY; 128 1.1 christos if (i != entry_number) 129 1.1 christos continue; 130 1.1 christos if (acl_get_tag_type(entry, &tag) == -1) 131 1.1 christos err(1, "%s: acl_get_tag_type() failed", filename); 132 1.1 christos if (tag == ACL_MASK) 133 1.1 christos have_mask = true; 134 1.1 christos } 135 1.1 christos 136 1.1 christos if (acl_delete_entry_np(acl_new, entry_number) == -1) { 137 1.1 christos carried_error++; 138 1.1 christos warn("%s: acl_delete_entry_np() failed", filename); 139 1.1 christos } 140 1.1 christos 141 1.1 christos acl_free(*prev_acl); 142 1.1 christos *prev_acl = acl_new; 143 1.1 christos 144 1.1 christos if (carried_error) 145 1.1 christos return (-1); 146 1.1 christos 147 1.1 christos return (0); 148 1.1 christos } 149 1.1 christos 150 1.1 christos /* 151 1.1 christos * remove default entries 152 1.1 christos */ 153 1.1 christos int 154 1.1 christos remove_default(acl_t *prev_acl, const char *filename) 155 1.1 christos { 156 1.1 christos 157 1.1 christos acl_free(*prev_acl); 158 1.1 christos *prev_acl = acl_init(ACL_MAX_ENTRIES); 159 1.1 christos if (*prev_acl == NULL) 160 1.1 christos err(1, "%s: acl_init() failed", filename); 161 1.1 christos 162 1.1 christos return (0); 163 1.1 christos } 164 1.1 christos 165 1.1 christos /* 166 1.1 christos * remove extended entries 167 1.1 christos */ 168 1.1 christos void 169 1.1 christos remove_ext(acl_t *prev_acl, const char *filename) 170 1.1 christos { 171 1.1 christos acl_t acl_new; 172 1.1 christos 173 1.1 christos acl_new = acl_strip_np(*prev_acl, !n_flag); 174 1.1 christos if (acl_new == NULL) 175 1.1 christos err(1, "%s: acl_strip_np() failed", filename); 176 1.1 christos 177 1.1 christos acl_free(*prev_acl); 178 1.1 christos *prev_acl = acl_new; 179 1.1 christos } 180