1aa015c8eSEdward Tomasz Napierala /*- 2aa015c8eSEdward Tomasz Napierala * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org> 3aa015c8eSEdward Tomasz Napierala * All rights reserved. 4aa015c8eSEdward Tomasz Napierala * 5aa015c8eSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 6aa015c8eSEdward Tomasz Napierala * modification, are permitted provided that the following conditions 7aa015c8eSEdward Tomasz Napierala * are met: 8aa015c8eSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 9aa015c8eSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 10aa015c8eSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 11aa015c8eSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 12aa015c8eSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 13aa015c8eSEdward Tomasz Napierala * 14aa015c8eSEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15aa015c8eSEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16aa015c8eSEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17aa015c8eSEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18aa015c8eSEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19aa015c8eSEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20aa015c8eSEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21aa015c8eSEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22aa015c8eSEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23aa015c8eSEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24aa015c8eSEdward Tomasz Napierala * SUCH DAMAGE. 25aa015c8eSEdward Tomasz Napierala */ 26aa015c8eSEdward Tomasz Napierala 27aa015c8eSEdward Tomasz Napierala #include <sys/cdefs.h> 28aa015c8eSEdward Tomasz Napierala __FBSDID("$FreeBSD$"); 29aa015c8eSEdward Tomasz Napierala 30aa015c8eSEdward Tomasz Napierala #include <stdio.h> 31aa015c8eSEdward Tomasz Napierala #include <stdlib.h> 32aa015c8eSEdward Tomasz Napierala #include <string.h> 33aa015c8eSEdward Tomasz Napierala #include <assert.h> 34aa015c8eSEdward Tomasz Napierala #include <err.h> 35aa015c8eSEdward Tomasz Napierala #include <sys/acl.h> 36aa015c8eSEdward Tomasz Napierala #include "acl_support.h" 37aa015c8eSEdward Tomasz Napierala 38aa015c8eSEdward Tomasz Napierala struct flagnames_struct { 39aa015c8eSEdward Tomasz Napierala uint32_t flag; 40aa015c8eSEdward Tomasz Napierala const char *name; 41aa015c8eSEdward Tomasz Napierala char letter; 42aa015c8eSEdward Tomasz Napierala }; 43aa015c8eSEdward Tomasz Napierala 44aa015c8eSEdward Tomasz Napierala struct flagnames_struct a_flags[] = 45aa015c8eSEdward Tomasz Napierala {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'}, 46aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'}, 47aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'}, 48aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'}, 49aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'}, 50aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'}, 51aa015c8eSEdward Tomasz Napierala /* 52aa015c8eSEdward Tomasz Napierala * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it 53aa015c8eSEdward Tomasz Napierala * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or 54aa015c8eSEdward Tomasz Napierala * ACE_EVERYONE either, for obvious reasons. 55aa015c8eSEdward Tomasz Napierala */ 56aa015c8eSEdward Tomasz Napierala { 0, 0, 0}}; 57aa015c8eSEdward Tomasz Napierala 58aa015c8eSEdward Tomasz Napierala struct flagnames_struct a_access_masks[] = 59aa015c8eSEdward Tomasz Napierala {{ ACL_READ_DATA, "read_data", 'r'}, 60aa015c8eSEdward Tomasz Napierala { ACL_WRITE_DATA, "write_data", 'w'}, 61aa015c8eSEdward Tomasz Napierala { ACL_EXECUTE, "execute", 'x'}, 62aa015c8eSEdward Tomasz Napierala { ACL_APPEND_DATA, "append_data", 'p'}, 63aa015c8eSEdward Tomasz Napierala { ACL_DELETE_CHILD, "delete_child", 'D'}, 64aa015c8eSEdward Tomasz Napierala { ACL_DELETE, "delete", 'd'}, 65aa015c8eSEdward Tomasz Napierala { ACL_READ_ATTRIBUTES, "read_attributes", 'a'}, 66aa015c8eSEdward Tomasz Napierala { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'}, 67aa015c8eSEdward Tomasz Napierala { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'}, 68aa015c8eSEdward Tomasz Napierala { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'}, 69aa015c8eSEdward Tomasz Napierala { ACL_READ_ACL, "read_acl", 'c'}, 70aa015c8eSEdward Tomasz Napierala { ACL_WRITE_ACL, "write_acl", 'C'}, 71aa015c8eSEdward Tomasz Napierala { ACL_WRITE_OWNER, "write_owner", 'o'}, 72aa015c8eSEdward Tomasz Napierala { ACL_SYNCHRONIZE, "synchronize", 's'}, 73aa015c8eSEdward Tomasz Napierala { 0, 0, 0}}; 74aa015c8eSEdward Tomasz Napierala 75aa015c8eSEdward Tomasz Napierala static const char * 76aa015c8eSEdward Tomasz Napierala format_flag(uint32_t *var, const struct flagnames_struct *flags) 77aa015c8eSEdward Tomasz Napierala { 78aa015c8eSEdward Tomasz Napierala 79aa015c8eSEdward Tomasz Napierala for (; flags->name != 0; flags++) { 80aa015c8eSEdward Tomasz Napierala if ((flags->flag & *var) == 0) 81aa015c8eSEdward Tomasz Napierala continue; 82aa015c8eSEdward Tomasz Napierala 83aa015c8eSEdward Tomasz Napierala *var &= ~flags->flag; 84aa015c8eSEdward Tomasz Napierala return (flags->name); 85aa015c8eSEdward Tomasz Napierala } 86aa015c8eSEdward Tomasz Napierala 87aa015c8eSEdward Tomasz Napierala return (NULL); 88aa015c8eSEdward Tomasz Napierala } 89aa015c8eSEdward Tomasz Napierala 90aa015c8eSEdward Tomasz Napierala static int 91aa015c8eSEdward Tomasz Napierala format_flags_verbose(char *str, size_t size, uint32_t var, 92aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags) 93aa015c8eSEdward Tomasz Napierala { 94aa015c8eSEdward Tomasz Napierala size_t off = 0; 95aa015c8eSEdward Tomasz Napierala const char *tmp; 96aa015c8eSEdward Tomasz Napierala 97aa015c8eSEdward Tomasz Napierala while ((tmp = format_flag(&var, flags)) != NULL) { 98aa015c8eSEdward Tomasz Napierala off += snprintf(str + off, size - off, "%s/", tmp); 99aa015c8eSEdward Tomasz Napierala assert (off < size); 100aa015c8eSEdward Tomasz Napierala } 101aa015c8eSEdward Tomasz Napierala 102aa015c8eSEdward Tomasz Napierala /* If there were any flags added... */ 103aa015c8eSEdward Tomasz Napierala if (off > 0) { 104aa015c8eSEdward Tomasz Napierala off--; 105aa015c8eSEdward Tomasz Napierala /* ... then remove the last slash. */ 106aa015c8eSEdward Tomasz Napierala assert(str[off] == '/'); 107aa015c8eSEdward Tomasz Napierala } 108aa015c8eSEdward Tomasz Napierala 109aa015c8eSEdward Tomasz Napierala str[off] = '\0'; 110aa015c8eSEdward Tomasz Napierala 111aa015c8eSEdward Tomasz Napierala return (0); 112aa015c8eSEdward Tomasz Napierala } 113aa015c8eSEdward Tomasz Napierala 114aa015c8eSEdward Tomasz Napierala static int 115aa015c8eSEdward Tomasz Napierala format_flags_compact(char *str, size_t size, uint32_t var, 116aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags) 117aa015c8eSEdward Tomasz Napierala { 118aa015c8eSEdward Tomasz Napierala size_t i; 119aa015c8eSEdward Tomasz Napierala 120aa015c8eSEdward Tomasz Napierala for (i = 0; flags[i].name != NULL; i++) { 121aa015c8eSEdward Tomasz Napierala assert(i < size); 122aa015c8eSEdward Tomasz Napierala if ((flags[i].flag & var) == 0) 123aa015c8eSEdward Tomasz Napierala str[i] = '-'; 124aa015c8eSEdward Tomasz Napierala else 125aa015c8eSEdward Tomasz Napierala str[i] = flags[i].letter; 126aa015c8eSEdward Tomasz Napierala } 127aa015c8eSEdward Tomasz Napierala 128aa015c8eSEdward Tomasz Napierala str[i] = '\0'; 129aa015c8eSEdward Tomasz Napierala 130aa015c8eSEdward Tomasz Napierala return (0); 131aa015c8eSEdward Tomasz Napierala } 132aa015c8eSEdward Tomasz Napierala 133aa015c8eSEdward Tomasz Napierala static int 134aa015c8eSEdward Tomasz Napierala parse_flags_verbose(const char *strp, uint32_t *var, 135aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags, const char *flags_name, 136aa015c8eSEdward Tomasz Napierala int *try_compact) 137aa015c8eSEdward Tomasz Napierala { 138aa015c8eSEdward Tomasz Napierala int i, found, ever_found = 0; 139aa015c8eSEdward Tomasz Napierala char *str, *flag; 140aa015c8eSEdward Tomasz Napierala 141aa015c8eSEdward Tomasz Napierala str = strdup(strp); 142aa015c8eSEdward Tomasz Napierala *try_compact = 0; 143aa015c8eSEdward Tomasz Napierala *var = 0; 144aa015c8eSEdward Tomasz Napierala 145aa015c8eSEdward Tomasz Napierala while (str != NULL) { 146aa015c8eSEdward Tomasz Napierala flag = strsep(&str, "/:"); 147aa015c8eSEdward Tomasz Napierala 148aa015c8eSEdward Tomasz Napierala found = 0; 149aa015c8eSEdward Tomasz Napierala for (i = 0; flags[i].name != NULL; i++) { 150aa015c8eSEdward Tomasz Napierala if (strcmp(flags[i].name, flag) == 0) { 151aa015c8eSEdward Tomasz Napierala *var |= flags[i].flag; 152aa015c8eSEdward Tomasz Napierala found = 1; 153aa015c8eSEdward Tomasz Napierala ever_found = 1; 154aa015c8eSEdward Tomasz Napierala } 155aa015c8eSEdward Tomasz Napierala } 156aa015c8eSEdward Tomasz Napierala 157aa015c8eSEdward Tomasz Napierala if (!found) { 158aa015c8eSEdward Tomasz Napierala if (ever_found) 159aa015c8eSEdward Tomasz Napierala warnx("malformed ACL: \"%s\" field contains " 160aa015c8eSEdward Tomasz Napierala "invalid flag \"%s\"", flags_name, flag); 161aa015c8eSEdward Tomasz Napierala else 162aa015c8eSEdward Tomasz Napierala *try_compact = 1; 163aa015c8eSEdward Tomasz Napierala free(str); 164aa015c8eSEdward Tomasz Napierala return (-1); 165aa015c8eSEdward Tomasz Napierala } 166aa015c8eSEdward Tomasz Napierala } 167aa015c8eSEdward Tomasz Napierala 168aa015c8eSEdward Tomasz Napierala free(str); 169aa015c8eSEdward Tomasz Napierala return (0); 170aa015c8eSEdward Tomasz Napierala } 171aa015c8eSEdward Tomasz Napierala 172aa015c8eSEdward Tomasz Napierala static int 173aa015c8eSEdward Tomasz Napierala parse_flags_compact(const char *str, uint32_t *var, 174aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags, const char *flags_name) 175aa015c8eSEdward Tomasz Napierala { 176aa015c8eSEdward Tomasz Napierala int i, j, found; 177aa015c8eSEdward Tomasz Napierala 178aa015c8eSEdward Tomasz Napierala *var = 0; 179aa015c8eSEdward Tomasz Napierala 180aa015c8eSEdward Tomasz Napierala for (i = 0;; i++) { 181aa015c8eSEdward Tomasz Napierala if (str[i] == '\0') 182aa015c8eSEdward Tomasz Napierala return (0); 183aa015c8eSEdward Tomasz Napierala 184aa015c8eSEdward Tomasz Napierala /* Ignore minus signs. */ 185aa015c8eSEdward Tomasz Napierala if (str[i] == '-') 186aa015c8eSEdward Tomasz Napierala continue; 187aa015c8eSEdward Tomasz Napierala 188aa015c8eSEdward Tomasz Napierala found = 0; 189aa015c8eSEdward Tomasz Napierala 190aa015c8eSEdward Tomasz Napierala for (j = 0; flags[j].name != NULL; j++) { 191aa015c8eSEdward Tomasz Napierala if (flags[j].letter == str[i]) { 192aa015c8eSEdward Tomasz Napierala *var |= flags[j].flag; 193aa015c8eSEdward Tomasz Napierala found = 1; 194aa015c8eSEdward Tomasz Napierala break; 195aa015c8eSEdward Tomasz Napierala } 196aa015c8eSEdward Tomasz Napierala } 197aa015c8eSEdward Tomasz Napierala 198aa015c8eSEdward Tomasz Napierala if (!found) { 199aa015c8eSEdward Tomasz Napierala warnx("malformed ACL: \"%s\" field contains " 200aa015c8eSEdward Tomasz Napierala "invalid flag \"%c\"", flags_name, str[i]); 201aa015c8eSEdward Tomasz Napierala return (-1); 202aa015c8eSEdward Tomasz Napierala } 203aa015c8eSEdward Tomasz Napierala } 204aa015c8eSEdward Tomasz Napierala } 205aa015c8eSEdward Tomasz Napierala 206aa015c8eSEdward Tomasz Napierala int 207aa015c8eSEdward Tomasz Napierala _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose) 208aa015c8eSEdward Tomasz Napierala { 209aa015c8eSEdward Tomasz Napierala 210aa015c8eSEdward Tomasz Napierala if (verbose) 211aa015c8eSEdward Tomasz Napierala return (format_flags_verbose(str, size, var, a_flags)); 212aa015c8eSEdward Tomasz Napierala 213aa015c8eSEdward Tomasz Napierala return (format_flags_compact(str, size, var, a_flags)); 214aa015c8eSEdward Tomasz Napierala } 215aa015c8eSEdward Tomasz Napierala 216aa015c8eSEdward Tomasz Napierala int 217aa015c8eSEdward Tomasz Napierala _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose) 218aa015c8eSEdward Tomasz Napierala { 219aa015c8eSEdward Tomasz Napierala 220aa015c8eSEdward Tomasz Napierala if (verbose) 221aa015c8eSEdward Tomasz Napierala return (format_flags_verbose(str, size, var, a_access_masks)); 222aa015c8eSEdward Tomasz Napierala 223aa015c8eSEdward Tomasz Napierala return (format_flags_compact(str, size, var, a_access_masks)); 224aa015c8eSEdward Tomasz Napierala } 225aa015c8eSEdward Tomasz Napierala 226aa015c8eSEdward Tomasz Napierala int 227aa015c8eSEdward Tomasz Napierala _nfs4_parse_flags(const char *str, acl_flag_t *flags) 228aa015c8eSEdward Tomasz Napierala { 229aa015c8eSEdward Tomasz Napierala int error, try_compact; 230aa015c8eSEdward Tomasz Napierala int tmpflags; 231aa015c8eSEdward Tomasz Napierala 232aa015c8eSEdward Tomasz Napierala error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact); 233aa015c8eSEdward Tomasz Napierala if (error && try_compact) 234aa015c8eSEdward Tomasz Napierala error = parse_flags_compact(str, &tmpflags, a_flags, "flags"); 235aa015c8eSEdward Tomasz Napierala 236aa015c8eSEdward Tomasz Napierala *flags = tmpflags; 237aa015c8eSEdward Tomasz Napierala 238aa015c8eSEdward Tomasz Napierala return (error); 239aa015c8eSEdward Tomasz Napierala } 240aa015c8eSEdward Tomasz Napierala 241aa015c8eSEdward Tomasz Napierala int 242aa015c8eSEdward Tomasz Napierala _nfs4_parse_access_mask(const char *str, acl_perm_t *perms) 243aa015c8eSEdward Tomasz Napierala { 244aa015c8eSEdward Tomasz Napierala int error, try_compact; 245aa015c8eSEdward Tomasz Napierala int tmpperms; 246aa015c8eSEdward Tomasz Napierala 247aa015c8eSEdward Tomasz Napierala error = parse_flags_verbose(str, &tmpperms, a_access_masks, 248aa015c8eSEdward Tomasz Napierala "access permissions", &try_compact); 249aa015c8eSEdward Tomasz Napierala if (error && try_compact) 250aa015c8eSEdward Tomasz Napierala error = parse_flags_compact(str, &tmpperms, 251aa015c8eSEdward Tomasz Napierala a_access_masks, "access permissions"); 252aa015c8eSEdward Tomasz Napierala 253aa015c8eSEdward Tomasz Napierala *perms = tmpperms; 254aa015c8eSEdward Tomasz Napierala 255aa015c8eSEdward Tomasz Napierala return (error); 256aa015c8eSEdward Tomasz Napierala } 257aa015c8eSEdward Tomasz Napierala /*- 258aa015c8eSEdward Tomasz Napierala * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org> 259aa015c8eSEdward Tomasz Napierala * All rights reserved. 260aa015c8eSEdward Tomasz Napierala * 261aa015c8eSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 262aa015c8eSEdward Tomasz Napierala * modification, are permitted provided that the following conditions 263aa015c8eSEdward Tomasz Napierala * are met: 264aa015c8eSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 265aa015c8eSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 266aa015c8eSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 267aa015c8eSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 268aa015c8eSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 269aa015c8eSEdward Tomasz Napierala * 270aa015c8eSEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 271aa015c8eSEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 272aa015c8eSEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 273aa015c8eSEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 274aa015c8eSEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 275aa015c8eSEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 276aa015c8eSEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 277aa015c8eSEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 278aa015c8eSEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 279aa015c8eSEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 280aa015c8eSEdward Tomasz Napierala * SUCH DAMAGE. 281aa015c8eSEdward Tomasz Napierala */ 282aa015c8eSEdward Tomasz Napierala 283aa015c8eSEdward Tomasz Napierala #include <sys/cdefs.h> 284aa015c8eSEdward Tomasz Napierala __FBSDID("$FreeBSD$"); 285aa015c8eSEdward Tomasz Napierala 286aa015c8eSEdward Tomasz Napierala #include <stdio.h> 287aa015c8eSEdward Tomasz Napierala #include <stdlib.h> 288aa015c8eSEdward Tomasz Napierala #include <string.h> 289aa015c8eSEdward Tomasz Napierala #include <assert.h> 290aa015c8eSEdward Tomasz Napierala #include <err.h> 291aa015c8eSEdward Tomasz Napierala #include <sys/acl.h> 292aa015c8eSEdward Tomasz Napierala #include "acl_support.h" 293aa015c8eSEdward Tomasz Napierala 294aa015c8eSEdward Tomasz Napierala struct flagnames_struct { 295aa015c8eSEdward Tomasz Napierala uint32_t flag; 296aa015c8eSEdward Tomasz Napierala const char *name; 297aa015c8eSEdward Tomasz Napierala char letter; 298aa015c8eSEdward Tomasz Napierala }; 299aa015c8eSEdward Tomasz Napierala 300aa015c8eSEdward Tomasz Napierala struct flagnames_struct a_flags[] = 301aa015c8eSEdward Tomasz Napierala {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'}, 302aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'}, 303aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'}, 304aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'}, 305aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'}, 306aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'}, 307aa015c8eSEdward Tomasz Napierala /* 308aa015c8eSEdward Tomasz Napierala * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it 309aa015c8eSEdward Tomasz Napierala * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or 310aa015c8eSEdward Tomasz Napierala * ACE_EVERYONE either, for obvious reasons. 311aa015c8eSEdward Tomasz Napierala */ 312aa015c8eSEdward Tomasz Napierala { 0, 0, 0}}; 313aa015c8eSEdward Tomasz Napierala 314aa015c8eSEdward Tomasz Napierala struct flagnames_struct a_access_masks[] = 315aa015c8eSEdward Tomasz Napierala {{ ACL_READ_DATA, "read_data", 'r'}, 316aa015c8eSEdward Tomasz Napierala { ACL_WRITE_DATA, "write_data", 'w'}, 317aa015c8eSEdward Tomasz Napierala { ACL_EXECUTE, "execute", 'x'}, 318aa015c8eSEdward Tomasz Napierala { ACL_APPEND_DATA, "append_data", 'p'}, 319aa015c8eSEdward Tomasz Napierala { ACL_DELETE_CHILD, "delete_child", 'D'}, 320aa015c8eSEdward Tomasz Napierala { ACL_DELETE, "delete", 'd'}, 321aa015c8eSEdward Tomasz Napierala { ACL_READ_ATTRIBUTES, "read_attributes", 'a'}, 322aa015c8eSEdward Tomasz Napierala { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'}, 323aa015c8eSEdward Tomasz Napierala { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'}, 324aa015c8eSEdward Tomasz Napierala { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'}, 325aa015c8eSEdward Tomasz Napierala { ACL_READ_ACL, "read_acl", 'c'}, 326aa015c8eSEdward Tomasz Napierala { ACL_WRITE_ACL, "write_acl", 'C'}, 327aa015c8eSEdward Tomasz Napierala { ACL_WRITE_OWNER, "write_owner", 'o'}, 328aa015c8eSEdward Tomasz Napierala { ACL_SYNCHRONIZE, "synchronize", 's'}, 329aa015c8eSEdward Tomasz Napierala { 0, 0, 0}}; 330aa015c8eSEdward Tomasz Napierala 331aa015c8eSEdward Tomasz Napierala static const char * 332aa015c8eSEdward Tomasz Napierala format_flag(uint32_t *var, const struct flagnames_struct *flags) 333aa015c8eSEdward Tomasz Napierala { 334aa015c8eSEdward Tomasz Napierala 335aa015c8eSEdward Tomasz Napierala for (; flags->name != 0; flags++) { 336aa015c8eSEdward Tomasz Napierala if ((flags->flag & *var) == 0) 337aa015c8eSEdward Tomasz Napierala continue; 338aa015c8eSEdward Tomasz Napierala 339aa015c8eSEdward Tomasz Napierala *var &= ~flags->flag; 340aa015c8eSEdward Tomasz Napierala return (flags->name); 341aa015c8eSEdward Tomasz Napierala } 342aa015c8eSEdward Tomasz Napierala 343aa015c8eSEdward Tomasz Napierala return (NULL); 344aa015c8eSEdward Tomasz Napierala } 345aa015c8eSEdward Tomasz Napierala 346aa015c8eSEdward Tomasz Napierala static int 347aa015c8eSEdward Tomasz Napierala format_flags_verbose(char *str, size_t size, uint32_t var, 348aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags) 349aa015c8eSEdward Tomasz Napierala { 350aa015c8eSEdward Tomasz Napierala size_t off = 0; 351aa015c8eSEdward Tomasz Napierala const char *tmp; 352aa015c8eSEdward Tomasz Napierala 353aa015c8eSEdward Tomasz Napierala while ((tmp = format_flag(&var, flags)) != NULL) { 354aa015c8eSEdward Tomasz Napierala off += snprintf(str + off, size - off, "%s/", tmp); 355aa015c8eSEdward Tomasz Napierala assert (off < size); 356aa015c8eSEdward Tomasz Napierala } 357aa015c8eSEdward Tomasz Napierala 358aa015c8eSEdward Tomasz Napierala /* If there were any flags added... */ 359aa015c8eSEdward Tomasz Napierala if (off > 0) { 360aa015c8eSEdward Tomasz Napierala off--; 361aa015c8eSEdward Tomasz Napierala /* ... then remove the last slash. */ 362aa015c8eSEdward Tomasz Napierala assert(str[off] == '/'); 363aa015c8eSEdward Tomasz Napierala } 364aa015c8eSEdward Tomasz Napierala 365aa015c8eSEdward Tomasz Napierala str[off] = '\0'; 366aa015c8eSEdward Tomasz Napierala 367aa015c8eSEdward Tomasz Napierala return (0); 368aa015c8eSEdward Tomasz Napierala } 369aa015c8eSEdward Tomasz Napierala 370aa015c8eSEdward Tomasz Napierala static int 371aa015c8eSEdward Tomasz Napierala format_flags_compact(char *str, size_t size, uint32_t var, 372aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags) 373aa015c8eSEdward Tomasz Napierala { 374aa015c8eSEdward Tomasz Napierala size_t i; 375aa015c8eSEdward Tomasz Napierala 376aa015c8eSEdward Tomasz Napierala for (i = 0; flags[i].name != NULL; i++) { 377aa015c8eSEdward Tomasz Napierala assert(i < size); 378aa015c8eSEdward Tomasz Napierala if ((flags[i].flag & var) == 0) 379aa015c8eSEdward Tomasz Napierala str[i] = '-'; 380aa015c8eSEdward Tomasz Napierala else 381aa015c8eSEdward Tomasz Napierala str[i] = flags[i].letter; 382aa015c8eSEdward Tomasz Napierala } 383aa015c8eSEdward Tomasz Napierala 384aa015c8eSEdward Tomasz Napierala str[i] = '\0'; 385aa015c8eSEdward Tomasz Napierala 386aa015c8eSEdward Tomasz Napierala return (0); 387aa015c8eSEdward Tomasz Napierala } 388aa015c8eSEdward Tomasz Napierala 389aa015c8eSEdward Tomasz Napierala static int 390aa015c8eSEdward Tomasz Napierala parse_flags_verbose(const char *strp, uint32_t *var, 391aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags, const char *flags_name, 392aa015c8eSEdward Tomasz Napierala int *try_compact) 393aa015c8eSEdward Tomasz Napierala { 394aa015c8eSEdward Tomasz Napierala int i, found, ever_found = 0; 395aa015c8eSEdward Tomasz Napierala char *str, *flag; 396aa015c8eSEdward Tomasz Napierala 397aa015c8eSEdward Tomasz Napierala str = strdup(strp); 398aa015c8eSEdward Tomasz Napierala *try_compact = 0; 399aa015c8eSEdward Tomasz Napierala *var = 0; 400aa015c8eSEdward Tomasz Napierala 401aa015c8eSEdward Tomasz Napierala while (str != NULL) { 402aa015c8eSEdward Tomasz Napierala flag = strsep(&str, "/:"); 403aa015c8eSEdward Tomasz Napierala 404aa015c8eSEdward Tomasz Napierala found = 0; 405aa015c8eSEdward Tomasz Napierala for (i = 0; flags[i].name != NULL; i++) { 406aa015c8eSEdward Tomasz Napierala if (strcmp(flags[i].name, flag) == 0) { 407aa015c8eSEdward Tomasz Napierala *var |= flags[i].flag; 408aa015c8eSEdward Tomasz Napierala found = 1; 409aa015c8eSEdward Tomasz Napierala ever_found = 1; 410aa015c8eSEdward Tomasz Napierala } 411aa015c8eSEdward Tomasz Napierala } 412aa015c8eSEdward Tomasz Napierala 413aa015c8eSEdward Tomasz Napierala if (!found) { 414aa015c8eSEdward Tomasz Napierala if (ever_found) 415aa015c8eSEdward Tomasz Napierala warnx("malformed ACL: \"%s\" field contains " 416aa015c8eSEdward Tomasz Napierala "invalid flag \"%s\"", flags_name, flag); 417aa015c8eSEdward Tomasz Napierala else 418aa015c8eSEdward Tomasz Napierala *try_compact = 1; 419aa015c8eSEdward Tomasz Napierala free(str); 420aa015c8eSEdward Tomasz Napierala return (-1); 421aa015c8eSEdward Tomasz Napierala } 422aa015c8eSEdward Tomasz Napierala } 423aa015c8eSEdward Tomasz Napierala 424aa015c8eSEdward Tomasz Napierala free(str); 425aa015c8eSEdward Tomasz Napierala return (0); 426aa015c8eSEdward Tomasz Napierala } 427aa015c8eSEdward Tomasz Napierala 428aa015c8eSEdward Tomasz Napierala static int 429aa015c8eSEdward Tomasz Napierala parse_flags_compact(const char *str, uint32_t *var, 430aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags, const char *flags_name) 431aa015c8eSEdward Tomasz Napierala { 432aa015c8eSEdward Tomasz Napierala int i, j, found; 433aa015c8eSEdward Tomasz Napierala 434aa015c8eSEdward Tomasz Napierala *var = 0; 435aa015c8eSEdward Tomasz Napierala 436aa015c8eSEdward Tomasz Napierala for (i = 0;; i++) { 437aa015c8eSEdward Tomasz Napierala if (str[i] == '\0') 438aa015c8eSEdward Tomasz Napierala return (0); 439aa015c8eSEdward Tomasz Napierala 440aa015c8eSEdward Tomasz Napierala /* Ignore minus signs. */ 441aa015c8eSEdward Tomasz Napierala if (str[i] == '-') 442aa015c8eSEdward Tomasz Napierala continue; 443aa015c8eSEdward Tomasz Napierala 444aa015c8eSEdward Tomasz Napierala found = 0; 445aa015c8eSEdward Tomasz Napierala 446aa015c8eSEdward Tomasz Napierala for (j = 0; flags[j].name != NULL; j++) { 447aa015c8eSEdward Tomasz Napierala if (flags[j].letter == str[i]) { 448aa015c8eSEdward Tomasz Napierala *var |= flags[j].flag; 449aa015c8eSEdward Tomasz Napierala found = 1; 450aa015c8eSEdward Tomasz Napierala break; 451aa015c8eSEdward Tomasz Napierala } 452aa015c8eSEdward Tomasz Napierala } 453aa015c8eSEdward Tomasz Napierala 454aa015c8eSEdward Tomasz Napierala if (!found) { 455aa015c8eSEdward Tomasz Napierala warnx("malformed ACL: \"%s\" field contains " 456aa015c8eSEdward Tomasz Napierala "invalid flag \"%c\"", flags_name, str[i]); 457aa015c8eSEdward Tomasz Napierala return (-1); 458aa015c8eSEdward Tomasz Napierala } 459aa015c8eSEdward Tomasz Napierala } 460aa015c8eSEdward Tomasz Napierala } 461aa015c8eSEdward Tomasz Napierala 462aa015c8eSEdward Tomasz Napierala int 463aa015c8eSEdward Tomasz Napierala _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose) 464aa015c8eSEdward Tomasz Napierala { 465aa015c8eSEdward Tomasz Napierala 466aa015c8eSEdward Tomasz Napierala if (verbose) 467aa015c8eSEdward Tomasz Napierala return (format_flags_verbose(str, size, var, a_flags)); 468aa015c8eSEdward Tomasz Napierala 469aa015c8eSEdward Tomasz Napierala return (format_flags_compact(str, size, var, a_flags)); 470aa015c8eSEdward Tomasz Napierala } 471aa015c8eSEdward Tomasz Napierala 472aa015c8eSEdward Tomasz Napierala int 473aa015c8eSEdward Tomasz Napierala _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose) 474aa015c8eSEdward Tomasz Napierala { 475aa015c8eSEdward Tomasz Napierala 476aa015c8eSEdward Tomasz Napierala if (verbose) 477aa015c8eSEdward Tomasz Napierala return (format_flags_verbose(str, size, var, a_access_masks)); 478aa015c8eSEdward Tomasz Napierala 479aa015c8eSEdward Tomasz Napierala return (format_flags_compact(str, size, var, a_access_masks)); 480aa015c8eSEdward Tomasz Napierala } 481aa015c8eSEdward Tomasz Napierala 482aa015c8eSEdward Tomasz Napierala int 483aa015c8eSEdward Tomasz Napierala _nfs4_parse_flags(const char *str, acl_flag_t *flags) 484aa015c8eSEdward Tomasz Napierala { 485aa015c8eSEdward Tomasz Napierala int error, try_compact; 486aa015c8eSEdward Tomasz Napierala int tmpflags; 487aa015c8eSEdward Tomasz Napierala 488aa015c8eSEdward Tomasz Napierala error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact); 489aa015c8eSEdward Tomasz Napierala if (error && try_compact) 490aa015c8eSEdward Tomasz Napierala error = parse_flags_compact(str, &tmpflags, a_flags, "flags"); 491aa015c8eSEdward Tomasz Napierala 492aa015c8eSEdward Tomasz Napierala *flags = tmpflags; 493aa015c8eSEdward Tomasz Napierala 494aa015c8eSEdward Tomasz Napierala return (error); 495aa015c8eSEdward Tomasz Napierala } 496aa015c8eSEdward Tomasz Napierala 497aa015c8eSEdward Tomasz Napierala int 498aa015c8eSEdward Tomasz Napierala _nfs4_parse_access_mask(const char *str, acl_perm_t *perms) 499aa015c8eSEdward Tomasz Napierala { 500aa015c8eSEdward Tomasz Napierala int error, try_compact; 501aa015c8eSEdward Tomasz Napierala int tmpperms; 502aa015c8eSEdward Tomasz Napierala 503aa015c8eSEdward Tomasz Napierala error = parse_flags_verbose(str, &tmpperms, a_access_masks, 504aa015c8eSEdward Tomasz Napierala "access permissions", &try_compact); 505aa015c8eSEdward Tomasz Napierala if (error && try_compact) 506aa015c8eSEdward Tomasz Napierala error = parse_flags_compact(str, &tmpperms, 507aa015c8eSEdward Tomasz Napierala a_access_masks, "access permissions"); 508aa015c8eSEdward Tomasz Napierala 509aa015c8eSEdward Tomasz Napierala *perms = tmpperms; 510aa015c8eSEdward Tomasz Napierala 511aa015c8eSEdward Tomasz Napierala return (error); 512aa015c8eSEdward Tomasz Napierala } 513aa015c8eSEdward Tomasz Napierala /*- 514aa015c8eSEdward Tomasz Napierala * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org> 515aa015c8eSEdward Tomasz Napierala * All rights reserved. 516aa015c8eSEdward Tomasz Napierala * 517aa015c8eSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 518aa015c8eSEdward Tomasz Napierala * modification, are permitted provided that the following conditions 519aa015c8eSEdward Tomasz Napierala * are met: 520aa015c8eSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 521aa015c8eSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 522aa015c8eSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 523aa015c8eSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 524aa015c8eSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 525aa015c8eSEdward Tomasz Napierala * 526aa015c8eSEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 527aa015c8eSEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 528aa015c8eSEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 529aa015c8eSEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 530aa015c8eSEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 531aa015c8eSEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 532aa015c8eSEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 533aa015c8eSEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 534aa015c8eSEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 535aa015c8eSEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 536aa015c8eSEdward Tomasz Napierala * SUCH DAMAGE. 537aa015c8eSEdward Tomasz Napierala */ 538aa015c8eSEdward Tomasz Napierala 539aa015c8eSEdward Tomasz Napierala #include <sys/cdefs.h> 540aa015c8eSEdward Tomasz Napierala __FBSDID("$FreeBSD$"); 541aa015c8eSEdward Tomasz Napierala 542aa015c8eSEdward Tomasz Napierala #include <stdio.h> 543aa015c8eSEdward Tomasz Napierala #include <stdlib.h> 544aa015c8eSEdward Tomasz Napierala #include <string.h> 545aa015c8eSEdward Tomasz Napierala #include <assert.h> 546aa015c8eSEdward Tomasz Napierala #include <err.h> 547aa015c8eSEdward Tomasz Napierala #include <sys/acl.h> 548aa015c8eSEdward Tomasz Napierala #include "acl_support.h" 549aa015c8eSEdward Tomasz Napierala 550aa015c8eSEdward Tomasz Napierala struct flagnames_struct { 551aa015c8eSEdward Tomasz Napierala uint32_t flag; 552aa015c8eSEdward Tomasz Napierala const char *name; 553aa015c8eSEdward Tomasz Napierala char letter; 554aa015c8eSEdward Tomasz Napierala }; 555aa015c8eSEdward Tomasz Napierala 556aa015c8eSEdward Tomasz Napierala struct flagnames_struct a_flags[] = 557aa015c8eSEdward Tomasz Napierala {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'}, 558aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'}, 559aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'}, 560aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'}, 561aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'}, 562aa015c8eSEdward Tomasz Napierala { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'}, 563aa015c8eSEdward Tomasz Napierala /* 564aa015c8eSEdward Tomasz Napierala * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it 565aa015c8eSEdward Tomasz Napierala * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or 566aa015c8eSEdward Tomasz Napierala * ACE_EVERYONE either, for obvious reasons. 567aa015c8eSEdward Tomasz Napierala */ 568aa015c8eSEdward Tomasz Napierala { 0, 0, 0}}; 569aa015c8eSEdward Tomasz Napierala 570aa015c8eSEdward Tomasz Napierala struct flagnames_struct a_access_masks[] = 571aa015c8eSEdward Tomasz Napierala {{ ACL_READ_DATA, "read_data", 'r'}, 572aa015c8eSEdward Tomasz Napierala { ACL_WRITE_DATA, "write_data", 'w'}, 573aa015c8eSEdward Tomasz Napierala { ACL_EXECUTE, "execute", 'x'}, 574aa015c8eSEdward Tomasz Napierala { ACL_APPEND_DATA, "append_data", 'p'}, 575aa015c8eSEdward Tomasz Napierala { ACL_DELETE_CHILD, "delete_child", 'D'}, 576aa015c8eSEdward Tomasz Napierala { ACL_DELETE, "delete", 'd'}, 577aa015c8eSEdward Tomasz Napierala { ACL_READ_ATTRIBUTES, "read_attributes", 'a'}, 578aa015c8eSEdward Tomasz Napierala { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'}, 579aa015c8eSEdward Tomasz Napierala { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'}, 580aa015c8eSEdward Tomasz Napierala { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'}, 581aa015c8eSEdward Tomasz Napierala { ACL_READ_ACL, "read_acl", 'c'}, 582aa015c8eSEdward Tomasz Napierala { ACL_WRITE_ACL, "write_acl", 'C'}, 583aa015c8eSEdward Tomasz Napierala { ACL_WRITE_OWNER, "write_owner", 'o'}, 584aa015c8eSEdward Tomasz Napierala { ACL_SYNCHRONIZE, "synchronize", 's'}, 585aa015c8eSEdward Tomasz Napierala { 0, 0, 0}}; 586aa015c8eSEdward Tomasz Napierala 587aa015c8eSEdward Tomasz Napierala static const char * 588aa015c8eSEdward Tomasz Napierala format_flag(uint32_t *var, const struct flagnames_struct *flags) 589aa015c8eSEdward Tomasz Napierala { 590aa015c8eSEdward Tomasz Napierala 591aa015c8eSEdward Tomasz Napierala for (; flags->name != 0; flags++) { 592aa015c8eSEdward Tomasz Napierala if ((flags->flag & *var) == 0) 593aa015c8eSEdward Tomasz Napierala continue; 594aa015c8eSEdward Tomasz Napierala 595aa015c8eSEdward Tomasz Napierala *var &= ~flags->flag; 596aa015c8eSEdward Tomasz Napierala return (flags->name); 597aa015c8eSEdward Tomasz Napierala } 598aa015c8eSEdward Tomasz Napierala 599aa015c8eSEdward Tomasz Napierala return (NULL); 600aa015c8eSEdward Tomasz Napierala } 601aa015c8eSEdward Tomasz Napierala 602aa015c8eSEdward Tomasz Napierala static int 603aa015c8eSEdward Tomasz Napierala format_flags_verbose(char *str, size_t size, uint32_t var, 604aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags) 605aa015c8eSEdward Tomasz Napierala { 606aa015c8eSEdward Tomasz Napierala size_t off = 0; 607aa015c8eSEdward Tomasz Napierala const char *tmp; 608aa015c8eSEdward Tomasz Napierala 609aa015c8eSEdward Tomasz Napierala while ((tmp = format_flag(&var, flags)) != NULL) { 610aa015c8eSEdward Tomasz Napierala off += snprintf(str + off, size - off, "%s/", tmp); 611aa015c8eSEdward Tomasz Napierala assert (off < size); 612aa015c8eSEdward Tomasz Napierala } 613aa015c8eSEdward Tomasz Napierala 614aa015c8eSEdward Tomasz Napierala /* If there were any flags added... */ 615aa015c8eSEdward Tomasz Napierala if (off > 0) { 616aa015c8eSEdward Tomasz Napierala off--; 617aa015c8eSEdward Tomasz Napierala /* ... then remove the last slash. */ 618aa015c8eSEdward Tomasz Napierala assert(str[off] == '/'); 619aa015c8eSEdward Tomasz Napierala } 620aa015c8eSEdward Tomasz Napierala 621aa015c8eSEdward Tomasz Napierala str[off] = '\0'; 622aa015c8eSEdward Tomasz Napierala 623aa015c8eSEdward Tomasz Napierala return (0); 624aa015c8eSEdward Tomasz Napierala } 625aa015c8eSEdward Tomasz Napierala 626aa015c8eSEdward Tomasz Napierala static int 627aa015c8eSEdward Tomasz Napierala format_flags_compact(char *str, size_t size, uint32_t var, 628aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags) 629aa015c8eSEdward Tomasz Napierala { 630aa015c8eSEdward Tomasz Napierala size_t i; 631aa015c8eSEdward Tomasz Napierala 632aa015c8eSEdward Tomasz Napierala for (i = 0; flags[i].name != NULL; i++) { 633aa015c8eSEdward Tomasz Napierala assert(i < size); 634aa015c8eSEdward Tomasz Napierala if ((flags[i].flag & var) == 0) 635aa015c8eSEdward Tomasz Napierala str[i] = '-'; 636aa015c8eSEdward Tomasz Napierala else 637aa015c8eSEdward Tomasz Napierala str[i] = flags[i].letter; 638aa015c8eSEdward Tomasz Napierala } 639aa015c8eSEdward Tomasz Napierala 640aa015c8eSEdward Tomasz Napierala str[i] = '\0'; 641aa015c8eSEdward Tomasz Napierala 642aa015c8eSEdward Tomasz Napierala return (0); 643aa015c8eSEdward Tomasz Napierala } 644aa015c8eSEdward Tomasz Napierala 645aa015c8eSEdward Tomasz Napierala static int 646aa015c8eSEdward Tomasz Napierala parse_flags_verbose(const char *strp, uint32_t *var, 647aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags, const char *flags_name, 648aa015c8eSEdward Tomasz Napierala int *try_compact) 649aa015c8eSEdward Tomasz Napierala { 650aa015c8eSEdward Tomasz Napierala int i, found, ever_found = 0; 651aa015c8eSEdward Tomasz Napierala char *str, *flag; 652aa015c8eSEdward Tomasz Napierala 653aa015c8eSEdward Tomasz Napierala str = strdup(strp); 654aa015c8eSEdward Tomasz Napierala *try_compact = 0; 655aa015c8eSEdward Tomasz Napierala *var = 0; 656aa015c8eSEdward Tomasz Napierala 657aa015c8eSEdward Tomasz Napierala while (str != NULL) { 658aa015c8eSEdward Tomasz Napierala flag = strsep(&str, "/:"); 659aa015c8eSEdward Tomasz Napierala 660aa015c8eSEdward Tomasz Napierala found = 0; 661aa015c8eSEdward Tomasz Napierala for (i = 0; flags[i].name != NULL; i++) { 662aa015c8eSEdward Tomasz Napierala if (strcmp(flags[i].name, flag) == 0) { 663aa015c8eSEdward Tomasz Napierala *var |= flags[i].flag; 664aa015c8eSEdward Tomasz Napierala found = 1; 665aa015c8eSEdward Tomasz Napierala ever_found = 1; 666aa015c8eSEdward Tomasz Napierala } 667aa015c8eSEdward Tomasz Napierala } 668aa015c8eSEdward Tomasz Napierala 669aa015c8eSEdward Tomasz Napierala if (!found) { 670aa015c8eSEdward Tomasz Napierala if (ever_found) 671aa015c8eSEdward Tomasz Napierala warnx("malformed ACL: \"%s\" field contains " 672aa015c8eSEdward Tomasz Napierala "invalid flag \"%s\"", flags_name, flag); 673aa015c8eSEdward Tomasz Napierala else 674aa015c8eSEdward Tomasz Napierala *try_compact = 1; 675aa015c8eSEdward Tomasz Napierala free(str); 676aa015c8eSEdward Tomasz Napierala return (-1); 677aa015c8eSEdward Tomasz Napierala } 678aa015c8eSEdward Tomasz Napierala } 679aa015c8eSEdward Tomasz Napierala 680aa015c8eSEdward Tomasz Napierala free(str); 681aa015c8eSEdward Tomasz Napierala return (0); 682aa015c8eSEdward Tomasz Napierala } 683aa015c8eSEdward Tomasz Napierala 684aa015c8eSEdward Tomasz Napierala static int 685aa015c8eSEdward Tomasz Napierala parse_flags_compact(const char *str, uint32_t *var, 686aa015c8eSEdward Tomasz Napierala const struct flagnames_struct *flags, const char *flags_name) 687aa015c8eSEdward Tomasz Napierala { 688aa015c8eSEdward Tomasz Napierala int i, j, found; 689aa015c8eSEdward Tomasz Napierala 690aa015c8eSEdward Tomasz Napierala *var = 0; 691aa015c8eSEdward Tomasz Napierala 692aa015c8eSEdward Tomasz Napierala for (i = 0;; i++) { 693aa015c8eSEdward Tomasz Napierala if (str[i] == '\0') 694aa015c8eSEdward Tomasz Napierala return (0); 695aa015c8eSEdward Tomasz Napierala 696aa015c8eSEdward Tomasz Napierala /* Ignore minus signs. */ 697aa015c8eSEdward Tomasz Napierala if (str[i] == '-') 698aa015c8eSEdward Tomasz Napierala continue; 699aa015c8eSEdward Tomasz Napierala 700aa015c8eSEdward Tomasz Napierala found = 0; 701aa015c8eSEdward Tomasz Napierala 702aa015c8eSEdward Tomasz Napierala for (j = 0; flags[j].name != NULL; j++) { 703aa015c8eSEdward Tomasz Napierala if (flags[j].letter == str[i]) { 704aa015c8eSEdward Tomasz Napierala *var |= flags[j].flag; 705aa015c8eSEdward Tomasz Napierala found = 1; 706aa015c8eSEdward Tomasz Napierala break; 707aa015c8eSEdward Tomasz Napierala } 708aa015c8eSEdward Tomasz Napierala } 709aa015c8eSEdward Tomasz Napierala 710aa015c8eSEdward Tomasz Napierala if (!found) { 711aa015c8eSEdward Tomasz Napierala warnx("malformed ACL: \"%s\" field contains " 712aa015c8eSEdward Tomasz Napierala "invalid flag \"%c\"", flags_name, str[i]); 713aa015c8eSEdward Tomasz Napierala return (-1); 714aa015c8eSEdward Tomasz Napierala } 715aa015c8eSEdward Tomasz Napierala } 716aa015c8eSEdward Tomasz Napierala } 717aa015c8eSEdward Tomasz Napierala 718aa015c8eSEdward Tomasz Napierala int 719aa015c8eSEdward Tomasz Napierala _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose) 720aa015c8eSEdward Tomasz Napierala { 721aa015c8eSEdward Tomasz Napierala 722aa015c8eSEdward Tomasz Napierala if (verbose) 723aa015c8eSEdward Tomasz Napierala return (format_flags_verbose(str, size, var, a_flags)); 724aa015c8eSEdward Tomasz Napierala 725aa015c8eSEdward Tomasz Napierala return (format_flags_compact(str, size, var, a_flags)); 726aa015c8eSEdward Tomasz Napierala } 727aa015c8eSEdward Tomasz Napierala 728aa015c8eSEdward Tomasz Napierala int 729aa015c8eSEdward Tomasz Napierala _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose) 730aa015c8eSEdward Tomasz Napierala { 731aa015c8eSEdward Tomasz Napierala 732aa015c8eSEdward Tomasz Napierala if (verbose) 733aa015c8eSEdward Tomasz Napierala return (format_flags_verbose(str, size, var, a_access_masks)); 734aa015c8eSEdward Tomasz Napierala 735aa015c8eSEdward Tomasz Napierala return (format_flags_compact(str, size, var, a_access_masks)); 736aa015c8eSEdward Tomasz Napierala } 737aa015c8eSEdward Tomasz Napierala 738aa015c8eSEdward Tomasz Napierala int 739aa015c8eSEdward Tomasz Napierala _nfs4_parse_flags(const char *str, acl_flag_t *flags) 740aa015c8eSEdward Tomasz Napierala { 741aa015c8eSEdward Tomasz Napierala int error, try_compact; 742aa015c8eSEdward Tomasz Napierala int tmpflags; 743aa015c8eSEdward Tomasz Napierala 744aa015c8eSEdward Tomasz Napierala error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact); 745aa015c8eSEdward Tomasz Napierala if (error && try_compact) 746aa015c8eSEdward Tomasz Napierala error = parse_flags_compact(str, &tmpflags, a_flags, "flags"); 747aa015c8eSEdward Tomasz Napierala 748aa015c8eSEdward Tomasz Napierala *flags = tmpflags; 749aa015c8eSEdward Tomasz Napierala 750aa015c8eSEdward Tomasz Napierala return (error); 751aa015c8eSEdward Tomasz Napierala } 752aa015c8eSEdward Tomasz Napierala 753aa015c8eSEdward Tomasz Napierala int 754aa015c8eSEdward Tomasz Napierala _nfs4_parse_access_mask(const char *str, acl_perm_t *perms) 755aa015c8eSEdward Tomasz Napierala { 756aa015c8eSEdward Tomasz Napierala int error, try_compact; 757aa015c8eSEdward Tomasz Napierala int tmpperms; 758aa015c8eSEdward Tomasz Napierala 759aa015c8eSEdward Tomasz Napierala error = parse_flags_verbose(str, &tmpperms, a_access_masks, 760aa015c8eSEdward Tomasz Napierala "access permissions", &try_compact); 761aa015c8eSEdward Tomasz Napierala if (error && try_compact) 762aa015c8eSEdward Tomasz Napierala error = parse_flags_compact(str, &tmpperms, 763aa015c8eSEdward Tomasz Napierala a_access_masks, "access permissions"); 764aa015c8eSEdward Tomasz Napierala 765aa015c8eSEdward Tomasz Napierala *perms = tmpperms; 766aa015c8eSEdward Tomasz Napierala 767aa015c8eSEdward Tomasz Napierala return (error); 768aa015c8eSEdward Tomasz Napierala } 769