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 #include <sys/types.h> 30*6185db85Sdougm #include <sys/stat.h> 31*6185db85Sdougm #include <fcntl.h> 32*6185db85Sdougm #include <stdlib.h> 33*6185db85Sdougm #include <stdio.h> 34*6185db85Sdougm #include <string.h> 35*6185db85Sdougm #include <ctype.h> 36*6185db85Sdougm #include <unistd.h> 37*6185db85Sdougm #include <getopt.h> 38*6185db85Sdougm #include <utmpx.h> 39*6185db85Sdougm #include <pwd.h> 40*6185db85Sdougm #include <auth_attr.h> 41*6185db85Sdougm #include <secdb.h> 42*6185db85Sdougm #include <sys/param.h> 43*6185db85Sdougm #include <sys/stat.h> 44*6185db85Sdougm #include <errno.h> 45*6185db85Sdougm 46*6185db85Sdougm #include <libshare.h> 47*6185db85Sdougm #include "sharemgr.h" 48*6185db85Sdougm #include <libscf.h> 49*6185db85Sdougm #include <libxml/tree.h> 50*6185db85Sdougm #include <libintl.h> 51*6185db85Sdougm 52*6185db85Sdougm static char *sa_get_usage(sa_usage_t); 53*6185db85Sdougm 54*6185db85Sdougm /* 55*6185db85Sdougm * Implementation of the common sub-commands supported by sharemgr. 56*6185db85Sdougm * A number of helper functions are also included. 57*6185db85Sdougm */ 58*6185db85Sdougm 59*6185db85Sdougm /* 60*6185db85Sdougm * has_protocol(group, proto) 61*6185db85Sdougm * If the group has an optionset with the specified protocol, 62*6185db85Sdougm * return true (1) otherwise false (0). 63*6185db85Sdougm */ 64*6185db85Sdougm static int 65*6185db85Sdougm has_protocol(sa_group_t group, char *protocol) 66*6185db85Sdougm { 67*6185db85Sdougm sa_optionset_t optionset; 68*6185db85Sdougm int result = 0; 69*6185db85Sdougm 70*6185db85Sdougm optionset = sa_get_optionset(group, protocol); 71*6185db85Sdougm if (optionset != NULL) { 72*6185db85Sdougm result++; 73*6185db85Sdougm } 74*6185db85Sdougm return (result); 75*6185db85Sdougm } 76*6185db85Sdougm 77*6185db85Sdougm /* 78*6185db85Sdougm * add_list(list, item) 79*6185db85Sdougm * Adds a new list member that points to item to the list. 80*6185db85Sdougm * If list is NULL, it starts a new list. The function returns 81*6185db85Sdougm * the first member of the list. 82*6185db85Sdougm */ 83*6185db85Sdougm struct list * 84*6185db85Sdougm add_list(struct list *listp, void *item, void *data) 85*6185db85Sdougm { 86*6185db85Sdougm struct list *new, *tmp; 87*6185db85Sdougm 88*6185db85Sdougm new = malloc(sizeof (struct list)); 89*6185db85Sdougm if (new != NULL) { 90*6185db85Sdougm new->next = NULL; 91*6185db85Sdougm new->item = item; 92*6185db85Sdougm new->itemdata = data; 93*6185db85Sdougm } else { 94*6185db85Sdougm return (listp); 95*6185db85Sdougm } 96*6185db85Sdougm 97*6185db85Sdougm if (listp == NULL) 98*6185db85Sdougm return (new); 99*6185db85Sdougm 100*6185db85Sdougm for (tmp = listp; tmp->next != NULL; tmp = tmp->next) { 101*6185db85Sdougm /* get to end of list */ 102*6185db85Sdougm } 103*6185db85Sdougm tmp->next = new; 104*6185db85Sdougm return (listp); 105*6185db85Sdougm } 106*6185db85Sdougm 107*6185db85Sdougm /* 108*6185db85Sdougm * free_list(list) 109*6185db85Sdougm * Given a list, free all the members of the list; 110*6185db85Sdougm */ 111*6185db85Sdougm static void 112*6185db85Sdougm free_list(struct list *listp) 113*6185db85Sdougm { 114*6185db85Sdougm struct list *tmp; 115*6185db85Sdougm while (listp != NULL) { 116*6185db85Sdougm tmp = listp; 117*6185db85Sdougm listp = listp->next; 118*6185db85Sdougm free(tmp); 119*6185db85Sdougm } 120*6185db85Sdougm } 121*6185db85Sdougm 122*6185db85Sdougm /* 123*6185db85Sdougm * check_authorization(instname, which) 124*6185db85Sdougm * 125*6185db85Sdougm * Checks to see if the specific type of authorization in which is 126*6185db85Sdougm * enabled for the user in this SMF service instance. 127*6185db85Sdougm */ 128*6185db85Sdougm 129*6185db85Sdougm static int 130*6185db85Sdougm check_authorization(char *instname, int which) 131*6185db85Sdougm { 132*6185db85Sdougm scf_handle_t *handle = NULL; 133*6185db85Sdougm scf_simple_prop_t *prop = NULL; 134*6185db85Sdougm char svcstring[SA_MAX_NAME_LEN + sizeof (SA_SVC_FMRI_BASE) + 1]; 135*6185db85Sdougm char *authstr = NULL; 136*6185db85Sdougm ssize_t numauths; 137*6185db85Sdougm int ret = 1; 138*6185db85Sdougm uid_t uid; 139*6185db85Sdougm struct passwd *pw = NULL; 140*6185db85Sdougm 141*6185db85Sdougm uid = getuid(); 142*6185db85Sdougm pw = getpwuid(uid); 143*6185db85Sdougm if (pw == NULL) 144*6185db85Sdougm ret = 0; 145*6185db85Sdougm 146*6185db85Sdougm if (ret == 1) { 147*6185db85Sdougm /* since names are restricted to SA_MAX_NAME_LEN won't overflow */ 148*6185db85Sdougm (void) snprintf(svcstring, sizeof (svcstring), 149*6185db85Sdougm "%s:%s", SA_SVC_FMRI_BASE, instname); 150*6185db85Sdougm handle = scf_handle_create(SCF_VERSION); 151*6185db85Sdougm if (handle != NULL) { 152*6185db85Sdougm if (scf_handle_bind(handle) == 0) { 153*6185db85Sdougm switch (which) { 154*6185db85Sdougm case SVC_SET: 155*6185db85Sdougm prop = scf_simple_prop_get(handle, svcstring, 156*6185db85Sdougm "general", 157*6185db85Sdougm SVC_AUTH_VALUE); 158*6185db85Sdougm break; 159*6185db85Sdougm case SVC_ACTION: 160*6185db85Sdougm prop = scf_simple_prop_get(handle, svcstring, 161*6185db85Sdougm "general", 162*6185db85Sdougm SVC_AUTH_ACTION); 163*6185db85Sdougm break; 164*6185db85Sdougm } 165*6185db85Sdougm } 166*6185db85Sdougm } 167*6185db85Sdougm } 168*6185db85Sdougm /* make sure we have an authorization string property */ 169*6185db85Sdougm if (prop != NULL) { 170*6185db85Sdougm int i; 171*6185db85Sdougm numauths = scf_simple_prop_numvalues(prop); 172*6185db85Sdougm for (ret = 0, i = 0; i < numauths; i++) { 173*6185db85Sdougm authstr = scf_simple_prop_next_astring(prop); 174*6185db85Sdougm if (authstr != NULL) { 175*6185db85Sdougm /* check if this user has one of the strings */ 176*6185db85Sdougm if (chkauthattr(authstr, pw->pw_name)) { 177*6185db85Sdougm ret = 1; 178*6185db85Sdougm break; 179*6185db85Sdougm } 180*6185db85Sdougm } 181*6185db85Sdougm } 182*6185db85Sdougm endauthattr(); 183*6185db85Sdougm scf_simple_prop_free(prop); 184*6185db85Sdougm } else { 185*6185db85Sdougm /* no authorization string defined */ 186*6185db85Sdougm ret = 0; 187*6185db85Sdougm } 188*6185db85Sdougm if (handle != NULL) 189*6185db85Sdougm scf_handle_destroy(handle); 190*6185db85Sdougm return (ret); 191*6185db85Sdougm } 192*6185db85Sdougm 193*6185db85Sdougm /* 194*6185db85Sdougm * check_authorizations(instname, flags) 195*6185db85Sdougm * 196*6185db85Sdougm * check all the needed authorizations for the user in this service 197*6185db85Sdougm * instance. Return value of 1(true) or 0(false) indicates whether 198*6185db85Sdougm * there are authorizations for the user or not. 199*6185db85Sdougm */ 200*6185db85Sdougm 201*6185db85Sdougm static int 202*6185db85Sdougm check_authorizations(char *instname, int flags) 203*6185db85Sdougm { 204*6185db85Sdougm int ret1 = 0; 205*6185db85Sdougm int ret2 = 0; 206*6185db85Sdougm int ret; 207*6185db85Sdougm 208*6185db85Sdougm if (flags & SVC_SET) 209*6185db85Sdougm ret1 = check_authorization(instname, SVC_SET); 210*6185db85Sdougm if (flags & SVC_ACTION) 211*6185db85Sdougm ret2 = check_authorization(instname, SVC_ACTION); 212*6185db85Sdougm switch (flags) { 213*6185db85Sdougm case SVC_ACTION: 214*6185db85Sdougm ret = ret2; 215*6185db85Sdougm break; 216*6185db85Sdougm case SVC_SET: 217*6185db85Sdougm ret = ret1; 218*6185db85Sdougm break; 219*6185db85Sdougm case SVC_ACTION|SVC_SET: 220*6185db85Sdougm ret = ret1 & ret2; 221*6185db85Sdougm break; 222*6185db85Sdougm default: 223*6185db85Sdougm /* if not flags set, we assume we don't need authorizations */ 224*6185db85Sdougm ret = 1; 225*6185db85Sdougm } 226*6185db85Sdougm return (ret); 227*6185db85Sdougm } 228*6185db85Sdougm 229*6185db85Sdougm /* 230*6185db85Sdougm * enable_all_groups(list, setstate, online, update) 231*6185db85Sdougm * Given a list of groups, enable each one found. If update is 232*6185db85Sdougm * not NULL, then update all the shares for the protocol that was 233*6185db85Sdougm * passed in. 234*6185db85Sdougm */ 235*6185db85Sdougm static int 236*6185db85Sdougm enable_all_groups(struct list *work, int setstate, int online, char *update) 237*6185db85Sdougm { 238*6185db85Sdougm sa_share_t share; 239*6185db85Sdougm int ret = SA_OK; 240*6185db85Sdougm char instance[SA_MAX_NAME_LEN + sizeof (SA_SVC_FMRI_BASE) + 1]; 241*6185db85Sdougm char *state; 242*6185db85Sdougm char *name; 243*6185db85Sdougm char *zfs = NULL; 244*6185db85Sdougm int dozfs = 0; 245*6185db85Sdougm sa_group_t group; 246*6185db85Sdougm 247*6185db85Sdougm while (work != NULL && ret == SA_OK) { 248*6185db85Sdougm group = (sa_group_t)work->item; 249*6185db85Sdougm /* if itemdata != NULL then a single share */ 250*6185db85Sdougm if (work->itemdata != NULL) { 251*6185db85Sdougm ret = sa_enable_share((sa_share_t)work->itemdata, NULL); 252*6185db85Sdougm } 253*6185db85Sdougm if (setstate) 254*6185db85Sdougm ret = sa_set_group_attr(group, "state", 255*6185db85Sdougm "enabled"); 256*6185db85Sdougm if (ret == SA_OK) { 257*6185db85Sdougm /* if itemdata == NULL then the whole group */ 258*6185db85Sdougm if (work->itemdata == NULL) { 259*6185db85Sdougm for (share = sa_get_share(group, NULL); 260*6185db85Sdougm share != NULL; share = sa_get_next_share(share)) { 261*6185db85Sdougm if (update != NULL) 262*6185db85Sdougm (void) sa_update_legacy(share, update); 263*6185db85Sdougm ret = sa_enable_share(share, NULL); 264*6185db85Sdougm } 265*6185db85Sdougm } 266*6185db85Sdougm if (online) { 267*6185db85Sdougm name = sa_get_group_attr(group, "name"); 268*6185db85Sdougm zfs = sa_get_group_attr(group, "zfs"); 269*6185db85Sdougm if (name != NULL) { 270*6185db85Sdougm if (zfs == NULL) { 271*6185db85Sdougm (void) snprintf(instance, sizeof (instance), 272*6185db85Sdougm "%s:%s", 273*6185db85Sdougm SA_SVC_FMRI_BASE, name); 274*6185db85Sdougm state = smf_get_state(instance); 275*6185db85Sdougm if (state == NULL || 276*6185db85Sdougm strcmp(state, "online") != 0) { 277*6185db85Sdougm (void) smf_enable_instance(instance, 0); 278*6185db85Sdougm free(state); 279*6185db85Sdougm } 280*6185db85Sdougm } else { 281*6185db85Sdougm dozfs++; 282*6185db85Sdougm sa_free_attr_string(zfs); 283*6185db85Sdougm zfs = NULL; 284*6185db85Sdougm } 285*6185db85Sdougm if (name != NULL) 286*6185db85Sdougm sa_free_attr_string(name); 287*6185db85Sdougm } 288*6185db85Sdougm } else { 289*6185db85Sdougm zfs = sa_get_group_attr(group, "zfs"); 290*6185db85Sdougm if (zfs != NULL) { 291*6185db85Sdougm dozfs++; 292*6185db85Sdougm sa_free_attr_string(zfs); 293*6185db85Sdougm zfs = NULL; 294*6185db85Sdougm } 295*6185db85Sdougm } 296*6185db85Sdougm work = work->next; 297*6185db85Sdougm } 298*6185db85Sdougm } 299*6185db85Sdougm if (ret == SA_OK) { 300*6185db85Sdougm ret = sa_update_config(); 301*6185db85Sdougm } 302*6185db85Sdougm /* do ZFS last to allow everything to get updated */ 303*6185db85Sdougm if (ret == SA_OK && dozfs) { 304*6185db85Sdougm FILE *sys; 305*6185db85Sdougm int err; 306*6185db85Sdougm sys = popen(ZFS_SHAREALL, "r"); 307*6185db85Sdougm if (sys != NULL) { 308*6185db85Sdougm err = pclose(sys); 309*6185db85Sdougm if (err != 0) 310*6185db85Sdougm ret = SA_SYSTEM_ERR; 311*6185db85Sdougm } else { 312*6185db85Sdougm ret = SA_SYSTEM_ERR; 313*6185db85Sdougm } 314*6185db85Sdougm } 315*6185db85Sdougm return (ret); 316*6185db85Sdougm } 317*6185db85Sdougm 318*6185db85Sdougm /* 319*6185db85Sdougm * chk_opt(optlistp, security, proto) 320*6185db85Sdougm * 321*6185db85Sdougm * Do a sanity check on the optlist provided for the protocol. This 322*6185db85Sdougm * is a syntax check and verification that the property is either a 323*6185db85Sdougm * general or specific to a names optionset. 324*6185db85Sdougm */ 325*6185db85Sdougm 326*6185db85Sdougm static int 327*6185db85Sdougm chk_opt(struct options *optlistp, int security, char *proto) 328*6185db85Sdougm { 329*6185db85Sdougm struct options *optlist; 330*6185db85Sdougm char *sep = ""; 331*6185db85Sdougm int notfirst = 0; 332*6185db85Sdougm int ret; 333*6185db85Sdougm 334*6185db85Sdougm for (optlist = optlistp; optlist != NULL; optlist = optlist->next) { 335*6185db85Sdougm char *optname; 336*6185db85Sdougm 337*6185db85Sdougm optname = optlist->optname; 338*6185db85Sdougm ret = OPT_ADD_OK; 339*6185db85Sdougm /* extract property/value pair */ 340*6185db85Sdougm if (sa_is_security(optname, proto)) { 341*6185db85Sdougm if (!security) 342*6185db85Sdougm ret = OPT_ADD_SECURITY; 343*6185db85Sdougm } else { 344*6185db85Sdougm if (security) 345*6185db85Sdougm ret = OPT_ADD_PROPERTY; 346*6185db85Sdougm } 347*6185db85Sdougm if (ret != OPT_ADD_OK) { 348*6185db85Sdougm if (notfirst == 0) 349*6185db85Sdougm (void) printf(gettext("Property syntax error: ")); 350*6185db85Sdougm switch (ret) { 351*6185db85Sdougm case OPT_ADD_SYNTAX: 352*6185db85Sdougm (void) printf(gettext("%ssyntax error: %s"), 353*6185db85Sdougm sep, optname); 354*6185db85Sdougm sep = ", "; 355*6185db85Sdougm break; 356*6185db85Sdougm case OPT_ADD_SECURITY: 357*6185db85Sdougm (void) printf(gettext("%s%s requires -S"), 358*6185db85Sdougm optname, sep); 359*6185db85Sdougm sep = ", "; 360*6185db85Sdougm break; 361*6185db85Sdougm case OPT_ADD_PROPERTY: 362*6185db85Sdougm (void) printf(gettext("%s%s not supported with -S"), 363*6185db85Sdougm optname, sep); 364*6185db85Sdougm sep = ", "; 365*6185db85Sdougm break; 366*6185db85Sdougm } 367*6185db85Sdougm notfirst++; 368*6185db85Sdougm } 369*6185db85Sdougm } 370*6185db85Sdougm if (notfirst) { 371*6185db85Sdougm (void) printf("\n"); 372*6185db85Sdougm ret = SA_SYNTAX_ERR; 373*6185db85Sdougm } 374*6185db85Sdougm return (ret); 375*6185db85Sdougm } 376*6185db85Sdougm 377*6185db85Sdougm /* 378*6185db85Sdougm * free_opt(optlist) 379*6185db85Sdougm * Free the specified option list. 380*6185db85Sdougm */ 381*6185db85Sdougm static void 382*6185db85Sdougm free_opt(struct options *optlist) 383*6185db85Sdougm { 384*6185db85Sdougm struct options *nextopt; 385*6185db85Sdougm while (optlist != NULL) { 386*6185db85Sdougm nextopt = optlist->next; 387*6185db85Sdougm free(optlist); 388*6185db85Sdougm optlist = nextopt; 389*6185db85Sdougm } 390*6185db85Sdougm } 391*6185db85Sdougm 392*6185db85Sdougm /* 393*6185db85Sdougm * check property list for valid properties 394*6185db85Sdougm * A null value is a remove which is always valid. 395*6185db85Sdougm */ 396*6185db85Sdougm static int 397*6185db85Sdougm valid_options(struct options *optlist, char *proto, void *object, char *sec) 398*6185db85Sdougm { 399*6185db85Sdougm int ret = SA_OK; 400*6185db85Sdougm struct options *cur; 401*6185db85Sdougm sa_property_t prop; 402*6185db85Sdougm sa_optionset_t parent = NULL; 403*6185db85Sdougm 404*6185db85Sdougm if (object != NULL) { 405*6185db85Sdougm if (sec == NULL) 406*6185db85Sdougm parent = sa_get_optionset(object, proto); 407*6185db85Sdougm else 408*6185db85Sdougm parent = sa_get_security(object, sec, proto); 409*6185db85Sdougm } 410*6185db85Sdougm 411*6185db85Sdougm for (cur = optlist; cur != NULL; cur = cur->next) { 412*6185db85Sdougm if (cur->optvalue != NULL) { 413*6185db85Sdougm prop = sa_create_property(cur->optname, cur->optvalue); 414*6185db85Sdougm if (prop == NULL) 415*6185db85Sdougm ret = SA_NO_MEMORY; 416*6185db85Sdougm if (ret != SA_OK || 417*6185db85Sdougm (ret = sa_valid_property(parent, proto, prop)) != SA_OK) { 418*6185db85Sdougm (void) printf(gettext("Could not add property %s: %s\n"), 419*6185db85Sdougm cur->optname, 420*6185db85Sdougm sa_errorstr(ret)); 421*6185db85Sdougm } 422*6185db85Sdougm (void) sa_remove_property(prop); 423*6185db85Sdougm } 424*6185db85Sdougm } 425*6185db85Sdougm return (ret); 426*6185db85Sdougm } 427*6185db85Sdougm 428*6185db85Sdougm /* 429*6185db85Sdougm * add_optionset(group, optlist, protocol, *err) 430*6185db85Sdougm * Add the options in optlist to an optionset and then add the optionset 431*6185db85Sdougm * to the group. 432*6185db85Sdougm * 433*6185db85Sdougm * The return value indicates if there was a "change" while errors are 434*6185db85Sdougm * returned via the *err parameters. 435*6185db85Sdougm */ 436*6185db85Sdougm static int 437*6185db85Sdougm add_optionset(sa_group_t group, struct options *optlist, char *proto, int *err) 438*6185db85Sdougm { 439*6185db85Sdougm sa_optionset_t optionset; 440*6185db85Sdougm int ret = SA_OK; 441*6185db85Sdougm int result = 0; 442*6185db85Sdougm 443*6185db85Sdougm optionset = sa_get_optionset(group, proto); 444*6185db85Sdougm if (optionset == NULL) { 445*6185db85Sdougm optionset = sa_create_optionset(group, proto); 446*6185db85Sdougm result = 1; /* adding a protocol is a change */ 447*6185db85Sdougm } 448*6185db85Sdougm if (optionset != NULL) { 449*6185db85Sdougm while (optlist != NULL) { 450*6185db85Sdougm sa_property_t prop; 451*6185db85Sdougm prop = sa_get_property(optionset, optlist->optname); 452*6185db85Sdougm if (prop == NULL) { 453*6185db85Sdougm /* 454*6185db85Sdougm * add the property, but only if it is 455*6185db85Sdougm * a non-NULL or non-zero length value 456*6185db85Sdougm */ 457*6185db85Sdougm if (optlist->optvalue != NULL) { 458*6185db85Sdougm prop = sa_create_property(optlist->optname, 459*6185db85Sdougm optlist->optvalue); 460*6185db85Sdougm if (prop != NULL) { 461*6185db85Sdougm ret = sa_valid_property(optionset, proto, prop); 462*6185db85Sdougm if (ret != SA_OK) { 463*6185db85Sdougm (void) sa_remove_property(prop); 464*6185db85Sdougm (void) printf(gettext("Could not add property " 465*6185db85Sdougm "%s: %s\n"), 466*6185db85Sdougm optlist->optname, 467*6185db85Sdougm sa_errorstr(ret)); 468*6185db85Sdougm } 469*6185db85Sdougm } 470*6185db85Sdougm if (ret == SA_OK) { 471*6185db85Sdougm ret = sa_add_property(optionset, prop); 472*6185db85Sdougm if (ret != SA_OK) { 473*6185db85Sdougm (void) printf(gettext("Could not add property" 474*6185db85Sdougm " %s: %s\n"), 475*6185db85Sdougm optlist->optname, 476*6185db85Sdougm sa_errorstr(ret)); 477*6185db85Sdougm } else { 478*6185db85Sdougm /* there was a change */ 479*6185db85Sdougm result = 1; 480*6185db85Sdougm } 481*6185db85Sdougm } 482*6185db85Sdougm } 483*6185db85Sdougm } else { 484*6185db85Sdougm ret = sa_update_property(prop, optlist->optvalue); 485*6185db85Sdougm /* should check to see if value changed */ 486*6185db85Sdougm if (ret != SA_OK) { 487*6185db85Sdougm (void) printf(gettext("Could not update " 488*6185db85Sdougm "property %s: %s\n"), 489*6185db85Sdougm optlist->optname, 490*6185db85Sdougm sa_errorstr(ret)); 491*6185db85Sdougm } else { 492*6185db85Sdougm result = 1; 493*6185db85Sdougm } 494*6185db85Sdougm } 495*6185db85Sdougm optlist = optlist->next; 496*6185db85Sdougm } 497*6185db85Sdougm ret = sa_commit_properties(optionset, 0); 498*6185db85Sdougm } 499*6185db85Sdougm if (err != NULL) 500*6185db85Sdougm *err = ret; 501*6185db85Sdougm return (result); 502*6185db85Sdougm } 503*6185db85Sdougm 504*6185db85Sdougm /* 505*6185db85Sdougm * sa_create(flags, argc, argv) 506*6185db85Sdougm * create a new group 507*6185db85Sdougm * this may or may not have a protocol associated with it. 508*6185db85Sdougm * No protocol means "all" protocols in this case. 509*6185db85Sdougm */ 510*6185db85Sdougm static int 511*6185db85Sdougm sa_create(int flags, int argc, char *argv[]) 512*6185db85Sdougm { 513*6185db85Sdougm char *groupname; 514*6185db85Sdougm 515*6185db85Sdougm sa_group_t group; 516*6185db85Sdougm int verbose = 0; 517*6185db85Sdougm int dryrun = 0; 518*6185db85Sdougm int c; 519*6185db85Sdougm char *protocol = NULL; 520*6185db85Sdougm int ret = SA_OK; 521*6185db85Sdougm struct options *optlist = NULL; 522*6185db85Sdougm int err = 0; 523*6185db85Sdougm int auth; 524*6185db85Sdougm 525*6185db85Sdougm while ((c = getopt(argc, argv, "?hvnP:p:")) != EOF) { 526*6185db85Sdougm switch (c) { 527*6185db85Sdougm case 'v': 528*6185db85Sdougm verbose++; 529*6185db85Sdougm break; 530*6185db85Sdougm case 'n': 531*6185db85Sdougm dryrun++; 532*6185db85Sdougm break; 533*6185db85Sdougm case 'P': 534*6185db85Sdougm protocol = optarg; 535*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 536*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 537*6185db85Sdougm protocol); 538*6185db85Sdougm return (SA_INVALID_PROTOCOL); 539*6185db85Sdougm } 540*6185db85Sdougm break; 541*6185db85Sdougm case 'p': 542*6185db85Sdougm ret = add_opt(&optlist, optarg, 0); 543*6185db85Sdougm switch (ret) { 544*6185db85Sdougm case OPT_ADD_SYNTAX: 545*6185db85Sdougm (void) printf(gettext("Property syntax error for " 546*6185db85Sdougm "property: %s\n"), 547*6185db85Sdougm optarg); 548*6185db85Sdougm return (SA_SYNTAX_ERR); 549*6185db85Sdougm case OPT_ADD_SECURITY: 550*6185db85Sdougm (void) printf(gettext("Security properties need " 551*6185db85Sdougm "to be set with set-security: %s\n"), 552*6185db85Sdougm optarg); 553*6185db85Sdougm return (SA_SYNTAX_ERR); 554*6185db85Sdougm default: 555*6185db85Sdougm break; 556*6185db85Sdougm } 557*6185db85Sdougm 558*6185db85Sdougm break; 559*6185db85Sdougm default: 560*6185db85Sdougm case 'h': 561*6185db85Sdougm case '?': 562*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 563*6185db85Sdougm sa_get_usage(USAGE_CREATE)); 564*6185db85Sdougm return (0); 565*6185db85Sdougm } 566*6185db85Sdougm } 567*6185db85Sdougm 568*6185db85Sdougm if (optind >= argc) { 569*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_CREATE)); 570*6185db85Sdougm (void) printf(gettext("\tgroup must be specified.\n")); 571*6185db85Sdougm return (SA_BAD_PATH); 572*6185db85Sdougm } 573*6185db85Sdougm 574*6185db85Sdougm if ((optind + 1) < argc) { 575*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_CREATE)); 576*6185db85Sdougm (void) printf(gettext("\textraneous group(s) at end\n")); 577*6185db85Sdougm return (SA_SYNTAX_ERR); 578*6185db85Sdougm } 579*6185db85Sdougm 580*6185db85Sdougm if (protocol == NULL && optlist != NULL) { 581*6185db85Sdougm /* lookup default protocol */ 582*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_CREATE)); 583*6185db85Sdougm (void) printf(gettext("\tprotocol must be specified " 584*6185db85Sdougm "with properties\n")); 585*6185db85Sdougm return (SA_INVALID_PROTOCOL); 586*6185db85Sdougm } 587*6185db85Sdougm 588*6185db85Sdougm if (optlist != NULL) 589*6185db85Sdougm ret = chk_opt(optlist, 0, protocol); 590*6185db85Sdougm if (ret == OPT_ADD_SECURITY) { 591*6185db85Sdougm (void) printf(gettext("Security properties not " 592*6185db85Sdougm "supported with create\n")); 593*6185db85Sdougm return (SA_SYNTAX_ERR); 594*6185db85Sdougm } 595*6185db85Sdougm 596*6185db85Sdougm /* 597*6185db85Sdougm * if a group already exists, we can only add a new protocol 598*6185db85Sdougm * to it and not create a new one or add the same protocol 599*6185db85Sdougm * again. 600*6185db85Sdougm */ 601*6185db85Sdougm 602*6185db85Sdougm groupname = argv[optind]; 603*6185db85Sdougm 604*6185db85Sdougm auth = check_authorizations(groupname, flags); 605*6185db85Sdougm 606*6185db85Sdougm group = sa_get_group(groupname); 607*6185db85Sdougm if (group != NULL) { 608*6185db85Sdougm /* group exists so must be a protocol add */ 609*6185db85Sdougm if (protocol != NULL) { 610*6185db85Sdougm if (has_protocol(group, protocol)) { 611*6185db85Sdougm (void) printf(gettext("Group \"%s\" already exists" 612*6185db85Sdougm " with protocol %s\n"), 613*6185db85Sdougm groupname, protocol); 614*6185db85Sdougm ret = SA_DUPLICATE_NAME; 615*6185db85Sdougm } 616*6185db85Sdougm } else { 617*6185db85Sdougm /* must add new protocol */ 618*6185db85Sdougm (void) printf(gettext("Group already exists and no protocol" 619*6185db85Sdougm " specified.\n")); 620*6185db85Sdougm ret = SA_DUPLICATE_NAME; 621*6185db85Sdougm } 622*6185db85Sdougm } else { 623*6185db85Sdougm /* 624*6185db85Sdougm * is it a valid name? Must comply with SMF instance 625*6185db85Sdougm * name restrictions. 626*6185db85Sdougm */ 627*6185db85Sdougm if (!sa_valid_group_name(groupname)) { 628*6185db85Sdougm ret = SA_INVALID_NAME; 629*6185db85Sdougm (void) printf(gettext("Invalid group name: %s\n"), groupname); 630*6185db85Sdougm } 631*6185db85Sdougm } 632*6185db85Sdougm if (ret == SA_OK) { 633*6185db85Sdougm /* check protocol vs optlist */ 634*6185db85Sdougm if (optlist != NULL) { 635*6185db85Sdougm /* check options, if any, for validity */ 636*6185db85Sdougm ret = valid_options(optlist, protocol, group, NULL); 637*6185db85Sdougm } 638*6185db85Sdougm } 639*6185db85Sdougm if (ret == SA_OK && !dryrun) { 640*6185db85Sdougm if (group == NULL) { 641*6185db85Sdougm group = sa_create_group((char *)groupname, &err); 642*6185db85Sdougm } 643*6185db85Sdougm if (group != NULL) { 644*6185db85Sdougm sa_optionset_t optionset; 645*6185db85Sdougm if (optlist != NULL) { 646*6185db85Sdougm (void) add_optionset(group, optlist, protocol, &ret); 647*6185db85Sdougm } else if (protocol != NULL) { 648*6185db85Sdougm optionset = sa_create_optionset(group, protocol); 649*6185db85Sdougm if (optionset == NULL) 650*6185db85Sdougm ret = SA_NO_MEMORY; 651*6185db85Sdougm } else if (protocol == NULL) { 652*6185db85Sdougm char **protolist; 653*6185db85Sdougm int numprotos, i; 654*6185db85Sdougm numprotos = sa_get_protocols(&protolist); 655*6185db85Sdougm for (i = 0; i < numprotos; i++) { 656*6185db85Sdougm optionset = sa_create_optionset(group, protolist[i]); 657*6185db85Sdougm } 658*6185db85Sdougm if (protolist != NULL) 659*6185db85Sdougm free(protolist); 660*6185db85Sdougm } 661*6185db85Sdougm /* 662*6185db85Sdougm * we have a group and legal additions 663*6185db85Sdougm */ 664*6185db85Sdougm if (ret == SA_OK) { 665*6185db85Sdougm /* 666*6185db85Sdougm * commit to configuration for protocols that 667*6185db85Sdougm * need to do block updates. For NFS, this 668*6185db85Sdougm * doesn't do anything but it will be run for 669*6185db85Sdougm * all protocols that implement the 670*6185db85Sdougm * appropriate plugin. 671*6185db85Sdougm */ 672*6185db85Sdougm ret = sa_update_config(); 673*6185db85Sdougm } else { 674*6185db85Sdougm if (group != NULL) 675*6185db85Sdougm (void) sa_remove_group(group); 676*6185db85Sdougm } 677*6185db85Sdougm } else { 678*6185db85Sdougm ret = err; 679*6185db85Sdougm (void) printf(gettext("Could not create group: %s\n"), 680*6185db85Sdougm sa_errorstr(ret)); 681*6185db85Sdougm } 682*6185db85Sdougm } 683*6185db85Sdougm if (dryrun && ret == SA_OK && !auth && verbose) { 684*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 685*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 686*6185db85Sdougm ret = SA_NO_PERMISSION; 687*6185db85Sdougm } 688*6185db85Sdougm free_opt(optlist); 689*6185db85Sdougm return (ret); 690*6185db85Sdougm } 691*6185db85Sdougm 692*6185db85Sdougm /* 693*6185db85Sdougm * group_status(group) 694*6185db85Sdougm * 695*6185db85Sdougm * return the current status (enabled/disabled) of the group. 696*6185db85Sdougm */ 697*6185db85Sdougm 698*6185db85Sdougm static char * 699*6185db85Sdougm group_status(sa_group_t group) 700*6185db85Sdougm { 701*6185db85Sdougm char *state; 702*6185db85Sdougm int enabled = 0; 703*6185db85Sdougm 704*6185db85Sdougm state = sa_get_group_attr(group, "state"); 705*6185db85Sdougm if (state != NULL) { 706*6185db85Sdougm if (strcmp(state, "enabled") == 0) { 707*6185db85Sdougm enabled = 1; 708*6185db85Sdougm } 709*6185db85Sdougm sa_free_attr_string(state); 710*6185db85Sdougm } 711*6185db85Sdougm return (enabled ? gettext("enabled") : gettext("disabled")); 712*6185db85Sdougm } 713*6185db85Sdougm 714*6185db85Sdougm /* 715*6185db85Sdougm * sa_delete(flags, argc, argv) 716*6185db85Sdougm * 717*6185db85Sdougm * Delete a group. 718*6185db85Sdougm */ 719*6185db85Sdougm 720*6185db85Sdougm static int 721*6185db85Sdougm sa_delete(int flags, int argc, char *argv[]) 722*6185db85Sdougm { 723*6185db85Sdougm char *groupname; 724*6185db85Sdougm sa_group_t group; 725*6185db85Sdougm sa_share_t share; 726*6185db85Sdougm int verbose = 0; 727*6185db85Sdougm int dryrun = 0; 728*6185db85Sdougm int force = 0; 729*6185db85Sdougm int c; 730*6185db85Sdougm char *protocol = NULL; 731*6185db85Sdougm char *sectype = NULL; 732*6185db85Sdougm int ret = SA_OK; 733*6185db85Sdougm int auth; 734*6185db85Sdougm 735*6185db85Sdougm while ((c = getopt(argc, argv, "?hvnP:fS:")) != EOF) { 736*6185db85Sdougm switch (c) { 737*6185db85Sdougm case 'v': 738*6185db85Sdougm verbose++; 739*6185db85Sdougm break; 740*6185db85Sdougm case 'n': 741*6185db85Sdougm dryrun++; 742*6185db85Sdougm break; 743*6185db85Sdougm case 'P': 744*6185db85Sdougm protocol = optarg; 745*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 746*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 747*6185db85Sdougm protocol); 748*6185db85Sdougm return (SA_INVALID_PROTOCOL); 749*6185db85Sdougm } 750*6185db85Sdougm break; 751*6185db85Sdougm case 'S': 752*6185db85Sdougm sectype = optarg; 753*6185db85Sdougm break; 754*6185db85Sdougm case 'f': 755*6185db85Sdougm force++; 756*6185db85Sdougm break; 757*6185db85Sdougm default: 758*6185db85Sdougm case 'h': 759*6185db85Sdougm case '?': 760*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 761*6185db85Sdougm sa_get_usage(USAGE_DELETE)); 762*6185db85Sdougm return (0); 763*6185db85Sdougm } 764*6185db85Sdougm } 765*6185db85Sdougm 766*6185db85Sdougm if (optind >= argc) { 767*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_DELETE)); 768*6185db85Sdougm (void) printf(gettext("\tgroup must be specified.\n")); 769*6185db85Sdougm return (SA_SYNTAX_ERR); 770*6185db85Sdougm } 771*6185db85Sdougm 772*6185db85Sdougm if ((optind + 1) < argc) { 773*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_DELETE)); 774*6185db85Sdougm (void) printf(gettext("\textraneous group(s) at end\n")); 775*6185db85Sdougm return (SA_SYNTAX_ERR); 776*6185db85Sdougm } 777*6185db85Sdougm 778*6185db85Sdougm if (sectype != NULL && protocol == NULL) { 779*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_DELETE)); 780*6185db85Sdougm (void) printf(gettext("\tsecurity requires protocol to be " 781*6185db85Sdougm "specified.\n")); 782*6185db85Sdougm return (SA_SYNTAX_ERR); 783*6185db85Sdougm } 784*6185db85Sdougm 785*6185db85Sdougm /* 786*6185db85Sdougm * Determine if the group already exists since it must in 787*6185db85Sdougm * order to be removed. 788*6185db85Sdougm * 789*6185db85Sdougm * We can delete when: 790*6185db85Sdougm * 791*6185db85Sdougm * - group is empty 792*6185db85Sdougm * - force flag is set 793*6185db85Sdougm * - if protocol specified, only delete the protocol 794*6185db85Sdougm */ 795*6185db85Sdougm 796*6185db85Sdougm groupname = argv[optind]; 797*6185db85Sdougm group = sa_get_group(groupname); 798*6185db85Sdougm if (group == NULL) { 799*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 800*6185db85Sdougm } else { 801*6185db85Sdougm auth = check_authorizations(groupname, flags); 802*6185db85Sdougm if (protocol == NULL) { 803*6185db85Sdougm share = sa_get_share(group, NULL); 804*6185db85Sdougm if (share != NULL) 805*6185db85Sdougm ret = SA_BUSY; 806*6185db85Sdougm if (share == NULL || (share != NULL && force == 1)) { 807*6185db85Sdougm ret = SA_OK; 808*6185db85Sdougm if (!dryrun) { 809*6185db85Sdougm while (share != NULL) { 810*6185db85Sdougm sa_share_t next_share; 811*6185db85Sdougm next_share = sa_get_next_share(share); 812*6185db85Sdougm /* 813*6185db85Sdougm * need to do the disable of each 814*6185db85Sdougm * share, but don't actually do 815*6185db85Sdougm * anything on a dryrun. 816*6185db85Sdougm */ 817*6185db85Sdougm ret = sa_disable_share(share, NULL); 818*6185db85Sdougm ret = sa_remove_share(share); 819*6185db85Sdougm share = next_share; 820*6185db85Sdougm } 821*6185db85Sdougm ret = sa_remove_group(group); 822*6185db85Sdougm } 823*6185db85Sdougm } 824*6185db85Sdougm /* commit to configuration if not a dryrun */ 825*6185db85Sdougm if (!dryrun && ret == SA_OK) { 826*6185db85Sdougm ret = sa_update_config(); 827*6185db85Sdougm } 828*6185db85Sdougm } else { 829*6185db85Sdougm /* a protocol delete */ 830*6185db85Sdougm sa_optionset_t optionset; 831*6185db85Sdougm sa_security_t security; 832*6185db85Sdougm if (sectype != NULL) { 833*6185db85Sdougm /* only delete specified security */ 834*6185db85Sdougm security = sa_get_security(group, sectype, protocol); 835*6185db85Sdougm if (security != NULL && !dryrun) { 836*6185db85Sdougm ret = sa_destroy_security(security); 837*6185db85Sdougm } else { 838*6185db85Sdougm ret = SA_INVALID_PROTOCOL; 839*6185db85Sdougm } 840*6185db85Sdougm } else { 841*6185db85Sdougm optionset = sa_get_optionset(group, protocol); 842*6185db85Sdougm if (optionset != NULL && !dryrun) { 843*6185db85Sdougm /* have an optionset with protocol to delete */ 844*6185db85Sdougm ret = sa_destroy_optionset(optionset); 845*6185db85Sdougm /* 846*6185db85Sdougm * now find all security sets for the protocol 847*6185db85Sdougm * and remove them. Don't remove other 848*6185db85Sdougm * protocols. 849*6185db85Sdougm */ 850*6185db85Sdougm for (security = sa_get_security(group, NULL, NULL); 851*6185db85Sdougm ret == SA_OK && security != NULL; 852*6185db85Sdougm security = sa_get_next_security(security)) { 853*6185db85Sdougm char *secprot; 854*6185db85Sdougm 855*6185db85Sdougm secprot = sa_get_security_attr(security, "type"); 856*6185db85Sdougm if (secprot != NULL && 857*6185db85Sdougm strcmp(secprot, protocol) == 0) 858*6185db85Sdougm ret = sa_destroy_security(security); 859*6185db85Sdougm if (secprot != NULL) 860*6185db85Sdougm sa_free_attr_string(secprot); 861*6185db85Sdougm } 862*6185db85Sdougm } else { 863*6185db85Sdougm if (!dryrun) 864*6185db85Sdougm ret = SA_INVALID_PROTOCOL; 865*6185db85Sdougm } 866*6185db85Sdougm } 867*6185db85Sdougm } 868*6185db85Sdougm } 869*6185db85Sdougm if (ret != SA_OK) { 870*6185db85Sdougm (void) printf(gettext("Could not delete group: %s\n"), 871*6185db85Sdougm sa_errorstr(ret)); 872*6185db85Sdougm } else if (dryrun && !auth && verbose) { 873*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 874*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 875*6185db85Sdougm } 876*6185db85Sdougm return (ret); 877*6185db85Sdougm } 878*6185db85Sdougm 879*6185db85Sdougm /* 880*6185db85Sdougm * strndupr(*buff, str, buffsize) 881*6185db85Sdougm * 882*6185db85Sdougm * used with small strings to duplicate and possibly increase the 883*6185db85Sdougm * buffer size of a string. 884*6185db85Sdougm */ 885*6185db85Sdougm static char * 886*6185db85Sdougm strndupr(char *buff, char *str, int *buffsize) 887*6185db85Sdougm { 888*6185db85Sdougm int limit; 889*6185db85Sdougm char *orig_buff = buff; 890*6185db85Sdougm 891*6185db85Sdougm if (buff == NULL) { 892*6185db85Sdougm buff = (char *)malloc(64); 893*6185db85Sdougm if (buff == NULL) 894*6185db85Sdougm return (NULL); 895*6185db85Sdougm *buffsize = 64; 896*6185db85Sdougm buff[0] = '\0'; 897*6185db85Sdougm } 898*6185db85Sdougm limit = strlen(buff) + strlen(str) + 1; 899*6185db85Sdougm if (limit > *buffsize) { 900*6185db85Sdougm limit = *buffsize = *buffsize + ((limit / 64) + 64); 901*6185db85Sdougm buff = realloc(buff, limit); 902*6185db85Sdougm } 903*6185db85Sdougm if (buff != NULL) { 904*6185db85Sdougm (void) strcat(buff, str); 905*6185db85Sdougm } else { 906*6185db85Sdougm /* if it fails, fail it hard */ 907*6185db85Sdougm if (orig_buff != NULL) 908*6185db85Sdougm free(orig_buff); 909*6185db85Sdougm } 910*6185db85Sdougm return (buff); 911*6185db85Sdougm } 912*6185db85Sdougm 913*6185db85Sdougm /* 914*6185db85Sdougm * group_proto(group) 915*6185db85Sdougm * 916*6185db85Sdougm * return a string of all the protocols (space separated) associated 917*6185db85Sdougm * with this group. 918*6185db85Sdougm */ 919*6185db85Sdougm 920*6185db85Sdougm static char * 921*6185db85Sdougm group_proto(sa_group_t group) 922*6185db85Sdougm { 923*6185db85Sdougm sa_optionset_t optionset; 924*6185db85Sdougm char *proto; 925*6185db85Sdougm char *buff = NULL; 926*6185db85Sdougm int buffsize = 0; 927*6185db85Sdougm int addspace = 0; 928*6185db85Sdougm /* 929*6185db85Sdougm * get the protocol list by finding the optionsets on this 930*6185db85Sdougm * group and extracting the type value. The initial call to 931*6185db85Sdougm * strndupr() initailizes buff. 932*6185db85Sdougm */ 933*6185db85Sdougm buff = strndupr(buff, "", &buffsize); 934*6185db85Sdougm if (buff != NULL) { 935*6185db85Sdougm for (optionset = sa_get_optionset(group, NULL); 936*6185db85Sdougm optionset != NULL && buff != NULL; 937*6185db85Sdougm optionset = sa_get_next_optionset(optionset)) { 938*6185db85Sdougm /* 939*6185db85Sdougm * extract out the protocol type from this optionset 940*6185db85Sdougm * and append it to the buffer "buff". strndupr() will 941*6185db85Sdougm * reallocate space as necessay. 942*6185db85Sdougm */ 943*6185db85Sdougm proto = sa_get_optionset_attr(optionset, "type"); 944*6185db85Sdougm if (proto != NULL) { 945*6185db85Sdougm if (addspace++) 946*6185db85Sdougm buff = strndupr(buff, " ", &buffsize); 947*6185db85Sdougm buff = strndupr(buff, proto, &buffsize); 948*6185db85Sdougm sa_free_attr_string(proto); 949*6185db85Sdougm } 950*6185db85Sdougm } 951*6185db85Sdougm } 952*6185db85Sdougm return (buff); 953*6185db85Sdougm } 954*6185db85Sdougm 955*6185db85Sdougm /* 956*6185db85Sdougm * sa_list(flags, argc, argv) 957*6185db85Sdougm * 958*6185db85Sdougm * implements the "list" subcommand to list groups and optionally 959*6185db85Sdougm * their state and protocols. 960*6185db85Sdougm */ 961*6185db85Sdougm 962*6185db85Sdougm static int 963*6185db85Sdougm sa_list(int flags, int argc, char *argv[]) 964*6185db85Sdougm { 965*6185db85Sdougm sa_group_t group; 966*6185db85Sdougm int verbose = 0; 967*6185db85Sdougm int c; 968*6185db85Sdougm char *protocol = NULL; 969*6185db85Sdougm #ifdef lint 970*6185db85Sdougm flags = flags; 971*6185db85Sdougm #endif 972*6185db85Sdougm 973*6185db85Sdougm while ((c = getopt(argc, argv, "?hvP:")) != EOF) { 974*6185db85Sdougm switch (c) { 975*6185db85Sdougm case 'v': 976*6185db85Sdougm verbose++; 977*6185db85Sdougm break; 978*6185db85Sdougm case 'P': 979*6185db85Sdougm protocol = optarg; 980*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 981*6185db85Sdougm (void) printf(gettext("Invalid protocol specified:" 982*6185db85Sdougm "%s\n"), 983*6185db85Sdougm protocol); 984*6185db85Sdougm return (SA_INVALID_PROTOCOL); 985*6185db85Sdougm } 986*6185db85Sdougm break; 987*6185db85Sdougm default: 988*6185db85Sdougm case 'h': 989*6185db85Sdougm case '?': 990*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_LIST)); 991*6185db85Sdougm return (0); 992*6185db85Sdougm } 993*6185db85Sdougm } 994*6185db85Sdougm 995*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 996*6185db85Sdougm group = sa_get_next_group(group)) { 997*6185db85Sdougm char *name; 998*6185db85Sdougm char *proto; 999*6185db85Sdougm if (protocol == NULL || has_protocol(group, protocol)) { 1000*6185db85Sdougm name = sa_get_group_attr(group, "name"); 1001*6185db85Sdougm if (name != NULL && (verbose > 1 || name[0] != '#')) { 1002*6185db85Sdougm (void) printf("%s", (char *)name); 1003*6185db85Sdougm if (verbose) { 1004*6185db85Sdougm /* 1005*6185db85Sdougm * need the list of protocols 1006*6185db85Sdougm * and current status once 1007*6185db85Sdougm * available. 1008*6185db85Sdougm */ 1009*6185db85Sdougm (void) printf("\t%s", group_status(group)); 1010*6185db85Sdougm proto = group_proto(group); 1011*6185db85Sdougm if (proto != NULL) { 1012*6185db85Sdougm (void) printf("\t%s", (char *)proto); 1013*6185db85Sdougm free(proto); 1014*6185db85Sdougm } 1015*6185db85Sdougm } 1016*6185db85Sdougm (void) printf("\n"); 1017*6185db85Sdougm } 1018*6185db85Sdougm if (name != NULL) 1019*6185db85Sdougm sa_free_attr_string(name); 1020*6185db85Sdougm } 1021*6185db85Sdougm } 1022*6185db85Sdougm return (0); 1023*6185db85Sdougm } 1024*6185db85Sdougm 1025*6185db85Sdougm /* 1026*6185db85Sdougm * out_properties(optionset, proto, sec) 1027*6185db85Sdougm * 1028*6185db85Sdougm * Format the properties and encode the protocol and optional named 1029*6185db85Sdougm * optionset into the string. 1030*6185db85Sdougm * 1031*6185db85Sdougm * format is protocol[:name]=(property-list) 1032*6185db85Sdougm */ 1033*6185db85Sdougm 1034*6185db85Sdougm static void 1035*6185db85Sdougm out_properties(sa_optionset_t optionset, char *proto, char *sec) 1036*6185db85Sdougm { 1037*6185db85Sdougm char *type; 1038*6185db85Sdougm char *value; 1039*6185db85Sdougm int spacer; 1040*6185db85Sdougm sa_property_t prop; 1041*6185db85Sdougm 1042*6185db85Sdougm if (sec == NULL) { 1043*6185db85Sdougm (void) printf(" %s=(", proto ? proto : gettext("all")); 1044*6185db85Sdougm } else { 1045*6185db85Sdougm (void) printf(" %s:%s=(", proto ? proto : gettext("all"), sec); 1046*6185db85Sdougm } 1047*6185db85Sdougm 1048*6185db85Sdougm for (spacer = 0, prop = sa_get_property(optionset, NULL); 1049*6185db85Sdougm prop != NULL; prop = sa_get_next_property(prop)) { 1050*6185db85Sdougm 1051*6185db85Sdougm /* 1052*6185db85Sdougm * extract the property name/value and output with 1053*6185db85Sdougm * appropriate spacing. I.e. no prefixed space the 1054*6185db85Sdougm * first time through but a space on subsequent 1055*6185db85Sdougm * properties. 1056*6185db85Sdougm */ 1057*6185db85Sdougm type = sa_get_property_attr(prop, "type"); 1058*6185db85Sdougm value = sa_get_property_attr(prop, "value"); 1059*6185db85Sdougm if (type != NULL) { 1060*6185db85Sdougm (void) printf("%s%s=", spacer ? " " : "", type); 1061*6185db85Sdougm spacer = 1; 1062*6185db85Sdougm if (value != NULL) 1063*6185db85Sdougm (void) printf("\"%s\"", value); 1064*6185db85Sdougm else 1065*6185db85Sdougm (void) printf("\"\""); 1066*6185db85Sdougm } 1067*6185db85Sdougm if (type != NULL) 1068*6185db85Sdougm sa_free_attr_string(type); 1069*6185db85Sdougm if (value != NULL) 1070*6185db85Sdougm sa_free_attr_string(value); 1071*6185db85Sdougm } 1072*6185db85Sdougm (void) printf(")"); 1073*6185db85Sdougm } 1074*6185db85Sdougm 1075*6185db85Sdougm /* 1076*6185db85Sdougm * show_properties(group, protocol, prefix) 1077*6185db85Sdougm * 1078*6185db85Sdougm * print the properties for a group. If protocol is NULL, do all 1079*6185db85Sdougm * protocols otherwise only the specified protocol. All security 1080*6185db85Sdougm * (named groups specific to the protocol) are included. 1081*6185db85Sdougm * 1082*6185db85Sdougm * The "prefix" is always applied. The caller knows whether it wants 1083*6185db85Sdougm * some type of prefix string (white space) or not. Once the prefix 1084*6185db85Sdougm * has been output, it is reduced to the zero length string for the 1085*6185db85Sdougm * remainder of the property output. 1086*6185db85Sdougm */ 1087*6185db85Sdougm 1088*6185db85Sdougm static void 1089*6185db85Sdougm show_properties(sa_group_t group, char *protocol, char *prefix) 1090*6185db85Sdougm { 1091*6185db85Sdougm sa_optionset_t optionset; 1092*6185db85Sdougm sa_security_t security; 1093*6185db85Sdougm char *value; 1094*6185db85Sdougm char *secvalue; 1095*6185db85Sdougm 1096*6185db85Sdougm if (protocol != NULL) { 1097*6185db85Sdougm optionset = sa_get_optionset(group, protocol); 1098*6185db85Sdougm if (optionset != NULL) { 1099*6185db85Sdougm (void) printf("%s", prefix); 1100*6185db85Sdougm prefix = ""; 1101*6185db85Sdougm out_properties(optionset, protocol, NULL); 1102*6185db85Sdougm } 1103*6185db85Sdougm security = sa_get_security(group, protocol, NULL); 1104*6185db85Sdougm if (security != NULL) { 1105*6185db85Sdougm (void) printf("%s", prefix); 1106*6185db85Sdougm prefix = ""; 1107*6185db85Sdougm out_properties(security, protocol, NULL); 1108*6185db85Sdougm } 1109*6185db85Sdougm } else { 1110*6185db85Sdougm for (optionset = sa_get_optionset(group, protocol); 1111*6185db85Sdougm optionset != NULL; 1112*6185db85Sdougm optionset = sa_get_next_optionset(optionset)) { 1113*6185db85Sdougm 1114*6185db85Sdougm value = sa_get_optionset_attr(optionset, "type"); 1115*6185db85Sdougm (void) printf("%s", prefix); 1116*6185db85Sdougm prefix = ""; 1117*6185db85Sdougm out_properties(optionset, value, 0); 1118*6185db85Sdougm if (value != NULL) 1119*6185db85Sdougm sa_free_attr_string(value); 1120*6185db85Sdougm } 1121*6185db85Sdougm for (security = sa_get_security(group, NULL, protocol); 1122*6185db85Sdougm security != NULL; 1123*6185db85Sdougm security = sa_get_next_security(security)) { 1124*6185db85Sdougm 1125*6185db85Sdougm value = sa_get_security_attr(security, "type"); 1126*6185db85Sdougm secvalue = sa_get_security_attr(security, "sectype"); 1127*6185db85Sdougm (void) printf("%s", prefix); 1128*6185db85Sdougm prefix = ""; 1129*6185db85Sdougm out_properties(security, value, secvalue); 1130*6185db85Sdougm if (value != NULL) 1131*6185db85Sdougm sa_free_attr_string(value); 1132*6185db85Sdougm if (secvalue != NULL) 1133*6185db85Sdougm sa_free_attr_string(secvalue); 1134*6185db85Sdougm } 1135*6185db85Sdougm } 1136*6185db85Sdougm } 1137*6185db85Sdougm 1138*6185db85Sdougm /* 1139*6185db85Sdougm * show_group(group, verbose, properties, proto, subgroup) 1140*6185db85Sdougm * 1141*6185db85Sdougm * helper function to show the contents of a group. 1142*6185db85Sdougm */ 1143*6185db85Sdougm 1144*6185db85Sdougm static void 1145*6185db85Sdougm show_group(sa_group_t group, int verbose, int properties, char *proto, 1146*6185db85Sdougm char *subgroup) 1147*6185db85Sdougm { 1148*6185db85Sdougm sa_share_t share; 1149*6185db85Sdougm char *groupname; 1150*6185db85Sdougm char *sharepath; 1151*6185db85Sdougm char *resource; 1152*6185db85Sdougm char *description; 1153*6185db85Sdougm char *type; 1154*6185db85Sdougm char *zfs = NULL; 1155*6185db85Sdougm int iszfs = 0; 1156*6185db85Sdougm 1157*6185db85Sdougm groupname = sa_get_group_attr(group, "name"); 1158*6185db85Sdougm if (groupname != NULL) { 1159*6185db85Sdougm if (proto != NULL && !has_protocol(group, proto)) { 1160*6185db85Sdougm sa_free_attr_string(groupname); 1161*6185db85Sdougm return; 1162*6185db85Sdougm } 1163*6185db85Sdougm /* 1164*6185db85Sdougm * check to see if the group is managed by ZFS. If 1165*6185db85Sdougm * there is an attribute, then it is. A non-NULL zfs 1166*6185db85Sdougm * variable will trigger the different way to display 1167*6185db85Sdougm * and will remove the transient property indicator 1168*6185db85Sdougm * from the output. 1169*6185db85Sdougm */ 1170*6185db85Sdougm zfs = sa_get_group_attr(group, "zfs"); 1171*6185db85Sdougm if (zfs != NULL) { 1172*6185db85Sdougm iszfs = 1; 1173*6185db85Sdougm sa_free_attr_string(zfs); 1174*6185db85Sdougm } 1175*6185db85Sdougm share = sa_get_share(group, NULL); 1176*6185db85Sdougm if (subgroup == NULL) 1177*6185db85Sdougm (void) printf("%s", groupname); 1178*6185db85Sdougm else 1179*6185db85Sdougm (void) printf(" %s/%s", subgroup, groupname); 1180*6185db85Sdougm if (properties) { 1181*6185db85Sdougm show_properties(group, proto, ""); 1182*6185db85Sdougm } 1183*6185db85Sdougm (void) printf("\n"); 1184*6185db85Sdougm if (strcmp(groupname, "zfs") == 0) { 1185*6185db85Sdougm sa_group_t zgroup; 1186*6185db85Sdougm 1187*6185db85Sdougm for (zgroup = sa_get_sub_group(group); zgroup != NULL; 1188*6185db85Sdougm zgroup = sa_get_next_group(zgroup)) { 1189*6185db85Sdougm show_group(zgroup, verbose, properties, proto, "zfs"); 1190*6185db85Sdougm } 1191*6185db85Sdougm sa_free_attr_string(groupname); 1192*6185db85Sdougm return; 1193*6185db85Sdougm } 1194*6185db85Sdougm /* 1195*6185db85Sdougm * have a group, so list the contents. Resource and 1196*6185db85Sdougm * description are only listed if verbose is set. 1197*6185db85Sdougm */ 1198*6185db85Sdougm for (share = sa_get_share(group, NULL); share != NULL; 1199*6185db85Sdougm share = sa_get_next_share(share)) { 1200*6185db85Sdougm sharepath = sa_get_share_attr(share, "path"); 1201*6185db85Sdougm if (sharepath != NULL) { 1202*6185db85Sdougm if (verbose) { 1203*6185db85Sdougm resource = sa_get_share_attr(share, "resource"); 1204*6185db85Sdougm description = sa_get_share_description(share); 1205*6185db85Sdougm type = sa_get_share_attr(share, "type"); 1206*6185db85Sdougm if (type != NULL && !iszfs && 1207*6185db85Sdougm strcmp(type, "transient") == 0) 1208*6185db85Sdougm (void) printf("\t* "); 1209*6185db85Sdougm else 1210*6185db85Sdougm (void) printf("\t "); 1211*6185db85Sdougm if (resource != NULL && strlen(resource) > 0) { 1212*6185db85Sdougm (void) printf("%s=%s", resource, sharepath); 1213*6185db85Sdougm } else { 1214*6185db85Sdougm (void) printf("%s", sharepath); 1215*6185db85Sdougm } 1216*6185db85Sdougm if (resource != NULL) 1217*6185db85Sdougm sa_free_attr_string(resource); 1218*6185db85Sdougm if (properties) 1219*6185db85Sdougm show_properties(share, NULL, "\t"); 1220*6185db85Sdougm if (description != NULL) { 1221*6185db85Sdougm if (strlen(description) > 0) { 1222*6185db85Sdougm (void) printf("\t\"%s\"", description); 1223*6185db85Sdougm } 1224*6185db85Sdougm sa_free_share_description(description); 1225*6185db85Sdougm } 1226*6185db85Sdougm if (type != NULL) 1227*6185db85Sdougm sa_free_attr_string(type); 1228*6185db85Sdougm } else { 1229*6185db85Sdougm (void) printf("\t%s", sharepath); 1230*6185db85Sdougm if (properties) 1231*6185db85Sdougm show_properties(share, NULL, "\t"); 1232*6185db85Sdougm } 1233*6185db85Sdougm (void) printf("\n"); 1234*6185db85Sdougm sa_free_attr_string(sharepath); 1235*6185db85Sdougm } 1236*6185db85Sdougm } 1237*6185db85Sdougm } 1238*6185db85Sdougm if (groupname != NULL) { 1239*6185db85Sdougm sa_free_attr_string(groupname); 1240*6185db85Sdougm } 1241*6185db85Sdougm } 1242*6185db85Sdougm 1243*6185db85Sdougm /* 1244*6185db85Sdougm * show_group_xml_init() 1245*6185db85Sdougm * 1246*6185db85Sdougm * Create an XML document that will be used to display config info via 1247*6185db85Sdougm * XML format. 1248*6185db85Sdougm */ 1249*6185db85Sdougm 1250*6185db85Sdougm xmlDocPtr 1251*6185db85Sdougm show_group_xml_init() 1252*6185db85Sdougm { 1253*6185db85Sdougm xmlDocPtr doc; 1254*6185db85Sdougm xmlNodePtr root; 1255*6185db85Sdougm 1256*6185db85Sdougm doc = xmlNewDoc((xmlChar *)"1.0"); 1257*6185db85Sdougm if (doc != NULL) { 1258*6185db85Sdougm root = xmlNewNode(NULL, (xmlChar *)"sharecfg"); 1259*6185db85Sdougm if (root != NULL) 1260*6185db85Sdougm xmlDocSetRootElement(doc, root); 1261*6185db85Sdougm } 1262*6185db85Sdougm return (doc); 1263*6185db85Sdougm } 1264*6185db85Sdougm 1265*6185db85Sdougm /* 1266*6185db85Sdougm * show_group_xml(doc, group) 1267*6185db85Sdougm * 1268*6185db85Sdougm * Copy the group info into the XML doc. 1269*6185db85Sdougm */ 1270*6185db85Sdougm 1271*6185db85Sdougm static void 1272*6185db85Sdougm show_group_xml(xmlDocPtr doc, sa_group_t group) 1273*6185db85Sdougm { 1274*6185db85Sdougm xmlNodePtr node; 1275*6185db85Sdougm xmlNodePtr root; 1276*6185db85Sdougm 1277*6185db85Sdougm root = xmlDocGetRootElement(doc); 1278*6185db85Sdougm node = xmlCopyNode((xmlNodePtr)group, 1); 1279*6185db85Sdougm if (node != NULL && root != NULL) { 1280*6185db85Sdougm xmlAddChild(root, node); 1281*6185db85Sdougm /* 1282*6185db85Sdougm * In the future, we may have interally used tags that 1283*6185db85Sdougm * should not appear in the XML output. Remove 1284*6185db85Sdougm * anything we don't want to show here. 1285*6185db85Sdougm */ 1286*6185db85Sdougm } 1287*6185db85Sdougm } 1288*6185db85Sdougm 1289*6185db85Sdougm /* 1290*6185db85Sdougm * sa_show(flags, argc, argv) 1291*6185db85Sdougm * 1292*6185db85Sdougm * Implements the show subcommand. 1293*6185db85Sdougm */ 1294*6185db85Sdougm 1295*6185db85Sdougm int 1296*6185db85Sdougm sa_show(int flags, int argc, char *argv[]) 1297*6185db85Sdougm { 1298*6185db85Sdougm sa_group_t group; 1299*6185db85Sdougm int verbose = 0; 1300*6185db85Sdougm int properties = 0; 1301*6185db85Sdougm int c; 1302*6185db85Sdougm int ret = SA_OK; 1303*6185db85Sdougm char *protocol = NULL; 1304*6185db85Sdougm int xml = 0; 1305*6185db85Sdougm xmlDocPtr doc; 1306*6185db85Sdougm #ifdef lint 1307*6185db85Sdougm flags = flags; 1308*6185db85Sdougm #endif 1309*6185db85Sdougm 1310*6185db85Sdougm while ((c = getopt(argc, argv, "?hvP:px")) != EOF) { 1311*6185db85Sdougm switch (c) { 1312*6185db85Sdougm case 'v': 1313*6185db85Sdougm verbose++; 1314*6185db85Sdougm break; 1315*6185db85Sdougm case 'p': 1316*6185db85Sdougm properties++; 1317*6185db85Sdougm break; 1318*6185db85Sdougm case 'P': 1319*6185db85Sdougm protocol = optarg; 1320*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 1321*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 1322*6185db85Sdougm protocol); 1323*6185db85Sdougm return (SA_INVALID_PROTOCOL); 1324*6185db85Sdougm } 1325*6185db85Sdougm break; 1326*6185db85Sdougm case 'x': 1327*6185db85Sdougm xml++; 1328*6185db85Sdougm break; 1329*6185db85Sdougm default: 1330*6185db85Sdougm case 'h': 1331*6185db85Sdougm case '?': 1332*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_SHOW)); 1333*6185db85Sdougm return (0); 1334*6185db85Sdougm } 1335*6185db85Sdougm } 1336*6185db85Sdougm 1337*6185db85Sdougm if (xml) { 1338*6185db85Sdougm doc = show_group_xml_init(); 1339*6185db85Sdougm if (doc == NULL) 1340*6185db85Sdougm ret = SA_NO_MEMORY; 1341*6185db85Sdougm } 1342*6185db85Sdougm 1343*6185db85Sdougm if (optind == argc) { 1344*6185db85Sdougm /* no group specified so go through them all */ 1345*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 1346*6185db85Sdougm group = sa_get_next_group(group)) { 1347*6185db85Sdougm /* 1348*6185db85Sdougm * have a group so check if one we want and then list 1349*6185db85Sdougm * contents with appropriate options. 1350*6185db85Sdougm */ 1351*6185db85Sdougm if (xml) 1352*6185db85Sdougm show_group_xml(doc, group); 1353*6185db85Sdougm else 1354*6185db85Sdougm show_group(group, verbose, properties, protocol, NULL); 1355*6185db85Sdougm } 1356*6185db85Sdougm } else { 1357*6185db85Sdougm /* have a specified list of groups */ 1358*6185db85Sdougm for (; optind < argc; optind++) { 1359*6185db85Sdougm group = sa_get_group(argv[optind]); 1360*6185db85Sdougm if (group != NULL) { 1361*6185db85Sdougm if (xml) 1362*6185db85Sdougm show_group_xml(doc, group); 1363*6185db85Sdougm else 1364*6185db85Sdougm show_group(group, verbose, properties, protocol, NULL); 1365*6185db85Sdougm } else { 1366*6185db85Sdougm (void) printf(gettext("%s: not found\n"), argv[optind]); 1367*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 1368*6185db85Sdougm } 1369*6185db85Sdougm } 1370*6185db85Sdougm } 1371*6185db85Sdougm if (xml && ret == SA_OK) { 1372*6185db85Sdougm xmlDocFormatDump(stdout, doc, 1); 1373*6185db85Sdougm xmlFreeDoc(doc); 1374*6185db85Sdougm } 1375*6185db85Sdougm return (ret); 1376*6185db85Sdougm 1377*6185db85Sdougm } 1378*6185db85Sdougm 1379*6185db85Sdougm /* 1380*6185db85Sdougm * enable_share(group, share, update_legacy) 1381*6185db85Sdougm * 1382*6185db85Sdougm * helper function to enable a share if the group is enabled. 1383*6185db85Sdougm */ 1384*6185db85Sdougm 1385*6185db85Sdougm static int 1386*6185db85Sdougm enable_share(sa_group_t group, sa_share_t share, int update_legacy) 1387*6185db85Sdougm { 1388*6185db85Sdougm char *value; 1389*6185db85Sdougm int enabled; 1390*6185db85Sdougm sa_optionset_t optionset; 1391*6185db85Sdougm int ret = SA_OK; 1392*6185db85Sdougm char *zfs = NULL; 1393*6185db85Sdougm int iszfs = 0; 1394*6185db85Sdougm 1395*6185db85Sdougm /* 1396*6185db85Sdougm * need to enable this share if the group is enabled but not 1397*6185db85Sdougm * otherwise. The enable is also done on each protocol 1398*6185db85Sdougm * represented in the group. 1399*6185db85Sdougm */ 1400*6185db85Sdougm value = sa_get_group_attr(group, "state"); 1401*6185db85Sdougm enabled = value != NULL && strcmp(value, "enabled") == 0; 1402*6185db85Sdougm if (value != NULL) 1403*6185db85Sdougm sa_free_attr_string(value); 1404*6185db85Sdougm /* remove legacy config if necessary */ 1405*6185db85Sdougm if (update_legacy) 1406*6185db85Sdougm ret = sa_delete_legacy(share); 1407*6185db85Sdougm zfs = sa_get_group_attr(group, "zfs"); 1408*6185db85Sdougm if (zfs != NULL) { 1409*6185db85Sdougm iszfs++; 1410*6185db85Sdougm sa_free_attr_string(zfs); 1411*6185db85Sdougm } 1412*6185db85Sdougm 1413*6185db85Sdougm /* 1414*6185db85Sdougm * Step through each optionset at the group level and 1415*6185db85Sdougm * enable the share based on the protocol type. This 1416*6185db85Sdougm * works because protocols must be set on the group 1417*6185db85Sdougm * for the protocol to be enabled. 1418*6185db85Sdougm */ 1419*6185db85Sdougm for (optionset = sa_get_optionset(group, NULL); 1420*6185db85Sdougm optionset != NULL && ret == SA_OK; 1421*6185db85Sdougm optionset = sa_get_next_optionset(optionset)) { 1422*6185db85Sdougm value = sa_get_optionset_attr(optionset, "type"); 1423*6185db85Sdougm if (value != NULL) { 1424*6185db85Sdougm if (enabled) 1425*6185db85Sdougm ret = sa_enable_share(share, value); 1426*6185db85Sdougm if (update_legacy && !iszfs) 1427*6185db85Sdougm (void) sa_update_legacy(share, value); 1428*6185db85Sdougm sa_free_attr_string(value); 1429*6185db85Sdougm } 1430*6185db85Sdougm } 1431*6185db85Sdougm if (ret == SA_OK) 1432*6185db85Sdougm (void) sa_update_config(); 1433*6185db85Sdougm return (ret); 1434*6185db85Sdougm } 1435*6185db85Sdougm 1436*6185db85Sdougm /* 1437*6185db85Sdougm * sa_addshare(flags, argc, argv) 1438*6185db85Sdougm * 1439*6185db85Sdougm * implements add-share subcommand. 1440*6185db85Sdougm */ 1441*6185db85Sdougm 1442*6185db85Sdougm int 1443*6185db85Sdougm sa_addshare(int flags, int argc, char *argv[]) 1444*6185db85Sdougm { 1445*6185db85Sdougm int verbose = 0; 1446*6185db85Sdougm int dryrun = 0; 1447*6185db85Sdougm int c; 1448*6185db85Sdougm int ret = SA_OK; 1449*6185db85Sdougm sa_group_t group; 1450*6185db85Sdougm sa_share_t share; 1451*6185db85Sdougm char *sharepath = NULL; 1452*6185db85Sdougm char *description = NULL; 1453*6185db85Sdougm char *resource = NULL; 1454*6185db85Sdougm int persist = SA_SHARE_PERMANENT; /* default to persist */ 1455*6185db85Sdougm int auth; 1456*6185db85Sdougm char dir[MAXPATHLEN]; 1457*6185db85Sdougm 1458*6185db85Sdougm while ((c = getopt(argc, argv, "?hvns:d:r:t")) != EOF) { 1459*6185db85Sdougm switch (c) { 1460*6185db85Sdougm case 'n': 1461*6185db85Sdougm dryrun++; 1462*6185db85Sdougm break; 1463*6185db85Sdougm case 'v': 1464*6185db85Sdougm verbose++; 1465*6185db85Sdougm break; 1466*6185db85Sdougm case 'd': 1467*6185db85Sdougm description = optarg; 1468*6185db85Sdougm break; 1469*6185db85Sdougm case 'r': 1470*6185db85Sdougm resource = optarg; 1471*6185db85Sdougm break; 1472*6185db85Sdougm case 's': 1473*6185db85Sdougm /* 1474*6185db85Sdougm * save share path into group. Currently limit 1475*6185db85Sdougm * to one share per command. 1476*6185db85Sdougm */ 1477*6185db85Sdougm if (sharepath != NULL) { 1478*6185db85Sdougm (void) printf(gettext("Adding multiple shares not" 1479*6185db85Sdougm "supported\n")); 1480*6185db85Sdougm return (1); 1481*6185db85Sdougm } 1482*6185db85Sdougm sharepath = optarg; 1483*6185db85Sdougm break; 1484*6185db85Sdougm case 't': 1485*6185db85Sdougm persist = SA_SHARE_TRANSIENT; 1486*6185db85Sdougm break; 1487*6185db85Sdougm default: 1488*6185db85Sdougm case 'h': 1489*6185db85Sdougm case '?': 1490*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1491*6185db85Sdougm sa_get_usage(USAGE_ADD_SHARE)); 1492*6185db85Sdougm return (0); 1493*6185db85Sdougm } 1494*6185db85Sdougm } 1495*6185db85Sdougm 1496*6185db85Sdougm if (optind >= argc) { 1497*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1498*6185db85Sdougm sa_get_usage(USAGE_ADD_SHARE)); 1499*6185db85Sdougm if (dryrun || sharepath != NULL || description != NULL || 1500*6185db85Sdougm resource != NULL || verbose || persist) { 1501*6185db85Sdougm (void) printf(gettext("\tgroup must be specified\n")); 1502*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 1503*6185db85Sdougm } else { 1504*6185db85Sdougm ret = SA_OK; 1505*6185db85Sdougm } 1506*6185db85Sdougm } else { 1507*6185db85Sdougm if (sharepath == NULL) { 1508*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1509*6185db85Sdougm sa_get_usage(USAGE_ADD_SHARE)); 1510*6185db85Sdougm (void) printf(gettext("\t-s sharepath must be specified\n")); 1511*6185db85Sdougm ret = SA_BAD_PATH; 1512*6185db85Sdougm } 1513*6185db85Sdougm if (ret == SA_OK) { 1514*6185db85Sdougm if (realpath(sharepath, dir) == NULL) { 1515*6185db85Sdougm ret = SA_BAD_PATH; 1516*6185db85Sdougm (void) printf(gettext("Path is not valid: %s\n"), 1517*6185db85Sdougm sharepath); 1518*6185db85Sdougm } else { 1519*6185db85Sdougm sharepath = dir; 1520*6185db85Sdougm } 1521*6185db85Sdougm } 1522*6185db85Sdougm if (ret == SA_OK && resource != NULL) { 1523*6185db85Sdougm /* check for valid syntax */ 1524*6185db85Sdougm if (strpbrk(resource, " \t/") != NULL) { 1525*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1526*6185db85Sdougm sa_get_usage(USAGE_ADD_SHARE)); 1527*6185db85Sdougm (void) printf(gettext("\tresource must not contain white" 1528*6185db85Sdougm "space or '/' characters\n")); 1529*6185db85Sdougm ret = SA_BAD_PATH; 1530*6185db85Sdougm } 1531*6185db85Sdougm } 1532*6185db85Sdougm if (ret == SA_OK) { 1533*6185db85Sdougm group = sa_get_group(argv[optind]); 1534*6185db85Sdougm if (group != NULL) { 1535*6185db85Sdougm auth = check_authorizations(argv[optind], flags); 1536*6185db85Sdougm share = sa_find_share(sharepath); 1537*6185db85Sdougm if (share != NULL) { 1538*6185db85Sdougm group = sa_get_parent_group(share); 1539*6185db85Sdougm if (group != NULL) { 1540*6185db85Sdougm char *groupname; 1541*6185db85Sdougm groupname = sa_get_group_attr(group, "name"); 1542*6185db85Sdougm if (groupname != NULL) { 1543*6185db85Sdougm (void) printf(gettext("Share path already " 1544*6185db85Sdougm "shared in group " 1545*6185db85Sdougm "\"%s\": %s\n"), 1546*6185db85Sdougm groupname, sharepath); 1547*6185db85Sdougm sa_free_attr_string(groupname); 1548*6185db85Sdougm } else { 1549*6185db85Sdougm (void) printf(gettext("Share path already" 1550*6185db85Sdougm "shared: %s\n"), 1551*6185db85Sdougm groupname, sharepath); 1552*6185db85Sdougm } 1553*6185db85Sdougm } else { 1554*6185db85Sdougm (void) printf(gettext("Share path %s already " 1555*6185db85Sdougm "shared\n"), 1556*6185db85Sdougm sharepath); 1557*6185db85Sdougm } 1558*6185db85Sdougm ret = SA_DUPLICATE_NAME; 1559*6185db85Sdougm } else { 1560*6185db85Sdougm /* 1561*6185db85Sdougm * need to check that resource name is unique 1562*6185db85Sdougm * at some point. 1563*6185db85Sdougm */ 1564*6185db85Sdougm if (dryrun) 1565*6185db85Sdougm ret = sa_check_path(group, sharepath); 1566*6185db85Sdougm else 1567*6185db85Sdougm share = sa_add_share(group, sharepath, 1568*6185db85Sdougm persist, &ret); 1569*6185db85Sdougm if (!dryrun && share == NULL) { 1570*6185db85Sdougm (void) printf(gettext("Could not add share: " 1571*6185db85Sdougm "%s\n"), 1572*6185db85Sdougm sa_errorstr(ret)); 1573*6185db85Sdougm } else { 1574*6185db85Sdougm if (!dryrun && ret == SA_OK) { 1575*6185db85Sdougm if (resource != NULL) { 1576*6185db85Sdougm if (strpbrk(resource, " \t/") == NULL) { 1577*6185db85Sdougm ret = sa_set_share_attr(share, 1578*6185db85Sdougm "resource", 1579*6185db85Sdougm resource); 1580*6185db85Sdougm } 1581*6185db85Sdougm } 1582*6185db85Sdougm if (ret == SA_OK && description != NULL) { 1583*6185db85Sdougm ret = sa_set_share_description(share, 1584*6185db85Sdougm description); 1585*6185db85Sdougm } 1586*6185db85Sdougm if (ret == SA_OK) { 1587*6185db85Sdougm /* now enable the share(s) */ 1588*6185db85Sdougm ret = enable_share(group, share, 1); 1589*6185db85Sdougm ret = sa_update_config(); 1590*6185db85Sdougm } 1591*6185db85Sdougm switch (ret) { 1592*6185db85Sdougm case SA_DUPLICATE_NAME: 1593*6185db85Sdougm (void) printf(gettext("Resource name in" 1594*6185db85Sdougm "use: %s\n"), 1595*6185db85Sdougm resource); 1596*6185db85Sdougm break; 1597*6185db85Sdougm default: 1598*6185db85Sdougm (void) printf(gettext("Could not set " 1599*6185db85Sdougm "attribute: %s\n"), 1600*6185db85Sdougm sa_errorstr(ret)); 1601*6185db85Sdougm break; 1602*6185db85Sdougm case SA_OK: 1603*6185db85Sdougm break; 1604*6185db85Sdougm } 1605*6185db85Sdougm } else if (dryrun && ret == SA_OK && 1606*6185db85Sdougm !auth && verbose) { 1607*6185db85Sdougm (void) printf(gettext("Command would fail: " 1608*6185db85Sdougm "%s\n"), 1609*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 1610*6185db85Sdougm ret = SA_NO_PERMISSION; 1611*6185db85Sdougm } 1612*6185db85Sdougm } 1613*6185db85Sdougm } 1614*6185db85Sdougm } else { 1615*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), 1616*6185db85Sdougm argv[optind]); 1617*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 1618*6185db85Sdougm } 1619*6185db85Sdougm } 1620*6185db85Sdougm } 1621*6185db85Sdougm return (ret); 1622*6185db85Sdougm } 1623*6185db85Sdougm 1624*6185db85Sdougm /* 1625*6185db85Sdougm * sa_moveshare(flags, argc, argv) 1626*6185db85Sdougm * 1627*6185db85Sdougm * implements move-share subcommand. 1628*6185db85Sdougm */ 1629*6185db85Sdougm 1630*6185db85Sdougm int 1631*6185db85Sdougm sa_moveshare(int flags, int argc, char *argv[]) 1632*6185db85Sdougm { 1633*6185db85Sdougm int verbose = 0; 1634*6185db85Sdougm int dryrun = 0; 1635*6185db85Sdougm int c; 1636*6185db85Sdougm int ret = SA_OK; 1637*6185db85Sdougm sa_group_t group; 1638*6185db85Sdougm sa_share_t share; 1639*6185db85Sdougm char *sharepath = NULL; 1640*6185db85Sdougm int authsrc = 0, authdst = 0; 1641*6185db85Sdougm 1642*6185db85Sdougm while ((c = getopt(argc, argv, "?hvns:")) != EOF) { 1643*6185db85Sdougm switch (c) { 1644*6185db85Sdougm case 'n': 1645*6185db85Sdougm dryrun++; 1646*6185db85Sdougm break; 1647*6185db85Sdougm case 'v': 1648*6185db85Sdougm verbose++; 1649*6185db85Sdougm break; 1650*6185db85Sdougm case 's': 1651*6185db85Sdougm /* 1652*6185db85Sdougm * remove share path from group. Currently limit 1653*6185db85Sdougm * to one share per command. 1654*6185db85Sdougm */ 1655*6185db85Sdougm if (sharepath != NULL) { 1656*6185db85Sdougm (void) printf(gettext("Moving multiple shares not" 1657*6185db85Sdougm "supported\n")); 1658*6185db85Sdougm return (SA_BAD_PATH); 1659*6185db85Sdougm } 1660*6185db85Sdougm sharepath = optarg; 1661*6185db85Sdougm break; 1662*6185db85Sdougm default: 1663*6185db85Sdougm case 'h': 1664*6185db85Sdougm case '?': 1665*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1666*6185db85Sdougm sa_get_usage(USAGE_MOVE_SHARE)); 1667*6185db85Sdougm return (0); 1668*6185db85Sdougm } 1669*6185db85Sdougm } 1670*6185db85Sdougm 1671*6185db85Sdougm if (optind >= argc || sharepath == NULL) { 1672*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1673*6185db85Sdougm sa_get_usage(USAGE_MOVE_SHARE)); 1674*6185db85Sdougm if (dryrun || verbose || sharepath != NULL) { 1675*6185db85Sdougm (void) printf(gettext("\tgroup must be specified\n")); 1676*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 1677*6185db85Sdougm } else { 1678*6185db85Sdougm if (sharepath == NULL) { 1679*6185db85Sdougm ret = SA_SYNTAX_ERR; 1680*6185db85Sdougm (void) printf(gettext("\tsharepath must be specified\n")); 1681*6185db85Sdougm } else 1682*6185db85Sdougm ret = SA_OK; 1683*6185db85Sdougm } 1684*6185db85Sdougm } else { 1685*6185db85Sdougm if (sharepath == NULL) { 1686*6185db85Sdougm (void) printf(gettext("sharepath must be specified with " 1687*6185db85Sdougm "the -s option\n")); 1688*6185db85Sdougm ret = SA_BAD_PATH; 1689*6185db85Sdougm } else { 1690*6185db85Sdougm group = sa_get_group(argv[optind]); 1691*6185db85Sdougm if (group != NULL) { 1692*6185db85Sdougm share = sa_find_share(sharepath); 1693*6185db85Sdougm authdst = check_authorizations(argv[optind], flags); 1694*6185db85Sdougm if (share == NULL) { 1695*6185db85Sdougm (void) printf(gettext("Share not found: %s\n"), 1696*6185db85Sdougm sharepath); 1697*6185db85Sdougm ret = SA_NO_SUCH_PATH; 1698*6185db85Sdougm } else { 1699*6185db85Sdougm sa_group_t parent; 1700*6185db85Sdougm char *zfsold; 1701*6185db85Sdougm char *zfsnew; 1702*6185db85Sdougm 1703*6185db85Sdougm parent = sa_get_parent_group(share); 1704*6185db85Sdougm if (parent != NULL) { 1705*6185db85Sdougm char *pname; 1706*6185db85Sdougm pname = sa_get_group_attr(parent, "name"); 1707*6185db85Sdougm if (pname != NULL) { 1708*6185db85Sdougm authsrc = check_authorizations(pname, flags); 1709*6185db85Sdougm sa_free_attr_string(pname); 1710*6185db85Sdougm } 1711*6185db85Sdougm zfsold = sa_get_group_attr(parent, "zfs"); 1712*6185db85Sdougm zfsnew = sa_get_group_attr(group, "zfs"); 1713*6185db85Sdougm if ((zfsold != NULL && zfsnew == NULL) || 1714*6185db85Sdougm (zfsold == NULL && zfsnew != NULL)) { 1715*6185db85Sdougm ret = SA_NOT_ALLOWED; 1716*6185db85Sdougm } 1717*6185db85Sdougm if (zfsold != NULL) 1718*6185db85Sdougm sa_free_attr_string(zfsold); 1719*6185db85Sdougm if (zfsnew != NULL) 1720*6185db85Sdougm sa_free_attr_string(zfsnew); 1721*6185db85Sdougm } 1722*6185db85Sdougm if (!dryrun && ret == SA_OK) { 1723*6185db85Sdougm ret = sa_move_share(group, share); 1724*6185db85Sdougm } 1725*6185db85Sdougm if (ret == SA_OK && parent != group && !dryrun) { 1726*6185db85Sdougm char *oldstate; 1727*6185db85Sdougm ret = sa_update_config(); 1728*6185db85Sdougm /* 1729*6185db85Sdougm * note that the share may need to be 1730*6185db85Sdougm * "unshared" if the new group is 1731*6185db85Sdougm * disabled and the old was enabled or 1732*6185db85Sdougm * it may need to be share to update 1733*6185db85Sdougm * if the new group is enabled. 1734*6185db85Sdougm */ 1735*6185db85Sdougm oldstate = sa_get_group_attr(parent, "state"); 1736*6185db85Sdougm /* enable_share determines what to do */ 1737*6185db85Sdougm if (strcmp(oldstate, "enabled") == 0) { 1738*6185db85Sdougm (void) sa_disable_share(share, NULL); 1739*6185db85Sdougm } 1740*6185db85Sdougm (void) enable_share(group, share, 1); 1741*6185db85Sdougm if (oldstate != NULL) 1742*6185db85Sdougm sa_free_attr_string(oldstate); 1743*6185db85Sdougm } 1744*6185db85Sdougm if (ret != SA_OK) { 1745*6185db85Sdougm (void) printf(gettext("Could not move share: %s\n"), 1746*6185db85Sdougm sa_errorstr(ret)); 1747*6185db85Sdougm } 1748*6185db85Sdougm if (dryrun && ret == SA_OK && !(authsrc & authdst) && 1749*6185db85Sdougm verbose) { 1750*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 1751*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 1752*6185db85Sdougm } 1753*6185db85Sdougm } 1754*6185db85Sdougm } else { 1755*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), 1756*6185db85Sdougm argv[optind]); 1757*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 1758*6185db85Sdougm } 1759*6185db85Sdougm } 1760*6185db85Sdougm } 1761*6185db85Sdougm return (ret); 1762*6185db85Sdougm } 1763*6185db85Sdougm 1764*6185db85Sdougm /* 1765*6185db85Sdougm * sa_removeshare(flags, argc, argv) 1766*6185db85Sdougm * 1767*6185db85Sdougm * implements remove-share subcommand. 1768*6185db85Sdougm */ 1769*6185db85Sdougm 1770*6185db85Sdougm int 1771*6185db85Sdougm sa_removeshare(int flags, int argc, char *argv[]) 1772*6185db85Sdougm { 1773*6185db85Sdougm int verbose = 0; 1774*6185db85Sdougm int dryrun = 0; 1775*6185db85Sdougm int force = 0; 1776*6185db85Sdougm int c; 1777*6185db85Sdougm int ret = SA_OK; 1778*6185db85Sdougm sa_group_t group; 1779*6185db85Sdougm sa_share_t share; 1780*6185db85Sdougm char *sharepath = NULL; 1781*6185db85Sdougm char dir[MAXPATHLEN]; 1782*6185db85Sdougm int auth; 1783*6185db85Sdougm 1784*6185db85Sdougm while ((c = getopt(argc, argv, "?hfns:v")) != EOF) { 1785*6185db85Sdougm switch (c) { 1786*6185db85Sdougm case 'n': 1787*6185db85Sdougm dryrun++; 1788*6185db85Sdougm break; 1789*6185db85Sdougm case 'v': 1790*6185db85Sdougm verbose++; 1791*6185db85Sdougm break; 1792*6185db85Sdougm case 'f': 1793*6185db85Sdougm force++; 1794*6185db85Sdougm break; 1795*6185db85Sdougm case 's': 1796*6185db85Sdougm /* 1797*6185db85Sdougm * remove share path from group. Currently limit 1798*6185db85Sdougm * to one share per command. 1799*6185db85Sdougm */ 1800*6185db85Sdougm if (sharepath != NULL) { 1801*6185db85Sdougm (void) printf(gettext("Removing multiple shares not" 1802*6185db85Sdougm "supported\n")); 1803*6185db85Sdougm return (SA_SYNTAX_ERR); 1804*6185db85Sdougm } 1805*6185db85Sdougm sharepath = optarg; 1806*6185db85Sdougm break; 1807*6185db85Sdougm default: 1808*6185db85Sdougm case 'h': 1809*6185db85Sdougm case '?': 1810*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1811*6185db85Sdougm sa_get_usage(USAGE_REMOVE_SHARE)); 1812*6185db85Sdougm return (0); 1813*6185db85Sdougm } 1814*6185db85Sdougm } 1815*6185db85Sdougm 1816*6185db85Sdougm if (optind >= argc || sharepath == NULL) { 1817*6185db85Sdougm if (sharepath == NULL) { 1818*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1819*6185db85Sdougm sa_get_usage(USAGE_REMOVE_SHARE)); 1820*6185db85Sdougm (void) printf(gettext("\t-s sharepath must be specified\n")); 1821*6185db85Sdougm ret = SA_BAD_PATH; 1822*6185db85Sdougm } else { 1823*6185db85Sdougm ret = SA_OK; 1824*6185db85Sdougm } 1825*6185db85Sdougm } 1826*6185db85Sdougm if (ret == SA_OK) { 1827*6185db85Sdougm if (optind < argc) { 1828*6185db85Sdougm if ((optind + 1) < argc) { 1829*6185db85Sdougm (void) printf(gettext("Extraneous group(s) at end of " 1830*6185db85Sdougm "command\n")); 1831*6185db85Sdougm ret = SA_SYNTAX_ERR; 1832*6185db85Sdougm } else { 1833*6185db85Sdougm group = sa_get_group(argv[optind]); 1834*6185db85Sdougm if (group == NULL) { 1835*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), 1836*6185db85Sdougm argv[optind]); 1837*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 1838*6185db85Sdougm } 1839*6185db85Sdougm } 1840*6185db85Sdougm } else { 1841*6185db85Sdougm group = NULL; 1842*6185db85Sdougm } 1843*6185db85Sdougm if (ret == SA_OK) { 1844*6185db85Sdougm if (realpath(sharepath, dir) == NULL) { 1845*6185db85Sdougm ret = SA_BAD_PATH; 1846*6185db85Sdougm (void) printf(gettext("Path is not valid: %s\n"), 1847*6185db85Sdougm sharepath); 1848*6185db85Sdougm } else { 1849*6185db85Sdougm sharepath = dir; 1850*6185db85Sdougm } 1851*6185db85Sdougm } 1852*6185db85Sdougm if (ret == SA_OK) { 1853*6185db85Sdougm if (group != NULL) 1854*6185db85Sdougm share = sa_get_share(group, sharepath); 1855*6185db85Sdougm else 1856*6185db85Sdougm share = sa_find_share(sharepath); 1857*6185db85Sdougm if (share == NULL) { 1858*6185db85Sdougm if (group != NULL) 1859*6185db85Sdougm (void) printf(gettext("Share not found in group %s:" 1860*6185db85Sdougm "%s\n"), 1861*6185db85Sdougm argv[optind], sharepath); 1862*6185db85Sdougm else 1863*6185db85Sdougm (void) printf(gettext("Share not found: %s\n"), 1864*6185db85Sdougm sharepath); 1865*6185db85Sdougm ret = SA_NO_SUCH_PATH; 1866*6185db85Sdougm } else { 1867*6185db85Sdougm if (group == NULL) 1868*6185db85Sdougm group = sa_get_parent_group(share); 1869*6185db85Sdougm if (!dryrun) { 1870*6185db85Sdougm if (ret == SA_OK) { 1871*6185db85Sdougm ret = sa_disable_share(share, NULL); 1872*6185db85Sdougm /* 1873*6185db85Sdougm * we don't care if it fails since it 1874*6185db85Sdougm * could be disabled already. 1875*6185db85Sdougm */ 1876*6185db85Sdougm if (ret == SA_OK || ret == SA_NO_SUCH_PATH || 1877*6185db85Sdougm ret == SA_NOT_SUPPORTED) { 1878*6185db85Sdougm ret = sa_remove_share(share); 1879*6185db85Sdougm } 1880*6185db85Sdougm if (ret == SA_OK) 1881*6185db85Sdougm ret = sa_update_config(); 1882*6185db85Sdougm } 1883*6185db85Sdougm if (ret != SA_OK) { 1884*6185db85Sdougm (void) printf(gettext("Could not remove share:" 1885*6185db85Sdougm " %s\n"), 1886*6185db85Sdougm sa_errorstr(ret)); 1887*6185db85Sdougm } 1888*6185db85Sdougm } else if (ret == SA_OK) { 1889*6185db85Sdougm char *pname; 1890*6185db85Sdougm pname = sa_get_group_attr(group, "name"); 1891*6185db85Sdougm if (pname != NULL) { 1892*6185db85Sdougm auth = check_authorizations(pname, flags); 1893*6185db85Sdougm sa_free_attr_string(pname); 1894*6185db85Sdougm } 1895*6185db85Sdougm if (!auth && verbose) { 1896*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 1897*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 1898*6185db85Sdougm } 1899*6185db85Sdougm } 1900*6185db85Sdougm } 1901*6185db85Sdougm } 1902*6185db85Sdougm } 1903*6185db85Sdougm return (ret); 1904*6185db85Sdougm } 1905*6185db85Sdougm 1906*6185db85Sdougm /* 1907*6185db85Sdougm * sa_set_share(flags, argc, argv) 1908*6185db85Sdougm * 1909*6185db85Sdougm * implements set-share subcommand. 1910*6185db85Sdougm */ 1911*6185db85Sdougm 1912*6185db85Sdougm int 1913*6185db85Sdougm sa_set_share(int flags, int argc, char *argv[]) 1914*6185db85Sdougm { 1915*6185db85Sdougm int dryrun = 0; 1916*6185db85Sdougm int c; 1917*6185db85Sdougm int ret = SA_OK; 1918*6185db85Sdougm sa_group_t group, sharegroup; 1919*6185db85Sdougm sa_share_t share; 1920*6185db85Sdougm char *sharepath = NULL; 1921*6185db85Sdougm char *description = NULL; 1922*6185db85Sdougm char *resource = NULL; 1923*6185db85Sdougm int auth; 1924*6185db85Sdougm int verbose = 0; 1925*6185db85Sdougm 1926*6185db85Sdougm while ((c = getopt(argc, argv, "?hnd:r:s:")) != EOF) { 1927*6185db85Sdougm switch (c) { 1928*6185db85Sdougm case 'n': 1929*6185db85Sdougm dryrun++; 1930*6185db85Sdougm break; 1931*6185db85Sdougm case 'd': 1932*6185db85Sdougm description = optarg; 1933*6185db85Sdougm break; 1934*6185db85Sdougm case 'r': 1935*6185db85Sdougm resource = optarg; 1936*6185db85Sdougm break; 1937*6185db85Sdougm case 'v': 1938*6185db85Sdougm verbose++; 1939*6185db85Sdougm break; 1940*6185db85Sdougm case 's': 1941*6185db85Sdougm /* 1942*6185db85Sdougm * save share path into group. Currently limit 1943*6185db85Sdougm * to one share per command. 1944*6185db85Sdougm */ 1945*6185db85Sdougm if (sharepath != NULL) { 1946*6185db85Sdougm (void) printf(gettext("Updating multiple shares not" 1947*6185db85Sdougm "supported\n")); 1948*6185db85Sdougm return (SA_BAD_PATH); 1949*6185db85Sdougm } 1950*6185db85Sdougm sharepath = optarg; 1951*6185db85Sdougm break; 1952*6185db85Sdougm default: 1953*6185db85Sdougm case 'h': 1954*6185db85Sdougm case '?': 1955*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1956*6185db85Sdougm sa_get_usage(USAGE_SET_SHARE)); 1957*6185db85Sdougm return (SA_OK); 1958*6185db85Sdougm } 1959*6185db85Sdougm } 1960*6185db85Sdougm if (optind >= argc || sharepath == NULL) { 1961*6185db85Sdougm if (sharepath == NULL) { 1962*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1963*6185db85Sdougm sa_get_usage(USAGE_SET_SHARE)); 1964*6185db85Sdougm (void) printf(gettext("\tgroup must be specified\n")); 1965*6185db85Sdougm ret = SA_BAD_PATH; 1966*6185db85Sdougm } else { 1967*6185db85Sdougm ret = SA_OK; 1968*6185db85Sdougm } 1969*6185db85Sdougm } 1970*6185db85Sdougm if ((optind + 1) < argc) { 1971*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 1972*6185db85Sdougm sa_get_usage(USAGE_SET_SHARE)); 1973*6185db85Sdougm (void) printf(gettext("\tExtraneous group(s) at end\n")); 1974*6185db85Sdougm ret = SA_SYNTAX_ERR; 1975*6185db85Sdougm } 1976*6185db85Sdougm if (ret == SA_OK) { 1977*6185db85Sdougm char *groupname; 1978*6185db85Sdougm if (optind < argc) { 1979*6185db85Sdougm groupname = argv[optind]; 1980*6185db85Sdougm group = sa_get_group(groupname); 1981*6185db85Sdougm } else { 1982*6185db85Sdougm group = NULL; 1983*6185db85Sdougm groupname = NULL; 1984*6185db85Sdougm } 1985*6185db85Sdougm share = sa_find_share(sharepath); 1986*6185db85Sdougm if (share != NULL) { 1987*6185db85Sdougm sharegroup = sa_get_parent_group(share); 1988*6185db85Sdougm if (group != NULL && group != sharegroup) { 1989*6185db85Sdougm (void) printf(gettext("Group \"%s\" does not contain " 1990*6185db85Sdougm "share %s\n"), 1991*6185db85Sdougm argv[optind], sharepath); 1992*6185db85Sdougm ret = SA_BAD_PATH; 1993*6185db85Sdougm } else { 1994*6185db85Sdougm int delgroupname = 0; 1995*6185db85Sdougm if (groupname == NULL) { 1996*6185db85Sdougm groupname = sa_get_group_attr(sharegroup, "name"); 1997*6185db85Sdougm delgroupname = 1; 1998*6185db85Sdougm } 1999*6185db85Sdougm if (groupname != NULL) { 2000*6185db85Sdougm auth = check_authorizations(groupname, flags); 2001*6185db85Sdougm if (delgroupname) { 2002*6185db85Sdougm sa_free_attr_string(groupname); 2003*6185db85Sdougm groupname = NULL; 2004*6185db85Sdougm } 2005*6185db85Sdougm } else { 2006*6185db85Sdougm ret = SA_NO_MEMORY; 2007*6185db85Sdougm } 2008*6185db85Sdougm if (resource != NULL) { 2009*6185db85Sdougm if (strpbrk(resource, " \t/") == NULL) { 2010*6185db85Sdougm if (!dryrun) { 2011*6185db85Sdougm ret = sa_set_share_attr(share, "resource", 2012*6185db85Sdougm resource); 2013*6185db85Sdougm } else { 2014*6185db85Sdougm sa_share_t resshare; 2015*6185db85Sdougm resshare = sa_get_resource(sharegroup, 2016*6185db85Sdougm resource); 2017*6185db85Sdougm if (resshare != NULL && resshare != share) 2018*6185db85Sdougm ret = SA_DUPLICATE_NAME; 2019*6185db85Sdougm } 2020*6185db85Sdougm } else { 2021*6185db85Sdougm ret = SA_BAD_PATH; 2022*6185db85Sdougm (void) printf(gettext("Resource must not contain " 2023*6185db85Sdougm "white space or '/'\n")); 2024*6185db85Sdougm } 2025*6185db85Sdougm } 2026*6185db85Sdougm if (ret == SA_OK && description != NULL) { 2027*6185db85Sdougm ret = sa_set_share_description(share, description); 2028*6185db85Sdougm } 2029*6185db85Sdougm } 2030*6185db85Sdougm if (!dryrun && ret == SA_OK) { 2031*6185db85Sdougm ret = sa_update_config(); 2032*6185db85Sdougm } 2033*6185db85Sdougm switch (ret) { 2034*6185db85Sdougm case SA_DUPLICATE_NAME: 2035*6185db85Sdougm (void) printf(gettext("Resource name in use: %s\n"), 2036*6185db85Sdougm resource); 2037*6185db85Sdougm break; 2038*6185db85Sdougm default: 2039*6185db85Sdougm (void) printf(gettext("Could not set attribute: %s\n"), 2040*6185db85Sdougm sa_errorstr(ret)); 2041*6185db85Sdougm break; 2042*6185db85Sdougm case SA_OK: 2043*6185db85Sdougm if (dryrun && !auth && verbose) { 2044*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 2045*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 2046*6185db85Sdougm } 2047*6185db85Sdougm break; 2048*6185db85Sdougm } 2049*6185db85Sdougm } else { 2050*6185db85Sdougm (void) printf(gettext("Share path \"%s\" not found\n"), 2051*6185db85Sdougm sharepath); 2052*6185db85Sdougm ret = SA_NO_SUCH_PATH; 2053*6185db85Sdougm } 2054*6185db85Sdougm } 2055*6185db85Sdougm return (ret); 2056*6185db85Sdougm } 2057*6185db85Sdougm 2058*6185db85Sdougm /* 2059*6185db85Sdougm * add_security(group, sectype, optlist, proto, *err) 2060*6185db85Sdougm * 2061*6185db85Sdougm * Helper function to add a security option (named optionset) to the 2062*6185db85Sdougm * group. 2063*6185db85Sdougm */ 2064*6185db85Sdougm 2065*6185db85Sdougm static int 2066*6185db85Sdougm add_security(sa_group_t group, char *sectype, 2067*6185db85Sdougm struct options *optlist, char *proto, int *err) 2068*6185db85Sdougm { 2069*6185db85Sdougm sa_security_t security; 2070*6185db85Sdougm int ret = SA_OK; 2071*6185db85Sdougm int result = 0; 2072*6185db85Sdougm 2073*6185db85Sdougm sectype = sa_proto_space_alias(proto, sectype); 2074*6185db85Sdougm security = sa_get_security(group, sectype, proto); 2075*6185db85Sdougm if (security == NULL) { 2076*6185db85Sdougm security = sa_create_security(group, sectype, proto); 2077*6185db85Sdougm } 2078*6185db85Sdougm if (sectype != NULL) 2079*6185db85Sdougm sa_free_attr_string(sectype); 2080*6185db85Sdougm if (security != NULL) { 2081*6185db85Sdougm while (optlist != NULL) { 2082*6185db85Sdougm sa_property_t prop; 2083*6185db85Sdougm prop = sa_get_property(security, optlist->optname); 2084*6185db85Sdougm if (prop == NULL) { 2085*6185db85Sdougm /* 2086*6185db85Sdougm * add the property, but only if it is 2087*6185db85Sdougm * a non-NULL or non-zero length value 2088*6185db85Sdougm */ 2089*6185db85Sdougm if (optlist->optvalue != NULL) { 2090*6185db85Sdougm prop = sa_create_property(optlist->optname, 2091*6185db85Sdougm optlist->optvalue); 2092*6185db85Sdougm if (prop != NULL) { 2093*6185db85Sdougm ret = sa_valid_property(security, proto, prop); 2094*6185db85Sdougm if (ret != SA_OK) { 2095*6185db85Sdougm (void) sa_remove_property(prop); 2096*6185db85Sdougm (void) printf(gettext("Could not add " 2097*6185db85Sdougm "property %s: %s\n"), 2098*6185db85Sdougm optlist->optname, 2099*6185db85Sdougm sa_errorstr(ret)); 2100*6185db85Sdougm } 2101*6185db85Sdougm if (ret == SA_OK) { 2102*6185db85Sdougm ret = sa_add_property(security, prop); 2103*6185db85Sdougm if (ret != SA_OK) { 2104*6185db85Sdougm (void) printf(gettext("Could not add " 2105*6185db85Sdougm "property (%s=%s): %s\n"), 2106*6185db85Sdougm optlist->optname, 2107*6185db85Sdougm optlist->optvalue, 2108*6185db85Sdougm sa_errorstr(ret)); 2109*6185db85Sdougm } else { 2110*6185db85Sdougm result = 1; 2111*6185db85Sdougm } 2112*6185db85Sdougm } 2113*6185db85Sdougm } 2114*6185db85Sdougm } 2115*6185db85Sdougm } else { 2116*6185db85Sdougm ret = sa_update_property(prop, optlist->optvalue); 2117*6185db85Sdougm result = 1; /* should check if really changed */ 2118*6185db85Sdougm } 2119*6185db85Sdougm optlist = optlist->next; 2120*6185db85Sdougm } 2121*6185db85Sdougm /* 2122*6185db85Sdougm * when done, properties may have all been removed but 2123*6185db85Sdougm * we need to keep the security type itself until 2124*6185db85Sdougm * explicitly removed. 2125*6185db85Sdougm */ 2126*6185db85Sdougm if (result) 2127*6185db85Sdougm ret = sa_commit_properties(security, 0); 2128*6185db85Sdougm } 2129*6185db85Sdougm *err = ret; 2130*6185db85Sdougm return (result); 2131*6185db85Sdougm } 2132*6185db85Sdougm 2133*6185db85Sdougm /* 2134*6185db85Sdougm * basic_set(groupname, optlist, protocol, sharepath, dryrun) 2135*6185db85Sdougm * 2136*6185db85Sdougm * This function implements "set" when a name space (-S) is not 2137*6185db85Sdougm * specified. It is a basic set. Options and other CLI parsing has 2138*6185db85Sdougm * already been done. 2139*6185db85Sdougm */ 2140*6185db85Sdougm 2141*6185db85Sdougm static int 2142*6185db85Sdougm basic_set(char *groupname, struct options *optlist, char *protocol, 2143*6185db85Sdougm char *sharepath, int dryrun) 2144*6185db85Sdougm { 2145*6185db85Sdougm sa_group_t group; 2146*6185db85Sdougm int ret = SA_OK; 2147*6185db85Sdougm int change = 0; 2148*6185db85Sdougm struct list *worklist = NULL; 2149*6185db85Sdougm 2150*6185db85Sdougm group = sa_get_group(groupname); 2151*6185db85Sdougm if (group != NULL) { 2152*6185db85Sdougm sa_share_t share = NULL; 2153*6185db85Sdougm if (sharepath != NULL) { 2154*6185db85Sdougm share = sa_get_share(group, sharepath); 2155*6185db85Sdougm if (share == NULL) { 2156*6185db85Sdougm (void) printf(gettext("Share does not exist in group %s\n"), 2157*6185db85Sdougm groupname, sharepath); 2158*6185db85Sdougm ret = SA_NO_SUCH_PATH; 2159*6185db85Sdougm } 2160*6185db85Sdougm } 2161*6185db85Sdougm if (ret == SA_OK) { 2162*6185db85Sdougm /* group must exist */ 2163*6185db85Sdougm ret = valid_options(optlist, protocol, 2164*6185db85Sdougm share == NULL ? group : share, NULL); 2165*6185db85Sdougm if (ret == SA_OK && !dryrun) { 2166*6185db85Sdougm if (share != NULL) 2167*6185db85Sdougm change |= add_optionset(share, optlist, protocol, 2168*6185db85Sdougm &ret); 2169*6185db85Sdougm else 2170*6185db85Sdougm change |= add_optionset(group, optlist, protocol, 2171*6185db85Sdougm &ret); 2172*6185db85Sdougm if (ret == SA_OK && change) { 2173*6185db85Sdougm worklist = add_list(worklist, group, share); 2174*6185db85Sdougm } 2175*6185db85Sdougm } 2176*6185db85Sdougm } 2177*6185db85Sdougm free_opt(optlist); 2178*6185db85Sdougm } else { 2179*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), groupname); 2180*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 2181*6185db85Sdougm } 2182*6185db85Sdougm /* 2183*6185db85Sdougm * we have a group and potentially legal additions 2184*6185db85Sdougm */ 2185*6185db85Sdougm 2186*6185db85Sdougm /* commit to configuration if not a dryrun */ 2187*6185db85Sdougm if (!dryrun && ret == SA_OK) { 2188*6185db85Sdougm if (change && worklist != NULL) { 2189*6185db85Sdougm /* properties changed, so update all shares */ 2190*6185db85Sdougm (void) enable_all_groups(worklist, 0, 0, protocol); 2191*6185db85Sdougm } 2192*6185db85Sdougm } 2193*6185db85Sdougm if (worklist != NULL) 2194*6185db85Sdougm free_list(worklist); 2195*6185db85Sdougm return (ret); 2196*6185db85Sdougm } 2197*6185db85Sdougm 2198*6185db85Sdougm /* 2199*6185db85Sdougm * space_set(groupname, optlist, protocol, sharepath, dryrun) 2200*6185db85Sdougm * 2201*6185db85Sdougm * This function implements "set" when a name space (-S) is 2202*6185db85Sdougm * specified. It is a namespace set. Options and other CLI parsing has 2203*6185db85Sdougm * already been done. 2204*6185db85Sdougm */ 2205*6185db85Sdougm 2206*6185db85Sdougm static int 2207*6185db85Sdougm space_set(char *groupname, struct options *optlist, char *protocol, 2208*6185db85Sdougm char *sharepath, int dryrun, char *sectype) 2209*6185db85Sdougm { 2210*6185db85Sdougm sa_group_t group; 2211*6185db85Sdougm int ret = SA_OK; 2212*6185db85Sdougm int change = 0; 2213*6185db85Sdougm struct list *worklist = NULL; 2214*6185db85Sdougm 2215*6185db85Sdougm /* 2216*6185db85Sdougm * make sure protcol and sectype are valid 2217*6185db85Sdougm */ 2218*6185db85Sdougm 2219*6185db85Sdougm if (sa_proto_valid_space(protocol, sectype) == 0) { 2220*6185db85Sdougm (void) printf(gettext("Option space \"%s\" not valid " 2221*6185db85Sdougm "for protocol.\n"), 2222*6185db85Sdougm sectype); 2223*6185db85Sdougm return (SA_INVALID_SECURITY); 2224*6185db85Sdougm } 2225*6185db85Sdougm 2226*6185db85Sdougm group = sa_get_group(groupname); 2227*6185db85Sdougm if (group != NULL) { 2228*6185db85Sdougm sa_share_t share = NULL; 2229*6185db85Sdougm if (sharepath != NULL) { 2230*6185db85Sdougm share = sa_get_share(group, sharepath); 2231*6185db85Sdougm if (share == NULL) { 2232*6185db85Sdougm (void) printf(gettext("Share does not exist in group %s\n"), 2233*6185db85Sdougm groupname, sharepath); 2234*6185db85Sdougm ret = SA_NO_SUCH_PATH; 2235*6185db85Sdougm } 2236*6185db85Sdougm } 2237*6185db85Sdougm if (ret == SA_OK) { 2238*6185db85Sdougm /* group must exist */ 2239*6185db85Sdougm ret = valid_options(optlist, protocol, 2240*6185db85Sdougm share == NULL ? group : share, sectype); 2241*6185db85Sdougm if (ret == SA_OK && !dryrun) { 2242*6185db85Sdougm if (share != NULL) 2243*6185db85Sdougm change = add_security(share, sectype, optlist, 2244*6185db85Sdougm protocol, 2245*6185db85Sdougm &ret); 2246*6185db85Sdougm else 2247*6185db85Sdougm change = add_security(group, sectype, optlist, 2248*6185db85Sdougm protocol, 2249*6185db85Sdougm &ret); 2250*6185db85Sdougm if (ret != SA_OK) 2251*6185db85Sdougm (void) printf(gettext("Could not set property: %s\n"), 2252*6185db85Sdougm sa_errorstr(ret)); 2253*6185db85Sdougm } 2254*6185db85Sdougm if (ret == SA_OK && change) 2255*6185db85Sdougm worklist = add_list(worklist, group, share); 2256*6185db85Sdougm } 2257*6185db85Sdougm free_opt(optlist); 2258*6185db85Sdougm } else { 2259*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), groupname); 2260*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 2261*6185db85Sdougm } 2262*6185db85Sdougm /* 2263*6185db85Sdougm * we have a group and potentially legal additions 2264*6185db85Sdougm */ 2265*6185db85Sdougm 2266*6185db85Sdougm /* commit to configuration if not a dryrun */ 2267*6185db85Sdougm if (!dryrun && ret == 0) { 2268*6185db85Sdougm if (change && worklist != NULL) { 2269*6185db85Sdougm /* properties changed, so update all shares */ 2270*6185db85Sdougm (void) enable_all_groups(worklist, 0, 0, protocol); 2271*6185db85Sdougm } 2272*6185db85Sdougm ret = sa_update_config(); 2273*6185db85Sdougm } 2274*6185db85Sdougm if (worklist != NULL) 2275*6185db85Sdougm free_list(worklist); 2276*6185db85Sdougm return (ret); 2277*6185db85Sdougm } 2278*6185db85Sdougm 2279*6185db85Sdougm /* 2280*6185db85Sdougm * sa_set(flags, argc, argv) 2281*6185db85Sdougm * 2282*6185db85Sdougm * Implements the set subcommand. It keys off of -S to determine which 2283*6185db85Sdougm * set of operations to actually do. 2284*6185db85Sdougm */ 2285*6185db85Sdougm 2286*6185db85Sdougm int 2287*6185db85Sdougm sa_set(int flags, int argc, char *argv[]) 2288*6185db85Sdougm { 2289*6185db85Sdougm char *groupname; 2290*6185db85Sdougm int verbose = 0; 2291*6185db85Sdougm int dryrun = 0; 2292*6185db85Sdougm int c; 2293*6185db85Sdougm char *protocol = NULL; 2294*6185db85Sdougm int ret = SA_OK; 2295*6185db85Sdougm struct options *optlist = NULL; 2296*6185db85Sdougm char *sharepath = NULL; 2297*6185db85Sdougm char *optset = NULL; 2298*6185db85Sdougm int auth; 2299*6185db85Sdougm 2300*6185db85Sdougm while ((c = getopt(argc, argv, "?hvnP:p:s:S:")) != EOF) { 2301*6185db85Sdougm switch (c) { 2302*6185db85Sdougm case 'v': 2303*6185db85Sdougm verbose++; 2304*6185db85Sdougm break; 2305*6185db85Sdougm case 'n': 2306*6185db85Sdougm dryrun++; 2307*6185db85Sdougm break; 2308*6185db85Sdougm case 'P': 2309*6185db85Sdougm protocol = optarg; 2310*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 2311*6185db85Sdougm (void) printf(gettext("Invalid protocol specified:" 2312*6185db85Sdougm "%s\n"), 2313*6185db85Sdougm protocol); 2314*6185db85Sdougm return (SA_INVALID_PROTOCOL); 2315*6185db85Sdougm } 2316*6185db85Sdougm break; 2317*6185db85Sdougm case 'p': 2318*6185db85Sdougm ret = add_opt(&optlist, optarg, 0); 2319*6185db85Sdougm switch (ret) { 2320*6185db85Sdougm case OPT_ADD_SYNTAX: 2321*6185db85Sdougm (void) printf(gettext("Property syntax error: %s\n"), 2322*6185db85Sdougm optarg); 2323*6185db85Sdougm return (SA_SYNTAX_ERR); 2324*6185db85Sdougm case OPT_ADD_MEMORY: 2325*6185db85Sdougm (void) printf(gettext("No memory to set property: %s\n"), 2326*6185db85Sdougm optarg); 2327*6185db85Sdougm return (SA_NO_MEMORY); 2328*6185db85Sdougm default: 2329*6185db85Sdougm break; 2330*6185db85Sdougm } 2331*6185db85Sdougm break; 2332*6185db85Sdougm case 's': 2333*6185db85Sdougm sharepath = optarg; 2334*6185db85Sdougm break; 2335*6185db85Sdougm case 'S': 2336*6185db85Sdougm optset = optarg; 2337*6185db85Sdougm break; 2338*6185db85Sdougm default: 2339*6185db85Sdougm case 'h': 2340*6185db85Sdougm case '?': 2341*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 2342*6185db85Sdougm sa_get_usage(USAGE_SET)); 2343*6185db85Sdougm return (SA_OK); 2344*6185db85Sdougm } 2345*6185db85Sdougm } 2346*6185db85Sdougm 2347*6185db85Sdougm if (optlist != NULL) 2348*6185db85Sdougm ret = chk_opt(optlist, optset != NULL, protocol); 2349*6185db85Sdougm 2350*6185db85Sdougm if (optind >= argc || (optlist == NULL && optset == NULL) || 2351*6185db85Sdougm protocol == NULL || 2352*6185db85Sdougm ret != OPT_ADD_OK) { 2353*6185db85Sdougm char *sep = "\t"; 2354*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_SET)); 2355*6185db85Sdougm if (optind >= argc) { 2356*6185db85Sdougm (void) printf(gettext("%sgroup must be specified"), sep); 2357*6185db85Sdougm sep = ", "; 2358*6185db85Sdougm } 2359*6185db85Sdougm if (optlist == NULL) { 2360*6185db85Sdougm (void) printf(gettext("%sat least one property must be" 2361*6185db85Sdougm " specified"), sep); 2362*6185db85Sdougm sep = ", "; 2363*6185db85Sdougm } 2364*6185db85Sdougm if (protocol == NULL) { 2365*6185db85Sdougm (void) printf(gettext("%sprotocol must be specified"), sep); 2366*6185db85Sdougm sep = ", "; 2367*6185db85Sdougm } 2368*6185db85Sdougm (void) printf("\n"); 2369*6185db85Sdougm ret = SA_SYNTAX_ERR; 2370*6185db85Sdougm } else { 2371*6185db85Sdougm /* 2372*6185db85Sdougm * if a group already exists, we can only add a new 2373*6185db85Sdougm * protocol to it and not create a new one or add the 2374*6185db85Sdougm * same protocol again. 2375*6185db85Sdougm */ 2376*6185db85Sdougm 2377*6185db85Sdougm groupname = argv[optind]; 2378*6185db85Sdougm auth = check_authorizations(groupname, flags); 2379*6185db85Sdougm if (optset == NULL) 2380*6185db85Sdougm ret = basic_set(groupname, optlist, protocol, 2381*6185db85Sdougm sharepath, dryrun); 2382*6185db85Sdougm else 2383*6185db85Sdougm ret = space_set(groupname, optlist, protocol, 2384*6185db85Sdougm sharepath, dryrun, optset); 2385*6185db85Sdougm if (dryrun && ret == SA_OK && !auth && verbose) { 2386*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 2387*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 2388*6185db85Sdougm } 2389*6185db85Sdougm } 2390*6185db85Sdougm return (ret); 2391*6185db85Sdougm } 2392*6185db85Sdougm 2393*6185db85Sdougm /* 2394*6185db85Sdougm * remove_options(group, optlist, proto, *err) 2395*6185db85Sdougm * 2396*6185db85Sdougm * helper function to actually remove options from a group after all 2397*6185db85Sdougm * preprocessing is done. 2398*6185db85Sdougm */ 2399*6185db85Sdougm 2400*6185db85Sdougm static int 2401*6185db85Sdougm remove_options(sa_group_t group, struct options *optlist, 2402*6185db85Sdougm char *proto, int *err) 2403*6185db85Sdougm { 2404*6185db85Sdougm struct options *cur; 2405*6185db85Sdougm sa_optionset_t optionset; 2406*6185db85Sdougm sa_property_t prop; 2407*6185db85Sdougm int change = 0; 2408*6185db85Sdougm int ret = SA_OK; 2409*6185db85Sdougm 2410*6185db85Sdougm optionset = sa_get_optionset(group, proto); 2411*6185db85Sdougm if (optionset != NULL) { 2412*6185db85Sdougm for (cur = optlist; cur != NULL; cur = cur->next) { 2413*6185db85Sdougm prop = sa_get_property(optionset, cur->optname); 2414*6185db85Sdougm if (prop != NULL) { 2415*6185db85Sdougm ret = sa_remove_property(prop); 2416*6185db85Sdougm if (ret != SA_OK) 2417*6185db85Sdougm break; 2418*6185db85Sdougm change = 1; 2419*6185db85Sdougm } 2420*6185db85Sdougm } 2421*6185db85Sdougm } 2422*6185db85Sdougm if (ret == SA_OK && change) 2423*6185db85Sdougm ret = sa_commit_properties(optionset, 0); 2424*6185db85Sdougm 2425*6185db85Sdougm if (err != NULL) 2426*6185db85Sdougm *err = ret; 2427*6185db85Sdougm return (change); 2428*6185db85Sdougm } 2429*6185db85Sdougm 2430*6185db85Sdougm /* 2431*6185db85Sdougm * valid_unset(group, optlist, proto) 2432*6185db85Sdougm * 2433*6185db85Sdougm * Sanity check the optlist to make sure they can be removed. Issue an 2434*6185db85Sdougm * error if a property doesn't exist. 2435*6185db85Sdougm */ 2436*6185db85Sdougm 2437*6185db85Sdougm static int 2438*6185db85Sdougm valid_unset(sa_group_t group, struct options *optlist, char *proto) 2439*6185db85Sdougm { 2440*6185db85Sdougm struct options *cur; 2441*6185db85Sdougm sa_optionset_t optionset; 2442*6185db85Sdougm sa_property_t prop; 2443*6185db85Sdougm int ret = SA_OK; 2444*6185db85Sdougm 2445*6185db85Sdougm optionset = sa_get_optionset(group, proto); 2446*6185db85Sdougm if (optionset != NULL) { 2447*6185db85Sdougm for (cur = optlist; cur != NULL; cur = cur->next) { 2448*6185db85Sdougm prop = sa_get_property(optionset, cur->optname); 2449*6185db85Sdougm if (prop == NULL) { 2450*6185db85Sdougm (void) printf(gettext("Could not unset property %s:" 2451*6185db85Sdougm " not set\n"), 2452*6185db85Sdougm cur->optname); 2453*6185db85Sdougm ret = SA_NO_SUCH_PROP; 2454*6185db85Sdougm } 2455*6185db85Sdougm } 2456*6185db85Sdougm } 2457*6185db85Sdougm return (ret); 2458*6185db85Sdougm } 2459*6185db85Sdougm 2460*6185db85Sdougm /* 2461*6185db85Sdougm * valid_unset_security(group, optlist, proto) 2462*6185db85Sdougm * 2463*6185db85Sdougm * Sanity check the optlist to make sure they can be removed. Issue an 2464*6185db85Sdougm * error if a property doesn't exist. 2465*6185db85Sdougm */ 2466*6185db85Sdougm 2467*6185db85Sdougm static int 2468*6185db85Sdougm valid_unset_security(sa_group_t group, struct options *optlist, char *proto, 2469*6185db85Sdougm char *sectype) 2470*6185db85Sdougm { 2471*6185db85Sdougm struct options *cur; 2472*6185db85Sdougm sa_security_t security; 2473*6185db85Sdougm sa_property_t prop; 2474*6185db85Sdougm int ret = SA_OK; 2475*6185db85Sdougm char *sec; 2476*6185db85Sdougm 2477*6185db85Sdougm sec = sa_proto_space_alias(proto, sectype); 2478*6185db85Sdougm security = sa_get_security(group, sec, proto); 2479*6185db85Sdougm if (security != NULL) { 2480*6185db85Sdougm for (cur = optlist; cur != NULL; cur = cur->next) { 2481*6185db85Sdougm prop = sa_get_property(security, cur->optname); 2482*6185db85Sdougm if (prop == NULL) { 2483*6185db85Sdougm (void) printf(gettext("Could not unset property %s:" 2484*6185db85Sdougm " not set\n"), 2485*6185db85Sdougm cur->optname); 2486*6185db85Sdougm ret = SA_NO_SUCH_PROP; 2487*6185db85Sdougm } 2488*6185db85Sdougm } 2489*6185db85Sdougm } else { 2490*6185db85Sdougm (void) printf(gettext("Could not unset %s: space not defined\n"), 2491*6185db85Sdougm sectype); 2492*6185db85Sdougm ret = SA_NO_SUCH_SECURITY; 2493*6185db85Sdougm } 2494*6185db85Sdougm if (sec != NULL) 2495*6185db85Sdougm sa_free_attr_string(sec); 2496*6185db85Sdougm return (ret); 2497*6185db85Sdougm } 2498*6185db85Sdougm 2499*6185db85Sdougm /* 2500*6185db85Sdougm * remove_security(group, optlist, proto) 2501*6185db85Sdougm * 2502*6185db85Sdougm * Remove the properties since they were checked as valid. 2503*6185db85Sdougm */ 2504*6185db85Sdougm 2505*6185db85Sdougm static int 2506*6185db85Sdougm remove_security(sa_group_t group, char *sectype, 2507*6185db85Sdougm struct options *optlist, char *proto, int *err) 2508*6185db85Sdougm { 2509*6185db85Sdougm sa_security_t security; 2510*6185db85Sdougm int ret = SA_OK; 2511*6185db85Sdougm int change = 0; 2512*6185db85Sdougm 2513*6185db85Sdougm sectype = sa_proto_space_alias(proto, sectype); 2514*6185db85Sdougm security = sa_get_security(group, sectype, proto); 2515*6185db85Sdougm if (sectype != NULL) 2516*6185db85Sdougm sa_free_attr_string(sectype); 2517*6185db85Sdougm 2518*6185db85Sdougm if (security != NULL) { 2519*6185db85Sdougm while (optlist != NULL) { 2520*6185db85Sdougm sa_property_t prop; 2521*6185db85Sdougm prop = sa_get_property(security, optlist->optname); 2522*6185db85Sdougm if (prop != NULL) { 2523*6185db85Sdougm ret = sa_remove_property(prop); 2524*6185db85Sdougm if (ret != SA_OK) 2525*6185db85Sdougm break; 2526*6185db85Sdougm change = 1; 2527*6185db85Sdougm } 2528*6185db85Sdougm optlist = optlist->next; 2529*6185db85Sdougm } 2530*6185db85Sdougm /* 2531*6185db85Sdougm * when done, properties may have all been removed but 2532*6185db85Sdougm * we need to keep the security type itself until 2533*6185db85Sdougm * explicitly removed. 2534*6185db85Sdougm */ 2535*6185db85Sdougm if (ret == SA_OK && change) 2536*6185db85Sdougm ret = sa_commit_properties(security, 0); 2537*6185db85Sdougm } else { 2538*6185db85Sdougm ret = SA_NO_SUCH_PROP; 2539*6185db85Sdougm } 2540*6185db85Sdougm if (err != NULL) 2541*6185db85Sdougm *err = ret; 2542*6185db85Sdougm return (change); 2543*6185db85Sdougm } 2544*6185db85Sdougm 2545*6185db85Sdougm /* 2546*6185db85Sdougm * basic_unset(groupname, optlist, protocol, sharepath, dryrun) 2547*6185db85Sdougm * 2548*6185db85Sdougm * unset non-named optionset properties. 2549*6185db85Sdougm */ 2550*6185db85Sdougm 2551*6185db85Sdougm static int 2552*6185db85Sdougm basic_unset(char *groupname, struct options *optlist, char *protocol, 2553*6185db85Sdougm char *sharepath, int dryrun) 2554*6185db85Sdougm { 2555*6185db85Sdougm sa_group_t group; 2556*6185db85Sdougm int ret = SA_OK; 2557*6185db85Sdougm int change = 0; 2558*6185db85Sdougm struct list *worklist = NULL; 2559*6185db85Sdougm 2560*6185db85Sdougm group = sa_get_group(groupname); 2561*6185db85Sdougm if (group != NULL) { 2562*6185db85Sdougm sa_share_t share = NULL; 2563*6185db85Sdougm if (sharepath != NULL) { 2564*6185db85Sdougm share = sa_get_share(group, sharepath); 2565*6185db85Sdougm if (share == NULL) { 2566*6185db85Sdougm (void) printf(gettext("Share does not exist in group %s\n"), 2567*6185db85Sdougm groupname, sharepath); 2568*6185db85Sdougm ret = SA_NO_SUCH_PATH; 2569*6185db85Sdougm } 2570*6185db85Sdougm } 2571*6185db85Sdougm if (ret == SA_OK) { 2572*6185db85Sdougm /* group must exist */ 2573*6185db85Sdougm ret = valid_unset(share != NULL ? share : group, 2574*6185db85Sdougm optlist, protocol); 2575*6185db85Sdougm if (ret == SA_OK && !dryrun) { 2576*6185db85Sdougm if (share != NULL) { 2577*6185db85Sdougm sa_optionset_t optionset; 2578*6185db85Sdougm sa_property_t prop; 2579*6185db85Sdougm change |= remove_options(share, optlist, protocol, 2580*6185db85Sdougm &ret); 2581*6185db85Sdougm /* if a share optionset is empty, remove it */ 2582*6185db85Sdougm optionset = sa_get_optionset((sa_share_t)share, 2583*6185db85Sdougm protocol); 2584*6185db85Sdougm if (optionset != NULL) { 2585*6185db85Sdougm prop = sa_get_property(optionset, NULL); 2586*6185db85Sdougm if (prop == NULL) 2587*6185db85Sdougm (void) sa_destroy_optionset(optionset); 2588*6185db85Sdougm } 2589*6185db85Sdougm } else { 2590*6185db85Sdougm change |= remove_options(group, optlist, protocol, 2591*6185db85Sdougm &ret); 2592*6185db85Sdougm } 2593*6185db85Sdougm if (ret == SA_OK && change) 2594*6185db85Sdougm worklist = add_list(worklist, group, share); 2595*6185db85Sdougm if (ret != SA_OK) 2596*6185db85Sdougm (void) printf(gettext("Could not remove properties:" 2597*6185db85Sdougm "%s\n"), 2598*6185db85Sdougm sa_errorstr(ret)); 2599*6185db85Sdougm } 2600*6185db85Sdougm } else { 2601*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), groupname); 2602*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 2603*6185db85Sdougm } 2604*6185db85Sdougm free_opt(optlist); 2605*6185db85Sdougm } 2606*6185db85Sdougm 2607*6185db85Sdougm /* 2608*6185db85Sdougm * we have a group and potentially legal additions 2609*6185db85Sdougm */ 2610*6185db85Sdougm /* commit to configuration if not a dryrun */ 2611*6185db85Sdougm if (!dryrun && ret == SA_OK) { 2612*6185db85Sdougm if (change && worklist != NULL) { 2613*6185db85Sdougm /* properties changed, so update all shares */ 2614*6185db85Sdougm (void) enable_all_groups(worklist, 0, 0, protocol); 2615*6185db85Sdougm } 2616*6185db85Sdougm } 2617*6185db85Sdougm if (worklist != NULL) 2618*6185db85Sdougm free_list(worklist); 2619*6185db85Sdougm return (ret); 2620*6185db85Sdougm } 2621*6185db85Sdougm 2622*6185db85Sdougm /* 2623*6185db85Sdougm * space_unset(groupname, optlist, protocol, sharepath, dryrun) 2624*6185db85Sdougm * 2625*6185db85Sdougm * unset named optionset properties. 2626*6185db85Sdougm */ 2627*6185db85Sdougm static int 2628*6185db85Sdougm space_unset(char *groupname, struct options *optlist, char *protocol, 2629*6185db85Sdougm char *sharepath, int dryrun, char *sectype) 2630*6185db85Sdougm { 2631*6185db85Sdougm sa_group_t group; 2632*6185db85Sdougm int ret = SA_OK; 2633*6185db85Sdougm int change = 0; 2634*6185db85Sdougm struct list *worklist = NULL; 2635*6185db85Sdougm 2636*6185db85Sdougm group = sa_get_group(groupname); 2637*6185db85Sdougm if (group != NULL) { 2638*6185db85Sdougm sa_share_t share = NULL; 2639*6185db85Sdougm if (sharepath != NULL) { 2640*6185db85Sdougm share = sa_get_share(group, sharepath); 2641*6185db85Sdougm if (share == NULL) { 2642*6185db85Sdougm (void) printf(gettext("Share does not exist in group %s\n"), 2643*6185db85Sdougm groupname, sharepath); 2644*6185db85Sdougm ret = SA_NO_SUCH_PATH; 2645*6185db85Sdougm } 2646*6185db85Sdougm } 2647*6185db85Sdougm if (ret == SA_OK) { 2648*6185db85Sdougm ret = valid_unset_security(share != NULL ? share : group, 2649*6185db85Sdougm optlist, protocol, sectype); 2650*6185db85Sdougm if (ret == SA_OK && !dryrun) { 2651*6185db85Sdougm if (optlist != NULL) { 2652*6185db85Sdougm if (share != NULL) { 2653*6185db85Sdougm sa_security_t optionset; 2654*6185db85Sdougm sa_property_t prop; 2655*6185db85Sdougm change = remove_security(share, sectype, 2656*6185db85Sdougm optlist, protocol, 2657*6185db85Sdougm &ret); 2658*6185db85Sdougm /* if a share security is empty, remove it */ 2659*6185db85Sdougm optionset = sa_get_security((sa_group_t)share, 2660*6185db85Sdougm sectype, 2661*6185db85Sdougm protocol); 2662*6185db85Sdougm if (optionset != NULL) { 2663*6185db85Sdougm prop = sa_get_property(optionset, NULL); 2664*6185db85Sdougm if (prop == NULL) 2665*6185db85Sdougm ret = sa_destroy_security(optionset); 2666*6185db85Sdougm } 2667*6185db85Sdougm } else { 2668*6185db85Sdougm change = remove_security(group, sectype, 2669*6185db85Sdougm optlist, protocol, 2670*6185db85Sdougm &ret); 2671*6185db85Sdougm } 2672*6185db85Sdougm } else { 2673*6185db85Sdougm sa_security_t security; 2674*6185db85Sdougm char *sec; 2675*6185db85Sdougm sec = sa_proto_space_alias(protocol, sectype); 2676*6185db85Sdougm security = sa_get_security(group, sec, protocol); 2677*6185db85Sdougm if (sec != NULL) 2678*6185db85Sdougm sa_free_attr_string(sec); 2679*6185db85Sdougm if (security != NULL) { 2680*6185db85Sdougm ret = sa_destroy_security(security); 2681*6185db85Sdougm if (ret == SA_OK) 2682*6185db85Sdougm change = 1; 2683*6185db85Sdougm } else { 2684*6185db85Sdougm ret = SA_NO_SUCH_PROP; 2685*6185db85Sdougm } 2686*6185db85Sdougm } 2687*6185db85Sdougm if (ret != SA_OK) 2688*6185db85Sdougm (void) printf(gettext("Could not unset property: %s\n"), 2689*6185db85Sdougm sa_errorstr(ret)); 2690*6185db85Sdougm } 2691*6185db85Sdougm 2692*6185db85Sdougm if (ret == SA_OK && change) 2693*6185db85Sdougm worklist = add_list(worklist, group, 0); 2694*6185db85Sdougm } 2695*6185db85Sdougm } else { 2696*6185db85Sdougm (void) printf(gettext("Group \"%s\" not found\n"), groupname); 2697*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 2698*6185db85Sdougm } 2699*6185db85Sdougm free_opt(optlist); 2700*6185db85Sdougm /* 2701*6185db85Sdougm * we have a group and potentially legal additions 2702*6185db85Sdougm */ 2703*6185db85Sdougm 2704*6185db85Sdougm /* commit to configuration if not a dryrun */ 2705*6185db85Sdougm if (!dryrun && ret == 0) { 2706*6185db85Sdougm if (change && worklist != NULL) { 2707*6185db85Sdougm /* properties changed, so update all shares */ 2708*6185db85Sdougm (void) enable_all_groups(worklist, 0, 0, protocol); 2709*6185db85Sdougm } 2710*6185db85Sdougm ret = sa_update_config(); 2711*6185db85Sdougm } 2712*6185db85Sdougm if (worklist != NULL) 2713*6185db85Sdougm free_list(worklist); 2714*6185db85Sdougm return (ret); 2715*6185db85Sdougm } 2716*6185db85Sdougm 2717*6185db85Sdougm /* 2718*6185db85Sdougm * sa_unset(flags, argc, argv) 2719*6185db85Sdougm * 2720*6185db85Sdougm * implements the unset subcommand. Parsing done here and then basic 2721*6185db85Sdougm * or space versions of the real code are called. 2722*6185db85Sdougm */ 2723*6185db85Sdougm 2724*6185db85Sdougm int 2725*6185db85Sdougm sa_unset(int flags, int argc, char *argv[]) 2726*6185db85Sdougm { 2727*6185db85Sdougm char *groupname; 2728*6185db85Sdougm int verbose = 0; 2729*6185db85Sdougm int dryrun = 0; 2730*6185db85Sdougm int c; 2731*6185db85Sdougm char *protocol = NULL; 2732*6185db85Sdougm int ret = SA_OK; 2733*6185db85Sdougm struct options *optlist = NULL; 2734*6185db85Sdougm char *sharepath = NULL; 2735*6185db85Sdougm char *optset = NULL; 2736*6185db85Sdougm int auth; 2737*6185db85Sdougm 2738*6185db85Sdougm while ((c = getopt(argc, argv, "?hvnP:p:s:S:")) != EOF) { 2739*6185db85Sdougm switch (c) { 2740*6185db85Sdougm case 'v': 2741*6185db85Sdougm verbose++; 2742*6185db85Sdougm break; 2743*6185db85Sdougm case 'n': 2744*6185db85Sdougm dryrun++; 2745*6185db85Sdougm break; 2746*6185db85Sdougm case 'P': 2747*6185db85Sdougm protocol = optarg; 2748*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 2749*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 2750*6185db85Sdougm protocol); 2751*6185db85Sdougm return (SA_INVALID_PROTOCOL); 2752*6185db85Sdougm } 2753*6185db85Sdougm break; 2754*6185db85Sdougm case 'p': 2755*6185db85Sdougm ret = add_opt(&optlist, optarg, 1); 2756*6185db85Sdougm switch (ret) { 2757*6185db85Sdougm case OPT_ADD_SYNTAX: 2758*6185db85Sdougm (void) printf(gettext("Property syntax error for " 2759*6185db85Sdougm "property %s\n"), 2760*6185db85Sdougm optarg); 2761*6185db85Sdougm return (SA_SYNTAX_ERR); 2762*6185db85Sdougm case OPT_ADD_PROPERTY: 2763*6185db85Sdougm (void) printf(gettext("Properties need to be set" 2764*6185db85Sdougm " with set command: %s\n"), 2765*6185db85Sdougm optarg); 2766*6185db85Sdougm return (SA_SYNTAX_ERR); 2767*6185db85Sdougm default: 2768*6185db85Sdougm break; 2769*6185db85Sdougm } 2770*6185db85Sdougm break; 2771*6185db85Sdougm case 's': 2772*6185db85Sdougm sharepath = optarg; 2773*6185db85Sdougm break; 2774*6185db85Sdougm case 'S': 2775*6185db85Sdougm optset = optarg; 2776*6185db85Sdougm break; 2777*6185db85Sdougm default: 2778*6185db85Sdougm case 'h': 2779*6185db85Sdougm case '?': 2780*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 2781*6185db85Sdougm sa_get_usage(USAGE_UNSET)); 2782*6185db85Sdougm return (SA_OK); 2783*6185db85Sdougm } 2784*6185db85Sdougm } 2785*6185db85Sdougm 2786*6185db85Sdougm if (optlist != NULL) 2787*6185db85Sdougm ret = chk_opt(optlist, optset != NULL, protocol); 2788*6185db85Sdougm 2789*6185db85Sdougm if (optind >= argc || (optlist == NULL && optset == NULL) || 2790*6185db85Sdougm protocol == NULL) { 2791*6185db85Sdougm char *sep = "\t"; 2792*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_UNSET)); 2793*6185db85Sdougm if (optind >= argc) { 2794*6185db85Sdougm (void) printf(gettext("%sgroup must be specified"), sep); 2795*6185db85Sdougm sep = ", "; 2796*6185db85Sdougm } 2797*6185db85Sdougm if (optlist == NULL) { 2798*6185db85Sdougm (void) printf(gettext("%sat least one property must be " 2799*6185db85Sdougm "specified"), 2800*6185db85Sdougm sep); 2801*6185db85Sdougm sep = ", "; 2802*6185db85Sdougm } 2803*6185db85Sdougm if (protocol == NULL) { 2804*6185db85Sdougm (void) printf(gettext("%sprotocol must be specified"), sep); 2805*6185db85Sdougm sep = ", "; 2806*6185db85Sdougm } 2807*6185db85Sdougm (void) printf("\n"); 2808*6185db85Sdougm ret = SA_SYNTAX_ERR; 2809*6185db85Sdougm } else { 2810*6185db85Sdougm 2811*6185db85Sdougm /* 2812*6185db85Sdougm * if a group already exists, we can only add a new 2813*6185db85Sdougm * protocol to it and not create a new one or add the 2814*6185db85Sdougm * same protocol again. 2815*6185db85Sdougm */ 2816*6185db85Sdougm 2817*6185db85Sdougm groupname = argv[optind]; 2818*6185db85Sdougm auth = check_authorizations(groupname, flags); 2819*6185db85Sdougm if (optset == NULL) 2820*6185db85Sdougm ret = basic_unset(groupname, optlist, protocol, 2821*6185db85Sdougm sharepath, dryrun); 2822*6185db85Sdougm else 2823*6185db85Sdougm ret = space_unset(groupname, optlist, protocol, 2824*6185db85Sdougm sharepath, dryrun, optset); 2825*6185db85Sdougm 2826*6185db85Sdougm if (dryrun && ret == SA_OK && !auth && verbose) { 2827*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 2828*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 2829*6185db85Sdougm } 2830*6185db85Sdougm } 2831*6185db85Sdougm return (ret); 2832*6185db85Sdougm } 2833*6185db85Sdougm 2834*6185db85Sdougm /* 2835*6185db85Sdougm * sa_enable_group(flags, argc, argv) 2836*6185db85Sdougm * 2837*6185db85Sdougm * Implements the enable subcommand 2838*6185db85Sdougm */ 2839*6185db85Sdougm 2840*6185db85Sdougm int 2841*6185db85Sdougm sa_enable_group(int flags, int argc, char *argv[]) 2842*6185db85Sdougm { 2843*6185db85Sdougm int verbose = 0; 2844*6185db85Sdougm int dryrun = 0; 2845*6185db85Sdougm int all = 0; 2846*6185db85Sdougm int c; 2847*6185db85Sdougm int ret = SA_OK; 2848*6185db85Sdougm char *protocol = NULL; 2849*6185db85Sdougm char *state; 2850*6185db85Sdougm struct list *worklist = NULL; 2851*6185db85Sdougm int auth = 1; 2852*6185db85Sdougm 2853*6185db85Sdougm while ((c = getopt(argc, argv, "?havnP:")) != EOF) { 2854*6185db85Sdougm switch (c) { 2855*6185db85Sdougm case 'a': 2856*6185db85Sdougm all = 1; 2857*6185db85Sdougm break; 2858*6185db85Sdougm case 'n': 2859*6185db85Sdougm dryrun++; 2860*6185db85Sdougm break; 2861*6185db85Sdougm case 'P': 2862*6185db85Sdougm protocol = optarg; 2863*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 2864*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 2865*6185db85Sdougm protocol); 2866*6185db85Sdougm return (SA_INVALID_PROTOCOL); 2867*6185db85Sdougm } 2868*6185db85Sdougm break; 2869*6185db85Sdougm case 'v': 2870*6185db85Sdougm verbose++; 2871*6185db85Sdougm break; 2872*6185db85Sdougm default: 2873*6185db85Sdougm case 'h': 2874*6185db85Sdougm case '?': 2875*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 2876*6185db85Sdougm sa_get_usage(USAGE_ENABLE)); 2877*6185db85Sdougm return (0); 2878*6185db85Sdougm } 2879*6185db85Sdougm } 2880*6185db85Sdougm 2881*6185db85Sdougm if (optind == argc && !all) { 2882*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_ENABLE)); 2883*6185db85Sdougm (void) printf(gettext("\tmust specify group\n")); 2884*6185db85Sdougm ret = SA_NO_SUCH_PATH; 2885*6185db85Sdougm } else { 2886*6185db85Sdougm sa_group_t group; 2887*6185db85Sdougm if (!all) { 2888*6185db85Sdougm while (optind < argc) { 2889*6185db85Sdougm group = sa_get_group(argv[optind]); 2890*6185db85Sdougm if (group != NULL) { 2891*6185db85Sdougm auth &= check_authorizations(argv[optind], flags); 2892*6185db85Sdougm state = sa_get_group_attr(group, "state"); 2893*6185db85Sdougm if (state != NULL && 2894*6185db85Sdougm strcmp(state, "enabled") == 0) { 2895*6185db85Sdougm /* already enabled */ 2896*6185db85Sdougm if (verbose) 2897*6185db85Sdougm (void) printf(gettext("Group \"%s\" is already " 2898*6185db85Sdougm "enabled\n"), 2899*6185db85Sdougm argv[optind]); 2900*6185db85Sdougm ret = SA_BUSY; /* already enabled */ 2901*6185db85Sdougm } else { 2902*6185db85Sdougm worklist = add_list(worklist, group, 0); 2903*6185db85Sdougm if (verbose) 2904*6185db85Sdougm (void) printf(gettext("Enabling group " 2905*6185db85Sdougm "\"%s\"\n"), 2906*6185db85Sdougm argv[optind]); 2907*6185db85Sdougm } 2908*6185db85Sdougm if (state != NULL) 2909*6185db85Sdougm sa_free_attr_string(state); 2910*6185db85Sdougm } else { 2911*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 2912*6185db85Sdougm } 2913*6185db85Sdougm optind++; 2914*6185db85Sdougm } 2915*6185db85Sdougm } else { 2916*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 2917*6185db85Sdougm group = sa_get_next_group(group)) { 2918*6185db85Sdougm worklist = add_list(worklist, group, 0); 2919*6185db85Sdougm } 2920*6185db85Sdougm } 2921*6185db85Sdougm if (!dryrun && ret == SA_OK) { 2922*6185db85Sdougm ret = enable_all_groups(worklist, 1, 0, NULL); 2923*6185db85Sdougm } 2924*6185db85Sdougm if (ret != SA_OK && ret != SA_BUSY) 2925*6185db85Sdougm (void) printf(gettext("Could not enable group: %s\n"), 2926*6185db85Sdougm sa_errorstr(ret)); 2927*6185db85Sdougm if (ret == SA_BUSY) 2928*6185db85Sdougm ret = SA_OK; 2929*6185db85Sdougm } 2930*6185db85Sdougm if (worklist != NULL) 2931*6185db85Sdougm free_list(worklist); 2932*6185db85Sdougm if (dryrun && ret == SA_OK && !auth && verbose) { 2933*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 2934*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 2935*6185db85Sdougm } 2936*6185db85Sdougm return (ret); 2937*6185db85Sdougm } 2938*6185db85Sdougm 2939*6185db85Sdougm /* 2940*6185db85Sdougm * disable_group(group, setstate) 2941*6185db85Sdougm * 2942*6185db85Sdougm * disable all the shares in the specified group honoring the setstate 2943*6185db85Sdougm * argument. This is a helper for disable_all_groups in order to 2944*6185db85Sdougm * simplify regular and subgroup (zfs) disabling. Group has already 2945*6185db85Sdougm * been checked for non-NULL. 2946*6185db85Sdougm */ 2947*6185db85Sdougm 2948*6185db85Sdougm static int 2949*6185db85Sdougm disable_group(sa_group_t group) 2950*6185db85Sdougm { 2951*6185db85Sdougm sa_share_t share; 2952*6185db85Sdougm int ret = SA_OK; 2953*6185db85Sdougm 2954*6185db85Sdougm for (share = sa_get_share(group, NULL); 2955*6185db85Sdougm share != NULL && ret == SA_OK; 2956*6185db85Sdougm share = sa_get_next_share(share)) { 2957*6185db85Sdougm ret = sa_disable_share(share, NULL); 2958*6185db85Sdougm if (ret == SA_NO_SUCH_PATH) { 2959*6185db85Sdougm /* 2960*6185db85Sdougm * this is OK since the path is gone. we can't 2961*6185db85Sdougm * re-share it anyway so no error. 2962*6185db85Sdougm */ 2963*6185db85Sdougm ret = SA_OK; 2964*6185db85Sdougm } 2965*6185db85Sdougm } 2966*6185db85Sdougm return (ret); 2967*6185db85Sdougm } 2968*6185db85Sdougm 2969*6185db85Sdougm 2970*6185db85Sdougm /* 2971*6185db85Sdougm * disable_all_groups(work, setstate) 2972*6185db85Sdougm * 2973*6185db85Sdougm * helper function that disables the shares in the list of groups 2974*6185db85Sdougm * provided. It optionally marks the group as disabled. Used by both 2975*6185db85Sdougm * enable and start subcommands. 2976*6185db85Sdougm */ 2977*6185db85Sdougm 2978*6185db85Sdougm static int 2979*6185db85Sdougm disable_all_groups(struct list *work, int setstate) 2980*6185db85Sdougm { 2981*6185db85Sdougm int ret = SA_OK; 2982*6185db85Sdougm sa_group_t subgroup, group; 2983*6185db85Sdougm 2984*6185db85Sdougm while (work != NULL && ret == SA_OK) { 2985*6185db85Sdougm group = (sa_group_t)work->item; 2986*6185db85Sdougm if (setstate) 2987*6185db85Sdougm ret = sa_set_group_attr(group, "state", "disabled"); 2988*6185db85Sdougm if (ret == SA_OK) { 2989*6185db85Sdougm char *name; 2990*6185db85Sdougm name = sa_get_group_attr(group, "name"); 2991*6185db85Sdougm if (name != NULL && strcmp(name, "zfs") == 0) { 2992*6185db85Sdougm /* need to get the sub-groups for stopping */ 2993*6185db85Sdougm for (subgroup = sa_get_sub_group(group); subgroup != NULL; 2994*6185db85Sdougm subgroup = sa_get_next_group(subgroup)) { 2995*6185db85Sdougm ret = disable_group(subgroup); 2996*6185db85Sdougm } 2997*6185db85Sdougm } else { 2998*6185db85Sdougm ret = disable_group(group); 2999*6185db85Sdougm } 3000*6185db85Sdougm /* 3001*6185db85Sdougm * we don't want to "disable" since it won't come 3002*6185db85Sdougm * up after a reboot. The SMF framework should do 3003*6185db85Sdougm * the right thing. On enable we do want to do 3004*6185db85Sdougm * something. 3005*6185db85Sdougm */ 3006*6185db85Sdougm } 3007*6185db85Sdougm work = work->next; 3008*6185db85Sdougm } 3009*6185db85Sdougm if (ret == SA_OK) 3010*6185db85Sdougm ret = sa_update_config(); 3011*6185db85Sdougm return (ret); 3012*6185db85Sdougm } 3013*6185db85Sdougm 3014*6185db85Sdougm /* 3015*6185db85Sdougm * sa_disable_group(flags, argc, argv) 3016*6185db85Sdougm * 3017*6185db85Sdougm * Implements the disable subcommand 3018*6185db85Sdougm */ 3019*6185db85Sdougm 3020*6185db85Sdougm int 3021*6185db85Sdougm sa_disable_group(int flags, int argc, char *argv[]) 3022*6185db85Sdougm { 3023*6185db85Sdougm int verbose = 0; 3024*6185db85Sdougm int dryrun = 0; 3025*6185db85Sdougm int all = 0; 3026*6185db85Sdougm int c; 3027*6185db85Sdougm int ret = SA_OK; 3028*6185db85Sdougm char *protocol; 3029*6185db85Sdougm char *state; 3030*6185db85Sdougm struct list *worklist = NULL; 3031*6185db85Sdougm int auth = 1; 3032*6185db85Sdougm 3033*6185db85Sdougm while ((c = getopt(argc, argv, "?havn")) != EOF) { 3034*6185db85Sdougm switch (c) { 3035*6185db85Sdougm case 'a': 3036*6185db85Sdougm all = 1; 3037*6185db85Sdougm break; 3038*6185db85Sdougm case 'n': 3039*6185db85Sdougm dryrun++; 3040*6185db85Sdougm break; 3041*6185db85Sdougm case 'P': 3042*6185db85Sdougm protocol = optarg; 3043*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 3044*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 3045*6185db85Sdougm protocol); 3046*6185db85Sdougm return (SA_INVALID_PROTOCOL); 3047*6185db85Sdougm } 3048*6185db85Sdougm break; 3049*6185db85Sdougm case 'v': 3050*6185db85Sdougm verbose++; 3051*6185db85Sdougm break; 3052*6185db85Sdougm default: 3053*6185db85Sdougm case 'h': 3054*6185db85Sdougm case '?': 3055*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3056*6185db85Sdougm sa_get_usage(USAGE_DISABLE)); 3057*6185db85Sdougm return (0); 3058*6185db85Sdougm } 3059*6185db85Sdougm } 3060*6185db85Sdougm 3061*6185db85Sdougm if (optind == argc && !all) { 3062*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3063*6185db85Sdougm sa_get_usage(USAGE_DISABLE)); 3064*6185db85Sdougm (void) printf(gettext("\tmust specify group\n")); 3065*6185db85Sdougm ret = SA_NO_SUCH_PATH; 3066*6185db85Sdougm } else { 3067*6185db85Sdougm sa_group_t group; 3068*6185db85Sdougm if (!all) { 3069*6185db85Sdougm while (optind < argc) { 3070*6185db85Sdougm group = sa_get_group(argv[optind]); 3071*6185db85Sdougm if (group != NULL) { 3072*6185db85Sdougm auth &= check_authorizations(argv[optind], flags); 3073*6185db85Sdougm state = sa_get_group_attr(group, "state"); 3074*6185db85Sdougm if (state == NULL || 3075*6185db85Sdougm strcmp(state, "disabled") == 0) { 3076*6185db85Sdougm /* already disabled */ 3077*6185db85Sdougm if (verbose) 3078*6185db85Sdougm (void) printf(gettext("Group \"%s\" is " 3079*6185db85Sdougm "already disabled\n"), 3080*6185db85Sdougm argv[optind]); 3081*6185db85Sdougm ret = SA_BUSY; /* already disable */ 3082*6185db85Sdougm } else { 3083*6185db85Sdougm worklist = add_list(worklist, group, 0); 3084*6185db85Sdougm if (verbose) 3085*6185db85Sdougm (void) printf(gettext("Disabling group " 3086*6185db85Sdougm "\"%s\"\n"), 3087*6185db85Sdougm argv[optind]); 3088*6185db85Sdougm } 3089*6185db85Sdougm if (state != NULL) 3090*6185db85Sdougm sa_free_attr_string(state); 3091*6185db85Sdougm } else { 3092*6185db85Sdougm ret = SA_NO_SUCH_GROUP; 3093*6185db85Sdougm } 3094*6185db85Sdougm optind++; 3095*6185db85Sdougm } 3096*6185db85Sdougm } else { 3097*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 3098*6185db85Sdougm group = sa_get_next_group(group)) { 3099*6185db85Sdougm worklist = add_list(worklist, group, 0); 3100*6185db85Sdougm } 3101*6185db85Sdougm } 3102*6185db85Sdougm if (ret == SA_OK && !dryrun) { 3103*6185db85Sdougm ret = disable_all_groups(worklist, 1); 3104*6185db85Sdougm } 3105*6185db85Sdougm if (ret != SA_OK && ret != SA_BUSY) 3106*6185db85Sdougm (void) printf(gettext("Could not disable group: %s\n"), 3107*6185db85Sdougm sa_errorstr(ret)); 3108*6185db85Sdougm if (ret == SA_BUSY) 3109*6185db85Sdougm ret = SA_OK; 3110*6185db85Sdougm } 3111*6185db85Sdougm if (worklist != NULL) 3112*6185db85Sdougm free_list(worklist); 3113*6185db85Sdougm if (dryrun && ret == SA_OK && !auth && verbose) { 3114*6185db85Sdougm (void) printf(gettext("Command would fail: %s\n"), 3115*6185db85Sdougm sa_errorstr(SA_NO_PERMISSION)); 3116*6185db85Sdougm } 3117*6185db85Sdougm return (ret); 3118*6185db85Sdougm } 3119*6185db85Sdougm 3120*6185db85Sdougm /* 3121*6185db85Sdougm * check_sharetab() 3122*6185db85Sdougm * 3123*6185db85Sdougm * Checks to see if the /etc/dfs/sharetab file is stale (exists from 3124*6185db85Sdougm * before the current boot). If it is, truncate it since nothing is 3125*6185db85Sdougm * really shared. 3126*6185db85Sdougm */ 3127*6185db85Sdougm 3128*6185db85Sdougm static void 3129*6185db85Sdougm check_sharetab() 3130*6185db85Sdougm { 3131*6185db85Sdougm int fd; 3132*6185db85Sdougm struct utmpx *utmpxp; 3133*6185db85Sdougm struct stat st; 3134*6185db85Sdougm 3135*6185db85Sdougm fd = open(SA_LEGACY_SHARETAB, O_RDWR); 3136*6185db85Sdougm if (fd >= 0) { 3137*6185db85Sdougm /* 3138*6185db85Sdougm * Attempt to get a lock on the file. Whgen we get 3139*6185db85Sdougm * one, then check to see if it is older than the boot 3140*6185db85Sdougm * time. Truncate if older than boot. 3141*6185db85Sdougm */ 3142*6185db85Sdougm (void) lockf(fd, F_LOCK, 0); 3143*6185db85Sdougm if ((fstat(fd, &st) == 0) && /* does sharetab exist? */ 3144*6185db85Sdougm (utmpxp = getutxent()) != NULL && /* does utmpx exist? */ 3145*6185db85Sdougm (utmpxp->ut_xtime > st.st_mtime)) /* sharetab older? */ 3146*6185db85Sdougm (void) ftruncate(fd, 0); 3147*6185db85Sdougm 3148*6185db85Sdougm (void) lockf(fd, F_ULOCK, 0); 3149*6185db85Sdougm (void) close(fd); 3150*6185db85Sdougm endutxent(); 3151*6185db85Sdougm } 3152*6185db85Sdougm } 3153*6185db85Sdougm 3154*6185db85Sdougm /* 3155*6185db85Sdougm * sa_start_group(flags, argc, argv) 3156*6185db85Sdougm * 3157*6185db85Sdougm * Implements the start command. 3158*6185db85Sdougm * This is similar to enable except it doesn't change the state 3159*6185db85Sdougm * of the group(s) and only enables shares if the group is already 3160*6185db85Sdougm * enabled. 3161*6185db85Sdougm */ 3162*6185db85Sdougm 3163*6185db85Sdougm int 3164*6185db85Sdougm sa_start_group(int flags, int argc, char *argv[]) 3165*6185db85Sdougm { 3166*6185db85Sdougm int verbose = 0; 3167*6185db85Sdougm int all = 0; 3168*6185db85Sdougm int c; 3169*6185db85Sdougm int ret = SMF_EXIT_OK; 3170*6185db85Sdougm char *protocol = NULL; 3171*6185db85Sdougm char *state; 3172*6185db85Sdougm struct list *worklist = NULL; 3173*6185db85Sdougm #ifdef lint 3174*6185db85Sdougm flags = flags; 3175*6185db85Sdougm #endif 3176*6185db85Sdougm 3177*6185db85Sdougm while ((c = getopt(argc, argv, "?havP:")) != EOF) { 3178*6185db85Sdougm switch (c) { 3179*6185db85Sdougm case 'a': 3180*6185db85Sdougm all = 1; 3181*6185db85Sdougm break; 3182*6185db85Sdougm case 'P': 3183*6185db85Sdougm protocol = optarg; 3184*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 3185*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 3186*6185db85Sdougm protocol); 3187*6185db85Sdougm return (SA_INVALID_PROTOCOL); 3188*6185db85Sdougm } 3189*6185db85Sdougm break; 3190*6185db85Sdougm case 'v': 3191*6185db85Sdougm verbose++; 3192*6185db85Sdougm break; 3193*6185db85Sdougm default: 3194*6185db85Sdougm case 'h': 3195*6185db85Sdougm case '?': 3196*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3197*6185db85Sdougm sa_get_usage(USAGE_START)); 3198*6185db85Sdougm return (SA_OK); 3199*6185db85Sdougm } 3200*6185db85Sdougm } 3201*6185db85Sdougm 3202*6185db85Sdougm if (optind == argc && !all) { 3203*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3204*6185db85Sdougm sa_get_usage(USAGE_START)); 3205*6185db85Sdougm ret = SMF_EXIT_ERR_FATAL; 3206*6185db85Sdougm } else { 3207*6185db85Sdougm sa_group_t group; 3208*6185db85Sdougm 3209*6185db85Sdougm check_sharetab(); 3210*6185db85Sdougm 3211*6185db85Sdougm if (!all) { 3212*6185db85Sdougm while (optind < argc) { 3213*6185db85Sdougm group = sa_get_group(argv[optind]); 3214*6185db85Sdougm if (group != NULL) { 3215*6185db85Sdougm state = sa_get_group_attr(group, "state"); 3216*6185db85Sdougm if (state == NULL || 3217*6185db85Sdougm strcmp(state, "enabled") == 0) { 3218*6185db85Sdougm worklist = add_list(worklist, group, 0); 3219*6185db85Sdougm if (verbose) 3220*6185db85Sdougm (void) printf(gettext("Starting group " 3221*6185db85Sdougm "\"%s\"\n"), 3222*6185db85Sdougm argv[optind]); 3223*6185db85Sdougm } else { 3224*6185db85Sdougm /* 3225*6185db85Sdougm * determine if there are any 3226*6185db85Sdougm * protocols. if there aren't any, 3227*6185db85Sdougm * then there isn't anything to do in 3228*6185db85Sdougm * any case so no error. 3229*6185db85Sdougm */ 3230*6185db85Sdougm if (sa_get_optionset(group, protocol) != NULL) { 3231*6185db85Sdougm ret = SMF_EXIT_OK; 3232*6185db85Sdougm } 3233*6185db85Sdougm } 3234*6185db85Sdougm if (state != NULL) 3235*6185db85Sdougm sa_free_attr_string(state); 3236*6185db85Sdougm } 3237*6185db85Sdougm optind++; 3238*6185db85Sdougm } 3239*6185db85Sdougm } else { 3240*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 3241*6185db85Sdougm group = sa_get_next_group(group)) { 3242*6185db85Sdougm state = sa_get_group_attr(group, "state"); 3243*6185db85Sdougm if (state == NULL || strcmp(state, "enabled") == 0) 3244*6185db85Sdougm worklist = add_list(worklist, group, 0); 3245*6185db85Sdougm if (state != NULL) 3246*6185db85Sdougm sa_free_attr_string(state); 3247*6185db85Sdougm } 3248*6185db85Sdougm } 3249*6185db85Sdougm (void) enable_all_groups(worklist, 0, 1, NULL); 3250*6185db85Sdougm } 3251*6185db85Sdougm if (worklist != NULL) 3252*6185db85Sdougm free_list(worklist); 3253*6185db85Sdougm return (ret); 3254*6185db85Sdougm } 3255*6185db85Sdougm 3256*6185db85Sdougm /* 3257*6185db85Sdougm * sa_stop_group(flags, argc, argv) 3258*6185db85Sdougm * 3259*6185db85Sdougm * Implements the stop command. 3260*6185db85Sdougm * This is similar to disable except it doesn't change the state 3261*6185db85Sdougm * of the group(s) and only disables shares if the group is already 3262*6185db85Sdougm * enabled. 3263*6185db85Sdougm */ 3264*6185db85Sdougm 3265*6185db85Sdougm int 3266*6185db85Sdougm sa_stop_group(int flags, int argc, char *argv[]) 3267*6185db85Sdougm { 3268*6185db85Sdougm int verbose = 0; 3269*6185db85Sdougm int all = 0; 3270*6185db85Sdougm int c; 3271*6185db85Sdougm int ret = SMF_EXIT_OK; 3272*6185db85Sdougm char *protocol = NULL; 3273*6185db85Sdougm char *state; 3274*6185db85Sdougm struct list *worklist = NULL; 3275*6185db85Sdougm #ifdef lint 3276*6185db85Sdougm flags = flags; 3277*6185db85Sdougm #endif 3278*6185db85Sdougm 3279*6185db85Sdougm while ((c = getopt(argc, argv, "?havP:")) != EOF) { 3280*6185db85Sdougm switch (c) { 3281*6185db85Sdougm case 'a': 3282*6185db85Sdougm all = 1; 3283*6185db85Sdougm break; 3284*6185db85Sdougm case 'P': 3285*6185db85Sdougm protocol = optarg; 3286*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 3287*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 3288*6185db85Sdougm protocol); 3289*6185db85Sdougm return (SA_INVALID_PROTOCOL); 3290*6185db85Sdougm } 3291*6185db85Sdougm break; 3292*6185db85Sdougm case 'v': 3293*6185db85Sdougm verbose++; 3294*6185db85Sdougm break; 3295*6185db85Sdougm default: 3296*6185db85Sdougm case 'h': 3297*6185db85Sdougm case '?': 3298*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3299*6185db85Sdougm sa_get_usage(USAGE_STOP)); 3300*6185db85Sdougm return (0); 3301*6185db85Sdougm } 3302*6185db85Sdougm } 3303*6185db85Sdougm 3304*6185db85Sdougm if (optind == argc && !all) { 3305*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_STOP)); 3306*6185db85Sdougm ret = SMF_EXIT_ERR_FATAL; 3307*6185db85Sdougm } else { 3308*6185db85Sdougm sa_group_t group; 3309*6185db85Sdougm if (!all) { 3310*6185db85Sdougm while (optind < argc) { 3311*6185db85Sdougm group = sa_get_group(argv[optind]); 3312*6185db85Sdougm if (group != NULL) { 3313*6185db85Sdougm state = sa_get_group_attr(group, "state"); 3314*6185db85Sdougm if (state == NULL || 3315*6185db85Sdougm strcmp(state, "enabled") == 0) { 3316*6185db85Sdougm worklist = add_list(worklist, group, 0); 3317*6185db85Sdougm if (verbose) 3318*6185db85Sdougm (void) printf(gettext("Stopping group " 3319*6185db85Sdougm "\"%s\"\n"), 3320*6185db85Sdougm argv[optind]); 3321*6185db85Sdougm } else { 3322*6185db85Sdougm ret = SMF_EXIT_OK; 3323*6185db85Sdougm } 3324*6185db85Sdougm if (state != NULL) 3325*6185db85Sdougm sa_free_attr_string(state); 3326*6185db85Sdougm } 3327*6185db85Sdougm optind++; 3328*6185db85Sdougm } 3329*6185db85Sdougm } else { 3330*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 3331*6185db85Sdougm group = sa_get_next_group(group)) { 3332*6185db85Sdougm state = sa_get_group_attr(group, "state"); 3333*6185db85Sdougm if (state == NULL || strcmp(state, "enabled") == 0) 3334*6185db85Sdougm worklist = add_list(worklist, group, 0); 3335*6185db85Sdougm if (state != NULL) 3336*6185db85Sdougm sa_free_attr_string(state); 3337*6185db85Sdougm } 3338*6185db85Sdougm } 3339*6185db85Sdougm (void) disable_all_groups(worklist, 0); 3340*6185db85Sdougm ret = sa_update_config(); 3341*6185db85Sdougm } 3342*6185db85Sdougm if (worklist != NULL) 3343*6185db85Sdougm free_list(worklist); 3344*6185db85Sdougm return (ret); 3345*6185db85Sdougm } 3346*6185db85Sdougm 3347*6185db85Sdougm /* 3348*6185db85Sdougm * remove_all_options(share, proto) 3349*6185db85Sdougm * 3350*6185db85Sdougm * Removes all options on a share. 3351*6185db85Sdougm */ 3352*6185db85Sdougm 3353*6185db85Sdougm static void 3354*6185db85Sdougm remove_all_options(sa_share_t share, char *proto) 3355*6185db85Sdougm { 3356*6185db85Sdougm sa_optionset_t optionset; 3357*6185db85Sdougm sa_security_t security; 3358*6185db85Sdougm sa_security_t prevsec = NULL; 3359*6185db85Sdougm 3360*6185db85Sdougm optionset = sa_get_optionset(share, proto); 3361*6185db85Sdougm if (optionset != NULL) 3362*6185db85Sdougm (void) sa_destroy_optionset(optionset); 3363*6185db85Sdougm for (security = sa_get_security(share, NULL, NULL); 3364*6185db85Sdougm security != NULL; 3365*6185db85Sdougm security = sa_get_next_security(security)) { 3366*6185db85Sdougm char *type; 3367*6185db85Sdougm /* 3368*6185db85Sdougm * we walk through the list. prevsec keeps the 3369*6185db85Sdougm * previous security so we can delete it without 3370*6185db85Sdougm * destroying the list. 3371*6185db85Sdougm */ 3372*6185db85Sdougm if (prevsec != NULL) { 3373*6185db85Sdougm /* remove the previously seen security */ 3374*6185db85Sdougm (void) sa_destroy_security(prevsec); 3375*6185db85Sdougm /* set to NULL so we don't try multiple times */ 3376*6185db85Sdougm prevsec = NULL; 3377*6185db85Sdougm } 3378*6185db85Sdougm type = sa_get_security_attr(security, "type"); 3379*6185db85Sdougm if (type != NULL) { 3380*6185db85Sdougm /* 3381*6185db85Sdougm * if the security matches the specified protocol, we 3382*6185db85Sdougm * want to remove it. prevsec holds it until either 3383*6185db85Sdougm * the next pass or we fall out of the loop. 3384*6185db85Sdougm */ 3385*6185db85Sdougm if (strcmp(type, proto) == 0) 3386*6185db85Sdougm prevsec = security; 3387*6185db85Sdougm sa_free_attr_string(type); 3388*6185db85Sdougm } 3389*6185db85Sdougm } 3390*6185db85Sdougm /* in case there is one left */ 3391*6185db85Sdougm if (prevsec != NULL) 3392*6185db85Sdougm (void) sa_destroy_security(prevsec); 3393*6185db85Sdougm } 3394*6185db85Sdougm 3395*6185db85Sdougm 3396*6185db85Sdougm /* 3397*6185db85Sdougm * for legacy support, we need to handle the old syntax. This is what 3398*6185db85Sdougm * we get if sharemgr is called with the name "share" rather than 3399*6185db85Sdougm * sharemgr. 3400*6185db85Sdougm */ 3401*6185db85Sdougm 3402*6185db85Sdougm static int 3403*6185db85Sdougm format_legacy_path(char *buff, int buffsize, char *proto, char *cmd) 3404*6185db85Sdougm { 3405*6185db85Sdougm int err; 3406*6185db85Sdougm 3407*6185db85Sdougm err = snprintf(buff, buffsize, "/usr/lib/fs/%s/%s", proto, cmd); 3408*6185db85Sdougm if (err > buffsize) 3409*6185db85Sdougm return (-1); 3410*6185db85Sdougm return (0); 3411*6185db85Sdougm } 3412*6185db85Sdougm 3413*6185db85Sdougm 3414*6185db85Sdougm /* 3415*6185db85Sdougm * check_legacy_cmd(proto, cmd) 3416*6185db85Sdougm * 3417*6185db85Sdougm * Check to see if the cmd exists in /usr/lib/fs/<proto>/<cmd> and is 3418*6185db85Sdougm * executable. 3419*6185db85Sdougm */ 3420*6185db85Sdougm 3421*6185db85Sdougm static int 3422*6185db85Sdougm check_legacy_cmd(char *path) 3423*6185db85Sdougm { 3424*6185db85Sdougm struct stat st; 3425*6185db85Sdougm int ret = 0; 3426*6185db85Sdougm 3427*6185db85Sdougm if (stat(path, &st) == 0) { 3428*6185db85Sdougm if (S_ISREG(st.st_mode) && st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) 3429*6185db85Sdougm ret = 1; 3430*6185db85Sdougm } 3431*6185db85Sdougm return (ret); 3432*6185db85Sdougm } 3433*6185db85Sdougm 3434*6185db85Sdougm /* 3435*6185db85Sdougm * run_legacy_command(proto, cmd, argv) 3436*6185db85Sdougm * 3437*6185db85Sdougm * we know the command exists, so attempt to execute it with all the 3438*6185db85Sdougm * arguments. This implements full legacy share support for those 3439*6185db85Sdougm * protocols that don't have plugin providers. 3440*6185db85Sdougm */ 3441*6185db85Sdougm 3442*6185db85Sdougm static int 3443*6185db85Sdougm run_legacy_command(char *path, char *argv[]) 3444*6185db85Sdougm { 3445*6185db85Sdougm int ret; 3446*6185db85Sdougm 3447*6185db85Sdougm ret = execv(path, argv); 3448*6185db85Sdougm if (ret < 0) { 3449*6185db85Sdougm switch (errno) { 3450*6185db85Sdougm case EACCES: 3451*6185db85Sdougm ret = SA_NO_PERMISSION; 3452*6185db85Sdougm break; 3453*6185db85Sdougm default: 3454*6185db85Sdougm ret = SA_SYSTEM_ERR; 3455*6185db85Sdougm break; 3456*6185db85Sdougm } 3457*6185db85Sdougm } 3458*6185db85Sdougm return (ret); 3459*6185db85Sdougm } 3460*6185db85Sdougm 3461*6185db85Sdougm /* 3462*6185db85Sdougm * out_share(out, group, proto, options) 3463*6185db85Sdougm * 3464*6185db85Sdougm * Display the share information in the format that the "share" 3465*6185db85Sdougm * command has traditionally used. 3466*6185db85Sdougm */ 3467*6185db85Sdougm 3468*6185db85Sdougm static void 3469*6185db85Sdougm out_share(FILE *out, sa_group_t group, char *proto, char *options) 3470*6185db85Sdougm { 3471*6185db85Sdougm sa_share_t share; 3472*6185db85Sdougm char resfmt[128]; 3473*6185db85Sdougm 3474*6185db85Sdougm for (share = sa_get_share(group, NULL); share != NULL; 3475*6185db85Sdougm share = sa_get_next_share(share)) { 3476*6185db85Sdougm char *path; 3477*6185db85Sdougm char *type; 3478*6185db85Sdougm char *resource; 3479*6185db85Sdougm char *description; 3480*6185db85Sdougm char *groupname; 3481*6185db85Sdougm char *sharedstate; 3482*6185db85Sdougm int shared = 1; 3483*6185db85Sdougm char *soptions; 3484*6185db85Sdougm 3485*6185db85Sdougm sharedstate = sa_get_share_attr(share, "shared"); 3486*6185db85Sdougm path = sa_get_share_attr(share, "path"); 3487*6185db85Sdougm type = sa_get_share_attr(share, "type"); 3488*6185db85Sdougm resource = sa_get_share_attr(share, "resource"); 3489*6185db85Sdougm groupname = sa_get_group_attr(group, "name"); 3490*6185db85Sdougm 3491*6185db85Sdougm if (groupname != NULL && strcmp(groupname, "default") == 0) { 3492*6185db85Sdougm sa_free_attr_string(groupname); 3493*6185db85Sdougm groupname = NULL; 3494*6185db85Sdougm } 3495*6185db85Sdougm description = sa_get_share_description(share); 3496*6185db85Sdougm soptions = options; 3497*6185db85Sdougm 3498*6185db85Sdougm if (sharedstate == NULL) 3499*6185db85Sdougm shared = 0; 3500*6185db85Sdougm 3501*6185db85Sdougm soptions = sa_proto_legacy_format(proto, share, 1); 3502*6185db85Sdougm 3503*6185db85Sdougm if (shared) { 3504*6185db85Sdougm /* only persisting share go here */ 3505*6185db85Sdougm (void) snprintf(resfmt, sizeof (resfmt), "%s%s%s", 3506*6185db85Sdougm resource != NULL ? resource : "-", 3507*6185db85Sdougm groupname != NULL ? "@" : "", 3508*6185db85Sdougm groupname != NULL ? groupname : ""); 3509*6185db85Sdougm (void) fprintf(out, "%-14.14s %s %s \"%s\" \n", 3510*6185db85Sdougm resfmt, 3511*6185db85Sdougm path, 3512*6185db85Sdougm (soptions != NULL && strlen(soptions) > 0) ? 3513*6185db85Sdougm soptions : "rw", 3514*6185db85Sdougm (description != NULL) ? description : ""); 3515*6185db85Sdougm } 3516*6185db85Sdougm 3517*6185db85Sdougm if (path != NULL) 3518*6185db85Sdougm sa_free_attr_string(path); 3519*6185db85Sdougm if (type != NULL) 3520*6185db85Sdougm sa_free_attr_string(type); 3521*6185db85Sdougm if (resource != NULL) 3522*6185db85Sdougm sa_free_attr_string(resource); 3523*6185db85Sdougm if (groupname != NULL) 3524*6185db85Sdougm sa_free_attr_string(groupname); 3525*6185db85Sdougm if (description != NULL) 3526*6185db85Sdougm sa_free_share_description(description); 3527*6185db85Sdougm if (sharedstate != NULL) 3528*6185db85Sdougm sa_free_attr_string(sharedstate); 3529*6185db85Sdougm if (soptions != NULL && soptions != options) 3530*6185db85Sdougm sa_format_free(soptions); 3531*6185db85Sdougm } 3532*6185db85Sdougm } 3533*6185db85Sdougm 3534*6185db85Sdougm /* 3535*6185db85Sdougm * output_legacy_file(out, proto) 3536*6185db85Sdougm * 3537*6185db85Sdougm * Walk all of the groups for the specified protocol and call 3538*6185db85Sdougm * out_share() to format and write in the format displayed by the 3539*6185db85Sdougm * "share" command with no arguments. 3540*6185db85Sdougm */ 3541*6185db85Sdougm 3542*6185db85Sdougm static void 3543*6185db85Sdougm output_legacy_file(FILE *out, char *proto) 3544*6185db85Sdougm { 3545*6185db85Sdougm sa_group_t group; 3546*6185db85Sdougm 3547*6185db85Sdougm for (group = sa_get_group(NULL); group != NULL; 3548*6185db85Sdougm group = sa_get_next_group(group)) { 3549*6185db85Sdougm char *options; 3550*6185db85Sdougm char *zfs; 3551*6185db85Sdougm 3552*6185db85Sdougm /* 3553*6185db85Sdougm * get default options preformated, being careful to 3554*6185db85Sdougm * handle legacy shares differently from new style 3555*6185db85Sdougm * shares. Legacy share have options on the share. 3556*6185db85Sdougm */ 3557*6185db85Sdougm 3558*6185db85Sdougm zfs = sa_get_group_attr(group, "zfs"); 3559*6185db85Sdougm if (zfs != NULL) { 3560*6185db85Sdougm sa_group_t zgroup; 3561*6185db85Sdougm sa_free_attr_string(zfs); 3562*6185db85Sdougm options = sa_proto_legacy_format(proto, group, 1); 3563*6185db85Sdougm for (zgroup = sa_get_sub_group(group); zgroup != NULL; 3564*6185db85Sdougm zgroup = sa_get_next_group(zgroup)) { 3565*6185db85Sdougm 3566*6185db85Sdougm /* got a group, so display it */ 3567*6185db85Sdougm out_share(out, zgroup, proto, options); 3568*6185db85Sdougm } 3569*6185db85Sdougm } else { 3570*6185db85Sdougm options = sa_proto_legacy_format(proto, group, 1); 3571*6185db85Sdougm out_share(out, group, proto, options); 3572*6185db85Sdougm } 3573*6185db85Sdougm if (options != NULL) 3574*6185db85Sdougm free(options); 3575*6185db85Sdougm } 3576*6185db85Sdougm } 3577*6185db85Sdougm 3578*6185db85Sdougm int 3579*6185db85Sdougm sa_legacy_share(int flags, int argc, char *argv[]) 3580*6185db85Sdougm { 3581*6185db85Sdougm char *protocol = "nfs"; 3582*6185db85Sdougm char *options = NULL; 3583*6185db85Sdougm char *description = NULL; 3584*6185db85Sdougm char *groupname = NULL; 3585*6185db85Sdougm char *sharepath = NULL; 3586*6185db85Sdougm char *resource = NULL; 3587*6185db85Sdougm char *groupstatus = NULL; 3588*6185db85Sdougm int persist = SA_SHARE_TRANSIENT; 3589*6185db85Sdougm int argsused = 0; 3590*6185db85Sdougm int c; 3591*6185db85Sdougm int ret = SA_OK; 3592*6185db85Sdougm int zfs = 0; 3593*6185db85Sdougm int true_legacy = 0; 3594*6185db85Sdougm int curtype = SA_SHARE_TRANSIENT; 3595*6185db85Sdougm char cmd[MAXPATHLEN]; 3596*6185db85Sdougm #ifdef lint 3597*6185db85Sdougm flags = flags; 3598*6185db85Sdougm #endif 3599*6185db85Sdougm 3600*6185db85Sdougm while ((c = getopt(argc, argv, "?hF:d:o:p")) != EOF) { 3601*6185db85Sdougm switch (c) { 3602*6185db85Sdougm case 'd': 3603*6185db85Sdougm description = optarg; 3604*6185db85Sdougm argsused++; 3605*6185db85Sdougm break; 3606*6185db85Sdougm case 'F': 3607*6185db85Sdougm protocol = optarg; 3608*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 3609*6185db85Sdougm if (format_legacy_path(cmd, MAXPATHLEN, 3610*6185db85Sdougm protocol, "share") == 0 && check_legacy_cmd(cmd)) { 3611*6185db85Sdougm true_legacy++; 3612*6185db85Sdougm } else { 3613*6185db85Sdougm (void) fprintf(stderr, 3614*6185db85Sdougm gettext("Invalid protocol specified:" 3615*6185db85Sdougm "%s\n"), 3616*6185db85Sdougm protocol); 3617*6185db85Sdougm return (SA_INVALID_PROTOCOL); 3618*6185db85Sdougm } 3619*6185db85Sdougm } 3620*6185db85Sdougm break; 3621*6185db85Sdougm case 'o': 3622*6185db85Sdougm options = optarg; 3623*6185db85Sdougm argsused++; 3624*6185db85Sdougm break; 3625*6185db85Sdougm case 'p': 3626*6185db85Sdougm persist = SA_SHARE_PERMANENT; 3627*6185db85Sdougm argsused++; 3628*6185db85Sdougm break; 3629*6185db85Sdougm case 'h': 3630*6185db85Sdougm case '?': 3631*6185db85Sdougm default: 3632*6185db85Sdougm (void) fprintf(stderr, gettext("usage: %s\n"), 3633*6185db85Sdougm sa_get_usage(USAGE_SHARE)); 3634*6185db85Sdougm return (SA_OK); 3635*6185db85Sdougm } 3636*6185db85Sdougm } 3637*6185db85Sdougm 3638*6185db85Sdougm /* have the info so construct what is needed */ 3639*6185db85Sdougm if (!argsused && optind == argc) { 3640*6185db85Sdougm /* display current info in share format */ 3641*6185db85Sdougm (void) output_legacy_file(stdout, "nfs"); 3642*6185db85Sdougm } else { 3643*6185db85Sdougm sa_group_t group = NULL; 3644*6185db85Sdougm sa_share_t share; 3645*6185db85Sdougm char dir[MAXPATHLEN]; 3646*6185db85Sdougm 3647*6185db85Sdougm /* we are modifying the configuration */ 3648*6185db85Sdougm if (optind == argc) { 3649*6185db85Sdougm (void) fprintf(stderr, gettext("usage: %s\n"), 3650*6185db85Sdougm sa_get_usage(USAGE_SHARE)); 3651*6185db85Sdougm return (SA_LEGACY_ERR); 3652*6185db85Sdougm } 3653*6185db85Sdougm 3654*6185db85Sdougm if (true_legacy) { 3655*6185db85Sdougm /* if still using legacy share/unshare, exec it */ 3656*6185db85Sdougm ret = run_legacy_command(cmd, argv); 3657*6185db85Sdougm return (ret); 3658*6185db85Sdougm } 3659*6185db85Sdougm 3660*6185db85Sdougm sharepath = argv[optind++]; 3661*6185db85Sdougm if (optind < argc) { 3662*6185db85Sdougm resource = argv[optind]; 3663*6185db85Sdougm groupname = strchr(resource, '@'); 3664*6185db85Sdougm if (groupname != NULL) 3665*6185db85Sdougm *groupname++ = '\0'; 3666*6185db85Sdougm } 3667*6185db85Sdougm if (realpath(sharepath, dir) == NULL) 3668*6185db85Sdougm ret = SA_BAD_PATH; 3669*6185db85Sdougm else 3670*6185db85Sdougm sharepath = dir; 3671*6185db85Sdougm if (ret == SA_OK) { 3672*6185db85Sdougm share = sa_find_share(sharepath); 3673*6185db85Sdougm } else { 3674*6185db85Sdougm share = NULL; 3675*6185db85Sdougm } 3676*6185db85Sdougm if (groupname != NULL) { 3677*6185db85Sdougm ret = SA_NOT_ALLOWED; 3678*6185db85Sdougm } else if (ret == SA_OK) { 3679*6185db85Sdougm char *legacygroup = "default"; 3680*6185db85Sdougm /* 3681*6185db85Sdougm * the legacy group is always present and zfs groups 3682*6185db85Sdougm * come and go. zfs shares may be in sub-groups and 3683*6185db85Sdougm * the zfs share will already be in that group so it 3684*6185db85Sdougm * isn't an error. 3685*6185db85Sdougm */ 3686*6185db85Sdougm if (share != NULL) { 3687*6185db85Sdougm /* 3688*6185db85Sdougm * if the share exists, then make sure it is one we 3689*6185db85Sdougm * want to handle. 3690*6185db85Sdougm */ 3691*6185db85Sdougm group = sa_get_parent_group(share); 3692*6185db85Sdougm } else { 3693*6185db85Sdougm group = sa_get_group(legacygroup); 3694*6185db85Sdougm } 3695*6185db85Sdougm if (group != NULL) { 3696*6185db85Sdougm groupstatus = group_status(group); 3697*6185db85Sdougm if (share == NULL) { 3698*6185db85Sdougm share = sa_add_share(group, sharepath, persist, &ret); 3699*6185db85Sdougm if (share == NULL && ret == SA_DUPLICATE_NAME) { 3700*6185db85Sdougm /* could be a ZFS path being started */ 3701*6185db85Sdougm if (sa_zfs_is_shared(sharepath)) { 3702*6185db85Sdougm ret = SA_OK; 3703*6185db85Sdougm group = sa_get_group("zfs"); 3704*6185db85Sdougm if (group == NULL) { 3705*6185db85Sdougm /* this shouldn't happen */ 3706*6185db85Sdougm ret = SA_CONFIG_ERR; 3707*6185db85Sdougm } 3708*6185db85Sdougm if (group != NULL) { 3709*6185db85Sdougm share = sa_add_share(group, sharepath, 3710*6185db85Sdougm persist, &ret); 3711*6185db85Sdougm } 3712*6185db85Sdougm } 3713*6185db85Sdougm } 3714*6185db85Sdougm } else { 3715*6185db85Sdougm /* 3716*6185db85Sdougm * may want to change persist state, but the 3717*6185db85Sdougm * important thing is to change options unless 3718*6185db85Sdougm * this is ZFS where we just want to do the 3719*6185db85Sdougm * enable since everything is current. 3720*6185db85Sdougm */ 3721*6185db85Sdougm if (!sa_zfs_is_shared(sharepath)) { 3722*6185db85Sdougm char *type; 3723*6185db85Sdougm remove_all_options(share, protocol); 3724*6185db85Sdougm type = sa_get_share_attr(share, "type"); 3725*6185db85Sdougm if (type != NULL && 3726*6185db85Sdougm strcmp(type, "transient") != 0) { 3727*6185db85Sdougm curtype = SA_SHARE_PERMANENT; 3728*6185db85Sdougm } 3729*6185db85Sdougm if (type != NULL) 3730*6185db85Sdougm sa_free_attr_string(type); 3731*6185db85Sdougm if (curtype != persist) { 3732*6185db85Sdougm (void) sa_set_share_attr(share, "type", 3733*6185db85Sdougm persist == SA_SHARE_PERMANENT ? 3734*6185db85Sdougm "persist" : "transient"); 3735*6185db85Sdougm } 3736*6185db85Sdougm } else { 3737*6185db85Sdougm zfs++; 3738*6185db85Sdougm } 3739*6185db85Sdougm } 3740*6185db85Sdougm if (!zfs) { 3741*6185db85Sdougm /* have a group to hold this share path */ 3742*6185db85Sdougm if (ret == SA_OK && options != NULL && 3743*6185db85Sdougm strlen(options) > 0) { 3744*6185db85Sdougm ret = sa_parse_legacy_options(share, 3745*6185db85Sdougm options, 3746*6185db85Sdougm protocol); 3747*6185db85Sdougm } 3748*6185db85Sdougm if (ret == SA_OK && description != NULL) 3749*6185db85Sdougm ret = sa_set_share_description(share, description); 3750*6185db85Sdougm if (ret == SA_OK && resource != NULL) 3751*6185db85Sdougm ret = sa_set_share_attr(share, "resource", 3752*6185db85Sdougm resource); 3753*6185db85Sdougm } 3754*6185db85Sdougm if (ret == SA_OK) { 3755*6185db85Sdougm if (strcmp(groupstatus, "enabled") == 0) 3756*6185db85Sdougm ret = sa_enable_share(share, protocol); 3757*6185db85Sdougm if (ret == SA_OK && persist == SA_SHARE_PERMANENT) { 3758*6185db85Sdougm (void) sa_update_legacy(share, protocol); 3759*6185db85Sdougm } 3760*6185db85Sdougm if (ret == SA_OK) 3761*6185db85Sdougm ret = sa_update_config(); 3762*6185db85Sdougm } 3763*6185db85Sdougm } else { 3764*6185db85Sdougm ret = SA_SYSTEM_ERR; 3765*6185db85Sdougm } 3766*6185db85Sdougm } 3767*6185db85Sdougm } 3768*6185db85Sdougm if (ret != SA_OK) { 3769*6185db85Sdougm (void) fprintf(stderr, gettext("Could not share: %s: %s\n"), 3770*6185db85Sdougm sharepath, sa_errorstr(ret)); 3771*6185db85Sdougm ret = SA_LEGACY_ERR; 3772*6185db85Sdougm 3773*6185db85Sdougm } 3774*6185db85Sdougm return (ret); 3775*6185db85Sdougm } 3776*6185db85Sdougm 3777*6185db85Sdougm /* 3778*6185db85Sdougm * sa_legacy_unshare(flags, argc, argv) 3779*6185db85Sdougm * 3780*6185db85Sdougm * Implements the original unshare command. 3781*6185db85Sdougm */ 3782*6185db85Sdougm 3783*6185db85Sdougm int 3784*6185db85Sdougm sa_legacy_unshare(int flags, int argc, char *argv[]) 3785*6185db85Sdougm { 3786*6185db85Sdougm char *protocol = "nfs"; /* for now */ 3787*6185db85Sdougm char *options = NULL; 3788*6185db85Sdougm char *sharepath = NULL; 3789*6185db85Sdougm int persist = SA_SHARE_TRANSIENT; 3790*6185db85Sdougm int argsused = 0; 3791*6185db85Sdougm int c; 3792*6185db85Sdougm int ret = SA_OK; 3793*6185db85Sdougm int true_legacy = 0; 3794*6185db85Sdougm char cmd[MAXPATHLEN]; 3795*6185db85Sdougm #ifdef lint 3796*6185db85Sdougm flags = flags; 3797*6185db85Sdougm options = options; 3798*6185db85Sdougm #endif 3799*6185db85Sdougm 3800*6185db85Sdougm while ((c = getopt(argc, argv, "?hF:o:p")) != EOF) { 3801*6185db85Sdougm switch (c) { 3802*6185db85Sdougm case 'h': 3803*6185db85Sdougm case '?': 3804*6185db85Sdougm break; 3805*6185db85Sdougm case 'F': 3806*6185db85Sdougm protocol = optarg; 3807*6185db85Sdougm if (!sa_valid_protocol(protocol)) { 3808*6185db85Sdougm if (format_legacy_path(cmd, MAXPATHLEN, 3809*6185db85Sdougm protocol, "unshare") == 0 && 3810*6185db85Sdougm check_legacy_cmd(cmd)) { 3811*6185db85Sdougm true_legacy++; 3812*6185db85Sdougm } else { 3813*6185db85Sdougm (void) printf(gettext("Invalid file system name\n")); 3814*6185db85Sdougm return (SA_INVALID_PROTOCOL); 3815*6185db85Sdougm } 3816*6185db85Sdougm } 3817*6185db85Sdougm break; 3818*6185db85Sdougm case 'o': 3819*6185db85Sdougm options = optarg; 3820*6185db85Sdougm argsused++; 3821*6185db85Sdougm break; 3822*6185db85Sdougm case 'p': 3823*6185db85Sdougm persist = SA_SHARE_PERMANENT; 3824*6185db85Sdougm argsused++; 3825*6185db85Sdougm break; 3826*6185db85Sdougm default: 3827*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3828*6185db85Sdougm sa_get_usage(USAGE_UNSHARE)); 3829*6185db85Sdougm return (SA_OK); 3830*6185db85Sdougm } 3831*6185db85Sdougm } 3832*6185db85Sdougm 3833*6185db85Sdougm /* have the info so construct what is needed */ 3834*6185db85Sdougm if (optind == argc || (optind + 1) < argc) { 3835*6185db85Sdougm ret = SA_SYNTAX_ERR; 3836*6185db85Sdougm } else { 3837*6185db85Sdougm sa_share_t share; 3838*6185db85Sdougm char dir[MAXPATHLEN]; 3839*6185db85Sdougm if (true_legacy) { 3840*6185db85Sdougm /* if still using legacy share/unshare, exec it */ 3841*6185db85Sdougm ret = run_legacy_command(cmd, argv); 3842*6185db85Sdougm return (ret); 3843*6185db85Sdougm } 3844*6185db85Sdougm sharepath = argv[optind++]; 3845*6185db85Sdougm if (realpath(sharepath, dir) == NULL) { 3846*6185db85Sdougm ret = SA_NO_SUCH_PATH; 3847*6185db85Sdougm } else { 3848*6185db85Sdougm sharepath = dir; 3849*6185db85Sdougm share = sa_find_share(sharepath); 3850*6185db85Sdougm if (share != NULL) { 3851*6185db85Sdougm ret = sa_disable_share(share, protocol); 3852*6185db85Sdougm if (ret == SA_OK) { 3853*6185db85Sdougm if (persist == SA_SHARE_PERMANENT) 3854*6185db85Sdougm ret = sa_remove_share(share); 3855*6185db85Sdougm ret = sa_update_config(); 3856*6185db85Sdougm } 3857*6185db85Sdougm } else { 3858*6185db85Sdougm ret = SA_NOT_SHARED; 3859*6185db85Sdougm } 3860*6185db85Sdougm } 3861*6185db85Sdougm } 3862*6185db85Sdougm switch (ret) { 3863*6185db85Sdougm default: 3864*6185db85Sdougm (void) printf("%s: %s\n", sharepath, sa_errorstr(ret)); 3865*6185db85Sdougm ret = SA_LEGACY_ERR; 3866*6185db85Sdougm break; 3867*6185db85Sdougm case SA_SYNTAX_ERR: 3868*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 3869*6185db85Sdougm sa_get_usage(USAGE_UNSHARE)); 3870*6185db85Sdougm break; 3871*6185db85Sdougm case SA_OK: 3872*6185db85Sdougm break; 3873*6185db85Sdougm } 3874*6185db85Sdougm return (ret); 3875*6185db85Sdougm } 3876*6185db85Sdougm 3877*6185db85Sdougm /* 3878*6185db85Sdougm * common commands that implement the sub-commands used by all 3879*6185db85Sdougm * protcols. The entries are found via the lookup command 3880*6185db85Sdougm */ 3881*6185db85Sdougm 3882*6185db85Sdougm static sa_command_t commands[] = { 3883*6185db85Sdougm {"add-share", 0, sa_addshare, USAGE_ADD_SHARE, SVC_SET}, 3884*6185db85Sdougm {"create", 0, sa_create, USAGE_CREATE, SVC_SET|SVC_ACTION}, 3885*6185db85Sdougm {"delete", 0, sa_delete, USAGE_DELETE, SVC_SET|SVC_ACTION}, 3886*6185db85Sdougm {"disable", 0, sa_disable_group, USAGE_DISABLE, SVC_SET|SVC_ACTION}, 3887*6185db85Sdougm {"enable", 0, sa_enable_group, USAGE_ENABLE, SVC_SET|SVC_ACTION}, 3888*6185db85Sdougm {"list", 0, sa_list, USAGE_LIST}, 3889*6185db85Sdougm {"move-share", 0, sa_moveshare, USAGE_MOVE_SHARE, SVC_SET}, 3890*6185db85Sdougm {"remove-share", 0, sa_removeshare, USAGE_REMOVE_SHARE, SVC_SET}, 3891*6185db85Sdougm {"set", 0, sa_set, USAGE_SET, SVC_SET}, 3892*6185db85Sdougm {"set-share", 0, sa_set_share, USAGE_SET_SHARE, SVC_SET}, 3893*6185db85Sdougm {"show", 0, sa_show, USAGE_SHOW}, 3894*6185db85Sdougm {"share", 0, sa_legacy_share, USAGE_SHARE, SVC_SET|SVC_ACTION}, 3895*6185db85Sdougm {"start", CMD_NODISPLAY, sa_start_group, USAGE_START, 3896*6185db85Sdougm SVC_SET|SVC_ACTION}, 3897*6185db85Sdougm {"stop", CMD_NODISPLAY, sa_stop_group, USAGE_STOP, SVC_SET|SVC_ACTION}, 3898*6185db85Sdougm {"unset", 0, sa_unset, USAGE_UNSET, SVC_SET}, 3899*6185db85Sdougm {"unshare", 0, sa_legacy_unshare, USAGE_UNSHARE, SVC_SET|SVC_ACTION}, 3900*6185db85Sdougm {NULL, 0, NULL, NULL} 3901*6185db85Sdougm }; 3902*6185db85Sdougm 3903*6185db85Sdougm static char * 3904*6185db85Sdougm sa_get_usage(sa_usage_t index) 3905*6185db85Sdougm { 3906*6185db85Sdougm char *ret = NULL; 3907*6185db85Sdougm switch (index) { 3908*6185db85Sdougm case USAGE_ADD_SHARE: 3909*6185db85Sdougm ret = gettext("add-share [-nth] [-r resource-name] " 3910*6185db85Sdougm "[-d \"description text\"] -s sharepath group"); 3911*6185db85Sdougm break; 3912*6185db85Sdougm case USAGE_CREATE: 3913*6185db85Sdougm ret = gettext("create [-nvh] [-P proto [-p property=value]] group"); 3914*6185db85Sdougm break; 3915*6185db85Sdougm case USAGE_DELETE: 3916*6185db85Sdougm ret = gettext("delete [-nvh] [-P proto] [-f] group"); 3917*6185db85Sdougm break; 3918*6185db85Sdougm case USAGE_DISABLE: 3919*6185db85Sdougm ret = gettext("disable [-nvh] {-a | group ...}"); 3920*6185db85Sdougm break; 3921*6185db85Sdougm case USAGE_ENABLE: 3922*6185db85Sdougm ret = gettext("enable [-nvh] {-a | group ...}"); 3923*6185db85Sdougm break; 3924*6185db85Sdougm case USAGE_LIST: 3925*6185db85Sdougm ret = gettext("list [-vh] [-P proto]"); 3926*6185db85Sdougm break; 3927*6185db85Sdougm case USAGE_MOVE_SHARE: 3928*6185db85Sdougm ret = gettext("move-share [-nvh] -s sharepath destination-group"); 3929*6185db85Sdougm break; 3930*6185db85Sdougm case USAGE_REMOVE_SHARE: 3931*6185db85Sdougm ret = gettext("remove-share [-fnvh] -s sharepath group"); 3932*6185db85Sdougm break; 3933*6185db85Sdougm case USAGE_SET: 3934*6185db85Sdougm ret = gettext("set [-nvh] -P proto [-S optspace] " 3935*6185db85Sdougm "[-p property=value]* [-s sharepath] group"); 3936*6185db85Sdougm break; 3937*6185db85Sdougm case USAGE_SET_SECURITY: 3938*6185db85Sdougm ret = gettext("set-security [-nvh] -P proto -S security-type " 3939*6185db85Sdougm "[-p property=value]* group"); 3940*6185db85Sdougm break; 3941*6185db85Sdougm case USAGE_SET_SHARE: 3942*6185db85Sdougm ret = gettext("set-share [-nh] [-r resource] " 3943*6185db85Sdougm "[-d \"description text\"] -s sharepath group"); 3944*6185db85Sdougm break; 3945*6185db85Sdougm case USAGE_SHOW: 3946*6185db85Sdougm ret = gettext("show [-pvxh] [-P proto] [group ...]"); 3947*6185db85Sdougm break; 3948*6185db85Sdougm case USAGE_SHARE: 3949*6185db85Sdougm ret = gettext("share [-F fstype] [-p] [-o optionlist]" 3950*6185db85Sdougm "[-d description] [pathname [resourcename]]"); 3951*6185db85Sdougm break; 3952*6185db85Sdougm case USAGE_START: 3953*6185db85Sdougm ret = gettext("start [-vh] [-P proto] {-a | group ...}"); 3954*6185db85Sdougm break; 3955*6185db85Sdougm case USAGE_STOP: 3956*6185db85Sdougm ret = gettext("stop [-vh] [-P proto] {-a | group ...}"); 3957*6185db85Sdougm break; 3958*6185db85Sdougm case USAGE_UNSET: 3959*6185db85Sdougm ret = gettext("unset [-nvh] -P proto [-S optspace] " 3960*6185db85Sdougm "[-p property]* group"); 3961*6185db85Sdougm break; 3962*6185db85Sdougm case USAGE_UNSET_SECURITY: 3963*6185db85Sdougm ret = gettext("unset-security [-nvh] -P proto -S security-type " 3964*6185db85Sdougm "[-p property]* group"); 3965*6185db85Sdougm break; 3966*6185db85Sdougm case USAGE_UNSHARE: 3967*6185db85Sdougm ret = gettext("unshare [-F fstype] [-p] [-o optionlist] sharepath"); 3968*6185db85Sdougm break; 3969*6185db85Sdougm } 3970*6185db85Sdougm return (ret); 3971*6185db85Sdougm } 3972*6185db85Sdougm 3973*6185db85Sdougm /* 3974*6185db85Sdougm * sa_lookup(cmd, proto) 3975*6185db85Sdougm * 3976*6185db85Sdougm * Lookup the sub-command. proto isn't currently used, but it may 3977*6185db85Sdougm * eventually provide a way to provide protocol specific sub-commands. 3978*6185db85Sdougm */ 3979*6185db85Sdougm 3980*6185db85Sdougm sa_command_t * 3981*6185db85Sdougm sa_lookup(char *cmd, char *proto) 3982*6185db85Sdougm { 3983*6185db85Sdougm int i; 3984*6185db85Sdougm size_t len; 3985*6185db85Sdougm #ifdef lint 3986*6185db85Sdougm proto = proto; 3987*6185db85Sdougm #endif 3988*6185db85Sdougm 3989*6185db85Sdougm len = strlen(cmd); 3990*6185db85Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 3991*6185db85Sdougm if (strncmp(cmd, commands[i].cmdname, len) == 0) 3992*6185db85Sdougm return (&commands[i]); 3993*6185db85Sdougm } 3994*6185db85Sdougm return (NULL); 3995*6185db85Sdougm } 3996*6185db85Sdougm 3997*6185db85Sdougm void 3998*6185db85Sdougm sub_command_help(char *proto) 3999*6185db85Sdougm { 4000*6185db85Sdougm int i; 4001*6185db85Sdougm #ifdef lint 4002*6185db85Sdougm proto = proto; 4003*6185db85Sdougm #endif 4004*6185db85Sdougm 4005*6185db85Sdougm (void) printf(gettext("\tsub-commands:\n")); 4006*6185db85Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 4007*6185db85Sdougm if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY))) 4008*6185db85Sdougm (void) printf("\t%s\n", 4009*6185db85Sdougm sa_get_usage((sa_usage_t)commands[i].cmdidx)); 4010*6185db85Sdougm } 4011*6185db85Sdougm } 4012