16185db85Sdougm /*
26185db85Sdougm * CDDL HEADER START
36185db85Sdougm *
46185db85Sdougm * The contents of this file are subject to the terms of the
56185db85Sdougm * Common Development and Distribution License (the "License").
66185db85Sdougm * You may not use this file except in compliance with the License.
76185db85Sdougm *
86185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96185db85Sdougm * or http://www.opensolaris.org/os/licensing.
106185db85Sdougm * See the License for the specific language governing permissions
116185db85Sdougm * and limitations under the License.
126185db85Sdougm *
136185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each
146185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the
166185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying
176185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner]
186185db85Sdougm *
196185db85Sdougm * CDDL HEADER END
206185db85Sdougm */
216185db85Sdougm
226185db85Sdougm /*
23fe1c642dSBill Krier * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
246185db85Sdougm * Use is subject to license terms.
25327e8b4bSAndy Fiddaman *
26327e8b4bSAndy Fiddaman * Copyright 2023 Oxide Computer Company
276185db85Sdougm */
286185db85Sdougm
296185db85Sdougm /* helper functions for using libscf with sharemgr */
306185db85Sdougm
316185db85Sdougm #include <libscf.h>
326185db85Sdougm #include <libxml/parser.h>
336185db85Sdougm #include <libxml/tree.h>
346185db85Sdougm #include "libshare.h"
356185db85Sdougm #include "libshare_impl.h"
366185db85Sdougm #include "scfutil.h"
376185db85Sdougm #include <string.h>
38da6c28aaSamw #include <ctype.h>
396185db85Sdougm #include <errno.h>
406185db85Sdougm #include <uuid/uuid.h>
416185db85Sdougm #include <sys/param.h>
42f345c0beSdougm #include <signal.h>
435b6e0c46Sdougm #include <sys/time.h>
441f29d134Sdougm #include <libintl.h>
456185db85Sdougm
466185db85Sdougm ssize_t scf_max_name_len;
476185db85Sdougm extern struct sa_proto_plugin *sap_proto_list;
48549ec3ffSdougm extern sa_handle_impl_t get_handle_for_root(xmlNodePtr);
495b6e0c46Sdougm static void set_transaction_tstamp(sa_handle_impl_t);
506185db85Sdougm /*
516185db85Sdougm * The SMF facility uses some properties that must exist. We want to
526185db85Sdougm * skip over these when processing protocol options.
536185db85Sdougm */
546185db85Sdougm static char *skip_props[] = {
556185db85Sdougm "modify_authorization",
566185db85Sdougm "action_authorization",
576185db85Sdougm "value_authorization",
586185db85Sdougm NULL
596185db85Sdougm };
606185db85Sdougm
616185db85Sdougm /*
626185db85Sdougm * sa_scf_fini(handle)
636185db85Sdougm *
6425a68471Sdougm * Must be called when done. Called with the handle allocated in
656185db85Sdougm * sa_scf_init(), it cleans up the state and frees any SCF resources
666185db85Sdougm * still in use. Called by sa_fini().
676185db85Sdougm */
686185db85Sdougm
696185db85Sdougm void
sa_scf_fini(scfutilhandle_t * handle)706185db85Sdougm sa_scf_fini(scfutilhandle_t *handle)
716185db85Sdougm {
726185db85Sdougm if (handle != NULL) {
7325a68471Sdougm int unbind = 0;
7425a68471Sdougm if (handle->scope != NULL) {
7525a68471Sdougm unbind = 1;
7625a68471Sdougm scf_scope_destroy(handle->scope);
7725a68471Sdougm }
7825a68471Sdougm if (handle->instance != NULL)
7925a68471Sdougm scf_instance_destroy(handle->instance);
8025a68471Sdougm if (handle->service != NULL)
8125a68471Sdougm scf_service_destroy(handle->service);
8225a68471Sdougm if (handle->pg != NULL)
8325a68471Sdougm scf_pg_destroy(handle->pg);
8425a68471Sdougm if (handle->handle != NULL) {
8525a68471Sdougm handle->scf_state = SCH_STATE_UNINIT;
8625a68471Sdougm if (unbind)
8725a68471Sdougm (void) scf_handle_unbind(handle->handle);
8825a68471Sdougm scf_handle_destroy(handle->handle);
8925a68471Sdougm }
9025a68471Sdougm free(handle);
916185db85Sdougm }
926185db85Sdougm }
936185db85Sdougm
946185db85Sdougm /*
956185db85Sdougm * sa_scf_init()
966185db85Sdougm *
9725a68471Sdougm * Must be called before using any of the SCF functions. Called by
986185db85Sdougm * sa_init() during the API setup.
996185db85Sdougm */
1006185db85Sdougm
1016185db85Sdougm scfutilhandle_t *
sa_scf_init(sa_handle_impl_t ihandle)102549ec3ffSdougm sa_scf_init(sa_handle_impl_t ihandle)
1036185db85Sdougm {
1046185db85Sdougm scfutilhandle_t *handle;
1056185db85Sdougm
1066185db85Sdougm scf_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
1076185db85Sdougm if (scf_max_name_len <= 0)
10825a68471Sdougm scf_max_name_len = SA_MAX_NAME_LEN + 1;
1096185db85Sdougm
1106185db85Sdougm handle = calloc(1, sizeof (scfutilhandle_t));
11125a68471Sdougm if (handle == NULL)
11225a68471Sdougm return (handle);
11325a68471Sdougm
11425a68471Sdougm ihandle->scfhandle = handle;
11525a68471Sdougm handle->scf_state = SCH_STATE_INITIALIZING;
11625a68471Sdougm handle->handle = scf_handle_create(SCF_VERSION);
11725a68471Sdougm if (handle->handle == NULL) {
1186185db85Sdougm free(handle);
1196185db85Sdougm handle = NULL;
1206185db85Sdougm (void) printf("libshare could not access SMF repository: %s\n",
12125a68471Sdougm scf_strerror(scf_error()));
12225a68471Sdougm return (handle);
1236185db85Sdougm }
12425a68471Sdougm if (scf_handle_bind(handle->handle) != 0)
12525a68471Sdougm goto err;
12625a68471Sdougm
12725a68471Sdougm handle->scope = scf_scope_create(handle->handle);
12825a68471Sdougm handle->service = scf_service_create(handle->handle);
12925a68471Sdougm handle->pg = scf_pg_create(handle->handle);
13025a68471Sdougm
13125a68471Sdougm /* Make sure we have sufficient SMF running */
13225a68471Sdougm handle->instance = scf_instance_create(handle->handle);
13325a68471Sdougm if (handle->scope == NULL || handle->service == NULL ||
13425a68471Sdougm handle->pg == NULL || handle->instance == NULL)
13525a68471Sdougm goto err;
13625a68471Sdougm if (scf_handle_get_scope(handle->handle,
13725a68471Sdougm SCF_SCOPE_LOCAL, handle->scope) != 0)
13825a68471Sdougm goto err;
13925a68471Sdougm if (scf_scope_get_service(handle->scope,
14025a68471Sdougm SA_GROUP_SVC_NAME, handle->service) != 0)
14125a68471Sdougm goto err;
14225a68471Sdougm
14325a68471Sdougm handle->scf_state = SCH_STATE_INIT;
14425a68471Sdougm if (sa_get_instance(handle, "default") != SA_OK) {
14525a68471Sdougm sa_group_t defgrp;
14625a68471Sdougm defgrp = sa_create_group((sa_handle_t)ihandle, "default", NULL);
1471f29d134Sdougm /* Only NFS enabled for "default" group. */
1481f29d134Sdougm if (defgrp != NULL)
1491f29d134Sdougm (void) sa_create_optionset(defgrp, "nfs");
15025a68471Sdougm }
15125a68471Sdougm
1526185db85Sdougm return (handle);
1536185db85Sdougm
15425a68471Sdougm /* Error handling/unwinding */
1556185db85Sdougm err:
1566185db85Sdougm (void) sa_scf_fini(handle);
157327e8b4bSAndy Fiddaman if (scf_error() != SCF_ERROR_NOT_FOUND) {
158327e8b4bSAndy Fiddaman (void) printf("libshare SMF initialization problem: %s\n",
159327e8b4bSAndy Fiddaman scf_strerror(scf_error()));
160327e8b4bSAndy Fiddaman }
1616185db85Sdougm return (NULL);
1626185db85Sdougm }
1636185db85Sdougm
1646185db85Sdougm /*
1656185db85Sdougm * get_scf_limit(name)
1666185db85Sdougm *
1676185db85Sdougm * Since we use scf_limit a lot and do the same check and return the
1686185db85Sdougm * same value if it fails, implement as a function for code
1696185db85Sdougm * simplification. Basically, if name isn't found, return MAXPATHLEN
1706185db85Sdougm * (1024) so we have a reasonable default buffer size.
1716185db85Sdougm */
1726185db85Sdougm static ssize_t
get_scf_limit(uint32_t name)1736185db85Sdougm get_scf_limit(uint32_t name)
1746185db85Sdougm {
1756185db85Sdougm ssize_t vallen;
1766185db85Sdougm
1776185db85Sdougm vallen = scf_limit(name);
1786185db85Sdougm if (vallen == (ssize_t)-1)
17925a68471Sdougm vallen = MAXPATHLEN;
1806185db85Sdougm return (vallen);
1816185db85Sdougm }
1826185db85Sdougm
1836185db85Sdougm /*
1846185db85Sdougm * skip_property(name)
1856185db85Sdougm *
18625a68471Sdougm * Internal function to check to see if a property is an SMF magic
1876185db85Sdougm * property that needs to be skipped.
1886185db85Sdougm */
1896185db85Sdougm static int
skip_property(char * name)1906185db85Sdougm skip_property(char *name)
1916185db85Sdougm {
1926185db85Sdougm int i;
1936185db85Sdougm
1946185db85Sdougm for (i = 0; skip_props[i] != NULL; i++)
19525a68471Sdougm if (strcmp(name, skip_props[i]) == 0)
196*2bc647a2SToomas Soome return (1);
1976185db85Sdougm return (0);
1986185db85Sdougm }
1996185db85Sdougm
2006185db85Sdougm /*
2016185db85Sdougm * generate_unique_sharename(sharename)
2026185db85Sdougm *
2036185db85Sdougm * Shares are represented in SMF as property groups. Due to share
2046185db85Sdougm * paths containing characters that are not allowed in SMF names and
2056185db85Sdougm * the need to be unique, we use UUIDs to construct a unique name.
2066185db85Sdougm */
2076185db85Sdougm
2086185db85Sdougm static void
generate_unique_sharename(char * sharename)2096185db85Sdougm generate_unique_sharename(char *sharename)
2106185db85Sdougm {
2116185db85Sdougm uuid_t uuid;
2126185db85Sdougm
2136185db85Sdougm uuid_generate(uuid);
2146185db85Sdougm (void) strcpy(sharename, "S-");
2156185db85Sdougm uuid_unparse(uuid, sharename + 2);
2166185db85Sdougm }
2176185db85Sdougm
2186185db85Sdougm /*
2196185db85Sdougm * valid_protocol(proto)
2206185db85Sdougm *
22125a68471Sdougm * Check to see if the specified protocol is a valid one for the
2226185db85Sdougm * general sharemgr facility. We determine this by checking which
2236185db85Sdougm * plugin protocols were found.
2246185db85Sdougm */
2256185db85Sdougm
2266185db85Sdougm static int
valid_protocol(char * proto)2276185db85Sdougm valid_protocol(char *proto)
2286185db85Sdougm {
2296185db85Sdougm struct sa_proto_plugin *plugin;
2306185db85Sdougm for (plugin = sap_proto_list; plugin != NULL;
2316185db85Sdougm plugin = plugin->plugin_next)
23225a68471Sdougm if (strcmp(proto, plugin->plugin_ops->sa_protocol) == 0)
23325a68471Sdougm return (1);
2346185db85Sdougm return (0);
2356185db85Sdougm }
2366185db85Sdougm
2376185db85Sdougm /*
2386185db85Sdougm * sa_extract_pgroup(root, handle, pg, nodetype, proto, sectype)
2396185db85Sdougm *
24025a68471Sdougm * Extract the name property group and create the specified type of
2416185db85Sdougm * node on the provided group. type will be optionset or security.
2426185db85Sdougm */
2436185db85Sdougm
2446185db85Sdougm static int
sa_extract_pgroup(xmlNodePtr root,scfutilhandle_t * handle,scf_propertygroup_t * pg,char * nodetype,char * proto,char * sectype)2456185db85Sdougm sa_extract_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
246327e8b4bSAndy Fiddaman scf_propertygroup_t *pg, char *nodetype, char *proto, char *sectype)
2476185db85Sdougm {
2486185db85Sdougm xmlNodePtr node;
2496185db85Sdougm scf_iter_t *iter;
2506185db85Sdougm scf_property_t *prop;
2516185db85Sdougm scf_value_t *value;
2526185db85Sdougm char *name;
2536185db85Sdougm char *valuestr;
2546185db85Sdougm ssize_t vallen;
2556185db85Sdougm int ret = SA_OK;
2566185db85Sdougm
2576185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
2586185db85Sdougm
2596185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)nodetype, NULL);
26025a68471Sdougm if (node == NULL)
26125a68471Sdougm return (ret);
26225a68471Sdougm
26325a68471Sdougm if (proto != NULL)
2647a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
26525a68471Sdougm if (sectype != NULL)
2667a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"sectype",
2677a9d7716Sthurlow (xmlChar *)sectype);
26825a68471Sdougm /*
26925a68471Sdougm * Have node to work with so iterate over the properties
27025a68471Sdougm * in the pg and create option sub nodes.
27125a68471Sdougm */
27225a68471Sdougm iter = scf_iter_create(handle->handle);
27325a68471Sdougm value = scf_value_create(handle->handle);
27425a68471Sdougm prop = scf_property_create(handle->handle);
27525a68471Sdougm name = malloc(scf_max_name_len);
27625a68471Sdougm valuestr = malloc(vallen);
27725a68471Sdougm /*
27825a68471Sdougm * Want to iterate through the properties and add them
27925a68471Sdougm * to the base optionset.
28025a68471Sdougm */
28125a68471Sdougm if (iter == NULL || value == NULL || prop == NULL ||
28225a68471Sdougm valuestr == NULL || name == NULL) {
28325a68471Sdougm ret = SA_NO_MEMORY;
28425a68471Sdougm goto out;
28525a68471Sdougm }
28625a68471Sdougm if (scf_iter_pg_properties(iter, pg) == 0) {
28725a68471Sdougm /* Now iterate the properties in the group */
28825a68471Sdougm while (scf_iter_next_property(iter, prop) > 0) {
28925a68471Sdougm /* have a property */
29025a68471Sdougm if (scf_property_get_name(prop, name,
29125a68471Sdougm scf_max_name_len) > 0) {
29225a68471Sdougm sa_property_t saprop;
29325a68471Sdougm /* Some properties are part of the framework */
2946185db85Sdougm if (skip_property(name))
29525a68471Sdougm continue;
29625a68471Sdougm if (scf_property_get_value(prop, value) != 0)
29725a68471Sdougm continue;
29825a68471Sdougm if (scf_value_get_astring(value, valuestr,
29925a68471Sdougm vallen) < 0)
30025a68471Sdougm continue;
30125a68471Sdougm saprop = sa_create_property(name, valuestr);
30225a68471Sdougm if (saprop != NULL) {
3036185db85Sdougm /*
30425a68471Sdougm * Since in SMF, don't
3056185db85Sdougm * recurse. Use xmlAddChild
3066185db85Sdougm * directly, instead.
3076185db85Sdougm */
3087a9d7716Sthurlow (void) xmlAddChild(node,
30925a68471Sdougm (xmlNodePtr) saprop);
3106185db85Sdougm }
3116185db85Sdougm }
3126185db85Sdougm }
3136185db85Sdougm }
31425a68471Sdougm out:
31525a68471Sdougm /* cleanup to avoid memory leaks */
31625a68471Sdougm if (value != NULL)
31725a68471Sdougm scf_value_destroy(value);
31825a68471Sdougm if (iter != NULL)
31925a68471Sdougm scf_iter_destroy(iter);
32025a68471Sdougm if (prop != NULL)
32125a68471Sdougm scf_property_destroy(prop);
32225a68471Sdougm if (name != NULL)
32325a68471Sdougm free(name);
32425a68471Sdougm if (valuestr != NULL)
32525a68471Sdougm free(valuestr);
32625a68471Sdougm
3276185db85Sdougm return (ret);
3286185db85Sdougm }
3296185db85Sdougm
3306185db85Sdougm /*
3316185db85Sdougm * sa_extract_attrs(root, handle, instance)
3326185db85Sdougm *
33325a68471Sdougm * Local function to extract the actual attributes/properties from the
3346185db85Sdougm * property group of the service instance. These are the well known
3356185db85Sdougm * attributes of "state" and "zfs". If additional attributes are
3366185db85Sdougm * added, they should be added here.
3376185db85Sdougm */
3386185db85Sdougm
3396185db85Sdougm static void
sa_extract_attrs(xmlNodePtr root,scfutilhandle_t * handle,scf_instance_t * instance)3406185db85Sdougm sa_extract_attrs(xmlNodePtr root, scfutilhandle_t *handle,
341327e8b4bSAndy Fiddaman scf_instance_t *instance)
3426185db85Sdougm {
3436185db85Sdougm scf_property_t *prop;
3446185db85Sdougm scf_value_t *value;
3456185db85Sdougm char *valuestr;
3466185db85Sdougm ssize_t vallen;
3476185db85Sdougm
3486185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
3496185db85Sdougm prop = scf_property_create(handle->handle);
3506185db85Sdougm value = scf_value_create(handle->handle);
3516185db85Sdougm valuestr = malloc(vallen);
35225a68471Sdougm if (prop == NULL || value == NULL || valuestr == NULL ||
35325a68471Sdougm scf_instance_get_pg(instance, "operation", handle->pg) != 0) {
35425a68471Sdougm goto out;
35525a68471Sdougm }
35625a68471Sdougm /*
35725a68471Sdougm * Have a property group with desired name so now get
35825a68471Sdougm * the known attributes.
35925a68471Sdougm */
36025a68471Sdougm if (scf_pg_get_property(handle->pg, "state", prop) == 0) {
36125a68471Sdougm /* Found the property so get the value */
3626185db85Sdougm if (scf_property_get_value(prop, value) == 0) {
36325a68471Sdougm if (scf_value_get_astring(value, valuestr,
36425a68471Sdougm vallen) >= 0) {
3657a9d7716Sthurlow (void) xmlSetProp(root, (xmlChar *)"state",
3666185db85Sdougm (xmlChar *)valuestr);
36725a68471Sdougm }
3686185db85Sdougm }
36925a68471Sdougm }
37025a68471Sdougm if (scf_pg_get_property(handle->pg, "zfs", prop) == 0) {
37125a68471Sdougm /* Found the property so get the value */
3726185db85Sdougm if (scf_property_get_value(prop, value) == 0) {
37325a68471Sdougm if (scf_value_get_astring(value, valuestr,
37425a68471Sdougm vallen) > 0) {
3757a9d7716Sthurlow (void) xmlSetProp(root, (xmlChar *)"zfs",
3766185db85Sdougm (xmlChar *)valuestr);
37725a68471Sdougm }
3786185db85Sdougm }
3796185db85Sdougm }
38025a68471Sdougm out:
3816185db85Sdougm if (valuestr != NULL)
38225a68471Sdougm free(valuestr);
3836185db85Sdougm if (value != NULL)
38425a68471Sdougm scf_value_destroy(value);
3856185db85Sdougm if (prop != NULL)
38625a68471Sdougm scf_property_destroy(prop);
3876185db85Sdougm }
3886185db85Sdougm
3896185db85Sdougm /*
39025a68471Sdougm * List of known share attributes.
3916185db85Sdougm */
3926185db85Sdougm
3936185db85Sdougm static char *share_attr[] = {
3946185db85Sdougm "path",
3956185db85Sdougm "id",
396da6c28aaSamw "drive-letter",
397da6c28aaSamw "exclude",
3986185db85Sdougm NULL,
3996185db85Sdougm };
4006185db85Sdougm
4016185db85Sdougm static int
is_share_attr(char * name)4026185db85Sdougm is_share_attr(char *name)
4036185db85Sdougm {
4046185db85Sdougm int i;
4056185db85Sdougm for (i = 0; share_attr[i] != NULL; i++)
40625a68471Sdougm if (strcmp(name, share_attr[i]) == 0)
40725a68471Sdougm return (1);
4086185db85Sdougm return (0);
4096185db85Sdougm }
4106185db85Sdougm
411da6c28aaSamw /*
412da6c28aaSamw * _sa_make_resource(node, valuestr)
413da6c28aaSamw *
414da6c28aaSamw * Make a resource node on the share node. The valusestr will either
415da6c28aaSamw * be old format (SMF acceptable string) or new format (pretty much an
416da6c28aaSamw * arbitrary string with "nnn:" prefixing in order to persist
417da6c28aaSamw * mapping). The input valuestr will get modified in place. This is
418da6c28aaSamw * only used in SMF repository parsing. A possible third field will be
419da6c28aaSamw * a "description" string.
420da6c28aaSamw */
421da6c28aaSamw
422da6c28aaSamw static void
_sa_make_resource(xmlNodePtr node,char * valuestr)423da6c28aaSamw _sa_make_resource(xmlNodePtr node, char *valuestr)
424da6c28aaSamw {
425da6c28aaSamw char *idx;
426da6c28aaSamw char *name;
427da6c28aaSamw char *description = NULL;
428da6c28aaSamw
429da6c28aaSamw idx = valuestr;
430da6c28aaSamw name = strchr(valuestr, ':');
431da6c28aaSamw if (name == NULL) {
432da6c28aaSamw /* this is old form so give an index of "0" */
433da6c28aaSamw idx = "0";
434da6c28aaSamw name = valuestr;
435da6c28aaSamw } else {
436da6c28aaSamw /* NUL the ':' and move past it */
437da6c28aaSamw *name++ = '\0';
438da6c28aaSamw /* There could also be a description string */
439da6c28aaSamw description = strchr(name, ':');
440da6c28aaSamw if (description != NULL)
441da6c28aaSamw *description++ = '\0';
442da6c28aaSamw }
443da6c28aaSamw node = xmlNewChild(node, NULL, (xmlChar *)"resource", NULL);
444da6c28aaSamw if (node != NULL) {
4457a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"name", (xmlChar *)name);
4467a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"id", (xmlChar *)idx);
447da6c28aaSamw /* SMF values are always persistent */
4487a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"type",
4497a9d7716Sthurlow (xmlChar *)"persist");
450da6c28aaSamw if (description != NULL && strlen(description) > 0) {
451da6c28aaSamw (void) xmlNewChild(node, NULL, (xmlChar *)"description",
452da6c28aaSamw (xmlChar *)description);
453da6c28aaSamw }
454da6c28aaSamw }
455da6c28aaSamw }
456da6c28aaSamw
457da6c28aaSamw
4586185db85Sdougm /*
4596185db85Sdougm * sa_share_from_pgroup
4606185db85Sdougm *
46125a68471Sdougm * Extract the share definition from the share property group. We do
4626185db85Sdougm * some sanity checking to avoid bad data.
4636185db85Sdougm *
4646185db85Sdougm * Since this is only constructing the internal data structures, we
4656185db85Sdougm * don't use the sa_* functions most of the time.
4666185db85Sdougm */
4676185db85Sdougm void
sa_share_from_pgroup(xmlNodePtr root,scfutilhandle_t * handle,scf_propertygroup_t * pg,char * id)4686185db85Sdougm sa_share_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
469327e8b4bSAndy Fiddaman scf_propertygroup_t *pg, char *id)
4706185db85Sdougm {
4716185db85Sdougm xmlNodePtr node;
4726185db85Sdougm char *name;
4736185db85Sdougm scf_iter_t *iter;
4746185db85Sdougm scf_property_t *prop;
4756185db85Sdougm scf_value_t *value;
4766185db85Sdougm ssize_t vallen;
4776185db85Sdougm char *valuestr;
4786185db85Sdougm int ret = SA_OK;
479f345c0beSdougm int have_path = 0;
4806185db85Sdougm
4816185db85Sdougm /*
4826185db85Sdougm * While preliminary check (starts with 'S') passed before
4836185db85Sdougm * getting here. Need to make sure it is in ID syntax
4846185db85Sdougm * (Snnnnnn). Note that shares with properties have similar
4856185db85Sdougm * pgroups.
4866185db85Sdougm */
4876185db85Sdougm vallen = strlen(id);
4886185db85Sdougm if (*id == SA_SHARE_PG_PREFIX[0] && vallen == SA_SHARE_PG_LEN) {
48925a68471Sdougm uuid_t uuid;
49025a68471Sdougm if (strncmp(id, SA_SHARE_PG_PREFIX,
49125a68471Sdougm SA_SHARE_PG_PREFIXLEN) != 0 ||
49225a68471Sdougm uuid_parse(id + 2, uuid) < 0)
49325a68471Sdougm return;
4946185db85Sdougm } else {
49525a68471Sdougm return;
4966185db85Sdougm }
4976185db85Sdougm
4986185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
4996185db85Sdougm
5006185db85Sdougm iter = scf_iter_create(handle->handle);
5016185db85Sdougm value = scf_value_create(handle->handle);
5026185db85Sdougm prop = scf_property_create(handle->handle);
5036185db85Sdougm name = malloc(scf_max_name_len);
5046185db85Sdougm valuestr = malloc(vallen);
5056185db85Sdougm
5066185db85Sdougm /*
50725a68471Sdougm * Construct the share XML node. It is similar to sa_add_share
5086185db85Sdougm * but never changes the repository. Also, there won't be any
5096185db85Sdougm * ZFS or transient shares. Root will be the group it is
5106185db85Sdougm * associated with.
5116185db85Sdougm */
5126185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"share", NULL);
5136185db85Sdougm if (node != NULL) {
5146185db85Sdougm /*
51525a68471Sdougm * Make sure the UUID part of the property group is
5166185db85Sdougm * stored in the share "id" property. We use this
5176185db85Sdougm * later.
5186185db85Sdougm */
5197a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"id", (xmlChar *)id);
5207a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"type",
5217a9d7716Sthurlow (xmlChar *)"persist");
5226185db85Sdougm }
5236185db85Sdougm
52425a68471Sdougm if (iter == NULL || value == NULL || prop == NULL || name == NULL)
52525a68471Sdougm goto out;
52625a68471Sdougm
52725a68471Sdougm /* Iterate over the share pg properties */
52825a68471Sdougm if (scf_iter_pg_properties(iter, pg) != 0)
52925a68471Sdougm goto out;
53025a68471Sdougm
53125a68471Sdougm while (scf_iter_next_property(iter, prop) > 0) {
53225a68471Sdougm ret = SA_SYSTEM_ERR; /* assume the worst */
53325a68471Sdougm if (scf_property_get_name(prop, name, scf_max_name_len) > 0) {
5346185db85Sdougm if (scf_property_get_value(prop, value) == 0) {
53525a68471Sdougm if (scf_value_get_astring(value, valuestr,
53625a68471Sdougm vallen) >= 0) {
53725a68471Sdougm ret = SA_OK;
53825a68471Sdougm }
539da6c28aaSamw } else if (strcmp(name, "resource") == 0) {
540da6c28aaSamw ret = SA_OK;
5416185db85Sdougm }
54225a68471Sdougm }
543da6c28aaSamw if (ret != SA_OK)
544da6c28aaSamw continue;
545da6c28aaSamw /*
546da6c28aaSamw * Check that we have the "path" property in
547da6c28aaSamw * name. The string in name will always be nul
548da6c28aaSamw * terminated if scf_property_get_name()
549da6c28aaSamw * succeeded.
550da6c28aaSamw */
551da6c28aaSamw if (strcmp(name, "path") == 0)
552da6c28aaSamw have_path = 1;
553da6c28aaSamw if (is_share_attr(name)) {
554f345c0beSdougm /*
555da6c28aaSamw * If a share attr, then simple -
556da6c28aaSamw * usually path and id name
557f345c0beSdougm */
5587a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)name,
559da6c28aaSamw (xmlChar *)valuestr);
560da6c28aaSamw } else if (strcmp(name, "resource") == 0) {
561da6c28aaSamw /*
562da6c28aaSamw * Resource names handled differently since
563da6c28aaSamw * there can be multiple on each share. The
564da6c28aaSamw * "resource" id must be preserved since this
565da6c28aaSamw * will be used by some protocols in mapping
566da6c28aaSamw * "property spaces" to names and is always
567da6c28aaSamw * used to create SMF property groups specific
568da6c28aaSamw * to resources. CIFS needs this. The first
569da6c28aaSamw * value is present so add and then loop for
570da6c28aaSamw * any additional. Since this is new and
571da6c28aaSamw * previous values may exist, handle
572da6c28aaSamw * conversions.
573da6c28aaSamw */
574da6c28aaSamw scf_iter_t *viter;
575da6c28aaSamw viter = scf_iter_create(handle->handle);
576da6c28aaSamw if (viter != NULL &&
577da6c28aaSamw scf_iter_property_values(viter, prop) == 0) {
578da6c28aaSamw while (scf_iter_next_value(viter, value) > 0) {
579da6c28aaSamw /* Have a value so process it */
580da6c28aaSamw if (scf_value_get_ustring(value,
581da6c28aaSamw valuestr, vallen) >= 0) {
582da6c28aaSamw /* have a ustring */
583da6c28aaSamw _sa_make_resource(node,
584da6c28aaSamw valuestr);
585da6c28aaSamw } else if (scf_value_get_astring(value,
586da6c28aaSamw valuestr, vallen) >= 0) {
587da6c28aaSamw /* have an astring */
588da6c28aaSamw _sa_make_resource(node,
589da6c28aaSamw valuestr);
590da6c28aaSamw }
59125a68471Sdougm }
592da6c28aaSamw scf_iter_destroy(viter);
593da6c28aaSamw }
594da6c28aaSamw } else {
595da6c28aaSamw if (strcmp(name, "description") == 0) {
596da6c28aaSamw /* We have a description node */
597da6c28aaSamw xmlNodePtr desc;
598da6c28aaSamw desc = xmlNewChild(node, NULL,
599da6c28aaSamw (xmlChar *)"description", NULL);
600da6c28aaSamw if (desc != NULL)
601da6c28aaSamw xmlNodeSetContent(desc,
602da6c28aaSamw (xmlChar *)valuestr);
6036185db85Sdougm }
6046185db85Sdougm }
6056185db85Sdougm }
60625a68471Sdougm out:
607f345c0beSdougm /*
60825a68471Sdougm * A share without a path is broken so we want to not include
609f345c0beSdougm * these. They shouldn't happen but if you kill a sharemgr in
610f345c0beSdougm * the process of creating a share, it could happen. They
611f345c0beSdougm * should be harmless. It is also possible that another
612f345c0beSdougm * sharemgr is running and in the process of creating a share.
613f345c0beSdougm */
614f345c0beSdougm if (have_path == 0 && node != NULL) {
61525a68471Sdougm xmlUnlinkNode(node);
61625a68471Sdougm xmlFreeNode(node);
617f345c0beSdougm }
6186185db85Sdougm if (name != NULL)
61925a68471Sdougm free(name);
6206185db85Sdougm if (valuestr != NULL)
62125a68471Sdougm free(valuestr);
6226185db85Sdougm if (value != NULL)
62325a68471Sdougm scf_value_destroy(value);
6246185db85Sdougm if (iter != NULL)
62525a68471Sdougm scf_iter_destroy(iter);
6266185db85Sdougm if (prop != NULL)
62725a68471Sdougm scf_property_destroy(prop);
6286185db85Sdougm }
6296185db85Sdougm
6306185db85Sdougm /*
6316185db85Sdougm * find_share_by_id(shareid)
6326185db85Sdougm *
6336185db85Sdougm * Search all shares in all groups until we find the share represented
6346185db85Sdougm * by "id".
6356185db85Sdougm */
6366185db85Sdougm
6376185db85Sdougm static sa_share_t
find_share_by_id(sa_handle_t handle,char * shareid)638549ec3ffSdougm find_share_by_id(sa_handle_t handle, char *shareid)
6396185db85Sdougm {
6406185db85Sdougm sa_group_t group;
6416185db85Sdougm sa_share_t share = NULL;
6426185db85Sdougm char *id = NULL;
6436185db85Sdougm int done = 0;
6446185db85Sdougm
64525a68471Sdougm for (group = sa_get_group(handle, NULL);
64625a68471Sdougm group != NULL && !done;
64725a68471Sdougm group = sa_get_next_group(group)) {
64825a68471Sdougm for (share = sa_get_share(group, NULL);
64925a68471Sdougm share != NULL;
65025a68471Sdougm share = sa_get_next_share(share)) {
6516185db85Sdougm id = sa_get_share_attr(share, "id");
6526185db85Sdougm if (id != NULL && strcmp(id, shareid) == 0) {
6536185db85Sdougm sa_free_attr_string(id);
6546185db85Sdougm id = NULL;
6556185db85Sdougm done++;
6566185db85Sdougm break;
6576185db85Sdougm }
6586185db85Sdougm if (id != NULL) {
65925a68471Sdougm sa_free_attr_string(id);
66025a68471Sdougm id = NULL;
6616185db85Sdougm }
6626185db85Sdougm }
6636185db85Sdougm }
6646185db85Sdougm return (share);
6656185db85Sdougm }
6666185db85Sdougm
6676185db85Sdougm /*
668da6c28aaSamw * find_resource_by_index(share, index)
669da6c28aaSamw *
670da6c28aaSamw * Search the resource records on the share for the id index.
671da6c28aaSamw */
672da6c28aaSamw static sa_resource_t
find_resource_by_index(sa_share_t share,char * index)673da6c28aaSamw find_resource_by_index(sa_share_t share, char *index)
674da6c28aaSamw {
675da6c28aaSamw sa_resource_t resource;
676da6c28aaSamw sa_resource_t found = NULL;
677da6c28aaSamw char *id;
678da6c28aaSamw
679da6c28aaSamw for (resource = sa_get_share_resource(share, NULL);
680da6c28aaSamw resource != NULL && found == NULL;
681da6c28aaSamw resource = sa_get_next_resource(resource)) {
682da6c28aaSamw id = (char *)xmlGetProp((xmlNodePtr)resource, (xmlChar *)"id");
683da6c28aaSamw if (id != NULL) {
684da6c28aaSamw if (strcmp(id, index) == 0) {
685da6c28aaSamw /* found it so save in "found" */
686da6c28aaSamw found = resource;
687da6c28aaSamw }
688da6c28aaSamw sa_free_attr_string(id);
689da6c28aaSamw }
690da6c28aaSamw }
691da6c28aaSamw return (found);
692da6c28aaSamw }
693da6c28aaSamw
694da6c28aaSamw /*
695da6c28aaSamw * sa_share_props_from_pgroup(root, handle, pg, id, sahandle)
6966185db85Sdougm *
69725a68471Sdougm * Extract share properties from the SMF property group. More sanity
6986185db85Sdougm * checks are done and the share object is created. We ignore some
6996185db85Sdougm * errors that could exist in the repository and only worry about
7006185db85Sdougm * property groups that validate in naming.
7016185db85Sdougm */
7026185db85Sdougm
7036185db85Sdougm static int
sa_share_props_from_pgroup(xmlNodePtr root,scfutilhandle_t * handle,scf_propertygroup_t * pg,char * id,sa_handle_t sahandle)7046185db85Sdougm sa_share_props_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
705327e8b4bSAndy Fiddaman scf_propertygroup_t *pg, char *id, sa_handle_t sahandle)
7066185db85Sdougm {
7076185db85Sdougm xmlNodePtr node;
70825a68471Sdougm char *name = NULL;
70925a68471Sdougm scf_iter_t *iter = NULL;
71025a68471Sdougm scf_property_t *prop = NULL;
71125a68471Sdougm scf_value_t *value = NULL;
7126185db85Sdougm ssize_t vallen;
71325a68471Sdougm char *valuestr = NULL;
7146185db85Sdougm int ret = SA_OK;
7156185db85Sdougm char *sectype = NULL;
716*2bc647a2SToomas Soome char *proto = NULL;
7176185db85Sdougm sa_share_t share;
71825a68471Sdougm uuid_t uuid;
7196185db85Sdougm
7206185db85Sdougm /*
7216185db85Sdougm * While preliminary check (starts with 'S') passed before
7226185db85Sdougm * getting here. Need to make sure it is in ID syntax
7236185db85Sdougm * (Snnnnnn). Note that shares with properties have similar
7246185db85Sdougm * pgroups. If the pg name is more than SA_SHARE_PG_LEN
7256185db85Sdougm * characters, it is likely one of the protocol/security
7266185db85Sdougm * versions.
7276185db85Sdougm */
7286185db85Sdougm vallen = strlen(id);
72925a68471Sdougm if (*id != SA_SHARE_PG_PREFIX[0] || vallen <= SA_SHARE_PG_LEN) {
73025a68471Sdougm /*
73125a68471Sdougm * It is ok to not have what we thought since someone might
73225a68471Sdougm * have added a name via SMF.
73325a68471Sdougm */
73425a68471Sdougm return (ret);
73525a68471Sdougm }
73625a68471Sdougm if (strncmp(id, SA_SHARE_PG_PREFIX, SA_SHARE_PG_PREFIXLEN) == 0) {
7376185db85Sdougm proto = strchr(id, '_');
7386185db85Sdougm if (proto == NULL)
73925a68471Sdougm return (ret);
7406185db85Sdougm *proto++ = '\0';
7416185db85Sdougm if (uuid_parse(id + SA_SHARE_PG_PREFIXLEN, uuid) < 0)
74225a68471Sdougm return (ret);
7436185db85Sdougm /*
7446185db85Sdougm * probably a legal optionset so check a few more
7456185db85Sdougm * syntax points below.
7466185db85Sdougm */
7476185db85Sdougm if (*proto == '\0') {
74825a68471Sdougm /* not a valid proto (null) */
74925a68471Sdougm return (ret);
7506185db85Sdougm }
751da6c28aaSamw
7526185db85Sdougm sectype = strchr(proto, '_');
7536185db85Sdougm if (sectype != NULL)
75425a68471Sdougm *sectype++ = '\0';
7556185db85Sdougm if (!valid_protocol(proto))
75625a68471Sdougm return (ret);
7576185db85Sdougm }
7586185db85Sdougm
7596185db85Sdougm /*
76025a68471Sdougm * To get here, we have a valid protocol and possibly a
7616185db85Sdougm * security. We now have to find the share that it is really
7626185db85Sdougm * associated with. The "id" portion of the pgroup name will
7636185db85Sdougm * match.
7646185db85Sdougm */
7656185db85Sdougm
766549ec3ffSdougm share = find_share_by_id(sahandle, id);
7676185db85Sdougm if (share == NULL)
76825a68471Sdougm return (SA_BAD_PATH);
7696185db85Sdougm
7706185db85Sdougm root = (xmlNodePtr)share;
7716185db85Sdougm
7726185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
7736185db85Sdougm
77425a68471Sdougm if (sectype == NULL)
77525a68471Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"optionset", NULL);
77625a68471Sdougm else {
777da6c28aaSamw if (isdigit((int)*sectype)) {
778da6c28aaSamw sa_resource_t resource;
779da6c28aaSamw /*
780da6c28aaSamw * If sectype[0] is a digit, then it is an index into
781da6c28aaSamw * the resource names. We need to find a resource
782da6c28aaSamw * record and then get the properties into an
783da6c28aaSamw * optionset. The optionset becomes the "node" and the
784da6c28aaSamw * rest is hung off of the share.
785da6c28aaSamw */
786da6c28aaSamw resource = find_resource_by_index(share, sectype);
787da6c28aaSamw if (resource != NULL) {
788da6c28aaSamw node = xmlNewChild(resource, NULL,
789da6c28aaSamw (xmlChar *)"optionset", NULL);
790da6c28aaSamw } else {
79155bf511dSas /* This shouldn't happen. */
792da6c28aaSamw ret = SA_SYSTEM_ERR;
79355bf511dSas goto out;
794da6c28aaSamw }
795da6c28aaSamw } else {
796da6c28aaSamw /*
797da6c28aaSamw * If not a digit, then it is a security type
798da6c28aaSamw * (alternate option space). Security types start with
799da6c28aaSamw * an alphabetic.
800da6c28aaSamw */
801da6c28aaSamw node = xmlNewChild(root, NULL, (xmlChar *)"security",
802da6c28aaSamw NULL);
803da6c28aaSamw if (node != NULL)
8047a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"sectype",
805da6c28aaSamw (xmlChar *)sectype);
806da6c28aaSamw }
80725a68471Sdougm }
80825a68471Sdougm if (node == NULL) {
80925a68471Sdougm ret = SA_NO_MEMORY;
81025a68471Sdougm goto out;
81125a68471Sdougm }
81225a68471Sdougm
8137a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
81425a68471Sdougm /* now find the properties */
8156185db85Sdougm iter = scf_iter_create(handle->handle);
8166185db85Sdougm value = scf_value_create(handle->handle);
8176185db85Sdougm prop = scf_property_create(handle->handle);
8186185db85Sdougm name = malloc(scf_max_name_len);
8196185db85Sdougm valuestr = malloc(vallen);
8206185db85Sdougm
82125a68471Sdougm if (iter == NULL || value == NULL || prop == NULL || name == NULL)
82225a68471Sdougm goto out;
82325a68471Sdougm
824da6c28aaSamw /* iterate over the share pg properties */
82525a68471Sdougm if (scf_iter_pg_properties(iter, pg) == 0) {
82625a68471Sdougm while (scf_iter_next_property(iter, prop) > 0) {
8276185db85Sdougm ret = SA_SYSTEM_ERR; /* assume the worst */
8286185db85Sdougm if (scf_property_get_name(prop, name,
82925a68471Sdougm scf_max_name_len) > 0) {
83025a68471Sdougm if (scf_property_get_value(prop, value) == 0) {
83125a68471Sdougm if (scf_value_get_astring(value,
83225a68471Sdougm valuestr, vallen) >= 0) {
83325a68471Sdougm ret = SA_OK;
83425a68471Sdougm }
8356185db85Sdougm }
8366185db85Sdougm } else {
83725a68471Sdougm ret = SA_SYSTEM_ERR;
8386185db85Sdougm }
8396185db85Sdougm if (ret == SA_OK) {
84025a68471Sdougm sa_property_t prop;
84125a68471Sdougm prop = sa_create_property(name, valuestr);
84225a68471Sdougm if (prop != NULL)
84325a68471Sdougm prop = (sa_property_t)xmlAddChild(node,
84425a68471Sdougm (xmlNodePtr)prop);
84525a68471Sdougm else
84625a68471Sdougm ret = SA_NO_MEMORY;
8476185db85Sdougm }
8486185db85Sdougm }
8496185db85Sdougm } else {
85025a68471Sdougm ret = SA_SYSTEM_ERR;
8516185db85Sdougm }
85225a68471Sdougm out:
8536185db85Sdougm if (iter != NULL)
85425a68471Sdougm scf_iter_destroy(iter);
8556185db85Sdougm if (value != NULL)
85625a68471Sdougm scf_value_destroy(value);
8576185db85Sdougm if (prop != NULL)
85825a68471Sdougm scf_property_destroy(prop);
8596185db85Sdougm if (name != NULL)
86025a68471Sdougm free(name);
8616185db85Sdougm if (valuestr != NULL)
86225a68471Sdougm free(valuestr);
8636185db85Sdougm return (ret);
8646185db85Sdougm }
8656185db85Sdougm
8666185db85Sdougm /*
8676185db85Sdougm * sa_extract_group(root, handle, instance)
8686185db85Sdougm *
86925a68471Sdougm * Get the config info for this instance of a group and create the XML
8706185db85Sdougm * subtree from it.
8716185db85Sdougm */
8726185db85Sdougm
8736185db85Sdougm static int
sa_extract_group(xmlNodePtr root,scfutilhandle_t * handle,scf_instance_t * instance,sa_handle_t sahandle)8746185db85Sdougm sa_extract_group(xmlNodePtr root, scfutilhandle_t *handle,
8755b6e0c46Sdougm scf_instance_t *instance, sa_handle_t sahandle)
8766185db85Sdougm {
8776185db85Sdougm char *buff;
8786185db85Sdougm xmlNodePtr node;
8796185db85Sdougm scf_iter_t *iter;
8806185db85Sdougm char *proto;
8816185db85Sdougm char *sectype;
8821f29d134Sdougm boolean_t have_shares = B_FALSE;
8831f29d134Sdougm boolean_t is_default = B_FALSE;
8841f29d134Sdougm boolean_t is_nfs = B_FALSE;
8856185db85Sdougm int ret = SA_OK;
8866185db85Sdougm int err;
8876185db85Sdougm
8886185db85Sdougm buff = malloc(scf_max_name_len);
88925a68471Sdougm if (buff == NULL)
89025a68471Sdougm return (SA_NO_MEMORY);
89125a68471Sdougm
8926185db85Sdougm iter = scf_iter_create(handle->handle);
89325a68471Sdougm if (iter == NULL) {
89425a68471Sdougm ret = SA_NO_MEMORY;
89525a68471Sdougm goto out;
89625a68471Sdougm }
89725a68471Sdougm
89825a68471Sdougm if (scf_instance_get_name(instance, buff, scf_max_name_len) > 0) {
8996185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"group", NULL);
90025a68471Sdougm if (node == NULL) {
90125a68471Sdougm ret = SA_NO_MEMORY;
90225a68471Sdougm goto out;
90325a68471Sdougm }
9047a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"name", (xmlChar *)buff);
90525a68471Sdougm if (strcmp(buff, "default") == 0)
9061f29d134Sdougm is_default = B_TRUE;
90725a68471Sdougm
90825a68471Sdougm sa_extract_attrs(node, handle, instance);
90925a68471Sdougm /*
91025a68471Sdougm * Iterate through all the property groups
91125a68471Sdougm * looking for those with security or
91225a68471Sdougm * optionset prefixes. The names of the
91325a68471Sdougm * matching pgroups are parsed to get the
91425a68471Sdougm * protocol, and for security, the sectype.
91525a68471Sdougm * Syntax is as follows:
91625a68471Sdougm * optionset | optionset_<proto>
91725a68471Sdougm * security_default | security_<proto>_<sectype>
91825a68471Sdougm * "operation" is handled by
91925a68471Sdougm * sa_extract_attrs().
92025a68471Sdougm */
92125a68471Sdougm if (scf_iter_instance_pgs(iter, instance) != 0) {
92225a68471Sdougm ret = SA_NO_MEMORY;
92325a68471Sdougm goto out;
92425a68471Sdougm }
92525a68471Sdougm while (scf_iter_next_pg(iter, handle->pg) > 0) {
92625a68471Sdougm /* Have a pgroup so sort it out */
92725a68471Sdougm ret = scf_pg_get_name(handle->pg, buff,
92825a68471Sdougm scf_max_name_len);
9291f29d134Sdougm if (ret <= 0)
9301f29d134Sdougm continue;
9311f29d134Sdougm is_nfs = B_FALSE;
9321f29d134Sdougm
9331f29d134Sdougm if (buff[0] == SA_SHARE_PG_PREFIX[0]) {
9341f29d134Sdougm sa_share_from_pgroup(node, handle,
9351f29d134Sdougm handle->pg, buff);
9361f29d134Sdougm have_shares = B_TRUE;
9371f29d134Sdougm } else if (strncmp(buff, "optionset", 9) == 0) {
9381f29d134Sdougm char *nodetype = "optionset";
9391f29d134Sdougm /* Have an optionset */
9401f29d134Sdougm sectype = NULL;
9411f29d134Sdougm proto = strchr(buff, '_');
9421f29d134Sdougm if (proto != NULL) {
9431f29d134Sdougm *proto++ = '\0';
9441f29d134Sdougm sectype = strchr(proto, '_');
9451f29d134Sdougm if (sectype != NULL) {
9461f29d134Sdougm *sectype++ = '\0';
9471f29d134Sdougm nodetype = "security";
9486185db85Sdougm }
9491f29d134Sdougm is_nfs = strcmp(proto, "nfs") == 0;
9501f29d134Sdougm } else if (strlen(buff) > 9) {
9516185db85Sdougm /*
9521f29d134Sdougm * This can only occur if
9531f29d134Sdougm * someone has made changes
9541f29d134Sdougm * via an SMF command. Since
9551f29d134Sdougm * this would be an unknown
9561f29d134Sdougm * syntax, we just ignore it.
9576185db85Sdougm */
9581f29d134Sdougm continue;
9591f29d134Sdougm }
9601f29d134Sdougm /*
9611f29d134Sdougm * If the group is not "default" or is
9621f29d134Sdougm * "default" and is_nfs, then extract the
9631f29d134Sdougm * pgroup. If it is_default and !is_nfs,
9641f29d134Sdougm * then we have an error and should remove
9651f29d134Sdougm * the extraneous protocols. We don't care
9661f29d134Sdougm * about errors on scf_pg_delete since we
9671f29d134Sdougm * might not have permission during an
9681f29d134Sdougm * extract only.
9691f29d134Sdougm */
9701f29d134Sdougm if (!is_default || is_nfs) {
9716185db85Sdougm ret = sa_extract_pgroup(node, handle,
9721f29d134Sdougm handle->pg, nodetype, proto,
97325a68471Sdougm sectype);
9741f29d134Sdougm } else {
9751f29d134Sdougm err = scf_pg_delete(handle->pg);
9761f29d134Sdougm if (err == 0)
9771f29d134Sdougm (void) fprintf(stderr,
9781f29d134Sdougm dgettext(TEXT_DOMAIN,
9791f29d134Sdougm "Removed protocol \"%s\" "
9801f29d134Sdougm "from group \"default\"\n"),
9811f29d134Sdougm proto);
9821f29d134Sdougm }
9831f29d134Sdougm } else if (strncmp(buff, "security", 8) == 0) {
9841f29d134Sdougm /*
9851f29d134Sdougm * Have a security (note that
9861f29d134Sdougm * this should change in the
9871f29d134Sdougm * future)
9881f29d134Sdougm */
9891f29d134Sdougm proto = strchr(buff, '_');
9901f29d134Sdougm sectype = NULL;
9911f29d134Sdougm if (proto != NULL) {
9921f29d134Sdougm *proto++ = '\0';
9931f29d134Sdougm sectype = strchr(proto, '_');
9941f29d134Sdougm if (sectype != NULL)
9951f29d134Sdougm *sectype++ = '\0';
9961f29d134Sdougm if (strcmp(proto, "default") == 0)
9971f29d134Sdougm proto = NULL;
9986185db85Sdougm }
9991f29d134Sdougm ret = sa_extract_pgroup(node, handle,
10001f29d134Sdougm handle->pg, "security", proto, sectype);
10016185db85Sdougm }
10021f29d134Sdougm /* Ignore everything else */
100325a68471Sdougm }
100425a68471Sdougm /*
100525a68471Sdougm * Make sure we have a valid default group.
100625a68471Sdougm * On first boot, default won't have any
100725a68471Sdougm * protocols defined and won't be enabled (but
10081f29d134Sdougm * should be). "default" only has NFS enabled on it.
100925a68471Sdougm */
101025a68471Sdougm if (is_default) {
101125a68471Sdougm char *state = sa_get_group_attr((sa_group_t)node,
101225a68471Sdougm "state");
101325a68471Sdougm
101425a68471Sdougm if (state == NULL) {
10156185db85Sdougm /* set attribute to enabled */
10166185db85Sdougm (void) sa_set_group_attr((sa_group_t)node,
101725a68471Sdougm "state", "enabled");
10181f29d134Sdougm (void) sa_create_optionset((sa_group_t)node,
10191f29d134Sdougm "nfs");
102025a68471Sdougm } else {
10216185db85Sdougm sa_free_attr_string(state);
10226185db85Sdougm }
102325a68471Sdougm }
102425a68471Sdougm /* Do a second pass if shares were found */
102525a68471Sdougm if (have_shares && scf_iter_instance_pgs(iter, instance) == 0) {
102625a68471Sdougm while (scf_iter_next_pg(iter, handle->pg) > 0) {
10276185db85Sdougm /*
102825a68471Sdougm * Have a pgroup so see if it is a
10296185db85Sdougm * share optionset
10306185db85Sdougm */
10316185db85Sdougm err = scf_pg_get_name(handle->pg, buff,
103225a68471Sdougm scf_max_name_len);
103325a68471Sdougm if (err <= 0)
103425a68471Sdougm continue;
103525a68471Sdougm if (buff[0] == SA_SHARE_PG_PREFIX[0]) {
10366185db85Sdougm ret = sa_share_props_from_pgroup(node,
103725a68471Sdougm handle, handle->pg, buff,
103825a68471Sdougm sahandle);
10396185db85Sdougm }
10406185db85Sdougm }
10416185db85Sdougm }
10426185db85Sdougm }
104325a68471Sdougm out:
10446185db85Sdougm if (iter != NULL)
104525a68471Sdougm scf_iter_destroy(iter);
10466185db85Sdougm if (buff != NULL)
104725a68471Sdougm free(buff);
10486185db85Sdougm return (ret);
10496185db85Sdougm }
10506185db85Sdougm
10516185db85Sdougm /*
10526185db85Sdougm * sa_extract_defaults(root, handle, instance)
10536185db85Sdougm *
105425a68471Sdougm * Local function to find the default properties that live in the
1055da6c28aaSamw * default instance's "operation" property group.
10566185db85Sdougm */
10576185db85Sdougm
10586185db85Sdougm static void
sa_extract_defaults(xmlNodePtr root,scfutilhandle_t * handle,scf_instance_t * instance)10596185db85Sdougm sa_extract_defaults(xmlNodePtr root, scfutilhandle_t *handle,
1060327e8b4bSAndy Fiddaman scf_instance_t *instance)
10616185db85Sdougm {
10626185db85Sdougm xmlNodePtr node;
10636185db85Sdougm scf_property_t *prop;
10646185db85Sdougm scf_value_t *value;
10656185db85Sdougm char *valuestr;
10666185db85Sdougm ssize_t vallen;
10676185db85Sdougm
10686185db85Sdougm vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
10696185db85Sdougm prop = scf_property_create(handle->handle);
10706185db85Sdougm value = scf_value_create(handle->handle);
10716185db85Sdougm valuestr = malloc(vallen);
107225a68471Sdougm
107325a68471Sdougm if (prop == NULL || value == NULL || vallen == 0 ||
107425a68471Sdougm scf_instance_get_pg(instance, "operation", handle->pg) != 0)
107525a68471Sdougm goto out;
107625a68471Sdougm
107725a68471Sdougm if (scf_pg_get_property(handle->pg, "legacy-timestamp", prop) != 0)
107825a68471Sdougm goto out;
107925a68471Sdougm
108025a68471Sdougm /* Found the property so get the value */
108125a68471Sdougm if (scf_property_get_value(prop, value) == 0) {
108225a68471Sdougm if (scf_value_get_astring(value, valuestr, vallen) > 0) {
10836185db85Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"legacy",
108425a68471Sdougm NULL);
10856185db85Sdougm if (node != NULL) {
10867a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"timestamp",
108725a68471Sdougm (xmlChar *)valuestr);
10887a9d7716Sthurlow (void) xmlSetProp(node, (xmlChar *)"path",
108925a68471Sdougm (xmlChar *)SA_LEGACY_DFSTAB);
10906185db85Sdougm }
10916185db85Sdougm }
10926185db85Sdougm }
109325a68471Sdougm out:
10946185db85Sdougm if (valuestr != NULL)
109525a68471Sdougm free(valuestr);
10966185db85Sdougm if (value != NULL)
109725a68471Sdougm scf_value_destroy(value);
10986185db85Sdougm if (prop != NULL)
109925a68471Sdougm scf_property_destroy(prop);
11006185db85Sdougm }
11016185db85Sdougm
11026185db85Sdougm
11036185db85Sdougm /*
1104da6c28aaSamw * sa_get_config(handle, root, doc, sahandle)
11056185db85Sdougm *
110625a68471Sdougm * Walk the SMF repository for /network/shares/group and find all the
11076185db85Sdougm * instances. These become group names. Then add the XML structure
11086185db85Sdougm * below the groups based on property groups and properties.
11096185db85Sdougm */
11106185db85Sdougm int
sa_get_config(scfutilhandle_t * handle,xmlNodePtr root,sa_handle_t sahandle)11111d1813a7Sdougm sa_get_config(scfutilhandle_t *handle, xmlNodePtr root, sa_handle_t sahandle)
11126185db85Sdougm {
11136185db85Sdougm int ret = SA_OK;
11146185db85Sdougm scf_instance_t *instance;
11156185db85Sdougm scf_iter_t *iter;
11166185db85Sdougm char buff[BUFSIZ * 2];
11176185db85Sdougm
11186185db85Sdougm instance = scf_instance_create(handle->handle);
11196185db85Sdougm iter = scf_iter_create(handle->handle);
11201d1813a7Sdougm if (instance != NULL && iter != NULL) {
112125a68471Sdougm if ((ret = scf_iter_service_instances(iter,
112225a68471Sdougm handle->service)) == 0) {
112325a68471Sdougm while ((ret = scf_iter_next_instance(iter,
112425a68471Sdougm instance)) > 0) {
112525a68471Sdougm if (scf_instance_get_name(instance, buff,
112625a68471Sdougm sizeof (buff)) > 0) {
112725a68471Sdougm if (strcmp(buff, "default") == 0)
112825a68471Sdougm sa_extract_defaults(root,
112925a68471Sdougm handle, instance);
113025a68471Sdougm ret = sa_extract_group(root, handle,
113125a68471Sdougm instance, sahandle);
113225a68471Sdougm }
113325a68471Sdougm }
11346185db85Sdougm }
11356185db85Sdougm }
11361d1813a7Sdougm
113725a68471Sdougm /* Always cleanup these */
11386185db85Sdougm if (instance != NULL)
113925a68471Sdougm scf_instance_destroy(instance);
11406185db85Sdougm if (iter != NULL)
114125a68471Sdougm scf_iter_destroy(iter);
11426185db85Sdougm return (ret);
11436185db85Sdougm }
11446185db85Sdougm
11456185db85Sdougm /*
11466185db85Sdougm * sa_get_instance(handle, instance)
11476185db85Sdougm *
114825a68471Sdougm * Get the instance of the group service. This is actually the
11496185db85Sdougm * specific group name. The instance is needed for all property and
11506185db85Sdougm * control operations.
11516185db85Sdougm */
11526185db85Sdougm
11536185db85Sdougm int
sa_get_instance(scfutilhandle_t * handle,char * instname)11546185db85Sdougm sa_get_instance(scfutilhandle_t *handle, char *instname)
11556185db85Sdougm {
11566185db85Sdougm if (scf_service_get_instance(handle->service, instname,
115725a68471Sdougm handle->instance) != 0) {
115825a68471Sdougm return (SA_NO_SUCH_GROUP);
11596185db85Sdougm }
11606185db85Sdougm return (SA_OK);
11616185db85Sdougm }
11626185db85Sdougm
11636185db85Sdougm /*
11646185db85Sdougm * sa_create_instance(handle, instname)
11656185db85Sdougm *
11666185db85Sdougm * Create a new SMF service instance. There can only be one with a
11676185db85Sdougm * given name.
11686185db85Sdougm */
11696185db85Sdougm
11706185db85Sdougm int
sa_create_instance(scfutilhandle_t * handle,char * instname)11716185db85Sdougm sa_create_instance(scfutilhandle_t *handle, char *instname)
11726185db85Sdougm {
11736185db85Sdougm int ret = SA_OK;
11746185db85Sdougm char instance[SA_GROUP_INST_LEN];
11756185db85Sdougm if (scf_service_add_instance(handle->service, instname,
117625a68471Sdougm handle->instance) != 0) {
11776185db85Sdougm /* better error returns need to be added based on real error */
117825a68471Sdougm if (scf_error() == SCF_ERROR_PERMISSION_DENIED)
117925a68471Sdougm ret = SA_NO_PERMISSION;
118025a68471Sdougm else
118125a68471Sdougm ret = SA_DUPLICATE_NAME;
11826185db85Sdougm } else {
118325a68471Sdougm /* have the service created, so enable it */
118425a68471Sdougm (void) snprintf(instance, sizeof (instance), "%s:%s",
118525a68471Sdougm SA_SVC_FMRI_BASE, instname);
118625a68471Sdougm (void) smf_enable_instance(instance, 0);
11876185db85Sdougm }
11886185db85Sdougm return (ret);
11896185db85Sdougm }
11906185db85Sdougm
11916185db85Sdougm /*
11926185db85Sdougm * sa_delete_instance(handle, instname)
11936185db85Sdougm *
11946185db85Sdougm * When a group goes away, we also remove the service instance.
11956185db85Sdougm */
11966185db85Sdougm
11976185db85Sdougm int
sa_delete_instance(scfutilhandle_t * handle,char * instname)11986185db85Sdougm sa_delete_instance(scfutilhandle_t *handle, char *instname)
11996185db85Sdougm {
12006185db85Sdougm int ret;
12016185db85Sdougm
12026185db85Sdougm if (strcmp(instname, "default") == 0) {
120325a68471Sdougm ret = SA_NO_PERMISSION;
12046185db85Sdougm } else {
120525a68471Sdougm if ((ret = sa_get_instance(handle, instname)) == SA_OK) {
120625a68471Sdougm if (scf_instance_delete(handle->instance) != 0)
120725a68471Sdougm /* need better analysis */
120825a68471Sdougm ret = SA_NO_PERMISSION;
120925a68471Sdougm }
12106185db85Sdougm }
12116185db85Sdougm return (ret);
12126185db85Sdougm }
12136185db85Sdougm
12146185db85Sdougm /*
12156185db85Sdougm * sa_create_pgroup(handle, pgroup)
12166185db85Sdougm *
12176185db85Sdougm * create a new property group
12186185db85Sdougm */
12196185db85Sdougm
12206185db85Sdougm int
sa_create_pgroup(scfutilhandle_t * handle,char * pgroup)12216185db85Sdougm sa_create_pgroup(scfutilhandle_t *handle, char *pgroup)
12226185db85Sdougm {
12236185db85Sdougm int ret = SA_OK;
12245b6e0c46Sdougm int persist = 0;
12255b6e0c46Sdougm
12266185db85Sdougm /*
122725a68471Sdougm * Only create a handle if it doesn't exist. It is ok to exist
12286185db85Sdougm * since the pg handle will be set as a side effect.
12296185db85Sdougm */
123025a68471Sdougm if (handle->pg == NULL)
123125a68471Sdougm handle->pg = scf_pg_create(handle->handle);
123225a68471Sdougm
12335b6e0c46Sdougm /*
12345b6e0c46Sdougm * Special case for a non-persistent property group. This is
12355b6e0c46Sdougm * internal use only.
12365b6e0c46Sdougm */
12375b6e0c46Sdougm if (*pgroup == '*') {
12385b6e0c46Sdougm persist = SCF_PG_FLAG_NONPERSISTENT;
12395b6e0c46Sdougm pgroup++;
12405b6e0c46Sdougm }
12415b6e0c46Sdougm
12426185db85Sdougm /*
124325a68471Sdougm * If the pgroup exists, we are done. If it doesn't, then we
12446185db85Sdougm * need to actually add one to the service instance.
12456185db85Sdougm */
12466185db85Sdougm if (scf_instance_get_pg(handle->instance,
124725a68471Sdougm pgroup, handle->pg) != 0) {
12485b6e0c46Sdougm
124925a68471Sdougm /* Doesn't exist so create one */
125025a68471Sdougm if (scf_instance_add_pg(handle->instance, pgroup,
12515b6e0c46Sdougm SCF_GROUP_APPLICATION, persist, handle->pg) != 0) {
125225a68471Sdougm switch (scf_error()) {
125325a68471Sdougm case SCF_ERROR_PERMISSION_DENIED:
125425a68471Sdougm ret = SA_NO_PERMISSION;
125525a68471Sdougm break;
125625a68471Sdougm default:
125725a68471Sdougm ret = SA_SYSTEM_ERR;
125825a68471Sdougm break;
125925a68471Sdougm }
12606185db85Sdougm }
12616185db85Sdougm }
12626185db85Sdougm return (ret);
12636185db85Sdougm }
12646185db85Sdougm
12656185db85Sdougm /*
12666185db85Sdougm * sa_delete_pgroup(handle, pgroup)
12676185db85Sdougm *
126825a68471Sdougm * Remove the property group from the current instance of the service,
12696185db85Sdougm * but only if it actually exists.
12706185db85Sdougm */
12716185db85Sdougm
12726185db85Sdougm int
sa_delete_pgroup(scfutilhandle_t * handle,char * pgroup)12736185db85Sdougm sa_delete_pgroup(scfutilhandle_t *handle, char *pgroup)
12746185db85Sdougm {
12756185db85Sdougm int ret = SA_OK;
12766185db85Sdougm /*
127725a68471Sdougm * Only delete if it does exist.
12786185db85Sdougm */
127925a68471Sdougm if (scf_instance_get_pg(handle->instance, pgroup, handle->pg) == 0) {
128025a68471Sdougm /* does exist so delete it */
128125a68471Sdougm if (scf_pg_delete(handle->pg) != 0)
128225a68471Sdougm ret = SA_SYSTEM_ERR;
12836185db85Sdougm } else {
128425a68471Sdougm ret = SA_SYSTEM_ERR;
12856185db85Sdougm }
12866185db85Sdougm if (ret == SA_SYSTEM_ERR &&
12876185db85Sdougm scf_error() == SCF_ERROR_PERMISSION_DENIED) {
12886185db85Sdougm ret = SA_NO_PERMISSION;
12896185db85Sdougm }
12906185db85Sdougm return (ret);
12916185db85Sdougm }
12926185db85Sdougm
12936185db85Sdougm /*
12946185db85Sdougm * sa_start_transaction(handle, pgroup)
12956185db85Sdougm *
12966185db85Sdougm * Start an SMF transaction so we can deal with properties. it would
12976185db85Sdougm * be nice to not have to expose this, but we have to in order to
12986185db85Sdougm * optimize.
12996185db85Sdougm *
13006185db85Sdougm * Basic model is to hold the transaction in the handle and allow
13016185db85Sdougm * property adds/deletes/updates to be added then close the
13026185db85Sdougm * transaction (or abort). There may eventually be a need to handle
13036185db85Sdougm * other types of transaction mechanisms but we don't do that now.
13046185db85Sdougm *
13056185db85Sdougm * An sa_start_transaction must be followed by either an
13066185db85Sdougm * sa_end_transaction or sa_abort_transaction before another
13076185db85Sdougm * sa_start_transaction can be done.
13086185db85Sdougm */
13096185db85Sdougm
13106185db85Sdougm int
sa_start_transaction(scfutilhandle_t * handle,char * propgroup)13116185db85Sdougm sa_start_transaction(scfutilhandle_t *handle, char *propgroup)
13126185db85Sdougm {
13136185db85Sdougm int ret = SA_OK;
13146185db85Sdougm /*
131525a68471Sdougm * Lookup the property group and create it if it doesn't already
13166185db85Sdougm * exist.
13176185db85Sdougm */
13185b6e0c46Sdougm if (handle == NULL)
13195b6e0c46Sdougm return (SA_CONFIG_ERR);
13205b6e0c46Sdougm
13216185db85Sdougm if (handle->scf_state == SCH_STATE_INIT) {
132225a68471Sdougm ret = sa_create_pgroup(handle, propgroup);
132325a68471Sdougm if (ret == SA_OK) {
132425a68471Sdougm handle->trans = scf_transaction_create(handle->handle);
132525a68471Sdougm if (handle->trans != NULL) {
132625a68471Sdougm if (scf_transaction_start(handle->trans,
132725a68471Sdougm handle->pg) != 0) {
132825a68471Sdougm ret = SA_SYSTEM_ERR;
132925a68471Sdougm }
133025a68471Sdougm if (ret != SA_OK) {
133125a68471Sdougm scf_transaction_destroy(handle->trans);
133225a68471Sdougm handle->trans = NULL;
133325a68471Sdougm }
133425a68471Sdougm } else {
133525a68471Sdougm ret = SA_SYSTEM_ERR;
133625a68471Sdougm }
13376185db85Sdougm }
13386185db85Sdougm }
13396185db85Sdougm if (ret == SA_SYSTEM_ERR &&
13406185db85Sdougm scf_error() == SCF_ERROR_PERMISSION_DENIED) {
13416185db85Sdougm ret = SA_NO_PERMISSION;
13426185db85Sdougm }
13436185db85Sdougm return (ret);
13446185db85Sdougm }
13456185db85Sdougm
13465b6e0c46Sdougm
13476185db85Sdougm /*
13485b6e0c46Sdougm * sa_end_transaction(scfhandle, sahandle)
13496185db85Sdougm *
13506185db85Sdougm * Commit the changes that were added to the transaction in the
13516185db85Sdougm * handle. Do all necessary cleanup.
13526185db85Sdougm */
13536185db85Sdougm
13546185db85Sdougm int
sa_end_transaction(scfutilhandle_t * handle,sa_handle_impl_t sahandle)13555b6e0c46Sdougm sa_end_transaction(scfutilhandle_t *handle, sa_handle_impl_t sahandle)
13566185db85Sdougm {
13576185db85Sdougm int ret = SA_OK;
13586185db85Sdougm
13595b6e0c46Sdougm if (handle == NULL || handle->trans == NULL || sahandle == NULL) {
13606185db85Sdougm ret = SA_SYSTEM_ERR;
136125a68471Sdougm } else {
136225a68471Sdougm if (scf_transaction_commit(handle->trans) < 0)
136325a68471Sdougm ret = SA_SYSTEM_ERR;
136425a68471Sdougm scf_transaction_destroy_children(handle->trans);
136525a68471Sdougm scf_transaction_destroy(handle->trans);
13665b6e0c46Sdougm if (ret == SA_OK)
13675b6e0c46Sdougm set_transaction_tstamp(sahandle);
136825a68471Sdougm handle->trans = NULL;
13696185db85Sdougm }
13706185db85Sdougm return (ret);
13716185db85Sdougm }
13726185db85Sdougm
13736185db85Sdougm /*
13746185db85Sdougm * sa_abort_transaction(handle)
13756185db85Sdougm *
13766185db85Sdougm * Abort the changes that were added to the transaction in the
13776185db85Sdougm * handle. Do all necessary cleanup.
13786185db85Sdougm */
13796185db85Sdougm
13806185db85Sdougm void
sa_abort_transaction(scfutilhandle_t * handle)13816185db85Sdougm sa_abort_transaction(scfutilhandle_t *handle)
13826185db85Sdougm {
13836185db85Sdougm if (handle->trans != NULL) {
138425a68471Sdougm scf_transaction_reset_all(handle->trans);
138525a68471Sdougm scf_transaction_destroy_children(handle->trans);
138625a68471Sdougm scf_transaction_destroy(handle->trans);
138725a68471Sdougm handle->trans = NULL;
13886185db85Sdougm }
13896185db85Sdougm }
13906185db85Sdougm
13915b6e0c46Sdougm /*
13925b6e0c46Sdougm * set_transaction_tstamp(sahandle)
13935b6e0c46Sdougm *
13945b6e0c46Sdougm * After a successful transaction commit, update the timestamp of the
13955b6e0c46Sdougm * last transaction. This lets us detect changes from other processes.
13965b6e0c46Sdougm */
13975b6e0c46Sdougm static void
set_transaction_tstamp(sa_handle_impl_t sahandle)13985b6e0c46Sdougm set_transaction_tstamp(sa_handle_impl_t sahandle)
13995b6e0c46Sdougm {
14005b6e0c46Sdougm char tstring[32];
14015b6e0c46Sdougm struct timeval tv;
14025b6e0c46Sdougm scfutilhandle_t *scfhandle;
14035b6e0c46Sdougm
14045b6e0c46Sdougm if (sahandle == NULL || sahandle->scfhandle == NULL)
14055b6e0c46Sdougm return;
14065b6e0c46Sdougm
14075b6e0c46Sdougm scfhandle = sahandle->scfhandle;
14085b6e0c46Sdougm
14095b6e0c46Sdougm if (sa_get_instance(scfhandle, "default") != SA_OK)
14105b6e0c46Sdougm return;
14115b6e0c46Sdougm
14125b6e0c46Sdougm if (gettimeofday(&tv, NULL) != 0)
14135b6e0c46Sdougm return;
14145b6e0c46Sdougm
14155b6e0c46Sdougm if (sa_start_transaction(scfhandle, "*state") != SA_OK)
14165b6e0c46Sdougm return;
14175b6e0c46Sdougm
14185b6e0c46Sdougm sahandle->tstrans = TSTAMP((*(timestruc_t *)&tv));
14195b6e0c46Sdougm (void) snprintf(tstring, sizeof (tstring), "%lld", sahandle->tstrans);
14205b6e0c46Sdougm if (sa_set_property(sahandle->scfhandle, "lastupdate", tstring) ==
14215b6e0c46Sdougm SA_OK) {
14225b6e0c46Sdougm /*
14235b6e0c46Sdougm * While best if it succeeds, a failure doesn't cause
14245b6e0c46Sdougm * problems and we will ignore it anyway.
14255b6e0c46Sdougm */
14265b6e0c46Sdougm (void) scf_transaction_commit(scfhandle->trans);
14275b6e0c46Sdougm scf_transaction_destroy_children(scfhandle->trans);
14285b6e0c46Sdougm scf_transaction_destroy(scfhandle->trans);
14295b6e0c46Sdougm } else {
14305b6e0c46Sdougm sa_abort_transaction(scfhandle);
14315b6e0c46Sdougm }
14325b6e0c46Sdougm }
14335b6e0c46Sdougm
14346185db85Sdougm /*
14356185db85Sdougm * sa_set_property(handle, prop, value)
14366185db85Sdougm *
143725a68471Sdougm * Set a property transaction entry into the pending SMF transaction.
14386185db85Sdougm */
14396185db85Sdougm
14406185db85Sdougm int
sa_set_property(scfutilhandle_t * handle,char * propname,char * valstr)14416185db85Sdougm sa_set_property(scfutilhandle_t *handle, char *propname, char *valstr)
14426185db85Sdougm {
14436185db85Sdougm int ret = SA_OK;
14446185db85Sdougm scf_value_t *value;
14456185db85Sdougm scf_transaction_entry_t *entry;
14466185db85Sdougm /*
144725a68471Sdougm * Properties must be set in transactions and don't take
14486185db85Sdougm * effect until the transaction has been ended/committed.
14496185db85Sdougm */
14506185db85Sdougm value = scf_value_create(handle->handle);
14516185db85Sdougm entry = scf_entry_create(handle->handle);
14526185db85Sdougm if (value != NULL && entry != NULL) {
145325a68471Sdougm if (scf_transaction_property_change(handle->trans, entry,
145425a68471Sdougm propname, SCF_TYPE_ASTRING) == 0 ||
145525a68471Sdougm scf_transaction_property_new(handle->trans, entry,
145625a68471Sdougm propname, SCF_TYPE_ASTRING) == 0) {
145725a68471Sdougm if (scf_value_set_astring(value, valstr) == 0) {
145825a68471Sdougm if (scf_entry_add_value(entry, value) != 0) {
145925a68471Sdougm ret = SA_SYSTEM_ERR;
146025a68471Sdougm scf_value_destroy(value);
146125a68471Sdougm }
146225a68471Sdougm /* The value is in the transaction */
146325a68471Sdougm value = NULL;
146425a68471Sdougm } else {
146525a68471Sdougm /* Value couldn't be constructed */
146625a68471Sdougm ret = SA_SYSTEM_ERR;
146725a68471Sdougm }
146825a68471Sdougm /* The entry is in the transaction */
146925a68471Sdougm entry = NULL;
14706185db85Sdougm } else {
147125a68471Sdougm ret = SA_SYSTEM_ERR;
14726185db85Sdougm }
14736185db85Sdougm } else {
147425a68471Sdougm ret = SA_SYSTEM_ERR;
14756185db85Sdougm }
14766185db85Sdougm if (ret == SA_SYSTEM_ERR) {
1477*2bc647a2SToomas Soome if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
147825a68471Sdougm ret = SA_NO_PERMISSION;
147925a68471Sdougm }
14806185db85Sdougm }
14816185db85Sdougm /*
148225a68471Sdougm * Cleanup if there were any errors that didn't leave these
14836185db85Sdougm * values where they would be cleaned up later.
14846185db85Sdougm */
14856185db85Sdougm if (value != NULL)
148625a68471Sdougm scf_value_destroy(value);
14876185db85Sdougm if (entry != NULL)
148825a68471Sdougm scf_entry_destroy(entry);
14896185db85Sdougm return (ret);
14906185db85Sdougm }
14916185db85Sdougm
1492da6c28aaSamw /*
1493da6c28aaSamw * check_resource(share)
1494da6c28aaSamw *
1495da6c28aaSamw * Check to see if share has any persistent resources. We don't want
1496da6c28aaSamw * to save if they are all transient.
1497da6c28aaSamw */
1498da6c28aaSamw static int
check_resource(sa_share_t share)1499da6c28aaSamw check_resource(sa_share_t share)
1500da6c28aaSamw {
1501da6c28aaSamw sa_resource_t resource;
1502da6c28aaSamw int ret = B_FALSE;
1503da6c28aaSamw
1504da6c28aaSamw for (resource = sa_get_share_resource(share, NULL);
1505da6c28aaSamw resource != NULL && ret == B_FALSE;
1506da6c28aaSamw resource = sa_get_next_resource(resource)) {
1507da6c28aaSamw char *type;
1508da6c28aaSamw type = sa_get_resource_attr(resource, "type");
1509da6c28aaSamw if (type != NULL) {
1510da6c28aaSamw if (strcmp(type, "transient") != 0) {
1511da6c28aaSamw ret = B_TRUE;
1512da6c28aaSamw }
1513da6c28aaSamw sa_free_attr_string(type);
1514da6c28aaSamw }
1515da6c28aaSamw }
1516da6c28aaSamw return (ret);
1517da6c28aaSamw }
1518da6c28aaSamw
1519da6c28aaSamw /*
1520da6c28aaSamw * sa_set_resource_property(handle, prop, value)
1521da6c28aaSamw *
1522da6c28aaSamw * set a property transaction entry into the pending SMF
1523da6c28aaSamw * transaction. We don't want to include any transient resources
1524da6c28aaSamw */
1525da6c28aaSamw
1526da6c28aaSamw static int
sa_set_resource_property(scfutilhandle_t * handle,sa_share_t share)1527da6c28aaSamw sa_set_resource_property(scfutilhandle_t *handle, sa_share_t share)
1528da6c28aaSamw {
1529da6c28aaSamw int ret = SA_OK;
1530da6c28aaSamw scf_value_t *value;
1531da6c28aaSamw scf_transaction_entry_t *entry;
1532da6c28aaSamw sa_resource_t resource;
1533*2bc647a2SToomas Soome char *valstr = NULL;
1534*2bc647a2SToomas Soome char *idstr = NULL;
1535*2bc647a2SToomas Soome char *description = NULL;
1536da6c28aaSamw char *propstr = NULL;
1537da6c28aaSamw size_t strsize;
1538da6c28aaSamw
1539da6c28aaSamw /* don't bother if no persistent resources */
1540da6c28aaSamw if (check_resource(share) == B_FALSE)
1541da6c28aaSamw return (ret);
1542da6c28aaSamw
1543da6c28aaSamw /*
1544da6c28aaSamw * properties must be set in transactions and don't take
1545da6c28aaSamw * effect until the transaction has been ended/committed.
1546da6c28aaSamw */
1547da6c28aaSamw entry = scf_entry_create(handle->handle);
1548da6c28aaSamw if (entry == NULL)
1549da6c28aaSamw return (SA_SYSTEM_ERR);
1550da6c28aaSamw
1551da6c28aaSamw if (scf_transaction_property_change(handle->trans, entry,
1552da6c28aaSamw "resource", SCF_TYPE_ASTRING) != 0 &&
1553da6c28aaSamw scf_transaction_property_new(handle->trans, entry,
1554da6c28aaSamw "resource", SCF_TYPE_ASTRING) != 0) {
1555da6c28aaSamw scf_entry_destroy(entry);
1556da6c28aaSamw return (SA_SYSTEM_ERR);
1557da6c28aaSamw
1558da6c28aaSamw }
1559da6c28aaSamw for (resource = sa_get_share_resource(share, NULL);
1560da6c28aaSamw resource != NULL;
1561da6c28aaSamw resource = sa_get_next_resource(resource)) {
1562da6c28aaSamw value = scf_value_create(handle->handle);
1563da6c28aaSamw if (value == NULL) {
1564da6c28aaSamw ret = SA_NO_MEMORY;
1565da6c28aaSamw break;
1566da6c28aaSamw }
1567da6c28aaSamw /* Get size of complete string */
1568da6c28aaSamw valstr = sa_get_resource_attr(resource, "name");
1569da6c28aaSamw idstr = sa_get_resource_attr(resource, "id");
1570da6c28aaSamw description = sa_get_resource_description(resource);
1571da6c28aaSamw strsize = (valstr != NULL) ? strlen(valstr) : 0;
1572da6c28aaSamw strsize += (idstr != NULL) ? strlen(idstr) : 0;
1573da6c28aaSamw strsize += (description != NULL) ? strlen(description) : 0;
1574da6c28aaSamw if (strsize > 0) {
1575da6c28aaSamw strsize += 3; /* add nul and ':' */
1576da6c28aaSamw propstr = (char *)malloc(strsize);
1577da6c28aaSamw if (propstr == NULL) {
1578da6c28aaSamw scf_value_destroy(value);
1579da6c28aaSamw ret = SA_NO_MEMORY;
1580da6c28aaSamw goto err;
1581da6c28aaSamw }
1582da6c28aaSamw if (idstr == NULL)
1583da6c28aaSamw (void) snprintf(propstr, strsize, "%s",
1584da6c28aaSamw valstr ? valstr : "");
1585da6c28aaSamw else
1586da6c28aaSamw (void) snprintf(propstr, strsize, "%s:%s:%s",
1587fe1c642dSBill Krier idstr, valstr ? valstr : "",
1588da6c28aaSamw description ? description : "");
1589da6c28aaSamw if (scf_value_set_astring(value, propstr) != 0) {
1590da6c28aaSamw ret = SA_SYSTEM_ERR;
1591da6c28aaSamw free(propstr);
1592da6c28aaSamw scf_value_destroy(value);
1593da6c28aaSamw break;
1594da6c28aaSamw }
1595da6c28aaSamw if (scf_entry_add_value(entry, value) != 0) {
1596da6c28aaSamw ret = SA_SYSTEM_ERR;
1597da6c28aaSamw free(propstr);
1598da6c28aaSamw scf_value_destroy(value);
1599da6c28aaSamw break;
1600da6c28aaSamw }
1601da6c28aaSamw /* the value is in the transaction */
1602da6c28aaSamw value = NULL;
1603da6c28aaSamw free(propstr);
1604da6c28aaSamw }
1605da6c28aaSamw err:
1606fe1c642dSBill Krier if (valstr != NULL) {
1607da6c28aaSamw sa_free_attr_string(valstr);
1608fe1c642dSBill Krier valstr = NULL;
1609fe1c642dSBill Krier }
1610fe1c642dSBill Krier if (idstr != NULL) {
1611da6c28aaSamw sa_free_attr_string(idstr);
1612fe1c642dSBill Krier idstr = NULL;
1613fe1c642dSBill Krier }
1614fe1c642dSBill Krier if (description != NULL) {
1615da6c28aaSamw sa_free_share_description(description);
1616fe1c642dSBill Krier description = NULL;
1617fe1c642dSBill Krier }
1618da6c28aaSamw }
1619da6c28aaSamw /* the entry is in the transaction */
1620da6c28aaSamw entry = NULL;
1621da6c28aaSamw
1622fe1c642dSBill Krier if (valstr != NULL)
1623fe1c642dSBill Krier sa_free_attr_string(valstr);
1624fe1c642dSBill Krier if (idstr != NULL)
1625fe1c642dSBill Krier sa_free_attr_string(idstr);
1626fe1c642dSBill Krier if (description != NULL)
1627fe1c642dSBill Krier sa_free_share_description(description);
1628fe1c642dSBill Krier
1629da6c28aaSamw if (ret == SA_SYSTEM_ERR) {
1630*2bc647a2SToomas Soome if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
1631da6c28aaSamw ret = SA_NO_PERMISSION;
1632da6c28aaSamw }
1633da6c28aaSamw }
1634da6c28aaSamw /*
1635da6c28aaSamw * cleanup if there were any errors that didn't leave
1636da6c28aaSamw * these values where they would be cleaned up later.
1637da6c28aaSamw */
1638da6c28aaSamw if (entry != NULL)
1639da6c28aaSamw scf_entry_destroy(entry);
1640da6c28aaSamw
1641da6c28aaSamw return (ret);
1642da6c28aaSamw }
1643da6c28aaSamw
16446185db85Sdougm /*
16456185db85Sdougm * sa_commit_share(handle, group, share)
16466185db85Sdougm *
164725a68471Sdougm * Commit this share to the repository.
16486185db85Sdougm * properties are added if they exist but can be added later.
16496185db85Sdougm * Need to add to dfstab and sharetab, if appropriate.
16506185db85Sdougm */
16516185db85Sdougm int
sa_commit_share(scfutilhandle_t * handle,sa_group_t group,sa_share_t share)16526185db85Sdougm sa_commit_share(scfutilhandle_t *handle, sa_group_t group, sa_share_t share)
16536185db85Sdougm {
16546185db85Sdougm int ret = SA_OK;
16556185db85Sdougm char *groupname;
16566185db85Sdougm char *name;
16576185db85Sdougm char *description;
16586185db85Sdougm char *sharename;
16596185db85Sdougm ssize_t proplen;
16606185db85Sdougm char *propstring;
16616185db85Sdougm
16626185db85Sdougm /*
166325a68471Sdougm * Don't commit in the zfs group. We do commit legacy
16646185db85Sdougm * (default) and all other groups/shares. ZFS is handled
16656185db85Sdougm * through the ZFS configuration rather than SMF.
16666185db85Sdougm */
16676185db85Sdougm
16686185db85Sdougm groupname = sa_get_group_attr(group, "name");
16696185db85Sdougm if (groupname != NULL) {
167025a68471Sdougm if (strcmp(groupname, "zfs") == 0) {
167125a68471Sdougm /*
167225a68471Sdougm * Adding to the ZFS group will result in the sharenfs
167325a68471Sdougm * property being set but we don't want to do anything
167425a68471Sdougm * SMF related at this point.
167525a68471Sdougm */
167625a68471Sdougm sa_free_attr_string(groupname);
167725a68471Sdougm return (ret);
167825a68471Sdougm }
16796185db85Sdougm }
16806185db85Sdougm
16816185db85Sdougm proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
16826185db85Sdougm propstring = malloc(proplen);
16836185db85Sdougm if (propstring == NULL)
168425a68471Sdougm ret = SA_NO_MEMORY;
16856185db85Sdougm
16866185db85Sdougm if (groupname != NULL && ret == SA_OK) {
168725a68471Sdougm ret = sa_get_instance(handle, groupname);
168825a68471Sdougm sa_free_attr_string(groupname);
168925a68471Sdougm groupname = NULL;
169025a68471Sdougm sharename = sa_get_share_attr(share, "id");
169125a68471Sdougm if (sharename == NULL) {
169225a68471Sdougm /* slipped by */
169325a68471Sdougm char shname[SA_SHARE_UUID_BUFLEN];
169425a68471Sdougm generate_unique_sharename(shname);
16957a9d7716Sthurlow (void) xmlSetProp((xmlNodePtr)share, (xmlChar *)"id",
16966185db85Sdougm (xmlChar *)shname);
169725a68471Sdougm sharename = strdup(shname);
169825a68471Sdougm }
169925a68471Sdougm if (sharename != NULL) {
170025a68471Sdougm sigset_t old, new;
17016185db85Sdougm /*
170225a68471Sdougm * Have a share name allocated so create a pgroup for
170325a68471Sdougm * it. It may already exist, but that is OK. In order
170425a68471Sdougm * to avoid creating a share pgroup that doesn't have
170525a68471Sdougm * a path property, block signals around the critical
170625a68471Sdougm * region of creating the share pgroup and props.
17076185db85Sdougm */
170825a68471Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new);
170925a68471Sdougm (void) sigaddset(&new, SIGHUP);
171025a68471Sdougm (void) sigaddset(&new, SIGINT);
171125a68471Sdougm (void) sigaddset(&new, SIGQUIT);
171225a68471Sdougm (void) sigaddset(&new, SIGTSTP);
171325a68471Sdougm (void) sigprocmask(SIG_SETMASK, &new, &old);
171425a68471Sdougm
171525a68471Sdougm ret = sa_create_pgroup(handle, sharename);
171625a68471Sdougm if (ret == SA_OK) {
171725a68471Sdougm /*
171825a68471Sdougm * Now start the transaction for the
171925a68471Sdougm * properties that define this share. They may
172025a68471Sdougm * exist so attempt to update before create.
172125a68471Sdougm */
172225a68471Sdougm ret = sa_start_transaction(handle, sharename);
172325a68471Sdougm }
172425a68471Sdougm if (ret == SA_OK) {
172525a68471Sdougm name = sa_get_share_attr(share, "path");
172625a68471Sdougm if (name != NULL) {
172725a68471Sdougm /*
172825a68471Sdougm * There needs to be a path
172925a68471Sdougm * for a share to exist.
173025a68471Sdougm */
173125a68471Sdougm ret = sa_set_property(handle, "path",
173225a68471Sdougm name);
173325a68471Sdougm sa_free_attr_string(name);
173425a68471Sdougm } else {
173525a68471Sdougm ret = SA_NO_MEMORY;
173625a68471Sdougm }
173725a68471Sdougm }
173825a68471Sdougm if (ret == SA_OK) {
1739da6c28aaSamw name = sa_get_share_attr(share, "drive-letter");
1740da6c28aaSamw if (name != NULL) {
1741da6c28aaSamw /* A drive letter may exist for SMB */
1742da6c28aaSamw ret = sa_set_property(handle,
1743da6c28aaSamw "drive-letter", name);
1744da6c28aaSamw sa_free_attr_string(name);
1745da6c28aaSamw }
1746da6c28aaSamw }
1747da6c28aaSamw if (ret == SA_OK) {
1748da6c28aaSamw name = sa_get_share_attr(share, "exclude");
1749da6c28aaSamw if (name != NULL) {
1750da6c28aaSamw /*
1751da6c28aaSamw * In special cases need to
1752da6c28aaSamw * exclude proto enable.
1753da6c28aaSamw */
175425a68471Sdougm ret = sa_set_property(handle,
1755da6c28aaSamw "exclude", name);
1756da6c28aaSamw sa_free_attr_string(name);
175725a68471Sdougm }
175825a68471Sdougm }
1759da6c28aaSamw if (ret == SA_OK) {
1760da6c28aaSamw /*
1761da6c28aaSamw * If there are resource names, bundle them up
1762da6c28aaSamw * and save appropriately.
1763da6c28aaSamw */
1764da6c28aaSamw ret = sa_set_resource_property(handle, share);
1765da6c28aaSamw }
1766da6c28aaSamw
176725a68471Sdougm if (ret == SA_OK) {
176825a68471Sdougm description = sa_get_share_description(share);
176925a68471Sdougm if (description != NULL) {
177025a68471Sdougm ret = sa_set_property(handle,
177125a68471Sdougm "description",
177225a68471Sdougm description);
177325a68471Sdougm sa_free_share_description(description);
177425a68471Sdougm }
177525a68471Sdougm }
177625a68471Sdougm /* Make sure we cleanup the transaction */
177725a68471Sdougm if (ret == SA_OK) {
17785b6e0c46Sdougm sa_handle_impl_t sahandle;
17795b6e0c46Sdougm sahandle = (sa_handle_impl_t)
17805b6e0c46Sdougm sa_find_group_handle(group);
17815b6e0c46Sdougm if (sahandle != NULL)
17825b6e0c46Sdougm ret = sa_end_transaction(handle,
17835b6e0c46Sdougm sahandle);
17845b6e0c46Sdougm else
17855b6e0c46Sdougm ret = SA_SYSTEM_ERR;
178625a68471Sdougm } else {
178725a68471Sdougm sa_abort_transaction(handle);
178825a68471Sdougm }
1789f345c0beSdougm
179025a68471Sdougm (void) sigprocmask(SIG_SETMASK, &old, NULL);
1791f345c0beSdougm
179225a68471Sdougm free(sharename);
179325a68471Sdougm }
17946185db85Sdougm }
17956185db85Sdougm if (ret == SA_SYSTEM_ERR) {
179625a68471Sdougm int err = scf_error();
179725a68471Sdougm if (err == SCF_ERROR_PERMISSION_DENIED)
179825a68471Sdougm ret = SA_NO_PERMISSION;
17996185db85Sdougm }
18006185db85Sdougm if (propstring != NULL)
180125a68471Sdougm free(propstring);
18026185db85Sdougm if (groupname != NULL)
180325a68471Sdougm sa_free_attr_string(groupname);
18046185db85Sdougm
18056185db85Sdougm return (ret);
18066185db85Sdougm }
18076185db85Sdougm
1808da6c28aaSamw /*
1809da6c28aaSamw * remove_resources(handle, share, shareid)
1810da6c28aaSamw *
1811da6c28aaSamw * If the share has resources, remove all of them and their
1812da6c28aaSamw * optionsets.
1813da6c28aaSamw */
1814da6c28aaSamw static int
remove_resources(scfutilhandle_t * handle,sa_share_t share,char * shareid)1815da6c28aaSamw remove_resources(scfutilhandle_t *handle, sa_share_t share, char *shareid)
1816da6c28aaSamw {
1817da6c28aaSamw sa_resource_t resource;
1818da6c28aaSamw sa_optionset_t opt;
1819da6c28aaSamw char *proto;
1820da6c28aaSamw char *id;
1821da6c28aaSamw ssize_t proplen;
1822da6c28aaSamw char *propstring;
1823da6c28aaSamw int ret = SA_OK;
1824da6c28aaSamw
1825da6c28aaSamw proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1826da6c28aaSamw propstring = malloc(proplen);
1827da6c28aaSamw if (propstring == NULL)
1828da6c28aaSamw return (SA_NO_MEMORY);
1829da6c28aaSamw
1830da6c28aaSamw for (resource = sa_get_share_resource(share, NULL);
1831da6c28aaSamw resource != NULL; resource = sa_get_next_resource(resource)) {
1832da6c28aaSamw id = sa_get_resource_attr(resource, "id");
1833da6c28aaSamw if (id == NULL)
1834da6c28aaSamw continue;
1835da6c28aaSamw for (opt = sa_get_optionset(resource, NULL);
1836da6c28aaSamw opt != NULL; opt = sa_get_next_optionset(resource)) {
1837da6c28aaSamw proto = sa_get_optionset_attr(opt, "type");
1838da6c28aaSamw if (proto != NULL) {
1839da6c28aaSamw (void) snprintf(propstring, proplen,
1840da6c28aaSamw "%s_%s_%s", shareid, proto, id);
1841da6c28aaSamw ret = sa_delete_pgroup(handle, propstring);
1842da6c28aaSamw sa_free_attr_string(proto);
1843da6c28aaSamw }
1844da6c28aaSamw }
1845da6c28aaSamw sa_free_attr_string(id);
1846da6c28aaSamw }
1847da6c28aaSamw free(propstring);
1848da6c28aaSamw return (ret);
1849da6c28aaSamw }
1850da6c28aaSamw
18516185db85Sdougm /*
18526185db85Sdougm * sa_delete_share(handle, group, share)
18536185db85Sdougm *
185425a68471Sdougm * Remove the specified share from the group (and service instance).
18556185db85Sdougm */
18566185db85Sdougm
18576185db85Sdougm int
sa_delete_share(scfutilhandle_t * handle,sa_group_t group,sa_share_t share)18586185db85Sdougm sa_delete_share(scfutilhandle_t *handle, sa_group_t group, sa_share_t share)
18596185db85Sdougm {
18606185db85Sdougm int ret = SA_OK;
18616185db85Sdougm char *groupname = NULL;
18626185db85Sdougm char *shareid = NULL;
18636185db85Sdougm sa_optionset_t opt;
18646185db85Sdougm sa_security_t sec;
18656185db85Sdougm ssize_t proplen;
18666185db85Sdougm char *propstring;
18676185db85Sdougm
18686185db85Sdougm proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
18696185db85Sdougm propstring = malloc(proplen);
18706185db85Sdougm if (propstring == NULL)
187125a68471Sdougm ret = SA_NO_MEMORY;
18726185db85Sdougm
18736185db85Sdougm if (ret == SA_OK) {
187425a68471Sdougm groupname = sa_get_group_attr(group, "name");
187525a68471Sdougm shareid = sa_get_share_attr(share, "id");
187625a68471Sdougm if (groupname == NULL || shareid == NULL) {
187725a68471Sdougm ret = SA_CONFIG_ERR;
187825a68471Sdougm goto out;
187925a68471Sdougm }
18806185db85Sdougm ret = sa_get_instance(handle, groupname);
18816185db85Sdougm if (ret == SA_OK) {
1882da6c28aaSamw /* If a share has resources, remove them */
1883da6c28aaSamw ret = remove_resources(handle, share, shareid);
188425a68471Sdougm /* If a share has properties, remove them */
188525a68471Sdougm ret = sa_delete_pgroup(handle, shareid);
188625a68471Sdougm for (opt = sa_get_optionset(share, NULL);
188725a68471Sdougm opt != NULL;
188825a68471Sdougm opt = sa_get_next_optionset(opt)) {
188925a68471Sdougm char *proto;
189025a68471Sdougm proto = sa_get_optionset_attr(opt, "type");
189125a68471Sdougm if (proto != NULL) {
189225a68471Sdougm (void) snprintf(propstring,
189325a68471Sdougm proplen, "%s_%s", shareid,
189425a68471Sdougm proto);
189525a68471Sdougm ret = sa_delete_pgroup(handle,
189625a68471Sdougm propstring);
189725a68471Sdougm sa_free_attr_string(proto);
189825a68471Sdougm } else {
189925a68471Sdougm ret = SA_NO_MEMORY;
190025a68471Sdougm }
19016185db85Sdougm }
19026185db85Sdougm /*
190325a68471Sdougm * If a share has security/negotiable
19046185db85Sdougm * properties, remove them.
19056185db85Sdougm */
190625a68471Sdougm for (sec = sa_get_security(share, NULL, NULL);
190725a68471Sdougm sec != NULL;
190825a68471Sdougm sec = sa_get_next_security(sec)) {
190925a68471Sdougm char *proto;
191025a68471Sdougm char *sectype;
191125a68471Sdougm proto = sa_get_security_attr(sec, "type");
191225a68471Sdougm sectype = sa_get_security_attr(sec, "sectype");
191325a68471Sdougm if (proto != NULL && sectype != NULL) {
191425a68471Sdougm (void) snprintf(propstring, proplen,
191525a68471Sdougm "%s_%s_%s", shareid, proto,
191625a68471Sdougm sectype);
191725a68471Sdougm ret = sa_delete_pgroup(handle,
191825a68471Sdougm propstring);
191925a68471Sdougm } else {
192025a68471Sdougm ret = SA_NO_MEMORY;
192125a68471Sdougm }
192225a68471Sdougm if (proto != NULL)
192325a68471Sdougm sa_free_attr_string(proto);
192425a68471Sdougm if (sectype != NULL)
192525a68471Sdougm sa_free_attr_string(sectype);
19266185db85Sdougm }
19276185db85Sdougm }
19286185db85Sdougm }
192925a68471Sdougm out:
19306185db85Sdougm if (groupname != NULL)
193125a68471Sdougm sa_free_attr_string(groupname);
19326185db85Sdougm if (shareid != NULL)
193325a68471Sdougm sa_free_attr_string(shareid);
19346185db85Sdougm if (propstring != NULL)
193525a68471Sdougm free(propstring);
19366185db85Sdougm
19376185db85Sdougm return (ret);
19386185db85Sdougm }
1939