1*6185db85Sdougm /* 2*6185db85Sdougm * CDDL HEADER START 3*6185db85Sdougm * 4*6185db85Sdougm * The contents of this file are subject to the terms of the 5*6185db85Sdougm * Common Development and Distribution License (the "License"). 6*6185db85Sdougm * You may not use this file except in compliance with the License. 7*6185db85Sdougm * 8*6185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6185db85Sdougm * or http://www.opensolaris.org/os/licensing. 10*6185db85Sdougm * See the License for the specific language governing permissions 11*6185db85Sdougm * and limitations under the License. 12*6185db85Sdougm * 13*6185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each 14*6185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the 16*6185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 17*6185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 18*6185db85Sdougm * 19*6185db85Sdougm * CDDL HEADER END 20*6185db85Sdougm */ 21*6185db85Sdougm 22*6185db85Sdougm /* 23*6185db85Sdougm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*6185db85Sdougm * Use is subject to license terms. 25*6185db85Sdougm */ 26*6185db85Sdougm 27*6185db85Sdougm #pragma ident "%Z%%M% %I% %E% SMI" 28*6185db85Sdougm 29*6185db85Sdougm /* 30*6185db85Sdougm * core library for common functions across all config store types 31*6185db85Sdougm * and file systems to be exported. This includes legacy dfstab/sharetab 32*6185db85Sdougm * parsing. Need to eliminate XML where possible. 33*6185db85Sdougm */ 34*6185db85Sdougm 35*6185db85Sdougm #include <stdio.h> 36*6185db85Sdougm #include <string.h> 37*6185db85Sdougm #include <ctype.h> 38*6185db85Sdougm #include <unistd.h> 39*6185db85Sdougm #include <limits.h> 40*6185db85Sdougm #include <errno.h> 41*6185db85Sdougm #include <sys/types.h> 42*6185db85Sdougm #include <sys/stat.h> 43*6185db85Sdougm #include <libxml/parser.h> 44*6185db85Sdougm #include <libxml/tree.h> 45*6185db85Sdougm #include "libshare.h" 46*6185db85Sdougm #include "libshare_impl.h" 47*6185db85Sdougm #include "libfsmgt.h" 48*6185db85Sdougm #include <fcntl.h> 49*6185db85Sdougm #include <sys/stat.h> 50*6185db85Sdougm #include <grp.h> 51*6185db85Sdougm #include <limits.h> 52*6185db85Sdougm #include <sys/param.h> 53*6185db85Sdougm #include <signal.h> 54*6185db85Sdougm #include <libintl.h> 55*6185db85Sdougm 56*6185db85Sdougm #include "sharetab.h" 57*6185db85Sdougm 58*6185db85Sdougm #define DFSTAB_NOTICE_LINES 5 59*6185db85Sdougm static char *notice[DFSTAB_NOTICE_LINES] = { 60*6185db85Sdougm "# Do not modify this file directly.\n", 61*6185db85Sdougm "# Use the sharemgr(1m) command for all share management\n", 62*6185db85Sdougm "# This file is reconstructed and only maintained for backward\n", 63*6185db85Sdougm "# compatibility. Configuration lines could be lost.\n", 64*6185db85Sdougm "#\n" 65*6185db85Sdougm }; 66*6185db85Sdougm 67*6185db85Sdougm #define STRNCAT(x, y, z) (xmlChar *)strncat((char *)x, (char *)y, z) 68*6185db85Sdougm 69*6185db85Sdougm /* will be much smaller, but this handles bad syntax in the file */ 70*6185db85Sdougm #define MAXARGSFORSHARE 256 71*6185db85Sdougm 72*6185db85Sdougm /* used internally only */ 73*6185db85Sdougm typedef 74*6185db85Sdougm struct sharelist { 75*6185db85Sdougm struct sharelist *next; 76*6185db85Sdougm int persist; 77*6185db85Sdougm char *path; 78*6185db85Sdougm char *resource; 79*6185db85Sdougm char *fstype; 80*6185db85Sdougm char *options; 81*6185db85Sdougm char *description; 82*6185db85Sdougm char *group; 83*6185db85Sdougm char *origline; 84*6185db85Sdougm int lineno; 85*6185db85Sdougm } xfs_sharelist_t; 86*6185db85Sdougm static void parse_dfstab(char *, xmlNodePtr); 87*6185db85Sdougm extern char *get_token(char *); 88*6185db85Sdougm static void dfs_free_list(xfs_sharelist_t *); 89*6185db85Sdougm /* prototypes */ 90*6185db85Sdougm void getlegacyconfig(char *, xmlNodePtr *); 91*6185db85Sdougm extern sa_share_t _sa_add_share(sa_group_t, char *, int, int *); 92*6185db85Sdougm extern xmlNodePtr _sa_get_next_error(xmlNodePtr); 93*6185db85Sdougm extern sa_group_t _sa_create_group(char *); 94*6185db85Sdougm static void outdfstab(FILE *, xfs_sharelist_t *); 95*6185db85Sdougm extern int _sa_remove_optionset(sa_optionset_t); 96*6185db85Sdougm extern int set_node_share(void *, char *, char *); 97*6185db85Sdougm extern void set_node_attr(void *, char *, char *); 98*6185db85Sdougm 99*6185db85Sdougm /* 100*6185db85Sdougm * alloc_sharelist() 101*6185db85Sdougm * 102*6185db85Sdougm * allocator function to return an zfs_sharelist_t 103*6185db85Sdougm */ 104*6185db85Sdougm 105*6185db85Sdougm static xfs_sharelist_t * 106*6185db85Sdougm alloc_sharelist() 107*6185db85Sdougm { 108*6185db85Sdougm xfs_sharelist_t *item; 109*6185db85Sdougm 110*6185db85Sdougm item = (xfs_sharelist_t *)malloc(sizeof (xfs_sharelist_t)); 111*6185db85Sdougm if (item != NULL) 112*6185db85Sdougm (void) memset(item, '\0', sizeof (xfs_sharelist_t)); 113*6185db85Sdougm return (item); 114*6185db85Sdougm } 115*6185db85Sdougm 116*6185db85Sdougm /* 117*6185db85Sdougm * fix_notice(list) 118*6185db85Sdougm * 119*6185db85Sdougm * Look at the beginning of the current /etc/dfs/dfstab file and add 120*6185db85Sdougm * the do not modify notice if it doesn't exist. 121*6185db85Sdougm */ 122*6185db85Sdougm 123*6185db85Sdougm static xfs_sharelist_t * 124*6185db85Sdougm fix_notice(xfs_sharelist_t *list) 125*6185db85Sdougm { 126*6185db85Sdougm xfs_sharelist_t *item, *prev; 127*6185db85Sdougm int i; 128*6185db85Sdougm 129*6185db85Sdougm if (list->path == NULL && list->description != NULL && 130*6185db85Sdougm strcmp(list->description, notice[0]) != 0) { 131*6185db85Sdougm for (prev = NULL, i = 0; i < DFSTAB_NOTICE_LINES; i++) { 132*6185db85Sdougm item = alloc_sharelist(); 133*6185db85Sdougm if (item != NULL) { 134*6185db85Sdougm item->description = strdup(notice[i]); 135*6185db85Sdougm if (prev == NULL) { 136*6185db85Sdougm item->next = list; 137*6185db85Sdougm prev = item; 138*6185db85Sdougm list = item; 139*6185db85Sdougm } else { 140*6185db85Sdougm item->next = prev->next; 141*6185db85Sdougm prev->next = item; 142*6185db85Sdougm prev = item; 143*6185db85Sdougm } 144*6185db85Sdougm } 145*6185db85Sdougm } 146*6185db85Sdougm } 147*6185db85Sdougm return (list); 148*6185db85Sdougm } 149*6185db85Sdougm 150*6185db85Sdougm /* 151*6185db85Sdougm * getdfstab(dfs) 152*6185db85Sdougm * 153*6185db85Sdougm * Returns an zfs_sharelist_t list of lines from the dfstab file 154*6185db85Sdougm * pointed to by the FILE pointer dfs. Each entry is parsed and the 155*6185db85Sdougm * original line is also preserved. Used in parsing and updating the 156*6185db85Sdougm * dfstab file. 157*6185db85Sdougm */ 158*6185db85Sdougm 159*6185db85Sdougm static xfs_sharelist_t * 160*6185db85Sdougm getdfstab(FILE *dfs) 161*6185db85Sdougm { 162*6185db85Sdougm char buff[_POSIX_ARG_MAX]; /* reasonable size given syntax of share */ 163*6185db85Sdougm char *bp; 164*6185db85Sdougm char *token; 165*6185db85Sdougm char *args[MAXARGSFORSHARE]; 166*6185db85Sdougm int argc; 167*6185db85Sdougm int c; 168*6185db85Sdougm static int line = 0; 169*6185db85Sdougm xfs_sharelist_t *item, *first, *last; 170*6185db85Sdougm 171*6185db85Sdougm if (dfs != NULL) { 172*6185db85Sdougm first = NULL; 173*6185db85Sdougm line = 0; 174*6185db85Sdougm while (fgets(buff, sizeof (buff), dfs) != NULL) { 175*6185db85Sdougm line++; 176*6185db85Sdougm bp = buff; 177*6185db85Sdougm if (buff[0] == '#') { 178*6185db85Sdougm item = alloc_sharelist(); 179*6185db85Sdougm if (item != NULL) { 180*6185db85Sdougm /* if no path, then comment */ 181*6185db85Sdougm item->lineno = line; 182*6185db85Sdougm item->description = strdup(buff); 183*6185db85Sdougm if (first == NULL) { 184*6185db85Sdougm first = item; 185*6185db85Sdougm last = item; 186*6185db85Sdougm } else { 187*6185db85Sdougm last->next = item; 188*6185db85Sdougm last = item; 189*6185db85Sdougm } 190*6185db85Sdougm } else { 191*6185db85Sdougm break; 192*6185db85Sdougm } 193*6185db85Sdougm continue; 194*6185db85Sdougm } else if (buff[0] == '\n') { 195*6185db85Sdougm continue; 196*6185db85Sdougm } 197*6185db85Sdougm optind = 1; 198*6185db85Sdougm item = alloc_sharelist(); 199*6185db85Sdougm if (item == NULL) { 200*6185db85Sdougm break; 201*6185db85Sdougm } else if (first == NULL) { 202*6185db85Sdougm first = item; 203*6185db85Sdougm last = item; 204*6185db85Sdougm } else { 205*6185db85Sdougm last->next = item; 206*6185db85Sdougm last = item; 207*6185db85Sdougm } 208*6185db85Sdougm item->lineno = line; 209*6185db85Sdougm item->origline = strdup(buff); 210*6185db85Sdougm (void) get_token(NULL); /* reset to new pointers */ 211*6185db85Sdougm argc = 0; 212*6185db85Sdougm while ((token = get_token(bp)) != NULL) { 213*6185db85Sdougm if (argc < MAXARGSFORSHARE) { 214*6185db85Sdougm args[argc++] = token; 215*6185db85Sdougm } 216*6185db85Sdougm } 217*6185db85Sdougm while ((c = getopt(argc, args, "F:o:d:pg:")) != -1) { 218*6185db85Sdougm switch (c) { 219*6185db85Sdougm case 'p': 220*6185db85Sdougm item->persist = 1; 221*6185db85Sdougm break; 222*6185db85Sdougm case 'F': 223*6185db85Sdougm item->fstype = strdup(optarg); 224*6185db85Sdougm break; 225*6185db85Sdougm case 'o': 226*6185db85Sdougm item->options = strdup(optarg); 227*6185db85Sdougm break; 228*6185db85Sdougm case 'd': 229*6185db85Sdougm item->description = strdup(optarg); 230*6185db85Sdougm break; 231*6185db85Sdougm case 'g': 232*6185db85Sdougm item->group = strdup(optarg); 233*6185db85Sdougm break; 234*6185db85Sdougm default: 235*6185db85Sdougm break; 236*6185db85Sdougm } 237*6185db85Sdougm } 238*6185db85Sdougm if (optind < argc) { 239*6185db85Sdougm item->path = strdup(args[optind]); 240*6185db85Sdougm optind++; 241*6185db85Sdougm if (optind < argc) { 242*6185db85Sdougm char *resource; 243*6185db85Sdougm char *optgroup; 244*6185db85Sdougm /* resource and/or groupname */ 245*6185db85Sdougm resource = args[optind]; 246*6185db85Sdougm optgroup = strchr(resource, '@'); 247*6185db85Sdougm if (optgroup != NULL) { 248*6185db85Sdougm *optgroup++ = '\0'; 249*6185db85Sdougm } 250*6185db85Sdougm if (optgroup != NULL) 251*6185db85Sdougm item->group = strdup(optgroup); 252*6185db85Sdougm if (resource != NULL && strlen(resource) > 0) 253*6185db85Sdougm item->resource = strdup(resource); 254*6185db85Sdougm } 255*6185db85Sdougm } 256*6185db85Sdougm } 257*6185db85Sdougm if (item->fstype == NULL) 258*6185db85Sdougm item->fstype = strdup("nfs"); /* this is the default */ 259*6185db85Sdougm } 260*6185db85Sdougm first = fix_notice(first); 261*6185db85Sdougm return (first); 262*6185db85Sdougm } 263*6185db85Sdougm 264*6185db85Sdougm /* 265*6185db85Sdougm * finddfsentry(list, path) 266*6185db85Sdougm * 267*6185db85Sdougm * Look for path in the zfs_sharelist_t list and return the tnry if it 268*6185db85Sdougm * exists. 269*6185db85Sdougm */ 270*6185db85Sdougm 271*6185db85Sdougm static xfs_sharelist_t * 272*6185db85Sdougm finddfsentry(xfs_sharelist_t *list, char *path) 273*6185db85Sdougm { 274*6185db85Sdougm xfs_sharelist_t *item; 275*6185db85Sdougm 276*6185db85Sdougm for (item = list; item != NULL; item = item->next) { 277*6185db85Sdougm if (item->path != NULL && strcmp(item->path, path) == 0) 278*6185db85Sdougm return (item); 279*6185db85Sdougm } 280*6185db85Sdougm return (NULL); 281*6185db85Sdougm } 282*6185db85Sdougm 283*6185db85Sdougm /* 284*6185db85Sdougm * remdfsentry(list, path, proto) 285*6185db85Sdougm * 286*6185db85Sdougm * Remove the specified path (with protocol) from the list. This will 287*6185db85Sdougm * remove it from dfstab when the file is rewritten. 288*6185db85Sdougm */ 289*6185db85Sdougm 290*6185db85Sdougm static xfs_sharelist_t * 291*6185db85Sdougm remdfsentry(xfs_sharelist_t *list, char *path, char *proto) 292*6185db85Sdougm { 293*6185db85Sdougm xfs_sharelist_t *item, *prev = NULL; 294*6185db85Sdougm 295*6185db85Sdougm 296*6185db85Sdougm for (item = prev = list; item != NULL; item = item->next) { 297*6185db85Sdougm /* skip comment entry but don't lose it */ 298*6185db85Sdougm if (item->path == NULL) { 299*6185db85Sdougm prev = item; 300*6185db85Sdougm continue; 301*6185db85Sdougm } 302*6185db85Sdougm /* if proto is NULL, remove all protocols */ 303*6185db85Sdougm if (proto == NULL || (strcmp(item->path, path) == 0 && 304*6185db85Sdougm (item->fstype != NULL && strcmp(item->fstype, proto) == 0))) 305*6185db85Sdougm break; 306*6185db85Sdougm if (item->fstype == NULL && 307*6185db85Sdougm (proto == NULL || strcmp(proto, "nfs") == 0)) 308*6185db85Sdougm break; 309*6185db85Sdougm prev = item; 310*6185db85Sdougm } 311*6185db85Sdougm if (item != NULL) { 312*6185db85Sdougm if (item == prev) { 313*6185db85Sdougm list = item->next; /* this must be the first one */ 314*6185db85Sdougm } else { 315*6185db85Sdougm prev->next = item->next; 316*6185db85Sdougm } 317*6185db85Sdougm item->next = NULL; 318*6185db85Sdougm dfs_free_list(item); 319*6185db85Sdougm } 320*6185db85Sdougm return (list); 321*6185db85Sdougm } 322*6185db85Sdougm 323*6185db85Sdougm /* 324*6185db85Sdougm * remdfsline(list, line) 325*6185db85Sdougm * 326*6185db85Sdougm * Remove the line specified from the list. 327*6185db85Sdougm */ 328*6185db85Sdougm 329*6185db85Sdougm static xfs_sharelist_t * 330*6185db85Sdougm remdfsline(xfs_sharelist_t *list, char *line) 331*6185db85Sdougm { 332*6185db85Sdougm xfs_sharelist_t *item, *prev = NULL; 333*6185db85Sdougm 334*6185db85Sdougm for (item = prev = list; item != NULL; item = item->next) { 335*6185db85Sdougm /* skip comment entry but don't lose it */ 336*6185db85Sdougm if (item->path == NULL) { 337*6185db85Sdougm prev = item; 338*6185db85Sdougm continue; 339*6185db85Sdougm } 340*6185db85Sdougm if (strcmp(item->origline, line) == 0) { 341*6185db85Sdougm break; 342*6185db85Sdougm } 343*6185db85Sdougm prev = item; 344*6185db85Sdougm } 345*6185db85Sdougm if (item != NULL) { 346*6185db85Sdougm if (item == prev) { 347*6185db85Sdougm list = item->next; /* this must be the first one */ 348*6185db85Sdougm } else { 349*6185db85Sdougm prev->next = item->next; 350*6185db85Sdougm } 351*6185db85Sdougm item->next = NULL; 352*6185db85Sdougm dfs_free_list(item); 353*6185db85Sdougm } 354*6185db85Sdougm return (list); 355*6185db85Sdougm } 356*6185db85Sdougm 357*6185db85Sdougm /* 358*6185db85Sdougm * adddfsentry(list, share, proto) 359*6185db85Sdougm * 360*6185db85Sdougm * Add an entry to the dfstab list for share (relative to proto). This 361*6185db85Sdougm * is used to update dfstab for legacy purposes. 362*6185db85Sdougm */ 363*6185db85Sdougm 364*6185db85Sdougm static xfs_sharelist_t * 365*6185db85Sdougm adddfsentry(xfs_sharelist_t *list, sa_share_t share, char *proto) 366*6185db85Sdougm { 367*6185db85Sdougm xfs_sharelist_t *item, *tmp; 368*6185db85Sdougm sa_group_t parent; 369*6185db85Sdougm char *groupname; 370*6185db85Sdougm 371*6185db85Sdougm item = alloc_sharelist(); 372*6185db85Sdougm if (item != NULL) { 373*6185db85Sdougm parent = sa_get_parent_group(share); 374*6185db85Sdougm groupname = sa_get_group_attr(parent, "name"); 375*6185db85Sdougm if (strcmp(groupname, "default") == 0) { 376*6185db85Sdougm sa_free_attr_string(groupname); 377*6185db85Sdougm groupname = NULL; 378*6185db85Sdougm } 379*6185db85Sdougm item->path = sa_get_share_attr(share, "path"); 380*6185db85Sdougm item->resource = sa_get_share_attr(share, "resource"); 381*6185db85Sdougm item->group = groupname; 382*6185db85Sdougm item->fstype = strdup(proto); 383*6185db85Sdougm item->options = sa_proto_legacy_format(proto, share, 1); 384*6185db85Sdougm if (item->options != NULL && strlen(item->options) == 0) { 385*6185db85Sdougm free(item->options); 386*6185db85Sdougm item->options = NULL; 387*6185db85Sdougm } 388*6185db85Sdougm item->description = sa_get_share_description(share); 389*6185db85Sdougm if (item->description != NULL && strlen(item->description) == 0) { 390*6185db85Sdougm sa_free_share_description(item->description); 391*6185db85Sdougm item->description = NULL; 392*6185db85Sdougm } 393*6185db85Sdougm if (list == NULL) { 394*6185db85Sdougm list = item; 395*6185db85Sdougm } else { 396*6185db85Sdougm for (tmp = list; tmp->next != NULL; tmp = tmp->next) 397*6185db85Sdougm /* do nothing */; 398*6185db85Sdougm tmp->next = item; 399*6185db85Sdougm } 400*6185db85Sdougm } 401*6185db85Sdougm return (list); 402*6185db85Sdougm } 403*6185db85Sdougm 404*6185db85Sdougm /* 405*6185db85Sdougm * outdfstab(dfstab, list) 406*6185db85Sdougm * 407*6185db85Sdougm * Output the list to dfstab making sure the file is truncated. 408*6185db85Sdougm * Comments and errors are preserved. 409*6185db85Sdougm */ 410*6185db85Sdougm 411*6185db85Sdougm static void 412*6185db85Sdougm outdfstab(FILE *dfstab, xfs_sharelist_t *list) 413*6185db85Sdougm { 414*6185db85Sdougm xfs_sharelist_t *item; 415*6185db85Sdougm 416*6185db85Sdougm (void) ftruncate(fileno(dfstab), 0); 417*6185db85Sdougm 418*6185db85Sdougm for (item = list; item != NULL; item = item->next) { 419*6185db85Sdougm if (item->path != NULL) { 420*6185db85Sdougm if (*item->path == '/') 421*6185db85Sdougm (void) fprintf(dfstab, "share %s%s%s%s%s%s%s %s%s%s%s%s\n", 422*6185db85Sdougm (item->fstype != NULL) ? "-F " : "", 423*6185db85Sdougm (item->fstype != NULL) ? item->fstype : "", 424*6185db85Sdougm (item->options != NULL) ? " -o " : "", 425*6185db85Sdougm (item->options != NULL) ? item->options : "", 426*6185db85Sdougm (item->description != NULL) ? " -d \"" : "", 427*6185db85Sdougm (item->description != NULL) ? 428*6185db85Sdougm item->description : "", 429*6185db85Sdougm (item->description != NULL) ? "\"" : "", 430*6185db85Sdougm item->path, 431*6185db85Sdougm ((item->resource != NULL) || 432*6185db85Sdougm (item->group != NULL)) ? " " : "", 433*6185db85Sdougm (item->resource != NULL) ? item->resource : "", 434*6185db85Sdougm item->group != NULL ? "@" : "", 435*6185db85Sdougm item->group != NULL ? item->group : ""); 436*6185db85Sdougm else 437*6185db85Sdougm (void) fprintf(dfstab, "%s", item->origline); 438*6185db85Sdougm } else { 439*6185db85Sdougm if (item->description != NULL) { 440*6185db85Sdougm (void) fprintf(dfstab, "%s", item->description); 441*6185db85Sdougm } else { 442*6185db85Sdougm (void) fprintf(dfstab, "%s", item->origline); 443*6185db85Sdougm } 444*6185db85Sdougm } 445*6185db85Sdougm } 446*6185db85Sdougm } 447*6185db85Sdougm 448*6185db85Sdougm /* 449*6185db85Sdougm * open_dfstab(file) 450*6185db85Sdougm * 451*6185db85Sdougm * Open the specified dfstab file. If the owner/group/perms are wrong, 452*6185db85Sdougm * fix them. 453*6185db85Sdougm */ 454*6185db85Sdougm 455*6185db85Sdougm static FILE * 456*6185db85Sdougm open_dfstab(char *file) 457*6185db85Sdougm { 458*6185db85Sdougm struct group *grp; 459*6185db85Sdougm struct group group; 460*6185db85Sdougm char *buff; 461*6185db85Sdougm int grsize; 462*6185db85Sdougm FILE *dfstab; 463*6185db85Sdougm 464*6185db85Sdougm dfstab = fopen(file, "r+"); 465*6185db85Sdougm if (dfstab == NULL) { 466*6185db85Sdougm dfstab = fopen(file, "w+"); 467*6185db85Sdougm } 468*6185db85Sdougm if (dfstab != NULL) { 469*6185db85Sdougm grsize = sysconf(_SC_GETGR_R_SIZE_MAX); 470*6185db85Sdougm buff = malloc(grsize); 471*6185db85Sdougm if (buff != NULL) 472*6185db85Sdougm grp = getgrnam_r(SA_DEFAULT_FILE_GRP, &group, buff, grsize); 473*6185db85Sdougm else 474*6185db85Sdougm grp = getgrnam(SA_DEFAULT_FILE_GRP); /* take the risk */ 475*6185db85Sdougm (void) fchmod(fileno(dfstab), 0644); 476*6185db85Sdougm (void) fchown(fileno(dfstab), 0, 477*6185db85Sdougm grp != NULL ? grp->gr_gid : 3); 478*6185db85Sdougm if (buff != NULL) 479*6185db85Sdougm free(buff); 480*6185db85Sdougm rewind(dfstab); 481*6185db85Sdougm } 482*6185db85Sdougm return (dfstab); 483*6185db85Sdougm } 484*6185db85Sdougm 485*6185db85Sdougm /* 486*6185db85Sdougm * sa_comment_line(line, err) 487*6185db85Sdougm * 488*6185db85Sdougm * Add a comment to the dfstab file with err as a prefix to the 489*6185db85Sdougm * original line. 490*6185db85Sdougm */ 491*6185db85Sdougm 492*6185db85Sdougm static void 493*6185db85Sdougm sa_comment_line(char *line, char *err) 494*6185db85Sdougm { 495*6185db85Sdougm FILE *dfstab; 496*6185db85Sdougm xfs_sharelist_t *list; 497*6185db85Sdougm sigset_t old, new; 498*6185db85Sdougm 499*6185db85Sdougm dfstab = open_dfstab(SA_LEGACY_DFSTAB); 500*6185db85Sdougm if (dfstab != NULL) { 501*6185db85Sdougm (void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8); 502*6185db85Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new); 503*6185db85Sdougm (void) sigaddset(&new, SIGHUP); 504*6185db85Sdougm (void) sigaddset(&new, SIGINT); 505*6185db85Sdougm (void) sigaddset(&new, SIGQUIT); 506*6185db85Sdougm (void) sigaddset(&new, SIGTSTP); 507*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &new, &old); 508*6185db85Sdougm (void) lockf(fileno(dfstab), F_LOCK, 0); 509*6185db85Sdougm list = getdfstab(dfstab); 510*6185db85Sdougm rewind(dfstab); 511*6185db85Sdougm (void) remdfsline(list, line); 512*6185db85Sdougm outdfstab(dfstab, list); 513*6185db85Sdougm (void) fprintf(dfstab, "# Error: %s: %s", err, line); 514*6185db85Sdougm (void) fsync(fileno(dfstab)); 515*6185db85Sdougm (void) lockf(fileno(dfstab), F_ULOCK, 0); 516*6185db85Sdougm (void) fclose(dfstab); 517*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &old, NULL); 518*6185db85Sdougm if (list != NULL) 519*6185db85Sdougm dfs_free_list(list); 520*6185db85Sdougm } 521*6185db85Sdougm } 522*6185db85Sdougm 523*6185db85Sdougm /* 524*6185db85Sdougm * sa_delete_legacy(share) 525*6185db85Sdougm * 526*6185db85Sdougm * Delete the specified share from the legacy config file. 527*6185db85Sdougm */ 528*6185db85Sdougm 529*6185db85Sdougm int 530*6185db85Sdougm sa_delete_legacy(sa_share_t share) 531*6185db85Sdougm { 532*6185db85Sdougm FILE *dfstab; 533*6185db85Sdougm int err; 534*6185db85Sdougm int ret = SA_OK; 535*6185db85Sdougm xfs_sharelist_t *list; 536*6185db85Sdougm char *path; 537*6185db85Sdougm sa_optionset_t optionset; 538*6185db85Sdougm sa_group_t parent; 539*6185db85Sdougm sigset_t old, new; 540*6185db85Sdougm 541*6185db85Sdougm dfstab = open_dfstab(SA_LEGACY_DFSTAB); 542*6185db85Sdougm if (dfstab != NULL) { 543*6185db85Sdougm (void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8); 544*6185db85Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new); 545*6185db85Sdougm (void) sigaddset(&new, SIGHUP); 546*6185db85Sdougm (void) sigaddset(&new, SIGINT); 547*6185db85Sdougm (void) sigaddset(&new, SIGQUIT); 548*6185db85Sdougm (void) sigaddset(&new, SIGTSTP); 549*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &new, &old); 550*6185db85Sdougm path = sa_get_share_attr(share, "path"); 551*6185db85Sdougm parent = sa_get_parent_group(share); 552*6185db85Sdougm if (parent != NULL) { 553*6185db85Sdougm (void) lockf(fileno(dfstab), F_LOCK, 0); 554*6185db85Sdougm list = getdfstab(dfstab); 555*6185db85Sdougm rewind(dfstab); 556*6185db85Sdougm for (optionset = sa_get_optionset(parent, NULL); 557*6185db85Sdougm optionset != NULL; 558*6185db85Sdougm optionset = sa_get_next_optionset(optionset)) { 559*6185db85Sdougm char *proto = sa_get_optionset_attr(optionset, "type"); 560*6185db85Sdougm if (list != NULL && proto != NULL) 561*6185db85Sdougm (void) remdfsentry(list, path, proto); 562*6185db85Sdougm if (proto == NULL) 563*6185db85Sdougm ret = SA_NO_MEMORY; 564*6185db85Sdougm /* 565*6185db85Sdougm * may want to only do the dfstab if this call 566*6185db85Sdougm * returns NOT IMPLEMENTED but it shouldn't 567*6185db85Sdougm * hurt. 568*6185db85Sdougm */ 569*6185db85Sdougm if (ret == SA_OK) { 570*6185db85Sdougm err = sa_proto_delete_legacy(proto, share); 571*6185db85Sdougm if (err != SA_NOT_IMPLEMENTED) 572*6185db85Sdougm ret = err; 573*6185db85Sdougm } 574*6185db85Sdougm if (proto != NULL) 575*6185db85Sdougm sa_free_attr_string(proto); 576*6185db85Sdougm } 577*6185db85Sdougm outdfstab(dfstab, list); 578*6185db85Sdougm if (list != NULL) 579*6185db85Sdougm dfs_free_list(list); 580*6185db85Sdougm (void) fflush(dfstab); 581*6185db85Sdougm (void) lockf(fileno(dfstab), F_ULOCK, 0); 582*6185db85Sdougm } 583*6185db85Sdougm (void) fsync(fileno(dfstab)); 584*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &old, NULL); 585*6185db85Sdougm (void) fclose(dfstab); 586*6185db85Sdougm sa_free_attr_string(path); 587*6185db85Sdougm } else { 588*6185db85Sdougm if (errno == EACCES || errno == EPERM) { 589*6185db85Sdougm ret = SA_NO_PERMISSION; 590*6185db85Sdougm } else { 591*6185db85Sdougm ret = SA_CONFIG_ERR; 592*6185db85Sdougm } 593*6185db85Sdougm } 594*6185db85Sdougm return (ret); 595*6185db85Sdougm } 596*6185db85Sdougm 597*6185db85Sdougm /* 598*6185db85Sdougm * sa_update_legacy(share, proto) 599*6185db85Sdougm * 600*6185db85Sdougm * There is an assumption that dfstab will be the most common form of 601*6185db85Sdougm * legacy configuration file for shares, but not the only one. Because 602*6185db85Sdougm * of that, dfstab handling is done in the main code with calls to 603*6185db85Sdougm * this function and protocol specific calls to deal with formating 604*6185db85Sdougm * options into dfstab/share compatible syntax. Since not everything 605*6185db85Sdougm * will be dfstab, there is a provision for calling a protocol 606*6185db85Sdougm * specific plugin interface that allows the protocol plugin to do its 607*6185db85Sdougm * own legacy files and skip the dfstab update. 608*6185db85Sdougm */ 609*6185db85Sdougm 610*6185db85Sdougm int 611*6185db85Sdougm sa_update_legacy(sa_share_t share, char *proto) 612*6185db85Sdougm { 613*6185db85Sdougm FILE *dfstab; 614*6185db85Sdougm int ret = SA_OK; 615*6185db85Sdougm xfs_sharelist_t *list; 616*6185db85Sdougm char *path; 617*6185db85Sdougm sigset_t old, new; 618*6185db85Sdougm char *persist; 619*6185db85Sdougm 620*6185db85Sdougm ret = sa_proto_update_legacy(proto, share); 621*6185db85Sdougm if (ret != SA_NOT_IMPLEMENTED) 622*6185db85Sdougm return (ret); 623*6185db85Sdougm /* do the dfstab format */ 624*6185db85Sdougm persist = sa_get_share_attr(share, "type"); 625*6185db85Sdougm /* 626*6185db85Sdougm * only update if the share is not transient -- no share type 627*6185db85Sdougm * set or the type is not "transient". 628*6185db85Sdougm */ 629*6185db85Sdougm if (persist == NULL || strcmp(persist, "transient") != 0) { 630*6185db85Sdougm dfstab = open_dfstab(SA_LEGACY_DFSTAB); 631*6185db85Sdougm if (dfstab != NULL) { 632*6185db85Sdougm (void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8); 633*6185db85Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new); 634*6185db85Sdougm (void) sigaddset(&new, SIGHUP); 635*6185db85Sdougm (void) sigaddset(&new, SIGINT); 636*6185db85Sdougm (void) sigaddset(&new, SIGQUIT); 637*6185db85Sdougm (void) sigaddset(&new, SIGTSTP); 638*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &new, &old); 639*6185db85Sdougm path = sa_get_share_attr(share, "path"); 640*6185db85Sdougm (void) lockf(fileno(dfstab), F_LOCK, 0); 641*6185db85Sdougm list = getdfstab(dfstab); 642*6185db85Sdougm rewind(dfstab); 643*6185db85Sdougm if (list != NULL) 644*6185db85Sdougm list = remdfsentry(list, path, proto); 645*6185db85Sdougm list = adddfsentry(list, share, proto); 646*6185db85Sdougm outdfstab(dfstab, list); 647*6185db85Sdougm (void) fflush(dfstab); 648*6185db85Sdougm (void) lockf(fileno(dfstab), F_ULOCK, 0); 649*6185db85Sdougm (void) fsync(fileno(dfstab)); 650*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &old, NULL); 651*6185db85Sdougm (void) fclose(dfstab); 652*6185db85Sdougm sa_free_attr_string(path); 653*6185db85Sdougm if (list != NULL) 654*6185db85Sdougm dfs_free_list(list); 655*6185db85Sdougm } else { 656*6185db85Sdougm if (errno == EACCES || errno == EPERM) { 657*6185db85Sdougm ret = SA_NO_PERMISSION; 658*6185db85Sdougm } else { 659*6185db85Sdougm ret = SA_CONFIG_ERR; 660*6185db85Sdougm } 661*6185db85Sdougm } 662*6185db85Sdougm } 663*6185db85Sdougm if (persist != NULL) 664*6185db85Sdougm sa_free_attr_string(persist); 665*6185db85Sdougm return (ret); 666*6185db85Sdougm } 667*6185db85Sdougm 668*6185db85Sdougm /* 669*6185db85Sdougm * sa_is_security(optname, proto) 670*6185db85Sdougm * 671*6185db85Sdougm * Check to see if optname is a security (named optionset) specific 672*6185db85Sdougm * property for the specified protocol. 673*6185db85Sdougm */ 674*6185db85Sdougm 675*6185db85Sdougm int 676*6185db85Sdougm sa_is_security(char *optname, char *proto) 677*6185db85Sdougm { 678*6185db85Sdougm int ret = 0; 679*6185db85Sdougm if (proto != NULL) 680*6185db85Sdougm ret = sa_proto_security_prop(proto, optname); 681*6185db85Sdougm return (ret); 682*6185db85Sdougm } 683*6185db85Sdougm 684*6185db85Sdougm /* 685*6185db85Sdougm * add_syntax_comment(root, line, err, todfstab) 686*6185db85Sdougm * 687*6185db85Sdougm * add a comment to the document indicating a syntax error. If 688*6185db85Sdougm * todfstab is set, write it back to the dfstab file as well. 689*6185db85Sdougm */ 690*6185db85Sdougm 691*6185db85Sdougm static void 692*6185db85Sdougm add_syntax_comment(xmlNodePtr root, char *line, char *err, int todfstab) 693*6185db85Sdougm { 694*6185db85Sdougm xmlNodePtr node; 695*6185db85Sdougm 696*6185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"error", (xmlChar *)line); 697*6185db85Sdougm if (node != NULL) { 698*6185db85Sdougm xmlSetProp(node, (xmlChar *)"type", (xmlChar *)err); 699*6185db85Sdougm } 700*6185db85Sdougm if (todfstab) 701*6185db85Sdougm sa_comment_line(line, err); 702*6185db85Sdougm } 703*6185db85Sdougm 704*6185db85Sdougm /* 705*6185db85Sdougm * sa_is_share(object) 706*6185db85Sdougm * 707*6185db85Sdougm * returns true of the object is of type "share". 708*6185db85Sdougm */ 709*6185db85Sdougm 710*6185db85Sdougm int 711*6185db85Sdougm sa_is_share(void *object) 712*6185db85Sdougm { 713*6185db85Sdougm if (object != NULL) { 714*6185db85Sdougm if (strcmp((char *)((xmlNodePtr)object)->name, "share") == 0) 715*6185db85Sdougm return (1); 716*6185db85Sdougm } 717*6185db85Sdougm return (0); 718*6185db85Sdougm } 719*6185db85Sdougm 720*6185db85Sdougm /* 721*6185db85Sdougm * _sa_remove_property(property) 722*6185db85Sdougm * 723*6185db85Sdougm * remove a property only from the document. 724*6185db85Sdougm */ 725*6185db85Sdougm 726*6185db85Sdougm static void 727*6185db85Sdougm _sa_remove_property(sa_property_t property) 728*6185db85Sdougm { 729*6185db85Sdougm xmlUnlinkNode((xmlNodePtr)property); 730*6185db85Sdougm xmlFreeNode((xmlNodePtr)property); 731*6185db85Sdougm } 732*6185db85Sdougm 733*6185db85Sdougm /* 734*6185db85Sdougm * sa_parse_legacy_options(group, options, proto) 735*6185db85Sdougm * 736*6185db85Sdougm * In order to support legacy configurations, we allow the protocol 737*6185db85Sdougm * specific plugin to parse legacy syntax options (like those in 738*6185db85Sdougm * /etc/dfs/dfstab). This adds a new optionset to the group (or 739*6185db85Sdougm * share). 740*6185db85Sdougm * 741*6185db85Sdougm * Once the optionset has been created, we then get the derived 742*6185db85Sdougm * optionset of the parent (options from the optionset of the parent 743*6185db85Sdougm * and any parent it might have) and remove those from the created 744*6185db85Sdougm * optionset. This avoids duplication of options. 745*6185db85Sdougm */ 746*6185db85Sdougm 747*6185db85Sdougm int 748*6185db85Sdougm sa_parse_legacy_options(sa_group_t group, char *options, char *proto) 749*6185db85Sdougm { 750*6185db85Sdougm int ret = SA_INVALID_PROTOCOL; 751*6185db85Sdougm sa_group_t parent; 752*6185db85Sdougm parent = sa_get_parent_group(group); 753*6185db85Sdougm 754*6185db85Sdougm if (proto != NULL) 755*6185db85Sdougm ret = sa_proto_legacy_opts(proto, group, options); 756*6185db85Sdougm /* 757*6185db85Sdougm * if in a group, remove the inherited options and security 758*6185db85Sdougm */ 759*6185db85Sdougm if (ret == SA_OK) { 760*6185db85Sdougm if (parent != NULL) { 761*6185db85Sdougm sa_optionset_t optionset; 762*6185db85Sdougm sa_property_t popt, prop; 763*6185db85Sdougm sa_optionset_t localoptions; 764*6185db85Sdougm /* find parent options to remove from child */ 765*6185db85Sdougm optionset = sa_get_derived_optionset(parent, proto, 1); 766*6185db85Sdougm localoptions = sa_get_optionset(group, proto); 767*6185db85Sdougm if (optionset != NULL) { 768*6185db85Sdougm for (popt = sa_get_property(optionset, NULL); 769*6185db85Sdougm popt != NULL; 770*6185db85Sdougm popt = sa_get_next_property(popt)) { 771*6185db85Sdougm char *tag; 772*6185db85Sdougm char *value1; 773*6185db85Sdougm char *value2; 774*6185db85Sdougm 775*6185db85Sdougm tag = sa_get_property_attr(popt, "type"); 776*6185db85Sdougm if (tag != NULL) { 777*6185db85Sdougm prop = sa_get_property(localoptions, tag); 778*6185db85Sdougm if (prop != NULL) { 779*6185db85Sdougm value1 = sa_get_property_attr(popt, "value"); 780*6185db85Sdougm value2 = sa_get_property_attr(prop, "value"); 781*6185db85Sdougm if (value1 != NULL && value2 != NULL && 782*6185db85Sdougm strcmp(value1, value2) == 0) { 783*6185db85Sdougm /* remove the property from the child */ 784*6185db85Sdougm (void) _sa_remove_property(prop); 785*6185db85Sdougm } 786*6185db85Sdougm if (value1 != NULL) 787*6185db85Sdougm sa_free_attr_string(value1); 788*6185db85Sdougm if (value2 != NULL) 789*6185db85Sdougm sa_free_attr_string(value2); 790*6185db85Sdougm } 791*6185db85Sdougm sa_free_attr_string(tag); 792*6185db85Sdougm } 793*6185db85Sdougm } 794*6185db85Sdougm prop = sa_get_property(localoptions, NULL); 795*6185db85Sdougm if (prop == NULL && sa_is_share(group)) { 796*6185db85Sdougm /* 797*6185db85Sdougm * all properties removed so remove the 798*6185db85Sdougm * optionset if it is on a share 799*6185db85Sdougm */ 800*6185db85Sdougm (void) _sa_remove_optionset(localoptions); 801*6185db85Sdougm } 802*6185db85Sdougm sa_free_derived_optionset(optionset); 803*6185db85Sdougm } 804*6185db85Sdougm /* 805*6185db85Sdougm * need to remove security here. If there are no 806*6185db85Sdougm * security options on the local group/share, don't 807*6185db85Sdougm * bother since those are the only ones that would be 808*6185db85Sdougm * affected. 809*6185db85Sdougm */ 810*6185db85Sdougm localoptions = sa_get_all_security_types(group, proto, 0); 811*6185db85Sdougm if (localoptions != NULL) { 812*6185db85Sdougm for (prop = sa_get_property(localoptions, NULL); 813*6185db85Sdougm prop != NULL; prop = sa_get_next_property(prop)) { 814*6185db85Sdougm char *tag; 815*6185db85Sdougm sa_security_t security; 816*6185db85Sdougm tag = sa_get_property_attr(prop, "type"); 817*6185db85Sdougm if (tag != NULL) { 818*6185db85Sdougm security = sa_get_security(group, tag, proto); 819*6185db85Sdougm sa_free_attr_string(tag); 820*6185db85Sdougm for (popt = sa_get_property(security, NULL); 821*6185db85Sdougm popt != NULL; 822*6185db85Sdougm popt = sa_get_next_property(popt)) { 823*6185db85Sdougm char *value1; 824*6185db85Sdougm char *value2; 825*6185db85Sdougm 826*6185db85Sdougm /* remove duplicates from this level */ 827*6185db85Sdougm value1 = sa_get_property_attr(popt, "value"); 828*6185db85Sdougm value2 = sa_get_property_attr(prop, "value"); 829*6185db85Sdougm if (value1 != NULL && value2 != NULL && 830*6185db85Sdougm strcmp(value1, value2) == 0) { 831*6185db85Sdougm /* remove the property from the child */ 832*6185db85Sdougm (void) _sa_remove_property(prop); 833*6185db85Sdougm } 834*6185db85Sdougm if (value1 != NULL) 835*6185db85Sdougm sa_free_attr_string(value1); 836*6185db85Sdougm if (value2 != NULL) 837*6185db85Sdougm sa_free_attr_string(value2); 838*6185db85Sdougm } 839*6185db85Sdougm } 840*6185db85Sdougm } 841*6185db85Sdougm (void) sa_destroy_optionset(localoptions); 842*6185db85Sdougm } 843*6185db85Sdougm } 844*6185db85Sdougm } 845*6185db85Sdougm return (ret); 846*6185db85Sdougm } 847*6185db85Sdougm 848*6185db85Sdougm /* 849*6185db85Sdougm * dfs_free_list(list) 850*6185db85Sdougm * 851*6185db85Sdougm * Free the data in each list entry of the list as well as freeing the 852*6185db85Sdougm * entries themselves. We need to avoid memory leaks and don't want to 853*6185db85Sdougm * dereference any NULL members. 854*6185db85Sdougm */ 855*6185db85Sdougm 856*6185db85Sdougm static void 857*6185db85Sdougm dfs_free_list(xfs_sharelist_t *list) 858*6185db85Sdougm { 859*6185db85Sdougm xfs_sharelist_t *entry; 860*6185db85Sdougm for (entry = list; entry != NULL; entry = list) { 861*6185db85Sdougm if (entry->path != NULL) 862*6185db85Sdougm free(entry->path); 863*6185db85Sdougm if (entry->resource != NULL) 864*6185db85Sdougm free(entry->resource); 865*6185db85Sdougm if (entry->fstype != NULL) 866*6185db85Sdougm free(entry->fstype); 867*6185db85Sdougm if (entry->options != NULL) 868*6185db85Sdougm free(entry->options); 869*6185db85Sdougm if (entry->description != NULL) 870*6185db85Sdougm free(entry->description); 871*6185db85Sdougm if (entry->origline != NULL) 872*6185db85Sdougm free(entry->origline); 873*6185db85Sdougm if (entry->group != NULL) 874*6185db85Sdougm free(entry->group); 875*6185db85Sdougm list = list->next; 876*6185db85Sdougm free(entry); 877*6185db85Sdougm } 878*6185db85Sdougm } 879*6185db85Sdougm 880*6185db85Sdougm /* 881*6185db85Sdougm * parse_dfstab(dfstab, root) 882*6185db85Sdougm * 883*6185db85Sdougm * Open and read the existing dfstab, parsing each line and adding it 884*6185db85Sdougm * to the internal configuration. Make sure syntax errors, etc are 885*6185db85Sdougm * preserved as comments. 886*6185db85Sdougm */ 887*6185db85Sdougm 888*6185db85Sdougm static void 889*6185db85Sdougm parse_dfstab(char *dfstab, xmlNodePtr root) 890*6185db85Sdougm { 891*6185db85Sdougm sa_share_t share; 892*6185db85Sdougm sa_group_t group; 893*6185db85Sdougm sa_group_t sgroup = NULL; 894*6185db85Sdougm sa_group_t defgroup; 895*6185db85Sdougm xfs_sharelist_t *head, *list; 896*6185db85Sdougm int err; 897*6185db85Sdougm int defined_group; 898*6185db85Sdougm FILE *dfs; 899*6185db85Sdougm char *oldprops; 900*6185db85Sdougm 901*6185db85Sdougm /* read the dfstab format file and fill in the doc tree */ 902*6185db85Sdougm 903*6185db85Sdougm dfs = fopen(dfstab, "r"); 904*6185db85Sdougm if (dfs == NULL) { 905*6185db85Sdougm return; 906*6185db85Sdougm } 907*6185db85Sdougm 908*6185db85Sdougm defgroup = sa_get_group("default"); 909*6185db85Sdougm 910*6185db85Sdougm for (head = list = getdfstab(dfs); 911*6185db85Sdougm list != NULL; 912*6185db85Sdougm list = list->next) { 913*6185db85Sdougm share = NULL; 914*6185db85Sdougm group = NULL; 915*6185db85Sdougm defined_group = 0; 916*6185db85Sdougm err = 0; 917*6185db85Sdougm 918*6185db85Sdougm if (list->origline == NULL) { 919*6185db85Sdougm /* 920*6185db85Sdougm * Comment line that we will likely skip. 921*6185db85Sdougm * If the line has the syntax: 922*6185db85Sdougm * # error: string: string 923*6185db85Sdougm * It should be preserved until manually deleted. 924*6185db85Sdougm */ 925*6185db85Sdougm if (list->description != NULL && 926*6185db85Sdougm strncmp(list->description, "# Error: ", 9) == 0) { 927*6185db85Sdougm char *line; 928*6185db85Sdougm char *error; 929*6185db85Sdougm char *cmd; 930*6185db85Sdougm line = strdup(list->description); 931*6185db85Sdougm if (line != NULL) { 932*6185db85Sdougm error = line + 9; 933*6185db85Sdougm cmd = strchr(error, ':'); 934*6185db85Sdougm if (cmd != NULL) { 935*6185db85Sdougm int len; 936*6185db85Sdougm *cmd = '\0'; 937*6185db85Sdougm cmd += 2; 938*6185db85Sdougm len = strlen(cmd); 939*6185db85Sdougm cmd[len - 1] = '\0'; 940*6185db85Sdougm add_syntax_comment(root, cmd, error, 0); 941*6185db85Sdougm } 942*6185db85Sdougm free(line); 943*6185db85Sdougm } 944*6185db85Sdougm } 945*6185db85Sdougm continue; 946*6185db85Sdougm } 947*6185db85Sdougm if (list->path != NULL && strlen(list->path) > 0 && 948*6185db85Sdougm *list->path == '/') { 949*6185db85Sdougm share = sa_find_share(list->path); 950*6185db85Sdougm if (share != NULL) 951*6185db85Sdougm sgroup = sa_get_parent_group(share); 952*6185db85Sdougm else 953*6185db85Sdougm sgroup = NULL; 954*6185db85Sdougm } else { 955*6185db85Sdougm (void) printf(gettext("No share specified in dfstab: " 956*6185db85Sdougm "line %d: %s\n"), 957*6185db85Sdougm list->lineno, list->origline); 958*6185db85Sdougm add_syntax_comment(root, list->origline, 959*6185db85Sdougm gettext("No share specified"), 960*6185db85Sdougm 1); 961*6185db85Sdougm continue; 962*6185db85Sdougm } 963*6185db85Sdougm if (list->group != NULL && strlen(list->group) > 0) { 964*6185db85Sdougm group = sa_get_group(list->group); 965*6185db85Sdougm defined_group = 1; 966*6185db85Sdougm } else { 967*6185db85Sdougm group = defgroup; 968*6185db85Sdougm } 969*6185db85Sdougm if (defined_group && group == NULL) { 970*6185db85Sdougm (void) printf(gettext("Unknown group used in dfstab: " 971*6185db85Sdougm "line %d: %s\n"), 972*6185db85Sdougm list->lineno, list->origline); 973*6185db85Sdougm add_syntax_comment(root, list->origline, 974*6185db85Sdougm gettext("Unknown group specified"), 1); 975*6185db85Sdougm continue; 976*6185db85Sdougm } 977*6185db85Sdougm if (group != NULL) { 978*6185db85Sdougm if (share == NULL) { 979*6185db85Sdougm if (!defined_group && group == defgroup) { 980*6185db85Sdougm /* this is an OK add for legacy */ 981*6185db85Sdougm share = sa_add_share(defgroup, list->path, 982*6185db85Sdougm SA_SHARE_PERMANENT | SA_SHARE_PARSER, 983*6185db85Sdougm &err); 984*6185db85Sdougm if (share != NULL) { 985*6185db85Sdougm if (list->description != NULL && 986*6185db85Sdougm strlen(list->description) > 0) 987*6185db85Sdougm (void) sa_set_share_description(share, 988*6185db85Sdougm list->description); 989*6185db85Sdougm if (list->options != NULL && 990*6185db85Sdougm strlen(list->options) > 0) { 991*6185db85Sdougm (void) sa_parse_legacy_options(share, 992*6185db85Sdougm list->options, 993*6185db85Sdougm list->fstype); 994*6185db85Sdougm } 995*6185db85Sdougm if (list->resource != NULL) 996*6185db85Sdougm (void) sa_set_share_attr(share, "resource", 997*6185db85Sdougm list->resource); 998*6185db85Sdougm } else { 999*6185db85Sdougm (void) printf(gettext("Error in dfstab: " 1000*6185db85Sdougm "line %d: %s\n"), 1001*6185db85Sdougm list->lineno, list->origline); 1002*6185db85Sdougm if (err != SA_BAD_PATH) 1003*6185db85Sdougm add_syntax_comment(root, list->origline, 1004*6185db85Sdougm gettext("Syntax"), 1); 1005*6185db85Sdougm else 1006*6185db85Sdougm add_syntax_comment(root, list->origline, 1007*6185db85Sdougm gettext("Path"), 1); 1008*6185db85Sdougm continue; 1009*6185db85Sdougm } 1010*6185db85Sdougm } 1011*6185db85Sdougm } else { 1012*6185db85Sdougm if (group != sgroup) { 1013*6185db85Sdougm (void) printf(gettext("Attempt to change" 1014*6185db85Sdougm "configuration in" 1015*6185db85Sdougm "dfstab: line %d: %s\n"), 1016*6185db85Sdougm list->lineno, list->origline); 1017*6185db85Sdougm add_syntax_comment(root, list->origline, 1018*6185db85Sdougm gettext("Attempt to change configuration"), 1); 1019*6185db85Sdougm continue; 1020*6185db85Sdougm } 1021*6185db85Sdougm /* its the same group but could have changed options */ 1022*6185db85Sdougm oldprops = sa_proto_legacy_format(list->fstype, share, 0); 1023*6185db85Sdougm if (oldprops != NULL) { 1024*6185db85Sdougm if (list->options != NULL && 1025*6185db85Sdougm strcmp(oldprops, list->options) != 0) { 1026*6185db85Sdougm sa_optionset_t opts; 1027*6185db85Sdougm sa_security_t secs; 1028*6185db85Sdougm /* possibly different values */ 1029*6185db85Sdougm opts = sa_get_optionset((sa_group_t)share, 1030*6185db85Sdougm list->fstype); 1031*6185db85Sdougm (void) sa_destroy_optionset(opts); 1032*6185db85Sdougm for (secs = sa_get_security((sa_group_t)share, 1033*6185db85Sdougm NULL, list->fstype); 1034*6185db85Sdougm secs != NULL; 1035*6185db85Sdougm secs = sa_get_security((sa_group_t)share, 1036*6185db85Sdougm NULL, list->fstype)) { 1037*6185db85Sdougm (void) sa_destroy_security(secs); 1038*6185db85Sdougm } 1039*6185db85Sdougm (void) sa_parse_legacy_options(share, 1040*6185db85Sdougm list->options, 1041*6185db85Sdougm list->fstype); 1042*6185db85Sdougm } 1043*6185db85Sdougm } 1044*6185db85Sdougm } 1045*6185db85Sdougm } else { 1046*6185db85Sdougm /* shouldn't happen */ 1047*6185db85Sdougm err = SA_CONFIG_ERR; 1048*6185db85Sdougm } 1049*6185db85Sdougm 1050*6185db85Sdougm } 1051*6185db85Sdougm dfs_free_list(head); 1052*6185db85Sdougm } 1053*6185db85Sdougm 1054*6185db85Sdougm /* 1055*6185db85Sdougm * legacy_removes(group, file) 1056*6185db85Sdougm * 1057*6185db85Sdougm * Find any shares that are "missing" from the legacy file. These 1058*6185db85Sdougm * should be removed from the configuration since they are likely from 1059*6185db85Sdougm * a legacy app or the admin modified the dfstab file directly. We 1060*6185db85Sdougm * have to support this even if it is not the recommended way to do 1061*6185db85Sdougm * things. 1062*6185db85Sdougm */ 1063*6185db85Sdougm 1064*6185db85Sdougm static void 1065*6185db85Sdougm legacy_removes(sa_group_t group, char *file) 1066*6185db85Sdougm { 1067*6185db85Sdougm sa_share_t share; 1068*6185db85Sdougm char *path; 1069*6185db85Sdougm xfs_sharelist_t *list, *item; 1070*6185db85Sdougm FILE *dfstab; 1071*6185db85Sdougm 1072*6185db85Sdougm dfstab = fopen(file, "r"); 1073*6185db85Sdougm if (dfstab != NULL) { 1074*6185db85Sdougm list = getdfstab(dfstab); 1075*6185db85Sdougm (void) fclose(dfstab); 1076*6185db85Sdougm for (share = sa_get_share(group, NULL); share != NULL; 1077*6185db85Sdougm share = sa_get_next_share(share)) { 1078*6185db85Sdougm /* now see if the share is in the dfstab file */ 1079*6185db85Sdougm path = sa_get_share_attr(share, "path"); 1080*6185db85Sdougm if (path != NULL) { 1081*6185db85Sdougm item = finddfsentry(list, path); 1082*6185db85Sdougm if (item == NULL) { 1083*6185db85Sdougm /* the share was removed this way */ 1084*6185db85Sdougm (void) sa_remove_share(share); 1085*6185db85Sdougm /* start over since the list was broken */ 1086*6185db85Sdougm share = sa_get_share(group, NULL); 1087*6185db85Sdougm } 1088*6185db85Sdougm sa_free_attr_string(path); 1089*6185db85Sdougm } 1090*6185db85Sdougm } 1091*6185db85Sdougm if (list != NULL) 1092*6185db85Sdougm dfs_free_list(list); 1093*6185db85Sdougm } 1094*6185db85Sdougm } 1095*6185db85Sdougm 1096*6185db85Sdougm /* 1097*6185db85Sdougm * getlegacyconfig(path, root) 1098*6185db85Sdougm * 1099*6185db85Sdougm * Parse dfstab and build the legacy configuration. This only gets 1100*6185db85Sdougm * called when a change was detected. 1101*6185db85Sdougm */ 1102*6185db85Sdougm 1103*6185db85Sdougm void 1104*6185db85Sdougm getlegacyconfig(char *path, xmlNodePtr *root) 1105*6185db85Sdougm { 1106*6185db85Sdougm sa_group_t defgroup; 1107*6185db85Sdougm 1108*6185db85Sdougm if (root != NULL) { 1109*6185db85Sdougm if (*root == NULL) 1110*6185db85Sdougm *root = xmlNewNode(NULL, (xmlChar *)"sharecfg"); 1111*6185db85Sdougm if (*root != NULL) { 1112*6185db85Sdougm if (strcmp(path, SA_LEGACY_DFSTAB) == 0) { 1113*6185db85Sdougm /* 1114*6185db85Sdougm * walk the default shares and find anything 1115*6185db85Sdougm * missing. we do this first to make sure it 1116*6185db85Sdougm * is cleaned up since there may be legacy 1117*6185db85Sdougm * code add/del via dfstab and we need to 1118*6185db85Sdougm * cleanup SMF. 1119*6185db85Sdougm */ 1120*6185db85Sdougm defgroup = sa_get_group("default"); 1121*6185db85Sdougm if (defgroup != NULL) { 1122*6185db85Sdougm legacy_removes(defgroup, path); 1123*6185db85Sdougm } 1124*6185db85Sdougm /* parse the dfstab and add anything new */ 1125*6185db85Sdougm parse_dfstab(path, *root); 1126*6185db85Sdougm } 1127*6185db85Sdougm } 1128*6185db85Sdougm } 1129*6185db85Sdougm } 1130*6185db85Sdougm 1131*6185db85Sdougm /* 1132*6185db85Sdougm * parse_sharetab(void) 1133*6185db85Sdougm * 1134*6185db85Sdougm * Read the /etc/dfs/sharetab file via libfsmgt and see which entries 1135*6185db85Sdougm * don't exist in the repository. These shares are marked transient. 1136*6185db85Sdougm * We also need to see if they are ZFS shares since ZFS bypasses the 1137*6185db85Sdougm * SMF repository. 1138*6185db85Sdougm */ 1139*6185db85Sdougm 1140*6185db85Sdougm int 1141*6185db85Sdougm parse_sharetab(void) 1142*6185db85Sdougm { 1143*6185db85Sdougm fs_sharelist_t *list, *tmplist; 1144*6185db85Sdougm int err = 0; 1145*6185db85Sdougm sa_share_t share; 1146*6185db85Sdougm sa_group_t group; 1147*6185db85Sdougm sa_group_t lgroup; 1148*6185db85Sdougm char *groupname; 1149*6185db85Sdougm int legacy = 0; 1150*6185db85Sdougm 1151*6185db85Sdougm list = fs_get_share_list(&err); 1152*6185db85Sdougm if (list == NULL) 1153*6185db85Sdougm return (legacy); 1154*6185db85Sdougm 1155*6185db85Sdougm lgroup = sa_get_group("default"); 1156*6185db85Sdougm 1157*6185db85Sdougm for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) { 1158*6185db85Sdougm group = NULL; 1159*6185db85Sdougm share = sa_find_share(tmplist->path); 1160*6185db85Sdougm if (share == NULL) { 1161*6185db85Sdougm /* 1162*6185db85Sdougm * this share is transient so needs to be 1163*6185db85Sdougm * added. Initially, this will be under 1164*6185db85Sdougm * default(legacy) unless it is a ZFS 1165*6185db85Sdougm * share. If zfs, we need a zfs group. 1166*6185db85Sdougm */ 1167*6185db85Sdougm if (tmplist->resource != NULL && 1168*6185db85Sdougm (groupname = strchr(tmplist->resource, '@')) != NULL) { 1169*6185db85Sdougm /* there is a defined group */ 1170*6185db85Sdougm *groupname++ = '\0'; 1171*6185db85Sdougm group = sa_get_group(groupname); 1172*6185db85Sdougm if (group != NULL) { 1173*6185db85Sdougm share = _sa_add_share(group, tmplist->path, 1174*6185db85Sdougm SA_SHARE_TRANSIENT, &err); 1175*6185db85Sdougm } else { 1176*6185db85Sdougm (void) printf(gettext("Group for temporary share" 1177*6185db85Sdougm "not found: %s\n"), 1178*6185db85Sdougm tmplist->path); 1179*6185db85Sdougm share = _sa_add_share(lgroup, tmplist->path, 1180*6185db85Sdougm SA_SHARE_TRANSIENT, &err); 1181*6185db85Sdougm } 1182*6185db85Sdougm } else { 1183*6185db85Sdougm if (sa_zfs_is_shared(tmplist->path)) { 1184*6185db85Sdougm group = sa_get_group("zfs"); 1185*6185db85Sdougm if (group == NULL) { 1186*6185db85Sdougm group = sa_create_group("zfs", &err); 1187*6185db85Sdougm if (group == NULL && err == SA_NO_PERMISSION) { 1188*6185db85Sdougm group = _sa_create_group("zfs"); 1189*6185db85Sdougm } 1190*6185db85Sdougm if (group != NULL) { 1191*6185db85Sdougm (void) sa_create_optionset(group, 1192*6185db85Sdougm tmplist->fstype); 1193*6185db85Sdougm (void) sa_set_group_attr(group, "zfs", "true"); 1194*6185db85Sdougm } 1195*6185db85Sdougm } 1196*6185db85Sdougm if (group != NULL) { 1197*6185db85Sdougm share = _sa_add_share(group, tmplist->path, 1198*6185db85Sdougm SA_SHARE_TRANSIENT, &err); 1199*6185db85Sdougm } 1200*6185db85Sdougm } else { 1201*6185db85Sdougm share = _sa_add_share(lgroup, tmplist->path, 1202*6185db85Sdougm SA_SHARE_TRANSIENT, &err); 1203*6185db85Sdougm } 1204*6185db85Sdougm } 1205*6185db85Sdougm if (share == NULL) 1206*6185db85Sdougm (void) printf(gettext("Problem with transient: %s\n"), 1207*6185db85Sdougm sa_errorstr(err)); 1208*6185db85Sdougm if (share != NULL) 1209*6185db85Sdougm set_node_attr(share, "shared", "true"); 1210*6185db85Sdougm 1211*6185db85Sdougm if (err == SA_OK) { 1212*6185db85Sdougm if (tmplist->options != NULL && 1213*6185db85Sdougm strlen(tmplist->options) > 0) { 1214*6185db85Sdougm (void) sa_parse_legacy_options(share, 1215*6185db85Sdougm tmplist->options, 1216*6185db85Sdougm tmplist->fstype); 1217*6185db85Sdougm } 1218*6185db85Sdougm if (tmplist->resource != NULL && 1219*6185db85Sdougm strcmp(tmplist->resource, "-") != 0) 1220*6185db85Sdougm set_node_attr(share, "resource", tmplist->resource); 1221*6185db85Sdougm if (tmplist->description != NULL) { 1222*6185db85Sdougm xmlNodePtr node; 1223*6185db85Sdougm node = xmlNewChild((xmlNodePtr)share, NULL, 1224*6185db85Sdougm (xmlChar *)"description", NULL); 1225*6185db85Sdougm xmlNodeSetContent(node, 1226*6185db85Sdougm (xmlChar *)tmplist->description); 1227*6185db85Sdougm } 1228*6185db85Sdougm legacy = 1; 1229*6185db85Sdougm } 1230*6185db85Sdougm } else { 1231*6185db85Sdougm /* 1232*6185db85Sdougm * if this is a legacy share, mark as shared so we 1233*6185db85Sdougm * only update sharetab appropriately. 1234*6185db85Sdougm */ 1235*6185db85Sdougm set_node_attr(share, "shared", "true"); 1236*6185db85Sdougm } 1237*6185db85Sdougm } 1238*6185db85Sdougm fs_free_share_list(list); 1239*6185db85Sdougm return (legacy); 1240*6185db85Sdougm } 1241*6185db85Sdougm 1242*6185db85Sdougm /* 1243*6185db85Sdougm * get the transient shares from the sharetab (or other) file. since 1244*6185db85Sdougm * these are transient, they only appear in the working file and not 1245*6185db85Sdougm * in a repository. 1246*6185db85Sdougm */ 1247*6185db85Sdougm int 1248*6185db85Sdougm gettransients(xmlNodePtr *root) 1249*6185db85Sdougm { 1250*6185db85Sdougm int legacy = 0; 1251*6185db85Sdougm 1252*6185db85Sdougm if (root != NULL) { 1253*6185db85Sdougm if (*root == NULL) 1254*6185db85Sdougm *root = xmlNewNode(NULL, (xmlChar *)"sharecfg"); 1255*6185db85Sdougm if (*root != NULL) { 1256*6185db85Sdougm legacy = parse_sharetab(); 1257*6185db85Sdougm } 1258*6185db85Sdougm } 1259*6185db85Sdougm return (legacy); 1260*6185db85Sdougm } 1261*6185db85Sdougm 1262*6185db85Sdougm /* 1263*6185db85Sdougm * sa_has_prop(optionset, prop) 1264*6185db85Sdougm * 1265*6185db85Sdougm * Is the specified property a member of the optionset? 1266*6185db85Sdougm */ 1267*6185db85Sdougm 1268*6185db85Sdougm int 1269*6185db85Sdougm sa_has_prop(sa_optionset_t optionset, sa_property_t prop) 1270*6185db85Sdougm { 1271*6185db85Sdougm char *name; 1272*6185db85Sdougm sa_property_t otherprop; 1273*6185db85Sdougm int result = 0; 1274*6185db85Sdougm 1275*6185db85Sdougm if (optionset != NULL) { 1276*6185db85Sdougm name = sa_get_property_attr(prop, "type"); 1277*6185db85Sdougm if (name != NULL) { 1278*6185db85Sdougm otherprop = sa_get_property(optionset, name); 1279*6185db85Sdougm if (otherprop != NULL) 1280*6185db85Sdougm result = 1; 1281*6185db85Sdougm sa_free_attr_string(name); 1282*6185db85Sdougm } 1283*6185db85Sdougm } 1284*6185db85Sdougm return (result); 1285*6185db85Sdougm } 1286*6185db85Sdougm 1287*6185db85Sdougm /* 1288*6185db85Sdougm * Update legacy files 1289*6185db85Sdougm * 1290*6185db85Sdougm * Provides functions to add/remove/modify individual entries 1291*6185db85Sdougm * in dfstab and sharetab 1292*6185db85Sdougm */ 1293*6185db85Sdougm 1294*6185db85Sdougm void 1295*6185db85Sdougm update_legacy_config(void) 1296*6185db85Sdougm { 1297*6185db85Sdougm /* 1298*6185db85Sdougm * no longer used -- this is a placeholder in case we need to 1299*6185db85Sdougm * add it back later. 1300*6185db85Sdougm */ 1301*6185db85Sdougm } 1302*6185db85Sdougm 1303*6185db85Sdougm /* 1304*6185db85Sdougm * sa_valid_property(object, proto, property) 1305*6185db85Sdougm * 1306*6185db85Sdougm * check to see if the specified property is valid relative to the 1307*6185db85Sdougm * specified protocol. The protocol plugin is called to do the work. 1308*6185db85Sdougm */ 1309*6185db85Sdougm 1310*6185db85Sdougm int 1311*6185db85Sdougm sa_valid_property(void *object, char *proto, sa_property_t property) 1312*6185db85Sdougm { 1313*6185db85Sdougm int ret = SA_OK; 1314*6185db85Sdougm 1315*6185db85Sdougm if (proto != NULL && property != NULL) { 1316*6185db85Sdougm ret = sa_proto_valid_prop(proto, property, object); 1317*6185db85Sdougm } 1318*6185db85Sdougm 1319*6185db85Sdougm return (ret); 1320*6185db85Sdougm } 1321*6185db85Sdougm 1322*6185db85Sdougm /* 1323*6185db85Sdougm * sa_fstype(path) 1324*6185db85Sdougm * 1325*6185db85Sdougm * Given path, return the string representing the path's file system 1326*6185db85Sdougm * type. This is used to discover ZFS shares. 1327*6185db85Sdougm */ 1328*6185db85Sdougm 1329*6185db85Sdougm char * 1330*6185db85Sdougm sa_fstype(char *path) 1331*6185db85Sdougm { 1332*6185db85Sdougm int err; 1333*6185db85Sdougm struct stat st; 1334*6185db85Sdougm 1335*6185db85Sdougm err = stat(path, &st); 1336*6185db85Sdougm if (err < 0) { 1337*6185db85Sdougm err = SA_NO_SUCH_PATH; 1338*6185db85Sdougm } else { 1339*6185db85Sdougm err = SA_OK; 1340*6185db85Sdougm } 1341*6185db85Sdougm if (err == SA_OK) { 1342*6185db85Sdougm /* have a valid path at this point */ 1343*6185db85Sdougm return (strdup(st.st_fstype)); 1344*6185db85Sdougm } 1345*6185db85Sdougm return (NULL); 1346*6185db85Sdougm } 1347*6185db85Sdougm 1348*6185db85Sdougm void 1349*6185db85Sdougm sa_free_fstype(char *type) 1350*6185db85Sdougm { 1351*6185db85Sdougm free(type); 1352*6185db85Sdougm } 1353*6185db85Sdougm 1354*6185db85Sdougm /* 1355*6185db85Sdougm * sa_get_derived_optionset(object, proto, hier) 1356*6185db85Sdougm * 1357*6185db85Sdougm * Work backward to the top of the share object tree and start 1358*6185db85Sdougm * copying protocol specific optionsets into a newly created 1359*6185db85Sdougm * optionset that doesn't have a parent (it will be freed 1360*6185db85Sdougm * later). This provides for the property inheritence model. That 1361*6185db85Sdougm * is, properties closer to the share take precedence over group 1362*6185db85Sdougm * level. This also provides for groups of groups in the future. 1363*6185db85Sdougm */ 1364*6185db85Sdougm 1365*6185db85Sdougm sa_optionset_t 1366*6185db85Sdougm sa_get_derived_optionset(void *object, char *proto, int hier) 1367*6185db85Sdougm { 1368*6185db85Sdougm sa_optionset_t newoptionset; 1369*6185db85Sdougm sa_optionset_t optionset; 1370*6185db85Sdougm sa_group_t group; 1371*6185db85Sdougm 1372*6185db85Sdougm if (hier && 1373*6185db85Sdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) { 1374*6185db85Sdougm newoptionset = sa_get_derived_optionset((void *)group, proto, hier); 1375*6185db85Sdougm } else { 1376*6185db85Sdougm newoptionset = (sa_optionset_t)xmlNewNode(NULL, 1377*6185db85Sdougm (xmlChar *)"optionset"); 1378*6185db85Sdougm if (newoptionset != NULL) { 1379*6185db85Sdougm sa_set_optionset_attr(newoptionset, "type", proto); 1380*6185db85Sdougm } 1381*6185db85Sdougm } 1382*6185db85Sdougm /* dont' do anything if memory wasn't allocated */ 1383*6185db85Sdougm if (newoptionset == NULL) 1384*6185db85Sdougm return (NULL); 1385*6185db85Sdougm 1386*6185db85Sdougm /* found the top so working back down the stack */ 1387*6185db85Sdougm optionset = sa_get_optionset((sa_optionset_t)object, proto); 1388*6185db85Sdougm if (optionset != NULL) { 1389*6185db85Sdougm sa_property_t prop; 1390*6185db85Sdougm /* add optionset to the newoptionset */ 1391*6185db85Sdougm for (prop = sa_get_property(optionset, NULL); 1392*6185db85Sdougm prop != NULL; prop = sa_get_next_property(prop)) { 1393*6185db85Sdougm sa_property_t newprop; 1394*6185db85Sdougm char *name; 1395*6185db85Sdougm char *value; 1396*6185db85Sdougm name = sa_get_property_attr(prop, "type"); 1397*6185db85Sdougm value = sa_get_property_attr(prop, "value"); 1398*6185db85Sdougm if (name != NULL) { 1399*6185db85Sdougm newprop = sa_get_property(newoptionset, name); 1400*6185db85Sdougm /* replace the value with the new value */ 1401*6185db85Sdougm if (newprop != NULL) { 1402*6185db85Sdougm /* 1403*6185db85Sdougm * only set if value is non NULL, old value ok 1404*6185db85Sdougm * if it is NULL. 1405*6185db85Sdougm */ 1406*6185db85Sdougm if (value != NULL) 1407*6185db85Sdougm set_node_attr(newprop, "value", value); 1408*6185db85Sdougm } else { 1409*6185db85Sdougm /* an entirely new property */ 1410*6185db85Sdougm if (value != NULL) { 1411*6185db85Sdougm newprop = sa_create_property(name, value); 1412*6185db85Sdougm if (newprop != NULL) { 1413*6185db85Sdougm newprop = (sa_property_t) 1414*6185db85Sdougm xmlAddChild((xmlNodePtr)newoptionset, 1415*6185db85Sdougm (xmlNodePtr)newprop); 1416*6185db85Sdougm } 1417*6185db85Sdougm } 1418*6185db85Sdougm } 1419*6185db85Sdougm sa_free_attr_string(name); 1420*6185db85Sdougm } 1421*6185db85Sdougm if (value != NULL) 1422*6185db85Sdougm sa_free_attr_string(value); 1423*6185db85Sdougm } 1424*6185db85Sdougm } 1425*6185db85Sdougm return (newoptionset); 1426*6185db85Sdougm } 1427*6185db85Sdougm 1428*6185db85Sdougm void 1429*6185db85Sdougm sa_free_derived_optionset(sa_optionset_t optionset) 1430*6185db85Sdougm { 1431*6185db85Sdougm /* while it shouldn't be linked, it doesn't hurt */ 1432*6185db85Sdougm if (optionset != NULL) { 1433*6185db85Sdougm xmlUnlinkNode((xmlNodePtr) optionset); 1434*6185db85Sdougm xmlFreeNode((xmlNodePtr) optionset); 1435*6185db85Sdougm } 1436*6185db85Sdougm } 1437*6185db85Sdougm 1438*6185db85Sdougm /* 1439*6185db85Sdougm * sa_get_all_security_types(object, proto, hier) 1440*6185db85Sdougm * 1441*6185db85Sdougm * find all the security types set for this object. This is 1442*6185db85Sdougm * preliminary to getting a derived security set. The return value is an 1443*6185db85Sdougm * optionset containg properties which are the sectype values found by 1444*6185db85Sdougm * walking up the XML document struture. The returned optionset 1445*6185db85Sdougm * is a derived optionset. 1446*6185db85Sdougm * 1447*6185db85Sdougm * If hier is 0, only look at object. If non-zero, walk up the tree. 1448*6185db85Sdougm */ 1449*6185db85Sdougm sa_optionset_t 1450*6185db85Sdougm sa_get_all_security_types(void *object, char *proto, int hier) 1451*6185db85Sdougm { 1452*6185db85Sdougm sa_optionset_t options; 1453*6185db85Sdougm sa_security_t security; 1454*6185db85Sdougm sa_group_t group; 1455*6185db85Sdougm sa_property_t prop; 1456*6185db85Sdougm 1457*6185db85Sdougm options = NULL; 1458*6185db85Sdougm 1459*6185db85Sdougm if (hier && 1460*6185db85Sdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) { 1461*6185db85Sdougm options = sa_get_all_security_types((void *)group, proto, hier); 1462*6185db85Sdougm } else { 1463*6185db85Sdougm options = (sa_optionset_t)xmlNewNode(NULL, 1464*6185db85Sdougm (xmlChar *)"optionset"); 1465*6185db85Sdougm } 1466*6185db85Sdougm /* hit the top so collect the security types working back */ 1467*6185db85Sdougm if (options != NULL) { 1468*6185db85Sdougm for (security = sa_get_security((sa_group_t)object, NULL, NULL); 1469*6185db85Sdougm security != NULL; security = sa_get_next_security(security)) { 1470*6185db85Sdougm char *type; 1471*6185db85Sdougm char *sectype; 1472*6185db85Sdougm 1473*6185db85Sdougm type = sa_get_security_attr(security, "type"); 1474*6185db85Sdougm if (type != NULL) { 1475*6185db85Sdougm if (strcmp(type, proto) != 0) { 1476*6185db85Sdougm sa_free_attr_string(type); 1477*6185db85Sdougm continue; 1478*6185db85Sdougm } 1479*6185db85Sdougm sectype = sa_get_security_attr(security, "sectype"); 1480*6185db85Sdougm if (sectype != NULL) { 1481*6185db85Sdougm /* 1482*6185db85Sdougm * have a security type, check to see if 1483*6185db85Sdougm * already present in optionset and add if it 1484*6185db85Sdougm * isn't. 1485*6185db85Sdougm */ 1486*6185db85Sdougm if (sa_get_property(options, sectype) == NULL) { 1487*6185db85Sdougm prop = sa_create_property(sectype, "true"); 1488*6185db85Sdougm if (prop != NULL) 1489*6185db85Sdougm prop = (sa_property_t) 1490*6185db85Sdougm xmlAddChild((xmlNodePtr)options, 1491*6185db85Sdougm (xmlNodePtr)prop); 1492*6185db85Sdougm } 1493*6185db85Sdougm sa_free_attr_string(sectype); 1494*6185db85Sdougm } 1495*6185db85Sdougm sa_free_attr_string(type); 1496*6185db85Sdougm } 1497*6185db85Sdougm } 1498*6185db85Sdougm } 1499*6185db85Sdougm return (options); 1500*6185db85Sdougm } 1501*6185db85Sdougm 1502*6185db85Sdougm /* 1503*6185db85Sdougm * sa_get_derived_security(object, sectype, proto, hier) 1504*6185db85Sdougm * 1505*6185db85Sdougm * Get the derived security(named optionset) for the object given the 1506*6185db85Sdougm * sectype and proto. If hier is non-zero, walk up the tree to get all 1507*6185db85Sdougm * properties defined for this object, otherwise just those on the 1508*6185db85Sdougm * object. 1509*6185db85Sdougm */ 1510*6185db85Sdougm 1511*6185db85Sdougm sa_security_t 1512*6185db85Sdougm sa_get_derived_security(void *object, char *sectype, char *proto, int hier) 1513*6185db85Sdougm { 1514*6185db85Sdougm sa_security_t newsecurity; 1515*6185db85Sdougm sa_security_t security; 1516*6185db85Sdougm sa_group_t group; 1517*6185db85Sdougm 1518*6185db85Sdougm if (hier && 1519*6185db85Sdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) { 1520*6185db85Sdougm newsecurity = sa_get_derived_security((void *)group, 1521*6185db85Sdougm sectype, proto, hier); 1522*6185db85Sdougm } else { 1523*6185db85Sdougm newsecurity = (sa_security_t)xmlNewNode(NULL, 1524*6185db85Sdougm (xmlChar *)"security"); 1525*6185db85Sdougm if (newsecurity != NULL) { 1526*6185db85Sdougm sa_set_security_attr(newsecurity, "type", proto); 1527*6185db85Sdougm sa_set_security_attr(newsecurity, "sectype", sectype); 1528*6185db85Sdougm } 1529*6185db85Sdougm } 1530*6185db85Sdougm /* dont' do anything if memory wasn't allocated */ 1531*6185db85Sdougm if (newsecurity == NULL) 1532*6185db85Sdougm return (NULL); 1533*6185db85Sdougm 1534*6185db85Sdougm /* found the top so working back down the stack */ 1535*6185db85Sdougm security = sa_get_security((sa_security_t)object, sectype, proto); 1536*6185db85Sdougm if (security != NULL) { 1537*6185db85Sdougm sa_property_t prop; 1538*6185db85Sdougm /* add security to the newsecurity */ 1539*6185db85Sdougm for (prop = sa_get_property(security, NULL); 1540*6185db85Sdougm prop != NULL; prop = sa_get_next_property(prop)) { 1541*6185db85Sdougm sa_property_t newprop; 1542*6185db85Sdougm char *name; 1543*6185db85Sdougm char *value; 1544*6185db85Sdougm name = sa_get_property_attr(prop, "type"); 1545*6185db85Sdougm value = sa_get_property_attr(prop, "value"); 1546*6185db85Sdougm if (name != NULL) { 1547*6185db85Sdougm newprop = sa_get_property(newsecurity, name); 1548*6185db85Sdougm /* replace the value with the new value */ 1549*6185db85Sdougm if (newprop != NULL) { 1550*6185db85Sdougm /* 1551*6185db85Sdougm * only set if value is non NULL, old value ok 1552*6185db85Sdougm * if it is NULL. 1553*6185db85Sdougm */ 1554*6185db85Sdougm if (value != NULL) 1555*6185db85Sdougm set_node_attr(newprop, name, value); 1556*6185db85Sdougm } else { 1557*6185db85Sdougm /* an entirely new property */ 1558*6185db85Sdougm if (value != NULL) { 1559*6185db85Sdougm newprop = sa_create_property(name, value); 1560*6185db85Sdougm newprop = (sa_property_t) 1561*6185db85Sdougm xmlAddChild((xmlNodePtr)newsecurity, 1562*6185db85Sdougm (xmlNodePtr)newprop); 1563*6185db85Sdougm } 1564*6185db85Sdougm } 1565*6185db85Sdougm sa_free_attr_string(name); 1566*6185db85Sdougm } 1567*6185db85Sdougm if (value != NULL) 1568*6185db85Sdougm sa_free_attr_string(value); 1569*6185db85Sdougm } 1570*6185db85Sdougm } 1571*6185db85Sdougm return (newsecurity); 1572*6185db85Sdougm } 1573*6185db85Sdougm 1574*6185db85Sdougm void 1575*6185db85Sdougm sa_free_derived_security(sa_security_t security) 1576*6185db85Sdougm { 1577*6185db85Sdougm /* while it shouldn't be linked, it doesn't hurt */ 1578*6185db85Sdougm if (security != NULL) { 1579*6185db85Sdougm xmlUnlinkNode((xmlNodePtr)security); 1580*6185db85Sdougm xmlFreeNode((xmlNodePtr)security); 1581*6185db85Sdougm } 1582*6185db85Sdougm } 1583*6185db85Sdougm 1584*6185db85Sdougm /* 1585*6185db85Sdougm * sharetab utility functions 1586*6185db85Sdougm * 1587*6185db85Sdougm * makes use of the original sharetab.c from fs.d/nfs/lib 1588*6185db85Sdougm */ 1589*6185db85Sdougm 1590*6185db85Sdougm /* 1591*6185db85Sdougm * fillshare(share, proto, sh) 1592*6185db85Sdougm * 1593*6185db85Sdougm * Fill the struct share with values obtained from the share object. 1594*6185db85Sdougm */ 1595*6185db85Sdougm static void 1596*6185db85Sdougm fillshare(sa_share_t share, char *proto, struct share *sh) 1597*6185db85Sdougm { 1598*6185db85Sdougm char *groupname = NULL; 1599*6185db85Sdougm char *value; 1600*6185db85Sdougm sa_group_t group; 1601*6185db85Sdougm char *buff; 1602*6185db85Sdougm char *zfs; 1603*6185db85Sdougm 1604*6185db85Sdougm group = sa_get_parent_group(share); 1605*6185db85Sdougm if (group != NULL) { 1606*6185db85Sdougm zfs = sa_get_group_attr(group, "zfs"); 1607*6185db85Sdougm groupname = sa_get_group_attr(group, "name"); 1608*6185db85Sdougm 1609*6185db85Sdougm if (groupname != NULL && 1610*6185db85Sdougm (strcmp(groupname, "default") == 0 || zfs != NULL)) { 1611*6185db85Sdougm /* 1612*6185db85Sdougm * since the groupname is either "default" or the 1613*6185db85Sdougm * group is a ZFS group, we don't want to keep 1614*6185db85Sdougm * groupname. We do want it if it is any other type of 1615*6185db85Sdougm * group. 1616*6185db85Sdougm */ 1617*6185db85Sdougm sa_free_attr_string(groupname); 1618*6185db85Sdougm groupname = NULL; 1619*6185db85Sdougm } 1620*6185db85Sdougm if (zfs != NULL) 1621*6185db85Sdougm sa_free_attr_string(zfs); 1622*6185db85Sdougm } 1623*6185db85Sdougm 1624*6185db85Sdougm value = sa_get_share_attr(share, "path"); 1625*6185db85Sdougm if (value != NULL) { 1626*6185db85Sdougm sh->sh_path = strdup(value); 1627*6185db85Sdougm sa_free_attr_string(value); 1628*6185db85Sdougm } 1629*6185db85Sdougm 1630*6185db85Sdougm value = sa_get_share_attr(share, "resource"); 1631*6185db85Sdougm if (value != NULL || groupname != NULL) { 1632*6185db85Sdougm int len = 0; 1633*6185db85Sdougm 1634*6185db85Sdougm if (value != NULL) 1635*6185db85Sdougm len += strlen(value); 1636*6185db85Sdougm if (groupname != NULL) 1637*6185db85Sdougm len += strlen(groupname); 1638*6185db85Sdougm len += 3; /* worst case */ 1639*6185db85Sdougm buff = malloc(len); 1640*6185db85Sdougm (void) snprintf(buff, len, "%s%s%s", 1641*6185db85Sdougm (value != NULL && strlen(value) > 0) ? value : "-", 1642*6185db85Sdougm groupname != NULL ? "@" : "", 1643*6185db85Sdougm groupname != NULL ? groupname : ""); 1644*6185db85Sdougm sh->sh_res = buff; 1645*6185db85Sdougm if (value != NULL) 1646*6185db85Sdougm sa_free_attr_string(value); 1647*6185db85Sdougm if (groupname != NULL) { 1648*6185db85Sdougm sa_free_attr_string(groupname); 1649*6185db85Sdougm groupname = NULL; 1650*6185db85Sdougm } 1651*6185db85Sdougm } else { 1652*6185db85Sdougm sh->sh_res = strdup("-"); 1653*6185db85Sdougm } 1654*6185db85Sdougm 1655*6185db85Sdougm sh->sh_fstype = strdup(proto); 1656*6185db85Sdougm value = sa_proto_legacy_format(proto, share, 1); 1657*6185db85Sdougm if (value != NULL) { 1658*6185db85Sdougm if (strlen(value) > 0) 1659*6185db85Sdougm sh->sh_opts = strdup(value); 1660*6185db85Sdougm else 1661*6185db85Sdougm sh->sh_opts = strdup("rw"); 1662*6185db85Sdougm free(value); 1663*6185db85Sdougm } else 1664*6185db85Sdougm sh->sh_opts = strdup("rw"); 1665*6185db85Sdougm 1666*6185db85Sdougm value = sa_get_share_description(share); 1667*6185db85Sdougm if (value != NULL) { 1668*6185db85Sdougm sh->sh_descr = strdup(value); 1669*6185db85Sdougm sa_free_share_description(value); 1670*6185db85Sdougm } else 1671*6185db85Sdougm sh->sh_descr = strdup(""); 1672*6185db85Sdougm } 1673*6185db85Sdougm 1674*6185db85Sdougm /* 1675*6185db85Sdougm * emptyshare(sh) 1676*6185db85Sdougm * 1677*6185db85Sdougm * Free the strings in the non-NULL members of sh. 1678*6185db85Sdougm */ 1679*6185db85Sdougm 1680*6185db85Sdougm static void 1681*6185db85Sdougm emptyshare(struct share *sh) 1682*6185db85Sdougm { 1683*6185db85Sdougm if (sh->sh_path != NULL) 1684*6185db85Sdougm free(sh->sh_path); 1685*6185db85Sdougm sh->sh_path = NULL; 1686*6185db85Sdougm if (sh->sh_res != NULL) 1687*6185db85Sdougm free(sh->sh_res); 1688*6185db85Sdougm sh->sh_res = NULL; 1689*6185db85Sdougm if (sh->sh_fstype != NULL) 1690*6185db85Sdougm free(sh->sh_fstype); 1691*6185db85Sdougm sh->sh_fstype = NULL; 1692*6185db85Sdougm if (sh->sh_opts != NULL) 1693*6185db85Sdougm free(sh->sh_opts); 1694*6185db85Sdougm sh->sh_opts = NULL; 1695*6185db85Sdougm if (sh->sh_descr != NULL) 1696*6185db85Sdougm free(sh->sh_descr); 1697*6185db85Sdougm sh->sh_descr = NULL; 1698*6185db85Sdougm } 1699*6185db85Sdougm 1700*6185db85Sdougm /* 1701*6185db85Sdougm * sa_update_sharetab(share, proto) 1702*6185db85Sdougm * 1703*6185db85Sdougm * Update the sharetab file with info from the specified share. 1704*6185db85Sdougm * This could be an update or add. 1705*6185db85Sdougm */ 1706*6185db85Sdougm 1707*6185db85Sdougm int 1708*6185db85Sdougm sa_update_sharetab(sa_share_t share, char *proto) 1709*6185db85Sdougm { 1710*6185db85Sdougm int ret = SA_OK; 1711*6185db85Sdougm struct share shtab; 1712*6185db85Sdougm char *path; 1713*6185db85Sdougm int logging = 0; 1714*6185db85Sdougm FILE *sharetab; 1715*6185db85Sdougm sigset_t old, new; 1716*6185db85Sdougm 1717*6185db85Sdougm path = sa_get_share_attr(share, "path"); 1718*6185db85Sdougm if (path != NULL) { 1719*6185db85Sdougm (void) memset(&shtab, '\0', sizeof (shtab)); 1720*6185db85Sdougm sharetab = fopen(SA_LEGACY_SHARETAB, "r+"); 1721*6185db85Sdougm if (sharetab == NULL) { 1722*6185db85Sdougm sharetab = fopen(SA_LEGACY_SHARETAB, "w+"); 1723*6185db85Sdougm } 1724*6185db85Sdougm if (sharetab != NULL) { 1725*6185db85Sdougm (void) setvbuf(sharetab, NULL, _IOLBF, BUFSIZ * 8); 1726*6185db85Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new); 1727*6185db85Sdougm (void) sigaddset(&new, SIGHUP); 1728*6185db85Sdougm (void) sigaddset(&new, SIGINT); 1729*6185db85Sdougm (void) sigaddset(&new, SIGQUIT); 1730*6185db85Sdougm (void) sigaddset(&new, SIGTSTP); 1731*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &new, &old); 1732*6185db85Sdougm (void) lockf(fileno(sharetab), F_LOCK, 0); 1733*6185db85Sdougm (void) remshare(sharetab, path, &logging); 1734*6185db85Sdougm /* fill in share structure and write it out */ 1735*6185db85Sdougm (void) fillshare(share, proto, &shtab); 1736*6185db85Sdougm (void) putshare(sharetab, &shtab); 1737*6185db85Sdougm emptyshare(&shtab); 1738*6185db85Sdougm (void) fflush(sharetab); 1739*6185db85Sdougm (void) lockf(fileno(sharetab), F_ULOCK, 0); 1740*6185db85Sdougm (void) fsync(fileno(sharetab)); 1741*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &old, NULL); 1742*6185db85Sdougm (void) fclose(sharetab); 1743*6185db85Sdougm } else { 1744*6185db85Sdougm if (errno == EACCES || errno == EPERM) { 1745*6185db85Sdougm ret = SA_NO_PERMISSION; 1746*6185db85Sdougm } else { 1747*6185db85Sdougm ret = SA_CONFIG_ERR; 1748*6185db85Sdougm } 1749*6185db85Sdougm } 1750*6185db85Sdougm sa_free_attr_string(path); 1751*6185db85Sdougm } 1752*6185db85Sdougm return (ret); 1753*6185db85Sdougm } 1754*6185db85Sdougm 1755*6185db85Sdougm /* 1756*6185db85Sdougm * sa_delete_sharetab(path, proto) 1757*6185db85Sdougm * 1758*6185db85Sdougm * remove the specified share from sharetab. 1759*6185db85Sdougm */ 1760*6185db85Sdougm 1761*6185db85Sdougm int 1762*6185db85Sdougm sa_delete_sharetab(char *path, char *proto) 1763*6185db85Sdougm { 1764*6185db85Sdougm int ret = SA_OK; 1765*6185db85Sdougm int logging = 0; 1766*6185db85Sdougm FILE *sharetab; 1767*6185db85Sdougm sigset_t old, new; 1768*6185db85Sdougm #ifdef lint 1769*6185db85Sdougm proto = proto; 1770*6185db85Sdougm #endif 1771*6185db85Sdougm 1772*6185db85Sdougm if (path != NULL) { 1773*6185db85Sdougm sharetab = fopen(SA_LEGACY_SHARETAB, "r+"); 1774*6185db85Sdougm if (sharetab == NULL) { 1775*6185db85Sdougm sharetab = fopen(SA_LEGACY_SHARETAB, "w+"); 1776*6185db85Sdougm } 1777*6185db85Sdougm if (sharetab != NULL) { 1778*6185db85Sdougm /* should block keyboard level signals around the lock */ 1779*6185db85Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new); 1780*6185db85Sdougm (void) sigaddset(&new, SIGHUP); 1781*6185db85Sdougm (void) sigaddset(&new, SIGINT); 1782*6185db85Sdougm (void) sigaddset(&new, SIGQUIT); 1783*6185db85Sdougm (void) sigaddset(&new, SIGTSTP); 1784*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &new, &old); 1785*6185db85Sdougm (void) lockf(fileno(sharetab), F_LOCK, 0); 1786*6185db85Sdougm ret = remshare(sharetab, path, &logging); 1787*6185db85Sdougm (void) fflush(sharetab); 1788*6185db85Sdougm (void) lockf(fileno(sharetab), F_ULOCK, 0); 1789*6185db85Sdougm (void) fsync(fileno(sharetab)); 1790*6185db85Sdougm (void) sigprocmask(SIG_SETMASK, &old, NULL); 1791*6185db85Sdougm (void) fclose(sharetab); 1792*6185db85Sdougm } else { 1793*6185db85Sdougm if (errno == EACCES || errno == EPERM) { 1794*6185db85Sdougm ret = SA_NO_PERMISSION; 1795*6185db85Sdougm } else { 1796*6185db85Sdougm ret = SA_CONFIG_ERR; 1797*6185db85Sdougm } 1798*6185db85Sdougm } 1799*6185db85Sdougm } 1800*6185db85Sdougm return (ret); 1801*6185db85Sdougm } 1802