xref: /onnv-gate/usr/src/lib/libstmf/common/store.c (revision 9585:bf09620212ab)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*9585STim.Szeto@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <libscf.h>
277836SJohn.Forte@Sun.COM #include <stdio.h>
287836SJohn.Forte@Sun.COM #include <stdlib.h>
297836SJohn.Forte@Sun.COM #include <errno.h>
307836SJohn.Forte@Sun.COM #include <assert.h>
317836SJohn.Forte@Sun.COM #include <strings.h>
327836SJohn.Forte@Sun.COM #include <libstmf.h>
337836SJohn.Forte@Sun.COM #include <store.h>
347836SJohn.Forte@Sun.COM #include <syslog.h>
357836SJohn.Forte@Sun.COM #include <signal.h>
367836SJohn.Forte@Sun.COM #include <pthread.h>
377836SJohn.Forte@Sun.COM #include <libnvpair.h>
387836SJohn.Forte@Sun.COM #include <limits.h>
397836SJohn.Forte@Sun.COM #include <unistd.h>
407836SJohn.Forte@Sun.COM 
417836SJohn.Forte@Sun.COM /*
427836SJohn.Forte@Sun.COM  * This file's functions are responsible for all store and retrieve operations
437836SJohn.Forte@Sun.COM  * against the STMF smf(5) database. The following shows the currently defined
447836SJohn.Forte@Sun.COM  * schema for the STMF database:
457836SJohn.Forte@Sun.COM  *
467836SJohn.Forte@Sun.COM  * Description of property groups for service: svc:/system/stmf
477836SJohn.Forte@Sun.COM  *
487836SJohn.Forte@Sun.COM  * Stability: Volatile
497836SJohn.Forte@Sun.COM  *
507836SJohn.Forte@Sun.COM  * 1. Property Group: host_groups
517836SJohn.Forte@Sun.COM  *        Properties: group_name-<N> where <N> is an unsigned integer
527836SJohn.Forte@Sun.COM  *                        type: ustring
537836SJohn.Forte@Sun.COM  *                        contains: group name
547836SJohn.Forte@Sun.COM  *                    group_name-<N>-member_list where <N> is an unsigned
557836SJohn.Forte@Sun.COM  *                            integer matching a group_name-<N> property.
567836SJohn.Forte@Sun.COM  *                        type: ustring
577836SJohn.Forte@Sun.COM  *                        contains: list of members
587836SJohn.Forte@Sun.COM  *
597836SJohn.Forte@Sun.COM  *        Description:
607836SJohn.Forte@Sun.COM  *             Contains the host group names as well as the host group members
617836SJohn.Forte@Sun.COM  *             for each host group.
627836SJohn.Forte@Sun.COM  *
637836SJohn.Forte@Sun.COM  * 2. Property Group: target_groups
647836SJohn.Forte@Sun.COM  *        Properties: group_name-<N> where <N> is an unsigned integer
657836SJohn.Forte@Sun.COM  *                        type: ustring
667836SJohn.Forte@Sun.COM  *                        contains: group name
677836SJohn.Forte@Sun.COM  *                    group_name-<N>-member_list where <N> is an unsigned
687836SJohn.Forte@Sun.COM  *                            integer matching a group_name-<N> property.
697836SJohn.Forte@Sun.COM  *                        type: ustring
707836SJohn.Forte@Sun.COM  *                        contains: list of members
717836SJohn.Forte@Sun.COM  *
727836SJohn.Forte@Sun.COM  *        Description:
737836SJohn.Forte@Sun.COM  *             Contains the target group names as well as the target group
747836SJohn.Forte@Sun.COM  *             members for each target group.
757836SJohn.Forte@Sun.COM  *
767836SJohn.Forte@Sun.COM  * 3. Property Group: lu-<GUID>
777836SJohn.Forte@Sun.COM  *                        where <GUID> is a 32 character hexadecimal string.
787836SJohn.Forte@Sun.COM  *        Properties: ve_cnt
797836SJohn.Forte@Sun.COM  *                        type: count
807836SJohn.Forte@Sun.COM  *                        contains: the number of current view entries
817836SJohn.Forte@Sun.COM  *                    view-entry-<N>-<GUID> where <N> is an unsigned integer
827836SJohn.Forte@Sun.COM  *                        type: ustring
837836SJohn.Forte@Sun.COM  *                        contains: nothing. Used as reference to the view
847836SJohn.Forte@Sun.COM  *                                  entry property group
857836SJohn.Forte@Sun.COM  *
867836SJohn.Forte@Sun.COM  *        Description:
877836SJohn.Forte@Sun.COM  *             Contains the references to each view entry. One lu-<GUID>
887836SJohn.Forte@Sun.COM  *             property group will exist for each logical unit with 1 or more
897836SJohn.Forte@Sun.COM  *             view entries.
907836SJohn.Forte@Sun.COM  *             Potentially can hold any other data that can be managed on a per
917836SJohn.Forte@Sun.COM  *             logical unit basis.
927836SJohn.Forte@Sun.COM  *
937836SJohn.Forte@Sun.COM  * 4. Property Group: view_entry-<N>-<GUID> (matches property in lu-<GUID>
947836SJohn.Forte@Sun.COM  *                    property group)
957836SJohn.Forte@Sun.COM  *        Properties: all_hosts
967836SJohn.Forte@Sun.COM  *                        type: boolean
977836SJohn.Forte@Sun.COM  *                        contains: when true, the value of host_group is
987836SJohn.Forte@Sun.COM  *                                  ignored
997836SJohn.Forte@Sun.COM  *                    all_targets
1007836SJohn.Forte@Sun.COM  *                        type: boolean
1017836SJohn.Forte@Sun.COM  *                        contains: when true, the value of target_group is
1027836SJohn.Forte@Sun.COM  *                                  ignored
1037836SJohn.Forte@Sun.COM  *                    host_group
1047836SJohn.Forte@Sun.COM  *                        type: ustring
1057836SJohn.Forte@Sun.COM  *                        contains: host group for logical unit mapping and
1067836SJohn.Forte@Sun.COM  *                                  masking purposes
1077836SJohn.Forte@Sun.COM  *                    target_group
1087836SJohn.Forte@Sun.COM  *                        type: ustring
1097836SJohn.Forte@Sun.COM  *                        contains: target group for logical unit mapping and
1107836SJohn.Forte@Sun.COM  *                                  masking purposes
1117836SJohn.Forte@Sun.COM  *                    lu_nbr
1127836SJohn.Forte@Sun.COM  *                        type: opaque
1137836SJohn.Forte@Sun.COM  *                        contains: the 8-byte SCSI logical unit number for
1147836SJohn.Forte@Sun.COM  *                                  mapping and masking purposes
1157836SJohn.Forte@Sun.COM  *        Description:
1167836SJohn.Forte@Sun.COM  *             One "view_entry-<N>-<GUID>" property group will exist for each
1177836SJohn.Forte@Sun.COM  *             view entry in the system. This property group name maps
1187836SJohn.Forte@Sun.COM  *             directly to the "lu-<GUID>" property group with a matching
1197836SJohn.Forte@Sun.COM  *             <GUID>.
1207836SJohn.Forte@Sun.COM  *
1217836SJohn.Forte@Sun.COM  * 5. Property Group: provider_data_pg_<provider-name>
1227836SJohn.Forte@Sun.COM  *                        where <provider-name> is the name of the provider
1237836SJohn.Forte@Sun.COM  *                           registered with stmf.
1247836SJohn.Forte@Sun.COM  *        Properties: provider_data_prop-<N>
1257836SJohn.Forte@Sun.COM  *                        where <N> is a sequential identifier for the data
1267836SJohn.Forte@Sun.COM  *                           chunk.
1277836SJohn.Forte@Sun.COM  *                        type: opaque
1287836SJohn.Forte@Sun.COM  *                        contains: up to STMF_PROVIDER_DATA_PROP_SIZE bytes
1297836SJohn.Forte@Sun.COM  *                                  of nvlist packed data.
1307836SJohn.Forte@Sun.COM  *                    provider_data_count
1317836SJohn.Forte@Sun.COM  *                        type: count
1327836SJohn.Forte@Sun.COM  *                        contains: the number of provider data chunks
1337836SJohn.Forte@Sun.COM  *                    provider_data_type
1347836SJohn.Forte@Sun.COM  *                        type: integer
1357836SJohn.Forte@Sun.COM  *                        contains: STMF_PORT_PROVIDER_TYPE or
1367836SJohn.Forte@Sun.COM  *                                  STMF_LU_PROVIDER_TYPE
1377836SJohn.Forte@Sun.COM  *
1387836SJohn.Forte@Sun.COM  *        Description:
1397836SJohn.Forte@Sun.COM  *             Holds the nvlist packed provider data set via
1407836SJohn.Forte@Sun.COM  *             stmfSetProviderData and retrieved via stmfGetProviderData. Data
1417836SJohn.Forte@Sun.COM  *             is stored in STMF_PROVIDER_DATA_PROP_SIZE chunks. On retrieve,
1427836SJohn.Forte@Sun.COM  *             these chunks are reassembled and unpacked.
1437836SJohn.Forte@Sun.COM  *
1447836SJohn.Forte@Sun.COM  */
1457836SJohn.Forte@Sun.COM 
1467836SJohn.Forte@Sun.COM static int iPsInit(scf_handle_t **, scf_service_t **);
1477836SJohn.Forte@Sun.COM static int iPsCreateDeleteGroup(char *, char *, int);
1487836SJohn.Forte@Sun.COM static int iPsAddRemoveGroupMember(char *, char *, char *, int);
1497836SJohn.Forte@Sun.COM static int iPsGetGroupList(char *, stmfGroupList **);
1507836SJohn.Forte@Sun.COM static int iPsGetGroupMemberList(char *, char *, stmfGroupProperties **);
1517836SJohn.Forte@Sun.COM static int iPsAddViewEntry(char *, char *, stmfViewEntry *);
1527836SJohn.Forte@Sun.COM static int iPsAddRemoveLuViewEntry(char *, char *, int);
1537836SJohn.Forte@Sun.COM static int iPsGetViewEntry(char *, stmfViewEntry *);
1547836SJohn.Forte@Sun.COM static int iPsGetActualGroupName(char *, char *, char *);
1557836SJohn.Forte@Sun.COM static int iPsGetServiceVersion(uint64_t *, scf_handle_t *, scf_service_t *);
156*9585STim.Szeto@Sun.COM static int iPsGetSetPersistType(uint8_t *, scf_handle_t *, scf_service_t *,
157*9585STim.Szeto@Sun.COM     int);
1587836SJohn.Forte@Sun.COM static int viewEntryCompare(const void *, const void *);
1597836SJohn.Forte@Sun.COM static int holdSignal(sigset_t *);
1607836SJohn.Forte@Sun.COM static int releaseSignal(sigset_t *);
1617836SJohn.Forte@Sun.COM static void sigHandler();
1627836SJohn.Forte@Sun.COM 
1637836SJohn.Forte@Sun.COM static pthread_mutex_t sigSetLock = PTHREAD_MUTEX_INITIALIZER;
1647836SJohn.Forte@Sun.COM 
1657836SJohn.Forte@Sun.COM sigset_t sigSet;
1667836SJohn.Forte@Sun.COM sigset_t signalsCaught;
1677836SJohn.Forte@Sun.COM 
1687836SJohn.Forte@Sun.COM struct sigaction currentActionQuit;
1697836SJohn.Forte@Sun.COM struct sigaction currentActionTerm;
1707836SJohn.Forte@Sun.COM struct sigaction currentActionInt;
1717836SJohn.Forte@Sun.COM 
1727836SJohn.Forte@Sun.COM boolean_t actionSet = B_FALSE;
1737836SJohn.Forte@Sun.COM 
1747836SJohn.Forte@Sun.COM /*
1757836SJohn.Forte@Sun.COM  * Version info for the SMF schema
1767836SJohn.Forte@Sun.COM  */
1777836SJohn.Forte@Sun.COM #define	STMF_SMF_VERSION    1
1787836SJohn.Forte@Sun.COM 
1797836SJohn.Forte@Sun.COM /*
180*9585STim.Szeto@Sun.COM  * Note: Do not change these property names and size values.
181*9585STim.Szeto@Sun.COM  * They represent fields in the persistent config and once modified
182*9585STim.Szeto@Sun.COM  * will have a nasty side effect of invalidating the existing store.
183*9585STim.Szeto@Sun.COM  * If you do need to change them, you'll need to use the versioning above
184*9585STim.Szeto@Sun.COM  * to retain backward compatiblity with the previous configuration schema.
185*9585STim.Szeto@Sun.COM  */
186*9585STim.Szeto@Sun.COM 
187*9585STim.Szeto@Sun.COM /* BEGIN STORE PROPERTY DEFINITIONS */
188*9585STim.Szeto@Sun.COM /*
1897836SJohn.Forte@Sun.COM  * Property Group Names and prefixes
1907836SJohn.Forte@Sun.COM  */
1917836SJohn.Forte@Sun.COM #define	STMF_HOST_GROUPS	"host_groups"
1927836SJohn.Forte@Sun.COM #define	STMF_TARGET_GROUPS	"target_groups"
1937836SJohn.Forte@Sun.COM #define	STMF_VE_PREFIX		"view_entry"
1947836SJohn.Forte@Sun.COM #define	STMF_LU_PREFIX		"lu"
1957836SJohn.Forte@Sun.COM #define	STMF_DATA_GROUP		"stmf_data"
1967836SJohn.Forte@Sun.COM 
1977836SJohn.Forte@Sun.COM /*
1987836SJohn.Forte@Sun.COM  * Property names and prefix for logical unit property group
1997836SJohn.Forte@Sun.COM  */
2007836SJohn.Forte@Sun.COM #define	STMF_VE_CNT		"ve_cnt"
2017836SJohn.Forte@Sun.COM #define	STMF_GROUP_PREFIX	"group_name"
2027836SJohn.Forte@Sun.COM #define	STMF_MEMBER_LIST_SUFFIX	"member_list"
2037836SJohn.Forte@Sun.COM #define	STMF_VERSION_NAME	"version_name"
204*9585STim.Szeto@Sun.COM #define	STMF_PERSIST_TYPE	"persist_method"
2057836SJohn.Forte@Sun.COM 
2067836SJohn.Forte@Sun.COM /*
2077836SJohn.Forte@Sun.COM  * Property names for view entry
2087836SJohn.Forte@Sun.COM  */
2097836SJohn.Forte@Sun.COM #define	STMF_VE_ALLHOSTS	    "all_hosts"
2107836SJohn.Forte@Sun.COM #define	STMF_VE_HOSTGROUP	    "host_group"
2117836SJohn.Forte@Sun.COM #define	STMF_VE_ALLTARGETS	    "all_targets"
2127836SJohn.Forte@Sun.COM #define	STMF_VE_TARGETGROUP	    "target_group"
2137836SJohn.Forte@Sun.COM #define	STMF_VE_LUNBR		    "lu_nbr"
2147836SJohn.Forte@Sun.COM 
2157836SJohn.Forte@Sun.COM /* Property group suffix for provider data */
2167836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PREFIX "provider_data_pg_"
2177836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_PREFIX "provider_data_prop"
2187836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_NAME_SIZE 256
2197836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_TYPE "provider_type"
2207836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_SET_COUNT "provider_data_set_cnt"
2217836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_COUNT "provider_data_cnt"
222*9585STim.Szeto@Sun.COM 
2237836SJohn.Forte@Sun.COM 
2247836SJohn.Forte@Sun.COM #define	STMF_SMF_READ_ATTR	"solaris.smf.read.stmf"
2257836SJohn.Forte@Sun.COM 
226*9585STim.Szeto@Sun.COM #define	STMF_PS_PERSIST_NONE	"none"
227*9585STim.Szeto@Sun.COM #define	STMF_PS_PERSIST_SMF	"smf"
228*9585STim.Szeto@Sun.COM #define	STMF_PROVIDER_DATA_PROP_SIZE 4000
229*9585STim.Szeto@Sun.COM /* END STORE PROPERTY DEFINITIONS */
2307836SJohn.Forte@Sun.COM 
2317836SJohn.Forte@Sun.COM /* service name */
2327836SJohn.Forte@Sun.COM #define	STMF_SERVICE	"system/stmf"
2337836SJohn.Forte@Sun.COM 
2347836SJohn.Forte@Sun.COM /* limits and flag values */
2357836SJohn.Forte@Sun.COM #define	GROUP_MEMBER_ALLOC 100
2367836SJohn.Forte@Sun.COM #define	VIEW_ENTRY_STRUCT_CNT 6
2377836SJohn.Forte@Sun.COM #define	VIEW_ENTRY_PG_SIZE 256
2387836SJohn.Forte@Sun.COM #define	LOGICAL_UNIT_PG_SIZE 256
2397836SJohn.Forte@Sun.COM #define	VIEW_ENTRY_MAX UINT32_MAX
2407836SJohn.Forte@Sun.COM #define	GROUP_MAX UINT64_MAX
2417836SJohn.Forte@Sun.COM #define	ADD 0
2427836SJohn.Forte@Sun.COM #define	REMOVE 1
243*9585STim.Szeto@Sun.COM #define	GET 0
244*9585STim.Szeto@Sun.COM #define	SET 1
2457836SJohn.Forte@Sun.COM 
2467836SJohn.Forte@Sun.COM /*
2477836SJohn.Forte@Sun.COM  * sigHandler
2487836SJohn.Forte@Sun.COM  *
2497836SJohn.Forte@Sun.COM  * Catch the signal and set the global signalsCaught to the signal received
2507836SJohn.Forte@Sun.COM  *
2517836SJohn.Forte@Sun.COM  * signalsCaught will be used by releaseSignal to raise this signal when
2527836SJohn.Forte@Sun.COM  * we're done processing our critical code.
2537836SJohn.Forte@Sun.COM  *
2547836SJohn.Forte@Sun.COM  */
2557836SJohn.Forte@Sun.COM static void
2567836SJohn.Forte@Sun.COM sigHandler(int sig)
2577836SJohn.Forte@Sun.COM {
2587836SJohn.Forte@Sun.COM 	(void) sigaddset(&signalsCaught, sig);
2597836SJohn.Forte@Sun.COM }
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM /*
2627836SJohn.Forte@Sun.COM  * iPsAddRemoveGroupMember
2637836SJohn.Forte@Sun.COM  *
2647836SJohn.Forte@Sun.COM  * Add or remove a member for a given group
2657836SJohn.Forte@Sun.COM  *
2667836SJohn.Forte@Sun.COM  * pgName - Property group name
2677836SJohn.Forte@Sun.COM  * groupName - group name to which the member is added/removed
2687836SJohn.Forte@Sun.COM  * memberName - member to be added/removed
2697836SJohn.Forte@Sun.COM  * addRemoveFlag - ADD/REMOVE
2707836SJohn.Forte@Sun.COM  *
2717836SJohn.Forte@Sun.COM  * returns:
2727836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2737836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2747836SJohn.Forte@Sun.COM  */
2757836SJohn.Forte@Sun.COM static int
2767836SJohn.Forte@Sun.COM iPsAddRemoveGroupMember(char *pgName, char *groupName, char *memberName,
2777836SJohn.Forte@Sun.COM int addRemoveFlag)
2787836SJohn.Forte@Sun.COM {
2797836SJohn.Forte@Sun.COM 	scf_handle_t *handle = NULL;
2807836SJohn.Forte@Sun.COM 	scf_service_t *svc = NULL;
2817836SJohn.Forte@Sun.COM 	scf_propertygroup_t *pg = NULL;
2827836SJohn.Forte@Sun.COM 	scf_property_t *prop = NULL;
2837836SJohn.Forte@Sun.COM 	scf_value_t *valueLookup = NULL;
2847836SJohn.Forte@Sun.COM 	scf_value_t **valueSet = NULL;
2857836SJohn.Forte@Sun.COM 	scf_iter_t *valueIter = NULL;
2867836SJohn.Forte@Sun.COM 	scf_transaction_t *tran = NULL;
2877836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry = NULL;
2887836SJohn.Forte@Sun.COM 	int i = 0;
2897836SJohn.Forte@Sun.COM 	int lastAlloc;
2907836SJohn.Forte@Sun.COM 	int valueArraySize = 0;
2917836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
2927836SJohn.Forte@Sun.COM 	char buf[STMF_IDENT_LENGTH];
2937836SJohn.Forte@Sun.COM 	int commitRet;
2947836SJohn.Forte@Sun.COM 	boolean_t found = B_FALSE;
2957836SJohn.Forte@Sun.COM 
2967836SJohn.Forte@Sun.COM 	assert(pgName != NULL && groupName != NULL && memberName != NULL);
2977836SJohn.Forte@Sun.COM 
2987836SJohn.Forte@Sun.COM 	/*
2997836SJohn.Forte@Sun.COM 	 * Init the service handle
3007836SJohn.Forte@Sun.COM 	 */
3017836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
3027836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3037836SJohn.Forte@Sun.COM 		goto out;
3047836SJohn.Forte@Sun.COM 	}
3057836SJohn.Forte@Sun.COM 
3067836SJohn.Forte@Sun.COM 	/*
3077836SJohn.Forte@Sun.COM 	 * Allocate scf resources
3087836SJohn.Forte@Sun.COM 	 */
3097836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
3107836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
3117836SJohn.Forte@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
3127836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
3137836SJohn.Forte@Sun.COM 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
3147836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
3157836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3167836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3177836SJohn.Forte@Sun.COM 		goto out;
3187836SJohn.Forte@Sun.COM 	}
3197836SJohn.Forte@Sun.COM 
3207836SJohn.Forte@Sun.COM 	/*
3217836SJohn.Forte@Sun.COM 	 * Get the service property group handle
3227836SJohn.Forte@Sun.COM 	 */
3237836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
3247836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
3257836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
3267836SJohn.Forte@Sun.COM 		} else {
3277836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
3287836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3297836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3307836SJohn.Forte@Sun.COM 		}
3317836SJohn.Forte@Sun.COM 		goto out;
3327836SJohn.Forte@Sun.COM 	}
3337836SJohn.Forte@Sun.COM 
3347836SJohn.Forte@Sun.COM 	/*
3357836SJohn.Forte@Sun.COM 	 * Begin the transaction
3367836SJohn.Forte@Sun.COM 	 */
3377836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
3387836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
3397836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3407836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3417836SJohn.Forte@Sun.COM 		goto out;
3427836SJohn.Forte@Sun.COM 	}
3437836SJohn.Forte@Sun.COM 
3447836SJohn.Forte@Sun.COM 	/*
3457836SJohn.Forte@Sun.COM 	 * We're changing an existing property by adding a propval
3467836SJohn.Forte@Sun.COM 	 * There are no add semantics in libscf for a property value. We'll
3477836SJohn.Forte@Sun.COM 	 * need to read in the current properties and apply them all to the
3487836SJohn.Forte@Sun.COM 	 * set and then add the one we were asked to add or omit the one
3497836SJohn.Forte@Sun.COM 	 * we were asked to remove.
3507836SJohn.Forte@Sun.COM 	 */
3517836SJohn.Forte@Sun.COM 	if (scf_transaction_property_change(tran, entry, groupName,
3527836SJohn.Forte@Sun.COM 	    SCF_TYPE_USTRING) == -1) {
3537836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
3547836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
3557836SJohn.Forte@Sun.COM 		} else {
3567836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3577836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "tran property change failed - %s",
3587836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3597836SJohn.Forte@Sun.COM 		}
3607836SJohn.Forte@Sun.COM 		goto out;
3617836SJohn.Forte@Sun.COM 	}
3627836SJohn.Forte@Sun.COM 
3637836SJohn.Forte@Sun.COM 	/*
3647836SJohn.Forte@Sun.COM 	 * Get the property handle
3657836SJohn.Forte@Sun.COM 	 */
3667836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, groupName, prop) == -1) {
3677836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3687836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3697836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3707836SJohn.Forte@Sun.COM 		goto out;
3717836SJohn.Forte@Sun.COM 	}
3727836SJohn.Forte@Sun.COM 
3737836SJohn.Forte@Sun.COM 	/*
3747836SJohn.Forte@Sun.COM 	 * Value lookup is used to lookup the existing values
3757836SJohn.Forte@Sun.COM 	 */
3767836SJohn.Forte@Sun.COM 	valueLookup = scf_value_create(handle);
3777836SJohn.Forte@Sun.COM 	if (valueLookup == NULL) {
3787836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf value alloc failed - %s",
3797836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3807836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3817836SJohn.Forte@Sun.COM 		goto out;
3827836SJohn.Forte@Sun.COM 	}
3837836SJohn.Forte@Sun.COM 
3847836SJohn.Forte@Sun.COM 	/*
3857836SJohn.Forte@Sun.COM 	 * valueIter is the iterator handle, create the resource
3867836SJohn.Forte@Sun.COM 	 */
3877836SJohn.Forte@Sun.COM 	if (scf_iter_property_values(valueIter, prop) == -1) {
3887836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter value failed - %s",
3897836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3907836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3917836SJohn.Forte@Sun.COM 		goto out;
3927836SJohn.Forte@Sun.COM 	}
3937836SJohn.Forte@Sun.COM 
3947836SJohn.Forte@Sun.COM 	/*
3957836SJohn.Forte@Sun.COM 	 * Allocate value resource pointers.
3967836SJohn.Forte@Sun.COM 	 * We need a value resource for each value as value pointers passed
3977836SJohn.Forte@Sun.COM 	 * to libscf cannot be destroyed until the commit or destroy on the
3987836SJohn.Forte@Sun.COM 	 * transaction is done.
3997836SJohn.Forte@Sun.COM 	 *
4007836SJohn.Forte@Sun.COM 	 * We're using GROUP_MEMBER_ALLOC initially. If it's not large
4017836SJohn.Forte@Sun.COM 	 * enough, we'll realloc on the fly
4027836SJohn.Forte@Sun.COM 	 */
4037836SJohn.Forte@Sun.COM 	valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
4047836SJohn.Forte@Sun.COM 	    * (lastAlloc = GROUP_MEMBER_ALLOC));
4057836SJohn.Forte@Sun.COM 	if (valueSet == NULL) {
4067836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
4077836SJohn.Forte@Sun.COM 		goto out;
4087836SJohn.Forte@Sun.COM 	}
4097836SJohn.Forte@Sun.COM 
4107836SJohn.Forte@Sun.COM 	/*
4117836SJohn.Forte@Sun.COM 	 * Iterate through the existing values
4127836SJohn.Forte@Sun.COM 	 */
4137836SJohn.Forte@Sun.COM 	while (scf_iter_next_value(valueIter, valueLookup) == 1) {
4147836SJohn.Forte@Sun.COM 		bzero(buf, sizeof (buf));
4157836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
4167836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
4177836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4187836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4197836SJohn.Forte@Sun.COM 			break;
4207836SJohn.Forte@Sun.COM 		}
4217836SJohn.Forte@Sun.COM 
4227836SJohn.Forte@Sun.COM 		/*
4237836SJohn.Forte@Sun.COM 		 * Check for existing
4247836SJohn.Forte@Sun.COM 		 * If we're adding, it's an error
4257836SJohn.Forte@Sun.COM 		 * If we're removing, we skip it and simply not
4267836SJohn.Forte@Sun.COM 		 * add it to the set. Subtraction by omission.
4277836SJohn.Forte@Sun.COM 		 */
4287836SJohn.Forte@Sun.COM 		if ((strlen(buf) == strlen(memberName)) &&
4297836SJohn.Forte@Sun.COM 		    bcmp(buf, memberName, strlen(buf)) == 0) {
4307836SJohn.Forte@Sun.COM 			if (addRemoveFlag == ADD) {
4317836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
4327836SJohn.Forte@Sun.COM 				break;
4337836SJohn.Forte@Sun.COM 			} else {
4347836SJohn.Forte@Sun.COM 				found = B_TRUE;
4357836SJohn.Forte@Sun.COM 				continue;
4367836SJohn.Forte@Sun.COM 			}
4377836SJohn.Forte@Sun.COM 		}
4387836SJohn.Forte@Sun.COM 
4397836SJohn.Forte@Sun.COM 		/*
4407836SJohn.Forte@Sun.COM 		 * Create the value resource for this iteration
4417836SJohn.Forte@Sun.COM 		 */
4427836SJohn.Forte@Sun.COM 		valueSet[i] = scf_value_create(handle);
4437836SJohn.Forte@Sun.COM 		if (valueSet[i] == NULL) {
4447836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
4457836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4467836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4477836SJohn.Forte@Sun.COM 			break;
4487836SJohn.Forte@Sun.COM 		}
4497836SJohn.Forte@Sun.COM 
4507836SJohn.Forte@Sun.COM 		/*
4517836SJohn.Forte@Sun.COM 		 * Set the value
4527836SJohn.Forte@Sun.COM 		 */
4537836SJohn.Forte@Sun.COM 		if (scf_value_set_ustring(valueSet[i], buf) == -1) {
4547836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
4557836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4567836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4577836SJohn.Forte@Sun.COM 			break;
4587836SJohn.Forte@Sun.COM 		}
4597836SJohn.Forte@Sun.COM 
4607836SJohn.Forte@Sun.COM 		/*
4617836SJohn.Forte@Sun.COM 		 * Now add the value
4627836SJohn.Forte@Sun.COM 		 */
4637836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
4647836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
4657836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4667836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4677836SJohn.Forte@Sun.COM 			break;
4687836SJohn.Forte@Sun.COM 		}
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM 		i++;
4717836SJohn.Forte@Sun.COM 
4727836SJohn.Forte@Sun.COM 		/*
4737836SJohn.Forte@Sun.COM 		 * realloc if we've hit the previous alloc size
4747836SJohn.Forte@Sun.COM 		 */
4757836SJohn.Forte@Sun.COM 		if (i >= lastAlloc) {
4767836SJohn.Forte@Sun.COM 			lastAlloc += GROUP_MEMBER_ALLOC;
4777836SJohn.Forte@Sun.COM 			valueSet = realloc(valueSet,
4787836SJohn.Forte@Sun.COM 			    sizeof (*valueSet) * lastAlloc);
4797836SJohn.Forte@Sun.COM 			if (valueSet == NULL) {
4807836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
4817836SJohn.Forte@Sun.COM 				break;
4827836SJohn.Forte@Sun.COM 			}
4837836SJohn.Forte@Sun.COM 		}
4847836SJohn.Forte@Sun.COM 	}
4857836SJohn.Forte@Sun.COM 
4867836SJohn.Forte@Sun.COM 	/*
4877836SJohn.Forte@Sun.COM 	 * set valueArraySize to final allocated length
4887836SJohn.Forte@Sun.COM 	 * so we can use it to destroy the resources correctly
4897836SJohn.Forte@Sun.COM 	 */
4907836SJohn.Forte@Sun.COM 	valueArraySize = i;
4917836SJohn.Forte@Sun.COM 
4927836SJohn.Forte@Sun.COM 	if (!found && (addRemoveFlag == REMOVE)) {
4937836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_MEMBER_NOT_FOUND;
4947836SJohn.Forte@Sun.COM 	}
4957836SJohn.Forte@Sun.COM 
4967836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
4977836SJohn.Forte@Sun.COM 		goto out;
4987836SJohn.Forte@Sun.COM 	}
4997836SJohn.Forte@Sun.COM 
5007836SJohn.Forte@Sun.COM 	/*
5017836SJohn.Forte@Sun.COM 	 * If we're adding, we have one more step. Add the member to the
5027836SJohn.Forte@Sun.COM 	 * propval list
5037836SJohn.Forte@Sun.COM 	 */
5047836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
5057836SJohn.Forte@Sun.COM 		/*
5067836SJohn.Forte@Sun.COM 		 * Now create the new entry
5077836SJohn.Forte@Sun.COM 		 */
5087836SJohn.Forte@Sun.COM 		valueSet[i] = scf_value_create(handle);
5097836SJohn.Forte@Sun.COM 		if (valueSet[i] == NULL) {
5107836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
5117836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
5127836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
5137836SJohn.Forte@Sun.COM 			goto out;
5147836SJohn.Forte@Sun.COM 		} else {
5157836SJohn.Forte@Sun.COM 			valueArraySize++;
5167836SJohn.Forte@Sun.COM 		}
5177836SJohn.Forte@Sun.COM 
5187836SJohn.Forte@Sun.COM 		/*
5197836SJohn.Forte@Sun.COM 		 * Set the new member name
5207836SJohn.Forte@Sun.COM 		 */
5217836SJohn.Forte@Sun.COM 		if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
5227836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
5237836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
5247836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
5257836SJohn.Forte@Sun.COM 			goto out;
5267836SJohn.Forte@Sun.COM 		}
5277836SJohn.Forte@Sun.COM 
5287836SJohn.Forte@Sun.COM 		/*
5297836SJohn.Forte@Sun.COM 		 * Add the new member
5307836SJohn.Forte@Sun.COM 		 */
5317836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
5327836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
5337836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
5347836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
5357836SJohn.Forte@Sun.COM 			goto out;
5367836SJohn.Forte@Sun.COM 		}
5377836SJohn.Forte@Sun.COM 	}
5387836SJohn.Forte@Sun.COM 
5397836SJohn.Forte@Sun.COM 	/*
5407836SJohn.Forte@Sun.COM 	 * Yes, we're finally done. We actually added or removed one entry
5417836SJohn.Forte@Sun.COM 	 * from the list.
5427836SJohn.Forte@Sun.COM 	 * Woohoo!
5437836SJohn.Forte@Sun.COM 	 */
5447836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
5457836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
5467836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
5477836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
5487836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
5497836SJohn.Forte@Sun.COM 		} else {
5507836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
5517836SJohn.Forte@Sun.COM 		}
5527836SJohn.Forte@Sun.COM 		goto out;
5537836SJohn.Forte@Sun.COM 	}
5547836SJohn.Forte@Sun.COM 
5557836SJohn.Forte@Sun.COM out:
5567836SJohn.Forte@Sun.COM 	/*
5577836SJohn.Forte@Sun.COM 	 * Free resources
5587836SJohn.Forte@Sun.COM 	 */
5597836SJohn.Forte@Sun.COM 	if (handle != NULL) {
5607836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
5617836SJohn.Forte@Sun.COM 	}
5627836SJohn.Forte@Sun.COM 	if (svc != NULL) {
5637836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
5647836SJohn.Forte@Sun.COM 	}
5657836SJohn.Forte@Sun.COM 	if (pg != NULL) {
5667836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
5677836SJohn.Forte@Sun.COM 	}
5687836SJohn.Forte@Sun.COM 	if (tran != NULL) {
5697836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
5707836SJohn.Forte@Sun.COM 	}
5717836SJohn.Forte@Sun.COM 	if (entry != NULL) {
5727836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry);
5737836SJohn.Forte@Sun.COM 	}
5747836SJohn.Forte@Sun.COM 	if (prop != NULL) {
5757836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
5767836SJohn.Forte@Sun.COM 	}
5777836SJohn.Forte@Sun.COM 	if (valueLookup != NULL) {
5787836SJohn.Forte@Sun.COM 		scf_value_destroy(valueLookup);
5797836SJohn.Forte@Sun.COM 	}
5807836SJohn.Forte@Sun.COM 	if (valueIter != NULL) {
5817836SJohn.Forte@Sun.COM 		scf_iter_destroy(valueIter);
5827836SJohn.Forte@Sun.COM 	}
5837836SJohn.Forte@Sun.COM 
5847836SJohn.Forte@Sun.COM 	/*
5857836SJohn.Forte@Sun.COM 	 * Free valueSet scf resources
5867836SJohn.Forte@Sun.COM 	 */
5877836SJohn.Forte@Sun.COM 	if (valueArraySize > 0) {
5887836SJohn.Forte@Sun.COM 		for (i = 0; i < valueArraySize; i++) {
5897836SJohn.Forte@Sun.COM 			scf_value_destroy(valueSet[i]);
5907836SJohn.Forte@Sun.COM 		}
5917836SJohn.Forte@Sun.COM 	}
5927836SJohn.Forte@Sun.COM 	/*
5937836SJohn.Forte@Sun.COM 	 * Now free the pointer array to the resources
5947836SJohn.Forte@Sun.COM 	 */
5957836SJohn.Forte@Sun.COM 	if (valueSet != NULL) {
5967836SJohn.Forte@Sun.COM 		free(valueSet);
5977836SJohn.Forte@Sun.COM 	}
5987836SJohn.Forte@Sun.COM 
5997836SJohn.Forte@Sun.COM 	return (ret);
6007836SJohn.Forte@Sun.COM }
6017836SJohn.Forte@Sun.COM 
6027836SJohn.Forte@Sun.COM /*
6037836SJohn.Forte@Sun.COM  * iPsAddRemoveLuViewEntry
6047836SJohn.Forte@Sun.COM  *
6057836SJohn.Forte@Sun.COM  * Adds or removes a view entry name property for a given logical unit
6067836SJohn.Forte@Sun.COM  * property group. There is one logical unit property group for every logical
6077836SJohn.Forte@Sun.COM  * unit that has one or more associated view entries.
6087836SJohn.Forte@Sun.COM  *
6097836SJohn.Forte@Sun.COM  * luPgName - Property group name of logical unit
6107836SJohn.Forte@Sun.COM  * viewEntryPgName - Property group name of view entry
6117836SJohn.Forte@Sun.COM  * addRemoveFlag - ADD_VE/REMOVE_VE
6127836SJohn.Forte@Sun.COM  *
6137836SJohn.Forte@Sun.COM  * returns:
6147836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
6157836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
6167836SJohn.Forte@Sun.COM  */
6177836SJohn.Forte@Sun.COM static int
6187836SJohn.Forte@Sun.COM iPsAddRemoveLuViewEntry(char *luPgName, char *viewEntryPgName,
6197836SJohn.Forte@Sun.COM     int addRemoveFlag)
6207836SJohn.Forte@Sun.COM {
6217836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
6227836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
6237836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
6247836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
6257836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
6267836SJohn.Forte@Sun.COM 	scf_transaction_t   *tran = NULL;
6277836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry = NULL;
6287836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entryVeName = NULL;
6297836SJohn.Forte@Sun.COM 	boolean_t createVeCnt = B_FALSE;
6307836SJohn.Forte@Sun.COM 	uint64_t veCnt = 0;
6317836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
6327836SJohn.Forte@Sun.COM 	int commitRet;
6337836SJohn.Forte@Sun.COM 
6347836SJohn.Forte@Sun.COM 	assert(luPgName != NULL || viewEntryPgName != NULL);
6357836SJohn.Forte@Sun.COM 	assert(!(addRemoveFlag != ADD && addRemoveFlag != REMOVE));
6367836SJohn.Forte@Sun.COM 
6377836SJohn.Forte@Sun.COM 	/*
6387836SJohn.Forte@Sun.COM 	 * Init the service handle
6397836SJohn.Forte@Sun.COM 	 */
6407836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
6417836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
6427836SJohn.Forte@Sun.COM 		goto out;
6437836SJohn.Forte@Sun.COM 	}
6447836SJohn.Forte@Sun.COM 
6457836SJohn.Forte@Sun.COM 	/*
6467836SJohn.Forte@Sun.COM 	 * Allocate scf resources
6477836SJohn.Forte@Sun.COM 	 */
6487836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
6497836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
6507836SJohn.Forte@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
6517836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
6527836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
6537836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
6547836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
6557836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
6567836SJohn.Forte@Sun.COM 		goto out;
6577836SJohn.Forte@Sun.COM 	}
6587836SJohn.Forte@Sun.COM 
6597836SJohn.Forte@Sun.COM 	/* get the LU property group */
6607836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, luPgName, pg) == -1) {
6617836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND &&
6627836SJohn.Forte@Sun.COM 		    addRemoveFlag == ADD) {
6637836SJohn.Forte@Sun.COM 			/* if it doesn't exist, create it */
6647836SJohn.Forte@Sun.COM 			if (scf_service_add_pg(svc, luPgName,
6657836SJohn.Forte@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
6667836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
6677836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
6687836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
6697836SJohn.Forte@Sun.COM 			} else {
6707836SJohn.Forte@Sun.COM 				/* we need to create the VE_CNT property */
6717836SJohn.Forte@Sun.COM 				createVeCnt = B_TRUE;
6727836SJohn.Forte@Sun.COM 				ret = STMF_PS_SUCCESS;
6737836SJohn.Forte@Sun.COM 			}
6747836SJohn.Forte@Sun.COM 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
6757836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
6767836SJohn.Forte@Sun.COM 		} else {
6777836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
6787836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
6797836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
6807836SJohn.Forte@Sun.COM 		}
6817836SJohn.Forte@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
6827836SJohn.Forte@Sun.COM 			goto out;
6837836SJohn.Forte@Sun.COM 		}
6847836SJohn.Forte@Sun.COM 	}
6857836SJohn.Forte@Sun.COM 
6867836SJohn.Forte@Sun.COM 
6877836SJohn.Forte@Sun.COM 	/*
6887836SJohn.Forte@Sun.COM 	 * Begin the transaction
6897836SJohn.Forte@Sun.COM 	 */
6907836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
6917836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
6927836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
6937836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
6947836SJohn.Forte@Sun.COM 		goto out;
6957836SJohn.Forte@Sun.COM 	}
6967836SJohn.Forte@Sun.COM 
6977836SJohn.Forte@Sun.COM 
6987836SJohn.Forte@Sun.COM 	if (createVeCnt) {
6997836SJohn.Forte@Sun.COM 		/*
7007836SJohn.Forte@Sun.COM 		 * Create the STMF_VE_CNT property. This will keep the current
7017836SJohn.Forte@Sun.COM 		 * total view entries for this logical unit.
7027836SJohn.Forte@Sun.COM 		 */
7037836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry, STMF_VE_CNT,
7047836SJohn.Forte@Sun.COM 		    SCF_TYPE_COUNT) == -1) {
7057836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
7067836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
7077836SJohn.Forte@Sun.COM 			} else {
7087836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
7097836SJohn.Forte@Sun.COM 				    "transaction property new failed - %s",
7107836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
7117836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
7127836SJohn.Forte@Sun.COM 			}
7137836SJohn.Forte@Sun.COM 			goto out;
7147836SJohn.Forte@Sun.COM 		}
7157836SJohn.Forte@Sun.COM 	} else {
7167836SJohn.Forte@Sun.COM 		/*
7177836SJohn.Forte@Sun.COM 		 * The STMF_VE_CNT property already exists. Just update
7187836SJohn.Forte@Sun.COM 		 * it.
7197836SJohn.Forte@Sun.COM 		 */
7207836SJohn.Forte@Sun.COM 		if (scf_transaction_property_change(tran, entry,
7217836SJohn.Forte@Sun.COM 		    STMF_VE_CNT, SCF_TYPE_COUNT) == -1) {
7227836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
7237836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
7247836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
7257836SJohn.Forte@Sun.COM 			goto out;
7267836SJohn.Forte@Sun.COM 		}
7277836SJohn.Forte@Sun.COM 
7287836SJohn.Forte@Sun.COM 		/*
7297836SJohn.Forte@Sun.COM 		 * Get the STMF_VE_CNT property
7307836SJohn.Forte@Sun.COM 		 */
7317836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) {
7327836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
7337836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
7347836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
7357836SJohn.Forte@Sun.COM 			goto out;
7367836SJohn.Forte@Sun.COM 		}
7377836SJohn.Forte@Sun.COM 
7387836SJohn.Forte@Sun.COM 		/*
7397836SJohn.Forte@Sun.COM 		 * Get the STMF_VE_CNT value
7407836SJohn.Forte@Sun.COM 		 */
7417836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
7427836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
7437836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
7447836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
7457836SJohn.Forte@Sun.COM 			goto out;
7467836SJohn.Forte@Sun.COM 		}
7477836SJohn.Forte@Sun.COM 
7487836SJohn.Forte@Sun.COM 		/*
7497836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
7507836SJohn.Forte@Sun.COM 		 */
7517836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value, &veCnt) == -1) {
7527836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get integer value failed - %s",
7537836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
7547836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
7557836SJohn.Forte@Sun.COM 			goto out;
7567836SJohn.Forte@Sun.COM 		}
7577836SJohn.Forte@Sun.COM 
7587836SJohn.Forte@Sun.COM 		/*
7597836SJohn.Forte@Sun.COM 		 * Reset the value resource as it is used below
7607836SJohn.Forte@Sun.COM 		 */
7617836SJohn.Forte@Sun.COM 		scf_value_reset(value);
7627836SJohn.Forte@Sun.COM 	}
7637836SJohn.Forte@Sun.COM 
7647836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
7657836SJohn.Forte@Sun.COM 		veCnt++;
7667836SJohn.Forte@Sun.COM 	} else {
7677836SJohn.Forte@Sun.COM 		/* Check if this is the last one being removed */
7687836SJohn.Forte@Sun.COM 		if (veCnt == 1) {
7697836SJohn.Forte@Sun.COM 			/*
7707836SJohn.Forte@Sun.COM 			 * Delete the pg and get out if this is the last
7717836SJohn.Forte@Sun.COM 			 * view entry
7727836SJohn.Forte@Sun.COM 			 */
7737836SJohn.Forte@Sun.COM 			if (scf_pg_delete(pg) == -1) {
7747836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "delete pg failed - %s",
7757836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
7767836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
7777836SJohn.Forte@Sun.COM 			}
7787836SJohn.Forte@Sun.COM 			goto out;
7797836SJohn.Forte@Sun.COM 		} else {
7807836SJohn.Forte@Sun.COM 			veCnt--;
7817836SJohn.Forte@Sun.COM 		}
7827836SJohn.Forte@Sun.COM 	}
7837836SJohn.Forte@Sun.COM 
7847836SJohn.Forte@Sun.COM 
7857836SJohn.Forte@Sun.COM 	/*
7867836SJohn.Forte@Sun.COM 	 * Set the view entry count
7877836SJohn.Forte@Sun.COM 	 */
7887836SJohn.Forte@Sun.COM 	scf_value_set_count(value, veCnt);
7897836SJohn.Forte@Sun.COM 
7907836SJohn.Forte@Sun.COM 	/*
7917836SJohn.Forte@Sun.COM 	 * Add the value to the transaction entry
7927836SJohn.Forte@Sun.COM 	 */
7937836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry, value) == -1) {
7947836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
7957836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
7967836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
7977836SJohn.Forte@Sun.COM 		goto out;
7987836SJohn.Forte@Sun.COM 	}
7997836SJohn.Forte@Sun.COM 
8007836SJohn.Forte@Sun.COM 	/*
8017836SJohn.Forte@Sun.COM 	 * Create a transaction entry resource for the view entry name
8027836SJohn.Forte@Sun.COM 	 */
8037836SJohn.Forte@Sun.COM 	entryVeName = scf_entry_create(handle);
8047836SJohn.Forte@Sun.COM 	if (entryVeName == NULL) {
8057836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf transaction entry alloc failed - %s",
8067836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
8077836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
8087836SJohn.Forte@Sun.COM 		goto out;
8097836SJohn.Forte@Sun.COM 	}
8107836SJohn.Forte@Sun.COM 
8117836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
8127836SJohn.Forte@Sun.COM 		/*
8137836SJohn.Forte@Sun.COM 		 * If adding, create a property with the view entry name
8147836SJohn.Forte@Sun.COM 		 */
8157836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entryVeName,
8167836SJohn.Forte@Sun.COM 		    viewEntryPgName, SCF_TYPE_USTRING) == -1) {
8177836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
8187836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
8197836SJohn.Forte@Sun.COM 			} else {
8207836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
8217836SJohn.Forte@Sun.COM 				    "transaction property new failed - %s",
8227836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
8237836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
8247836SJohn.Forte@Sun.COM 			}
8257836SJohn.Forte@Sun.COM 			goto out;
8267836SJohn.Forte@Sun.COM 		}
8277836SJohn.Forte@Sun.COM 	} else {
8287836SJohn.Forte@Sun.COM 		/*
8297836SJohn.Forte@Sun.COM 		 * If removing, delete the existing property with the view
8307836SJohn.Forte@Sun.COM 		 * entry name
8317836SJohn.Forte@Sun.COM 		 */
8327836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, entryVeName,
8337836SJohn.Forte@Sun.COM 		    viewEntryPgName) == -1) {
8347836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND) {
8357836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_NOT_FOUND;
8367836SJohn.Forte@Sun.COM 			} else {
8377836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
8387836SJohn.Forte@Sun.COM 				    "transaction property delete failed - %s",
8397836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
8407836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
8417836SJohn.Forte@Sun.COM 			}
8427836SJohn.Forte@Sun.COM 			goto out;
8437836SJohn.Forte@Sun.COM 		}
8447836SJohn.Forte@Sun.COM 	}
8457836SJohn.Forte@Sun.COM 
8467836SJohn.Forte@Sun.COM 	/*
8477836SJohn.Forte@Sun.COM 	 * Commit property transaction
8487836SJohn.Forte@Sun.COM 	 */
8497836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
8507836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
8517836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
8527836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
8537836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
8547836SJohn.Forte@Sun.COM 		} else {
8557836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
8567836SJohn.Forte@Sun.COM 		}
8577836SJohn.Forte@Sun.COM 		goto out;
8587836SJohn.Forte@Sun.COM 	}
8597836SJohn.Forte@Sun.COM 
8607836SJohn.Forte@Sun.COM out:
8617836SJohn.Forte@Sun.COM 	/*
8627836SJohn.Forte@Sun.COM 	 * Free resources
8637836SJohn.Forte@Sun.COM 	 */
8647836SJohn.Forte@Sun.COM 	if (handle != NULL) {
8657836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
8667836SJohn.Forte@Sun.COM 	}
8677836SJohn.Forte@Sun.COM 	if (svc != NULL) {
8687836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
8697836SJohn.Forte@Sun.COM 	}
8707836SJohn.Forte@Sun.COM 	if (pg != NULL) {
8717836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
8727836SJohn.Forte@Sun.COM 	}
8737836SJohn.Forte@Sun.COM 	if (tran != NULL) {
8747836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
8757836SJohn.Forte@Sun.COM 	}
8767836SJohn.Forte@Sun.COM 	if (entry != NULL) {
8777836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry);
8787836SJohn.Forte@Sun.COM 	}
8797836SJohn.Forte@Sun.COM 	if (entryVeName != NULL) {
8807836SJohn.Forte@Sun.COM 		scf_entry_destroy(entryVeName);
8817836SJohn.Forte@Sun.COM 	}
8827836SJohn.Forte@Sun.COM 	if (prop != NULL) {
8837836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
8847836SJohn.Forte@Sun.COM 	}
8857836SJohn.Forte@Sun.COM 	if (value != NULL) {
8867836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
8877836SJohn.Forte@Sun.COM 	}
8887836SJohn.Forte@Sun.COM 
8897836SJohn.Forte@Sun.COM 	return (ret);
8907836SJohn.Forte@Sun.COM }
8917836SJohn.Forte@Sun.COM 
8927836SJohn.Forte@Sun.COM /*
8937836SJohn.Forte@Sun.COM  * iPsAddViewEntry
8947836SJohn.Forte@Sun.COM  *
8957836SJohn.Forte@Sun.COM  * Add a view entry property group and optionally, a logical unit property
8967836SJohn.Forte@Sun.COM  * group if it does not exist.
8977836SJohn.Forte@Sun.COM  *
8987836SJohn.Forte@Sun.COM  * luName - ascii hexadecimal logical unit identifier
8997836SJohn.Forte@Sun.COM  * viewEntryName - name of view entry (VIEW_ENTRY_nn)
9007836SJohn.Forte@Sun.COM  * viewEntry - pointer to stmfViewEntry structure
9017836SJohn.Forte@Sun.COM  */
9027836SJohn.Forte@Sun.COM static int
9037836SJohn.Forte@Sun.COM iPsAddViewEntry(char *luPgName, char *viewEntryPgName, stmfViewEntry *viewEntry)
9047836SJohn.Forte@Sun.COM {
9057836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
9067836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
9077836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
9087836SJohn.Forte@Sun.COM 	scf_value_t	*value[VIEW_ENTRY_STRUCT_CNT];
9097836SJohn.Forte@Sun.COM 	scf_transaction_t   *tran = NULL;
9107836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry[VIEW_ENTRY_STRUCT_CNT];
9117836SJohn.Forte@Sun.COM 	int i = 0;
9127836SJohn.Forte@Sun.COM 	int j = 0;
9137836SJohn.Forte@Sun.COM 	int ret;
9147836SJohn.Forte@Sun.COM 	uint8_t scfBool;
9157836SJohn.Forte@Sun.COM 	boolean_t createdVePg = B_FALSE;
9167836SJohn.Forte@Sun.COM 	int backoutRet;
9177836SJohn.Forte@Sun.COM 	int commitRet;
9187836SJohn.Forte@Sun.COM 
9197836SJohn.Forte@Sun.COM 	assert(luPgName != NULL || viewEntryPgName != NULL ||
9207836SJohn.Forte@Sun.COM 	    viewEntry == NULL);
9217836SJohn.Forte@Sun.COM 
9227836SJohn.Forte@Sun.COM 	bzero(value, sizeof (value));
9237836SJohn.Forte@Sun.COM 	bzero(entry, sizeof (entry));
9247836SJohn.Forte@Sun.COM 
9257836SJohn.Forte@Sun.COM 	/*
9267836SJohn.Forte@Sun.COM 	 * Init the service handle
9277836SJohn.Forte@Sun.COM 	 */
9287836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
9297836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
9307836SJohn.Forte@Sun.COM 		goto out;
9317836SJohn.Forte@Sun.COM 	}
9327836SJohn.Forte@Sun.COM 
9337836SJohn.Forte@Sun.COM 	/*
9347836SJohn.Forte@Sun.COM 	 * Allocate scf resources
9357836SJohn.Forte@Sun.COM 	 */
9367836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
9377836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL)) {
9387836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
9397836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
9407836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
9417836SJohn.Forte@Sun.COM 		goto out;
9427836SJohn.Forte@Sun.COM 	}
9437836SJohn.Forte@Sun.COM 
9447836SJohn.Forte@Sun.COM 	/*
9457836SJohn.Forte@Sun.COM 	 * allocate value and entry resources for scf
9467836SJohn.Forte@Sun.COM 	 */
9477836SJohn.Forte@Sun.COM 	for (i = 0; i < VIEW_ENTRY_STRUCT_CNT; i++) {
9487836SJohn.Forte@Sun.COM 		if (((value[i] = scf_value_create(handle)) == NULL) ||
9497836SJohn.Forte@Sun.COM 		    ((entry[i] = scf_entry_create(handle)) == NULL)) {
9507836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf alloc resource failed - %s",
9517836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
9527836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
9537836SJohn.Forte@Sun.COM 			goto out;
9547836SJohn.Forte@Sun.COM 		}
9557836SJohn.Forte@Sun.COM 	}
9567836SJohn.Forte@Sun.COM 
9577836SJohn.Forte@Sun.COM 	i = 0;
9587836SJohn.Forte@Sun.COM 
9597836SJohn.Forte@Sun.COM 	/*
9607836SJohn.Forte@Sun.COM 	 * Create the View Entry property group
9617836SJohn.Forte@Sun.COM 	 */
9627836SJohn.Forte@Sun.COM 	if (scf_service_add_pg(svc, viewEntryPgName, SCF_GROUP_APPLICATION,
9637836SJohn.Forte@Sun.COM 	    0, pg) == -1) {
9647836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
9657836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
9667836SJohn.Forte@Sun.COM 		} else {
9677836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add pg failed - %s",
9687836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
9697836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
9707836SJohn.Forte@Sun.COM 		}
9717836SJohn.Forte@Sun.COM 		goto out;
9727836SJohn.Forte@Sun.COM 	}
9737836SJohn.Forte@Sun.COM 
9747836SJohn.Forte@Sun.COM 	createdVePg = B_TRUE;
9757836SJohn.Forte@Sun.COM 
9767836SJohn.Forte@Sun.COM 	/*
9777836SJohn.Forte@Sun.COM 	 * Add the view entry as properties on the view entry group
9787836SJohn.Forte@Sun.COM 	 */
9797836SJohn.Forte@Sun.COM 
9807836SJohn.Forte@Sun.COM 	/*
9817836SJohn.Forte@Sun.COM 	 * Begin property update transaction
9827836SJohn.Forte@Sun.COM 	 */
9837836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
9847836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
9857836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
9867836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
9877836SJohn.Forte@Sun.COM 		goto out;
9887836SJohn.Forte@Sun.COM 	}
9897836SJohn.Forte@Sun.COM 
9907836SJohn.Forte@Sun.COM 	/*
9917836SJohn.Forte@Sun.COM 	 * Add allHosts property
9927836SJohn.Forte@Sun.COM 	 */
9937836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
9947836SJohn.Forte@Sun.COM 	    STMF_VE_ALLHOSTS, SCF_TYPE_BOOLEAN) == -1) {
9957836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
9967836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
9977836SJohn.Forte@Sun.COM 		} else {
9987836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
9997836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
10007836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
10017836SJohn.Forte@Sun.COM 		}
10027836SJohn.Forte@Sun.COM 		goto out;
10037836SJohn.Forte@Sun.COM 	}
10047836SJohn.Forte@Sun.COM 
10057836SJohn.Forte@Sun.COM 	/* Set the allHosts value */
10067836SJohn.Forte@Sun.COM 	scfBool = viewEntry->allHosts;
10077836SJohn.Forte@Sun.COM 	scf_value_set_boolean(value[i], scfBool);
10087836SJohn.Forte@Sun.COM 
10097836SJohn.Forte@Sun.COM 	/*
10107836SJohn.Forte@Sun.COM 	 * Add the allHosts value to the transaction
10117836SJohn.Forte@Sun.COM 	 */
10127836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
10137836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
10147836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
10157836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
10167836SJohn.Forte@Sun.COM 		goto out;
10177836SJohn.Forte@Sun.COM 	}
10187836SJohn.Forte@Sun.COM 
10197836SJohn.Forte@Sun.COM 	i++;
10207836SJohn.Forte@Sun.COM 
10217836SJohn.Forte@Sun.COM 	/*
10227836SJohn.Forte@Sun.COM 	 * Create hostGroup property
10237836SJohn.Forte@Sun.COM 	 */
10247836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
10257836SJohn.Forte@Sun.COM 	    STMF_VE_HOSTGROUP, SCF_TYPE_USTRING) == -1) {
10267836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
10277836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
10287836SJohn.Forte@Sun.COM 		} else {
10297836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
10307836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
10317836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
10327836SJohn.Forte@Sun.COM 		}
10337836SJohn.Forte@Sun.COM 		goto out;
10347836SJohn.Forte@Sun.COM 	}
10357836SJohn.Forte@Sun.COM 
10367836SJohn.Forte@Sun.COM 	/*
10377836SJohn.Forte@Sun.COM 	 * Set the value for hostGroup
10387836SJohn.Forte@Sun.COM 	 */
10397836SJohn.Forte@Sun.COM 	if (scf_value_set_ustring(value[i], viewEntry->hostGroup) == -1) {
10407836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
10417836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
10427836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
10437836SJohn.Forte@Sun.COM 		goto out;
10447836SJohn.Forte@Sun.COM 	}
10457836SJohn.Forte@Sun.COM 
10467836SJohn.Forte@Sun.COM 	/*
10477836SJohn.Forte@Sun.COM 	 * Add the hostGroup value to the transaction entry
10487836SJohn.Forte@Sun.COM 	 */
10497836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
10507836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
10517836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
10527836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
10537836SJohn.Forte@Sun.COM 		goto out;
10547836SJohn.Forte@Sun.COM 	}
10557836SJohn.Forte@Sun.COM 
10567836SJohn.Forte@Sun.COM 	i++;
10577836SJohn.Forte@Sun.COM 
10587836SJohn.Forte@Sun.COM 	/*
10597836SJohn.Forte@Sun.COM 	 * Create the allTargets property
10607836SJohn.Forte@Sun.COM 	 */
10617836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
10627836SJohn.Forte@Sun.COM 	    STMF_VE_ALLTARGETS, SCF_TYPE_BOOLEAN) == -1) {
10637836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
10647836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
10657836SJohn.Forte@Sun.COM 		} else {
10667836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
10677836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
10687836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
10697836SJohn.Forte@Sun.COM 		}
10707836SJohn.Forte@Sun.COM 		goto out;
10717836SJohn.Forte@Sun.COM 	}
10727836SJohn.Forte@Sun.COM 
10737836SJohn.Forte@Sun.COM 	/*
10747836SJohn.Forte@Sun.COM 	 * Set the allTargets value
10757836SJohn.Forte@Sun.COM 	 */
10767836SJohn.Forte@Sun.COM 	scfBool = viewEntry->allTargets;
10777836SJohn.Forte@Sun.COM 	scf_value_set_boolean(value[i], scfBool);
10787836SJohn.Forte@Sun.COM 
10797836SJohn.Forte@Sun.COM 	/*
10807836SJohn.Forte@Sun.COM 	 * Add the allTargets value to the transaction
10817836SJohn.Forte@Sun.COM 	 */
10827836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
10837836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
10847836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
10857836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
10867836SJohn.Forte@Sun.COM 		goto out;
10877836SJohn.Forte@Sun.COM 	}
10887836SJohn.Forte@Sun.COM 
10897836SJohn.Forte@Sun.COM 	i++;
10907836SJohn.Forte@Sun.COM 
10917836SJohn.Forte@Sun.COM 	/*
10927836SJohn.Forte@Sun.COM 	 * Create targetGroup property
10937836SJohn.Forte@Sun.COM 	 */
10947836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
10957836SJohn.Forte@Sun.COM 	    STMF_VE_TARGETGROUP, SCF_TYPE_USTRING) == -1) {
10967836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
10977836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
10987836SJohn.Forte@Sun.COM 		} else {
10997836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
11007836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
11017836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
11027836SJohn.Forte@Sun.COM 		}
11037836SJohn.Forte@Sun.COM 		goto out;
11047836SJohn.Forte@Sun.COM 	}
11057836SJohn.Forte@Sun.COM 
11067836SJohn.Forte@Sun.COM 	/*
11077836SJohn.Forte@Sun.COM 	 * Set the value for targetGroup
11087836SJohn.Forte@Sun.COM 	 */
11097836SJohn.Forte@Sun.COM 	if (scf_value_set_ustring(value[i], viewEntry->targetGroup) == -1) {
11107836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
11117836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
11127836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
11137836SJohn.Forte@Sun.COM 		goto out;
11147836SJohn.Forte@Sun.COM 	}
11157836SJohn.Forte@Sun.COM 
11167836SJohn.Forte@Sun.COM 	/*
11177836SJohn.Forte@Sun.COM 	 * Add targetGroup value to the transaction
11187836SJohn.Forte@Sun.COM 	 */
11197836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
11207836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
11217836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
11227836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
11237836SJohn.Forte@Sun.COM 		goto out;
11247836SJohn.Forte@Sun.COM 	}
11257836SJohn.Forte@Sun.COM 
11267836SJohn.Forte@Sun.COM 	i++;
11277836SJohn.Forte@Sun.COM 
11287836SJohn.Forte@Sun.COM 	/*
11297836SJohn.Forte@Sun.COM 	 * Create the luNbr property
11307836SJohn.Forte@Sun.COM 	 */
11317836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i], STMF_VE_LUNBR,
11327836SJohn.Forte@Sun.COM 	    SCF_TYPE_OPAQUE) == -1) {
11337836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
11347836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
11357836SJohn.Forte@Sun.COM 		} else {
11367836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
11377836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
11387836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
11397836SJohn.Forte@Sun.COM 		}
11407836SJohn.Forte@Sun.COM 		goto out;
11417836SJohn.Forte@Sun.COM 	}
11427836SJohn.Forte@Sun.COM 
11437836SJohn.Forte@Sun.COM 	/*
11447836SJohn.Forte@Sun.COM 	 * Set the luNbr
11457836SJohn.Forte@Sun.COM 	 */
11467836SJohn.Forte@Sun.COM 	if (scf_value_set_opaque(value[i], (char *)viewEntry->luNbr,
11477836SJohn.Forte@Sun.COM 	    sizeof (viewEntry->luNbr)) == -1) {
11487836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
11497836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
11507836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
11517836SJohn.Forte@Sun.COM 		goto out;
11527836SJohn.Forte@Sun.COM 	}
11537836SJohn.Forte@Sun.COM 
11547836SJohn.Forte@Sun.COM 	/*
11557836SJohn.Forte@Sun.COM 	 * Add luNbr to the transaction entry
11567836SJohn.Forte@Sun.COM 	 */
11577836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
11587836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
11597836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
11607836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
11617836SJohn.Forte@Sun.COM 		goto out;
11627836SJohn.Forte@Sun.COM 	}
11637836SJohn.Forte@Sun.COM 
11647836SJohn.Forte@Sun.COM 	/*
11657836SJohn.Forte@Sun.COM 	 * Now that we've successfully added the view entry,
11667836SJohn.Forte@Sun.COM 	 * update the logical unit property group or create
11677836SJohn.Forte@Sun.COM 	 * it if it does not exist
11687836SJohn.Forte@Sun.COM 	 */
11697836SJohn.Forte@Sun.COM 	ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, ADD);
11707836SJohn.Forte@Sun.COM 
11717836SJohn.Forte@Sun.COM 	/*
11727836SJohn.Forte@Sun.COM 	 * If we did not add the view entry name to the logical unit,
11737836SJohn.Forte@Sun.COM 	 * make sure we do not commit the transaction
11747836SJohn.Forte@Sun.COM 	 */
11757836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
11767836SJohn.Forte@Sun.COM 		goto out;
11777836SJohn.Forte@Sun.COM 	}
11787836SJohn.Forte@Sun.COM 
11797836SJohn.Forte@Sun.COM 	/*
11807836SJohn.Forte@Sun.COM 	 * Commit property transaction
11817836SJohn.Forte@Sun.COM 	 */
11827836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
11837836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
11847836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
11857836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
11867836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
11877836SJohn.Forte@Sun.COM 		} else {
11887836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
11897836SJohn.Forte@Sun.COM 		}
11907836SJohn.Forte@Sun.COM 	}
11917836SJohn.Forte@Sun.COM 
11927836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
11937836SJohn.Forte@Sun.COM 		/*
11947836SJohn.Forte@Sun.COM 		 * If we did not commit, try to remove the view entry name
11957836SJohn.Forte@Sun.COM 		 * from the logical unit.
11967836SJohn.Forte@Sun.COM 		 * If that fails, we're now inconsistent.
11977836SJohn.Forte@Sun.COM 		 */
11987836SJohn.Forte@Sun.COM 		backoutRet = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
11997836SJohn.Forte@Sun.COM 		    REMOVE);
12007836SJohn.Forte@Sun.COM 
12017836SJohn.Forte@Sun.COM 		if (backoutRet != STMF_PS_SUCCESS) {
12027836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "remove lu view entry failed"
12037836SJohn.Forte@Sun.COM 			    "possible inconsistency - %s",
12047836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
12057836SJohn.Forte@Sun.COM 		}
12067836SJohn.Forte@Sun.COM 		/*
12077836SJohn.Forte@Sun.COM 		 * We are still in an error scenario even though the remove
12087836SJohn.Forte@Sun.COM 		 * lu view entry succeeded.
12097836SJohn.Forte@Sun.COM 		 */
12107836SJohn.Forte@Sun.COM 		goto out;
12117836SJohn.Forte@Sun.COM 	}
12127836SJohn.Forte@Sun.COM 
12137836SJohn.Forte@Sun.COM out:
12147836SJohn.Forte@Sun.COM 	/*
12157836SJohn.Forte@Sun.COM 	 * Free resources
12167836SJohn.Forte@Sun.COM 	 */
12177836SJohn.Forte@Sun.COM 	if (handle != NULL) {
12187836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
12197836SJohn.Forte@Sun.COM 	}
12207836SJohn.Forte@Sun.COM 	if (svc != NULL) {
12217836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
12227836SJohn.Forte@Sun.COM 	}
12237836SJohn.Forte@Sun.COM 	/* if there was an error, delete the created pg if one was created */
12247836SJohn.Forte@Sun.COM 	if ((ret != STMF_PS_SUCCESS) && createdVePg) {
12257836SJohn.Forte@Sun.COM 		if (scf_pg_delete(pg) == -1) {
12267836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "delete VE pg failed - %s",
12277836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
12287836SJohn.Forte@Sun.COM 		}
12297836SJohn.Forte@Sun.COM 	}
12307836SJohn.Forte@Sun.COM 	if (pg != NULL) {
12317836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
12327836SJohn.Forte@Sun.COM 	}
12337836SJohn.Forte@Sun.COM 	if (tran != NULL) {
12347836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
12357836SJohn.Forte@Sun.COM 	}
12367836SJohn.Forte@Sun.COM 	/*
12377836SJohn.Forte@Sun.COM 	 * Free value and entry scf resources
12387836SJohn.Forte@Sun.COM 	 */
12397836SJohn.Forte@Sun.COM 	if (i > 0) {
12407836SJohn.Forte@Sun.COM 		for (j = 0; j < VIEW_ENTRY_STRUCT_CNT; j++) {
12417836SJohn.Forte@Sun.COM 			if (value[j] != NULL)
12427836SJohn.Forte@Sun.COM 				scf_value_destroy(value[j]);
12437836SJohn.Forte@Sun.COM 			if (entry[j] != NULL)
12447836SJohn.Forte@Sun.COM 				scf_entry_destroy(entry[j]);
12457836SJohn.Forte@Sun.COM 		}
12467836SJohn.Forte@Sun.COM 	}
12477836SJohn.Forte@Sun.COM 
12487836SJohn.Forte@Sun.COM 	return (ret);
12497836SJohn.Forte@Sun.COM }
12507836SJohn.Forte@Sun.COM /*
12517836SJohn.Forte@Sun.COM  * psClearProviderData
12527836SJohn.Forte@Sun.COM  *
12537836SJohn.Forte@Sun.COM  * providerName - name of provider data to clear
12547836SJohn.Forte@Sun.COM  */
12557836SJohn.Forte@Sun.COM int
12567836SJohn.Forte@Sun.COM psClearProviderData(char *providerName, int providerType)
12577836SJohn.Forte@Sun.COM {
12587836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
12597836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
12607836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
12617836SJohn.Forte@Sun.COM 	char pgName[MAXPATHLEN];
12627836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
12637836SJohn.Forte@Sun.COM 	boolean_t pgNotFound = B_FALSE;
12647836SJohn.Forte@Sun.COM 
12657836SJohn.Forte@Sun.COM 	if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
12667836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE)) {
12677836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_INVALID_ARG;
12687836SJohn.Forte@Sun.COM 		goto out;
12697836SJohn.Forte@Sun.COM 	}
12707836SJohn.Forte@Sun.COM 
12717836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
12727836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
12737836SJohn.Forte@Sun.COM 		goto out;
12747836SJohn.Forte@Sun.COM 	}
12757836SJohn.Forte@Sun.COM 
12767836SJohn.Forte@Sun.COM 	/*
12777836SJohn.Forte@Sun.COM 	 * Allocate scf resources
12787836SJohn.Forte@Sun.COM 	 */
12797836SJohn.Forte@Sun.COM 	if ((pg = scf_pg_create(handle)) == NULL) {
12807836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
12817836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
12827836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
12837836SJohn.Forte@Sun.COM 		goto out;
12847836SJohn.Forte@Sun.COM 	}
12857836SJohn.Forte@Sun.COM 
12867836SJohn.Forte@Sun.COM 	/*
12877836SJohn.Forte@Sun.COM 	 * create the property group name
12887836SJohn.Forte@Sun.COM 	 */
12897836SJohn.Forte@Sun.COM 	(void) snprintf(pgName, sizeof (pgName), "%s%s",
12907836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PREFIX, providerName);
12917836SJohn.Forte@Sun.COM 
12927836SJohn.Forte@Sun.COM 	/*
12937836SJohn.Forte@Sun.COM 	 * delete provider property group
12947836SJohn.Forte@Sun.COM 	 */
12957836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
12967836SJohn.Forte@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
12977836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
12987836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
12997836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
13007836SJohn.Forte@Sun.COM 			goto out;
13017836SJohn.Forte@Sun.COM 		} else {
13027836SJohn.Forte@Sun.COM 			pgNotFound = B_TRUE;
13037836SJohn.Forte@Sun.COM 		}
13047836SJohn.Forte@Sun.COM 	}
13057836SJohn.Forte@Sun.COM 
13067836SJohn.Forte@Sun.COM 	if (!pgNotFound && (scf_pg_delete(pg) == -1)) {
13077836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "delete pg failed - %s",
13087836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
13097836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
13107836SJohn.Forte@Sun.COM 		goto out;
13117836SJohn.Forte@Sun.COM 	}
13127836SJohn.Forte@Sun.COM 
13137836SJohn.Forte@Sun.COM 	if (pgNotFound) {
13147836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOT_FOUND;
13157836SJohn.Forte@Sun.COM 	}
13167836SJohn.Forte@Sun.COM 
13177836SJohn.Forte@Sun.COM out:
13187836SJohn.Forte@Sun.COM 	/*
13197836SJohn.Forte@Sun.COM 	 * Free resources
13207836SJohn.Forte@Sun.COM 	 */
13217836SJohn.Forte@Sun.COM 	if (handle != NULL) {
13227836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
13237836SJohn.Forte@Sun.COM 	}
13247836SJohn.Forte@Sun.COM 	if (svc != NULL) {
13257836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
13267836SJohn.Forte@Sun.COM 	}
13277836SJohn.Forte@Sun.COM 	if (pg != NULL) {
13287836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
13297836SJohn.Forte@Sun.COM 	}
13307836SJohn.Forte@Sun.COM 
13317836SJohn.Forte@Sun.COM 	return (ret);
13327836SJohn.Forte@Sun.COM }
13337836SJohn.Forte@Sun.COM 
13347836SJohn.Forte@Sun.COM /*
13357836SJohn.Forte@Sun.COM  * iPsCreateDeleteGroup
13367836SJohn.Forte@Sun.COM  *
13377836SJohn.Forte@Sun.COM  * Creates or deletes a group (target or host)
13387836SJohn.Forte@Sun.COM  *
13397836SJohn.Forte@Sun.COM  * When creating a group, two properties are created. One to hold the group
13407836SJohn.Forte@Sun.COM  * name and the other to hold the group members.
13417836SJohn.Forte@Sun.COM  *
13427836SJohn.Forte@Sun.COM  * pgName - Property group name
13437836SJohn.Forte@Sun.COM  * groupName - group name to create
13447836SJohn.Forte@Sun.COM  * addRemoveFlag - ADD_GROUP/REMOVE_GROUP
13457836SJohn.Forte@Sun.COM  *
13467836SJohn.Forte@Sun.COM  * returns:
13477836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
13487836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
13497836SJohn.Forte@Sun.COM  */
13507836SJohn.Forte@Sun.COM static int
13517836SJohn.Forte@Sun.COM iPsCreateDeleteGroup(char *pgRefName, char *groupName, int addRemoveFlag)
13527836SJohn.Forte@Sun.COM {
13537836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
13547836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
13557836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
13567836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
13577836SJohn.Forte@Sun.COM 	scf_iter_t	*propIter = NULL;
13587836SJohn.Forte@Sun.COM 	scf_transaction_t   *tran = NULL;
13597836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry1 = NULL;
13607836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry2 = NULL;
13617836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
13627836SJohn.Forte@Sun.COM 	uint64_t groupIdx;
13637836SJohn.Forte@Sun.COM 	char buf1[MAXNAMELEN];
13647836SJohn.Forte@Sun.COM 	char buf2[MAXNAMELEN];
13657836SJohn.Forte@Sun.COM 	char tmpbuf[MAXNAMELEN];
13667836SJohn.Forte@Sun.COM 	boolean_t found = B_FALSE;
13677836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
13687836SJohn.Forte@Sun.COM 	int commitRet;
13697836SJohn.Forte@Sun.COM 
13707836SJohn.Forte@Sun.COM 	assert(groupName != NULL);
13717836SJohn.Forte@Sun.COM 
13727836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
13737836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
13747836SJohn.Forte@Sun.COM 		goto out;
13757836SJohn.Forte@Sun.COM 	}
13767836SJohn.Forte@Sun.COM 
13777836SJohn.Forte@Sun.COM 	/*
13787836SJohn.Forte@Sun.COM 	 * Allocate scf resources
13797836SJohn.Forte@Sun.COM 	 */
13807836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
13817836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
13827836SJohn.Forte@Sun.COM 	    ((entry1 = scf_entry_create(handle)) == NULL) ||
13837836SJohn.Forte@Sun.COM 	    ((entry2 = scf_entry_create(handle)) == NULL) ||
13847836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
13857836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
13867836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
13877836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
13887836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
13897836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
13907836SJohn.Forte@Sun.COM 		goto out;
13917836SJohn.Forte@Sun.COM 	}
13927836SJohn.Forte@Sun.COM 
13937836SJohn.Forte@Sun.COM 	/*
13947836SJohn.Forte@Sun.COM 	 * Get the property group being modified
13957836SJohn.Forte@Sun.COM 	 */
13967836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgRefName, pg) == -1) {
13977836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND &&
13987836SJohn.Forte@Sun.COM 		    addRemoveFlag == ADD) {
13997836SJohn.Forte@Sun.COM 			if (scf_service_add_pg(svc, pgRefName,
14007836SJohn.Forte@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
14017836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
14027836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
14037836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
14047836SJohn.Forte@Sun.COM 			}
14057836SJohn.Forte@Sun.COM 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
14067836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
14077836SJohn.Forte@Sun.COM 		} else {
14087836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
14097836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
14107836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
14117836SJohn.Forte@Sun.COM 		}
14127836SJohn.Forte@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
14137836SJohn.Forte@Sun.COM 			goto out;
14147836SJohn.Forte@Sun.COM 		}
14157836SJohn.Forte@Sun.COM 	}
14167836SJohn.Forte@Sun.COM 
14177836SJohn.Forte@Sun.COM 	/*
14187836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
14197836SJohn.Forte@Sun.COM 	 */
14207836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
14217836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
14227836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
14237836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
14247836SJohn.Forte@Sun.COM 		goto out;
14257836SJohn.Forte@Sun.COM 	}
14267836SJohn.Forte@Sun.COM 
14277836SJohn.Forte@Sun.COM 	/*
14287836SJohn.Forte@Sun.COM 	 * Iterate through the group names.
14297836SJohn.Forte@Sun.COM 	 * If we find it in the list, it's an error when addRemoveFlag == ADD.
14307836SJohn.Forte@Sun.COM 	 */
14317836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
14327836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, buf1, sizeof (buf1)) == -1) {
14337836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
14347836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
14357836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
14367836SJohn.Forte@Sun.COM 			break;
14377836SJohn.Forte@Sun.COM 		}
14387836SJohn.Forte@Sun.COM 		/*
14397836SJohn.Forte@Sun.COM 		 * Skip over member list properties
14407836SJohn.Forte@Sun.COM 		 */
14417836SJohn.Forte@Sun.COM 		if (strstr(buf1, STMF_MEMBER_LIST_SUFFIX)) {
14427836SJohn.Forte@Sun.COM 			continue;
14437836SJohn.Forte@Sun.COM 		}
14447836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
14457836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
14467836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
14477836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
14487836SJohn.Forte@Sun.COM 			break;
14497836SJohn.Forte@Sun.COM 		}
14507836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(value, tmpbuf,
14517836SJohn.Forte@Sun.COM 		    sizeof (tmpbuf)) == -1) {
14527836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get ustring failed - %s",
14537836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
14547836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
14557836SJohn.Forte@Sun.COM 			break;
14567836SJohn.Forte@Sun.COM 		}
14577836SJohn.Forte@Sun.COM 
14587836SJohn.Forte@Sun.COM 		if ((strlen(tmpbuf) == strlen(groupName)) &&
14597836SJohn.Forte@Sun.COM 		    bcmp(tmpbuf, groupName, strlen(tmpbuf)) == 0) {
14607836SJohn.Forte@Sun.COM 			if (addRemoveFlag == ADD) {
14617836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
14627836SJohn.Forte@Sun.COM 			}
14637836SJohn.Forte@Sun.COM 			found = B_TRUE;
14647836SJohn.Forte@Sun.COM 			/*
14657836SJohn.Forte@Sun.COM 			 * buf1 contains the name for REMOVE
14667836SJohn.Forte@Sun.COM 			 */
14677836SJohn.Forte@Sun.COM 			break;
14687836SJohn.Forte@Sun.COM 		}
14697836SJohn.Forte@Sun.COM 	}
14707836SJohn.Forte@Sun.COM 
14717836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
14727836SJohn.Forte@Sun.COM 		goto out;
14737836SJohn.Forte@Sun.COM 	}
14747836SJohn.Forte@Sun.COM 
14757836SJohn.Forte@Sun.COM 	scf_value_reset(value);
14767836SJohn.Forte@Sun.COM 
14777836SJohn.Forte@Sun.COM 	if (!found && addRemoveFlag == REMOVE) {
14787836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOT_FOUND;
14797836SJohn.Forte@Sun.COM 		goto out;
14807836SJohn.Forte@Sun.COM 	}
14817836SJohn.Forte@Sun.COM 
14827836SJohn.Forte@Sun.COM 	/*
14837836SJohn.Forte@Sun.COM 	 * If we're adding, we need to create a new property name for the
14847836SJohn.Forte@Sun.COM 	 * new group
14857836SJohn.Forte@Sun.COM 	 */
14867836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
14877836SJohn.Forte@Sun.COM 		for (groupIdx = 0; groupIdx < GROUP_MAX; groupIdx++) {
14887836SJohn.Forte@Sun.COM 			if (snprintf(buf1, sizeof (buf1), "%s-%lld",
14897836SJohn.Forte@Sun.COM 			    STMF_GROUP_PREFIX, groupIdx) > sizeof (buf1)) {
14907836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
14917836SJohn.Forte@Sun.COM 				    "buffer overflow on property name %s",
14927836SJohn.Forte@Sun.COM 				    buf1);
14937836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
14947836SJohn.Forte@Sun.COM 				break;
14957836SJohn.Forte@Sun.COM 			}
14967836SJohn.Forte@Sun.COM 			if (scf_pg_get_property(pg, buf1, prop) == -1) {
14977836SJohn.Forte@Sun.COM 				if (scf_error() != SCF_ERROR_NOT_FOUND) {
14987836SJohn.Forte@Sun.COM 					syslog(LOG_ERR, "get pg failed - %s",
14997836SJohn.Forte@Sun.COM 					    scf_strerror(scf_error()));
15007836SJohn.Forte@Sun.COM 					ret = STMF_PS_ERROR;
15017836SJohn.Forte@Sun.COM 				}
15027836SJohn.Forte@Sun.COM 				break;
15037836SJohn.Forte@Sun.COM 			}
15047836SJohn.Forte@Sun.COM 		}
15057836SJohn.Forte@Sun.COM 	}
15067836SJohn.Forte@Sun.COM 
15077836SJohn.Forte@Sun.COM 	/*
15087836SJohn.Forte@Sun.COM 	 * Now create the new member list property for the new group
15097836SJohn.Forte@Sun.COM 	 */
15107836SJohn.Forte@Sun.COM 	if (snprintf(buf2, sizeof (buf2), "%s-%s", buf1,
15117836SJohn.Forte@Sun.COM 	    STMF_MEMBER_LIST_SUFFIX) > sizeof (buf2)) {
15127836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
15137836SJohn.Forte@Sun.COM 		    buf1);
15147836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
15157836SJohn.Forte@Sun.COM 		goto out;
15167836SJohn.Forte@Sun.COM 	}
15177836SJohn.Forte@Sun.COM 
15187836SJohn.Forte@Sun.COM 	/*
15197836SJohn.Forte@Sun.COM 	 * buf1 now contains the name of the property if it was found in the
15207836SJohn.Forte@Sun.COM 	 * list in the case of delete or the next available property name
15217836SJohn.Forte@Sun.COM 	 * in the case of create
15227836SJohn.Forte@Sun.COM 	 *
15237836SJohn.Forte@Sun.COM 	 * buf2 now contains the member list property name
15247836SJohn.Forte@Sun.COM 	 */
15257836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
15267836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
15277836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
15287836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
15297836SJohn.Forte@Sun.COM 		goto out;
15307836SJohn.Forte@Sun.COM 	}
15317836SJohn.Forte@Sun.COM 
15327836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
15337836SJohn.Forte@Sun.COM 		/*
15347836SJohn.Forte@Sun.COM 		 * Create the property 'group name'
15357836SJohn.Forte@Sun.COM 		 * This is the container for the group name
15367836SJohn.Forte@Sun.COM 		 */
15377836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry1, buf1,
15387836SJohn.Forte@Sun.COM 		    SCF_TYPE_USTRING) == -1) {
15397836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
15407836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
15417836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
15427836SJohn.Forte@Sun.COM 			goto out;
15437836SJohn.Forte@Sun.COM 		}
15447836SJohn.Forte@Sun.COM 		if (scf_value_set_ustring(value, groupName) == -1) {
15457836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set ustring failed - %s",
15467836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
15477836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
15487836SJohn.Forte@Sun.COM 			goto out;
15497836SJohn.Forte@Sun.COM 		}
15507836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry1, value) == -1) {
15517836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
15527836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
15537836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
15547836SJohn.Forte@Sun.COM 			goto out;
15557836SJohn.Forte@Sun.COM 		}
15567836SJohn.Forte@Sun.COM 		/*
15577836SJohn.Forte@Sun.COM 		 * Create the property 'group list'
15587836SJohn.Forte@Sun.COM 		 * This is the container for the group members
15597836SJohn.Forte@Sun.COM 		 */
15607836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry2, buf2,
15617836SJohn.Forte@Sun.COM 		    SCF_TYPE_USTRING) == -1) {
15627836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
15637836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
15647836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
15657836SJohn.Forte@Sun.COM 			goto out;
15667836SJohn.Forte@Sun.COM 		}
15677836SJohn.Forte@Sun.COM 	} else {
15687836SJohn.Forte@Sun.COM 		/*
15697836SJohn.Forte@Sun.COM 		 * Delete the property 'group name'
15707836SJohn.Forte@Sun.COM 		 */
15717836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, entry1, buf1)
15727836SJohn.Forte@Sun.COM 		    == -1) {
15737836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
15747836SJohn.Forte@Sun.COM 			    "transaction property delete failed - %s",
15757836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
15767836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
15777836SJohn.Forte@Sun.COM 			goto out;
15787836SJohn.Forte@Sun.COM 		}
15797836SJohn.Forte@Sun.COM 		/*
15807836SJohn.Forte@Sun.COM 		 * Delete the property 'group list'
15817836SJohn.Forte@Sun.COM 		 */
15827836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, entry2, buf2)
15837836SJohn.Forte@Sun.COM 		    == -1) {
15847836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
15857836SJohn.Forte@Sun.COM 			    "transaction property delete failed - %s",
15867836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
15877836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
15887836SJohn.Forte@Sun.COM 			goto out;
15897836SJohn.Forte@Sun.COM 		}
15907836SJohn.Forte@Sun.COM 	}
15917836SJohn.Forte@Sun.COM 
15927836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
15937836SJohn.Forte@Sun.COM 		goto out;
15947836SJohn.Forte@Sun.COM 	}
15957836SJohn.Forte@Sun.COM 
15967836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
15977836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
15987836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
15997836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
16007836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
16017836SJohn.Forte@Sun.COM 		} else {
16027836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
16037836SJohn.Forte@Sun.COM 		}
16047836SJohn.Forte@Sun.COM 	}
16057836SJohn.Forte@Sun.COM 
16067836SJohn.Forte@Sun.COM out:
16077836SJohn.Forte@Sun.COM 	/*
16087836SJohn.Forte@Sun.COM 	 * Free resources
16097836SJohn.Forte@Sun.COM 	 */
16107836SJohn.Forte@Sun.COM 	if (handle != NULL) {
16117836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
16127836SJohn.Forte@Sun.COM 	}
16137836SJohn.Forte@Sun.COM 	if (svc != NULL) {
16147836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
16157836SJohn.Forte@Sun.COM 	}
16167836SJohn.Forte@Sun.COM 	if (pg != NULL) {
16177836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
16187836SJohn.Forte@Sun.COM 	}
16197836SJohn.Forte@Sun.COM 	if (tran != NULL) {
16207836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
16217836SJohn.Forte@Sun.COM 	}
16227836SJohn.Forte@Sun.COM 	if (entry1 != NULL) {
16237836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry1);
16247836SJohn.Forte@Sun.COM 	}
16257836SJohn.Forte@Sun.COM 	if (entry2 != NULL) {
16267836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry2);
16277836SJohn.Forte@Sun.COM 	}
16287836SJohn.Forte@Sun.COM 	if (prop != NULL) {
16297836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
16307836SJohn.Forte@Sun.COM 	}
16317836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
16327836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
16337836SJohn.Forte@Sun.COM 	}
16347836SJohn.Forte@Sun.COM 	if (value != NULL) {
16357836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
16367836SJohn.Forte@Sun.COM 	}
16377836SJohn.Forte@Sun.COM 
16387836SJohn.Forte@Sun.COM 	return (ret);
16397836SJohn.Forte@Sun.COM }
16407836SJohn.Forte@Sun.COM 
16417836SJohn.Forte@Sun.COM /*
16427836SJohn.Forte@Sun.COM  * iPsGetGroupList
16437836SJohn.Forte@Sun.COM  *
16447836SJohn.Forte@Sun.COM  * pgName - Property group name
16457836SJohn.Forte@Sun.COM  * groupList - pointer to pointer to stmfGroupList structure. On success,
16467836SJohn.Forte@Sun.COM  * contains the list of groups
16477836SJohn.Forte@Sun.COM  *
16487836SJohn.Forte@Sun.COM  * returns:
16497836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
16507836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
16517836SJohn.Forte@Sun.COM  */
16527836SJohn.Forte@Sun.COM static int
16537836SJohn.Forte@Sun.COM iPsGetGroupList(char *pgName, stmfGroupList **groupList)
16547836SJohn.Forte@Sun.COM {
16557836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
16567836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
16577836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
16587836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
16597836SJohn.Forte@Sun.COM 	scf_iter_t	*propIter = NULL;
16607836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
16617836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
16627836SJohn.Forte@Sun.COM 	int memberCnt = 0;
16637836SJohn.Forte@Sun.COM 	int i = 0;
16647836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
16657836SJohn.Forte@Sun.COM 
16667836SJohn.Forte@Sun.COM 	assert(groupList != NULL);
16677836SJohn.Forte@Sun.COM 
16687836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
16697836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
16707836SJohn.Forte@Sun.COM 		goto out;
16717836SJohn.Forte@Sun.COM 	}
16727836SJohn.Forte@Sun.COM 
16737836SJohn.Forte@Sun.COM 	/*
16747836SJohn.Forte@Sun.COM 	 * Allocate scf resources
16757836SJohn.Forte@Sun.COM 	 */
16767836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
16777836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
16787836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
16797836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
16807836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
16817836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
16827836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
16837836SJohn.Forte@Sun.COM 		goto out;
16847836SJohn.Forte@Sun.COM 	}
16857836SJohn.Forte@Sun.COM 
16867836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
16877836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
16887836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
16897836SJohn.Forte@Sun.COM 		} else {
16907836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
16917836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
16927836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
16937836SJohn.Forte@Sun.COM 		}
16947836SJohn.Forte@Sun.COM 		goto out;
16957836SJohn.Forte@Sun.COM 	}
16967836SJohn.Forte@Sun.COM 
16977836SJohn.Forte@Sun.COM 	/*
16987836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
16997836SJohn.Forte@Sun.COM 	 */
17007836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
17017836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
17027836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
17037836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
17047836SJohn.Forte@Sun.COM 		goto out;
17057836SJohn.Forte@Sun.COM 	}
17067836SJohn.Forte@Sun.COM 
17077836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
17087836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) {
17097836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
17107836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
17117836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
17127836SJohn.Forte@Sun.COM 			break;
17137836SJohn.Forte@Sun.COM 		}
17147836SJohn.Forte@Sun.COM 		/*
17157836SJohn.Forte@Sun.COM 		 * Skip over member list properties
17167836SJohn.Forte@Sun.COM 		 */
17177836SJohn.Forte@Sun.COM 		if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) {
17187836SJohn.Forte@Sun.COM 			continue;
17197836SJohn.Forte@Sun.COM 		}
17207836SJohn.Forte@Sun.COM 		memberCnt++;
17217836SJohn.Forte@Sun.COM 	}
17227836SJohn.Forte@Sun.COM 
17237836SJohn.Forte@Sun.COM 	/*
17247836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
17257836SJohn.Forte@Sun.COM 	 */
17267836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
17277836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
17287836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
17297836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
17307836SJohn.Forte@Sun.COM 		goto out;
17317836SJohn.Forte@Sun.COM 	}
17327836SJohn.Forte@Sun.COM 
17337836SJohn.Forte@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
17347836SJohn.Forte@Sun.COM 	    memberCnt * sizeof (stmfGroupName));
17357836SJohn.Forte@Sun.COM 
17367836SJohn.Forte@Sun.COM 	if (*groupList == NULL) {
17377836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
17387836SJohn.Forte@Sun.COM 		goto out;
17397836SJohn.Forte@Sun.COM 	}
17407836SJohn.Forte@Sun.COM 
17417836SJohn.Forte@Sun.COM 	/*
17427836SJohn.Forte@Sun.COM 	 * In order to get a list of groups, simply get all of the
17437836SJohn.Forte@Sun.COM 	 * properties that are not member list properties, i.e. the group
17447836SJohn.Forte@Sun.COM 	 * name properties.
17457836SJohn.Forte@Sun.COM 	 * It's possible for this list to grow beyond what was originally
17467836SJohn.Forte@Sun.COM 	 * read so just ensure we're not writing beyond our allocated buffer
17477836SJohn.Forte@Sun.COM 	 * by ensuring i < memberCnt
17487836SJohn.Forte@Sun.COM 	 */
17497836SJohn.Forte@Sun.COM 	while ((scf_iter_next_property(propIter, prop) == 1) &&
17507836SJohn.Forte@Sun.COM 	    (i < memberCnt)) {
17517836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) {
17527836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
17537836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
17547836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
17557836SJohn.Forte@Sun.COM 			break;
17567836SJohn.Forte@Sun.COM 		}
17577836SJohn.Forte@Sun.COM 		/*
17587836SJohn.Forte@Sun.COM 		 * Skip over member list properties
17597836SJohn.Forte@Sun.COM 		 */
17607836SJohn.Forte@Sun.COM 		if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) {
17617836SJohn.Forte@Sun.COM 			continue;
17627836SJohn.Forte@Sun.COM 		}
17637836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
17647836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
17657836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
17667836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
17677836SJohn.Forte@Sun.COM 			break;
17687836SJohn.Forte@Sun.COM 		}
17697836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) {
17707836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get ustring failed - %s",
17717836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
17727836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
17737836SJohn.Forte@Sun.COM 			break;
17747836SJohn.Forte@Sun.COM 		}
17757836SJohn.Forte@Sun.COM 		bcopy(buf, (*groupList)->name[i++], strlen(buf));
17767836SJohn.Forte@Sun.COM 		(*groupList)->cnt++;
17777836SJohn.Forte@Sun.COM 	}
17787836SJohn.Forte@Sun.COM 
17797836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
17807836SJohn.Forte@Sun.COM 		free(*groupList);
17817836SJohn.Forte@Sun.COM 		goto out;
17827836SJohn.Forte@Sun.COM 	}
17837836SJohn.Forte@Sun.COM 
17847836SJohn.Forte@Sun.COM out:
17857836SJohn.Forte@Sun.COM 	/*
17867836SJohn.Forte@Sun.COM 	 * Free resources
17877836SJohn.Forte@Sun.COM 	 */
17887836SJohn.Forte@Sun.COM 	if (handle != NULL) {
17897836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
17907836SJohn.Forte@Sun.COM 	}
17917836SJohn.Forte@Sun.COM 	if (svc != NULL) {
17927836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
17937836SJohn.Forte@Sun.COM 	}
17947836SJohn.Forte@Sun.COM 	if (pg != NULL) {
17957836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
17967836SJohn.Forte@Sun.COM 	}
17977836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
17987836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
17997836SJohn.Forte@Sun.COM 	}
18007836SJohn.Forte@Sun.COM 	if (prop != NULL) {
18017836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
18027836SJohn.Forte@Sun.COM 	}
18037836SJohn.Forte@Sun.COM 	if (value != NULL) {
18047836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
18057836SJohn.Forte@Sun.COM 	}
18067836SJohn.Forte@Sun.COM 
18077836SJohn.Forte@Sun.COM 	return (ret);
18087836SJohn.Forte@Sun.COM }
18097836SJohn.Forte@Sun.COM 
18107836SJohn.Forte@Sun.COM /*
18117836SJohn.Forte@Sun.COM  * iPsGetGroupMemberList
18127836SJohn.Forte@Sun.COM  *
18137836SJohn.Forte@Sun.COM  * pgName - Property group name
18147836SJohn.Forte@Sun.COM  * groupName - group name (host group or target group)
18157836SJohn.Forte@Sun.COM  * groupMemberList - pointer to pointer to stmfGroupProperties structure. On
18167836SJohn.Forte@Sun.COM  * success, contains the list of group members
18177836SJohn.Forte@Sun.COM  *
18187836SJohn.Forte@Sun.COM  * returns:
18197836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
18207836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
18217836SJohn.Forte@Sun.COM  */
18227836SJohn.Forte@Sun.COM static int
18237836SJohn.Forte@Sun.COM iPsGetGroupMemberList(char *pgName, char *groupName,
18247836SJohn.Forte@Sun.COM     stmfGroupProperties **groupMemberList)
18257836SJohn.Forte@Sun.COM {
18267836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
18277836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
18287836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
18297836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
18307836SJohn.Forte@Sun.COM 	scf_value_t	*valueLookup = NULL;
18317836SJohn.Forte@Sun.COM 	scf_iter_t	*valueIter = NULL;
18327836SJohn.Forte@Sun.COM 	int i = 0;
18337836SJohn.Forte@Sun.COM 	int memberCnt;
18347836SJohn.Forte@Sun.COM 	int len;
18357836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
18367836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
18377836SJohn.Forte@Sun.COM 
18387836SJohn.Forte@Sun.COM 	assert(pgName != NULL && groupName != NULL);
18397836SJohn.Forte@Sun.COM 
18407836SJohn.Forte@Sun.COM 	/*
18417836SJohn.Forte@Sun.COM 	 * init the service handle
18427836SJohn.Forte@Sun.COM 	 */
18437836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
18447836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
18457836SJohn.Forte@Sun.COM 		goto out;
18467836SJohn.Forte@Sun.COM 	}
18477836SJohn.Forte@Sun.COM 
18487836SJohn.Forte@Sun.COM 	/*
18497836SJohn.Forte@Sun.COM 	 * Allocate scf resources
18507836SJohn.Forte@Sun.COM 	 */
18517836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
18527836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
18537836SJohn.Forte@Sun.COM 	    ((valueIter = scf_iter_create(handle)) == NULL) ||
18547836SJohn.Forte@Sun.COM 	    ((valueLookup = scf_value_create(handle)) == NULL)) {
18557836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
18567836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
18577836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
18587836SJohn.Forte@Sun.COM 		goto out;
18597836SJohn.Forte@Sun.COM 	}
18607836SJohn.Forte@Sun.COM 
18617836SJohn.Forte@Sun.COM 	/*
18627836SJohn.Forte@Sun.COM 	 * get the service property group handle
18637836SJohn.Forte@Sun.COM 	 */
18647836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
18657836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
18667836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
18677836SJohn.Forte@Sun.COM 		} else {
18687836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
18697836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
18707836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
18717836SJohn.Forte@Sun.COM 		}
18727836SJohn.Forte@Sun.COM 		goto out;
18737836SJohn.Forte@Sun.COM 	}
18747836SJohn.Forte@Sun.COM 
18757836SJohn.Forte@Sun.COM 	/*
18767836SJohn.Forte@Sun.COM 	 * Get the property handle
18777836SJohn.Forte@Sun.COM 	 * based on the target or host group name
18787836SJohn.Forte@Sun.COM 	 */
18797836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, groupName, prop) == -1) {
18807836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
18817836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
18827836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
18837836SJohn.Forte@Sun.COM 		goto out;
18847836SJohn.Forte@Sun.COM 	}
18857836SJohn.Forte@Sun.COM 
18867836SJohn.Forte@Sun.COM 	/*
18877836SJohn.Forte@Sun.COM 	 * valueIter is the iterator handle
18887836SJohn.Forte@Sun.COM 	 */
18897836SJohn.Forte@Sun.COM 	if (scf_iter_property_values(valueIter, prop) == -1) {
18907836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter value failed - %s",
18917836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
18927836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
18937836SJohn.Forte@Sun.COM 		goto out;
18947836SJohn.Forte@Sun.COM 	}
18957836SJohn.Forte@Sun.COM 
18967836SJohn.Forte@Sun.COM 	while (scf_iter_next_value(valueIter, valueLookup) == 1) {
18977836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
18987836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
18997836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
19007836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
19017836SJohn.Forte@Sun.COM 			break;
19027836SJohn.Forte@Sun.COM 		}
19037836SJohn.Forte@Sun.COM 		i++;
19047836SJohn.Forte@Sun.COM 	}
19057836SJohn.Forte@Sun.COM 
19067836SJohn.Forte@Sun.COM 	/*
19077836SJohn.Forte@Sun.COM 	 * valueIter is the iterator handle
19087836SJohn.Forte@Sun.COM 	 */
19097836SJohn.Forte@Sun.COM 	if (scf_iter_property_values(valueIter, prop) == -1) {
19107836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter value failed - %s",
19117836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
19127836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
19137836SJohn.Forte@Sun.COM 		goto out;
19147836SJohn.Forte@Sun.COM 	}
19157836SJohn.Forte@Sun.COM 
19167836SJohn.Forte@Sun.COM 	memberCnt = i;
19177836SJohn.Forte@Sun.COM 
19187836SJohn.Forte@Sun.COM 	*groupMemberList = (stmfGroupProperties *)calloc(1,
19197836SJohn.Forte@Sun.COM 	    sizeof (stmfGroupProperties) + memberCnt * sizeof (stmfDevid));
19207836SJohn.Forte@Sun.COM 	if (*groupMemberList == NULL) {
19217836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
19227836SJohn.Forte@Sun.COM 		goto out;
19237836SJohn.Forte@Sun.COM 	}
19247836SJohn.Forte@Sun.COM 
19257836SJohn.Forte@Sun.COM 	i = 0;
19267836SJohn.Forte@Sun.COM 	while ((scf_iter_next_value(valueIter, valueLookup) == 1) &&
19277836SJohn.Forte@Sun.COM 	    (i < memberCnt)) {
19287836SJohn.Forte@Sun.COM 		if ((len = scf_value_get_ustring(valueLookup, buf, MAXNAMELEN))
19297836SJohn.Forte@Sun.COM 		    == -1) {
19307836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
19317836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
19327836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
19337836SJohn.Forte@Sun.COM 			break;
19347836SJohn.Forte@Sun.COM 		}
19357836SJohn.Forte@Sun.COM 		if (len < sizeof (stmfDevid) - 1) {
19367836SJohn.Forte@Sun.COM 			(*groupMemberList)->name[i].identLength = len;
19377836SJohn.Forte@Sun.COM 			bcopy(buf,
19387836SJohn.Forte@Sun.COM 			    (*groupMemberList)->name[i++].ident, len);
19397836SJohn.Forte@Sun.COM 			(*groupMemberList)->cnt++;
19407836SJohn.Forte@Sun.COM 		} else {
19417836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
19427836SJohn.Forte@Sun.COM 			break;
19437836SJohn.Forte@Sun.COM 		}
19447836SJohn.Forte@Sun.COM 	}
19457836SJohn.Forte@Sun.COM 
19467836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
19477836SJohn.Forte@Sun.COM 		free(*groupMemberList);
19487836SJohn.Forte@Sun.COM 		goto out;
19497836SJohn.Forte@Sun.COM 	}
19507836SJohn.Forte@Sun.COM 
19517836SJohn.Forte@Sun.COM out:
19527836SJohn.Forte@Sun.COM 	/*
19537836SJohn.Forte@Sun.COM 	 * Free resources
19547836SJohn.Forte@Sun.COM 	 */
19557836SJohn.Forte@Sun.COM 	if (handle != NULL) {
19567836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
19577836SJohn.Forte@Sun.COM 	}
19587836SJohn.Forte@Sun.COM 	if (svc != NULL) {
19597836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
19607836SJohn.Forte@Sun.COM 	}
19617836SJohn.Forte@Sun.COM 	if (pg != NULL) {
19627836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
19637836SJohn.Forte@Sun.COM 	}
19647836SJohn.Forte@Sun.COM 	if (prop != NULL) {
19657836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
19667836SJohn.Forte@Sun.COM 	}
19677836SJohn.Forte@Sun.COM 	if (valueLookup != NULL) {
19687836SJohn.Forte@Sun.COM 		scf_value_destroy(valueLookup);
19697836SJohn.Forte@Sun.COM 	}
19707836SJohn.Forte@Sun.COM 	if (valueIter != NULL) {
19717836SJohn.Forte@Sun.COM 		scf_iter_destroy(valueIter);
19727836SJohn.Forte@Sun.COM 	}
19737836SJohn.Forte@Sun.COM 
19747836SJohn.Forte@Sun.COM 	return (ret);
19757836SJohn.Forte@Sun.COM }
19767836SJohn.Forte@Sun.COM 
1977*9585STim.Szeto@Sun.COM int
1978*9585STim.Szeto@Sun.COM psGetServicePersist(uint8_t *persistType)
1979*9585STim.Szeto@Sun.COM {
1980*9585STim.Szeto@Sun.COM 	scf_handle_t	*handle = NULL;
1981*9585STim.Szeto@Sun.COM 	scf_service_t	*svc = NULL;
1982*9585STim.Szeto@Sun.COM 	int ret;
1983*9585STim.Szeto@Sun.COM 
1984*9585STim.Szeto@Sun.COM 
1985*9585STim.Szeto@Sun.COM 	ret = iPsInit(&handle, &svc);
1986*9585STim.Szeto@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1987*9585STim.Szeto@Sun.COM 		return (STMF_PS_ERROR);
1988*9585STim.Szeto@Sun.COM 	}
1989*9585STim.Szeto@Sun.COM 
1990*9585STim.Szeto@Sun.COM 	ret = iPsGetSetPersistType(persistType, handle, svc, GET);
1991*9585STim.Szeto@Sun.COM 
1992*9585STim.Szeto@Sun.COM 	/*
1993*9585STim.Szeto@Sun.COM 	 * Free resources
1994*9585STim.Szeto@Sun.COM 	 */
1995*9585STim.Szeto@Sun.COM 	if (handle != NULL) {
1996*9585STim.Szeto@Sun.COM 		scf_handle_destroy(handle);
1997*9585STim.Szeto@Sun.COM 	}
1998*9585STim.Szeto@Sun.COM 	if (svc != NULL) {
1999*9585STim.Szeto@Sun.COM 		scf_service_destroy(svc);
2000*9585STim.Szeto@Sun.COM 	}
2001*9585STim.Szeto@Sun.COM 	return (ret);
2002*9585STim.Szeto@Sun.COM }
2003*9585STim.Szeto@Sun.COM 
2004*9585STim.Szeto@Sun.COM int
2005*9585STim.Szeto@Sun.COM psSetServicePersist(uint8_t persistType)
2006*9585STim.Szeto@Sun.COM {
2007*9585STim.Szeto@Sun.COM 	scf_handle_t	*handle = NULL;
2008*9585STim.Szeto@Sun.COM 	scf_service_t	*svc = NULL;
2009*9585STim.Szeto@Sun.COM 	int ret;
2010*9585STim.Szeto@Sun.COM 
2011*9585STim.Szeto@Sun.COM 
2012*9585STim.Szeto@Sun.COM 	ret = iPsInit(&handle, &svc);
2013*9585STim.Szeto@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2014*9585STim.Szeto@Sun.COM 		return (STMF_PS_ERROR);
2015*9585STim.Szeto@Sun.COM 	}
2016*9585STim.Szeto@Sun.COM 
2017*9585STim.Szeto@Sun.COM 	ret = iPsGetSetPersistType(&persistType, handle, svc, SET);
2018*9585STim.Szeto@Sun.COM 
2019*9585STim.Szeto@Sun.COM 	/*
2020*9585STim.Szeto@Sun.COM 	 * Free resources
2021*9585STim.Szeto@Sun.COM 	 */
2022*9585STim.Szeto@Sun.COM 	if (handle != NULL) {
2023*9585STim.Szeto@Sun.COM 		scf_handle_destroy(handle);
2024*9585STim.Szeto@Sun.COM 	}
2025*9585STim.Szeto@Sun.COM 	if (svc != NULL) {
2026*9585STim.Szeto@Sun.COM 		scf_service_destroy(svc);
2027*9585STim.Szeto@Sun.COM 	}
2028*9585STim.Szeto@Sun.COM 	return (ret);
2029*9585STim.Szeto@Sun.COM }
2030*9585STim.Szeto@Sun.COM 
2031*9585STim.Szeto@Sun.COM static int
2032*9585STim.Szeto@Sun.COM iPsGetSetPersistType(uint8_t *persistType, scf_handle_t *handle,
2033*9585STim.Szeto@Sun.COM scf_service_t *svc, int getSet)
2034*9585STim.Szeto@Sun.COM {
2035*9585STim.Szeto@Sun.COM 	scf_propertygroup_t	*pg = NULL;
2036*9585STim.Szeto@Sun.COM 	scf_property_t	*prop = NULL;
2037*9585STim.Szeto@Sun.COM 	scf_value_t	*value = NULL;
2038*9585STim.Szeto@Sun.COM 	scf_transaction_t *tran = NULL;
2039*9585STim.Szeto@Sun.COM 	scf_transaction_entry_t *entry = NULL;
2040*9585STim.Szeto@Sun.COM 	char iPersistTypeGet[MAXNAMELEN] = {0};
2041*9585STim.Szeto@Sun.COM 	char *iPersistType;
2042*9585STim.Szeto@Sun.COM 	int ret = STMF_PS_SUCCESS;
2043*9585STim.Szeto@Sun.COM 	int commitRet;
2044*9585STim.Szeto@Sun.COM 
2045*9585STim.Szeto@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
2046*9585STim.Szeto@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
2047*9585STim.Szeto@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
2048*9585STim.Szeto@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
2049*9585STim.Szeto@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
2050*9585STim.Szeto@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
2051*9585STim.Szeto@Sun.COM 		    scf_strerror(scf_error()));
2052*9585STim.Szeto@Sun.COM 		ret = STMF_PS_ERROR;
2053*9585STim.Szeto@Sun.COM 		goto out;
2054*9585STim.Szeto@Sun.COM 	}
2055*9585STim.Szeto@Sun.COM 
2056*9585STim.Szeto@Sun.COM 	if (getSet == GET) {
2057*9585STim.Szeto@Sun.COM 		/* set to default */
2058*9585STim.Szeto@Sun.COM 		*persistType = STMF_PERSIST_SMF;
2059*9585STim.Szeto@Sun.COM 		iPersistType = STMF_PS_PERSIST_SMF;
2060*9585STim.Szeto@Sun.COM 	}
2061*9585STim.Szeto@Sun.COM 
2062*9585STim.Szeto@Sun.COM 	if (getSet == SET) {
2063*9585STim.Szeto@Sun.COM 		if (*persistType == STMF_PERSIST_SMF) {
2064*9585STim.Szeto@Sun.COM 			iPersistType = STMF_PS_PERSIST_SMF;
2065*9585STim.Szeto@Sun.COM 		} else if (*persistType == STMF_PERSIST_NONE) {
2066*9585STim.Szeto@Sun.COM 			iPersistType = STMF_PS_PERSIST_NONE;
2067*9585STim.Szeto@Sun.COM 		} else {
2068*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2069*9585STim.Szeto@Sun.COM 			goto out;
2070*9585STim.Szeto@Sun.COM 		}
2071*9585STim.Szeto@Sun.COM 	}
2072*9585STim.Szeto@Sun.COM 
2073*9585STim.Szeto@Sun.COM 	/*
2074*9585STim.Szeto@Sun.COM 	 * get stmf data property group
2075*9585STim.Szeto@Sun.COM 	 */
2076*9585STim.Szeto@Sun.COM 	if (scf_service_get_pg(svc, STMF_DATA_GROUP, pg) == -1) {
2077*9585STim.Szeto@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
2078*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
2079*9585STim.Szeto@Sun.COM 		} else {
2080*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
2081*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2082*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2083*9585STim.Szeto@Sun.COM 		}
2084*9585STim.Szeto@Sun.COM 		goto out;
2085*9585STim.Szeto@Sun.COM 	}
2086*9585STim.Szeto@Sun.COM 
2087*9585STim.Szeto@Sun.COM 	/* find persistence property */
2088*9585STim.Szeto@Sun.COM 	/*
2089*9585STim.Szeto@Sun.COM 	 * Get the persistence property
2090*9585STim.Szeto@Sun.COM 	 */
2091*9585STim.Szeto@Sun.COM 	if (scf_pg_get_property(pg, STMF_PERSIST_TYPE, prop) == -1) {
2092*9585STim.Szeto@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
2093*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
2094*9585STim.Szeto@Sun.COM 		} else {
2095*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
2096*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2097*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2098*9585STim.Szeto@Sun.COM 			goto out;
2099*9585STim.Szeto@Sun.COM 		}
2100*9585STim.Szeto@Sun.COM 	}
2101*9585STim.Szeto@Sun.COM 
2102*9585STim.Szeto@Sun.COM 	/* no persist property found */
2103*9585STim.Szeto@Sun.COM 	if (ret == STMF_PS_ERROR_NOT_FOUND || getSet == SET) {
2104*9585STim.Szeto@Sun.COM 		/*
2105*9585STim.Szeto@Sun.COM 		 * If we have no persistType property, go ahead
2106*9585STim.Szeto@Sun.COM 		 * and create it with the user specified value or
2107*9585STim.Szeto@Sun.COM 		 * the default value.
2108*9585STim.Szeto@Sun.COM 		 */
2109*9585STim.Szeto@Sun.COM 		/*
2110*9585STim.Szeto@Sun.COM 		 * Begin the transaction
2111*9585STim.Szeto@Sun.COM 		 */
2112*9585STim.Szeto@Sun.COM 		if (scf_transaction_start(tran, pg) == -1) {
2113*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "start transaction failed - %s",
2114*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2115*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2116*9585STim.Szeto@Sun.COM 			goto out;
2117*9585STim.Szeto@Sun.COM 		}
2118*9585STim.Szeto@Sun.COM 
2119*9585STim.Szeto@Sun.COM 		/* is this a SET or GET w/error? */
2120*9585STim.Szeto@Sun.COM 		if (ret) {
2121*9585STim.Szeto@Sun.COM 			if (scf_transaction_property_new(tran, entry,
2122*9585STim.Szeto@Sun.COM 			    STMF_PERSIST_TYPE, SCF_TYPE_ASTRING) == -1) {
2123*9585STim.Szeto@Sun.COM 				syslog(LOG_ERR,
2124*9585STim.Szeto@Sun.COM 				    "transaction property new failed - %s",
2125*9585STim.Szeto@Sun.COM 				    scf_strerror(scf_error()));
2126*9585STim.Szeto@Sun.COM 				ret = STMF_PS_ERROR;
2127*9585STim.Szeto@Sun.COM 				goto out;
2128*9585STim.Szeto@Sun.COM 			}
2129*9585STim.Szeto@Sun.COM 		} else {
2130*9585STim.Szeto@Sun.COM 			if (scf_transaction_property_change(tran, entry,
2131*9585STim.Szeto@Sun.COM 			    STMF_PERSIST_TYPE, SCF_TYPE_ASTRING) == -1) {
2132*9585STim.Szeto@Sun.COM 				syslog(LOG_ERR,
2133*9585STim.Szeto@Sun.COM 				    "transaction property change failed - %s",
2134*9585STim.Szeto@Sun.COM 				    scf_strerror(scf_error()));
2135*9585STim.Szeto@Sun.COM 				ret = STMF_PS_ERROR;
2136*9585STim.Szeto@Sun.COM 				goto out;
2137*9585STim.Szeto@Sun.COM 			}
2138*9585STim.Szeto@Sun.COM 		}
2139*9585STim.Szeto@Sun.COM 
2140*9585STim.Szeto@Sun.COM 		/*
2141*9585STim.Szeto@Sun.COM 		 * set the persist type
2142*9585STim.Szeto@Sun.COM 		 */
2143*9585STim.Szeto@Sun.COM 		if (scf_value_set_astring(value, iPersistType) == -1) {
2144*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
2145*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2146*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2147*9585STim.Szeto@Sun.COM 			goto out;
2148*9585STim.Szeto@Sun.COM 		}
2149*9585STim.Szeto@Sun.COM 
2150*9585STim.Szeto@Sun.COM 		/*
2151*9585STim.Szeto@Sun.COM 		 * add the value to the transaction
2152*9585STim.Szeto@Sun.COM 		 */
2153*9585STim.Szeto@Sun.COM 		if (scf_entry_add_value(entry, value) == -1) {
2154*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
2155*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2156*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2157*9585STim.Szeto@Sun.COM 			goto out;
2158*9585STim.Szeto@Sun.COM 		}
2159*9585STim.Szeto@Sun.COM 		if ((commitRet = scf_transaction_commit(tran)) != 1) {
2160*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "transaction commit failed - %s",
2161*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2162*9585STim.Szeto@Sun.COM 			if (commitRet == 0) {
2163*9585STim.Szeto@Sun.COM 				ret = STMF_PS_ERROR_BUSY;
2164*9585STim.Szeto@Sun.COM 			} else {
2165*9585STim.Szeto@Sun.COM 				ret = STMF_PS_ERROR;
2166*9585STim.Szeto@Sun.COM 			}
2167*9585STim.Szeto@Sun.COM 			goto out;
2168*9585STim.Szeto@Sun.COM 		}
2169*9585STim.Szeto@Sun.COM 		/* reset return value */
2170*9585STim.Szeto@Sun.COM 		ret = STMF_PS_SUCCESS;
2171*9585STim.Szeto@Sun.COM 	} else if (getSet == GET) {
2172*9585STim.Szeto@Sun.COM 		/* get the persist property */
2173*9585STim.Szeto@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
2174*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
2175*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2176*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2177*9585STim.Szeto@Sun.COM 			goto out;
2178*9585STim.Szeto@Sun.COM 		}
2179*9585STim.Szeto@Sun.COM 
2180*9585STim.Szeto@Sun.COM 		/*
2181*9585STim.Szeto@Sun.COM 		 * Get the value of the persist property
2182*9585STim.Szeto@Sun.COM 		 */
2183*9585STim.Szeto@Sun.COM 		if (scf_value_get_astring(value, iPersistTypeGet, MAXNAMELEN)
2184*9585STim.Szeto@Sun.COM 		    == -1) {
2185*9585STim.Szeto@Sun.COM 			syslog(LOG_ERR, "get count value failed - %s",
2186*9585STim.Szeto@Sun.COM 			    scf_strerror(scf_error()));
2187*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2188*9585STim.Szeto@Sun.COM 			goto out;
2189*9585STim.Szeto@Sun.COM 		}
2190*9585STim.Szeto@Sun.COM 	}
2191*9585STim.Szeto@Sun.COM 
2192*9585STim.Szeto@Sun.COM 	if (getSet == GET) {
2193*9585STim.Szeto@Sun.COM 		if (strcmp(iPersistTypeGet, STMF_PS_PERSIST_NONE) == 0) {
2194*9585STim.Szeto@Sun.COM 			*persistType = STMF_PERSIST_NONE;
2195*9585STim.Szeto@Sun.COM 		} else if (strcmp(iPersistTypeGet, STMF_PS_PERSIST_SMF) == 0) {
2196*9585STim.Szeto@Sun.COM 			*persistType = STMF_PERSIST_SMF;
2197*9585STim.Szeto@Sun.COM 		} else {
2198*9585STim.Szeto@Sun.COM 			ret = STMF_PS_ERROR;
2199*9585STim.Szeto@Sun.COM 			goto out;
2200*9585STim.Szeto@Sun.COM 		}
2201*9585STim.Szeto@Sun.COM 	}
2202*9585STim.Szeto@Sun.COM out:
2203*9585STim.Szeto@Sun.COM 	/*
2204*9585STim.Szeto@Sun.COM 	 * Free resources.
2205*9585STim.Szeto@Sun.COM 	 * handle and svc should not be free'd here. They're
2206*9585STim.Szeto@Sun.COM 	 * free'd elsewhere
2207*9585STim.Szeto@Sun.COM 	 */
2208*9585STim.Szeto@Sun.COM 	if (pg != NULL) {
2209*9585STim.Szeto@Sun.COM 		scf_pg_destroy(pg);
2210*9585STim.Szeto@Sun.COM 	}
2211*9585STim.Szeto@Sun.COM 	if (prop != NULL) {
2212*9585STim.Szeto@Sun.COM 		scf_property_destroy(prop);
2213*9585STim.Szeto@Sun.COM 	}
2214*9585STim.Szeto@Sun.COM 	if (entry != NULL) {
2215*9585STim.Szeto@Sun.COM 		scf_entry_destroy(entry);
2216*9585STim.Szeto@Sun.COM 	}
2217*9585STim.Szeto@Sun.COM 	if (tran != NULL) {
2218*9585STim.Szeto@Sun.COM 		scf_transaction_destroy(tran);
2219*9585STim.Szeto@Sun.COM 	}
2220*9585STim.Szeto@Sun.COM 	if (value != NULL) {
2221*9585STim.Szeto@Sun.COM 		scf_value_destroy(value);
2222*9585STim.Szeto@Sun.COM 	}
2223*9585STim.Szeto@Sun.COM 	return (ret);
2224*9585STim.Szeto@Sun.COM }
2225*9585STim.Szeto@Sun.COM 
22267836SJohn.Forte@Sun.COM /*
22277836SJohn.Forte@Sun.COM  * Initialize scf stmf service access
22287836SJohn.Forte@Sun.COM  * handle - returned handle
22297836SJohn.Forte@Sun.COM  * service - returned service handle
22307836SJohn.Forte@Sun.COM  *
22317836SJohn.Forte@Sun.COM  * Both handle and service must be destroyed by the caller
22327836SJohn.Forte@Sun.COM  */
22337836SJohn.Forte@Sun.COM static int
22347836SJohn.Forte@Sun.COM iPsInit(scf_handle_t **handle, scf_service_t **service)
22357836SJohn.Forte@Sun.COM {
22367836SJohn.Forte@Sun.COM 	scf_scope_t	*scope = NULL;
22377836SJohn.Forte@Sun.COM 	uint64_t version;
22387836SJohn.Forte@Sun.COM 	int ret;
22397836SJohn.Forte@Sun.COM 
22407836SJohn.Forte@Sun.COM 	assert(handle != NULL && service != NULL);
22417836SJohn.Forte@Sun.COM 
22427836SJohn.Forte@Sun.COM 	if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
22437836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_handle_create failed - %s",
22447836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
22457836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
22467836SJohn.Forte@Sun.COM 		goto err;
22477836SJohn.Forte@Sun.COM 	}
22487836SJohn.Forte@Sun.COM 
22497836SJohn.Forte@Sun.COM 	if (scf_handle_bind(*handle) == -1) {
22507836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_handle_bind failed - %s",
22517836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
22527836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
22537836SJohn.Forte@Sun.COM 		goto err;
22547836SJohn.Forte@Sun.COM 	}
22557836SJohn.Forte@Sun.COM 
22567836SJohn.Forte@Sun.COM 	if ((*service = scf_service_create(*handle)) == NULL) {
22577836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_service_create failed - %s",
22587836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
22597836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
22607836SJohn.Forte@Sun.COM 		goto err;
22617836SJohn.Forte@Sun.COM 	}
22627836SJohn.Forte@Sun.COM 
22637836SJohn.Forte@Sun.COM 	if ((scope = scf_scope_create(*handle)) == NULL) {
22647836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_scope_create failed - %s",
22657836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
22667836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
22677836SJohn.Forte@Sun.COM 		goto err;
22687836SJohn.Forte@Sun.COM 	}
22697836SJohn.Forte@Sun.COM 
22707836SJohn.Forte@Sun.COM 	if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
22717836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
22727836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
22737836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
22747836SJohn.Forte@Sun.COM 		goto err;
22757836SJohn.Forte@Sun.COM 	}
22767836SJohn.Forte@Sun.COM 
22777836SJohn.Forte@Sun.COM 	if (scf_scope_get_service(scope, STMF_SERVICE, *service) == -1) {
22787836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_scope_get_service failed - %s",
22797836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
22807836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_SERVICE_NOT_FOUND;
22817836SJohn.Forte@Sun.COM 		goto err;
22827836SJohn.Forte@Sun.COM 	}
22837836SJohn.Forte@Sun.COM 
22847836SJohn.Forte@Sun.COM 
22857836SJohn.Forte@Sun.COM 	/*
22867836SJohn.Forte@Sun.COM 	 * Get and check the version number
22877836SJohn.Forte@Sun.COM 	 */
22887836SJohn.Forte@Sun.COM 	ret = iPsGetServiceVersion(&version, *handle, *service);
22897836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
22907836SJohn.Forte@Sun.COM 		goto err;
22917836SJohn.Forte@Sun.COM 	}
22927836SJohn.Forte@Sun.COM 
22937836SJohn.Forte@Sun.COM 	if (version != STMF_SMF_VERSION) {
22947836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_VERSION_MISMATCH;
22957836SJohn.Forte@Sun.COM 		goto err;
22967836SJohn.Forte@Sun.COM 	}
22977836SJohn.Forte@Sun.COM 
22987836SJohn.Forte@Sun.COM 	/* we only need destroy the scope here */
22997836SJohn.Forte@Sun.COM 	scf_scope_destroy(scope);
23007836SJohn.Forte@Sun.COM 
23017836SJohn.Forte@Sun.COM 	return (STMF_PS_SUCCESS);
23027836SJohn.Forte@Sun.COM 
23037836SJohn.Forte@Sun.COM err:
23047836SJohn.Forte@Sun.COM 	if (*handle != NULL) {
23057836SJohn.Forte@Sun.COM 		scf_handle_destroy(*handle);
23067836SJohn.Forte@Sun.COM 	}
23077836SJohn.Forte@Sun.COM 	if (*service != NULL) {
23087836SJohn.Forte@Sun.COM 		scf_service_destroy(*service);
23097836SJohn.Forte@Sun.COM 		*service = NULL;
23107836SJohn.Forte@Sun.COM 	}
23117836SJohn.Forte@Sun.COM 	if (scope != NULL) {
23127836SJohn.Forte@Sun.COM 		scf_scope_destroy(scope);
23137836SJohn.Forte@Sun.COM 	}
23147836SJohn.Forte@Sun.COM 	return (ret);
23157836SJohn.Forte@Sun.COM }
23167836SJohn.Forte@Sun.COM 
2317*9585STim.Szeto@Sun.COM 
23187836SJohn.Forte@Sun.COM /*
23197836SJohn.Forte@Sun.COM  * called by iPsInit only
23207836SJohn.Forte@Sun.COM  * iPsGetServiceVersion
23217836SJohn.Forte@Sun.COM  */
23227836SJohn.Forte@Sun.COM static int
23237836SJohn.Forte@Sun.COM iPsGetServiceVersion(uint64_t *version, scf_handle_t *handle,
23247836SJohn.Forte@Sun.COM scf_service_t *svc)
23257836SJohn.Forte@Sun.COM {
23267836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
23277836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
23287836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
23297836SJohn.Forte@Sun.COM 	scf_transaction_t *tran = NULL;
23307836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry = NULL;
23317836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
23327836SJohn.Forte@Sun.COM 	int commitRet;
23337836SJohn.Forte@Sun.COM 
23347836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
23357836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
23367836SJohn.Forte@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
23377836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
23387836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
23397836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
23407836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
23417836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
23427836SJohn.Forte@Sun.COM 		goto out;
23437836SJohn.Forte@Sun.COM 	}
23447836SJohn.Forte@Sun.COM 
23457836SJohn.Forte@Sun.COM 	*version = STMF_SMF_VERSION;
23467836SJohn.Forte@Sun.COM 
23477836SJohn.Forte@Sun.COM 	/*
23487836SJohn.Forte@Sun.COM 	 * get stmf data property group
23497836SJohn.Forte@Sun.COM 	 */
23507836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, STMF_DATA_GROUP, pg) == -1) {
23517836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
23527836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
23537836SJohn.Forte@Sun.COM 		} else {
23547836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
23557836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
23567836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
23577836SJohn.Forte@Sun.COM 			goto out;
23587836SJohn.Forte@Sun.COM 		}
23597836SJohn.Forte@Sun.COM 	}
23607836SJohn.Forte@Sun.COM 
23617836SJohn.Forte@Sun.COM 	/* create the group */
23627836SJohn.Forte@Sun.COM 	if (ret == STMF_PS_ERROR_NOT_FOUND) {
23637836SJohn.Forte@Sun.COM 		/*
23647836SJohn.Forte@Sun.COM 		 * create the property group.
23657836SJohn.Forte@Sun.COM 		 */
23667836SJohn.Forte@Sun.COM 		if (scf_service_add_pg(svc, STMF_DATA_GROUP,
23677836SJohn.Forte@Sun.COM 		    SCF_GROUP_APPLICATION, 0, pg) == -1) {
23687836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add pg failed - %s",
23697836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
23707836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
23717836SJohn.Forte@Sun.COM 			goto out;
23727836SJohn.Forte@Sun.COM 		}
23737836SJohn.Forte@Sun.COM 		/* reset return value */
23747836SJohn.Forte@Sun.COM 		ret = STMF_PS_SUCCESS;
23757836SJohn.Forte@Sun.COM 	}
23767836SJohn.Forte@Sun.COM 
23777836SJohn.Forte@Sun.COM 	/* find version property */
23787836SJohn.Forte@Sun.COM 	/*
23797836SJohn.Forte@Sun.COM 	 * Get the version property
23807836SJohn.Forte@Sun.COM 	 */
23817836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VERSION_NAME, prop) == -1) {
23827836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
23837836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
23847836SJohn.Forte@Sun.COM 		} else {
23857836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
23867836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
23877836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
23887836SJohn.Forte@Sun.COM 			goto out;
23897836SJohn.Forte@Sun.COM 		}
23907836SJohn.Forte@Sun.COM 	}
23917836SJohn.Forte@Sun.COM 
23927836SJohn.Forte@Sun.COM 	/* no version property found */
23937836SJohn.Forte@Sun.COM 	if (ret == STMF_PS_ERROR_NOT_FOUND) {
23947836SJohn.Forte@Sun.COM 		/*
23957836SJohn.Forte@Sun.COM 		 * If we have no version property, go ahead
23967836SJohn.Forte@Sun.COM 		 * and create it. We're obviously making an assumption
23977836SJohn.Forte@Sun.COM 		 * here that someone did not delete the existing property
23987836SJohn.Forte@Sun.COM 		 * and that this is the initial set and the initial call
23997836SJohn.Forte@Sun.COM 		 * to iPsInit.
24007836SJohn.Forte@Sun.COM 		 * If they did delete it, this will simply plant this
24017836SJohn.Forte@Sun.COM 		 * library's version on this service. That may or may not be
24027836SJohn.Forte@Sun.COM 		 * correct and we have no way of determining that.
24037836SJohn.Forte@Sun.COM 		 */
24047836SJohn.Forte@Sun.COM 		/*
24057836SJohn.Forte@Sun.COM 		 * Begin the transaction
24067836SJohn.Forte@Sun.COM 		 */
24077836SJohn.Forte@Sun.COM 		if (scf_transaction_start(tran, pg) == -1) {
24087836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "start transaction failed - %s",
24097836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24107836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
24117836SJohn.Forte@Sun.COM 			goto out;
24127836SJohn.Forte@Sun.COM 		}
24137836SJohn.Forte@Sun.COM 
24147836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry,
24157836SJohn.Forte@Sun.COM 		    STMF_VERSION_NAME, SCF_TYPE_COUNT) == -1) {
24167836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
24177836SJohn.Forte@Sun.COM 			    "transaction property new failed - %s",
24187836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24197836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
24207836SJohn.Forte@Sun.COM 			goto out;
24217836SJohn.Forte@Sun.COM 		}
24227836SJohn.Forte@Sun.COM 
24237836SJohn.Forte@Sun.COM 		/*
24247836SJohn.Forte@Sun.COM 		 * set the version number
24257836SJohn.Forte@Sun.COM 		 */
24267836SJohn.Forte@Sun.COM 		scf_value_set_count(value, *version);
24277836SJohn.Forte@Sun.COM 
24287836SJohn.Forte@Sun.COM 		/*
24297836SJohn.Forte@Sun.COM 		 * add the value to the transaction
24307836SJohn.Forte@Sun.COM 		 */
24317836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry, value) == -1) {
24327836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
24337836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24347836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
24357836SJohn.Forte@Sun.COM 			goto out;
24367836SJohn.Forte@Sun.COM 		}
24377836SJohn.Forte@Sun.COM 		if ((commitRet = scf_transaction_commit(tran)) != 1) {
24387836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction commit failed - %s",
24397836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24407836SJohn.Forte@Sun.COM 			if (commitRet == 0) {
24417836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_BUSY;
24427836SJohn.Forte@Sun.COM 			} else {
24437836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
24447836SJohn.Forte@Sun.COM 			}
24457836SJohn.Forte@Sun.COM 			goto out;
24467836SJohn.Forte@Sun.COM 		}
24477836SJohn.Forte@Sun.COM 		/* reset return value */
24487836SJohn.Forte@Sun.COM 		ret = STMF_PS_SUCCESS;
24497836SJohn.Forte@Sun.COM 	} else {
24507836SJohn.Forte@Sun.COM 		/* get the version property */
24517836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_VERSION_NAME, prop) == -1) {
24527836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
24537836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24547836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
24557836SJohn.Forte@Sun.COM 			goto out;
24567836SJohn.Forte@Sun.COM 		}
24577836SJohn.Forte@Sun.COM 
24587836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
24597836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
24607836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24617836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
24627836SJohn.Forte@Sun.COM 			goto out;
24637836SJohn.Forte@Sun.COM 		}
24647836SJohn.Forte@Sun.COM 
24657836SJohn.Forte@Sun.COM 		/*
24667836SJohn.Forte@Sun.COM 		 * Get the actual value of the view entry count property
24677836SJohn.Forte@Sun.COM 		 */
24687836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value, version) == -1) {
24697836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get count value failed - %s",
24707836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
24717836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
24727836SJohn.Forte@Sun.COM 			goto out;
24737836SJohn.Forte@Sun.COM 		}
24747836SJohn.Forte@Sun.COM 	}
24757836SJohn.Forte@Sun.COM 
24767836SJohn.Forte@Sun.COM out:
24777836SJohn.Forte@Sun.COM 	/*
24787836SJohn.Forte@Sun.COM 	 * Free resources.
24797836SJohn.Forte@Sun.COM 	 * handle and svc should not be free'd here. They're
24807836SJohn.Forte@Sun.COM 	 * free'd elsewhere
24817836SJohn.Forte@Sun.COM 	 */
24827836SJohn.Forte@Sun.COM 	if (pg != NULL) {
24837836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
24847836SJohn.Forte@Sun.COM 	}
24857836SJohn.Forte@Sun.COM 	if (prop != NULL) {
24867836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
24877836SJohn.Forte@Sun.COM 	}
24887836SJohn.Forte@Sun.COM 	if (entry != NULL) {
24897836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry);
24907836SJohn.Forte@Sun.COM 	}
24917836SJohn.Forte@Sun.COM 	if (tran != NULL) {
24927836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
24937836SJohn.Forte@Sun.COM 	}
24947836SJohn.Forte@Sun.COM 	if (value != NULL) {
24957836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
24967836SJohn.Forte@Sun.COM 	}
24977836SJohn.Forte@Sun.COM 	return (ret);
24987836SJohn.Forte@Sun.COM }
24997836SJohn.Forte@Sun.COM 
25007836SJohn.Forte@Sun.COM 
25017836SJohn.Forte@Sun.COM 
25027836SJohn.Forte@Sun.COM /*
25037836SJohn.Forte@Sun.COM  * iPsGetActualGroupName
25047836SJohn.Forte@Sun.COM  *
25057836SJohn.Forte@Sun.COM  * pgName - Property group name
25067836SJohn.Forte@Sun.COM  * groupName - requested group name
25077836SJohn.Forte@Sun.COM  * actualName - actual group name to reference (len must be >= MAXNAMELEN)
25087836SJohn.Forte@Sun.COM  *
25097836SJohn.Forte@Sun.COM  * returns:
25107836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
25117836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
25127836SJohn.Forte@Sun.COM  */
25137836SJohn.Forte@Sun.COM static int
25147836SJohn.Forte@Sun.COM iPsGetActualGroupName(char *pgName, char *groupName, char *actualName)
25157836SJohn.Forte@Sun.COM {
25167836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
25177836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
25187836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
25197836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
25207836SJohn.Forte@Sun.COM 	scf_iter_t	*propIter = NULL;
25217836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
25227836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
25237836SJohn.Forte@Sun.COM 	int ret;
25247836SJohn.Forte@Sun.COM 
25257836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
25267836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
25277836SJohn.Forte@Sun.COM 		goto out;
25287836SJohn.Forte@Sun.COM 	}
25297836SJohn.Forte@Sun.COM 
25307836SJohn.Forte@Sun.COM 	/*
25317836SJohn.Forte@Sun.COM 	 * Allocate scf resources
25327836SJohn.Forte@Sun.COM 	 */
25337836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
25347836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
25357836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
25367836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
25377836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
25387836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
25397836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
25407836SJohn.Forte@Sun.COM 		goto out;
25417836SJohn.Forte@Sun.COM 	}
25427836SJohn.Forte@Sun.COM 
25437836SJohn.Forte@Sun.COM 	/*
25447836SJohn.Forte@Sun.COM 	 * get group list property group
25457836SJohn.Forte@Sun.COM 	 */
25467836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
25477836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
25487836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
25497836SJohn.Forte@Sun.COM 		} else {
25507836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
25517836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
25527836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
25537836SJohn.Forte@Sun.COM 		}
25547836SJohn.Forte@Sun.COM 		goto out;
25557836SJohn.Forte@Sun.COM 	}
25567836SJohn.Forte@Sun.COM 
25577836SJohn.Forte@Sun.COM 	/*
25587836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
25597836SJohn.Forte@Sun.COM 	 */
25607836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
25617836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
25627836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
25637836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
25647836SJohn.Forte@Sun.COM 		goto out;
25657836SJohn.Forte@Sun.COM 	}
25667836SJohn.Forte@Sun.COM 
25677836SJohn.Forte@Sun.COM 	/*
25687836SJohn.Forte@Sun.COM 	 * Iterate through group properties searching for the requested
25697836SJohn.Forte@Sun.COM 	 * group name. When we find it, we need to get the property name
25707836SJohn.Forte@Sun.COM 	 * since it refers to the actual group name.
25717836SJohn.Forte@Sun.COM 	 */
25727836SJohn.Forte@Sun.COM 
25737836SJohn.Forte@Sun.COM 	/* initialize to not found */
25747836SJohn.Forte@Sun.COM 	ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
25757836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
25767836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, actualName, MAXNAMELEN) == -1) {
25777836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
25787836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
25797836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
25807836SJohn.Forte@Sun.COM 			break;
25817836SJohn.Forte@Sun.COM 		}
25827836SJohn.Forte@Sun.COM 		/*
25837836SJohn.Forte@Sun.COM 		 * Skip over non-member list properties
25847836SJohn.Forte@Sun.COM 		 */
25857836SJohn.Forte@Sun.COM 		if (strstr(actualName, STMF_MEMBER_LIST_SUFFIX)) {
25867836SJohn.Forte@Sun.COM 			continue;
25877836SJohn.Forte@Sun.COM 		}
25887836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
25897836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
25907836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
25917836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
25927836SJohn.Forte@Sun.COM 			break;
25937836SJohn.Forte@Sun.COM 		}
25947836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) {
25957836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get ustring failed - %s",
25967836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
25977836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
25987836SJohn.Forte@Sun.COM 			break;
25997836SJohn.Forte@Sun.COM 		}
26007836SJohn.Forte@Sun.COM 
26017836SJohn.Forte@Sun.COM 		/*
26027836SJohn.Forte@Sun.COM 		 * When we find a match, set success and break
26037836SJohn.Forte@Sun.COM 		 */
26047836SJohn.Forte@Sun.COM 		if ((strlen(buf) == strlen(groupName)) &&
26057836SJohn.Forte@Sun.COM 		    bcmp(buf, groupName, strlen(buf)) == 0) {
26067836SJohn.Forte@Sun.COM 			ret = STMF_PS_SUCCESS;
26077836SJohn.Forte@Sun.COM 			break;
26087836SJohn.Forte@Sun.COM 		}
26097836SJohn.Forte@Sun.COM 	}
26107836SJohn.Forte@Sun.COM 
26117836SJohn.Forte@Sun.COM 	/*
26127836SJohn.Forte@Sun.COM 	 * if we didn't find it, ret is set to STMF_PS_ERROR_GROUP_NOT_FOUND
26137836SJohn.Forte@Sun.COM 	 */
26147836SJohn.Forte@Sun.COM 
26157836SJohn.Forte@Sun.COM out:
26167836SJohn.Forte@Sun.COM 	/*
26177836SJohn.Forte@Sun.COM 	 * Free resources
26187836SJohn.Forte@Sun.COM 	 */
26197836SJohn.Forte@Sun.COM 	if (handle != NULL) {
26207836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
26217836SJohn.Forte@Sun.COM 	}
26227836SJohn.Forte@Sun.COM 	if (svc != NULL) {
26237836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
26247836SJohn.Forte@Sun.COM 	}
26257836SJohn.Forte@Sun.COM 	if (pg != NULL) {
26267836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
26277836SJohn.Forte@Sun.COM 	}
26287836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
26297836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
26307836SJohn.Forte@Sun.COM 	}
26317836SJohn.Forte@Sun.COM 	if (prop != NULL) {
26327836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
26337836SJohn.Forte@Sun.COM 	}
26347836SJohn.Forte@Sun.COM 	if (value != NULL) {
26357836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
26367836SJohn.Forte@Sun.COM 	}
26377836SJohn.Forte@Sun.COM 
26387836SJohn.Forte@Sun.COM 	return (ret);
26397836SJohn.Forte@Sun.COM }
26407836SJohn.Forte@Sun.COM 
26417836SJohn.Forte@Sun.COM /*
26427836SJohn.Forte@Sun.COM  * psAddHostGroupMember
26437836SJohn.Forte@Sun.COM  *
26447836SJohn.Forte@Sun.COM  * Add a host group member to a host group,
26457836SJohn.Forte@Sun.COM  *
26467836SJohn.Forte@Sun.COM  * Input: groupName - name of group to which the member is added
26477836SJohn.Forte@Sun.COM  *        memberName - name of group member to add
26487836SJohn.Forte@Sun.COM  */
26497836SJohn.Forte@Sun.COM int
26507836SJohn.Forte@Sun.COM psAddHostGroupMember(char *groupName, char *memberName)
26517836SJohn.Forte@Sun.COM {
26527836SJohn.Forte@Sun.COM 	int ret;
26537836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
26547836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
26557836SJohn.Forte@Sun.COM 
26567836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName,
26577836SJohn.Forte@Sun.COM 	    groupPropName);
26587836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
26597836SJohn.Forte@Sun.COM 		return (ret);
26607836SJohn.Forte@Sun.COM 	}
26617836SJohn.Forte@Sun.COM 
26627836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
26637836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
26647836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
26657836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
26667836SJohn.Forte@Sun.COM 		    groupPropName);
26677836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
26687836SJohn.Forte@Sun.COM 	}
26697836SJohn.Forte@Sun.COM 
26707836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS, groupPropListName,
26717836SJohn.Forte@Sun.COM 	    memberName, ADD));
26727836SJohn.Forte@Sun.COM }
26737836SJohn.Forte@Sun.COM 
26747836SJohn.Forte@Sun.COM /*
26757836SJohn.Forte@Sun.COM  * psAddTargetGroupMember
26767836SJohn.Forte@Sun.COM  *
26777836SJohn.Forte@Sun.COM  * Add a target port group member to a target group
26787836SJohn.Forte@Sun.COM  *
26797836SJohn.Forte@Sun.COM  * Input: groupName - name of group to which the member is added
26807836SJohn.Forte@Sun.COM  *        memberName - name of group member to add. Must be nul terminated.
26817836SJohn.Forte@Sun.COM  */
26827836SJohn.Forte@Sun.COM int
26837836SJohn.Forte@Sun.COM psAddTargetGroupMember(char *groupName, char *memberName)
26847836SJohn.Forte@Sun.COM {
26857836SJohn.Forte@Sun.COM 	int ret;
26867836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
26877836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
26887836SJohn.Forte@Sun.COM 
26897836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName,
26907836SJohn.Forte@Sun.COM 	    groupPropName);
26917836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
26927836SJohn.Forte@Sun.COM 		return (ret);
26937836SJohn.Forte@Sun.COM 	}
26947836SJohn.Forte@Sun.COM 
26957836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
26967836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
26977836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
26987836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
26997836SJohn.Forte@Sun.COM 		    groupPropName);
27007836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
27017836SJohn.Forte@Sun.COM 	}
27027836SJohn.Forte@Sun.COM 
27037836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS, groupPropListName,
27047836SJohn.Forte@Sun.COM 	    memberName, ADD));
27057836SJohn.Forte@Sun.COM }
27067836SJohn.Forte@Sun.COM 
27077836SJohn.Forte@Sun.COM 
27087836SJohn.Forte@Sun.COM /*
27097836SJohn.Forte@Sun.COM  * psAddViewEntry
27107836SJohn.Forte@Sun.COM  *
27117836SJohn.Forte@Sun.COM  * luGuid - logical unit identifier
27127836SJohn.Forte@Sun.COM  * viewEntry - pointer to viewEntry allocated by the caller that contains
27137836SJohn.Forte@Sun.COM  *             the values to set for this view entry
27147836SJohn.Forte@Sun.COM  *
27157836SJohn.Forte@Sun.COM  * returns:
27167836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
27177836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
27187836SJohn.Forte@Sun.COM  */
27197836SJohn.Forte@Sun.COM int
27207836SJohn.Forte@Sun.COM psAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
27217836SJohn.Forte@Sun.COM {
27227836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
27237836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
27247836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
27257836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
27267836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
27277836SJohn.Forte@Sun.COM 	char scfLuPgName[LOGICAL_UNIT_PG_SIZE];
27287836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
27297836SJohn.Forte@Sun.COM 	sigset_t sigmaskRestore;
27307836SJohn.Forte@Sun.COM 
27317836SJohn.Forte@Sun.COM 	/* grab the signal hold lock */
27327836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&sigSetLock);
27337836SJohn.Forte@Sun.COM 
27347836SJohn.Forte@Sun.COM 	/*
27357836SJohn.Forte@Sun.COM 	 * hold signals until we're done
27367836SJohn.Forte@Sun.COM 	 */
27377836SJohn.Forte@Sun.COM 	if (holdSignal(&sigmaskRestore) != 0) {
27387836SJohn.Forte@Sun.COM 		(void) pthread_mutex_unlock(&sigSetLock);
27397836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
27407836SJohn.Forte@Sun.COM 	}
27417836SJohn.Forte@Sun.COM 
27427836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
27437836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
27447836SJohn.Forte@Sun.COM 		goto out;
27457836SJohn.Forte@Sun.COM 	}
27467836SJohn.Forte@Sun.COM 
27477836SJohn.Forte@Sun.COM 	pg = scf_pg_create(handle);
27487836SJohn.Forte@Sun.COM 	if (pg == NULL) {
27497836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf pg alloc failed - %s",
27507836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
27517836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
27527836SJohn.Forte@Sun.COM 		goto out;
27537836SJohn.Forte@Sun.COM 	}
27547836SJohn.Forte@Sun.COM 
27557836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
27567836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
27577836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
27587836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
27597836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
27607836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
27617836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
27627836SJohn.Forte@Sun.COM 
27637836SJohn.Forte@Sun.COM 	(void) snprintf(scfLuPgName, sizeof (scfLuPgName), "%s-%s",
27647836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
27657836SJohn.Forte@Sun.COM 
27667836SJohn.Forte@Sun.COM 	bzero(viewEntryPgName, sizeof (viewEntryPgName));
27677836SJohn.Forte@Sun.COM 	/*
27687836SJohn.Forte@Sun.COM 	 * Format of view entry property group name:
27697836SJohn.Forte@Sun.COM 	 *	VE-<view_entry_name>-<lu_name>
27707836SJohn.Forte@Sun.COM 	 */
27717836SJohn.Forte@Sun.COM 	(void) snprintf(viewEntryPgName, sizeof (viewEntryPgName),
27727836SJohn.Forte@Sun.COM 	    "%s-%d-%s", STMF_VE_PREFIX, viewEntry->veIndex, guidAsciiBuf);
27737836SJohn.Forte@Sun.COM 
27747836SJohn.Forte@Sun.COM 	ret = iPsAddViewEntry(scfLuPgName, viewEntryPgName, viewEntry);
27757836SJohn.Forte@Sun.COM 
27767836SJohn.Forte@Sun.COM out:
27777836SJohn.Forte@Sun.COM 	/*
27787836SJohn.Forte@Sun.COM 	 * Okay, we're done. Release the signals
27797836SJohn.Forte@Sun.COM 	 */
27807836SJohn.Forte@Sun.COM 	if (releaseSignal(&sigmaskRestore) != 0) {
27817836SJohn.Forte@Sun.COM 		/*
27827836SJohn.Forte@Sun.COM 		 * Don't set this as an STMF_PS_ERROR_*. We succeeded
27837836SJohn.Forte@Sun.COM 		 * the requested operation. But we do need to log it.
27847836SJohn.Forte@Sun.COM 		 */
27857836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "Unable to release one or more signals - %s",
27867836SJohn.Forte@Sun.COM 		    strerror(errno));
27877836SJohn.Forte@Sun.COM 	}
27887836SJohn.Forte@Sun.COM 
27897836SJohn.Forte@Sun.COM 	/*
27907836SJohn.Forte@Sun.COM 	 * Free resources
27917836SJohn.Forte@Sun.COM 	 */
27927836SJohn.Forte@Sun.COM 	if (handle != NULL) {
27937836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
27947836SJohn.Forte@Sun.COM 	}
27957836SJohn.Forte@Sun.COM 	if (svc != NULL) {
27967836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
27977836SJohn.Forte@Sun.COM 	}
27987836SJohn.Forte@Sun.COM 	if (pg != NULL) {
27997836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
28007836SJohn.Forte@Sun.COM 	}
28017836SJohn.Forte@Sun.COM 
28027836SJohn.Forte@Sun.COM 	/* release the signal hold lock */
28037836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&sigSetLock);
28047836SJohn.Forte@Sun.COM 
28057836SJohn.Forte@Sun.COM 	return (ret);
28067836SJohn.Forte@Sun.COM }
28077836SJohn.Forte@Sun.COM 
28087836SJohn.Forte@Sun.COM /*
28097836SJohn.Forte@Sun.COM  * psCheckService
28107836SJohn.Forte@Sun.COM  *
28117836SJohn.Forte@Sun.COM  * Purpose: Checks whether service exists
28127836SJohn.Forte@Sun.COM  *
28137836SJohn.Forte@Sun.COM  */
28147836SJohn.Forte@Sun.COM int
28157836SJohn.Forte@Sun.COM psCheckService()
28167836SJohn.Forte@Sun.COM {
28177836SJohn.Forte@Sun.COM 	int ret;
28187836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
28197836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
28207836SJohn.Forte@Sun.COM 
28217836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
28227836SJohn.Forte@Sun.COM 
28237836SJohn.Forte@Sun.COM 	/*
28247836SJohn.Forte@Sun.COM 	 * Free resources
28257836SJohn.Forte@Sun.COM 	 */
28267836SJohn.Forte@Sun.COM 	if (handle != NULL) {
28277836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
28287836SJohn.Forte@Sun.COM 	}
28297836SJohn.Forte@Sun.COM 	if (svc != NULL) {
28307836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
28317836SJohn.Forte@Sun.COM 	}
28327836SJohn.Forte@Sun.COM 
28337836SJohn.Forte@Sun.COM 	return (ret);
28347836SJohn.Forte@Sun.COM }
28357836SJohn.Forte@Sun.COM 
28367836SJohn.Forte@Sun.COM /*
28377836SJohn.Forte@Sun.COM  * psCreateHostGroup
28387836SJohn.Forte@Sun.COM  *
28397836SJohn.Forte@Sun.COM  * groupName - name of group to create
28407836SJohn.Forte@Sun.COM  *
28417836SJohn.Forte@Sun.COM  * returns:
28427836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
28437836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
28447836SJohn.Forte@Sun.COM  */
28457836SJohn.Forte@Sun.COM int
28467836SJohn.Forte@Sun.COM psCreateHostGroup(char *groupName)
28477836SJohn.Forte@Sun.COM {
28487836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_HOST_GROUPS, groupName, ADD));
28497836SJohn.Forte@Sun.COM }
28507836SJohn.Forte@Sun.COM 
28517836SJohn.Forte@Sun.COM /*
28527836SJohn.Forte@Sun.COM  * psCreateTargetGroup
28537836SJohn.Forte@Sun.COM  *
28547836SJohn.Forte@Sun.COM  * groupName - name of group to create
28557836SJohn.Forte@Sun.COM  *
28567836SJohn.Forte@Sun.COM  * returns:
28577836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
28587836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
28597836SJohn.Forte@Sun.COM  */
28607836SJohn.Forte@Sun.COM int
28617836SJohn.Forte@Sun.COM psCreateTargetGroup(char *groupName)
28627836SJohn.Forte@Sun.COM {
28637836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS, groupName, ADD));
28647836SJohn.Forte@Sun.COM }
28657836SJohn.Forte@Sun.COM 
28667836SJohn.Forte@Sun.COM /*
28677836SJohn.Forte@Sun.COM  * psDeleteHostGroup
28687836SJohn.Forte@Sun.COM  *
28697836SJohn.Forte@Sun.COM  * groupName - name of group to delete
28707836SJohn.Forte@Sun.COM  *
28717836SJohn.Forte@Sun.COM  * returns:
28727836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
28737836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
28747836SJohn.Forte@Sun.COM  */
28757836SJohn.Forte@Sun.COM int
28767836SJohn.Forte@Sun.COM psDeleteHostGroup(char *groupName)
28777836SJohn.Forte@Sun.COM {
28787836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_HOST_GROUPS, groupName, REMOVE));
28797836SJohn.Forte@Sun.COM }
28807836SJohn.Forte@Sun.COM 
28817836SJohn.Forte@Sun.COM /*
28827836SJohn.Forte@Sun.COM  * psDeleteTargetGroup
28837836SJohn.Forte@Sun.COM  *
28847836SJohn.Forte@Sun.COM  * groupName - name of group to delete
28857836SJohn.Forte@Sun.COM  *
28867836SJohn.Forte@Sun.COM  * returns:
28877836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
28887836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
28897836SJohn.Forte@Sun.COM  */
28907836SJohn.Forte@Sun.COM int
28917836SJohn.Forte@Sun.COM psDeleteTargetGroup(char *groupName)
28927836SJohn.Forte@Sun.COM {
28937836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS, groupName,
28947836SJohn.Forte@Sun.COM 	    REMOVE));
28957836SJohn.Forte@Sun.COM }
28967836SJohn.Forte@Sun.COM 
28977836SJohn.Forte@Sun.COM /*
28987836SJohn.Forte@Sun.COM  * psGetHostGroupList
28997836SJohn.Forte@Sun.COM  *
29007836SJohn.Forte@Sun.COM  * groupList - pointer to pointer to stmfGroupList. Contains the list
29017836SJohn.Forte@Sun.COM  *             of host groups on successful return.
29027836SJohn.Forte@Sun.COM  *
29037836SJohn.Forte@Sun.COM  * returns:
29047836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
29057836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
29067836SJohn.Forte@Sun.COM  */
29077836SJohn.Forte@Sun.COM int
29087836SJohn.Forte@Sun.COM psGetHostGroupList(stmfGroupList **groupList)
29097836SJohn.Forte@Sun.COM {
29107836SJohn.Forte@Sun.COM 	return (iPsGetGroupList(STMF_HOST_GROUPS, groupList));
29117836SJohn.Forte@Sun.COM }
29127836SJohn.Forte@Sun.COM 
29137836SJohn.Forte@Sun.COM /*
29147836SJohn.Forte@Sun.COM  * psGetLogicalUnitList
29157836SJohn.Forte@Sun.COM  *
29167836SJohn.Forte@Sun.COM  *
29177836SJohn.Forte@Sun.COM  */
29187836SJohn.Forte@Sun.COM int
29197836SJohn.Forte@Sun.COM psGetLogicalUnitList(stmfGuidList **guidList)
29207836SJohn.Forte@Sun.COM {
29217836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
29227836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
29237836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
29247836SJohn.Forte@Sun.COM 	scf_iter_t	*pgIter = NULL;
29257836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
29267836SJohn.Forte@Sun.COM 	int guidCnt = 0;
29277836SJohn.Forte@Sun.COM 	int i = 0, j;
29287836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
29297836SJohn.Forte@Sun.COM 	unsigned int guid[sizeof (stmfGuid)];
29307836SJohn.Forte@Sun.COM 	stmfGuid outGuid;
29317836SJohn.Forte@Sun.COM 
29327836SJohn.Forte@Sun.COM 	assert(guidList != NULL);
29337836SJohn.Forte@Sun.COM 
29347836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
29357836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
29367836SJohn.Forte@Sun.COM 		goto out;
29377836SJohn.Forte@Sun.COM 	}
29387836SJohn.Forte@Sun.COM 
29397836SJohn.Forte@Sun.COM 	/*
29407836SJohn.Forte@Sun.COM 	 * Allocate scf resources
29417836SJohn.Forte@Sun.COM 	 */
29427836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
29437836SJohn.Forte@Sun.COM 	    ((pgIter = scf_iter_create(handle)) == NULL)) {
29447836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
29457836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
29467836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
29477836SJohn.Forte@Sun.COM 		goto out;
29487836SJohn.Forte@Sun.COM 	}
29497836SJohn.Forte@Sun.COM 
29507836SJohn.Forte@Sun.COM 	/*
29517836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
29527836SJohn.Forte@Sun.COM 	 */
29537836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
29547836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
29557836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
29567836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
29577836SJohn.Forte@Sun.COM 		goto out;
29587836SJohn.Forte@Sun.COM 	}
29597836SJohn.Forte@Sun.COM 
29607836SJohn.Forte@Sun.COM 	while (scf_iter_next_pg(pgIter, pg) == 1) {
29617836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
29627836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
29637836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
29647836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
29657836SJohn.Forte@Sun.COM 			break;
29667836SJohn.Forte@Sun.COM 		}
29677836SJohn.Forte@Sun.COM 		/*
29687836SJohn.Forte@Sun.COM 		 * Only count LU property groups
29697836SJohn.Forte@Sun.COM 		 */
29707836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_LU_PREFIX, strlen(STMF_LU_PREFIX)) == 0) {
29717836SJohn.Forte@Sun.COM 			guidCnt++;
29727836SJohn.Forte@Sun.COM 		}
29737836SJohn.Forte@Sun.COM 	}
29747836SJohn.Forte@Sun.COM 
29757836SJohn.Forte@Sun.COM 	/*
29767836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
29777836SJohn.Forte@Sun.COM 	 */
29787836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
29797836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
29807836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
29817836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
29827836SJohn.Forte@Sun.COM 		goto out;
29837836SJohn.Forte@Sun.COM 	}
29847836SJohn.Forte@Sun.COM 
29857836SJohn.Forte@Sun.COM 	*guidList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
29867836SJohn.Forte@Sun.COM 	    guidCnt * sizeof (stmfGuid));
29877836SJohn.Forte@Sun.COM 	if (*guidList == NULL) {
29887836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
29897836SJohn.Forte@Sun.COM 		goto out;
29907836SJohn.Forte@Sun.COM 	}
29917836SJohn.Forte@Sun.COM 
29927836SJohn.Forte@Sun.COM 	/*
29937836SJohn.Forte@Sun.COM 	 * it's possible for entries to be added/removed while we're retrieving
29947836SJohn.Forte@Sun.COM 	 * the property groups. Just make sure we don't write beyond our
29957836SJohn.Forte@Sun.COM 	 * allocated buffer by checking to ensure i < guidCnt.
29967836SJohn.Forte@Sun.COM 	 */
29977836SJohn.Forte@Sun.COM 	while ((scf_iter_next_pg(pgIter, pg) == 1) && (i < guidCnt)) {
29987836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
29997836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
30007836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
30017836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
30027836SJohn.Forte@Sun.COM 			break;
30037836SJohn.Forte@Sun.COM 		}
30047836SJohn.Forte@Sun.COM 		/*
30057836SJohn.Forte@Sun.COM 		 * Only use LU property groups
30067836SJohn.Forte@Sun.COM 		 */
30077836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_LU_PREFIX, strlen(STMF_LU_PREFIX)) != 0) {
30087836SJohn.Forte@Sun.COM 			continue;
30097836SJohn.Forte@Sun.COM 		}
30107836SJohn.Forte@Sun.COM 
30117836SJohn.Forte@Sun.COM 		j = strlen(STMF_LU_PREFIX) + strlen("-");
30127836SJohn.Forte@Sun.COM 
30137836SJohn.Forte@Sun.COM 		(void) sscanf(buf + j,
30147836SJohn.Forte@Sun.COM 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
30157836SJohn.Forte@Sun.COM 		    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
30167836SJohn.Forte@Sun.COM 		    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
30177836SJohn.Forte@Sun.COM 		    &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
30187836SJohn.Forte@Sun.COM 
30197836SJohn.Forte@Sun.COM 		for (j = 0; j < sizeof (stmfGuid); j++) {
30207836SJohn.Forte@Sun.COM 			outGuid.guid[j] = guid[j];
30217836SJohn.Forte@Sun.COM 		}
30227836SJohn.Forte@Sun.COM 
30237836SJohn.Forte@Sun.COM 		bcopy(&outGuid, (*guidList)->guid[i++].guid, sizeof (stmfGuid));
30247836SJohn.Forte@Sun.COM 		(*guidList)->cnt++;
30257836SJohn.Forte@Sun.COM 	}
30267836SJohn.Forte@Sun.COM 
30277836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
30287836SJohn.Forte@Sun.COM 		free(*guidList);
30297836SJohn.Forte@Sun.COM 		goto out;
30307836SJohn.Forte@Sun.COM 	}
30317836SJohn.Forte@Sun.COM 
30327836SJohn.Forte@Sun.COM out:
30337836SJohn.Forte@Sun.COM 	/*
30347836SJohn.Forte@Sun.COM 	 * Free resources
30357836SJohn.Forte@Sun.COM 	 */
30367836SJohn.Forte@Sun.COM 	if (handle != NULL) {
30377836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
30387836SJohn.Forte@Sun.COM 	}
30397836SJohn.Forte@Sun.COM 	if (svc != NULL) {
30407836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
30417836SJohn.Forte@Sun.COM 	}
30427836SJohn.Forte@Sun.COM 	if (pg != NULL) {
30437836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
30447836SJohn.Forte@Sun.COM 	}
30457836SJohn.Forte@Sun.COM 	if (pgIter != NULL) {
30467836SJohn.Forte@Sun.COM 		scf_iter_destroy(pgIter);
30477836SJohn.Forte@Sun.COM 	}
30487836SJohn.Forte@Sun.COM 
30497836SJohn.Forte@Sun.COM 	return (ret);
30507836SJohn.Forte@Sun.COM }
30517836SJohn.Forte@Sun.COM 
30527836SJohn.Forte@Sun.COM /*
30537836SJohn.Forte@Sun.COM  * psGetTargetGroupList
30547836SJohn.Forte@Sun.COM  *
30557836SJohn.Forte@Sun.COM  * groupList - pointer to pointer to stmfGroupList. Contains the list
30567836SJohn.Forte@Sun.COM  *             of target groups on successful return.
30577836SJohn.Forte@Sun.COM  *
30587836SJohn.Forte@Sun.COM  * returns:
30597836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
30607836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
30617836SJohn.Forte@Sun.COM  */
30627836SJohn.Forte@Sun.COM int
30637836SJohn.Forte@Sun.COM psGetTargetGroupList(stmfGroupList **groupList)
30647836SJohn.Forte@Sun.COM {
30657836SJohn.Forte@Sun.COM 	return (iPsGetGroupList(STMF_TARGET_GROUPS, groupList));
30667836SJohn.Forte@Sun.COM }
30677836SJohn.Forte@Sun.COM 
30687836SJohn.Forte@Sun.COM /*
30697836SJohn.Forte@Sun.COM  * psGetHostGroupMemberList
30707836SJohn.Forte@Sun.COM  *
30717836SJohn.Forte@Sun.COM  * groupName - group name for which to retrieve a member list
30727836SJohn.Forte@Sun.COM  * groupMemberList - pointer to pointer to stmfGroupProperties list
30737836SJohn.Forte@Sun.COM  *
30747836SJohn.Forte@Sun.COM  * returns:
30757836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
30767836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
30777836SJohn.Forte@Sun.COM  */
30787836SJohn.Forte@Sun.COM int
30797836SJohn.Forte@Sun.COM psGetHostGroupMemberList(char *groupName, stmfGroupProperties **groupMemberList)
30807836SJohn.Forte@Sun.COM {
30817836SJohn.Forte@Sun.COM 	int ret;
30827836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
30837836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
30847836SJohn.Forte@Sun.COM 
30857836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName,
30867836SJohn.Forte@Sun.COM 	    groupPropName);
30877836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
30887836SJohn.Forte@Sun.COM 		return (ret);
30897836SJohn.Forte@Sun.COM 	}
30907836SJohn.Forte@Sun.COM 
30917836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
30927836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
30937836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
30947836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
30957836SJohn.Forte@Sun.COM 		    groupPropName);
30967836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
30977836SJohn.Forte@Sun.COM 	}
30987836SJohn.Forte@Sun.COM 
30997836SJohn.Forte@Sun.COM 	return (iPsGetGroupMemberList(STMF_HOST_GROUPS, groupPropListName,
31007836SJohn.Forte@Sun.COM 	    groupMemberList));
31017836SJohn.Forte@Sun.COM }
31027836SJohn.Forte@Sun.COM 
31037836SJohn.Forte@Sun.COM /*
31047836SJohn.Forte@Sun.COM  * psGetTargetGroupMemberList
31057836SJohn.Forte@Sun.COM  *
31067836SJohn.Forte@Sun.COM  * groupName - group name for which to retrieve a member list
31077836SJohn.Forte@Sun.COM  * groupMemberList - pointer to pointer to stmfGroupProperties list
31087836SJohn.Forte@Sun.COM  *
31097836SJohn.Forte@Sun.COM  * returns:
31107836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
31117836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
31127836SJohn.Forte@Sun.COM  */
31137836SJohn.Forte@Sun.COM int
31147836SJohn.Forte@Sun.COM psGetTargetGroupMemberList(char *groupName,
31157836SJohn.Forte@Sun.COM     stmfGroupProperties **groupMemberList)
31167836SJohn.Forte@Sun.COM {
31177836SJohn.Forte@Sun.COM 	int ret;
31187836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
31197836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
31207836SJohn.Forte@Sun.COM 
31217836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName,
31227836SJohn.Forte@Sun.COM 	    groupPropName);
31237836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
31247836SJohn.Forte@Sun.COM 		return (ret);
31257836SJohn.Forte@Sun.COM 	}
31267836SJohn.Forte@Sun.COM 
31277836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
31287836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
31297836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
31307836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
31317836SJohn.Forte@Sun.COM 		    groupPropName);
31327836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
31337836SJohn.Forte@Sun.COM 	}
31347836SJohn.Forte@Sun.COM 
31357836SJohn.Forte@Sun.COM 	return (iPsGetGroupMemberList(STMF_TARGET_GROUPS,
31367836SJohn.Forte@Sun.COM 	    groupPropListName, groupMemberList));
31377836SJohn.Forte@Sun.COM }
31387836SJohn.Forte@Sun.COM 
31397836SJohn.Forte@Sun.COM /*
31407836SJohn.Forte@Sun.COM  * qsort function
31417836SJohn.Forte@Sun.COM  * sort on veIndex
31427836SJohn.Forte@Sun.COM  */
31437836SJohn.Forte@Sun.COM static int
31447836SJohn.Forte@Sun.COM viewEntryCompare(const void *p1, const void *p2)
31457836SJohn.Forte@Sun.COM {
31467836SJohn.Forte@Sun.COM 
31477836SJohn.Forte@Sun.COM 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
31487836SJohn.Forte@Sun.COM 	if (v1->veIndex > v2->veIndex)
31497836SJohn.Forte@Sun.COM 		return (1);
31507836SJohn.Forte@Sun.COM 	if (v1->veIndex < v2->veIndex)
31517836SJohn.Forte@Sun.COM 		return (-1);
31527836SJohn.Forte@Sun.COM 	return (0);
31537836SJohn.Forte@Sun.COM }
31547836SJohn.Forte@Sun.COM 
31557836SJohn.Forte@Sun.COM /*
31567836SJohn.Forte@Sun.COM  * psGetViewEntryList
31577836SJohn.Forte@Sun.COM  *
31587836SJohn.Forte@Sun.COM  * luGuid - identifier of logical unit for which to retrieve a view entry list
31597836SJohn.Forte@Sun.COM  * viewEntryList - pointer to pointer to stmfViewEntryList. It will be allocated
31607836SJohn.Forte@Sun.COM  *                 on successful return.
31617836SJohn.Forte@Sun.COM  *
31627836SJohn.Forte@Sun.COM  * returns:
31637836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
31647836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
31657836SJohn.Forte@Sun.COM  */
31667836SJohn.Forte@Sun.COM int
31677836SJohn.Forte@Sun.COM psGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
31687836SJohn.Forte@Sun.COM {
31697836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
31707836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
31717836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
31727836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
31737836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
31747836SJohn.Forte@Sun.COM 	scf_iter_t  *propIter = NULL;
31757836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
31767836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
31777836SJohn.Forte@Sun.COM 	char luPgName[LOGICAL_UNIT_PG_SIZE];
31787836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
31797836SJohn.Forte@Sun.COM 	uint64_t i = 0;
31807836SJohn.Forte@Sun.COM 	uint64_t veCnt;
31817836SJohn.Forte@Sun.COM 
31827836SJohn.Forte@Sun.COM 
31837836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
31847836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
31857836SJohn.Forte@Sun.COM 		goto out;
31867836SJohn.Forte@Sun.COM 	}
31877836SJohn.Forte@Sun.COM 
31887836SJohn.Forte@Sun.COM 	/*
31897836SJohn.Forte@Sun.COM 	 * Allocate scf resources
31907836SJohn.Forte@Sun.COM 	 */
31917836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
31927836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
31937836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
31947836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
31957836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
31967836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
31977836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
31987836SJohn.Forte@Sun.COM 		goto out;
31997836SJohn.Forte@Sun.COM 	}
32007836SJohn.Forte@Sun.COM 
32017836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
32027836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
32037836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
32047836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
32057836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
32067836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
32077836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
32087836SJohn.Forte@Sun.COM 
32097836SJohn.Forte@Sun.COM 	/* form the LU property group name (LU-<guid>) */
32107836SJohn.Forte@Sun.COM 	(void) snprintf(luPgName, sizeof (luPgName), "%s-%s",
32117836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
32127836SJohn.Forte@Sun.COM 
32137836SJohn.Forte@Sun.COM 	/* get the property group associated with this LU */
32147836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, luPgName, pg) == -1) {
32157836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
32167836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
32177836SJohn.Forte@Sun.COM 		} else {
32187836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
32197836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
32207836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
32217836SJohn.Forte@Sun.COM 		}
32227836SJohn.Forte@Sun.COM 		goto out;
32237836SJohn.Forte@Sun.COM 	}
32247836SJohn.Forte@Sun.COM 
32257836SJohn.Forte@Sun.COM 	/* get the view entry count property */
32267836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) {
32277836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
32287836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
32297836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
32307836SJohn.Forte@Sun.COM 		goto out;
32317836SJohn.Forte@Sun.COM 	}
32327836SJohn.Forte@Sun.COM 
32337836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
32347836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property value failed - %s",
32357836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
32367836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
32377836SJohn.Forte@Sun.COM 		goto out;
32387836SJohn.Forte@Sun.COM 	}
32397836SJohn.Forte@Sun.COM 
32407836SJohn.Forte@Sun.COM 	/*
32417836SJohn.Forte@Sun.COM 	 * Get the actual value of the view entry count property
32427836SJohn.Forte@Sun.COM 	 */
32437836SJohn.Forte@Sun.COM 	if (scf_value_get_count(value, &veCnt) == -1) {
32447836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get integer value failed - %s",
32457836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
32467836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
32477836SJohn.Forte@Sun.COM 		goto out;
32487836SJohn.Forte@Sun.COM 	}
32497836SJohn.Forte@Sun.COM 
32507836SJohn.Forte@Sun.COM 	/*
32517836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
32527836SJohn.Forte@Sun.COM 	 */
32537836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
32547836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
32557836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
32567836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
32577836SJohn.Forte@Sun.COM 		goto out;
32587836SJohn.Forte@Sun.COM 	}
32597836SJohn.Forte@Sun.COM 
32607836SJohn.Forte@Sun.COM 	/*
32617836SJohn.Forte@Sun.COM 	 * alloc the list based on the view entry count
32627836SJohn.Forte@Sun.COM 	 */
32637836SJohn.Forte@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
32647836SJohn.Forte@Sun.COM 	    sizeof (stmfViewEntryList) + veCnt * sizeof (stmfViewEntry));
32657836SJohn.Forte@Sun.COM 	if (*viewEntryList == NULL) {
32667836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
32677836SJohn.Forte@Sun.COM 		goto out;
32687836SJohn.Forte@Sun.COM 	}
32697836SJohn.Forte@Sun.COM 
32707836SJohn.Forte@Sun.COM 	i = 0;
32717836SJohn.Forte@Sun.COM 	/*
32727836SJohn.Forte@Sun.COM 	 * iterate through the view entry properties to find the
32737836SJohn.Forte@Sun.COM 	 * view entries
32747836SJohn.Forte@Sun.COM 	 */
32757836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
32767836SJohn.Forte@Sun.COM 		/* find match for view entry property */
32777836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, viewEntryPgName,
32787836SJohn.Forte@Sun.COM 		    sizeof (viewEntryPgName)) != -1) {
32797836SJohn.Forte@Sun.COM 			if (strncmp(viewEntryPgName, STMF_VE_PREFIX,
32807836SJohn.Forte@Sun.COM 			    strlen(STMF_VE_PREFIX)) != 0) {
32817836SJohn.Forte@Sun.COM 				continue;
32827836SJohn.Forte@Sun.COM 			}
32837836SJohn.Forte@Sun.COM 			/*
32847836SJohn.Forte@Sun.COM 			 * We've exceeded our alloc limit
32857836SJohn.Forte@Sun.COM 			 * break with error
32867836SJohn.Forte@Sun.COM 			 */
32877836SJohn.Forte@Sun.COM 			if (i == veCnt) {
32887836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
32897836SJohn.Forte@Sun.COM 				break;
32907836SJohn.Forte@Sun.COM 			}
32917836SJohn.Forte@Sun.COM 
32927836SJohn.Forte@Sun.COM 			if ((ret = iPsGetViewEntry(viewEntryPgName,
32937836SJohn.Forte@Sun.COM 			    &((*viewEntryList)->ve[i]))) != STMF_PS_SUCCESS) {
32947836SJohn.Forte@Sun.COM 				break;
32957836SJohn.Forte@Sun.COM 			}
32967836SJohn.Forte@Sun.COM 
32977836SJohn.Forte@Sun.COM 			i++;
32987836SJohn.Forte@Sun.COM 
32997836SJohn.Forte@Sun.COM 			/* set the list count */
33007836SJohn.Forte@Sun.COM 			(*viewEntryList)->cnt++;
33017836SJohn.Forte@Sun.COM 		} else {
33027836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf pg iter service failed - %s",
33037836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
33047836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
33057836SJohn.Forte@Sun.COM 			break;
33067836SJohn.Forte@Sun.COM 		}
33077836SJohn.Forte@Sun.COM 
33087836SJohn.Forte@Sun.COM 	}
33097836SJohn.Forte@Sun.COM 
33107836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
33117836SJohn.Forte@Sun.COM 		free(*viewEntryList);
33127836SJohn.Forte@Sun.COM 		goto out;
33137836SJohn.Forte@Sun.COM 	}
33147836SJohn.Forte@Sun.COM 
33157836SJohn.Forte@Sun.COM 	/*
33167836SJohn.Forte@Sun.COM 	 * We're sorting the final list here based on the veIndex
33177836SJohn.Forte@Sun.COM 	 * If we don't, the caller is going to have to do it to reap
33187836SJohn.Forte@Sun.COM 	 * some intelligent output.
33197836SJohn.Forte@Sun.COM 	 */
33207836SJohn.Forte@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
33217836SJohn.Forte@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
33227836SJohn.Forte@Sun.COM 
33237836SJohn.Forte@Sun.COM out:
33247836SJohn.Forte@Sun.COM 	/*
33257836SJohn.Forte@Sun.COM 	 * Free resources
33267836SJohn.Forte@Sun.COM 	 */
33277836SJohn.Forte@Sun.COM 	if (handle != NULL) {
33287836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
33297836SJohn.Forte@Sun.COM 	}
33307836SJohn.Forte@Sun.COM 	if (svc != NULL) {
33317836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
33327836SJohn.Forte@Sun.COM 	}
33337836SJohn.Forte@Sun.COM 	if (pg != NULL) {
33347836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
33357836SJohn.Forte@Sun.COM 	}
33367836SJohn.Forte@Sun.COM 	if (prop != NULL) {
33377836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
33387836SJohn.Forte@Sun.COM 	}
33397836SJohn.Forte@Sun.COM 	if (value != NULL) {
33407836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
33417836SJohn.Forte@Sun.COM 	}
33427836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
33437836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
33447836SJohn.Forte@Sun.COM 	}
33457836SJohn.Forte@Sun.COM 
33467836SJohn.Forte@Sun.COM 	return (ret);
33477836SJohn.Forte@Sun.COM }
33487836SJohn.Forte@Sun.COM 
33497836SJohn.Forte@Sun.COM /*
33507836SJohn.Forte@Sun.COM  * iPsGetViewEntry
33517836SJohn.Forte@Sun.COM  *
33527836SJohn.Forte@Sun.COM  * viewEntryPgName - view entry property group name to retrieve
33537836SJohn.Forte@Sun.COM  * viewEntry - pointer to stmfViewEntry structure allocated by the caller
33547836SJohn.Forte@Sun.COM  *
33557836SJohn.Forte@Sun.COM  * returns:
33567836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
33577836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
33587836SJohn.Forte@Sun.COM  */
33597836SJohn.Forte@Sun.COM static int
33607836SJohn.Forte@Sun.COM iPsGetViewEntry(char *viewEntryPgName, stmfViewEntry *viewEntry)
33617836SJohn.Forte@Sun.COM {
33627836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
33637836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
33647836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
33657836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
33667836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
33677836SJohn.Forte@Sun.COM 	uint8_t scfBool;
33687836SJohn.Forte@Sun.COM 	char *indexPtr;
33697836SJohn.Forte@Sun.COM 	char groupName[sizeof (stmfGroupName)];
33707836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
33717836SJohn.Forte@Sun.COM 
33727836SJohn.Forte@Sun.COM 
33737836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
33747836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
33757836SJohn.Forte@Sun.COM 		goto out;
33767836SJohn.Forte@Sun.COM 	}
33777836SJohn.Forte@Sun.COM 
33787836SJohn.Forte@Sun.COM 	/*
33797836SJohn.Forte@Sun.COM 	 * Allocate scf resources
33807836SJohn.Forte@Sun.COM 	 */
33817836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
33827836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
33837836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
33847836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
33857836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
33867836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
33877836SJohn.Forte@Sun.COM 		goto out;
33887836SJohn.Forte@Sun.COM 	}
33897836SJohn.Forte@Sun.COM 
33907836SJohn.Forte@Sun.COM 	bzero(viewEntry, sizeof (stmfViewEntry));
33917836SJohn.Forte@Sun.COM 
33927836SJohn.Forte@Sun.COM 	/*
33937836SJohn.Forte@Sun.COM 	 * get the service property group view entry handle
33947836SJohn.Forte@Sun.COM 	 */
33957836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) {
33967836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
33977836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
33987836SJohn.Forte@Sun.COM 		} else {
33997836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
34007836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
34017836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
34027836SJohn.Forte@Sun.COM 		}
34037836SJohn.Forte@Sun.COM 		goto out;
34047836SJohn.Forte@Sun.COM 	}
34057836SJohn.Forte@Sun.COM 
34067836SJohn.Forte@Sun.COM 
34077836SJohn.Forte@Sun.COM 	/*
34087836SJohn.Forte@Sun.COM 	 * get index
34097836SJohn.Forte@Sun.COM 	 * format is: VE-<veIndex>-GUID
34107836SJohn.Forte@Sun.COM 	 */
34117836SJohn.Forte@Sun.COM 	indexPtr = strchr(viewEntryPgName, '-');
34127836SJohn.Forte@Sun.COM 	if (!indexPtr) {
34137836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34147836SJohn.Forte@Sun.COM 		goto out;
34157836SJohn.Forte@Sun.COM 	}
34167836SJohn.Forte@Sun.COM 
34177836SJohn.Forte@Sun.COM 	/* Set the index */
34187836SJohn.Forte@Sun.COM 	viewEntry->veIndex = atoi(strtok(++indexPtr, "-"));
34197836SJohn.Forte@Sun.COM 
34207836SJohn.Forte@Sun.COM 	viewEntry->veIndexValid = B_TRUE;
34217836SJohn.Forte@Sun.COM 
34227836SJohn.Forte@Sun.COM 	/* get allHosts property */
34237836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_ALLHOSTS,
34247836SJohn.Forte@Sun.COM 	    prop) == -1) {
34257836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34267836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34277836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34287836SJohn.Forte@Sun.COM 		goto out;
34297836SJohn.Forte@Sun.COM 	}
34307836SJohn.Forte@Sun.COM 
34317836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
34327836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34337836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34347836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34357836SJohn.Forte@Sun.COM 		goto out;
34367836SJohn.Forte@Sun.COM 	}
34377836SJohn.Forte@Sun.COM 
34387836SJohn.Forte@Sun.COM 	/* set allHosts */
34397836SJohn.Forte@Sun.COM 	if (scf_value_get_boolean(value, (uint8_t *)&scfBool) == -1) {
34407836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34417836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34427836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34437836SJohn.Forte@Sun.COM 		goto out;
34447836SJohn.Forte@Sun.COM 	}
34457836SJohn.Forte@Sun.COM 	viewEntry->allHosts = scfBool;
34467836SJohn.Forte@Sun.COM 
34477836SJohn.Forte@Sun.COM 	/* get hostGroup property */
34487836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_HOSTGROUP,
34497836SJohn.Forte@Sun.COM 	    prop) == -1) {
34507836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34517836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34527836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34537836SJohn.Forte@Sun.COM 		goto out;
34547836SJohn.Forte@Sun.COM 	}
34557836SJohn.Forte@Sun.COM 
34567836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
34577836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34587836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34597836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34607836SJohn.Forte@Sun.COM 		goto out;
34617836SJohn.Forte@Sun.COM 	}
34627836SJohn.Forte@Sun.COM 
34637836SJohn.Forte@Sun.COM 	if (scf_value_get_ustring(value, groupName,
34647836SJohn.Forte@Sun.COM 	    sizeof (groupName)) == -1) {
34657836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
34667836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34677836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34687836SJohn.Forte@Sun.COM 		goto out;
34697836SJohn.Forte@Sun.COM 	}
34707836SJohn.Forte@Sun.COM 	/* set hostGroup */
34717836SJohn.Forte@Sun.COM 	bcopy(groupName, viewEntry->hostGroup, strlen(groupName));
34727836SJohn.Forte@Sun.COM 
34737836SJohn.Forte@Sun.COM 	/* get allTargets property */
34747836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_ALLTARGETS,
34757836SJohn.Forte@Sun.COM 	    prop) == -1) {
34767836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34777836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34787836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34797836SJohn.Forte@Sun.COM 		goto out;
34807836SJohn.Forte@Sun.COM 	}
34817836SJohn.Forte@Sun.COM 
34827836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
34837836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34847836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34857836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34867836SJohn.Forte@Sun.COM 		goto out;
34877836SJohn.Forte@Sun.COM 	}
34887836SJohn.Forte@Sun.COM 
34897836SJohn.Forte@Sun.COM 	/* set allTargets */
34907836SJohn.Forte@Sun.COM 	if (scf_value_get_boolean(value, (uint8_t *)&scfBool) == -1) {
34917836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
34927836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
34937836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
34947836SJohn.Forte@Sun.COM 		goto out;
34957836SJohn.Forte@Sun.COM 	}
34967836SJohn.Forte@Sun.COM 	viewEntry->allTargets = scfBool;
34977836SJohn.Forte@Sun.COM 
34987836SJohn.Forte@Sun.COM 	/* get targetGroup property */
34997836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_TARGETGROUP, prop) == -1) {
35007836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
35017836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
35027836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
35037836SJohn.Forte@Sun.COM 		goto out;
35047836SJohn.Forte@Sun.COM 	}
35057836SJohn.Forte@Sun.COM 
35067836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
35077836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
35087836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
35097836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
35107836SJohn.Forte@Sun.COM 		goto out;
35117836SJohn.Forte@Sun.COM 	}
35127836SJohn.Forte@Sun.COM 
35137836SJohn.Forte@Sun.COM 	if (scf_value_get_ustring(value, groupName,
35147836SJohn.Forte@Sun.COM 	    sizeof (groupName)) == -1) {
35157836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
35167836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
35177836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
35187836SJohn.Forte@Sun.COM 		goto out;
35197836SJohn.Forte@Sun.COM 	}
35207836SJohn.Forte@Sun.COM 	/* set targetGroup */
35217836SJohn.Forte@Sun.COM 	bcopy(groupName, viewEntry->targetGroup, strlen(groupName));
35227836SJohn.Forte@Sun.COM 
35237836SJohn.Forte@Sun.COM 	/* get luNbr property */
35247836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_LUNBR,
35257836SJohn.Forte@Sun.COM 	    prop) == -1) {
35267836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
35277836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
35287836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
35297836SJohn.Forte@Sun.COM 		goto out;
35307836SJohn.Forte@Sun.COM 	}
35317836SJohn.Forte@Sun.COM 
35327836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
35337836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property value failed - %s",
35347836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
35357836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
35367836SJohn.Forte@Sun.COM 		goto out;
35377836SJohn.Forte@Sun.COM 	}
35387836SJohn.Forte@Sun.COM 
35397836SJohn.Forte@Sun.COM 	/* set luNbr */
35407836SJohn.Forte@Sun.COM 	if (scf_value_get_opaque(value, (char *)viewEntry->luNbr,
35417836SJohn.Forte@Sun.COM 	    sizeof (viewEntry->luNbr)) == -1) {
35427836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get opaque value failed - %s",
35437836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
35447836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
35457836SJohn.Forte@Sun.COM 		goto out;
35467836SJohn.Forte@Sun.COM 	}
35477836SJohn.Forte@Sun.COM 	/* set luNbrValid to true since we just got it */
35487836SJohn.Forte@Sun.COM 	viewEntry->luNbrValid = B_TRUE;
35497836SJohn.Forte@Sun.COM 
35507836SJohn.Forte@Sun.COM out:
35517836SJohn.Forte@Sun.COM 	/*
35527836SJohn.Forte@Sun.COM 	 * Free resources
35537836SJohn.Forte@Sun.COM 	 */
35547836SJohn.Forte@Sun.COM 	if (handle != NULL) {
35557836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
35567836SJohn.Forte@Sun.COM 	}
35577836SJohn.Forte@Sun.COM 	if (svc != NULL) {
35587836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
35597836SJohn.Forte@Sun.COM 	}
35607836SJohn.Forte@Sun.COM 	if (pg != NULL) {
35617836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
35627836SJohn.Forte@Sun.COM 	}
35637836SJohn.Forte@Sun.COM 	if (value != NULL) {
35647836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
35657836SJohn.Forte@Sun.COM 	}
35667836SJohn.Forte@Sun.COM 	if (prop != NULL) {
35677836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
35687836SJohn.Forte@Sun.COM 	}
35697836SJohn.Forte@Sun.COM 
35707836SJohn.Forte@Sun.COM 	return (ret);
35717836SJohn.Forte@Sun.COM }
35727836SJohn.Forte@Sun.COM 
35737836SJohn.Forte@Sun.COM 
35747836SJohn.Forte@Sun.COM /*
35757836SJohn.Forte@Sun.COM  * psRemoveHostGroupMember
35767836SJohn.Forte@Sun.COM  *
35777836SJohn.Forte@Sun.COM  * Remove a host group member from a host group,
35787836SJohn.Forte@Sun.COM  *
35797836SJohn.Forte@Sun.COM  * groupName - name of group from which the member is removed
35807836SJohn.Forte@Sun.COM  * memberName - name of group member to remove
35817836SJohn.Forte@Sun.COM  *
35827836SJohn.Forte@Sun.COM  * returns:
35837836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
35847836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
35857836SJohn.Forte@Sun.COM  */
35867836SJohn.Forte@Sun.COM int
35877836SJohn.Forte@Sun.COM psRemoveHostGroupMember(char *groupName, char *memberName)
35887836SJohn.Forte@Sun.COM {
35897836SJohn.Forte@Sun.COM 	int ret;
35907836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
35917836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
35927836SJohn.Forte@Sun.COM 
35937836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName,
35947836SJohn.Forte@Sun.COM 	    groupPropName);
35957836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
35967836SJohn.Forte@Sun.COM 		return (ret);
35977836SJohn.Forte@Sun.COM 	}
35987836SJohn.Forte@Sun.COM 
35997836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
36007836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
36017836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
36027836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
36037836SJohn.Forte@Sun.COM 		    groupPropName);
36047836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
36057836SJohn.Forte@Sun.COM 	}
36067836SJohn.Forte@Sun.COM 
36077836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS, groupPropListName,
36087836SJohn.Forte@Sun.COM 	    memberName, REMOVE));
36097836SJohn.Forte@Sun.COM }
36107836SJohn.Forte@Sun.COM 
36117836SJohn.Forte@Sun.COM /*
36127836SJohn.Forte@Sun.COM  * psRemoveTargetGroupMember
36137836SJohn.Forte@Sun.COM  *
36147836SJohn.Forte@Sun.COM  * Remove a target port group member from an target port group,
36157836SJohn.Forte@Sun.COM  *
36167836SJohn.Forte@Sun.COM  * groupName - name of group from which the member is removed
36177836SJohn.Forte@Sun.COM  * memberName - name of group member to remove
36187836SJohn.Forte@Sun.COM  *
36197836SJohn.Forte@Sun.COM  * returns:
36207836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
36217836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
36227836SJohn.Forte@Sun.COM  */
36237836SJohn.Forte@Sun.COM int
36247836SJohn.Forte@Sun.COM psRemoveTargetGroupMember(char *groupName, char *memberName)
36257836SJohn.Forte@Sun.COM {
36267836SJohn.Forte@Sun.COM 	int ret;
36277836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
36287836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
36297836SJohn.Forte@Sun.COM 
36307836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName,
36317836SJohn.Forte@Sun.COM 	    groupPropName);
36327836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
36337836SJohn.Forte@Sun.COM 		return (ret);
36347836SJohn.Forte@Sun.COM 	}
36357836SJohn.Forte@Sun.COM 
36367836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
36377836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
36387836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
36397836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
36407836SJohn.Forte@Sun.COM 		    groupPropName);
36417836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
36427836SJohn.Forte@Sun.COM 	}
36437836SJohn.Forte@Sun.COM 
36447836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS, groupPropListName,
36457836SJohn.Forte@Sun.COM 	    memberName, REMOVE));
36467836SJohn.Forte@Sun.COM }
36477836SJohn.Forte@Sun.COM 
36487836SJohn.Forte@Sun.COM /*
36497836SJohn.Forte@Sun.COM  * psGetProviderData
36507836SJohn.Forte@Sun.COM  *
36517836SJohn.Forte@Sun.COM  * Retrieves an nvlist on a per provider basis
36527836SJohn.Forte@Sun.COM  *
36537836SJohn.Forte@Sun.COM  * providerName - property group name to use
36547836SJohn.Forte@Sun.COM  * nvl - nvlist to retrieve
36557836SJohn.Forte@Sun.COM  *
36567836SJohn.Forte@Sun.COM  */
36577836SJohn.Forte@Sun.COM int
36587836SJohn.Forte@Sun.COM psGetProviderData(char *providerName, nvlist_t **nvl, int providerType,
36597836SJohn.Forte@Sun.COM     uint64_t *setToken)
36607836SJohn.Forte@Sun.COM {
36617836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
36627836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
36637836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
36647836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
36657836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
36667836SJohn.Forte@Sun.COM 	uint64_t blockCnt = 0;
36677836SJohn.Forte@Sun.COM 	ssize_t blockOffset = 0;
36687836SJohn.Forte@Sun.COM 	ssize_t actualBlockSize = 0;
36697836SJohn.Forte@Sun.COM 	char pgName[MAXPATHLEN];
36707836SJohn.Forte@Sun.COM 	char dataPropertyName[STMF_PROVIDER_DATA_PROP_NAME_SIZE];
36717836SJohn.Forte@Sun.COM 	char *nvlistEncoded = NULL;
36727836SJohn.Forte@Sun.COM 	ssize_t nvlistEncodedSize = 0;
36737836SJohn.Forte@Sun.COM 	boolean_t foundSetCnt = B_TRUE;
36747836SJohn.Forte@Sun.COM 	int i;
36757836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
36767836SJohn.Forte@Sun.COM 
36777836SJohn.Forte@Sun.COM 	if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
36787836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE)) {
36797836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_INVALID_ARG;
36807836SJohn.Forte@Sun.COM 		goto out;
36817836SJohn.Forte@Sun.COM 	}
36827836SJohn.Forte@Sun.COM 
36837836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
36847836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
36857836SJohn.Forte@Sun.COM 		goto out;
36867836SJohn.Forte@Sun.COM 	}
36877836SJohn.Forte@Sun.COM 
36887836SJohn.Forte@Sun.COM 	/*
36897836SJohn.Forte@Sun.COM 	 * create the property group name
36907836SJohn.Forte@Sun.COM 	 */
36917836SJohn.Forte@Sun.COM 	(void) snprintf(pgName, sizeof (pgName), "%s%s",
36927836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PREFIX, providerName);
36937836SJohn.Forte@Sun.COM 
36947836SJohn.Forte@Sun.COM 	/*
36957836SJohn.Forte@Sun.COM 	 * Allocate scf resources
36967836SJohn.Forte@Sun.COM 	 */
36977836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
36987836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL) ||
36997836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL)) {
37007836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
37017836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
37027836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
37037836SJohn.Forte@Sun.COM 		goto out;
37047836SJohn.Forte@Sun.COM 	}
37057836SJohn.Forte@Sun.COM 
37067836SJohn.Forte@Sun.COM 	/*
37077836SJohn.Forte@Sun.COM 	 * Retrieve the existing property group.
37087836SJohn.Forte@Sun.COM 	 */
37097836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
37107836SJohn.Forte@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
37117836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
37127836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
37137836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
37147836SJohn.Forte@Sun.COM 			goto out;
37157836SJohn.Forte@Sun.COM 		} else {
37167836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
37177836SJohn.Forte@Sun.COM 			goto out;
37187836SJohn.Forte@Sun.COM 		}
37197836SJohn.Forte@Sun.COM 	}
37207836SJohn.Forte@Sun.COM 
37217836SJohn.Forte@Sun.COM 	/*
37227836SJohn.Forte@Sun.COM 	 * Get the STMF_PROVIDER_DATA_PROP_COUNT property
37237836SJohn.Forte@Sun.COM 	 */
37247836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_COUNT,
37257836SJohn.Forte@Sun.COM 	    prop) == -1) {
37267836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
37277836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
37287836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
37297836SJohn.Forte@Sun.COM 		goto out;
37307836SJohn.Forte@Sun.COM 	}
37317836SJohn.Forte@Sun.COM 
37327836SJohn.Forte@Sun.COM 	/*
37337836SJohn.Forte@Sun.COM 	 * Get the STMF_PROVIDER_DATA_PROP_COUNT value
37347836SJohn.Forte@Sun.COM 	 */
37357836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
37367836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property value failed - %s",
37377836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
37387836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
37397836SJohn.Forte@Sun.COM 		goto out;
37407836SJohn.Forte@Sun.COM 	}
37417836SJohn.Forte@Sun.COM 
37427836SJohn.Forte@Sun.COM 	/*
37437836SJohn.Forte@Sun.COM 	 * Now get the actual value from the value handle
37447836SJohn.Forte@Sun.COM 	 */
37457836SJohn.Forte@Sun.COM 	if (scf_value_get_count(value, &blockCnt) == -1) {
37467836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get integer value failed - %s",
37477836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
37487836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
37497836SJohn.Forte@Sun.COM 		goto out;
37507836SJohn.Forte@Sun.COM 	}
37517836SJohn.Forte@Sun.COM 
37527836SJohn.Forte@Sun.COM 	/* Has the caller requested the token to be set? */
37537836SJohn.Forte@Sun.COM 	if (setToken) {
37547836SJohn.Forte@Sun.COM 		/*
37557836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
37567836SJohn.Forte@Sun.COM 		 * If it doesn't exist, we assume it to be zero.
37577836SJohn.Forte@Sun.COM 		 */
37587836SJohn.Forte@Sun.COM 		*setToken = 0;
37597836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_SET_COUNT,
37607836SJohn.Forte@Sun.COM 		    prop) == -1) {
37617836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND) {
37627836SJohn.Forte@Sun.COM 				foundSetCnt = B_FALSE;
37637836SJohn.Forte@Sun.COM 			} else {
37647836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "get property failed - %s",
37657836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
37667836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
37677836SJohn.Forte@Sun.COM 				goto out;
37687836SJohn.Forte@Sun.COM 			}
37697836SJohn.Forte@Sun.COM 		}
37707836SJohn.Forte@Sun.COM 
37717836SJohn.Forte@Sun.COM 		if (foundSetCnt) {
37727836SJohn.Forte@Sun.COM 			/*
37737836SJohn.Forte@Sun.COM 			 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
37747836SJohn.Forte@Sun.COM 			 */
37757836SJohn.Forte@Sun.COM 			if (scf_property_get_value(prop, value) == -1) {
37767836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
37777836SJohn.Forte@Sun.COM 				    "get property value failed - %s",
37787836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
37797836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
37807836SJohn.Forte@Sun.COM 				goto out;
37817836SJohn.Forte@Sun.COM 			}
37827836SJohn.Forte@Sun.COM 
37837836SJohn.Forte@Sun.COM 			/*
37847836SJohn.Forte@Sun.COM 			 * Now get the actual value from the value handle
37857836SJohn.Forte@Sun.COM 			 * and set the caller's token
37867836SJohn.Forte@Sun.COM 			 */
37877836SJohn.Forte@Sun.COM 			if (scf_value_get_count(value, setToken) == -1) {
37887836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
37897836SJohn.Forte@Sun.COM 				    "get integer value failed - %s",
37907836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
37917836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
37927836SJohn.Forte@Sun.COM 				goto out;
37937836SJohn.Forte@Sun.COM 			}
37947836SJohn.Forte@Sun.COM 		}
37957836SJohn.Forte@Sun.COM 	}
37967836SJohn.Forte@Sun.COM 
37977836SJohn.Forte@Sun.COM 	nvlistEncoded = (char *)calloc(1,
37987836SJohn.Forte@Sun.COM 	    blockCnt * STMF_PROVIDER_DATA_PROP_SIZE);
37997836SJohn.Forte@Sun.COM 	if (nvlistEncoded == NULL) {
38007836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "nvlistEncoded alloc failed");
38017836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
38027836SJohn.Forte@Sun.COM 		goto out;
38037836SJohn.Forte@Sun.COM 	}
38047836SJohn.Forte@Sun.COM 
38057836SJohn.Forte@Sun.COM 	for (i = 0; i < blockCnt; i++) {
38067836SJohn.Forte@Sun.COM 		bzero(dataPropertyName, sizeof (dataPropertyName));
38077836SJohn.Forte@Sun.COM 		/*
38087836SJohn.Forte@Sun.COM 		 * create the name to use for the property
38097836SJohn.Forte@Sun.COM 		 */
38107836SJohn.Forte@Sun.COM 		(void) snprintf(dataPropertyName, sizeof (dataPropertyName),
38117836SJohn.Forte@Sun.COM 		    "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
38127836SJohn.Forte@Sun.COM 
38137836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, dataPropertyName, prop) == -1) {
38147836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
38157836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
38167836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
38177836SJohn.Forte@Sun.COM 			goto out;
38187836SJohn.Forte@Sun.COM 		}
38197836SJohn.Forte@Sun.COM 
38207836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
38217836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
38227836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
38237836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
38247836SJohn.Forte@Sun.COM 			goto out;
38257836SJohn.Forte@Sun.COM 		}
38267836SJohn.Forte@Sun.COM 
38277836SJohn.Forte@Sun.COM 		/*
38287836SJohn.Forte@Sun.COM 		 * Set the data block offset
38297836SJohn.Forte@Sun.COM 		 */
38307836SJohn.Forte@Sun.COM 		blockOffset = STMF_PROVIDER_DATA_PROP_SIZE * i;
38317836SJohn.Forte@Sun.COM 		actualBlockSize = scf_value_get_opaque(value,
38327836SJohn.Forte@Sun.COM 		    &nvlistEncoded[blockOffset], STMF_PROVIDER_DATA_PROP_SIZE);
38337836SJohn.Forte@Sun.COM 		if (actualBlockSize == -1) {
38347836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get opaque property value failed - %s",
38357836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
38367836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
38377836SJohn.Forte@Sun.COM 			goto out;
38387836SJohn.Forte@Sun.COM 		}
38397836SJohn.Forte@Sun.COM 		nvlistEncodedSize += actualBlockSize;
38407836SJohn.Forte@Sun.COM 	}
38417836SJohn.Forte@Sun.COM 
38427836SJohn.Forte@Sun.COM 	if (nvlist_unpack(nvlistEncoded, nvlistEncodedSize, nvl, 0) != 0) {
38437836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "unable to unpack nvlist");
38447836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
38457836SJohn.Forte@Sun.COM 		goto out;
38467836SJohn.Forte@Sun.COM 	}
38477836SJohn.Forte@Sun.COM 
38487836SJohn.Forte@Sun.COM 
38497836SJohn.Forte@Sun.COM out:
38507836SJohn.Forte@Sun.COM 	/*
38517836SJohn.Forte@Sun.COM 	 * Free resources
38527836SJohn.Forte@Sun.COM 	 */
38537836SJohn.Forte@Sun.COM 	if (handle != NULL) {
38547836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
38557836SJohn.Forte@Sun.COM 	}
38567836SJohn.Forte@Sun.COM 	if (svc != NULL) {
38577836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
38587836SJohn.Forte@Sun.COM 	}
38597836SJohn.Forte@Sun.COM 	if (pg != NULL) {
38607836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
38617836SJohn.Forte@Sun.COM 	}
38627836SJohn.Forte@Sun.COM 	if (prop != NULL) {
38637836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
38647836SJohn.Forte@Sun.COM 	}
38657836SJohn.Forte@Sun.COM 	if (value != NULL) {
38667836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
38677836SJohn.Forte@Sun.COM 	}
38687836SJohn.Forte@Sun.COM 	if (nvlistEncoded != NULL) {
38697836SJohn.Forte@Sun.COM 		free(nvlistEncoded);
38707836SJohn.Forte@Sun.COM 	}
38717836SJohn.Forte@Sun.COM 
38727836SJohn.Forte@Sun.COM 	return (ret);
38737836SJohn.Forte@Sun.COM 
38747836SJohn.Forte@Sun.COM }
38757836SJohn.Forte@Sun.COM /*
38767836SJohn.Forte@Sun.COM  * psGetProviderDataList
38777836SJohn.Forte@Sun.COM  *
38787836SJohn.Forte@Sun.COM  * Retrieves the list of providers that currently store persistent data
38797836SJohn.Forte@Sun.COM  *
38807836SJohn.Forte@Sun.COM  * providerList - pointer to a pointer to an stmfProviderList structure
38817836SJohn.Forte@Sun.COM  *                On success, this will contain the list of providers
38827836SJohn.Forte@Sun.COM  *                currently storing persistent data.
38837836SJohn.Forte@Sun.COM  */
38847836SJohn.Forte@Sun.COM int
38857836SJohn.Forte@Sun.COM psGetProviderDataList(stmfProviderList **providerList)
38867836SJohn.Forte@Sun.COM {
38877836SJohn.Forte@Sun.COM 	scf_handle_t *handle = NULL;
38887836SJohn.Forte@Sun.COM 	scf_service_t *svc = NULL;
38897836SJohn.Forte@Sun.COM 	scf_propertygroup_t *pg = NULL;
38907836SJohn.Forte@Sun.COM 	scf_property_t *prop = NULL;
38917836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
38927836SJohn.Forte@Sun.COM 	scf_iter_t *pgIter = NULL;
38937836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
38947836SJohn.Forte@Sun.COM 	int providerCnt = 0;
38957836SJohn.Forte@Sun.COM 	int64_t providerType;
38967836SJohn.Forte@Sun.COM 	int i = 0, j;
38977836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
38987836SJohn.Forte@Sun.COM 
38997836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
39007836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
39017836SJohn.Forte@Sun.COM 		goto out;
39027836SJohn.Forte@Sun.COM 	}
39037836SJohn.Forte@Sun.COM 
39047836SJohn.Forte@Sun.COM 	*providerList = NULL;
39057836SJohn.Forte@Sun.COM 
39067836SJohn.Forte@Sun.COM 	/*
39077836SJohn.Forte@Sun.COM 	 * Allocate scf resources
39087836SJohn.Forte@Sun.COM 	 */
39097836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
39107836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL) ||
39117836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
39127836SJohn.Forte@Sun.COM 	    ((pgIter = scf_iter_create(handle)) == NULL)) {
39137836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
39147836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
39157836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
39167836SJohn.Forte@Sun.COM 		goto out;
39177836SJohn.Forte@Sun.COM 	}
39187836SJohn.Forte@Sun.COM 
39197836SJohn.Forte@Sun.COM 	/*
39207836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
39217836SJohn.Forte@Sun.COM 	 */
39227836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
39237836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
39247836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
39257836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
39267836SJohn.Forte@Sun.COM 		goto out;
39277836SJohn.Forte@Sun.COM 	}
39287836SJohn.Forte@Sun.COM 
39297836SJohn.Forte@Sun.COM 	while (scf_iter_next_pg(pgIter, pg) == 1) {
39307836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
39317836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
39327836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
39337836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
39347836SJohn.Forte@Sun.COM 			break;
39357836SJohn.Forte@Sun.COM 		}
39367836SJohn.Forte@Sun.COM 		/*
39377836SJohn.Forte@Sun.COM 		 * Only count LU property groups
39387836SJohn.Forte@Sun.COM 		 */
39397836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_PROVIDER_DATA_PREFIX,
39407836SJohn.Forte@Sun.COM 		    strlen(STMF_PROVIDER_DATA_PREFIX)) == 0) {
39417836SJohn.Forte@Sun.COM 			providerCnt++;
39427836SJohn.Forte@Sun.COM 		}
39437836SJohn.Forte@Sun.COM 	}
39447836SJohn.Forte@Sun.COM 
39457836SJohn.Forte@Sun.COM 	/*
39467836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
39477836SJohn.Forte@Sun.COM 	 */
39487836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
39497836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
39507836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
39517836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
39527836SJohn.Forte@Sun.COM 		goto out;
39537836SJohn.Forte@Sun.COM 	}
39547836SJohn.Forte@Sun.COM 
39557836SJohn.Forte@Sun.COM 	*providerList = (stmfProviderList *)calloc(1,
39567836SJohn.Forte@Sun.COM 	    sizeof (stmfProviderList) + providerCnt * sizeof (stmfProvider));
39577836SJohn.Forte@Sun.COM 	if (*providerList == NULL) {
39587836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
39597836SJohn.Forte@Sun.COM 		goto out;
39607836SJohn.Forte@Sun.COM 	}
39617836SJohn.Forte@Sun.COM 
39627836SJohn.Forte@Sun.COM 	/*
39637836SJohn.Forte@Sun.COM 	 * it's possible for entries to be added/removed while we're retrieving
39647836SJohn.Forte@Sun.COM 	 * the property groups. Just make sure we don't write beyond our
39657836SJohn.Forte@Sun.COM 	 * allocated buffer by checking to ensure i < providerCnt.
39667836SJohn.Forte@Sun.COM 	 */
39677836SJohn.Forte@Sun.COM 	while ((scf_iter_next_pg(pgIter, pg) == 1) && (i < providerCnt)) {
39687836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
39697836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
39707836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
39717836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
39727836SJohn.Forte@Sun.COM 			break;
39737836SJohn.Forte@Sun.COM 		}
39747836SJohn.Forte@Sun.COM 		/*
39757836SJohn.Forte@Sun.COM 		 * Only use provider data property groups
39767836SJohn.Forte@Sun.COM 		 */
39777836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_PROVIDER_DATA_PREFIX,
39787836SJohn.Forte@Sun.COM 		    strlen(STMF_PROVIDER_DATA_PREFIX)) != 0) {
39797836SJohn.Forte@Sun.COM 			continue;
39807836SJohn.Forte@Sun.COM 		}
39817836SJohn.Forte@Sun.COM 
39827836SJohn.Forte@Sun.COM 		/*
39837836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_TYPE property
39847836SJohn.Forte@Sun.COM 		 */
39857836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_TYPE,
39867836SJohn.Forte@Sun.COM 		    prop) == -1) {
39877836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
39887836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
39897836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
39907836SJohn.Forte@Sun.COM 			break;
39917836SJohn.Forte@Sun.COM 		}
39927836SJohn.Forte@Sun.COM 
39937836SJohn.Forte@Sun.COM 		/*
39947836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_TYPE value
39957836SJohn.Forte@Sun.COM 		 */
39967836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
39977836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
39987836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
39997836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
40007836SJohn.Forte@Sun.COM 			break;
40017836SJohn.Forte@Sun.COM 		}
40027836SJohn.Forte@Sun.COM 
40037836SJohn.Forte@Sun.COM 		/*
40047836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
40057836SJohn.Forte@Sun.COM 		 */
40067836SJohn.Forte@Sun.COM 		if (scf_value_get_integer(value, &providerType) == -1) {
40077836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get integer value failed - %s",
40087836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
40097836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
40107836SJohn.Forte@Sun.COM 			break;
40117836SJohn.Forte@Sun.COM 		}
40127836SJohn.Forte@Sun.COM 
40137836SJohn.Forte@Sun.COM 		(*providerList)->provider[i].providerType = providerType;
40147836SJohn.Forte@Sun.COM 
40157836SJohn.Forte@Sun.COM 		/* determine offset for copy of provider name */
40167836SJohn.Forte@Sun.COM 		j = strlen(STMF_PROVIDER_DATA_PREFIX);
40177836SJohn.Forte@Sun.COM 
40187836SJohn.Forte@Sun.COM 		/* copy provider name to caller's list */
40197836SJohn.Forte@Sun.COM 		(void) strncpy((*providerList)->provider[i].name, buf + j,
40207836SJohn.Forte@Sun.COM 		    sizeof ((*providerList)->provider[i].name));
40217836SJohn.Forte@Sun.COM 		i++;
40227836SJohn.Forte@Sun.COM 		(*providerList)->cnt++;
40237836SJohn.Forte@Sun.COM 	}
40247836SJohn.Forte@Sun.COM 
40257836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
40267836SJohn.Forte@Sun.COM 		free(*providerList);
40277836SJohn.Forte@Sun.COM 		goto out;
40287836SJohn.Forte@Sun.COM 	}
40297836SJohn.Forte@Sun.COM 
40307836SJohn.Forte@Sun.COM out:
40317836SJohn.Forte@Sun.COM 	/*
40327836SJohn.Forte@Sun.COM 	 * Free resources
40337836SJohn.Forte@Sun.COM 	 */
40347836SJohn.Forte@Sun.COM 	if (handle != NULL) {
40357836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
40367836SJohn.Forte@Sun.COM 	}
40377836SJohn.Forte@Sun.COM 	if (svc != NULL) {
40387836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
40397836SJohn.Forte@Sun.COM 	}
40407836SJohn.Forte@Sun.COM 	if (pg != NULL) {
40417836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
40427836SJohn.Forte@Sun.COM 	}
40437836SJohn.Forte@Sun.COM 	if (value != NULL) {
40447836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
40457836SJohn.Forte@Sun.COM 	}
40467836SJohn.Forte@Sun.COM 	if (prop != NULL) {
40477836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
40487836SJohn.Forte@Sun.COM 	}
40497836SJohn.Forte@Sun.COM 	if (pgIter != NULL) {
40507836SJohn.Forte@Sun.COM 		scf_iter_destroy(pgIter);
40517836SJohn.Forte@Sun.COM 	}
40527836SJohn.Forte@Sun.COM 
40537836SJohn.Forte@Sun.COM 	return (ret);
40547836SJohn.Forte@Sun.COM }
40557836SJohn.Forte@Sun.COM 
40567836SJohn.Forte@Sun.COM 
40577836SJohn.Forte@Sun.COM /*
40587836SJohn.Forte@Sun.COM  * psSetProviderData
40597836SJohn.Forte@Sun.COM  *
40607836SJohn.Forte@Sun.COM  * Stores a packed nvlist on a per provider basis
40617836SJohn.Forte@Sun.COM  *
40627836SJohn.Forte@Sun.COM  * providerName - property group name to use
40637836SJohn.Forte@Sun.COM  * nvl - nvlist to store
40647836SJohn.Forte@Sun.COM  * providerType - type of provider (logical unit or port)
40657836SJohn.Forte@Sun.COM  *
40667836SJohn.Forte@Sun.COM  */
40677836SJohn.Forte@Sun.COM int
40687836SJohn.Forte@Sun.COM psSetProviderData(char *providerName, nvlist_t *nvl, int providerType,
40697836SJohn.Forte@Sun.COM     uint64_t *setToken)
40707836SJohn.Forte@Sun.COM {
40717836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
40727836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
40737836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
40747836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
40757836SJohn.Forte@Sun.COM 	scf_transaction_t *tran = NULL;
40767836SJohn.Forte@Sun.COM 	/* represents arrays of entry and value pointers for scf */
40777836SJohn.Forte@Sun.COM 	scf_transaction_entry_t	**addEntry = NULL;
40787836SJohn.Forte@Sun.COM 	scf_transaction_entry_t	**deleteEntry = NULL;
40797836SJohn.Forte@Sun.COM 	scf_value_t **addValue = NULL;
40807836SJohn.Forte@Sun.COM 
40817836SJohn.Forte@Sun.COM 	/*
40827836SJohn.Forte@Sun.COM 	 * These declarations are for known entry and value set/get
40837836SJohn.Forte@Sun.COM 	 * operations
40847836SJohn.Forte@Sun.COM 	 */
40857836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry1 = NULL;
40867836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry2 = NULL;
40877836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry3 = NULL;
40887836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry5 = NULL;
40897836SJohn.Forte@Sun.COM 	scf_value_t *value1 = NULL;
40907836SJohn.Forte@Sun.COM 	scf_value_t *value2 = NULL;
40917836SJohn.Forte@Sun.COM 	scf_value_t *value3 = NULL;
40927836SJohn.Forte@Sun.COM 	scf_value_t *value4 = NULL;
40937836SJohn.Forte@Sun.COM 	scf_value_t *value5 = NULL;
40947836SJohn.Forte@Sun.COM 
40957836SJohn.Forte@Sun.COM 	boolean_t newPg = B_FALSE;
40967836SJohn.Forte@Sun.COM 	char pgName[MAXPATHLEN];
40977836SJohn.Forte@Sun.COM 	char dataPropertyName[STMF_PROVIDER_DATA_PROP_NAME_SIZE];
40987836SJohn.Forte@Sun.COM 	char *nvlistEncoded = NULL;
40997836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
41007836SJohn.Forte@Sun.COM 	size_t blockSize;
41017836SJohn.Forte@Sun.COM 	int i, j = 0;
41027836SJohn.Forte@Sun.COM 	int addEntryAlloc = 0, deleteEntryAlloc = 0, addValueAlloc = 0;
41037836SJohn.Forte@Sun.COM 	int blockOffset;
41047836SJohn.Forte@Sun.COM 	uint64_t oldBlockCnt = 0;
41057836SJohn.Forte@Sun.COM 	uint64_t blockCnt = 0;
41067836SJohn.Forte@Sun.COM 	uint64_t setCnt = 0;
41077836SJohn.Forte@Sun.COM 	boolean_t foundSetCnt = B_TRUE;
41087836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
41097836SJohn.Forte@Sun.COM 	int commitRet;
41107836SJohn.Forte@Sun.COM 
41117836SJohn.Forte@Sun.COM 	if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
41127836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE)) {
41137836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_INVALID_ARG;
41147836SJohn.Forte@Sun.COM 		goto out;
41157836SJohn.Forte@Sun.COM 	}
41167836SJohn.Forte@Sun.COM 
41177836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
41187836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
41197836SJohn.Forte@Sun.COM 		goto out;
41207836SJohn.Forte@Sun.COM 	}
41217836SJohn.Forte@Sun.COM 
41227836SJohn.Forte@Sun.COM 	bzero(pgName, sizeof (pgName));
41237836SJohn.Forte@Sun.COM 	/*
41247836SJohn.Forte@Sun.COM 	 * create the property group name
41257836SJohn.Forte@Sun.COM 	 */
41267836SJohn.Forte@Sun.COM 	(void) snprintf(pgName, sizeof (pgName), "%s%s",
41277836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PREFIX, providerName);
41287836SJohn.Forte@Sun.COM 
41297836SJohn.Forte@Sun.COM 	/*
41307836SJohn.Forte@Sun.COM 	 * Allocate scf resources
41317836SJohn.Forte@Sun.COM 	 */
41327836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
41337836SJohn.Forte@Sun.COM 	    ((entry1 = scf_entry_create(handle)) == NULL) ||
41347836SJohn.Forte@Sun.COM 	    ((entry2 = scf_entry_create(handle)) == NULL) ||
41357836SJohn.Forte@Sun.COM 	    ((entry3 = scf_entry_create(handle)) == NULL) ||
41367836SJohn.Forte@Sun.COM 	    ((entry5 = scf_entry_create(handle)) == NULL) ||
41377836SJohn.Forte@Sun.COM 	    ((value1 = scf_value_create(handle)) == NULL) ||
41387836SJohn.Forte@Sun.COM 	    ((value2 = scf_value_create(handle)) == NULL) ||
41397836SJohn.Forte@Sun.COM 	    ((value3 = scf_value_create(handle)) == NULL) ||
41407836SJohn.Forte@Sun.COM 	    ((value4 = scf_value_create(handle)) == NULL) ||
41417836SJohn.Forte@Sun.COM 	    ((value5 = scf_value_create(handle)) == NULL) ||
41427836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
41437836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL)) {
41447836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
41457836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
41467836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
41477836SJohn.Forte@Sun.COM 		goto out;
41487836SJohn.Forte@Sun.COM 	}
41497836SJohn.Forte@Sun.COM 
41507836SJohn.Forte@Sun.COM 	/*
41517836SJohn.Forte@Sun.COM 	 * Get the existing property group
41527836SJohn.Forte@Sun.COM 	 */
41537836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
41547836SJohn.Forte@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
41557836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
41567836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
41577836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
41587836SJohn.Forte@Sun.COM 			goto out;
41597836SJohn.Forte@Sun.COM 		} else {
41607836SJohn.Forte@Sun.COM 			/*
41617836SJohn.Forte@Sun.COM 			 * create the property group.
41627836SJohn.Forte@Sun.COM 			 */
41637836SJohn.Forte@Sun.COM 			if (scf_service_add_pg(svc, pgName,
41647836SJohn.Forte@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
41657836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
41667836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
41677836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
41687836SJohn.Forte@Sun.COM 				goto out;
41697836SJohn.Forte@Sun.COM 			}
41707836SJohn.Forte@Sun.COM 			newPg = B_TRUE;
41717836SJohn.Forte@Sun.COM 		}
41727836SJohn.Forte@Sun.COM 	}
41737836SJohn.Forte@Sun.COM 
41747836SJohn.Forte@Sun.COM 	/*
41757836SJohn.Forte@Sun.COM 	 * Begin the transaction
41767836SJohn.Forte@Sun.COM 	 */
41777836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
41787836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
41797836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
41807836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
41817836SJohn.Forte@Sun.COM 		goto out;
41827836SJohn.Forte@Sun.COM 	}
41837836SJohn.Forte@Sun.COM 
41847836SJohn.Forte@Sun.COM 	if (!newPg) {
41857836SJohn.Forte@Sun.COM 		/*
41867836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_COUNT property
41877836SJohn.Forte@Sun.COM 		 */
41887836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_COUNT,
41897836SJohn.Forte@Sun.COM 		    prop) == -1) {
41907836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
41917836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
41927836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
41937836SJohn.Forte@Sun.COM 			goto out;
41947836SJohn.Forte@Sun.COM 		}
41957836SJohn.Forte@Sun.COM 
41967836SJohn.Forte@Sun.COM 		/*
41977836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_COUNT value
41987836SJohn.Forte@Sun.COM 		 */
41997836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value4) == -1) {
42007836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
42017836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
42027836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
42037836SJohn.Forte@Sun.COM 			goto out;
42047836SJohn.Forte@Sun.COM 		}
42057836SJohn.Forte@Sun.COM 
42067836SJohn.Forte@Sun.COM 		/*
42077836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
42087836SJohn.Forte@Sun.COM 		 */
42097836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value4, &oldBlockCnt) == -1) {
42107836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get integer value failed - %s",
42117836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
42127836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
42137836SJohn.Forte@Sun.COM 			goto out;
42147836SJohn.Forte@Sun.COM 		}
42157836SJohn.Forte@Sun.COM 	}
42167836SJohn.Forte@Sun.COM 
42177836SJohn.Forte@Sun.COM 	/*
42187836SJohn.Forte@Sun.COM 	 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
42197836SJohn.Forte@Sun.COM 	 * If it doesn't exist, we'll create it later after successfully
42207836SJohn.Forte@Sun.COM 	 * setting the data.
42217836SJohn.Forte@Sun.COM 	 */
42227836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_SET_COUNT,
42237836SJohn.Forte@Sun.COM 	    prop) == -1) {
42247836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
42257836SJohn.Forte@Sun.COM 			foundSetCnt = B_FALSE;
42267836SJohn.Forte@Sun.COM 		} else {
42277836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
42287836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
42297836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
42307836SJohn.Forte@Sun.COM 			goto out;
42317836SJohn.Forte@Sun.COM 		}
42327836SJohn.Forte@Sun.COM 	}
42337836SJohn.Forte@Sun.COM 
42347836SJohn.Forte@Sun.COM 	if (foundSetCnt) {
42357836SJohn.Forte@Sun.COM 		/*
42367836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
42377836SJohn.Forte@Sun.COM 		 */
42387836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value5) == -1) {
42397836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
42407836SJohn.Forte@Sun.COM 			    "get property value failed - %s",
42417836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
42427836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
42437836SJohn.Forte@Sun.COM 			goto out;
42447836SJohn.Forte@Sun.COM 		}
42457836SJohn.Forte@Sun.COM 
42467836SJohn.Forte@Sun.COM 		/*
42477836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
42487836SJohn.Forte@Sun.COM 		 */
42497836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value5, &setCnt) == -1) {
42507836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
42517836SJohn.Forte@Sun.COM 			    "get integer value failed - %s",
42527836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
42537836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
42547836SJohn.Forte@Sun.COM 			goto out;
42557836SJohn.Forte@Sun.COM 		}
42567836SJohn.Forte@Sun.COM 
42577836SJohn.Forte@Sun.COM 		/*
42587836SJohn.Forte@Sun.COM 		 * Compare the setCnt prop to the caller's.
42597836SJohn.Forte@Sun.COM 		 */
42607836SJohn.Forte@Sun.COM 		if (setToken && (*setToken != setCnt)) {
42617836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_PROV_DATA_STALE;
42627836SJohn.Forte@Sun.COM 			goto out;
42637836SJohn.Forte@Sun.COM 		}
42647836SJohn.Forte@Sun.COM 	}
42657836SJohn.Forte@Sun.COM 
42667836SJohn.Forte@Sun.COM 	setCnt++;
42677836SJohn.Forte@Sun.COM 
42687836SJohn.Forte@Sun.COM 	/*
42697836SJohn.Forte@Sun.COM 	 * prepare the list for writing
42707836SJohn.Forte@Sun.COM 	 */
42717836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &nvlistEncoded, &nvlistEncodedSize,
42727836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
42737836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "nvlist_pack failed");
42747836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
42757836SJohn.Forte@Sun.COM 		goto out;
42767836SJohn.Forte@Sun.COM 	}
42777836SJohn.Forte@Sun.COM 
42787836SJohn.Forte@Sun.COM 	/* Determine how many chunks we need to write */
42797836SJohn.Forte@Sun.COM 	blockCnt = nvlistEncodedSize/STMF_PROVIDER_DATA_PROP_SIZE;
42807836SJohn.Forte@Sun.COM 	if (nvlistEncodedSize % STMF_PROVIDER_DATA_PROP_SIZE)
42817836SJohn.Forte@Sun.COM 		blockCnt++;
42827836SJohn.Forte@Sun.COM 
42837836SJohn.Forte@Sun.COM 	/* allocate entry and value resources for writing those chunks */
42847836SJohn.Forte@Sun.COM 	addEntry = (scf_transaction_entry_t **)calloc(1, sizeof (*addEntry)
42857836SJohn.Forte@Sun.COM 	    * blockCnt);
42867836SJohn.Forte@Sun.COM 	if (addEntry == NULL) {
42877836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "addEntry alloc failed");
42887836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
42897836SJohn.Forte@Sun.COM 		goto out;
42907836SJohn.Forte@Sun.COM 	}
42917836SJohn.Forte@Sun.COM 
42927836SJohn.Forte@Sun.COM 	addValue = (scf_value_t **)calloc(1, sizeof (*addValue)
42937836SJohn.Forte@Sun.COM 	    * blockCnt);
42947836SJohn.Forte@Sun.COM 	if (addValue == NULL) {
42957836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "value alloc failed");
42967836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
42977836SJohn.Forte@Sun.COM 		goto out;
42987836SJohn.Forte@Sun.COM 	}
42997836SJohn.Forte@Sun.COM 
43007836SJohn.Forte@Sun.COM 	/*
43017836SJohn.Forte@Sun.COM 	 * allocate entry delete resources for deleting anything existing
43027836SJohn.Forte@Sun.COM 	 * that is more than the new block count. We could leave them around
43037836SJohn.Forte@Sun.COM 	 * without suffering any ill effects but it will be cleaner to look at
43047836SJohn.Forte@Sun.COM 	 * in smf tools if they are deleted.
43057836SJohn.Forte@Sun.COM 	 */
43067836SJohn.Forte@Sun.COM 	if (oldBlockCnt > blockCnt) {
43077836SJohn.Forte@Sun.COM 		deleteEntry = (scf_transaction_entry_t **)calloc(1,
43087836SJohn.Forte@Sun.COM 		    sizeof (*deleteEntry) * (oldBlockCnt - blockCnt));
43097836SJohn.Forte@Sun.COM 		if (deleteEntry == NULL) {
43107836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "deleteEntry alloc failed");
43117836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOMEM;
43127836SJohn.Forte@Sun.COM 			goto out;
43137836SJohn.Forte@Sun.COM 		}
43147836SJohn.Forte@Sun.COM 		deleteEntryAlloc = oldBlockCnt - blockCnt;
43157836SJohn.Forte@Sun.COM 	}
43167836SJohn.Forte@Sun.COM 
43177836SJohn.Forte@Sun.COM 
43187836SJohn.Forte@Sun.COM 	for (i = 0; i < blockCnt; i++) {
43197836SJohn.Forte@Sun.COM 		/*
43207836SJohn.Forte@Sun.COM 		 * Create the entry resource for the prop
43217836SJohn.Forte@Sun.COM 		 */
43227836SJohn.Forte@Sun.COM 		addEntry[i] = scf_entry_create(handle);
43237836SJohn.Forte@Sun.COM 		if (addEntry[i] == NULL) {
43247836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
43257836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
43267836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
43277836SJohn.Forte@Sun.COM 			goto out;
43287836SJohn.Forte@Sun.COM 		}
43297836SJohn.Forte@Sun.COM 
43307836SJohn.Forte@Sun.COM 		/* bump alloc count for addEntry allocation */
43317836SJohn.Forte@Sun.COM 		addEntryAlloc++;
43327836SJohn.Forte@Sun.COM 
43337836SJohn.Forte@Sun.COM 		/*
43347836SJohn.Forte@Sun.COM 		 * create the name to use for the property
43357836SJohn.Forte@Sun.COM 		 */
43367836SJohn.Forte@Sun.COM 		(void) snprintf(dataPropertyName, sizeof (dataPropertyName),
43377836SJohn.Forte@Sun.COM 		    "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
43387836SJohn.Forte@Sun.COM 
43397836SJohn.Forte@Sun.COM 		/*
43407836SJohn.Forte@Sun.COM 		 * Create the new property
43417836SJohn.Forte@Sun.COM 		 */
43427836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, addEntry[i],
43437836SJohn.Forte@Sun.COM 		    dataPropertyName, SCF_TYPE_OPAQUE) == -1) {
43447836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
43457836SJohn.Forte@Sun.COM 				if (scf_transaction_property_change(tran,
43467836SJohn.Forte@Sun.COM 				    addEntry[i], dataPropertyName,
43477836SJohn.Forte@Sun.COM 				    SCF_TYPE_OPAQUE) == -1) {
43487836SJohn.Forte@Sun.COM 					syslog(LOG_ERR, "transaction property"
43497836SJohn.Forte@Sun.COM 					    "change failed - %s",
43507836SJohn.Forte@Sun.COM 					    scf_strerror(scf_error()));
43517836SJohn.Forte@Sun.COM 					ret = STMF_PS_ERROR;
43527836SJohn.Forte@Sun.COM 					goto out;
43537836SJohn.Forte@Sun.COM 				}
43547836SJohn.Forte@Sun.COM 			} else {
43557836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
43567836SJohn.Forte@Sun.COM 				    "transaction property new failed - %s",
43577836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
43587836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
43597836SJohn.Forte@Sun.COM 				goto out;
43607836SJohn.Forte@Sun.COM 			}
43617836SJohn.Forte@Sun.COM 		}
43627836SJohn.Forte@Sun.COM 		/*
43637836SJohn.Forte@Sun.COM 		 * Create the value resource for the prop
43647836SJohn.Forte@Sun.COM 		 */
43657836SJohn.Forte@Sun.COM 		addValue[i] = scf_value_create(handle);
43667836SJohn.Forte@Sun.COM 		if (addValue[i] == NULL) {
43677836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
43687836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
43697836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
43707836SJohn.Forte@Sun.COM 			goto out;
43717836SJohn.Forte@Sun.COM 		}
43727836SJohn.Forte@Sun.COM 
43737836SJohn.Forte@Sun.COM 		/* bump alloc count for addValue allocation */
43747836SJohn.Forte@Sun.COM 		addValueAlloc++;
43757836SJohn.Forte@Sun.COM 
43767836SJohn.Forte@Sun.COM 		/*
43777836SJohn.Forte@Sun.COM 		 * Set the data block offset and size
43787836SJohn.Forte@Sun.COM 		 */
43797836SJohn.Forte@Sun.COM 		if ((STMF_PROVIDER_DATA_PROP_SIZE * (i + 1))
43807836SJohn.Forte@Sun.COM 		    > nvlistEncodedSize) {
43817836SJohn.Forte@Sun.COM 			blockSize = nvlistEncodedSize
43827836SJohn.Forte@Sun.COM 			    - STMF_PROVIDER_DATA_PROP_SIZE * i;
43837836SJohn.Forte@Sun.COM 		} else {
43847836SJohn.Forte@Sun.COM 			blockSize = STMF_PROVIDER_DATA_PROP_SIZE;
43857836SJohn.Forte@Sun.COM 		}
43867836SJohn.Forte@Sun.COM 
43877836SJohn.Forte@Sun.COM 		blockOffset = STMF_PROVIDER_DATA_PROP_SIZE * i;
43887836SJohn.Forte@Sun.COM 		if (scf_value_set_opaque(addValue[i],
43897836SJohn.Forte@Sun.COM 		    &nvlistEncoded[blockOffset], blockSize) == -1) {
43907836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
43917836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
43927836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
43937836SJohn.Forte@Sun.COM 			goto out;
43947836SJohn.Forte@Sun.COM 		}
43957836SJohn.Forte@Sun.COM 
43967836SJohn.Forte@Sun.COM 		/*
43977836SJohn.Forte@Sun.COM 		 * Add the data block to the transaction entry
43987836SJohn.Forte@Sun.COM 		 */
43997836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(addEntry[i], addValue[i]) == -1) {
44007836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
44017836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44027836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44037836SJohn.Forte@Sun.COM 			goto out;
44047836SJohn.Forte@Sun.COM 		}
44057836SJohn.Forte@Sun.COM 	}
44067836SJohn.Forte@Sun.COM 
44077836SJohn.Forte@Sun.COM 	/*
44087836SJohn.Forte@Sun.COM 	 * Now we need to delete any chunks (properties) that are no longer
44097836SJohn.Forte@Sun.COM 	 * needed. Iterate through the rest of the chunks deleting each.
44107836SJohn.Forte@Sun.COM 	 */
44117836SJohn.Forte@Sun.COM 	for (i = blockCnt; i < oldBlockCnt; i++) {
44127836SJohn.Forte@Sun.COM 		/*
44137836SJohn.Forte@Sun.COM 		 * Create the entry resource for the prop
44147836SJohn.Forte@Sun.COM 		 */
44157836SJohn.Forte@Sun.COM 		deleteEntry[j] = scf_entry_create(handle);
44167836SJohn.Forte@Sun.COM 		if (deleteEntry[j] == NULL) {
44177836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
44187836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44197836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44207836SJohn.Forte@Sun.COM 			goto out;
44217836SJohn.Forte@Sun.COM 		}
44227836SJohn.Forte@Sun.COM 
44237836SJohn.Forte@Sun.COM 		/*
44247836SJohn.Forte@Sun.COM 		 * create the name to use for the property
44257836SJohn.Forte@Sun.COM 		 */
44267836SJohn.Forte@Sun.COM 		(void) snprintf(dataPropertyName, sizeof (dataPropertyName),
44277836SJohn.Forte@Sun.COM 		    "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
44287836SJohn.Forte@Sun.COM 
44297836SJohn.Forte@Sun.COM 		/*
44307836SJohn.Forte@Sun.COM 		 * Delete the existing property
44317836SJohn.Forte@Sun.COM 		 */
44327836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, deleteEntry[j++],
44337836SJohn.Forte@Sun.COM 		    dataPropertyName) == -1) {
44347836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
44357836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44367836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44377836SJohn.Forte@Sun.COM 			goto out;
44387836SJohn.Forte@Sun.COM 		}
44397836SJohn.Forte@Sun.COM 	}
44407836SJohn.Forte@Sun.COM 
44417836SJohn.Forte@Sun.COM 	if (newPg) {
44427836SJohn.Forte@Sun.COM 		/*
44437836SJohn.Forte@Sun.COM 		 * Ensure the read_authorization property is set
44447836SJohn.Forte@Sun.COM 		 * for the group
44457836SJohn.Forte@Sun.COM 		 */
44467836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry1,
44477836SJohn.Forte@Sun.COM 		    "read_authorization", SCF_TYPE_ASTRING) == -1) {
44487836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
44497836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44507836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44517836SJohn.Forte@Sun.COM 			goto out;
44527836SJohn.Forte@Sun.COM 		}
44537836SJohn.Forte@Sun.COM 
44547836SJohn.Forte@Sun.COM 		if (scf_value_set_astring(value1, STMF_SMF_READ_ATTR) == -1) {
44557836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
44567836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44577836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44587836SJohn.Forte@Sun.COM 			goto out;
44597836SJohn.Forte@Sun.COM 		}
44607836SJohn.Forte@Sun.COM 
44617836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry1, value1) == -1) {
44627836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
44637836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44647836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44657836SJohn.Forte@Sun.COM 			goto out;
44667836SJohn.Forte@Sun.COM 		}
44677836SJohn.Forte@Sun.COM 	}
44687836SJohn.Forte@Sun.COM 
44697836SJohn.Forte@Sun.COM 	/* create or change the count property */
44707836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry2,
44717836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PROP_COUNT, SCF_TYPE_COUNT) == -1) {
44727836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
44737836SJohn.Forte@Sun.COM 			if (scf_transaction_property_change(tran, entry2,
44747836SJohn.Forte@Sun.COM 			    STMF_PROVIDER_DATA_PROP_COUNT,
44757836SJohn.Forte@Sun.COM 			    SCF_TYPE_COUNT) == -1) {
44767836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
44777836SJohn.Forte@Sun.COM 				    "transaction property change failed - %s",
44787836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
44797836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
44807836SJohn.Forte@Sun.COM 				goto out;
44817836SJohn.Forte@Sun.COM 			}
44827836SJohn.Forte@Sun.COM 		} else {
44837836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
44847836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
44857836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
44867836SJohn.Forte@Sun.COM 			goto out;
44877836SJohn.Forte@Sun.COM 		}
44887836SJohn.Forte@Sun.COM 	}
44897836SJohn.Forte@Sun.COM 
44907836SJohn.Forte@Sun.COM 	scf_value_set_count(value2, blockCnt);
44917836SJohn.Forte@Sun.COM 
44927836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry2, value2) == -1) {
44937836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
44947836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
44957836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
44967836SJohn.Forte@Sun.COM 		goto out;
44977836SJohn.Forte@Sun.COM 	}
44987836SJohn.Forte@Sun.COM 
44997836SJohn.Forte@Sun.COM 	/* create or change the set count property */
45007836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry5,
45017836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PROP_SET_COUNT, SCF_TYPE_COUNT) == -1) {
45027836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
45037836SJohn.Forte@Sun.COM 			if (scf_transaction_property_change(tran, entry5,
45047836SJohn.Forte@Sun.COM 			    STMF_PROVIDER_DATA_PROP_SET_COUNT,
45057836SJohn.Forte@Sun.COM 			    SCF_TYPE_COUNT) == -1) {
45067836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
45077836SJohn.Forte@Sun.COM 				    "transaction property change failed - %s",
45087836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
45097836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
45107836SJohn.Forte@Sun.COM 				goto out;
45117836SJohn.Forte@Sun.COM 			}
45127836SJohn.Forte@Sun.COM 		} else {
45137836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
45147836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
45157836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
45167836SJohn.Forte@Sun.COM 			goto out;
45177836SJohn.Forte@Sun.COM 		}
45187836SJohn.Forte@Sun.COM 	}
45197836SJohn.Forte@Sun.COM 
45207836SJohn.Forte@Sun.COM 
45217836SJohn.Forte@Sun.COM 
45227836SJohn.Forte@Sun.COM 	scf_value_set_count(value5, setCnt);
45237836SJohn.Forte@Sun.COM 
45247836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry5, value5) == -1) {
45257836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
45267836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
45277836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
45287836SJohn.Forte@Sun.COM 		goto out;
45297836SJohn.Forte@Sun.COM 	}
45307836SJohn.Forte@Sun.COM 
45317836SJohn.Forte@Sun.COM 	/* create or change the provider type property */
45327836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry3,
45337836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PROP_TYPE, SCF_TYPE_INTEGER) == -1) {
45347836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
45357836SJohn.Forte@Sun.COM 			if (scf_transaction_property_change(tran, entry3,
45367836SJohn.Forte@Sun.COM 			    STMF_PROVIDER_DATA_PROP_TYPE,
45377836SJohn.Forte@Sun.COM 			    SCF_TYPE_INTEGER) == -1) {
45387836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
45397836SJohn.Forte@Sun.COM 				    "transaction property change failed - %s",
45407836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
45417836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
45427836SJohn.Forte@Sun.COM 				goto out;
45437836SJohn.Forte@Sun.COM 			}
45447836SJohn.Forte@Sun.COM 		} else {
45457836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
45467836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
45477836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
45487836SJohn.Forte@Sun.COM 			goto out;
45497836SJohn.Forte@Sun.COM 		}
45507836SJohn.Forte@Sun.COM 	}
45517836SJohn.Forte@Sun.COM 
45527836SJohn.Forte@Sun.COM 	switch (providerType) {
45537836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
45547836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
45557836SJohn.Forte@Sun.COM 			scf_value_set_integer(value3, providerType);
45567836SJohn.Forte@Sun.COM 			break;
45577836SJohn.Forte@Sun.COM 		default:
45587836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
45597836SJohn.Forte@Sun.COM 			goto out;
45607836SJohn.Forte@Sun.COM 	}
45617836SJohn.Forte@Sun.COM 
45627836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry3, value3) == -1) {
45637836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
45647836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
45657836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
45667836SJohn.Forte@Sun.COM 		goto out;
45677836SJohn.Forte@Sun.COM 	}
45687836SJohn.Forte@Sun.COM 
45697836SJohn.Forte@Sun.COM 
45707836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
45717836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
45727836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
45737836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
45747836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
45757836SJohn.Forte@Sun.COM 		} else {
45767836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
45777836SJohn.Forte@Sun.COM 		}
45787836SJohn.Forte@Sun.COM 		goto out;
45797836SJohn.Forte@Sun.COM 	}
45807836SJohn.Forte@Sun.COM 
45817836SJohn.Forte@Sun.COM 	/* pass the new token back to the caller if requested */
45827836SJohn.Forte@Sun.COM 	if (ret == STMF_PS_SUCCESS && setToken) {
45837836SJohn.Forte@Sun.COM 		*setToken = setCnt;
45847836SJohn.Forte@Sun.COM 	}
45857836SJohn.Forte@Sun.COM 
45867836SJohn.Forte@Sun.COM out:
45877836SJohn.Forte@Sun.COM 	/*
45887836SJohn.Forte@Sun.COM 	 * Free resources
45897836SJohn.Forte@Sun.COM 	 */
45907836SJohn.Forte@Sun.COM 	if (handle != NULL) {
45917836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
45927836SJohn.Forte@Sun.COM 	}
45937836SJohn.Forte@Sun.COM 	if (svc != NULL) {
45947836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
45957836SJohn.Forte@Sun.COM 	}
45967836SJohn.Forte@Sun.COM 	if (pg != NULL) {
45977836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
45987836SJohn.Forte@Sun.COM 	}
45997836SJohn.Forte@Sun.COM 	if (prop != NULL) {
46007836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
46017836SJohn.Forte@Sun.COM 	}
46027836SJohn.Forte@Sun.COM 	if (tran != NULL) {
46037836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
46047836SJohn.Forte@Sun.COM 	}
46057836SJohn.Forte@Sun.COM 	for (i = 0; i < addEntryAlloc; i++) {
46067836SJohn.Forte@Sun.COM 		scf_entry_destroy(addEntry[i]);
46077836SJohn.Forte@Sun.COM 	}
46087836SJohn.Forte@Sun.COM 	for (i = 0; i < addValueAlloc; i++) {
46097836SJohn.Forte@Sun.COM 		scf_value_destroy(addValue[i]);
46107836SJohn.Forte@Sun.COM 	}
46117836SJohn.Forte@Sun.COM 	free(addValue);
46127836SJohn.Forte@Sun.COM 	free(addEntry);
46137836SJohn.Forte@Sun.COM 	for (i = 0; i < deleteEntryAlloc; i++) {
46147836SJohn.Forte@Sun.COM 		scf_entry_destroy(deleteEntry[i]);
46157836SJohn.Forte@Sun.COM 	}
46167836SJohn.Forte@Sun.COM 	free(deleteEntry);
46177836SJohn.Forte@Sun.COM 	if (entry1 != NULL) {
46187836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry1);
46197836SJohn.Forte@Sun.COM 	}
46207836SJohn.Forte@Sun.COM 	if (entry2 != NULL) {
46217836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry2);
46227836SJohn.Forte@Sun.COM 	}
46237836SJohn.Forte@Sun.COM 	if (entry3 != NULL) {
46247836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry3);
46257836SJohn.Forte@Sun.COM 	}
46267836SJohn.Forte@Sun.COM 	if (entry5 != NULL) {
46277836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry5);
46287836SJohn.Forte@Sun.COM 	}
46297836SJohn.Forte@Sun.COM 	if (value1 != NULL) {
46307836SJohn.Forte@Sun.COM 		scf_value_destroy(value1);
46317836SJohn.Forte@Sun.COM 	}
46327836SJohn.Forte@Sun.COM 	if (value2 != NULL) {
46337836SJohn.Forte@Sun.COM 		scf_value_destroy(value2);
46347836SJohn.Forte@Sun.COM 	}
46357836SJohn.Forte@Sun.COM 	if (value3 != NULL) {
46367836SJohn.Forte@Sun.COM 		scf_value_destroy(value3);
46377836SJohn.Forte@Sun.COM 	}
46387836SJohn.Forte@Sun.COM 	if (value4 != NULL) {
46397836SJohn.Forte@Sun.COM 		scf_value_destroy(value4);
46407836SJohn.Forte@Sun.COM 	}
46417836SJohn.Forte@Sun.COM 	if (value5 != NULL) {
46427836SJohn.Forte@Sun.COM 		scf_value_destroy(value5);
46437836SJohn.Forte@Sun.COM 	}
46447836SJohn.Forte@Sun.COM 	if (nvlistEncoded != NULL) {
46457836SJohn.Forte@Sun.COM 		free(nvlistEncoded);
46467836SJohn.Forte@Sun.COM 	}
46477836SJohn.Forte@Sun.COM 
46487836SJohn.Forte@Sun.COM 	return (ret);
46497836SJohn.Forte@Sun.COM }
46507836SJohn.Forte@Sun.COM 
46517836SJohn.Forte@Sun.COM /*
46527836SJohn.Forte@Sun.COM  * psGetViewEntry
46537836SJohn.Forte@Sun.COM  *
46547836SJohn.Forte@Sun.COM  * Purpose: Get a single view entry based on the logical unit identifier and
46557836SJohn.Forte@Sun.COM  *          view entry index
46567836SJohn.Forte@Sun.COM  *
46577836SJohn.Forte@Sun.COM  * lu - logical unit identifier
46587836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry
46597836SJohn.Forte@Sun.COM  * ve - caller allocated stmfViewEntry structure. On success, this will
46607836SJohn.Forte@Sun.COM  *      contain the retrieved view entry
46617836SJohn.Forte@Sun.COM  */
46627836SJohn.Forte@Sun.COM int
46637836SJohn.Forte@Sun.COM psGetViewEntry(stmfGuid *lu, uint32_t viewEntryIndex, stmfViewEntry *ve)
46647836SJohn.Forte@Sun.COM {
46657836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
46667836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
46677836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
46687836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
46697836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
46707836SJohn.Forte@Sun.COM 	char luPgName[LOGICAL_UNIT_PG_SIZE];
46717836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
46727836SJohn.Forte@Sun.COM 
46737836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
46747836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
46757836SJohn.Forte@Sun.COM 		goto out;
46767836SJohn.Forte@Sun.COM 	}
46777836SJohn.Forte@Sun.COM 
46787836SJohn.Forte@Sun.COM 	pg = scf_pg_create(handle);
46797836SJohn.Forte@Sun.COM 	if (pg == NULL) {
46807836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf pg alloc failed - %s",
46817836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
46827836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
46837836SJohn.Forte@Sun.COM 		goto out;
46847836SJohn.Forte@Sun.COM 	}
46857836SJohn.Forte@Sun.COM 
46867836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
46877836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
46887836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
46897836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
46907836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
46917836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
46927836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
46937836SJohn.Forte@Sun.COM 
46947836SJohn.Forte@Sun.COM 	(void) snprintf(luPgName, sizeof (luPgName), "%s-%s",
46957836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
46967836SJohn.Forte@Sun.COM 
46977836SJohn.Forte@Sun.COM 	/*
46987836SJohn.Forte@Sun.COM 	 * Format of view entry property group name:
46997836SJohn.Forte@Sun.COM 	 *	VE-<view_entry_index>-<lu_name>
47007836SJohn.Forte@Sun.COM 	 */
47017836SJohn.Forte@Sun.COM 	(void) snprintf(viewEntryPgName, sizeof (viewEntryPgName),
47027836SJohn.Forte@Sun.COM 	    "%s-%d-%s", STMF_VE_PREFIX, viewEntryIndex, guidAsciiBuf);
47037836SJohn.Forte@Sun.COM 
47047836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) {
47057836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
47067836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
47077836SJohn.Forte@Sun.COM 		} else {
47087836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
47097836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
47107836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
47117836SJohn.Forte@Sun.COM 		}
47127836SJohn.Forte@Sun.COM 		goto out;
47137836SJohn.Forte@Sun.COM 	}
47147836SJohn.Forte@Sun.COM 
47157836SJohn.Forte@Sun.COM 
47167836SJohn.Forte@Sun.COM 	if ((ret = iPsGetViewEntry(viewEntryPgName, ve)) != STMF_PS_SUCCESS) {
47177836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
47187836SJohn.Forte@Sun.COM 		goto out;
47197836SJohn.Forte@Sun.COM 	}
47207836SJohn.Forte@Sun.COM 
47217836SJohn.Forte@Sun.COM out:
47227836SJohn.Forte@Sun.COM 	/*
47237836SJohn.Forte@Sun.COM 	 * Free resources
47247836SJohn.Forte@Sun.COM 	 */
47257836SJohn.Forte@Sun.COM 	if (handle != NULL) {
47267836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
47277836SJohn.Forte@Sun.COM 	}
47287836SJohn.Forte@Sun.COM 	if (svc != NULL) {
47297836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
47307836SJohn.Forte@Sun.COM 	}
47317836SJohn.Forte@Sun.COM 	if (pg != NULL) {
47327836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
47337836SJohn.Forte@Sun.COM 	}
47347836SJohn.Forte@Sun.COM 
47357836SJohn.Forte@Sun.COM 	return (ret);
47367836SJohn.Forte@Sun.COM }
47377836SJohn.Forte@Sun.COM 
47387836SJohn.Forte@Sun.COM /*
47397836SJohn.Forte@Sun.COM  * psRemoveViewEntry
47407836SJohn.Forte@Sun.COM  *
47417836SJohn.Forte@Sun.COM  * Remove a view entry
47427836SJohn.Forte@Sun.COM  *
47437836SJohn.Forte@Sun.COM  * luGuid - identifier of logical unit from which to remove view entry
47447836SJohn.Forte@Sun.COM  * viewEntryIndex - view entry name to remove
47457836SJohn.Forte@Sun.COM  *
47467836SJohn.Forte@Sun.COM  * returns:
47477836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
47487836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
47497836SJohn.Forte@Sun.COM  */
47507836SJohn.Forte@Sun.COM int
47517836SJohn.Forte@Sun.COM psRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
47527836SJohn.Forte@Sun.COM {
47537836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
47547836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
47557836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
47567836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
47577836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
47587836SJohn.Forte@Sun.COM 	char luPgName[LOGICAL_UNIT_PG_SIZE];
47597836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
47607836SJohn.Forte@Sun.COM 	sigset_t sigmaskRestore;
47617836SJohn.Forte@Sun.COM 
47627836SJohn.Forte@Sun.COM 	/* grab the signal hold lock */
47637836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&sigSetLock);
47647836SJohn.Forte@Sun.COM 
47657836SJohn.Forte@Sun.COM 	/*
47667836SJohn.Forte@Sun.COM 	 * hold signals until we're done
47677836SJohn.Forte@Sun.COM 	 */
47687836SJohn.Forte@Sun.COM 	if (holdSignal(&sigmaskRestore) != 0) {
47697836SJohn.Forte@Sun.COM 		(void) pthread_mutex_unlock(&sigSetLock);
47707836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
47717836SJohn.Forte@Sun.COM 	}
47727836SJohn.Forte@Sun.COM 
47737836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
47747836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
47757836SJohn.Forte@Sun.COM 		goto out;
47767836SJohn.Forte@Sun.COM 	}
47777836SJohn.Forte@Sun.COM 
47787836SJohn.Forte@Sun.COM 	pg = scf_pg_create(handle);
47797836SJohn.Forte@Sun.COM 	if (pg == NULL) {
47807836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf pg alloc failed - %s",
47817836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
47827836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
47837836SJohn.Forte@Sun.COM 		goto out;
47847836SJohn.Forte@Sun.COM 	}
47857836SJohn.Forte@Sun.COM 
47867836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
47877836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
47887836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
47897836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
47907836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
47917836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
47927836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
47937836SJohn.Forte@Sun.COM 
47947836SJohn.Forte@Sun.COM 	(void) snprintf(luPgName, sizeof (luPgName), "%s-%s",
47957836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
47967836SJohn.Forte@Sun.COM 
47977836SJohn.Forte@Sun.COM 	/*
47987836SJohn.Forte@Sun.COM 	 * Format of view entry property group name:
47997836SJohn.Forte@Sun.COM 	 *	VE-<view_entry_index>-<lu_name>
48007836SJohn.Forte@Sun.COM 	 */
48017836SJohn.Forte@Sun.COM 	(void) snprintf(viewEntryPgName, sizeof (viewEntryPgName),
48027836SJohn.Forte@Sun.COM 	    "%s-%d-%s", STMF_VE_PREFIX, viewEntryIndex, guidAsciiBuf);
48037836SJohn.Forte@Sun.COM 
48047836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) {
48057836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
48067836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
48077836SJohn.Forte@Sun.COM 		} else {
48087836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
48097836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
48107836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
48117836SJohn.Forte@Sun.COM 		}
48127836SJohn.Forte@Sun.COM 		goto out;
48137836SJohn.Forte@Sun.COM 	}
48147836SJohn.Forte@Sun.COM 
48157836SJohn.Forte@Sun.COM 	/*
48167836SJohn.Forte@Sun.COM 	 * update the logical unit property group to remove
48177836SJohn.Forte@Sun.COM 	 * the view entry and update the view entry count
48187836SJohn.Forte@Sun.COM 	 * If it fails, we won't delete the property group so that
48197836SJohn.Forte@Sun.COM 	 * we maintain consistency.
48207836SJohn.Forte@Sun.COM 	 */
48217836SJohn.Forte@Sun.COM 	if ((ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
48227836SJohn.Forte@Sun.COM 	    REMOVE)) != STMF_PS_SUCCESS) {
48237836SJohn.Forte@Sun.COM 		goto out;
48247836SJohn.Forte@Sun.COM 	}
48257836SJohn.Forte@Sun.COM 
48267836SJohn.Forte@Sun.COM 	/*
48277836SJohn.Forte@Sun.COM 	 * Delete the view entry. If this fails, we should try to add
48287836SJohn.Forte@Sun.COM 	 * the logical unit view entry property group back otherwise
48297836SJohn.Forte@Sun.COM 	 * we're inconsistent.
48307836SJohn.Forte@Sun.COM 	 */
48317836SJohn.Forte@Sun.COM 	if (scf_pg_delete(pg) == -1) {
48327836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "delete pg failed - %s",
48337836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
48347836SJohn.Forte@Sun.COM 		if ((ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
48357836SJohn.Forte@Sun.COM 		    ADD)) != STMF_PS_SUCCESS) {
48367836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add of view entry failed, possible"
48377836SJohn.Forte@Sun.COM 			    "inconsistency - %s", scf_strerror(scf_error()));
48387836SJohn.Forte@Sun.COM 		}
48397836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
48407836SJohn.Forte@Sun.COM 		goto out;
48417836SJohn.Forte@Sun.COM 	}
48427836SJohn.Forte@Sun.COM 
48437836SJohn.Forte@Sun.COM out:
48447836SJohn.Forte@Sun.COM 	/*
48457836SJohn.Forte@Sun.COM 	 * Okay, we're done. Release the signals
48467836SJohn.Forte@Sun.COM 	 */
48477836SJohn.Forte@Sun.COM 	if (releaseSignal(&sigmaskRestore) != 0) {
48487836SJohn.Forte@Sun.COM 		/*
48497836SJohn.Forte@Sun.COM 		 * Don't set this as an STMF_PS_ERROR_*. We succeeded
48507836SJohn.Forte@Sun.COM 		 * the requested operation. But we do need to log it.
48517836SJohn.Forte@Sun.COM 		 */
48527836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "Unable to release one or more signals - %s",
48537836SJohn.Forte@Sun.COM 		    strerror(errno));
48547836SJohn.Forte@Sun.COM 	}
48557836SJohn.Forte@Sun.COM 
48567836SJohn.Forte@Sun.COM 	/*
48577836SJohn.Forte@Sun.COM 	 * Free resources
48587836SJohn.Forte@Sun.COM 	 */
48597836SJohn.Forte@Sun.COM 	if (handle != NULL) {
48607836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
48617836SJohn.Forte@Sun.COM 	}
48627836SJohn.Forte@Sun.COM 	if (svc != NULL) {
48637836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
48647836SJohn.Forte@Sun.COM 	}
48657836SJohn.Forte@Sun.COM 	if (pg != NULL) {
48667836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
48677836SJohn.Forte@Sun.COM 	}
48687836SJohn.Forte@Sun.COM 
48697836SJohn.Forte@Sun.COM 	/* release the signal hold lock */
48707836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&sigSetLock);
48717836SJohn.Forte@Sun.COM 
48727836SJohn.Forte@Sun.COM 	return (ret);
48737836SJohn.Forte@Sun.COM }
48747836SJohn.Forte@Sun.COM 
48757836SJohn.Forte@Sun.COM 
48767836SJohn.Forte@Sun.COM 
48777836SJohn.Forte@Sun.COM /*
48787836SJohn.Forte@Sun.COM  * holdSignal
48797836SJohn.Forte@Sun.COM  *
48807836SJohn.Forte@Sun.COM  * Hold SIGINT, SIGTERM, SIGQUIT until further notice.
48817836SJohn.Forte@Sun.COM  *
48827836SJohn.Forte@Sun.COM  * Saves old signal mask on a per thread basis
48837836SJohn.Forte@Sun.COM  * and saves action for the process.
48847836SJohn.Forte@Sun.COM  *
48857836SJohn.Forte@Sun.COM  * Installs action for above signals.
48867836SJohn.Forte@Sun.COM  *
48877836SJohn.Forte@Sun.COM  * locks held: sigSetLock
48887836SJohn.Forte@Sun.COM  *
48897836SJohn.Forte@Sun.COM  * returns:
48907836SJohn.Forte@Sun.COM  *  0 on success
48917836SJohn.Forte@Sun.COM  *  non-zero otherwise
48927836SJohn.Forte@Sun.COM  */
48937836SJohn.Forte@Sun.COM static int
48947836SJohn.Forte@Sun.COM holdSignal(sigset_t *sigmaskRestore)
48957836SJohn.Forte@Sun.COM {
48967836SJohn.Forte@Sun.COM 	struct sigaction act;
48977836SJohn.Forte@Sun.COM 	sigset_t sigmask;
48987836SJohn.Forte@Sun.COM 
48997836SJohn.Forte@Sun.COM 	/*
49007836SJohn.Forte@Sun.COM 	 * Return existing signal mask for this thread
49017836SJohn.Forte@Sun.COM 	 */
49027836SJohn.Forte@Sun.COM 	if (pthread_sigmask(0, NULL, sigmaskRestore) != 0) {
49037836SJohn.Forte@Sun.COM 		return (1);
49047836SJohn.Forte@Sun.COM 	}
49057836SJohn.Forte@Sun.COM 
49067836SJohn.Forte@Sun.COM 	(void) sigemptyset(&act.sa_mask);
49077836SJohn.Forte@Sun.COM 	act.sa_handler = sigHandler;
49087836SJohn.Forte@Sun.COM 	act.sa_flags = 0;
49097836SJohn.Forte@Sun.COM 
49107836SJohn.Forte@Sun.COM 	/*
49117836SJohn.Forte@Sun.COM 	 * Have we set the actions for the signals we want to catch?
49127836SJohn.Forte@Sun.COM 	 */
49137836SJohn.Forte@Sun.COM 	if (!actionSet) {
49147836SJohn.Forte@Sun.COM 		if (sigaction(SIGQUIT, &act, &currentActionQuit) != 0) {
49157836SJohn.Forte@Sun.COM 			return (1);
49167836SJohn.Forte@Sun.COM 		}
49177836SJohn.Forte@Sun.COM 
49187836SJohn.Forte@Sun.COM 		if (sigaction(SIGINT, &act, &currentActionInt) != 0) {
49197836SJohn.Forte@Sun.COM 			return (1);
49207836SJohn.Forte@Sun.COM 		}
49217836SJohn.Forte@Sun.COM 
49227836SJohn.Forte@Sun.COM 		if (sigaction(SIGTERM, &act, &currentActionTerm) != 0) {
49237836SJohn.Forte@Sun.COM 			return (1);
49247836SJohn.Forte@Sun.COM 		}
49257836SJohn.Forte@Sun.COM 
49267836SJohn.Forte@Sun.COM 		actionSet = B_TRUE;
49277836SJohn.Forte@Sun.COM 	}
49287836SJohn.Forte@Sun.COM 
49297836SJohn.Forte@Sun.COM 	/*
49307836SJohn.Forte@Sun.COM 	 * We still need to change the mask for the current thread
49317836SJohn.Forte@Sun.COM 	 */
49327836SJohn.Forte@Sun.COM 	if (sigfillset(&sigmask) != 0) {
49337836SJohn.Forte@Sun.COM 		return (1);
49347836SJohn.Forte@Sun.COM 	}
49357836SJohn.Forte@Sun.COM 
49367836SJohn.Forte@Sun.COM 	(void) sigdelset(&sigmask, SIGQUIT);
49377836SJohn.Forte@Sun.COM 
49387836SJohn.Forte@Sun.COM 	(void) sigdelset(&sigmask, SIGINT);
49397836SJohn.Forte@Sun.COM 
49407836SJohn.Forte@Sun.COM 	(void) sigdelset(&sigmask, SIGTERM);
49417836SJohn.Forte@Sun.COM 
49427836SJohn.Forte@Sun.COM 	if (pthread_sigmask(SIG_SETMASK, &sigmask, NULL) != 0) {
49437836SJohn.Forte@Sun.COM 		return (1);
49447836SJohn.Forte@Sun.COM 	}
49457836SJohn.Forte@Sun.COM 
49467836SJohn.Forte@Sun.COM 	return (0);
49477836SJohn.Forte@Sun.COM }
49487836SJohn.Forte@Sun.COM 
49497836SJohn.Forte@Sun.COM /*
49507836SJohn.Forte@Sun.COM  * releaseSignal
49517836SJohn.Forte@Sun.COM  *
49527836SJohn.Forte@Sun.COM  * Re-install the original signal mask and signal actions
49537836SJohn.Forte@Sun.COM  *
49547836SJohn.Forte@Sun.COM  * Also, raise any signals that were caught during the hold period and clear
49557836SJohn.Forte@Sun.COM  * the signal from the caught set (signalsCaught).
49567836SJohn.Forte@Sun.COM  *
49577836SJohn.Forte@Sun.COM  * locks held: sigSetLock
49587836SJohn.Forte@Sun.COM  *
49597836SJohn.Forte@Sun.COM  * Returns
49607836SJohn.Forte@Sun.COM  *  0 on success
49617836SJohn.Forte@Sun.COM  *  non-zero otherwise
49627836SJohn.Forte@Sun.COM  */
49637836SJohn.Forte@Sun.COM static int
49647836SJohn.Forte@Sun.COM releaseSignal(sigset_t *sigmaskRestore)
49657836SJohn.Forte@Sun.COM {
49667836SJohn.Forte@Sun.COM 	int ret = 0;
49677836SJohn.Forte@Sun.COM 
49687836SJohn.Forte@Sun.COM 	if (sigaction(SIGQUIT, &currentActionQuit, NULL) != 0) {
49697836SJohn.Forte@Sun.COM 		ret = 1;
49707836SJohn.Forte@Sun.COM 	}
49717836SJohn.Forte@Sun.COM 
49727836SJohn.Forte@Sun.COM 	if (sigaction(SIGINT, &currentActionInt, NULL) != 0) {
49737836SJohn.Forte@Sun.COM 		ret = 1;
49747836SJohn.Forte@Sun.COM 	}
49757836SJohn.Forte@Sun.COM 
49767836SJohn.Forte@Sun.COM 	if (sigaction(SIGTERM, &currentActionTerm, NULL) != 0) {
49777836SJohn.Forte@Sun.COM 		ret = 1;
49787836SJohn.Forte@Sun.COM 	}
49797836SJohn.Forte@Sun.COM 
49807836SJohn.Forte@Sun.COM 	actionSet = B_FALSE;
49817836SJohn.Forte@Sun.COM 
49827836SJohn.Forte@Sun.COM 	/*
49837836SJohn.Forte@Sun.COM 	 * Restore previous signal mask for this thread
49847836SJohn.Forte@Sun.COM 	 */
49857836SJohn.Forte@Sun.COM 	if (pthread_sigmask(SIG_SETMASK, sigmaskRestore, NULL) != 0) {
49867836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "Unable to restore sigmask");
49877836SJohn.Forte@Sun.COM 	}
49887836SJohn.Forte@Sun.COM 
49897836SJohn.Forte@Sun.COM 	/*
49907836SJohn.Forte@Sun.COM 	 * Now raise signals that were raised while we were held
49917836SJohn.Forte@Sun.COM 	 */
49927836SJohn.Forte@Sun.COM 	if (sigismember(&signalsCaught, SIGTERM)) {
49937836SJohn.Forte@Sun.COM 		(void) sigdelset(&signalsCaught, SIGTERM);
49947836SJohn.Forte@Sun.COM 		(void) raise(SIGTERM);
49957836SJohn.Forte@Sun.COM 	}
49967836SJohn.Forte@Sun.COM 
49977836SJohn.Forte@Sun.COM 	if (sigismember(&signalsCaught, SIGINT)) {
49987836SJohn.Forte@Sun.COM 		(void) sigdelset(&signalsCaught, SIGINT);
49997836SJohn.Forte@Sun.COM 		(void) raise(SIGINT);
50007836SJohn.Forte@Sun.COM 	}
50017836SJohn.Forte@Sun.COM 
50027836SJohn.Forte@Sun.COM 	if (sigismember(&signalsCaught, SIGQUIT)) {
50037836SJohn.Forte@Sun.COM 		(void) sigdelset(&signalsCaught, SIGQUIT);
50047836SJohn.Forte@Sun.COM 		(void) raise(SIGQUIT);
50057836SJohn.Forte@Sun.COM 	}
50067836SJohn.Forte@Sun.COM 
50077836SJohn.Forte@Sun.COM 	return (ret);
50087836SJohn.Forte@Sun.COM }
5009