1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <libscf.h>
27*7836SJohn.Forte@Sun.COM #include <stdio.h>
28*7836SJohn.Forte@Sun.COM #include <stdlib.h>
29*7836SJohn.Forte@Sun.COM #include <errno.h>
30*7836SJohn.Forte@Sun.COM #include <assert.h>
31*7836SJohn.Forte@Sun.COM #include <strings.h>
32*7836SJohn.Forte@Sun.COM #include <libstmf.h>
33*7836SJohn.Forte@Sun.COM #include <store.h>
34*7836SJohn.Forte@Sun.COM #include <syslog.h>
35*7836SJohn.Forte@Sun.COM #include <signal.h>
36*7836SJohn.Forte@Sun.COM #include <pthread.h>
37*7836SJohn.Forte@Sun.COM #include <libnvpair.h>
38*7836SJohn.Forte@Sun.COM #include <limits.h>
39*7836SJohn.Forte@Sun.COM #include <unistd.h>
40*7836SJohn.Forte@Sun.COM 
41*7836SJohn.Forte@Sun.COM /*
42*7836SJohn.Forte@Sun.COM  * This file's functions are responsible for all store and retrieve operations
43*7836SJohn.Forte@Sun.COM  * against the STMF smf(5) database. The following shows the currently defined
44*7836SJohn.Forte@Sun.COM  * schema for the STMF database:
45*7836SJohn.Forte@Sun.COM  *
46*7836SJohn.Forte@Sun.COM  * Description of property groups for service: svc:/system/stmf
47*7836SJohn.Forte@Sun.COM  *
48*7836SJohn.Forte@Sun.COM  * Stability: Volatile
49*7836SJohn.Forte@Sun.COM  *
50*7836SJohn.Forte@Sun.COM  * 1. Property Group: host_groups
51*7836SJohn.Forte@Sun.COM  *        Properties: group_name-<N> where <N> is an unsigned integer
52*7836SJohn.Forte@Sun.COM  *                        type: ustring
53*7836SJohn.Forte@Sun.COM  *                        contains: group name
54*7836SJohn.Forte@Sun.COM  *                    group_name-<N>-member_list where <N> is an unsigned
55*7836SJohn.Forte@Sun.COM  *                            integer matching a group_name-<N> property.
56*7836SJohn.Forte@Sun.COM  *                        type: ustring
57*7836SJohn.Forte@Sun.COM  *                        contains: list of members
58*7836SJohn.Forte@Sun.COM  *
59*7836SJohn.Forte@Sun.COM  *        Description:
60*7836SJohn.Forte@Sun.COM  *             Contains the host group names as well as the host group members
61*7836SJohn.Forte@Sun.COM  *             for each host group.
62*7836SJohn.Forte@Sun.COM  *
63*7836SJohn.Forte@Sun.COM  * 2. Property Group: target_groups
64*7836SJohn.Forte@Sun.COM  *        Properties: group_name-<N> where <N> is an unsigned integer
65*7836SJohn.Forte@Sun.COM  *                        type: ustring
66*7836SJohn.Forte@Sun.COM  *                        contains: group name
67*7836SJohn.Forte@Sun.COM  *                    group_name-<N>-member_list where <N> is an unsigned
68*7836SJohn.Forte@Sun.COM  *                            integer matching a group_name-<N> property.
69*7836SJohn.Forte@Sun.COM  *                        type: ustring
70*7836SJohn.Forte@Sun.COM  *                        contains: list of members
71*7836SJohn.Forte@Sun.COM  *
72*7836SJohn.Forte@Sun.COM  *        Description:
73*7836SJohn.Forte@Sun.COM  *             Contains the target group names as well as the target group
74*7836SJohn.Forte@Sun.COM  *             members for each target group.
75*7836SJohn.Forte@Sun.COM  *
76*7836SJohn.Forte@Sun.COM  * 3. Property Group: lu-<GUID>
77*7836SJohn.Forte@Sun.COM  *                        where <GUID> is a 32 character hexadecimal string.
78*7836SJohn.Forte@Sun.COM  *        Properties: ve_cnt
79*7836SJohn.Forte@Sun.COM  *                        type: count
80*7836SJohn.Forte@Sun.COM  *                        contains: the number of current view entries
81*7836SJohn.Forte@Sun.COM  *                    view-entry-<N>-<GUID> where <N> is an unsigned integer
82*7836SJohn.Forte@Sun.COM  *                        type: ustring
83*7836SJohn.Forte@Sun.COM  *                        contains: nothing. Used as reference to the view
84*7836SJohn.Forte@Sun.COM  *                                  entry property group
85*7836SJohn.Forte@Sun.COM  *
86*7836SJohn.Forte@Sun.COM  *        Description:
87*7836SJohn.Forte@Sun.COM  *             Contains the references to each view entry. One lu-<GUID>
88*7836SJohn.Forte@Sun.COM  *             property group will exist for each logical unit with 1 or more
89*7836SJohn.Forte@Sun.COM  *             view entries.
90*7836SJohn.Forte@Sun.COM  *             Potentially can hold any other data that can be managed on a per
91*7836SJohn.Forte@Sun.COM  *             logical unit basis.
92*7836SJohn.Forte@Sun.COM  *
93*7836SJohn.Forte@Sun.COM  * 4. Property Group: view_entry-<N>-<GUID> (matches property in lu-<GUID>
94*7836SJohn.Forte@Sun.COM  *                    property group)
95*7836SJohn.Forte@Sun.COM  *        Properties: all_hosts
96*7836SJohn.Forte@Sun.COM  *                        type: boolean
97*7836SJohn.Forte@Sun.COM  *                        contains: when true, the value of host_group is
98*7836SJohn.Forte@Sun.COM  *                                  ignored
99*7836SJohn.Forte@Sun.COM  *                    all_targets
100*7836SJohn.Forte@Sun.COM  *                        type: boolean
101*7836SJohn.Forte@Sun.COM  *                        contains: when true, the value of target_group is
102*7836SJohn.Forte@Sun.COM  *                                  ignored
103*7836SJohn.Forte@Sun.COM  *                    host_group
104*7836SJohn.Forte@Sun.COM  *                        type: ustring
105*7836SJohn.Forte@Sun.COM  *                        contains: host group for logical unit mapping and
106*7836SJohn.Forte@Sun.COM  *                                  masking purposes
107*7836SJohn.Forte@Sun.COM  *                    target_group
108*7836SJohn.Forte@Sun.COM  *                        type: ustring
109*7836SJohn.Forte@Sun.COM  *                        contains: target group for logical unit mapping and
110*7836SJohn.Forte@Sun.COM  *                                  masking purposes
111*7836SJohn.Forte@Sun.COM  *                    lu_nbr
112*7836SJohn.Forte@Sun.COM  *                        type: opaque
113*7836SJohn.Forte@Sun.COM  *                        contains: the 8-byte SCSI logical unit number for
114*7836SJohn.Forte@Sun.COM  *                                  mapping and masking purposes
115*7836SJohn.Forte@Sun.COM  *        Description:
116*7836SJohn.Forte@Sun.COM  *             One "view_entry-<N>-<GUID>" property group will exist for each
117*7836SJohn.Forte@Sun.COM  *             view entry in the system. This property group name maps
118*7836SJohn.Forte@Sun.COM  *             directly to the "lu-<GUID>" property group with a matching
119*7836SJohn.Forte@Sun.COM  *             <GUID>.
120*7836SJohn.Forte@Sun.COM  *
121*7836SJohn.Forte@Sun.COM  * 5. Property Group: provider_data_pg_<provider-name>
122*7836SJohn.Forte@Sun.COM  *                        where <provider-name> is the name of the provider
123*7836SJohn.Forte@Sun.COM  *                           registered with stmf.
124*7836SJohn.Forte@Sun.COM  *        Properties: provider_data_prop-<N>
125*7836SJohn.Forte@Sun.COM  *                        where <N> is a sequential identifier for the data
126*7836SJohn.Forte@Sun.COM  *                           chunk.
127*7836SJohn.Forte@Sun.COM  *                        type: opaque
128*7836SJohn.Forte@Sun.COM  *                        contains: up to STMF_PROVIDER_DATA_PROP_SIZE bytes
129*7836SJohn.Forte@Sun.COM  *                                  of nvlist packed data.
130*7836SJohn.Forte@Sun.COM  *                    provider_data_count
131*7836SJohn.Forte@Sun.COM  *                        type: count
132*7836SJohn.Forte@Sun.COM  *                        contains: the number of provider data chunks
133*7836SJohn.Forte@Sun.COM  *                    provider_data_type
134*7836SJohn.Forte@Sun.COM  *                        type: integer
135*7836SJohn.Forte@Sun.COM  *                        contains: STMF_PORT_PROVIDER_TYPE or
136*7836SJohn.Forte@Sun.COM  *                                  STMF_LU_PROVIDER_TYPE
137*7836SJohn.Forte@Sun.COM  *
138*7836SJohn.Forte@Sun.COM  *        Description:
139*7836SJohn.Forte@Sun.COM  *             Holds the nvlist packed provider data set via
140*7836SJohn.Forte@Sun.COM  *             stmfSetProviderData and retrieved via stmfGetProviderData. Data
141*7836SJohn.Forte@Sun.COM  *             is stored in STMF_PROVIDER_DATA_PROP_SIZE chunks. On retrieve,
142*7836SJohn.Forte@Sun.COM  *             these chunks are reassembled and unpacked.
143*7836SJohn.Forte@Sun.COM  *
144*7836SJohn.Forte@Sun.COM  */
145*7836SJohn.Forte@Sun.COM 
146*7836SJohn.Forte@Sun.COM static int iPsInit(scf_handle_t **, scf_service_t **);
147*7836SJohn.Forte@Sun.COM static int iPsCreateDeleteGroup(char *, char *, int);
148*7836SJohn.Forte@Sun.COM static int iPsAddRemoveGroupMember(char *, char *, char *, int);
149*7836SJohn.Forte@Sun.COM static int iPsGetGroupList(char *, stmfGroupList **);
150*7836SJohn.Forte@Sun.COM static int iPsGetGroupMemberList(char *, char *, stmfGroupProperties **);
151*7836SJohn.Forte@Sun.COM static int iPsAddViewEntry(char *, char *, stmfViewEntry *);
152*7836SJohn.Forte@Sun.COM static int iPsAddRemoveLuViewEntry(char *, char *, int);
153*7836SJohn.Forte@Sun.COM static int iPsGetViewEntry(char *, stmfViewEntry *);
154*7836SJohn.Forte@Sun.COM static int iPsGetActualGroupName(char *, char *, char *);
155*7836SJohn.Forte@Sun.COM static int iPsGetServiceVersion(uint64_t *, scf_handle_t *, scf_service_t *);
156*7836SJohn.Forte@Sun.COM static int viewEntryCompare(const void *, const void *);
157*7836SJohn.Forte@Sun.COM static int holdSignal(sigset_t *);
158*7836SJohn.Forte@Sun.COM static int releaseSignal(sigset_t *);
159*7836SJohn.Forte@Sun.COM static void sigHandler();
160*7836SJohn.Forte@Sun.COM 
161*7836SJohn.Forte@Sun.COM static pthread_mutex_t sigSetLock = PTHREAD_MUTEX_INITIALIZER;
162*7836SJohn.Forte@Sun.COM 
163*7836SJohn.Forte@Sun.COM sigset_t sigSet;
164*7836SJohn.Forte@Sun.COM sigset_t signalsCaught;
165*7836SJohn.Forte@Sun.COM 
166*7836SJohn.Forte@Sun.COM struct sigaction currentActionQuit;
167*7836SJohn.Forte@Sun.COM struct sigaction currentActionTerm;
168*7836SJohn.Forte@Sun.COM struct sigaction currentActionInt;
169*7836SJohn.Forte@Sun.COM 
170*7836SJohn.Forte@Sun.COM boolean_t actionSet = B_FALSE;
171*7836SJohn.Forte@Sun.COM 
172*7836SJohn.Forte@Sun.COM /*
173*7836SJohn.Forte@Sun.COM  * Version info for the SMF schema
174*7836SJohn.Forte@Sun.COM  */
175*7836SJohn.Forte@Sun.COM #define	STMF_SMF_VERSION    1
176*7836SJohn.Forte@Sun.COM 
177*7836SJohn.Forte@Sun.COM /*
178*7836SJohn.Forte@Sun.COM  * Property Group Names and prefixes
179*7836SJohn.Forte@Sun.COM  */
180*7836SJohn.Forte@Sun.COM #define	STMF_HOST_GROUPS	"host_groups"
181*7836SJohn.Forte@Sun.COM #define	STMF_TARGET_GROUPS	"target_groups"
182*7836SJohn.Forte@Sun.COM #define	STMF_VE_PREFIX		"view_entry"
183*7836SJohn.Forte@Sun.COM #define	STMF_LU_PREFIX		"lu"
184*7836SJohn.Forte@Sun.COM #define	STMF_DATA_GROUP		"stmf_data"
185*7836SJohn.Forte@Sun.COM 
186*7836SJohn.Forte@Sun.COM /*
187*7836SJohn.Forte@Sun.COM  * Property names and prefix for logical unit property group
188*7836SJohn.Forte@Sun.COM  */
189*7836SJohn.Forte@Sun.COM #define	STMF_VE_CNT		"ve_cnt"
190*7836SJohn.Forte@Sun.COM #define	STMF_GROUP_PREFIX	"group_name"
191*7836SJohn.Forte@Sun.COM #define	STMF_MEMBER_LIST_SUFFIX	"member_list"
192*7836SJohn.Forte@Sun.COM #define	STMF_VERSION_NAME	"version_name"
193*7836SJohn.Forte@Sun.COM 
194*7836SJohn.Forte@Sun.COM /*
195*7836SJohn.Forte@Sun.COM  * Property names for view entry
196*7836SJohn.Forte@Sun.COM  */
197*7836SJohn.Forte@Sun.COM #define	STMF_VE_ALLHOSTS	    "all_hosts"
198*7836SJohn.Forte@Sun.COM #define	STMF_VE_HOSTGROUP	    "host_group"
199*7836SJohn.Forte@Sun.COM #define	STMF_VE_ALLTARGETS	    "all_targets"
200*7836SJohn.Forte@Sun.COM #define	STMF_VE_TARGETGROUP	    "target_group"
201*7836SJohn.Forte@Sun.COM #define	STMF_VE_LUNBR		    "lu_nbr"
202*7836SJohn.Forte@Sun.COM 
203*7836SJohn.Forte@Sun.COM /* Property group suffix for provider data */
204*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PREFIX "provider_data_pg_"
205*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_PREFIX "provider_data_prop"
206*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_NAME_SIZE 256
207*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_TYPE "provider_type"
208*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_SET_COUNT "provider_data_set_cnt"
209*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_COUNT "provider_data_cnt"
210*7836SJohn.Forte@Sun.COM /*
211*7836SJohn.Forte@Sun.COM  * This is the data chunk size. The current value limit for scf is 4096.
212*7836SJohn.Forte@Sun.COM  * This is defined by REP_PROTOCOL_VALUE_LEN in
213*7836SJohn.Forte@Sun.COM  * OS/Net: usr/src/common/svc/repcache_protocol.h
214*7836SJohn.Forte@Sun.COM  *
215*7836SJohn.Forte@Sun.COM  * Larger data property size = better performance
216*7836SJohn.Forte@Sun.COM  */
217*7836SJohn.Forte@Sun.COM #define	STMF_PROVIDER_DATA_PROP_SIZE 4000
218*7836SJohn.Forte@Sun.COM 
219*7836SJohn.Forte@Sun.COM #define	STMF_SMF_READ_ATTR	"solaris.smf.read.stmf"
220*7836SJohn.Forte@Sun.COM 
221*7836SJohn.Forte@Sun.COM 
222*7836SJohn.Forte@Sun.COM /* service name */
223*7836SJohn.Forte@Sun.COM #define	STMF_SERVICE	"system/stmf"
224*7836SJohn.Forte@Sun.COM 
225*7836SJohn.Forte@Sun.COM /* limits and flag values */
226*7836SJohn.Forte@Sun.COM #define	GROUP_MEMBER_ALLOC 100
227*7836SJohn.Forte@Sun.COM #define	VIEW_ENTRY_STRUCT_CNT 6
228*7836SJohn.Forte@Sun.COM #define	VIEW_ENTRY_PG_SIZE 256
229*7836SJohn.Forte@Sun.COM #define	LOGICAL_UNIT_PG_SIZE 256
230*7836SJohn.Forte@Sun.COM #define	VIEW_ENTRY_MAX UINT32_MAX
231*7836SJohn.Forte@Sun.COM #define	GROUP_MAX UINT64_MAX
232*7836SJohn.Forte@Sun.COM #define	ADD 0
233*7836SJohn.Forte@Sun.COM #define	REMOVE 1
234*7836SJohn.Forte@Sun.COM 
235*7836SJohn.Forte@Sun.COM /*
236*7836SJohn.Forte@Sun.COM  * sigHandler
237*7836SJohn.Forte@Sun.COM  *
238*7836SJohn.Forte@Sun.COM  * Catch the signal and set the global signalsCaught to the signal received
239*7836SJohn.Forte@Sun.COM  *
240*7836SJohn.Forte@Sun.COM  * signalsCaught will be used by releaseSignal to raise this signal when
241*7836SJohn.Forte@Sun.COM  * we're done processing our critical code.
242*7836SJohn.Forte@Sun.COM  *
243*7836SJohn.Forte@Sun.COM  */
244*7836SJohn.Forte@Sun.COM static void
245*7836SJohn.Forte@Sun.COM sigHandler(int sig)
246*7836SJohn.Forte@Sun.COM {
247*7836SJohn.Forte@Sun.COM 	(void) sigaddset(&signalsCaught, sig);
248*7836SJohn.Forte@Sun.COM }
249*7836SJohn.Forte@Sun.COM 
250*7836SJohn.Forte@Sun.COM /*
251*7836SJohn.Forte@Sun.COM  * iPsAddRemoveGroupMember
252*7836SJohn.Forte@Sun.COM  *
253*7836SJohn.Forte@Sun.COM  * Add or remove a member for a given group
254*7836SJohn.Forte@Sun.COM  *
255*7836SJohn.Forte@Sun.COM  * pgName - Property group name
256*7836SJohn.Forte@Sun.COM  * groupName - group name to which the member is added/removed
257*7836SJohn.Forte@Sun.COM  * memberName - member to be added/removed
258*7836SJohn.Forte@Sun.COM  * addRemoveFlag - ADD/REMOVE
259*7836SJohn.Forte@Sun.COM  *
260*7836SJohn.Forte@Sun.COM  * returns:
261*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
262*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
263*7836SJohn.Forte@Sun.COM  */
264*7836SJohn.Forte@Sun.COM static int
265*7836SJohn.Forte@Sun.COM iPsAddRemoveGroupMember(char *pgName, char *groupName, char *memberName,
266*7836SJohn.Forte@Sun.COM int addRemoveFlag)
267*7836SJohn.Forte@Sun.COM {
268*7836SJohn.Forte@Sun.COM 	scf_handle_t *handle = NULL;
269*7836SJohn.Forte@Sun.COM 	scf_service_t *svc = NULL;
270*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t *pg = NULL;
271*7836SJohn.Forte@Sun.COM 	scf_property_t *prop = NULL;
272*7836SJohn.Forte@Sun.COM 	scf_value_t *valueLookup = NULL;
273*7836SJohn.Forte@Sun.COM 	scf_value_t **valueSet = NULL;
274*7836SJohn.Forte@Sun.COM 	scf_iter_t *valueIter = NULL;
275*7836SJohn.Forte@Sun.COM 	scf_transaction_t *tran = NULL;
276*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry = NULL;
277*7836SJohn.Forte@Sun.COM 	int i = 0;
278*7836SJohn.Forte@Sun.COM 	int lastAlloc;
279*7836SJohn.Forte@Sun.COM 	int valueArraySize = 0;
280*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
281*7836SJohn.Forte@Sun.COM 	char buf[STMF_IDENT_LENGTH];
282*7836SJohn.Forte@Sun.COM 	int commitRet;
283*7836SJohn.Forte@Sun.COM 	boolean_t found = B_FALSE;
284*7836SJohn.Forte@Sun.COM 
285*7836SJohn.Forte@Sun.COM 	assert(pgName != NULL && groupName != NULL && memberName != NULL);
286*7836SJohn.Forte@Sun.COM 
287*7836SJohn.Forte@Sun.COM 	/*
288*7836SJohn.Forte@Sun.COM 	 * Init the service handle
289*7836SJohn.Forte@Sun.COM 	 */
290*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
291*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
292*7836SJohn.Forte@Sun.COM 		goto out;
293*7836SJohn.Forte@Sun.COM 	}
294*7836SJohn.Forte@Sun.COM 
295*7836SJohn.Forte@Sun.COM 	/*
296*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
297*7836SJohn.Forte@Sun.COM 	 */
298*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
299*7836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
300*7836SJohn.Forte@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
301*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
302*7836SJohn.Forte@Sun.COM 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
303*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
304*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
305*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
306*7836SJohn.Forte@Sun.COM 		goto out;
307*7836SJohn.Forte@Sun.COM 	}
308*7836SJohn.Forte@Sun.COM 
309*7836SJohn.Forte@Sun.COM 	/*
310*7836SJohn.Forte@Sun.COM 	 * Get the service property group handle
311*7836SJohn.Forte@Sun.COM 	 */
312*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
313*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
314*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
315*7836SJohn.Forte@Sun.COM 		} else {
316*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
317*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
318*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
319*7836SJohn.Forte@Sun.COM 		}
320*7836SJohn.Forte@Sun.COM 		goto out;
321*7836SJohn.Forte@Sun.COM 	}
322*7836SJohn.Forte@Sun.COM 
323*7836SJohn.Forte@Sun.COM 	/*
324*7836SJohn.Forte@Sun.COM 	 * Begin the transaction
325*7836SJohn.Forte@Sun.COM 	 */
326*7836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
327*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
328*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
329*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
330*7836SJohn.Forte@Sun.COM 		goto out;
331*7836SJohn.Forte@Sun.COM 	}
332*7836SJohn.Forte@Sun.COM 
333*7836SJohn.Forte@Sun.COM 	/*
334*7836SJohn.Forte@Sun.COM 	 * We're changing an existing property by adding a propval
335*7836SJohn.Forte@Sun.COM 	 * There are no add semantics in libscf for a property value. We'll
336*7836SJohn.Forte@Sun.COM 	 * need to read in the current properties and apply them all to the
337*7836SJohn.Forte@Sun.COM 	 * set and then add the one we were asked to add or omit the one
338*7836SJohn.Forte@Sun.COM 	 * we were asked to remove.
339*7836SJohn.Forte@Sun.COM 	 */
340*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_change(tran, entry, groupName,
341*7836SJohn.Forte@Sun.COM 	    SCF_TYPE_USTRING) == -1) {
342*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
343*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
344*7836SJohn.Forte@Sun.COM 		} else {
345*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
346*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "tran property change failed - %s",
347*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
348*7836SJohn.Forte@Sun.COM 		}
349*7836SJohn.Forte@Sun.COM 		goto out;
350*7836SJohn.Forte@Sun.COM 	}
351*7836SJohn.Forte@Sun.COM 
352*7836SJohn.Forte@Sun.COM 	/*
353*7836SJohn.Forte@Sun.COM 	 * Get the property handle
354*7836SJohn.Forte@Sun.COM 	 */
355*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, groupName, prop) == -1) {
356*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
357*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
358*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
359*7836SJohn.Forte@Sun.COM 		goto out;
360*7836SJohn.Forte@Sun.COM 	}
361*7836SJohn.Forte@Sun.COM 
362*7836SJohn.Forte@Sun.COM 	/*
363*7836SJohn.Forte@Sun.COM 	 * Value lookup is used to lookup the existing values
364*7836SJohn.Forte@Sun.COM 	 */
365*7836SJohn.Forte@Sun.COM 	valueLookup = scf_value_create(handle);
366*7836SJohn.Forte@Sun.COM 	if (valueLookup == NULL) {
367*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf value alloc failed - %s",
368*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
369*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
370*7836SJohn.Forte@Sun.COM 		goto out;
371*7836SJohn.Forte@Sun.COM 	}
372*7836SJohn.Forte@Sun.COM 
373*7836SJohn.Forte@Sun.COM 	/*
374*7836SJohn.Forte@Sun.COM 	 * valueIter is the iterator handle, create the resource
375*7836SJohn.Forte@Sun.COM 	 */
376*7836SJohn.Forte@Sun.COM 	if (scf_iter_property_values(valueIter, prop) == -1) {
377*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter value failed - %s",
378*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
379*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
380*7836SJohn.Forte@Sun.COM 		goto out;
381*7836SJohn.Forte@Sun.COM 	}
382*7836SJohn.Forte@Sun.COM 
383*7836SJohn.Forte@Sun.COM 	/*
384*7836SJohn.Forte@Sun.COM 	 * Allocate value resource pointers.
385*7836SJohn.Forte@Sun.COM 	 * We need a value resource for each value as value pointers passed
386*7836SJohn.Forte@Sun.COM 	 * to libscf cannot be destroyed until the commit or destroy on the
387*7836SJohn.Forte@Sun.COM 	 * transaction is done.
388*7836SJohn.Forte@Sun.COM 	 *
389*7836SJohn.Forte@Sun.COM 	 * We're using GROUP_MEMBER_ALLOC initially. If it's not large
390*7836SJohn.Forte@Sun.COM 	 * enough, we'll realloc on the fly
391*7836SJohn.Forte@Sun.COM 	 */
392*7836SJohn.Forte@Sun.COM 	valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
393*7836SJohn.Forte@Sun.COM 	    * (lastAlloc = GROUP_MEMBER_ALLOC));
394*7836SJohn.Forte@Sun.COM 	if (valueSet == NULL) {
395*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
396*7836SJohn.Forte@Sun.COM 		goto out;
397*7836SJohn.Forte@Sun.COM 	}
398*7836SJohn.Forte@Sun.COM 
399*7836SJohn.Forte@Sun.COM 	/*
400*7836SJohn.Forte@Sun.COM 	 * Iterate through the existing values
401*7836SJohn.Forte@Sun.COM 	 */
402*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_value(valueIter, valueLookup) == 1) {
403*7836SJohn.Forte@Sun.COM 		bzero(buf, sizeof (buf));
404*7836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
405*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
406*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
407*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
408*7836SJohn.Forte@Sun.COM 			break;
409*7836SJohn.Forte@Sun.COM 		}
410*7836SJohn.Forte@Sun.COM 
411*7836SJohn.Forte@Sun.COM 		/*
412*7836SJohn.Forte@Sun.COM 		 * Check for existing
413*7836SJohn.Forte@Sun.COM 		 * If we're adding, it's an error
414*7836SJohn.Forte@Sun.COM 		 * If we're removing, we skip it and simply not
415*7836SJohn.Forte@Sun.COM 		 * add it to the set. Subtraction by omission.
416*7836SJohn.Forte@Sun.COM 		 */
417*7836SJohn.Forte@Sun.COM 		if ((strlen(buf) == strlen(memberName)) &&
418*7836SJohn.Forte@Sun.COM 		    bcmp(buf, memberName, strlen(buf)) == 0) {
419*7836SJohn.Forte@Sun.COM 			if (addRemoveFlag == ADD) {
420*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
421*7836SJohn.Forte@Sun.COM 				break;
422*7836SJohn.Forte@Sun.COM 			} else {
423*7836SJohn.Forte@Sun.COM 				found = B_TRUE;
424*7836SJohn.Forte@Sun.COM 				continue;
425*7836SJohn.Forte@Sun.COM 			}
426*7836SJohn.Forte@Sun.COM 		}
427*7836SJohn.Forte@Sun.COM 
428*7836SJohn.Forte@Sun.COM 		/*
429*7836SJohn.Forte@Sun.COM 		 * Create the value resource for this iteration
430*7836SJohn.Forte@Sun.COM 		 */
431*7836SJohn.Forte@Sun.COM 		valueSet[i] = scf_value_create(handle);
432*7836SJohn.Forte@Sun.COM 		if (valueSet[i] == NULL) {
433*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
434*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
435*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
436*7836SJohn.Forte@Sun.COM 			break;
437*7836SJohn.Forte@Sun.COM 		}
438*7836SJohn.Forte@Sun.COM 
439*7836SJohn.Forte@Sun.COM 		/*
440*7836SJohn.Forte@Sun.COM 		 * Set the value
441*7836SJohn.Forte@Sun.COM 		 */
442*7836SJohn.Forte@Sun.COM 		if (scf_value_set_ustring(valueSet[i], buf) == -1) {
443*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
444*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
445*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
446*7836SJohn.Forte@Sun.COM 			break;
447*7836SJohn.Forte@Sun.COM 		}
448*7836SJohn.Forte@Sun.COM 
449*7836SJohn.Forte@Sun.COM 		/*
450*7836SJohn.Forte@Sun.COM 		 * Now add the value
451*7836SJohn.Forte@Sun.COM 		 */
452*7836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
453*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
454*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
455*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
456*7836SJohn.Forte@Sun.COM 			break;
457*7836SJohn.Forte@Sun.COM 		}
458*7836SJohn.Forte@Sun.COM 
459*7836SJohn.Forte@Sun.COM 		i++;
460*7836SJohn.Forte@Sun.COM 
461*7836SJohn.Forte@Sun.COM 		/*
462*7836SJohn.Forte@Sun.COM 		 * realloc if we've hit the previous alloc size
463*7836SJohn.Forte@Sun.COM 		 */
464*7836SJohn.Forte@Sun.COM 		if (i >= lastAlloc) {
465*7836SJohn.Forte@Sun.COM 			lastAlloc += GROUP_MEMBER_ALLOC;
466*7836SJohn.Forte@Sun.COM 			valueSet = realloc(valueSet,
467*7836SJohn.Forte@Sun.COM 			    sizeof (*valueSet) * lastAlloc);
468*7836SJohn.Forte@Sun.COM 			if (valueSet == NULL) {
469*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
470*7836SJohn.Forte@Sun.COM 				break;
471*7836SJohn.Forte@Sun.COM 			}
472*7836SJohn.Forte@Sun.COM 		}
473*7836SJohn.Forte@Sun.COM 	}
474*7836SJohn.Forte@Sun.COM 
475*7836SJohn.Forte@Sun.COM 	/*
476*7836SJohn.Forte@Sun.COM 	 * set valueArraySize to final allocated length
477*7836SJohn.Forte@Sun.COM 	 * so we can use it to destroy the resources correctly
478*7836SJohn.Forte@Sun.COM 	 */
479*7836SJohn.Forte@Sun.COM 	valueArraySize = i;
480*7836SJohn.Forte@Sun.COM 
481*7836SJohn.Forte@Sun.COM 	if (!found && (addRemoveFlag == REMOVE)) {
482*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_MEMBER_NOT_FOUND;
483*7836SJohn.Forte@Sun.COM 	}
484*7836SJohn.Forte@Sun.COM 
485*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
486*7836SJohn.Forte@Sun.COM 		goto out;
487*7836SJohn.Forte@Sun.COM 	}
488*7836SJohn.Forte@Sun.COM 
489*7836SJohn.Forte@Sun.COM 	/*
490*7836SJohn.Forte@Sun.COM 	 * If we're adding, we have one more step. Add the member to the
491*7836SJohn.Forte@Sun.COM 	 * propval list
492*7836SJohn.Forte@Sun.COM 	 */
493*7836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
494*7836SJohn.Forte@Sun.COM 		/*
495*7836SJohn.Forte@Sun.COM 		 * Now create the new entry
496*7836SJohn.Forte@Sun.COM 		 */
497*7836SJohn.Forte@Sun.COM 		valueSet[i] = scf_value_create(handle);
498*7836SJohn.Forte@Sun.COM 		if (valueSet[i] == NULL) {
499*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
500*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
501*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
502*7836SJohn.Forte@Sun.COM 			goto out;
503*7836SJohn.Forte@Sun.COM 		} else {
504*7836SJohn.Forte@Sun.COM 			valueArraySize++;
505*7836SJohn.Forte@Sun.COM 		}
506*7836SJohn.Forte@Sun.COM 
507*7836SJohn.Forte@Sun.COM 		/*
508*7836SJohn.Forte@Sun.COM 		 * Set the new member name
509*7836SJohn.Forte@Sun.COM 		 */
510*7836SJohn.Forte@Sun.COM 		if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
511*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
512*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
513*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
514*7836SJohn.Forte@Sun.COM 			goto out;
515*7836SJohn.Forte@Sun.COM 		}
516*7836SJohn.Forte@Sun.COM 
517*7836SJohn.Forte@Sun.COM 		/*
518*7836SJohn.Forte@Sun.COM 		 * Add the new member
519*7836SJohn.Forte@Sun.COM 		 */
520*7836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
521*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
522*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
523*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
524*7836SJohn.Forte@Sun.COM 			goto out;
525*7836SJohn.Forte@Sun.COM 		}
526*7836SJohn.Forte@Sun.COM 	}
527*7836SJohn.Forte@Sun.COM 
528*7836SJohn.Forte@Sun.COM 	/*
529*7836SJohn.Forte@Sun.COM 	 * Yes, we're finally done. We actually added or removed one entry
530*7836SJohn.Forte@Sun.COM 	 * from the list.
531*7836SJohn.Forte@Sun.COM 	 * Woohoo!
532*7836SJohn.Forte@Sun.COM 	 */
533*7836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
534*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
535*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
536*7836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
537*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
538*7836SJohn.Forte@Sun.COM 		} else {
539*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
540*7836SJohn.Forte@Sun.COM 		}
541*7836SJohn.Forte@Sun.COM 		goto out;
542*7836SJohn.Forte@Sun.COM 	}
543*7836SJohn.Forte@Sun.COM 
544*7836SJohn.Forte@Sun.COM out:
545*7836SJohn.Forte@Sun.COM 	/*
546*7836SJohn.Forte@Sun.COM 	 * Free resources
547*7836SJohn.Forte@Sun.COM 	 */
548*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
549*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
550*7836SJohn.Forte@Sun.COM 	}
551*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
552*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
553*7836SJohn.Forte@Sun.COM 	}
554*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
555*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
556*7836SJohn.Forte@Sun.COM 	}
557*7836SJohn.Forte@Sun.COM 	if (tran != NULL) {
558*7836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
559*7836SJohn.Forte@Sun.COM 	}
560*7836SJohn.Forte@Sun.COM 	if (entry != NULL) {
561*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry);
562*7836SJohn.Forte@Sun.COM 	}
563*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
564*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
565*7836SJohn.Forte@Sun.COM 	}
566*7836SJohn.Forte@Sun.COM 	if (valueLookup != NULL) {
567*7836SJohn.Forte@Sun.COM 		scf_value_destroy(valueLookup);
568*7836SJohn.Forte@Sun.COM 	}
569*7836SJohn.Forte@Sun.COM 	if (valueIter != NULL) {
570*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(valueIter);
571*7836SJohn.Forte@Sun.COM 	}
572*7836SJohn.Forte@Sun.COM 
573*7836SJohn.Forte@Sun.COM 	/*
574*7836SJohn.Forte@Sun.COM 	 * Free valueSet scf resources
575*7836SJohn.Forte@Sun.COM 	 */
576*7836SJohn.Forte@Sun.COM 	if (valueArraySize > 0) {
577*7836SJohn.Forte@Sun.COM 		for (i = 0; i < valueArraySize; i++) {
578*7836SJohn.Forte@Sun.COM 			scf_value_destroy(valueSet[i]);
579*7836SJohn.Forte@Sun.COM 		}
580*7836SJohn.Forte@Sun.COM 	}
581*7836SJohn.Forte@Sun.COM 	/*
582*7836SJohn.Forte@Sun.COM 	 * Now free the pointer array to the resources
583*7836SJohn.Forte@Sun.COM 	 */
584*7836SJohn.Forte@Sun.COM 	if (valueSet != NULL) {
585*7836SJohn.Forte@Sun.COM 		free(valueSet);
586*7836SJohn.Forte@Sun.COM 	}
587*7836SJohn.Forte@Sun.COM 
588*7836SJohn.Forte@Sun.COM 	return (ret);
589*7836SJohn.Forte@Sun.COM }
590*7836SJohn.Forte@Sun.COM 
591*7836SJohn.Forte@Sun.COM /*
592*7836SJohn.Forte@Sun.COM  * iPsAddRemoveLuViewEntry
593*7836SJohn.Forte@Sun.COM  *
594*7836SJohn.Forte@Sun.COM  * Adds or removes a view entry name property for a given logical unit
595*7836SJohn.Forte@Sun.COM  * property group. There is one logical unit property group for every logical
596*7836SJohn.Forte@Sun.COM  * unit that has one or more associated view entries.
597*7836SJohn.Forte@Sun.COM  *
598*7836SJohn.Forte@Sun.COM  * luPgName - Property group name of logical unit
599*7836SJohn.Forte@Sun.COM  * viewEntryPgName - Property group name of view entry
600*7836SJohn.Forte@Sun.COM  * addRemoveFlag - ADD_VE/REMOVE_VE
601*7836SJohn.Forte@Sun.COM  *
602*7836SJohn.Forte@Sun.COM  * returns:
603*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
604*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
605*7836SJohn.Forte@Sun.COM  */
606*7836SJohn.Forte@Sun.COM static int
607*7836SJohn.Forte@Sun.COM iPsAddRemoveLuViewEntry(char *luPgName, char *viewEntryPgName,
608*7836SJohn.Forte@Sun.COM     int addRemoveFlag)
609*7836SJohn.Forte@Sun.COM {
610*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
611*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
612*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
613*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
614*7836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
615*7836SJohn.Forte@Sun.COM 	scf_transaction_t   *tran = NULL;
616*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry = NULL;
617*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entryVeName = NULL;
618*7836SJohn.Forte@Sun.COM 	boolean_t createVeCnt = B_FALSE;
619*7836SJohn.Forte@Sun.COM 	uint64_t veCnt = 0;
620*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
621*7836SJohn.Forte@Sun.COM 	int commitRet;
622*7836SJohn.Forte@Sun.COM 
623*7836SJohn.Forte@Sun.COM 	assert(luPgName != NULL || viewEntryPgName != NULL);
624*7836SJohn.Forte@Sun.COM 	assert(!(addRemoveFlag != ADD && addRemoveFlag != REMOVE));
625*7836SJohn.Forte@Sun.COM 
626*7836SJohn.Forte@Sun.COM 	/*
627*7836SJohn.Forte@Sun.COM 	 * Init the service handle
628*7836SJohn.Forte@Sun.COM 	 */
629*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
630*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
631*7836SJohn.Forte@Sun.COM 		goto out;
632*7836SJohn.Forte@Sun.COM 	}
633*7836SJohn.Forte@Sun.COM 
634*7836SJohn.Forte@Sun.COM 	/*
635*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
636*7836SJohn.Forte@Sun.COM 	 */
637*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
638*7836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
639*7836SJohn.Forte@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
640*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
641*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
642*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
643*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
644*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
645*7836SJohn.Forte@Sun.COM 		goto out;
646*7836SJohn.Forte@Sun.COM 	}
647*7836SJohn.Forte@Sun.COM 
648*7836SJohn.Forte@Sun.COM 	/* get the LU property group */
649*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, luPgName, pg) == -1) {
650*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND &&
651*7836SJohn.Forte@Sun.COM 		    addRemoveFlag == ADD) {
652*7836SJohn.Forte@Sun.COM 			/* if it doesn't exist, create it */
653*7836SJohn.Forte@Sun.COM 			if (scf_service_add_pg(svc, luPgName,
654*7836SJohn.Forte@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
655*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
656*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
657*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
658*7836SJohn.Forte@Sun.COM 			} else {
659*7836SJohn.Forte@Sun.COM 				/* we need to create the VE_CNT property */
660*7836SJohn.Forte@Sun.COM 				createVeCnt = B_TRUE;
661*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_SUCCESS;
662*7836SJohn.Forte@Sun.COM 			}
663*7836SJohn.Forte@Sun.COM 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
664*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
665*7836SJohn.Forte@Sun.COM 		} else {
666*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
667*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
668*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
669*7836SJohn.Forte@Sun.COM 		}
670*7836SJohn.Forte@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
671*7836SJohn.Forte@Sun.COM 			goto out;
672*7836SJohn.Forte@Sun.COM 		}
673*7836SJohn.Forte@Sun.COM 	}
674*7836SJohn.Forte@Sun.COM 
675*7836SJohn.Forte@Sun.COM 
676*7836SJohn.Forte@Sun.COM 	/*
677*7836SJohn.Forte@Sun.COM 	 * Begin the transaction
678*7836SJohn.Forte@Sun.COM 	 */
679*7836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
680*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
681*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
682*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
683*7836SJohn.Forte@Sun.COM 		goto out;
684*7836SJohn.Forte@Sun.COM 	}
685*7836SJohn.Forte@Sun.COM 
686*7836SJohn.Forte@Sun.COM 
687*7836SJohn.Forte@Sun.COM 	if (createVeCnt) {
688*7836SJohn.Forte@Sun.COM 		/*
689*7836SJohn.Forte@Sun.COM 		 * Create the STMF_VE_CNT property. This will keep the current
690*7836SJohn.Forte@Sun.COM 		 * total view entries for this logical unit.
691*7836SJohn.Forte@Sun.COM 		 */
692*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry, STMF_VE_CNT,
693*7836SJohn.Forte@Sun.COM 		    SCF_TYPE_COUNT) == -1) {
694*7836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
695*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
696*7836SJohn.Forte@Sun.COM 			} else {
697*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
698*7836SJohn.Forte@Sun.COM 				    "transaction property new failed - %s",
699*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
700*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
701*7836SJohn.Forte@Sun.COM 			}
702*7836SJohn.Forte@Sun.COM 			goto out;
703*7836SJohn.Forte@Sun.COM 		}
704*7836SJohn.Forte@Sun.COM 	} else {
705*7836SJohn.Forte@Sun.COM 		/*
706*7836SJohn.Forte@Sun.COM 		 * The STMF_VE_CNT property already exists. Just update
707*7836SJohn.Forte@Sun.COM 		 * it.
708*7836SJohn.Forte@Sun.COM 		 */
709*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_change(tran, entry,
710*7836SJohn.Forte@Sun.COM 		    STMF_VE_CNT, SCF_TYPE_COUNT) == -1) {
711*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
712*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
713*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
714*7836SJohn.Forte@Sun.COM 			goto out;
715*7836SJohn.Forte@Sun.COM 		}
716*7836SJohn.Forte@Sun.COM 
717*7836SJohn.Forte@Sun.COM 		/*
718*7836SJohn.Forte@Sun.COM 		 * Get the STMF_VE_CNT property
719*7836SJohn.Forte@Sun.COM 		 */
720*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) {
721*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
722*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
723*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
724*7836SJohn.Forte@Sun.COM 			goto out;
725*7836SJohn.Forte@Sun.COM 		}
726*7836SJohn.Forte@Sun.COM 
727*7836SJohn.Forte@Sun.COM 		/*
728*7836SJohn.Forte@Sun.COM 		 * Get the STMF_VE_CNT value
729*7836SJohn.Forte@Sun.COM 		 */
730*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
731*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
732*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
733*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
734*7836SJohn.Forte@Sun.COM 			goto out;
735*7836SJohn.Forte@Sun.COM 		}
736*7836SJohn.Forte@Sun.COM 
737*7836SJohn.Forte@Sun.COM 		/*
738*7836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
739*7836SJohn.Forte@Sun.COM 		 */
740*7836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value, &veCnt) == -1) {
741*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get integer value failed - %s",
742*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
743*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
744*7836SJohn.Forte@Sun.COM 			goto out;
745*7836SJohn.Forte@Sun.COM 		}
746*7836SJohn.Forte@Sun.COM 
747*7836SJohn.Forte@Sun.COM 		/*
748*7836SJohn.Forte@Sun.COM 		 * Reset the value resource as it is used below
749*7836SJohn.Forte@Sun.COM 		 */
750*7836SJohn.Forte@Sun.COM 		scf_value_reset(value);
751*7836SJohn.Forte@Sun.COM 	}
752*7836SJohn.Forte@Sun.COM 
753*7836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
754*7836SJohn.Forte@Sun.COM 		veCnt++;
755*7836SJohn.Forte@Sun.COM 	} else {
756*7836SJohn.Forte@Sun.COM 		/* Check if this is the last one being removed */
757*7836SJohn.Forte@Sun.COM 		if (veCnt == 1) {
758*7836SJohn.Forte@Sun.COM 			/*
759*7836SJohn.Forte@Sun.COM 			 * Delete the pg and get out if this is the last
760*7836SJohn.Forte@Sun.COM 			 * view entry
761*7836SJohn.Forte@Sun.COM 			 */
762*7836SJohn.Forte@Sun.COM 			if (scf_pg_delete(pg) == -1) {
763*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "delete pg failed - %s",
764*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
765*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
766*7836SJohn.Forte@Sun.COM 			}
767*7836SJohn.Forte@Sun.COM 			goto out;
768*7836SJohn.Forte@Sun.COM 		} else {
769*7836SJohn.Forte@Sun.COM 			veCnt--;
770*7836SJohn.Forte@Sun.COM 		}
771*7836SJohn.Forte@Sun.COM 	}
772*7836SJohn.Forte@Sun.COM 
773*7836SJohn.Forte@Sun.COM 
774*7836SJohn.Forte@Sun.COM 	/*
775*7836SJohn.Forte@Sun.COM 	 * Set the view entry count
776*7836SJohn.Forte@Sun.COM 	 */
777*7836SJohn.Forte@Sun.COM 	scf_value_set_count(value, veCnt);
778*7836SJohn.Forte@Sun.COM 
779*7836SJohn.Forte@Sun.COM 	/*
780*7836SJohn.Forte@Sun.COM 	 * Add the value to the transaction entry
781*7836SJohn.Forte@Sun.COM 	 */
782*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry, value) == -1) {
783*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
784*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
785*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
786*7836SJohn.Forte@Sun.COM 		goto out;
787*7836SJohn.Forte@Sun.COM 	}
788*7836SJohn.Forte@Sun.COM 
789*7836SJohn.Forte@Sun.COM 	/*
790*7836SJohn.Forte@Sun.COM 	 * Create a transaction entry resource for the view entry name
791*7836SJohn.Forte@Sun.COM 	 */
792*7836SJohn.Forte@Sun.COM 	entryVeName = scf_entry_create(handle);
793*7836SJohn.Forte@Sun.COM 	if (entryVeName == NULL) {
794*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf transaction entry alloc failed - %s",
795*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
796*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
797*7836SJohn.Forte@Sun.COM 		goto out;
798*7836SJohn.Forte@Sun.COM 	}
799*7836SJohn.Forte@Sun.COM 
800*7836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
801*7836SJohn.Forte@Sun.COM 		/*
802*7836SJohn.Forte@Sun.COM 		 * If adding, create a property with the view entry name
803*7836SJohn.Forte@Sun.COM 		 */
804*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entryVeName,
805*7836SJohn.Forte@Sun.COM 		    viewEntryPgName, SCF_TYPE_USTRING) == -1) {
806*7836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
807*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
808*7836SJohn.Forte@Sun.COM 			} else {
809*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
810*7836SJohn.Forte@Sun.COM 				    "transaction property new failed - %s",
811*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
812*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
813*7836SJohn.Forte@Sun.COM 			}
814*7836SJohn.Forte@Sun.COM 			goto out;
815*7836SJohn.Forte@Sun.COM 		}
816*7836SJohn.Forte@Sun.COM 	} else {
817*7836SJohn.Forte@Sun.COM 		/*
818*7836SJohn.Forte@Sun.COM 		 * If removing, delete the existing property with the view
819*7836SJohn.Forte@Sun.COM 		 * entry name
820*7836SJohn.Forte@Sun.COM 		 */
821*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, entryVeName,
822*7836SJohn.Forte@Sun.COM 		    viewEntryPgName) == -1) {
823*7836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND) {
824*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_NOT_FOUND;
825*7836SJohn.Forte@Sun.COM 			} else {
826*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
827*7836SJohn.Forte@Sun.COM 				    "transaction property delete failed - %s",
828*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
829*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
830*7836SJohn.Forte@Sun.COM 			}
831*7836SJohn.Forte@Sun.COM 			goto out;
832*7836SJohn.Forte@Sun.COM 		}
833*7836SJohn.Forte@Sun.COM 	}
834*7836SJohn.Forte@Sun.COM 
835*7836SJohn.Forte@Sun.COM 	/*
836*7836SJohn.Forte@Sun.COM 	 * Commit property transaction
837*7836SJohn.Forte@Sun.COM 	 */
838*7836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
839*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
840*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
841*7836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
842*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
843*7836SJohn.Forte@Sun.COM 		} else {
844*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
845*7836SJohn.Forte@Sun.COM 		}
846*7836SJohn.Forte@Sun.COM 		goto out;
847*7836SJohn.Forte@Sun.COM 	}
848*7836SJohn.Forte@Sun.COM 
849*7836SJohn.Forte@Sun.COM out:
850*7836SJohn.Forte@Sun.COM 	/*
851*7836SJohn.Forte@Sun.COM 	 * Free resources
852*7836SJohn.Forte@Sun.COM 	 */
853*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
854*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
855*7836SJohn.Forte@Sun.COM 	}
856*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
857*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
858*7836SJohn.Forte@Sun.COM 	}
859*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
860*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
861*7836SJohn.Forte@Sun.COM 	}
862*7836SJohn.Forte@Sun.COM 	if (tran != NULL) {
863*7836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
864*7836SJohn.Forte@Sun.COM 	}
865*7836SJohn.Forte@Sun.COM 	if (entry != NULL) {
866*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry);
867*7836SJohn.Forte@Sun.COM 	}
868*7836SJohn.Forte@Sun.COM 	if (entryVeName != NULL) {
869*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entryVeName);
870*7836SJohn.Forte@Sun.COM 	}
871*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
872*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
873*7836SJohn.Forte@Sun.COM 	}
874*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
875*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
876*7836SJohn.Forte@Sun.COM 	}
877*7836SJohn.Forte@Sun.COM 
878*7836SJohn.Forte@Sun.COM 	return (ret);
879*7836SJohn.Forte@Sun.COM }
880*7836SJohn.Forte@Sun.COM 
881*7836SJohn.Forte@Sun.COM /*
882*7836SJohn.Forte@Sun.COM  * iPsAddViewEntry
883*7836SJohn.Forte@Sun.COM  *
884*7836SJohn.Forte@Sun.COM  * Add a view entry property group and optionally, a logical unit property
885*7836SJohn.Forte@Sun.COM  * group if it does not exist.
886*7836SJohn.Forte@Sun.COM  *
887*7836SJohn.Forte@Sun.COM  * luName - ascii hexadecimal logical unit identifier
888*7836SJohn.Forte@Sun.COM  * viewEntryName - name of view entry (VIEW_ENTRY_nn)
889*7836SJohn.Forte@Sun.COM  * viewEntry - pointer to stmfViewEntry structure
890*7836SJohn.Forte@Sun.COM  */
891*7836SJohn.Forte@Sun.COM static int
892*7836SJohn.Forte@Sun.COM iPsAddViewEntry(char *luPgName, char *viewEntryPgName, stmfViewEntry *viewEntry)
893*7836SJohn.Forte@Sun.COM {
894*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
895*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
896*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
897*7836SJohn.Forte@Sun.COM 	scf_value_t	*value[VIEW_ENTRY_STRUCT_CNT];
898*7836SJohn.Forte@Sun.COM 	scf_transaction_t   *tran = NULL;
899*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry[VIEW_ENTRY_STRUCT_CNT];
900*7836SJohn.Forte@Sun.COM 	int i = 0;
901*7836SJohn.Forte@Sun.COM 	int j = 0;
902*7836SJohn.Forte@Sun.COM 	int ret;
903*7836SJohn.Forte@Sun.COM 	uint8_t scfBool;
904*7836SJohn.Forte@Sun.COM 	boolean_t createdVePg = B_FALSE;
905*7836SJohn.Forte@Sun.COM 	int backoutRet;
906*7836SJohn.Forte@Sun.COM 	int commitRet;
907*7836SJohn.Forte@Sun.COM 
908*7836SJohn.Forte@Sun.COM 	assert(luPgName != NULL || viewEntryPgName != NULL ||
909*7836SJohn.Forte@Sun.COM 	    viewEntry == NULL);
910*7836SJohn.Forte@Sun.COM 
911*7836SJohn.Forte@Sun.COM 	bzero(value, sizeof (value));
912*7836SJohn.Forte@Sun.COM 	bzero(entry, sizeof (entry));
913*7836SJohn.Forte@Sun.COM 
914*7836SJohn.Forte@Sun.COM 	/*
915*7836SJohn.Forte@Sun.COM 	 * Init the service handle
916*7836SJohn.Forte@Sun.COM 	 */
917*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
918*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
919*7836SJohn.Forte@Sun.COM 		goto out;
920*7836SJohn.Forte@Sun.COM 	}
921*7836SJohn.Forte@Sun.COM 
922*7836SJohn.Forte@Sun.COM 	/*
923*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
924*7836SJohn.Forte@Sun.COM 	 */
925*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
926*7836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL)) {
927*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
928*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
929*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
930*7836SJohn.Forte@Sun.COM 		goto out;
931*7836SJohn.Forte@Sun.COM 	}
932*7836SJohn.Forte@Sun.COM 
933*7836SJohn.Forte@Sun.COM 	/*
934*7836SJohn.Forte@Sun.COM 	 * allocate value and entry resources for scf
935*7836SJohn.Forte@Sun.COM 	 */
936*7836SJohn.Forte@Sun.COM 	for (i = 0; i < VIEW_ENTRY_STRUCT_CNT; i++) {
937*7836SJohn.Forte@Sun.COM 		if (((value[i] = scf_value_create(handle)) == NULL) ||
938*7836SJohn.Forte@Sun.COM 		    ((entry[i] = scf_entry_create(handle)) == NULL)) {
939*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf alloc resource failed - %s",
940*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
941*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
942*7836SJohn.Forte@Sun.COM 			goto out;
943*7836SJohn.Forte@Sun.COM 		}
944*7836SJohn.Forte@Sun.COM 	}
945*7836SJohn.Forte@Sun.COM 
946*7836SJohn.Forte@Sun.COM 	i = 0;
947*7836SJohn.Forte@Sun.COM 
948*7836SJohn.Forte@Sun.COM 	/*
949*7836SJohn.Forte@Sun.COM 	 * Create the View Entry property group
950*7836SJohn.Forte@Sun.COM 	 */
951*7836SJohn.Forte@Sun.COM 	if (scf_service_add_pg(svc, viewEntryPgName, SCF_GROUP_APPLICATION,
952*7836SJohn.Forte@Sun.COM 	    0, pg) == -1) {
953*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
954*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
955*7836SJohn.Forte@Sun.COM 		} else {
956*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add pg failed - %s",
957*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
958*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
959*7836SJohn.Forte@Sun.COM 		}
960*7836SJohn.Forte@Sun.COM 		goto out;
961*7836SJohn.Forte@Sun.COM 	}
962*7836SJohn.Forte@Sun.COM 
963*7836SJohn.Forte@Sun.COM 	createdVePg = B_TRUE;
964*7836SJohn.Forte@Sun.COM 
965*7836SJohn.Forte@Sun.COM 	/*
966*7836SJohn.Forte@Sun.COM 	 * Add the view entry as properties on the view entry group
967*7836SJohn.Forte@Sun.COM 	 */
968*7836SJohn.Forte@Sun.COM 
969*7836SJohn.Forte@Sun.COM 	/*
970*7836SJohn.Forte@Sun.COM 	 * Begin property update transaction
971*7836SJohn.Forte@Sun.COM 	 */
972*7836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
973*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
974*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
975*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
976*7836SJohn.Forte@Sun.COM 		goto out;
977*7836SJohn.Forte@Sun.COM 	}
978*7836SJohn.Forte@Sun.COM 
979*7836SJohn.Forte@Sun.COM 	/*
980*7836SJohn.Forte@Sun.COM 	 * Add allHosts property
981*7836SJohn.Forte@Sun.COM 	 */
982*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
983*7836SJohn.Forte@Sun.COM 	    STMF_VE_ALLHOSTS, SCF_TYPE_BOOLEAN) == -1) {
984*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
985*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
986*7836SJohn.Forte@Sun.COM 		} else {
987*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
988*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
989*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
990*7836SJohn.Forte@Sun.COM 		}
991*7836SJohn.Forte@Sun.COM 		goto out;
992*7836SJohn.Forte@Sun.COM 	}
993*7836SJohn.Forte@Sun.COM 
994*7836SJohn.Forte@Sun.COM 	/* Set the allHosts value */
995*7836SJohn.Forte@Sun.COM 	scfBool = viewEntry->allHosts;
996*7836SJohn.Forte@Sun.COM 	scf_value_set_boolean(value[i], scfBool);
997*7836SJohn.Forte@Sun.COM 
998*7836SJohn.Forte@Sun.COM 	/*
999*7836SJohn.Forte@Sun.COM 	 * Add the allHosts value to the transaction
1000*7836SJohn.Forte@Sun.COM 	 */
1001*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
1002*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
1003*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1004*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1005*7836SJohn.Forte@Sun.COM 		goto out;
1006*7836SJohn.Forte@Sun.COM 	}
1007*7836SJohn.Forte@Sun.COM 
1008*7836SJohn.Forte@Sun.COM 	i++;
1009*7836SJohn.Forte@Sun.COM 
1010*7836SJohn.Forte@Sun.COM 	/*
1011*7836SJohn.Forte@Sun.COM 	 * Create hostGroup property
1012*7836SJohn.Forte@Sun.COM 	 */
1013*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
1014*7836SJohn.Forte@Sun.COM 	    STMF_VE_HOSTGROUP, SCF_TYPE_USTRING) == -1) {
1015*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
1016*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
1017*7836SJohn.Forte@Sun.COM 		} else {
1018*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
1019*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1020*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1021*7836SJohn.Forte@Sun.COM 		}
1022*7836SJohn.Forte@Sun.COM 		goto out;
1023*7836SJohn.Forte@Sun.COM 	}
1024*7836SJohn.Forte@Sun.COM 
1025*7836SJohn.Forte@Sun.COM 	/*
1026*7836SJohn.Forte@Sun.COM 	 * Set the value for hostGroup
1027*7836SJohn.Forte@Sun.COM 	 */
1028*7836SJohn.Forte@Sun.COM 	if (scf_value_set_ustring(value[i], viewEntry->hostGroup) == -1) {
1029*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
1030*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1031*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1032*7836SJohn.Forte@Sun.COM 		goto out;
1033*7836SJohn.Forte@Sun.COM 	}
1034*7836SJohn.Forte@Sun.COM 
1035*7836SJohn.Forte@Sun.COM 	/*
1036*7836SJohn.Forte@Sun.COM 	 * Add the hostGroup value to the transaction entry
1037*7836SJohn.Forte@Sun.COM 	 */
1038*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
1039*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
1040*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1041*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1042*7836SJohn.Forte@Sun.COM 		goto out;
1043*7836SJohn.Forte@Sun.COM 	}
1044*7836SJohn.Forte@Sun.COM 
1045*7836SJohn.Forte@Sun.COM 	i++;
1046*7836SJohn.Forte@Sun.COM 
1047*7836SJohn.Forte@Sun.COM 	/*
1048*7836SJohn.Forte@Sun.COM 	 * Create the allTargets property
1049*7836SJohn.Forte@Sun.COM 	 */
1050*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
1051*7836SJohn.Forte@Sun.COM 	    STMF_VE_ALLTARGETS, SCF_TYPE_BOOLEAN) == -1) {
1052*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
1053*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
1054*7836SJohn.Forte@Sun.COM 		} else {
1055*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
1056*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1057*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1058*7836SJohn.Forte@Sun.COM 		}
1059*7836SJohn.Forte@Sun.COM 		goto out;
1060*7836SJohn.Forte@Sun.COM 	}
1061*7836SJohn.Forte@Sun.COM 
1062*7836SJohn.Forte@Sun.COM 	/*
1063*7836SJohn.Forte@Sun.COM 	 * Set the allTargets value
1064*7836SJohn.Forte@Sun.COM 	 */
1065*7836SJohn.Forte@Sun.COM 	scfBool = viewEntry->allTargets;
1066*7836SJohn.Forte@Sun.COM 	scf_value_set_boolean(value[i], scfBool);
1067*7836SJohn.Forte@Sun.COM 
1068*7836SJohn.Forte@Sun.COM 	/*
1069*7836SJohn.Forte@Sun.COM 	 * Add the allTargets value to the transaction
1070*7836SJohn.Forte@Sun.COM 	 */
1071*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
1072*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
1073*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1074*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1075*7836SJohn.Forte@Sun.COM 		goto out;
1076*7836SJohn.Forte@Sun.COM 	}
1077*7836SJohn.Forte@Sun.COM 
1078*7836SJohn.Forte@Sun.COM 	i++;
1079*7836SJohn.Forte@Sun.COM 
1080*7836SJohn.Forte@Sun.COM 	/*
1081*7836SJohn.Forte@Sun.COM 	 * Create targetGroup property
1082*7836SJohn.Forte@Sun.COM 	 */
1083*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i],
1084*7836SJohn.Forte@Sun.COM 	    STMF_VE_TARGETGROUP, SCF_TYPE_USTRING) == -1) {
1085*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
1086*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
1087*7836SJohn.Forte@Sun.COM 		} else {
1088*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
1089*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1090*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1091*7836SJohn.Forte@Sun.COM 		}
1092*7836SJohn.Forte@Sun.COM 		goto out;
1093*7836SJohn.Forte@Sun.COM 	}
1094*7836SJohn.Forte@Sun.COM 
1095*7836SJohn.Forte@Sun.COM 	/*
1096*7836SJohn.Forte@Sun.COM 	 * Set the value for targetGroup
1097*7836SJohn.Forte@Sun.COM 	 */
1098*7836SJohn.Forte@Sun.COM 	if (scf_value_set_ustring(value[i], viewEntry->targetGroup) == -1) {
1099*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
1100*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1101*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1102*7836SJohn.Forte@Sun.COM 		goto out;
1103*7836SJohn.Forte@Sun.COM 	}
1104*7836SJohn.Forte@Sun.COM 
1105*7836SJohn.Forte@Sun.COM 	/*
1106*7836SJohn.Forte@Sun.COM 	 * Add targetGroup value to the transaction
1107*7836SJohn.Forte@Sun.COM 	 */
1108*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
1109*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
1110*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1111*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1112*7836SJohn.Forte@Sun.COM 		goto out;
1113*7836SJohn.Forte@Sun.COM 	}
1114*7836SJohn.Forte@Sun.COM 
1115*7836SJohn.Forte@Sun.COM 	i++;
1116*7836SJohn.Forte@Sun.COM 
1117*7836SJohn.Forte@Sun.COM 	/*
1118*7836SJohn.Forte@Sun.COM 	 * Create the luNbr property
1119*7836SJohn.Forte@Sun.COM 	 */
1120*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry[i], STMF_VE_LUNBR,
1121*7836SJohn.Forte@Sun.COM 	    SCF_TYPE_OPAQUE) == -1) {
1122*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
1123*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_EXISTS;
1124*7836SJohn.Forte@Sun.COM 		} else {
1125*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
1126*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1127*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1128*7836SJohn.Forte@Sun.COM 		}
1129*7836SJohn.Forte@Sun.COM 		goto out;
1130*7836SJohn.Forte@Sun.COM 	}
1131*7836SJohn.Forte@Sun.COM 
1132*7836SJohn.Forte@Sun.COM 	/*
1133*7836SJohn.Forte@Sun.COM 	 * Set the luNbr
1134*7836SJohn.Forte@Sun.COM 	 */
1135*7836SJohn.Forte@Sun.COM 	if (scf_value_set_opaque(value[i], (char *)viewEntry->luNbr,
1136*7836SJohn.Forte@Sun.COM 	    sizeof (viewEntry->luNbr)) == -1) {
1137*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
1138*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1139*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1140*7836SJohn.Forte@Sun.COM 		goto out;
1141*7836SJohn.Forte@Sun.COM 	}
1142*7836SJohn.Forte@Sun.COM 
1143*7836SJohn.Forte@Sun.COM 	/*
1144*7836SJohn.Forte@Sun.COM 	 * Add luNbr to the transaction entry
1145*7836SJohn.Forte@Sun.COM 	 */
1146*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry[i], value[i]) == -1) {
1147*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
1148*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1149*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1150*7836SJohn.Forte@Sun.COM 		goto out;
1151*7836SJohn.Forte@Sun.COM 	}
1152*7836SJohn.Forte@Sun.COM 
1153*7836SJohn.Forte@Sun.COM 	/*
1154*7836SJohn.Forte@Sun.COM 	 * Now that we've successfully added the view entry,
1155*7836SJohn.Forte@Sun.COM 	 * update the logical unit property group or create
1156*7836SJohn.Forte@Sun.COM 	 * it if it does not exist
1157*7836SJohn.Forte@Sun.COM 	 */
1158*7836SJohn.Forte@Sun.COM 	ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName, ADD);
1159*7836SJohn.Forte@Sun.COM 
1160*7836SJohn.Forte@Sun.COM 	/*
1161*7836SJohn.Forte@Sun.COM 	 * If we did not add the view entry name to the logical unit,
1162*7836SJohn.Forte@Sun.COM 	 * make sure we do not commit the transaction
1163*7836SJohn.Forte@Sun.COM 	 */
1164*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1165*7836SJohn.Forte@Sun.COM 		goto out;
1166*7836SJohn.Forte@Sun.COM 	}
1167*7836SJohn.Forte@Sun.COM 
1168*7836SJohn.Forte@Sun.COM 	/*
1169*7836SJohn.Forte@Sun.COM 	 * Commit property transaction
1170*7836SJohn.Forte@Sun.COM 	 */
1171*7836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
1172*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
1173*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1174*7836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
1175*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
1176*7836SJohn.Forte@Sun.COM 		} else {
1177*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1178*7836SJohn.Forte@Sun.COM 		}
1179*7836SJohn.Forte@Sun.COM 	}
1180*7836SJohn.Forte@Sun.COM 
1181*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1182*7836SJohn.Forte@Sun.COM 		/*
1183*7836SJohn.Forte@Sun.COM 		 * If we did not commit, try to remove the view entry name
1184*7836SJohn.Forte@Sun.COM 		 * from the logical unit.
1185*7836SJohn.Forte@Sun.COM 		 * If that fails, we're now inconsistent.
1186*7836SJohn.Forte@Sun.COM 		 */
1187*7836SJohn.Forte@Sun.COM 		backoutRet = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
1188*7836SJohn.Forte@Sun.COM 		    REMOVE);
1189*7836SJohn.Forte@Sun.COM 
1190*7836SJohn.Forte@Sun.COM 		if (backoutRet != STMF_PS_SUCCESS) {
1191*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "remove lu view entry failed"
1192*7836SJohn.Forte@Sun.COM 			    "possible inconsistency - %s",
1193*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1194*7836SJohn.Forte@Sun.COM 		}
1195*7836SJohn.Forte@Sun.COM 		/*
1196*7836SJohn.Forte@Sun.COM 		 * We are still in an error scenario even though the remove
1197*7836SJohn.Forte@Sun.COM 		 * lu view entry succeeded.
1198*7836SJohn.Forte@Sun.COM 		 */
1199*7836SJohn.Forte@Sun.COM 		goto out;
1200*7836SJohn.Forte@Sun.COM 	}
1201*7836SJohn.Forte@Sun.COM 
1202*7836SJohn.Forte@Sun.COM out:
1203*7836SJohn.Forte@Sun.COM 	/*
1204*7836SJohn.Forte@Sun.COM 	 * Free resources
1205*7836SJohn.Forte@Sun.COM 	 */
1206*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
1207*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
1208*7836SJohn.Forte@Sun.COM 	}
1209*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
1210*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
1211*7836SJohn.Forte@Sun.COM 	}
1212*7836SJohn.Forte@Sun.COM 	/* if there was an error, delete the created pg if one was created */
1213*7836SJohn.Forte@Sun.COM 	if ((ret != STMF_PS_SUCCESS) && createdVePg) {
1214*7836SJohn.Forte@Sun.COM 		if (scf_pg_delete(pg) == -1) {
1215*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "delete VE pg failed - %s",
1216*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1217*7836SJohn.Forte@Sun.COM 		}
1218*7836SJohn.Forte@Sun.COM 	}
1219*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
1220*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
1221*7836SJohn.Forte@Sun.COM 	}
1222*7836SJohn.Forte@Sun.COM 	if (tran != NULL) {
1223*7836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
1224*7836SJohn.Forte@Sun.COM 	}
1225*7836SJohn.Forte@Sun.COM 	/*
1226*7836SJohn.Forte@Sun.COM 	 * Free value and entry scf resources
1227*7836SJohn.Forte@Sun.COM 	 */
1228*7836SJohn.Forte@Sun.COM 	if (i > 0) {
1229*7836SJohn.Forte@Sun.COM 		for (j = 0; j < VIEW_ENTRY_STRUCT_CNT; j++) {
1230*7836SJohn.Forte@Sun.COM 			if (value[j] != NULL)
1231*7836SJohn.Forte@Sun.COM 				scf_value_destroy(value[j]);
1232*7836SJohn.Forte@Sun.COM 			if (entry[j] != NULL)
1233*7836SJohn.Forte@Sun.COM 				scf_entry_destroy(entry[j]);
1234*7836SJohn.Forte@Sun.COM 		}
1235*7836SJohn.Forte@Sun.COM 	}
1236*7836SJohn.Forte@Sun.COM 
1237*7836SJohn.Forte@Sun.COM 	return (ret);
1238*7836SJohn.Forte@Sun.COM }
1239*7836SJohn.Forte@Sun.COM /*
1240*7836SJohn.Forte@Sun.COM  * psClearProviderData
1241*7836SJohn.Forte@Sun.COM  *
1242*7836SJohn.Forte@Sun.COM  * providerName - name of provider data to clear
1243*7836SJohn.Forte@Sun.COM  */
1244*7836SJohn.Forte@Sun.COM int
1245*7836SJohn.Forte@Sun.COM psClearProviderData(char *providerName, int providerType)
1246*7836SJohn.Forte@Sun.COM {
1247*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
1248*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
1249*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
1250*7836SJohn.Forte@Sun.COM 	char pgName[MAXPATHLEN];
1251*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
1252*7836SJohn.Forte@Sun.COM 	boolean_t pgNotFound = B_FALSE;
1253*7836SJohn.Forte@Sun.COM 
1254*7836SJohn.Forte@Sun.COM 	if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
1255*7836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE)) {
1256*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_INVALID_ARG;
1257*7836SJohn.Forte@Sun.COM 		goto out;
1258*7836SJohn.Forte@Sun.COM 	}
1259*7836SJohn.Forte@Sun.COM 
1260*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
1261*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1262*7836SJohn.Forte@Sun.COM 		goto out;
1263*7836SJohn.Forte@Sun.COM 	}
1264*7836SJohn.Forte@Sun.COM 
1265*7836SJohn.Forte@Sun.COM 	/*
1266*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
1267*7836SJohn.Forte@Sun.COM 	 */
1268*7836SJohn.Forte@Sun.COM 	if ((pg = scf_pg_create(handle)) == NULL) {
1269*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
1270*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1271*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1272*7836SJohn.Forte@Sun.COM 		goto out;
1273*7836SJohn.Forte@Sun.COM 	}
1274*7836SJohn.Forte@Sun.COM 
1275*7836SJohn.Forte@Sun.COM 	/*
1276*7836SJohn.Forte@Sun.COM 	 * create the property group name
1277*7836SJohn.Forte@Sun.COM 	 */
1278*7836SJohn.Forte@Sun.COM 	(void) snprintf(pgName, sizeof (pgName), "%s%s",
1279*7836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PREFIX, providerName);
1280*7836SJohn.Forte@Sun.COM 
1281*7836SJohn.Forte@Sun.COM 	/*
1282*7836SJohn.Forte@Sun.COM 	 * delete provider property group
1283*7836SJohn.Forte@Sun.COM 	 */
1284*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
1285*7836SJohn.Forte@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
1286*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
1287*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1288*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1289*7836SJohn.Forte@Sun.COM 			goto out;
1290*7836SJohn.Forte@Sun.COM 		} else {
1291*7836SJohn.Forte@Sun.COM 			pgNotFound = B_TRUE;
1292*7836SJohn.Forte@Sun.COM 		}
1293*7836SJohn.Forte@Sun.COM 	}
1294*7836SJohn.Forte@Sun.COM 
1295*7836SJohn.Forte@Sun.COM 	if (!pgNotFound && (scf_pg_delete(pg) == -1)) {
1296*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "delete pg failed - %s",
1297*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1298*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1299*7836SJohn.Forte@Sun.COM 		goto out;
1300*7836SJohn.Forte@Sun.COM 	}
1301*7836SJohn.Forte@Sun.COM 
1302*7836SJohn.Forte@Sun.COM 	if (pgNotFound) {
1303*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOT_FOUND;
1304*7836SJohn.Forte@Sun.COM 	}
1305*7836SJohn.Forte@Sun.COM 
1306*7836SJohn.Forte@Sun.COM out:
1307*7836SJohn.Forte@Sun.COM 	/*
1308*7836SJohn.Forte@Sun.COM 	 * Free resources
1309*7836SJohn.Forte@Sun.COM 	 */
1310*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
1311*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
1312*7836SJohn.Forte@Sun.COM 	}
1313*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
1314*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
1315*7836SJohn.Forte@Sun.COM 	}
1316*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
1317*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
1318*7836SJohn.Forte@Sun.COM 	}
1319*7836SJohn.Forte@Sun.COM 
1320*7836SJohn.Forte@Sun.COM 	return (ret);
1321*7836SJohn.Forte@Sun.COM }
1322*7836SJohn.Forte@Sun.COM 
1323*7836SJohn.Forte@Sun.COM /*
1324*7836SJohn.Forte@Sun.COM  * iPsCreateDeleteGroup
1325*7836SJohn.Forte@Sun.COM  *
1326*7836SJohn.Forte@Sun.COM  * Creates or deletes a group (target or host)
1327*7836SJohn.Forte@Sun.COM  *
1328*7836SJohn.Forte@Sun.COM  * When creating a group, two properties are created. One to hold the group
1329*7836SJohn.Forte@Sun.COM  * name and the other to hold the group members.
1330*7836SJohn.Forte@Sun.COM  *
1331*7836SJohn.Forte@Sun.COM  * pgName - Property group name
1332*7836SJohn.Forte@Sun.COM  * groupName - group name to create
1333*7836SJohn.Forte@Sun.COM  * addRemoveFlag - ADD_GROUP/REMOVE_GROUP
1334*7836SJohn.Forte@Sun.COM  *
1335*7836SJohn.Forte@Sun.COM  * returns:
1336*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
1337*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
1338*7836SJohn.Forte@Sun.COM  */
1339*7836SJohn.Forte@Sun.COM static int
1340*7836SJohn.Forte@Sun.COM iPsCreateDeleteGroup(char *pgRefName, char *groupName, int addRemoveFlag)
1341*7836SJohn.Forte@Sun.COM {
1342*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
1343*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
1344*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
1345*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
1346*7836SJohn.Forte@Sun.COM 	scf_iter_t	*propIter = NULL;
1347*7836SJohn.Forte@Sun.COM 	scf_transaction_t   *tran = NULL;
1348*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry1 = NULL;
1349*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry2 = NULL;
1350*7836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
1351*7836SJohn.Forte@Sun.COM 	uint64_t groupIdx;
1352*7836SJohn.Forte@Sun.COM 	char buf1[MAXNAMELEN];
1353*7836SJohn.Forte@Sun.COM 	char buf2[MAXNAMELEN];
1354*7836SJohn.Forte@Sun.COM 	char tmpbuf[MAXNAMELEN];
1355*7836SJohn.Forte@Sun.COM 	boolean_t found = B_FALSE;
1356*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
1357*7836SJohn.Forte@Sun.COM 	int commitRet;
1358*7836SJohn.Forte@Sun.COM 
1359*7836SJohn.Forte@Sun.COM 	assert(groupName != NULL);
1360*7836SJohn.Forte@Sun.COM 
1361*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
1362*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1363*7836SJohn.Forte@Sun.COM 		goto out;
1364*7836SJohn.Forte@Sun.COM 	}
1365*7836SJohn.Forte@Sun.COM 
1366*7836SJohn.Forte@Sun.COM 	/*
1367*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
1368*7836SJohn.Forte@Sun.COM 	 */
1369*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
1370*7836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
1371*7836SJohn.Forte@Sun.COM 	    ((entry1 = scf_entry_create(handle)) == NULL) ||
1372*7836SJohn.Forte@Sun.COM 	    ((entry2 = scf_entry_create(handle)) == NULL) ||
1373*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
1374*7836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
1375*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
1376*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
1377*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1378*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1379*7836SJohn.Forte@Sun.COM 		goto out;
1380*7836SJohn.Forte@Sun.COM 	}
1381*7836SJohn.Forte@Sun.COM 
1382*7836SJohn.Forte@Sun.COM 	/*
1383*7836SJohn.Forte@Sun.COM 	 * Get the property group being modified
1384*7836SJohn.Forte@Sun.COM 	 */
1385*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgRefName, pg) == -1) {
1386*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND &&
1387*7836SJohn.Forte@Sun.COM 		    addRemoveFlag == ADD) {
1388*7836SJohn.Forte@Sun.COM 			if (scf_service_add_pg(svc, pgRefName,
1389*7836SJohn.Forte@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
1390*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
1391*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
1392*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
1393*7836SJohn.Forte@Sun.COM 			}
1394*7836SJohn.Forte@Sun.COM 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
1395*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
1396*7836SJohn.Forte@Sun.COM 		} else {
1397*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
1398*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1399*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1400*7836SJohn.Forte@Sun.COM 		}
1401*7836SJohn.Forte@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
1402*7836SJohn.Forte@Sun.COM 			goto out;
1403*7836SJohn.Forte@Sun.COM 		}
1404*7836SJohn.Forte@Sun.COM 	}
1405*7836SJohn.Forte@Sun.COM 
1406*7836SJohn.Forte@Sun.COM 	/*
1407*7836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
1408*7836SJohn.Forte@Sun.COM 	 */
1409*7836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
1410*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
1411*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1412*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1413*7836SJohn.Forte@Sun.COM 		goto out;
1414*7836SJohn.Forte@Sun.COM 	}
1415*7836SJohn.Forte@Sun.COM 
1416*7836SJohn.Forte@Sun.COM 	/*
1417*7836SJohn.Forte@Sun.COM 	 * Iterate through the group names.
1418*7836SJohn.Forte@Sun.COM 	 * If we find it in the list, it's an error when addRemoveFlag == ADD.
1419*7836SJohn.Forte@Sun.COM 	 */
1420*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
1421*7836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, buf1, sizeof (buf1)) == -1) {
1422*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
1423*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1424*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1425*7836SJohn.Forte@Sun.COM 			break;
1426*7836SJohn.Forte@Sun.COM 		}
1427*7836SJohn.Forte@Sun.COM 		/*
1428*7836SJohn.Forte@Sun.COM 		 * Skip over member list properties
1429*7836SJohn.Forte@Sun.COM 		 */
1430*7836SJohn.Forte@Sun.COM 		if (strstr(buf1, STMF_MEMBER_LIST_SUFFIX)) {
1431*7836SJohn.Forte@Sun.COM 			continue;
1432*7836SJohn.Forte@Sun.COM 		}
1433*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
1434*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
1435*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1436*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1437*7836SJohn.Forte@Sun.COM 			break;
1438*7836SJohn.Forte@Sun.COM 		}
1439*7836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(value, tmpbuf,
1440*7836SJohn.Forte@Sun.COM 		    sizeof (tmpbuf)) == -1) {
1441*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get ustring failed - %s",
1442*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1443*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1444*7836SJohn.Forte@Sun.COM 			break;
1445*7836SJohn.Forte@Sun.COM 		}
1446*7836SJohn.Forte@Sun.COM 
1447*7836SJohn.Forte@Sun.COM 		if ((strlen(tmpbuf) == strlen(groupName)) &&
1448*7836SJohn.Forte@Sun.COM 		    bcmp(tmpbuf, groupName, strlen(tmpbuf)) == 0) {
1449*7836SJohn.Forte@Sun.COM 			if (addRemoveFlag == ADD) {
1450*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_EXISTS;
1451*7836SJohn.Forte@Sun.COM 			}
1452*7836SJohn.Forte@Sun.COM 			found = B_TRUE;
1453*7836SJohn.Forte@Sun.COM 			/*
1454*7836SJohn.Forte@Sun.COM 			 * buf1 contains the name for REMOVE
1455*7836SJohn.Forte@Sun.COM 			 */
1456*7836SJohn.Forte@Sun.COM 			break;
1457*7836SJohn.Forte@Sun.COM 		}
1458*7836SJohn.Forte@Sun.COM 	}
1459*7836SJohn.Forte@Sun.COM 
1460*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1461*7836SJohn.Forte@Sun.COM 		goto out;
1462*7836SJohn.Forte@Sun.COM 	}
1463*7836SJohn.Forte@Sun.COM 
1464*7836SJohn.Forte@Sun.COM 	scf_value_reset(value);
1465*7836SJohn.Forte@Sun.COM 
1466*7836SJohn.Forte@Sun.COM 	if (!found && addRemoveFlag == REMOVE) {
1467*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOT_FOUND;
1468*7836SJohn.Forte@Sun.COM 		goto out;
1469*7836SJohn.Forte@Sun.COM 	}
1470*7836SJohn.Forte@Sun.COM 
1471*7836SJohn.Forte@Sun.COM 	/*
1472*7836SJohn.Forte@Sun.COM 	 * If we're adding, we need to create a new property name for the
1473*7836SJohn.Forte@Sun.COM 	 * new group
1474*7836SJohn.Forte@Sun.COM 	 */
1475*7836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
1476*7836SJohn.Forte@Sun.COM 		for (groupIdx = 0; groupIdx < GROUP_MAX; groupIdx++) {
1477*7836SJohn.Forte@Sun.COM 			if (snprintf(buf1, sizeof (buf1), "%s-%lld",
1478*7836SJohn.Forte@Sun.COM 			    STMF_GROUP_PREFIX, groupIdx) > sizeof (buf1)) {
1479*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
1480*7836SJohn.Forte@Sun.COM 				    "buffer overflow on property name %s",
1481*7836SJohn.Forte@Sun.COM 				    buf1);
1482*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
1483*7836SJohn.Forte@Sun.COM 				break;
1484*7836SJohn.Forte@Sun.COM 			}
1485*7836SJohn.Forte@Sun.COM 			if (scf_pg_get_property(pg, buf1, prop) == -1) {
1486*7836SJohn.Forte@Sun.COM 				if (scf_error() != SCF_ERROR_NOT_FOUND) {
1487*7836SJohn.Forte@Sun.COM 					syslog(LOG_ERR, "get pg failed - %s",
1488*7836SJohn.Forte@Sun.COM 					    scf_strerror(scf_error()));
1489*7836SJohn.Forte@Sun.COM 					ret = STMF_PS_ERROR;
1490*7836SJohn.Forte@Sun.COM 				}
1491*7836SJohn.Forte@Sun.COM 				break;
1492*7836SJohn.Forte@Sun.COM 			}
1493*7836SJohn.Forte@Sun.COM 		}
1494*7836SJohn.Forte@Sun.COM 	}
1495*7836SJohn.Forte@Sun.COM 
1496*7836SJohn.Forte@Sun.COM 	/*
1497*7836SJohn.Forte@Sun.COM 	 * Now create the new member list property for the new group
1498*7836SJohn.Forte@Sun.COM 	 */
1499*7836SJohn.Forte@Sun.COM 	if (snprintf(buf2, sizeof (buf2), "%s-%s", buf1,
1500*7836SJohn.Forte@Sun.COM 	    STMF_MEMBER_LIST_SUFFIX) > sizeof (buf2)) {
1501*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
1502*7836SJohn.Forte@Sun.COM 		    buf1);
1503*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1504*7836SJohn.Forte@Sun.COM 		goto out;
1505*7836SJohn.Forte@Sun.COM 	}
1506*7836SJohn.Forte@Sun.COM 
1507*7836SJohn.Forte@Sun.COM 	/*
1508*7836SJohn.Forte@Sun.COM 	 * buf1 now contains the name of the property if it was found in the
1509*7836SJohn.Forte@Sun.COM 	 * list in the case of delete or the next available property name
1510*7836SJohn.Forte@Sun.COM 	 * in the case of create
1511*7836SJohn.Forte@Sun.COM 	 *
1512*7836SJohn.Forte@Sun.COM 	 * buf2 now contains the member list property name
1513*7836SJohn.Forte@Sun.COM 	 */
1514*7836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
1515*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
1516*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1517*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1518*7836SJohn.Forte@Sun.COM 		goto out;
1519*7836SJohn.Forte@Sun.COM 	}
1520*7836SJohn.Forte@Sun.COM 
1521*7836SJohn.Forte@Sun.COM 	if (addRemoveFlag == ADD) {
1522*7836SJohn.Forte@Sun.COM 		/*
1523*7836SJohn.Forte@Sun.COM 		 * Create the property 'group name'
1524*7836SJohn.Forte@Sun.COM 		 * This is the container for the group name
1525*7836SJohn.Forte@Sun.COM 		 */
1526*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry1, buf1,
1527*7836SJohn.Forte@Sun.COM 		    SCF_TYPE_USTRING) == -1) {
1528*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
1529*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1530*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1531*7836SJohn.Forte@Sun.COM 			goto out;
1532*7836SJohn.Forte@Sun.COM 		}
1533*7836SJohn.Forte@Sun.COM 		if (scf_value_set_ustring(value, groupName) == -1) {
1534*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set ustring failed - %s",
1535*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1536*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1537*7836SJohn.Forte@Sun.COM 			goto out;
1538*7836SJohn.Forte@Sun.COM 		}
1539*7836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry1, value) == -1) {
1540*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
1541*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1542*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1543*7836SJohn.Forte@Sun.COM 			goto out;
1544*7836SJohn.Forte@Sun.COM 		}
1545*7836SJohn.Forte@Sun.COM 		/*
1546*7836SJohn.Forte@Sun.COM 		 * Create the property 'group list'
1547*7836SJohn.Forte@Sun.COM 		 * This is the container for the group members
1548*7836SJohn.Forte@Sun.COM 		 */
1549*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry2, buf2,
1550*7836SJohn.Forte@Sun.COM 		    SCF_TYPE_USTRING) == -1) {
1551*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
1552*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1553*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1554*7836SJohn.Forte@Sun.COM 			goto out;
1555*7836SJohn.Forte@Sun.COM 		}
1556*7836SJohn.Forte@Sun.COM 	} else {
1557*7836SJohn.Forte@Sun.COM 		/*
1558*7836SJohn.Forte@Sun.COM 		 * Delete the property 'group name'
1559*7836SJohn.Forte@Sun.COM 		 */
1560*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, entry1, buf1)
1561*7836SJohn.Forte@Sun.COM 		    == -1) {
1562*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
1563*7836SJohn.Forte@Sun.COM 			    "transaction property delete failed - %s",
1564*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1565*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1566*7836SJohn.Forte@Sun.COM 			goto out;
1567*7836SJohn.Forte@Sun.COM 		}
1568*7836SJohn.Forte@Sun.COM 		/*
1569*7836SJohn.Forte@Sun.COM 		 * Delete the property 'group list'
1570*7836SJohn.Forte@Sun.COM 		 */
1571*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, entry2, buf2)
1572*7836SJohn.Forte@Sun.COM 		    == -1) {
1573*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
1574*7836SJohn.Forte@Sun.COM 			    "transaction property delete failed - %s",
1575*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1576*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1577*7836SJohn.Forte@Sun.COM 			goto out;
1578*7836SJohn.Forte@Sun.COM 		}
1579*7836SJohn.Forte@Sun.COM 	}
1580*7836SJohn.Forte@Sun.COM 
1581*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1582*7836SJohn.Forte@Sun.COM 		goto out;
1583*7836SJohn.Forte@Sun.COM 	}
1584*7836SJohn.Forte@Sun.COM 
1585*7836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
1586*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
1587*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1588*7836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
1589*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
1590*7836SJohn.Forte@Sun.COM 		} else {
1591*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1592*7836SJohn.Forte@Sun.COM 		}
1593*7836SJohn.Forte@Sun.COM 	}
1594*7836SJohn.Forte@Sun.COM 
1595*7836SJohn.Forte@Sun.COM out:
1596*7836SJohn.Forte@Sun.COM 	/*
1597*7836SJohn.Forte@Sun.COM 	 * Free resources
1598*7836SJohn.Forte@Sun.COM 	 */
1599*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
1600*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
1601*7836SJohn.Forte@Sun.COM 	}
1602*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
1603*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
1604*7836SJohn.Forte@Sun.COM 	}
1605*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
1606*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
1607*7836SJohn.Forte@Sun.COM 	}
1608*7836SJohn.Forte@Sun.COM 	if (tran != NULL) {
1609*7836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
1610*7836SJohn.Forte@Sun.COM 	}
1611*7836SJohn.Forte@Sun.COM 	if (entry1 != NULL) {
1612*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry1);
1613*7836SJohn.Forte@Sun.COM 	}
1614*7836SJohn.Forte@Sun.COM 	if (entry2 != NULL) {
1615*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry2);
1616*7836SJohn.Forte@Sun.COM 	}
1617*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
1618*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
1619*7836SJohn.Forte@Sun.COM 	}
1620*7836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
1621*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
1622*7836SJohn.Forte@Sun.COM 	}
1623*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
1624*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
1625*7836SJohn.Forte@Sun.COM 	}
1626*7836SJohn.Forte@Sun.COM 
1627*7836SJohn.Forte@Sun.COM 	return (ret);
1628*7836SJohn.Forte@Sun.COM }
1629*7836SJohn.Forte@Sun.COM 
1630*7836SJohn.Forte@Sun.COM /*
1631*7836SJohn.Forte@Sun.COM  * iPsGetGroupList
1632*7836SJohn.Forte@Sun.COM  *
1633*7836SJohn.Forte@Sun.COM  * pgName - Property group name
1634*7836SJohn.Forte@Sun.COM  * groupList - pointer to pointer to stmfGroupList structure. On success,
1635*7836SJohn.Forte@Sun.COM  * contains the list of groups
1636*7836SJohn.Forte@Sun.COM  *
1637*7836SJohn.Forte@Sun.COM  * returns:
1638*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
1639*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
1640*7836SJohn.Forte@Sun.COM  */
1641*7836SJohn.Forte@Sun.COM static int
1642*7836SJohn.Forte@Sun.COM iPsGetGroupList(char *pgName, stmfGroupList **groupList)
1643*7836SJohn.Forte@Sun.COM {
1644*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
1645*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
1646*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
1647*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
1648*7836SJohn.Forte@Sun.COM 	scf_iter_t	*propIter = NULL;
1649*7836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
1650*7836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
1651*7836SJohn.Forte@Sun.COM 	int memberCnt = 0;
1652*7836SJohn.Forte@Sun.COM 	int i = 0;
1653*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
1654*7836SJohn.Forte@Sun.COM 
1655*7836SJohn.Forte@Sun.COM 	assert(groupList != NULL);
1656*7836SJohn.Forte@Sun.COM 
1657*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
1658*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1659*7836SJohn.Forte@Sun.COM 		goto out;
1660*7836SJohn.Forte@Sun.COM 	}
1661*7836SJohn.Forte@Sun.COM 
1662*7836SJohn.Forte@Sun.COM 	/*
1663*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
1664*7836SJohn.Forte@Sun.COM 	 */
1665*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
1666*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
1667*7836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
1668*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
1669*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
1670*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1671*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1672*7836SJohn.Forte@Sun.COM 		goto out;
1673*7836SJohn.Forte@Sun.COM 	}
1674*7836SJohn.Forte@Sun.COM 
1675*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
1676*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
1677*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
1678*7836SJohn.Forte@Sun.COM 		} else {
1679*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
1680*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1681*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1682*7836SJohn.Forte@Sun.COM 		}
1683*7836SJohn.Forte@Sun.COM 		goto out;
1684*7836SJohn.Forte@Sun.COM 	}
1685*7836SJohn.Forte@Sun.COM 
1686*7836SJohn.Forte@Sun.COM 	/*
1687*7836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
1688*7836SJohn.Forte@Sun.COM 	 */
1689*7836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
1690*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
1691*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1692*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1693*7836SJohn.Forte@Sun.COM 		goto out;
1694*7836SJohn.Forte@Sun.COM 	}
1695*7836SJohn.Forte@Sun.COM 
1696*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
1697*7836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) {
1698*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
1699*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1700*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1701*7836SJohn.Forte@Sun.COM 			break;
1702*7836SJohn.Forte@Sun.COM 		}
1703*7836SJohn.Forte@Sun.COM 		/*
1704*7836SJohn.Forte@Sun.COM 		 * Skip over member list properties
1705*7836SJohn.Forte@Sun.COM 		 */
1706*7836SJohn.Forte@Sun.COM 		if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) {
1707*7836SJohn.Forte@Sun.COM 			continue;
1708*7836SJohn.Forte@Sun.COM 		}
1709*7836SJohn.Forte@Sun.COM 		memberCnt++;
1710*7836SJohn.Forte@Sun.COM 	}
1711*7836SJohn.Forte@Sun.COM 
1712*7836SJohn.Forte@Sun.COM 	/*
1713*7836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
1714*7836SJohn.Forte@Sun.COM 	 */
1715*7836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
1716*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
1717*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1718*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1719*7836SJohn.Forte@Sun.COM 		goto out;
1720*7836SJohn.Forte@Sun.COM 	}
1721*7836SJohn.Forte@Sun.COM 
1722*7836SJohn.Forte@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
1723*7836SJohn.Forte@Sun.COM 	    memberCnt * sizeof (stmfGroupName));
1724*7836SJohn.Forte@Sun.COM 
1725*7836SJohn.Forte@Sun.COM 	if (*groupList == NULL) {
1726*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
1727*7836SJohn.Forte@Sun.COM 		goto out;
1728*7836SJohn.Forte@Sun.COM 	}
1729*7836SJohn.Forte@Sun.COM 
1730*7836SJohn.Forte@Sun.COM 	/*
1731*7836SJohn.Forte@Sun.COM 	 * In order to get a list of groups, simply get all of the
1732*7836SJohn.Forte@Sun.COM 	 * properties that are not member list properties, i.e. the group
1733*7836SJohn.Forte@Sun.COM 	 * name properties.
1734*7836SJohn.Forte@Sun.COM 	 * It's possible for this list to grow beyond what was originally
1735*7836SJohn.Forte@Sun.COM 	 * read so just ensure we're not writing beyond our allocated buffer
1736*7836SJohn.Forte@Sun.COM 	 * by ensuring i < memberCnt
1737*7836SJohn.Forte@Sun.COM 	 */
1738*7836SJohn.Forte@Sun.COM 	while ((scf_iter_next_property(propIter, prop) == 1) &&
1739*7836SJohn.Forte@Sun.COM 	    (i < memberCnt)) {
1740*7836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, buf, sizeof (buf)) == -1) {
1741*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
1742*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1743*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1744*7836SJohn.Forte@Sun.COM 			break;
1745*7836SJohn.Forte@Sun.COM 		}
1746*7836SJohn.Forte@Sun.COM 		/*
1747*7836SJohn.Forte@Sun.COM 		 * Skip over member list properties
1748*7836SJohn.Forte@Sun.COM 		 */
1749*7836SJohn.Forte@Sun.COM 		if (strstr(buf, STMF_MEMBER_LIST_SUFFIX)) {
1750*7836SJohn.Forte@Sun.COM 			continue;
1751*7836SJohn.Forte@Sun.COM 		}
1752*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
1753*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
1754*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1755*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1756*7836SJohn.Forte@Sun.COM 			break;
1757*7836SJohn.Forte@Sun.COM 		}
1758*7836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) {
1759*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get ustring failed - %s",
1760*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1761*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1762*7836SJohn.Forte@Sun.COM 			break;
1763*7836SJohn.Forte@Sun.COM 		}
1764*7836SJohn.Forte@Sun.COM 		bcopy(buf, (*groupList)->name[i++], strlen(buf));
1765*7836SJohn.Forte@Sun.COM 		(*groupList)->cnt++;
1766*7836SJohn.Forte@Sun.COM 	}
1767*7836SJohn.Forte@Sun.COM 
1768*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1769*7836SJohn.Forte@Sun.COM 		free(*groupList);
1770*7836SJohn.Forte@Sun.COM 		goto out;
1771*7836SJohn.Forte@Sun.COM 	}
1772*7836SJohn.Forte@Sun.COM 
1773*7836SJohn.Forte@Sun.COM out:
1774*7836SJohn.Forte@Sun.COM 	/*
1775*7836SJohn.Forte@Sun.COM 	 * Free resources
1776*7836SJohn.Forte@Sun.COM 	 */
1777*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
1778*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
1779*7836SJohn.Forte@Sun.COM 	}
1780*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
1781*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
1782*7836SJohn.Forte@Sun.COM 	}
1783*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
1784*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
1785*7836SJohn.Forte@Sun.COM 	}
1786*7836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
1787*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
1788*7836SJohn.Forte@Sun.COM 	}
1789*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
1790*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
1791*7836SJohn.Forte@Sun.COM 	}
1792*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
1793*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
1794*7836SJohn.Forte@Sun.COM 	}
1795*7836SJohn.Forte@Sun.COM 
1796*7836SJohn.Forte@Sun.COM 	return (ret);
1797*7836SJohn.Forte@Sun.COM }
1798*7836SJohn.Forte@Sun.COM 
1799*7836SJohn.Forte@Sun.COM /*
1800*7836SJohn.Forte@Sun.COM  * iPsGetGroupMemberList
1801*7836SJohn.Forte@Sun.COM  *
1802*7836SJohn.Forte@Sun.COM  * pgName - Property group name
1803*7836SJohn.Forte@Sun.COM  * groupName - group name (host group or target group)
1804*7836SJohn.Forte@Sun.COM  * groupMemberList - pointer to pointer to stmfGroupProperties structure. On
1805*7836SJohn.Forte@Sun.COM  * success, contains the list of group members
1806*7836SJohn.Forte@Sun.COM  *
1807*7836SJohn.Forte@Sun.COM  * returns:
1808*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
1809*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
1810*7836SJohn.Forte@Sun.COM  */
1811*7836SJohn.Forte@Sun.COM static int
1812*7836SJohn.Forte@Sun.COM iPsGetGroupMemberList(char *pgName, char *groupName,
1813*7836SJohn.Forte@Sun.COM     stmfGroupProperties **groupMemberList)
1814*7836SJohn.Forte@Sun.COM {
1815*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
1816*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
1817*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
1818*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
1819*7836SJohn.Forte@Sun.COM 	scf_value_t	*valueLookup = NULL;
1820*7836SJohn.Forte@Sun.COM 	scf_iter_t	*valueIter = NULL;
1821*7836SJohn.Forte@Sun.COM 	int i = 0;
1822*7836SJohn.Forte@Sun.COM 	int memberCnt;
1823*7836SJohn.Forte@Sun.COM 	int len;
1824*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
1825*7836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
1826*7836SJohn.Forte@Sun.COM 
1827*7836SJohn.Forte@Sun.COM 	assert(pgName != NULL && groupName != NULL);
1828*7836SJohn.Forte@Sun.COM 
1829*7836SJohn.Forte@Sun.COM 	/*
1830*7836SJohn.Forte@Sun.COM 	 * init the service handle
1831*7836SJohn.Forte@Sun.COM 	 */
1832*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
1833*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1834*7836SJohn.Forte@Sun.COM 		goto out;
1835*7836SJohn.Forte@Sun.COM 	}
1836*7836SJohn.Forte@Sun.COM 
1837*7836SJohn.Forte@Sun.COM 	/*
1838*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
1839*7836SJohn.Forte@Sun.COM 	 */
1840*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
1841*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
1842*7836SJohn.Forte@Sun.COM 	    ((valueIter = scf_iter_create(handle)) == NULL) ||
1843*7836SJohn.Forte@Sun.COM 	    ((valueLookup = scf_value_create(handle)) == NULL)) {
1844*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
1845*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1846*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1847*7836SJohn.Forte@Sun.COM 		goto out;
1848*7836SJohn.Forte@Sun.COM 	}
1849*7836SJohn.Forte@Sun.COM 
1850*7836SJohn.Forte@Sun.COM 	/*
1851*7836SJohn.Forte@Sun.COM 	 * get the service property group handle
1852*7836SJohn.Forte@Sun.COM 	 */
1853*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
1854*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
1855*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
1856*7836SJohn.Forte@Sun.COM 		} else {
1857*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
1858*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1859*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1860*7836SJohn.Forte@Sun.COM 		}
1861*7836SJohn.Forte@Sun.COM 		goto out;
1862*7836SJohn.Forte@Sun.COM 	}
1863*7836SJohn.Forte@Sun.COM 
1864*7836SJohn.Forte@Sun.COM 	/*
1865*7836SJohn.Forte@Sun.COM 	 * Get the property handle
1866*7836SJohn.Forte@Sun.COM 	 * based on the target or host group name
1867*7836SJohn.Forte@Sun.COM 	 */
1868*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, groupName, prop) == -1) {
1869*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
1870*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1871*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1872*7836SJohn.Forte@Sun.COM 		goto out;
1873*7836SJohn.Forte@Sun.COM 	}
1874*7836SJohn.Forte@Sun.COM 
1875*7836SJohn.Forte@Sun.COM 	/*
1876*7836SJohn.Forte@Sun.COM 	 * valueIter is the iterator handle
1877*7836SJohn.Forte@Sun.COM 	 */
1878*7836SJohn.Forte@Sun.COM 	if (scf_iter_property_values(valueIter, prop) == -1) {
1879*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter value failed - %s",
1880*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1881*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1882*7836SJohn.Forte@Sun.COM 		goto out;
1883*7836SJohn.Forte@Sun.COM 	}
1884*7836SJohn.Forte@Sun.COM 
1885*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_value(valueIter, valueLookup) == 1) {
1886*7836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
1887*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
1888*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1889*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1890*7836SJohn.Forte@Sun.COM 			break;
1891*7836SJohn.Forte@Sun.COM 		}
1892*7836SJohn.Forte@Sun.COM 		i++;
1893*7836SJohn.Forte@Sun.COM 	}
1894*7836SJohn.Forte@Sun.COM 
1895*7836SJohn.Forte@Sun.COM 	/*
1896*7836SJohn.Forte@Sun.COM 	 * valueIter is the iterator handle
1897*7836SJohn.Forte@Sun.COM 	 */
1898*7836SJohn.Forte@Sun.COM 	if (scf_iter_property_values(valueIter, prop) == -1) {
1899*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter value failed - %s",
1900*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1901*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1902*7836SJohn.Forte@Sun.COM 		goto out;
1903*7836SJohn.Forte@Sun.COM 	}
1904*7836SJohn.Forte@Sun.COM 
1905*7836SJohn.Forte@Sun.COM 	memberCnt = i;
1906*7836SJohn.Forte@Sun.COM 
1907*7836SJohn.Forte@Sun.COM 	*groupMemberList = (stmfGroupProperties *)calloc(1,
1908*7836SJohn.Forte@Sun.COM 	    sizeof (stmfGroupProperties) + memberCnt * sizeof (stmfDevid));
1909*7836SJohn.Forte@Sun.COM 	if (*groupMemberList == NULL) {
1910*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
1911*7836SJohn.Forte@Sun.COM 		goto out;
1912*7836SJohn.Forte@Sun.COM 	}
1913*7836SJohn.Forte@Sun.COM 
1914*7836SJohn.Forte@Sun.COM 	i = 0;
1915*7836SJohn.Forte@Sun.COM 	while ((scf_iter_next_value(valueIter, valueLookup) == 1) &&
1916*7836SJohn.Forte@Sun.COM 	    (i < memberCnt)) {
1917*7836SJohn.Forte@Sun.COM 		if ((len = scf_value_get_ustring(valueLookup, buf, MAXNAMELEN))
1918*7836SJohn.Forte@Sun.COM 		    == -1) {
1919*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "iter value failed - %s",
1920*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
1921*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1922*7836SJohn.Forte@Sun.COM 			break;
1923*7836SJohn.Forte@Sun.COM 		}
1924*7836SJohn.Forte@Sun.COM 		if (len < sizeof (stmfDevid) - 1) {
1925*7836SJohn.Forte@Sun.COM 			(*groupMemberList)->name[i].identLength = len;
1926*7836SJohn.Forte@Sun.COM 			bcopy(buf,
1927*7836SJohn.Forte@Sun.COM 			    (*groupMemberList)->name[i++].ident, len);
1928*7836SJohn.Forte@Sun.COM 			(*groupMemberList)->cnt++;
1929*7836SJohn.Forte@Sun.COM 		} else {
1930*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
1931*7836SJohn.Forte@Sun.COM 			break;
1932*7836SJohn.Forte@Sun.COM 		}
1933*7836SJohn.Forte@Sun.COM 	}
1934*7836SJohn.Forte@Sun.COM 
1935*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
1936*7836SJohn.Forte@Sun.COM 		free(*groupMemberList);
1937*7836SJohn.Forte@Sun.COM 		goto out;
1938*7836SJohn.Forte@Sun.COM 	}
1939*7836SJohn.Forte@Sun.COM 
1940*7836SJohn.Forte@Sun.COM out:
1941*7836SJohn.Forte@Sun.COM 	/*
1942*7836SJohn.Forte@Sun.COM 	 * Free resources
1943*7836SJohn.Forte@Sun.COM 	 */
1944*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
1945*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
1946*7836SJohn.Forte@Sun.COM 	}
1947*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
1948*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
1949*7836SJohn.Forte@Sun.COM 	}
1950*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
1951*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
1952*7836SJohn.Forte@Sun.COM 	}
1953*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
1954*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
1955*7836SJohn.Forte@Sun.COM 	}
1956*7836SJohn.Forte@Sun.COM 	if (valueLookup != NULL) {
1957*7836SJohn.Forte@Sun.COM 		scf_value_destroy(valueLookup);
1958*7836SJohn.Forte@Sun.COM 	}
1959*7836SJohn.Forte@Sun.COM 	if (valueIter != NULL) {
1960*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(valueIter);
1961*7836SJohn.Forte@Sun.COM 	}
1962*7836SJohn.Forte@Sun.COM 
1963*7836SJohn.Forte@Sun.COM 	return (ret);
1964*7836SJohn.Forte@Sun.COM }
1965*7836SJohn.Forte@Sun.COM 
1966*7836SJohn.Forte@Sun.COM /*
1967*7836SJohn.Forte@Sun.COM  * Initialize scf stmf service access
1968*7836SJohn.Forte@Sun.COM  * handle - returned handle
1969*7836SJohn.Forte@Sun.COM  * service - returned service handle
1970*7836SJohn.Forte@Sun.COM  *
1971*7836SJohn.Forte@Sun.COM  * Both handle and service must be destroyed by the caller
1972*7836SJohn.Forte@Sun.COM  */
1973*7836SJohn.Forte@Sun.COM static int
1974*7836SJohn.Forte@Sun.COM iPsInit(scf_handle_t **handle, scf_service_t **service)
1975*7836SJohn.Forte@Sun.COM {
1976*7836SJohn.Forte@Sun.COM 	scf_scope_t	*scope = NULL;
1977*7836SJohn.Forte@Sun.COM 	uint64_t version;
1978*7836SJohn.Forte@Sun.COM 	int ret;
1979*7836SJohn.Forte@Sun.COM 
1980*7836SJohn.Forte@Sun.COM 	assert(handle != NULL && service != NULL);
1981*7836SJohn.Forte@Sun.COM 
1982*7836SJohn.Forte@Sun.COM 	if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
1983*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_handle_create failed - %s",
1984*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1985*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1986*7836SJohn.Forte@Sun.COM 		goto err;
1987*7836SJohn.Forte@Sun.COM 	}
1988*7836SJohn.Forte@Sun.COM 
1989*7836SJohn.Forte@Sun.COM 	if (scf_handle_bind(*handle) == -1) {
1990*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_handle_bind failed - %s",
1991*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1992*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
1993*7836SJohn.Forte@Sun.COM 		goto err;
1994*7836SJohn.Forte@Sun.COM 	}
1995*7836SJohn.Forte@Sun.COM 
1996*7836SJohn.Forte@Sun.COM 	if ((*service = scf_service_create(*handle)) == NULL) {
1997*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_service_create failed - %s",
1998*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
1999*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2000*7836SJohn.Forte@Sun.COM 		goto err;
2001*7836SJohn.Forte@Sun.COM 	}
2002*7836SJohn.Forte@Sun.COM 
2003*7836SJohn.Forte@Sun.COM 	if ((scope = scf_scope_create(*handle)) == NULL) {
2004*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_scope_create failed - %s",
2005*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2006*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2007*7836SJohn.Forte@Sun.COM 		goto err;
2008*7836SJohn.Forte@Sun.COM 	}
2009*7836SJohn.Forte@Sun.COM 
2010*7836SJohn.Forte@Sun.COM 	if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
2011*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
2012*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2013*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2014*7836SJohn.Forte@Sun.COM 		goto err;
2015*7836SJohn.Forte@Sun.COM 	}
2016*7836SJohn.Forte@Sun.COM 
2017*7836SJohn.Forte@Sun.COM 	if (scf_scope_get_service(scope, STMF_SERVICE, *service) == -1) {
2018*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf_scope_get_service failed - %s",
2019*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2020*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_SERVICE_NOT_FOUND;
2021*7836SJohn.Forte@Sun.COM 		goto err;
2022*7836SJohn.Forte@Sun.COM 	}
2023*7836SJohn.Forte@Sun.COM 
2024*7836SJohn.Forte@Sun.COM 
2025*7836SJohn.Forte@Sun.COM 	/*
2026*7836SJohn.Forte@Sun.COM 	 * Get and check the version number
2027*7836SJohn.Forte@Sun.COM 	 */
2028*7836SJohn.Forte@Sun.COM 	ret = iPsGetServiceVersion(&version, *handle, *service);
2029*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2030*7836SJohn.Forte@Sun.COM 		goto err;
2031*7836SJohn.Forte@Sun.COM 	}
2032*7836SJohn.Forte@Sun.COM 
2033*7836SJohn.Forte@Sun.COM 	if (version != STMF_SMF_VERSION) {
2034*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_VERSION_MISMATCH;
2035*7836SJohn.Forte@Sun.COM 		goto err;
2036*7836SJohn.Forte@Sun.COM 	}
2037*7836SJohn.Forte@Sun.COM 
2038*7836SJohn.Forte@Sun.COM 	/* we only need destroy the scope here */
2039*7836SJohn.Forte@Sun.COM 	scf_scope_destroy(scope);
2040*7836SJohn.Forte@Sun.COM 
2041*7836SJohn.Forte@Sun.COM 	return (STMF_PS_SUCCESS);
2042*7836SJohn.Forte@Sun.COM 
2043*7836SJohn.Forte@Sun.COM err:
2044*7836SJohn.Forte@Sun.COM 	if (*handle != NULL) {
2045*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(*handle);
2046*7836SJohn.Forte@Sun.COM 	}
2047*7836SJohn.Forte@Sun.COM 	if (*service != NULL) {
2048*7836SJohn.Forte@Sun.COM 		scf_service_destroy(*service);
2049*7836SJohn.Forte@Sun.COM 		*service = NULL;
2050*7836SJohn.Forte@Sun.COM 	}
2051*7836SJohn.Forte@Sun.COM 	if (scope != NULL) {
2052*7836SJohn.Forte@Sun.COM 		scf_scope_destroy(scope);
2053*7836SJohn.Forte@Sun.COM 	}
2054*7836SJohn.Forte@Sun.COM 	return (ret);
2055*7836SJohn.Forte@Sun.COM }
2056*7836SJohn.Forte@Sun.COM 
2057*7836SJohn.Forte@Sun.COM /*
2058*7836SJohn.Forte@Sun.COM  * called by iPsInit only
2059*7836SJohn.Forte@Sun.COM  * iPsGetServiceVersion
2060*7836SJohn.Forte@Sun.COM  */
2061*7836SJohn.Forte@Sun.COM static int
2062*7836SJohn.Forte@Sun.COM iPsGetServiceVersion(uint64_t *version, scf_handle_t *handle,
2063*7836SJohn.Forte@Sun.COM scf_service_t *svc)
2064*7836SJohn.Forte@Sun.COM {
2065*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
2066*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
2067*7836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
2068*7836SJohn.Forte@Sun.COM 	scf_transaction_t *tran = NULL;
2069*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry = NULL;
2070*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
2071*7836SJohn.Forte@Sun.COM 	int commitRet;
2072*7836SJohn.Forte@Sun.COM 
2073*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
2074*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
2075*7836SJohn.Forte@Sun.COM 	    ((entry = scf_entry_create(handle)) == NULL) ||
2076*7836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL) ||
2077*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
2078*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
2079*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2080*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2081*7836SJohn.Forte@Sun.COM 		goto out;
2082*7836SJohn.Forte@Sun.COM 	}
2083*7836SJohn.Forte@Sun.COM 
2084*7836SJohn.Forte@Sun.COM 	*version = STMF_SMF_VERSION;
2085*7836SJohn.Forte@Sun.COM 
2086*7836SJohn.Forte@Sun.COM 	/*
2087*7836SJohn.Forte@Sun.COM 	 * get stmf data property group
2088*7836SJohn.Forte@Sun.COM 	 */
2089*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, STMF_DATA_GROUP, pg) == -1) {
2090*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
2091*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
2092*7836SJohn.Forte@Sun.COM 		} else {
2093*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
2094*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2095*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2096*7836SJohn.Forte@Sun.COM 			goto out;
2097*7836SJohn.Forte@Sun.COM 		}
2098*7836SJohn.Forte@Sun.COM 	}
2099*7836SJohn.Forte@Sun.COM 
2100*7836SJohn.Forte@Sun.COM 	/* create the group */
2101*7836SJohn.Forte@Sun.COM 	if (ret == STMF_PS_ERROR_NOT_FOUND) {
2102*7836SJohn.Forte@Sun.COM 		/*
2103*7836SJohn.Forte@Sun.COM 		 * create the property group.
2104*7836SJohn.Forte@Sun.COM 		 */
2105*7836SJohn.Forte@Sun.COM 		if (scf_service_add_pg(svc, STMF_DATA_GROUP,
2106*7836SJohn.Forte@Sun.COM 		    SCF_GROUP_APPLICATION, 0, pg) == -1) {
2107*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add pg failed - %s",
2108*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2109*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2110*7836SJohn.Forte@Sun.COM 			goto out;
2111*7836SJohn.Forte@Sun.COM 		}
2112*7836SJohn.Forte@Sun.COM 		/* reset return value */
2113*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_SUCCESS;
2114*7836SJohn.Forte@Sun.COM 	}
2115*7836SJohn.Forte@Sun.COM 
2116*7836SJohn.Forte@Sun.COM 	/* find version property */
2117*7836SJohn.Forte@Sun.COM 	/*
2118*7836SJohn.Forte@Sun.COM 	 * Get the version property
2119*7836SJohn.Forte@Sun.COM 	 */
2120*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VERSION_NAME, prop) == -1) {
2121*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
2122*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
2123*7836SJohn.Forte@Sun.COM 		} else {
2124*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
2125*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2126*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2127*7836SJohn.Forte@Sun.COM 			goto out;
2128*7836SJohn.Forte@Sun.COM 		}
2129*7836SJohn.Forte@Sun.COM 	}
2130*7836SJohn.Forte@Sun.COM 
2131*7836SJohn.Forte@Sun.COM 	/* no version property found */
2132*7836SJohn.Forte@Sun.COM 	if (ret == STMF_PS_ERROR_NOT_FOUND) {
2133*7836SJohn.Forte@Sun.COM 		/*
2134*7836SJohn.Forte@Sun.COM 		 * If we have no version property, go ahead
2135*7836SJohn.Forte@Sun.COM 		 * and create it. We're obviously making an assumption
2136*7836SJohn.Forte@Sun.COM 		 * here that someone did not delete the existing property
2137*7836SJohn.Forte@Sun.COM 		 * and that this is the initial set and the initial call
2138*7836SJohn.Forte@Sun.COM 		 * to iPsInit.
2139*7836SJohn.Forte@Sun.COM 		 * If they did delete it, this will simply plant this
2140*7836SJohn.Forte@Sun.COM 		 * library's version on this service. That may or may not be
2141*7836SJohn.Forte@Sun.COM 		 * correct and we have no way of determining that.
2142*7836SJohn.Forte@Sun.COM 		 */
2143*7836SJohn.Forte@Sun.COM 		/*
2144*7836SJohn.Forte@Sun.COM 		 * Begin the transaction
2145*7836SJohn.Forte@Sun.COM 		 */
2146*7836SJohn.Forte@Sun.COM 		if (scf_transaction_start(tran, pg) == -1) {
2147*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "start transaction failed - %s",
2148*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2149*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2150*7836SJohn.Forte@Sun.COM 			goto out;
2151*7836SJohn.Forte@Sun.COM 		}
2152*7836SJohn.Forte@Sun.COM 
2153*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry,
2154*7836SJohn.Forte@Sun.COM 		    STMF_VERSION_NAME, SCF_TYPE_COUNT) == -1) {
2155*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
2156*7836SJohn.Forte@Sun.COM 			    "transaction property new failed - %s",
2157*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2158*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2159*7836SJohn.Forte@Sun.COM 			goto out;
2160*7836SJohn.Forte@Sun.COM 		}
2161*7836SJohn.Forte@Sun.COM 
2162*7836SJohn.Forte@Sun.COM 		/*
2163*7836SJohn.Forte@Sun.COM 		 * set the version number
2164*7836SJohn.Forte@Sun.COM 		 */
2165*7836SJohn.Forte@Sun.COM 		scf_value_set_count(value, *version);
2166*7836SJohn.Forte@Sun.COM 
2167*7836SJohn.Forte@Sun.COM 		/*
2168*7836SJohn.Forte@Sun.COM 		 * add the value to the transaction
2169*7836SJohn.Forte@Sun.COM 		 */
2170*7836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry, value) == -1) {
2171*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
2172*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2173*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2174*7836SJohn.Forte@Sun.COM 			goto out;
2175*7836SJohn.Forte@Sun.COM 		}
2176*7836SJohn.Forte@Sun.COM 		if ((commitRet = scf_transaction_commit(tran)) != 1) {
2177*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction commit failed - %s",
2178*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2179*7836SJohn.Forte@Sun.COM 			if (commitRet == 0) {
2180*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR_BUSY;
2181*7836SJohn.Forte@Sun.COM 			} else {
2182*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
2183*7836SJohn.Forte@Sun.COM 			}
2184*7836SJohn.Forte@Sun.COM 			goto out;
2185*7836SJohn.Forte@Sun.COM 		}
2186*7836SJohn.Forte@Sun.COM 		/* reset return value */
2187*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_SUCCESS;
2188*7836SJohn.Forte@Sun.COM 	} else {
2189*7836SJohn.Forte@Sun.COM 		/* get the version property */
2190*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_VERSION_NAME, prop) == -1) {
2191*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
2192*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2193*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2194*7836SJohn.Forte@Sun.COM 			goto out;
2195*7836SJohn.Forte@Sun.COM 		}
2196*7836SJohn.Forte@Sun.COM 
2197*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
2198*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
2199*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2200*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2201*7836SJohn.Forte@Sun.COM 			goto out;
2202*7836SJohn.Forte@Sun.COM 		}
2203*7836SJohn.Forte@Sun.COM 
2204*7836SJohn.Forte@Sun.COM 		/*
2205*7836SJohn.Forte@Sun.COM 		 * Get the actual value of the view entry count property
2206*7836SJohn.Forte@Sun.COM 		 */
2207*7836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value, version) == -1) {
2208*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get count value failed - %s",
2209*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2210*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2211*7836SJohn.Forte@Sun.COM 			goto out;
2212*7836SJohn.Forte@Sun.COM 		}
2213*7836SJohn.Forte@Sun.COM 	}
2214*7836SJohn.Forte@Sun.COM 
2215*7836SJohn.Forte@Sun.COM out:
2216*7836SJohn.Forte@Sun.COM 	/*
2217*7836SJohn.Forte@Sun.COM 	 * Free resources.
2218*7836SJohn.Forte@Sun.COM 	 * handle and svc should not be free'd here. They're
2219*7836SJohn.Forte@Sun.COM 	 * free'd elsewhere
2220*7836SJohn.Forte@Sun.COM 	 */
2221*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
2222*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
2223*7836SJohn.Forte@Sun.COM 	}
2224*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
2225*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
2226*7836SJohn.Forte@Sun.COM 	}
2227*7836SJohn.Forte@Sun.COM 	if (entry != NULL) {
2228*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry);
2229*7836SJohn.Forte@Sun.COM 	}
2230*7836SJohn.Forte@Sun.COM 	if (tran != NULL) {
2231*7836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
2232*7836SJohn.Forte@Sun.COM 	}
2233*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
2234*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
2235*7836SJohn.Forte@Sun.COM 	}
2236*7836SJohn.Forte@Sun.COM 	return (ret);
2237*7836SJohn.Forte@Sun.COM }
2238*7836SJohn.Forte@Sun.COM 
2239*7836SJohn.Forte@Sun.COM 
2240*7836SJohn.Forte@Sun.COM 
2241*7836SJohn.Forte@Sun.COM /*
2242*7836SJohn.Forte@Sun.COM  * iPsGetActualGroupName
2243*7836SJohn.Forte@Sun.COM  *
2244*7836SJohn.Forte@Sun.COM  * pgName - Property group name
2245*7836SJohn.Forte@Sun.COM  * groupName - requested group name
2246*7836SJohn.Forte@Sun.COM  * actualName - actual group name to reference (len must be >= MAXNAMELEN)
2247*7836SJohn.Forte@Sun.COM  *
2248*7836SJohn.Forte@Sun.COM  * returns:
2249*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2250*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2251*7836SJohn.Forte@Sun.COM  */
2252*7836SJohn.Forte@Sun.COM static int
2253*7836SJohn.Forte@Sun.COM iPsGetActualGroupName(char *pgName, char *groupName, char *actualName)
2254*7836SJohn.Forte@Sun.COM {
2255*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
2256*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
2257*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
2258*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
2259*7836SJohn.Forte@Sun.COM 	scf_iter_t	*propIter = NULL;
2260*7836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
2261*7836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
2262*7836SJohn.Forte@Sun.COM 	int ret;
2263*7836SJohn.Forte@Sun.COM 
2264*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
2265*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2266*7836SJohn.Forte@Sun.COM 		goto out;
2267*7836SJohn.Forte@Sun.COM 	}
2268*7836SJohn.Forte@Sun.COM 
2269*7836SJohn.Forte@Sun.COM 	/*
2270*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
2271*7836SJohn.Forte@Sun.COM 	 */
2272*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
2273*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
2274*7836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
2275*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
2276*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
2277*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2278*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2279*7836SJohn.Forte@Sun.COM 		goto out;
2280*7836SJohn.Forte@Sun.COM 	}
2281*7836SJohn.Forte@Sun.COM 
2282*7836SJohn.Forte@Sun.COM 	/*
2283*7836SJohn.Forte@Sun.COM 	 * get group list property group
2284*7836SJohn.Forte@Sun.COM 	 */
2285*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
2286*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
2287*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
2288*7836SJohn.Forte@Sun.COM 		} else {
2289*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
2290*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2291*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2292*7836SJohn.Forte@Sun.COM 		}
2293*7836SJohn.Forte@Sun.COM 		goto out;
2294*7836SJohn.Forte@Sun.COM 	}
2295*7836SJohn.Forte@Sun.COM 
2296*7836SJohn.Forte@Sun.COM 	/*
2297*7836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
2298*7836SJohn.Forte@Sun.COM 	 */
2299*7836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
2300*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
2301*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2302*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2303*7836SJohn.Forte@Sun.COM 		goto out;
2304*7836SJohn.Forte@Sun.COM 	}
2305*7836SJohn.Forte@Sun.COM 
2306*7836SJohn.Forte@Sun.COM 	/*
2307*7836SJohn.Forte@Sun.COM 	 * Iterate through group properties searching for the requested
2308*7836SJohn.Forte@Sun.COM 	 * group name. When we find it, we need to get the property name
2309*7836SJohn.Forte@Sun.COM 	 * since it refers to the actual group name.
2310*7836SJohn.Forte@Sun.COM 	 */
2311*7836SJohn.Forte@Sun.COM 
2312*7836SJohn.Forte@Sun.COM 	/* initialize to not found */
2313*7836SJohn.Forte@Sun.COM 	ret = STMF_PS_ERROR_GROUP_NOT_FOUND;
2314*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
2315*7836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, actualName, MAXNAMELEN) == -1) {
2316*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
2317*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2318*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2319*7836SJohn.Forte@Sun.COM 			break;
2320*7836SJohn.Forte@Sun.COM 		}
2321*7836SJohn.Forte@Sun.COM 		/*
2322*7836SJohn.Forte@Sun.COM 		 * Skip over non-member list properties
2323*7836SJohn.Forte@Sun.COM 		 */
2324*7836SJohn.Forte@Sun.COM 		if (strstr(actualName, STMF_MEMBER_LIST_SUFFIX)) {
2325*7836SJohn.Forte@Sun.COM 			continue;
2326*7836SJohn.Forte@Sun.COM 		}
2327*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
2328*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
2329*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2330*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2331*7836SJohn.Forte@Sun.COM 			break;
2332*7836SJohn.Forte@Sun.COM 		}
2333*7836SJohn.Forte@Sun.COM 		if (scf_value_get_ustring(value, buf, sizeof (buf)) == -1) {
2334*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get ustring failed - %s",
2335*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2336*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2337*7836SJohn.Forte@Sun.COM 			break;
2338*7836SJohn.Forte@Sun.COM 		}
2339*7836SJohn.Forte@Sun.COM 
2340*7836SJohn.Forte@Sun.COM 		/*
2341*7836SJohn.Forte@Sun.COM 		 * When we find a match, set success and break
2342*7836SJohn.Forte@Sun.COM 		 */
2343*7836SJohn.Forte@Sun.COM 		if ((strlen(buf) == strlen(groupName)) &&
2344*7836SJohn.Forte@Sun.COM 		    bcmp(buf, groupName, strlen(buf)) == 0) {
2345*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_SUCCESS;
2346*7836SJohn.Forte@Sun.COM 			break;
2347*7836SJohn.Forte@Sun.COM 		}
2348*7836SJohn.Forte@Sun.COM 	}
2349*7836SJohn.Forte@Sun.COM 
2350*7836SJohn.Forte@Sun.COM 	/*
2351*7836SJohn.Forte@Sun.COM 	 * if we didn't find it, ret is set to STMF_PS_ERROR_GROUP_NOT_FOUND
2352*7836SJohn.Forte@Sun.COM 	 */
2353*7836SJohn.Forte@Sun.COM 
2354*7836SJohn.Forte@Sun.COM out:
2355*7836SJohn.Forte@Sun.COM 	/*
2356*7836SJohn.Forte@Sun.COM 	 * Free resources
2357*7836SJohn.Forte@Sun.COM 	 */
2358*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
2359*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
2360*7836SJohn.Forte@Sun.COM 	}
2361*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
2362*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
2363*7836SJohn.Forte@Sun.COM 	}
2364*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
2365*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
2366*7836SJohn.Forte@Sun.COM 	}
2367*7836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
2368*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
2369*7836SJohn.Forte@Sun.COM 	}
2370*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
2371*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
2372*7836SJohn.Forte@Sun.COM 	}
2373*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
2374*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
2375*7836SJohn.Forte@Sun.COM 	}
2376*7836SJohn.Forte@Sun.COM 
2377*7836SJohn.Forte@Sun.COM 	return (ret);
2378*7836SJohn.Forte@Sun.COM }
2379*7836SJohn.Forte@Sun.COM 
2380*7836SJohn.Forte@Sun.COM /*
2381*7836SJohn.Forte@Sun.COM  * psAddHostGroupMember
2382*7836SJohn.Forte@Sun.COM  *
2383*7836SJohn.Forte@Sun.COM  * Add a host group member to a host group,
2384*7836SJohn.Forte@Sun.COM  *
2385*7836SJohn.Forte@Sun.COM  * Input: groupName - name of group to which the member is added
2386*7836SJohn.Forte@Sun.COM  *        memberName - name of group member to add
2387*7836SJohn.Forte@Sun.COM  */
2388*7836SJohn.Forte@Sun.COM int
2389*7836SJohn.Forte@Sun.COM psAddHostGroupMember(char *groupName, char *memberName)
2390*7836SJohn.Forte@Sun.COM {
2391*7836SJohn.Forte@Sun.COM 	int ret;
2392*7836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
2393*7836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
2394*7836SJohn.Forte@Sun.COM 
2395*7836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName,
2396*7836SJohn.Forte@Sun.COM 	    groupPropName);
2397*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2398*7836SJohn.Forte@Sun.COM 		return (ret);
2399*7836SJohn.Forte@Sun.COM 	}
2400*7836SJohn.Forte@Sun.COM 
2401*7836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
2402*7836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
2403*7836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
2404*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
2405*7836SJohn.Forte@Sun.COM 		    groupPropName);
2406*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
2407*7836SJohn.Forte@Sun.COM 	}
2408*7836SJohn.Forte@Sun.COM 
2409*7836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS, groupPropListName,
2410*7836SJohn.Forte@Sun.COM 	    memberName, ADD));
2411*7836SJohn.Forte@Sun.COM }
2412*7836SJohn.Forte@Sun.COM 
2413*7836SJohn.Forte@Sun.COM /*
2414*7836SJohn.Forte@Sun.COM  * psAddTargetGroupMember
2415*7836SJohn.Forte@Sun.COM  *
2416*7836SJohn.Forte@Sun.COM  * Add a target port group member to a target group
2417*7836SJohn.Forte@Sun.COM  *
2418*7836SJohn.Forte@Sun.COM  * Input: groupName - name of group to which the member is added
2419*7836SJohn.Forte@Sun.COM  *        memberName - name of group member to add. Must be nul terminated.
2420*7836SJohn.Forte@Sun.COM  */
2421*7836SJohn.Forte@Sun.COM int
2422*7836SJohn.Forte@Sun.COM psAddTargetGroupMember(char *groupName, char *memberName)
2423*7836SJohn.Forte@Sun.COM {
2424*7836SJohn.Forte@Sun.COM 	int ret;
2425*7836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
2426*7836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
2427*7836SJohn.Forte@Sun.COM 
2428*7836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName,
2429*7836SJohn.Forte@Sun.COM 	    groupPropName);
2430*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2431*7836SJohn.Forte@Sun.COM 		return (ret);
2432*7836SJohn.Forte@Sun.COM 	}
2433*7836SJohn.Forte@Sun.COM 
2434*7836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
2435*7836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
2436*7836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
2437*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
2438*7836SJohn.Forte@Sun.COM 		    groupPropName);
2439*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
2440*7836SJohn.Forte@Sun.COM 	}
2441*7836SJohn.Forte@Sun.COM 
2442*7836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS, groupPropListName,
2443*7836SJohn.Forte@Sun.COM 	    memberName, ADD));
2444*7836SJohn.Forte@Sun.COM }
2445*7836SJohn.Forte@Sun.COM 
2446*7836SJohn.Forte@Sun.COM 
2447*7836SJohn.Forte@Sun.COM /*
2448*7836SJohn.Forte@Sun.COM  * psAddViewEntry
2449*7836SJohn.Forte@Sun.COM  *
2450*7836SJohn.Forte@Sun.COM  * luGuid - logical unit identifier
2451*7836SJohn.Forte@Sun.COM  * viewEntry - pointer to viewEntry allocated by the caller that contains
2452*7836SJohn.Forte@Sun.COM  *             the values to set for this view entry
2453*7836SJohn.Forte@Sun.COM  *
2454*7836SJohn.Forte@Sun.COM  * returns:
2455*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2456*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2457*7836SJohn.Forte@Sun.COM  */
2458*7836SJohn.Forte@Sun.COM int
2459*7836SJohn.Forte@Sun.COM psAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
2460*7836SJohn.Forte@Sun.COM {
2461*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
2462*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
2463*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
2464*7836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
2465*7836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
2466*7836SJohn.Forte@Sun.COM 	char scfLuPgName[LOGICAL_UNIT_PG_SIZE];
2467*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
2468*7836SJohn.Forte@Sun.COM 	sigset_t sigmaskRestore;
2469*7836SJohn.Forte@Sun.COM 
2470*7836SJohn.Forte@Sun.COM 	/* grab the signal hold lock */
2471*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&sigSetLock);
2472*7836SJohn.Forte@Sun.COM 
2473*7836SJohn.Forte@Sun.COM 	/*
2474*7836SJohn.Forte@Sun.COM 	 * hold signals until we're done
2475*7836SJohn.Forte@Sun.COM 	 */
2476*7836SJohn.Forte@Sun.COM 	if (holdSignal(&sigmaskRestore) != 0) {
2477*7836SJohn.Forte@Sun.COM 		(void) pthread_mutex_unlock(&sigSetLock);
2478*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
2479*7836SJohn.Forte@Sun.COM 	}
2480*7836SJohn.Forte@Sun.COM 
2481*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
2482*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2483*7836SJohn.Forte@Sun.COM 		goto out;
2484*7836SJohn.Forte@Sun.COM 	}
2485*7836SJohn.Forte@Sun.COM 
2486*7836SJohn.Forte@Sun.COM 	pg = scf_pg_create(handle);
2487*7836SJohn.Forte@Sun.COM 	if (pg == NULL) {
2488*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf pg alloc failed - %s",
2489*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2490*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2491*7836SJohn.Forte@Sun.COM 		goto out;
2492*7836SJohn.Forte@Sun.COM 	}
2493*7836SJohn.Forte@Sun.COM 
2494*7836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
2495*7836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
2496*7836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
2497*7836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
2498*7836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
2499*7836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
2500*7836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
2501*7836SJohn.Forte@Sun.COM 
2502*7836SJohn.Forte@Sun.COM 	(void) snprintf(scfLuPgName, sizeof (scfLuPgName), "%s-%s",
2503*7836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
2504*7836SJohn.Forte@Sun.COM 
2505*7836SJohn.Forte@Sun.COM 	bzero(viewEntryPgName, sizeof (viewEntryPgName));
2506*7836SJohn.Forte@Sun.COM 	/*
2507*7836SJohn.Forte@Sun.COM 	 * Format of view entry property group name:
2508*7836SJohn.Forte@Sun.COM 	 *	VE-<view_entry_name>-<lu_name>
2509*7836SJohn.Forte@Sun.COM 	 */
2510*7836SJohn.Forte@Sun.COM 	(void) snprintf(viewEntryPgName, sizeof (viewEntryPgName),
2511*7836SJohn.Forte@Sun.COM 	    "%s-%d-%s", STMF_VE_PREFIX, viewEntry->veIndex, guidAsciiBuf);
2512*7836SJohn.Forte@Sun.COM 
2513*7836SJohn.Forte@Sun.COM 	ret = iPsAddViewEntry(scfLuPgName, viewEntryPgName, viewEntry);
2514*7836SJohn.Forte@Sun.COM 
2515*7836SJohn.Forte@Sun.COM out:
2516*7836SJohn.Forte@Sun.COM 	/*
2517*7836SJohn.Forte@Sun.COM 	 * Okay, we're done. Release the signals
2518*7836SJohn.Forte@Sun.COM 	 */
2519*7836SJohn.Forte@Sun.COM 	if (releaseSignal(&sigmaskRestore) != 0) {
2520*7836SJohn.Forte@Sun.COM 		/*
2521*7836SJohn.Forte@Sun.COM 		 * Don't set this as an STMF_PS_ERROR_*. We succeeded
2522*7836SJohn.Forte@Sun.COM 		 * the requested operation. But we do need to log it.
2523*7836SJohn.Forte@Sun.COM 		 */
2524*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "Unable to release one or more signals - %s",
2525*7836SJohn.Forte@Sun.COM 		    strerror(errno));
2526*7836SJohn.Forte@Sun.COM 	}
2527*7836SJohn.Forte@Sun.COM 
2528*7836SJohn.Forte@Sun.COM 	/*
2529*7836SJohn.Forte@Sun.COM 	 * Free resources
2530*7836SJohn.Forte@Sun.COM 	 */
2531*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
2532*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
2533*7836SJohn.Forte@Sun.COM 	}
2534*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
2535*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
2536*7836SJohn.Forte@Sun.COM 	}
2537*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
2538*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
2539*7836SJohn.Forte@Sun.COM 	}
2540*7836SJohn.Forte@Sun.COM 
2541*7836SJohn.Forte@Sun.COM 	/* release the signal hold lock */
2542*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&sigSetLock);
2543*7836SJohn.Forte@Sun.COM 
2544*7836SJohn.Forte@Sun.COM 	return (ret);
2545*7836SJohn.Forte@Sun.COM }
2546*7836SJohn.Forte@Sun.COM 
2547*7836SJohn.Forte@Sun.COM /*
2548*7836SJohn.Forte@Sun.COM  * psCheckService
2549*7836SJohn.Forte@Sun.COM  *
2550*7836SJohn.Forte@Sun.COM  * Purpose: Checks whether service exists
2551*7836SJohn.Forte@Sun.COM  *
2552*7836SJohn.Forte@Sun.COM  */
2553*7836SJohn.Forte@Sun.COM int
2554*7836SJohn.Forte@Sun.COM psCheckService()
2555*7836SJohn.Forte@Sun.COM {
2556*7836SJohn.Forte@Sun.COM 	int ret;
2557*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
2558*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
2559*7836SJohn.Forte@Sun.COM 
2560*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
2561*7836SJohn.Forte@Sun.COM 
2562*7836SJohn.Forte@Sun.COM 	/*
2563*7836SJohn.Forte@Sun.COM 	 * Free resources
2564*7836SJohn.Forte@Sun.COM 	 */
2565*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
2566*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
2567*7836SJohn.Forte@Sun.COM 	}
2568*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
2569*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
2570*7836SJohn.Forte@Sun.COM 	}
2571*7836SJohn.Forte@Sun.COM 
2572*7836SJohn.Forte@Sun.COM 	return (ret);
2573*7836SJohn.Forte@Sun.COM }
2574*7836SJohn.Forte@Sun.COM 
2575*7836SJohn.Forte@Sun.COM /*
2576*7836SJohn.Forte@Sun.COM  * psCreateHostGroup
2577*7836SJohn.Forte@Sun.COM  *
2578*7836SJohn.Forte@Sun.COM  * groupName - name of group to create
2579*7836SJohn.Forte@Sun.COM  *
2580*7836SJohn.Forte@Sun.COM  * returns:
2581*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2582*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2583*7836SJohn.Forte@Sun.COM  */
2584*7836SJohn.Forte@Sun.COM int
2585*7836SJohn.Forte@Sun.COM psCreateHostGroup(char *groupName)
2586*7836SJohn.Forte@Sun.COM {
2587*7836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_HOST_GROUPS, groupName, ADD));
2588*7836SJohn.Forte@Sun.COM }
2589*7836SJohn.Forte@Sun.COM 
2590*7836SJohn.Forte@Sun.COM /*
2591*7836SJohn.Forte@Sun.COM  * psCreateTargetGroup
2592*7836SJohn.Forte@Sun.COM  *
2593*7836SJohn.Forte@Sun.COM  * groupName - name of group to create
2594*7836SJohn.Forte@Sun.COM  *
2595*7836SJohn.Forte@Sun.COM  * returns:
2596*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2597*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2598*7836SJohn.Forte@Sun.COM  */
2599*7836SJohn.Forte@Sun.COM int
2600*7836SJohn.Forte@Sun.COM psCreateTargetGroup(char *groupName)
2601*7836SJohn.Forte@Sun.COM {
2602*7836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS, groupName, ADD));
2603*7836SJohn.Forte@Sun.COM }
2604*7836SJohn.Forte@Sun.COM 
2605*7836SJohn.Forte@Sun.COM /*
2606*7836SJohn.Forte@Sun.COM  * psDeleteHostGroup
2607*7836SJohn.Forte@Sun.COM  *
2608*7836SJohn.Forte@Sun.COM  * groupName - name of group to delete
2609*7836SJohn.Forte@Sun.COM  *
2610*7836SJohn.Forte@Sun.COM  * returns:
2611*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2612*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2613*7836SJohn.Forte@Sun.COM  */
2614*7836SJohn.Forte@Sun.COM int
2615*7836SJohn.Forte@Sun.COM psDeleteHostGroup(char *groupName)
2616*7836SJohn.Forte@Sun.COM {
2617*7836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_HOST_GROUPS, groupName, REMOVE));
2618*7836SJohn.Forte@Sun.COM }
2619*7836SJohn.Forte@Sun.COM 
2620*7836SJohn.Forte@Sun.COM /*
2621*7836SJohn.Forte@Sun.COM  * psDeleteTargetGroup
2622*7836SJohn.Forte@Sun.COM  *
2623*7836SJohn.Forte@Sun.COM  * groupName - name of group to delete
2624*7836SJohn.Forte@Sun.COM  *
2625*7836SJohn.Forte@Sun.COM  * returns:
2626*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2627*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2628*7836SJohn.Forte@Sun.COM  */
2629*7836SJohn.Forte@Sun.COM int
2630*7836SJohn.Forte@Sun.COM psDeleteTargetGroup(char *groupName)
2631*7836SJohn.Forte@Sun.COM {
2632*7836SJohn.Forte@Sun.COM 	return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS, groupName,
2633*7836SJohn.Forte@Sun.COM 	    REMOVE));
2634*7836SJohn.Forte@Sun.COM }
2635*7836SJohn.Forte@Sun.COM 
2636*7836SJohn.Forte@Sun.COM /*
2637*7836SJohn.Forte@Sun.COM  * psGetHostGroupList
2638*7836SJohn.Forte@Sun.COM  *
2639*7836SJohn.Forte@Sun.COM  * groupList - pointer to pointer to stmfGroupList. Contains the list
2640*7836SJohn.Forte@Sun.COM  *             of host groups on successful return.
2641*7836SJohn.Forte@Sun.COM  *
2642*7836SJohn.Forte@Sun.COM  * returns:
2643*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2644*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2645*7836SJohn.Forte@Sun.COM  */
2646*7836SJohn.Forte@Sun.COM int
2647*7836SJohn.Forte@Sun.COM psGetHostGroupList(stmfGroupList **groupList)
2648*7836SJohn.Forte@Sun.COM {
2649*7836SJohn.Forte@Sun.COM 	return (iPsGetGroupList(STMF_HOST_GROUPS, groupList));
2650*7836SJohn.Forte@Sun.COM }
2651*7836SJohn.Forte@Sun.COM 
2652*7836SJohn.Forte@Sun.COM /*
2653*7836SJohn.Forte@Sun.COM  * psGetLogicalUnitList
2654*7836SJohn.Forte@Sun.COM  *
2655*7836SJohn.Forte@Sun.COM  *
2656*7836SJohn.Forte@Sun.COM  */
2657*7836SJohn.Forte@Sun.COM int
2658*7836SJohn.Forte@Sun.COM psGetLogicalUnitList(stmfGuidList **guidList)
2659*7836SJohn.Forte@Sun.COM {
2660*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
2661*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
2662*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
2663*7836SJohn.Forte@Sun.COM 	scf_iter_t	*pgIter = NULL;
2664*7836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
2665*7836SJohn.Forte@Sun.COM 	int guidCnt = 0;
2666*7836SJohn.Forte@Sun.COM 	int i = 0, j;
2667*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
2668*7836SJohn.Forte@Sun.COM 	unsigned int guid[sizeof (stmfGuid)];
2669*7836SJohn.Forte@Sun.COM 	stmfGuid outGuid;
2670*7836SJohn.Forte@Sun.COM 
2671*7836SJohn.Forte@Sun.COM 	assert(guidList != NULL);
2672*7836SJohn.Forte@Sun.COM 
2673*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
2674*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2675*7836SJohn.Forte@Sun.COM 		goto out;
2676*7836SJohn.Forte@Sun.COM 	}
2677*7836SJohn.Forte@Sun.COM 
2678*7836SJohn.Forte@Sun.COM 	/*
2679*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
2680*7836SJohn.Forte@Sun.COM 	 */
2681*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
2682*7836SJohn.Forte@Sun.COM 	    ((pgIter = scf_iter_create(handle)) == NULL)) {
2683*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
2684*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2685*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2686*7836SJohn.Forte@Sun.COM 		goto out;
2687*7836SJohn.Forte@Sun.COM 	}
2688*7836SJohn.Forte@Sun.COM 
2689*7836SJohn.Forte@Sun.COM 	/*
2690*7836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
2691*7836SJohn.Forte@Sun.COM 	 */
2692*7836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
2693*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
2694*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2695*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2696*7836SJohn.Forte@Sun.COM 		goto out;
2697*7836SJohn.Forte@Sun.COM 	}
2698*7836SJohn.Forte@Sun.COM 
2699*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_pg(pgIter, pg) == 1) {
2700*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
2701*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
2702*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2703*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2704*7836SJohn.Forte@Sun.COM 			break;
2705*7836SJohn.Forte@Sun.COM 		}
2706*7836SJohn.Forte@Sun.COM 		/*
2707*7836SJohn.Forte@Sun.COM 		 * Only count LU property groups
2708*7836SJohn.Forte@Sun.COM 		 */
2709*7836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_LU_PREFIX, strlen(STMF_LU_PREFIX)) == 0) {
2710*7836SJohn.Forte@Sun.COM 			guidCnt++;
2711*7836SJohn.Forte@Sun.COM 		}
2712*7836SJohn.Forte@Sun.COM 	}
2713*7836SJohn.Forte@Sun.COM 
2714*7836SJohn.Forte@Sun.COM 	/*
2715*7836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
2716*7836SJohn.Forte@Sun.COM 	 */
2717*7836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
2718*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
2719*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2720*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2721*7836SJohn.Forte@Sun.COM 		goto out;
2722*7836SJohn.Forte@Sun.COM 	}
2723*7836SJohn.Forte@Sun.COM 
2724*7836SJohn.Forte@Sun.COM 	*guidList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
2725*7836SJohn.Forte@Sun.COM 	    guidCnt * sizeof (stmfGuid));
2726*7836SJohn.Forte@Sun.COM 	if (*guidList == NULL) {
2727*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
2728*7836SJohn.Forte@Sun.COM 		goto out;
2729*7836SJohn.Forte@Sun.COM 	}
2730*7836SJohn.Forte@Sun.COM 
2731*7836SJohn.Forte@Sun.COM 	/*
2732*7836SJohn.Forte@Sun.COM 	 * it's possible for entries to be added/removed while we're retrieving
2733*7836SJohn.Forte@Sun.COM 	 * the property groups. Just make sure we don't write beyond our
2734*7836SJohn.Forte@Sun.COM 	 * allocated buffer by checking to ensure i < guidCnt.
2735*7836SJohn.Forte@Sun.COM 	 */
2736*7836SJohn.Forte@Sun.COM 	while ((scf_iter_next_pg(pgIter, pg) == 1) && (i < guidCnt)) {
2737*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
2738*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
2739*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2740*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2741*7836SJohn.Forte@Sun.COM 			break;
2742*7836SJohn.Forte@Sun.COM 		}
2743*7836SJohn.Forte@Sun.COM 		/*
2744*7836SJohn.Forte@Sun.COM 		 * Only use LU property groups
2745*7836SJohn.Forte@Sun.COM 		 */
2746*7836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_LU_PREFIX, strlen(STMF_LU_PREFIX)) != 0) {
2747*7836SJohn.Forte@Sun.COM 			continue;
2748*7836SJohn.Forte@Sun.COM 		}
2749*7836SJohn.Forte@Sun.COM 
2750*7836SJohn.Forte@Sun.COM 		j = strlen(STMF_LU_PREFIX) + strlen("-");
2751*7836SJohn.Forte@Sun.COM 
2752*7836SJohn.Forte@Sun.COM 		(void) sscanf(buf + j,
2753*7836SJohn.Forte@Sun.COM 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2754*7836SJohn.Forte@Sun.COM 		    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2755*7836SJohn.Forte@Sun.COM 		    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
2756*7836SJohn.Forte@Sun.COM 		    &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
2757*7836SJohn.Forte@Sun.COM 
2758*7836SJohn.Forte@Sun.COM 		for (j = 0; j < sizeof (stmfGuid); j++) {
2759*7836SJohn.Forte@Sun.COM 			outGuid.guid[j] = guid[j];
2760*7836SJohn.Forte@Sun.COM 		}
2761*7836SJohn.Forte@Sun.COM 
2762*7836SJohn.Forte@Sun.COM 		bcopy(&outGuid, (*guidList)->guid[i++].guid, sizeof (stmfGuid));
2763*7836SJohn.Forte@Sun.COM 		(*guidList)->cnt++;
2764*7836SJohn.Forte@Sun.COM 	}
2765*7836SJohn.Forte@Sun.COM 
2766*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2767*7836SJohn.Forte@Sun.COM 		free(*guidList);
2768*7836SJohn.Forte@Sun.COM 		goto out;
2769*7836SJohn.Forte@Sun.COM 	}
2770*7836SJohn.Forte@Sun.COM 
2771*7836SJohn.Forte@Sun.COM out:
2772*7836SJohn.Forte@Sun.COM 	/*
2773*7836SJohn.Forte@Sun.COM 	 * Free resources
2774*7836SJohn.Forte@Sun.COM 	 */
2775*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
2776*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
2777*7836SJohn.Forte@Sun.COM 	}
2778*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
2779*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
2780*7836SJohn.Forte@Sun.COM 	}
2781*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
2782*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
2783*7836SJohn.Forte@Sun.COM 	}
2784*7836SJohn.Forte@Sun.COM 	if (pgIter != NULL) {
2785*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(pgIter);
2786*7836SJohn.Forte@Sun.COM 	}
2787*7836SJohn.Forte@Sun.COM 
2788*7836SJohn.Forte@Sun.COM 	return (ret);
2789*7836SJohn.Forte@Sun.COM }
2790*7836SJohn.Forte@Sun.COM 
2791*7836SJohn.Forte@Sun.COM /*
2792*7836SJohn.Forte@Sun.COM  * psGetTargetGroupList
2793*7836SJohn.Forte@Sun.COM  *
2794*7836SJohn.Forte@Sun.COM  * groupList - pointer to pointer to stmfGroupList. Contains the list
2795*7836SJohn.Forte@Sun.COM  *             of target groups on successful return.
2796*7836SJohn.Forte@Sun.COM  *
2797*7836SJohn.Forte@Sun.COM  * returns:
2798*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2799*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2800*7836SJohn.Forte@Sun.COM  */
2801*7836SJohn.Forte@Sun.COM int
2802*7836SJohn.Forte@Sun.COM psGetTargetGroupList(stmfGroupList **groupList)
2803*7836SJohn.Forte@Sun.COM {
2804*7836SJohn.Forte@Sun.COM 	return (iPsGetGroupList(STMF_TARGET_GROUPS, groupList));
2805*7836SJohn.Forte@Sun.COM }
2806*7836SJohn.Forte@Sun.COM 
2807*7836SJohn.Forte@Sun.COM /*
2808*7836SJohn.Forte@Sun.COM  * psGetHostGroupMemberList
2809*7836SJohn.Forte@Sun.COM  *
2810*7836SJohn.Forte@Sun.COM  * groupName - group name for which to retrieve a member list
2811*7836SJohn.Forte@Sun.COM  * groupMemberList - pointer to pointer to stmfGroupProperties list
2812*7836SJohn.Forte@Sun.COM  *
2813*7836SJohn.Forte@Sun.COM  * returns:
2814*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2815*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2816*7836SJohn.Forte@Sun.COM  */
2817*7836SJohn.Forte@Sun.COM int
2818*7836SJohn.Forte@Sun.COM psGetHostGroupMemberList(char *groupName, stmfGroupProperties **groupMemberList)
2819*7836SJohn.Forte@Sun.COM {
2820*7836SJohn.Forte@Sun.COM 	int ret;
2821*7836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
2822*7836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
2823*7836SJohn.Forte@Sun.COM 
2824*7836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName,
2825*7836SJohn.Forte@Sun.COM 	    groupPropName);
2826*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2827*7836SJohn.Forte@Sun.COM 		return (ret);
2828*7836SJohn.Forte@Sun.COM 	}
2829*7836SJohn.Forte@Sun.COM 
2830*7836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
2831*7836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
2832*7836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
2833*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
2834*7836SJohn.Forte@Sun.COM 		    groupPropName);
2835*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
2836*7836SJohn.Forte@Sun.COM 	}
2837*7836SJohn.Forte@Sun.COM 
2838*7836SJohn.Forte@Sun.COM 	return (iPsGetGroupMemberList(STMF_HOST_GROUPS, groupPropListName,
2839*7836SJohn.Forte@Sun.COM 	    groupMemberList));
2840*7836SJohn.Forte@Sun.COM }
2841*7836SJohn.Forte@Sun.COM 
2842*7836SJohn.Forte@Sun.COM /*
2843*7836SJohn.Forte@Sun.COM  * psGetTargetGroupMemberList
2844*7836SJohn.Forte@Sun.COM  *
2845*7836SJohn.Forte@Sun.COM  * groupName - group name for which to retrieve a member list
2846*7836SJohn.Forte@Sun.COM  * groupMemberList - pointer to pointer to stmfGroupProperties list
2847*7836SJohn.Forte@Sun.COM  *
2848*7836SJohn.Forte@Sun.COM  * returns:
2849*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2850*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2851*7836SJohn.Forte@Sun.COM  */
2852*7836SJohn.Forte@Sun.COM int
2853*7836SJohn.Forte@Sun.COM psGetTargetGroupMemberList(char *groupName,
2854*7836SJohn.Forte@Sun.COM     stmfGroupProperties **groupMemberList)
2855*7836SJohn.Forte@Sun.COM {
2856*7836SJohn.Forte@Sun.COM 	int ret;
2857*7836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
2858*7836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
2859*7836SJohn.Forte@Sun.COM 
2860*7836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName,
2861*7836SJohn.Forte@Sun.COM 	    groupPropName);
2862*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2863*7836SJohn.Forte@Sun.COM 		return (ret);
2864*7836SJohn.Forte@Sun.COM 	}
2865*7836SJohn.Forte@Sun.COM 
2866*7836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
2867*7836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
2868*7836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
2869*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
2870*7836SJohn.Forte@Sun.COM 		    groupPropName);
2871*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
2872*7836SJohn.Forte@Sun.COM 	}
2873*7836SJohn.Forte@Sun.COM 
2874*7836SJohn.Forte@Sun.COM 	return (iPsGetGroupMemberList(STMF_TARGET_GROUPS,
2875*7836SJohn.Forte@Sun.COM 	    groupPropListName, groupMemberList));
2876*7836SJohn.Forte@Sun.COM }
2877*7836SJohn.Forte@Sun.COM 
2878*7836SJohn.Forte@Sun.COM /*
2879*7836SJohn.Forte@Sun.COM  * qsort function
2880*7836SJohn.Forte@Sun.COM  * sort on veIndex
2881*7836SJohn.Forte@Sun.COM  */
2882*7836SJohn.Forte@Sun.COM static int
2883*7836SJohn.Forte@Sun.COM viewEntryCompare(const void *p1, const void *p2)
2884*7836SJohn.Forte@Sun.COM {
2885*7836SJohn.Forte@Sun.COM 
2886*7836SJohn.Forte@Sun.COM 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
2887*7836SJohn.Forte@Sun.COM 	if (v1->veIndex > v2->veIndex)
2888*7836SJohn.Forte@Sun.COM 		return (1);
2889*7836SJohn.Forte@Sun.COM 	if (v1->veIndex < v2->veIndex)
2890*7836SJohn.Forte@Sun.COM 		return (-1);
2891*7836SJohn.Forte@Sun.COM 	return (0);
2892*7836SJohn.Forte@Sun.COM }
2893*7836SJohn.Forte@Sun.COM 
2894*7836SJohn.Forte@Sun.COM /*
2895*7836SJohn.Forte@Sun.COM  * psGetViewEntryList
2896*7836SJohn.Forte@Sun.COM  *
2897*7836SJohn.Forte@Sun.COM  * luGuid - identifier of logical unit for which to retrieve a view entry list
2898*7836SJohn.Forte@Sun.COM  * viewEntryList - pointer to pointer to stmfViewEntryList. It will be allocated
2899*7836SJohn.Forte@Sun.COM  *                 on successful return.
2900*7836SJohn.Forte@Sun.COM  *
2901*7836SJohn.Forte@Sun.COM  * returns:
2902*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
2903*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
2904*7836SJohn.Forte@Sun.COM  */
2905*7836SJohn.Forte@Sun.COM int
2906*7836SJohn.Forte@Sun.COM psGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
2907*7836SJohn.Forte@Sun.COM {
2908*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
2909*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
2910*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
2911*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
2912*7836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
2913*7836SJohn.Forte@Sun.COM 	scf_iter_t  *propIter = NULL;
2914*7836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
2915*7836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
2916*7836SJohn.Forte@Sun.COM 	char luPgName[LOGICAL_UNIT_PG_SIZE];
2917*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
2918*7836SJohn.Forte@Sun.COM 	uint64_t i = 0;
2919*7836SJohn.Forte@Sun.COM 	uint64_t veCnt;
2920*7836SJohn.Forte@Sun.COM 
2921*7836SJohn.Forte@Sun.COM 
2922*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
2923*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
2924*7836SJohn.Forte@Sun.COM 		goto out;
2925*7836SJohn.Forte@Sun.COM 	}
2926*7836SJohn.Forte@Sun.COM 
2927*7836SJohn.Forte@Sun.COM 	/*
2928*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
2929*7836SJohn.Forte@Sun.COM 	 */
2930*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
2931*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
2932*7836SJohn.Forte@Sun.COM 	    ((propIter = scf_iter_create(handle)) == NULL) ||
2933*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
2934*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
2935*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2936*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2937*7836SJohn.Forte@Sun.COM 		goto out;
2938*7836SJohn.Forte@Sun.COM 	}
2939*7836SJohn.Forte@Sun.COM 
2940*7836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
2941*7836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
2942*7836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
2943*7836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
2944*7836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
2945*7836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
2946*7836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
2947*7836SJohn.Forte@Sun.COM 
2948*7836SJohn.Forte@Sun.COM 	/* form the LU property group name (LU-<guid>) */
2949*7836SJohn.Forte@Sun.COM 	(void) snprintf(luPgName, sizeof (luPgName), "%s-%s",
2950*7836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
2951*7836SJohn.Forte@Sun.COM 
2952*7836SJohn.Forte@Sun.COM 	/* get the property group associated with this LU */
2953*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, luPgName, pg) == -1) {
2954*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
2955*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
2956*7836SJohn.Forte@Sun.COM 		} else {
2957*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
2958*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
2959*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
2960*7836SJohn.Forte@Sun.COM 		}
2961*7836SJohn.Forte@Sun.COM 		goto out;
2962*7836SJohn.Forte@Sun.COM 	}
2963*7836SJohn.Forte@Sun.COM 
2964*7836SJohn.Forte@Sun.COM 	/* get the view entry count property */
2965*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_CNT, prop) == -1) {
2966*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
2967*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2968*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2969*7836SJohn.Forte@Sun.COM 		goto out;
2970*7836SJohn.Forte@Sun.COM 	}
2971*7836SJohn.Forte@Sun.COM 
2972*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
2973*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property value failed - %s",
2974*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2975*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2976*7836SJohn.Forte@Sun.COM 		goto out;
2977*7836SJohn.Forte@Sun.COM 	}
2978*7836SJohn.Forte@Sun.COM 
2979*7836SJohn.Forte@Sun.COM 	/*
2980*7836SJohn.Forte@Sun.COM 	 * Get the actual value of the view entry count property
2981*7836SJohn.Forte@Sun.COM 	 */
2982*7836SJohn.Forte@Sun.COM 	if (scf_value_get_count(value, &veCnt) == -1) {
2983*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get integer value failed - %s",
2984*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2985*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2986*7836SJohn.Forte@Sun.COM 		goto out;
2987*7836SJohn.Forte@Sun.COM 	}
2988*7836SJohn.Forte@Sun.COM 
2989*7836SJohn.Forte@Sun.COM 	/*
2990*7836SJohn.Forte@Sun.COM 	 * propIter is the iterator handle
2991*7836SJohn.Forte@Sun.COM 	 */
2992*7836SJohn.Forte@Sun.COM 	if (scf_iter_pg_properties(propIter, pg) == -1) {
2993*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter properties failed - %s",
2994*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
2995*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
2996*7836SJohn.Forte@Sun.COM 		goto out;
2997*7836SJohn.Forte@Sun.COM 	}
2998*7836SJohn.Forte@Sun.COM 
2999*7836SJohn.Forte@Sun.COM 	/*
3000*7836SJohn.Forte@Sun.COM 	 * alloc the list based on the view entry count
3001*7836SJohn.Forte@Sun.COM 	 */
3002*7836SJohn.Forte@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
3003*7836SJohn.Forte@Sun.COM 	    sizeof (stmfViewEntryList) + veCnt * sizeof (stmfViewEntry));
3004*7836SJohn.Forte@Sun.COM 	if (*viewEntryList == NULL) {
3005*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
3006*7836SJohn.Forte@Sun.COM 		goto out;
3007*7836SJohn.Forte@Sun.COM 	}
3008*7836SJohn.Forte@Sun.COM 
3009*7836SJohn.Forte@Sun.COM 	i = 0;
3010*7836SJohn.Forte@Sun.COM 	/*
3011*7836SJohn.Forte@Sun.COM 	 * iterate through the view entry properties to find the
3012*7836SJohn.Forte@Sun.COM 	 * view entries
3013*7836SJohn.Forte@Sun.COM 	 */
3014*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_property(propIter, prop) == 1) {
3015*7836SJohn.Forte@Sun.COM 		/* find match for view entry property */
3016*7836SJohn.Forte@Sun.COM 		if (scf_property_get_name(prop, viewEntryPgName,
3017*7836SJohn.Forte@Sun.COM 		    sizeof (viewEntryPgName)) != -1) {
3018*7836SJohn.Forte@Sun.COM 			if (strncmp(viewEntryPgName, STMF_VE_PREFIX,
3019*7836SJohn.Forte@Sun.COM 			    strlen(STMF_VE_PREFIX)) != 0) {
3020*7836SJohn.Forte@Sun.COM 				continue;
3021*7836SJohn.Forte@Sun.COM 			}
3022*7836SJohn.Forte@Sun.COM 			/*
3023*7836SJohn.Forte@Sun.COM 			 * We've exceeded our alloc limit
3024*7836SJohn.Forte@Sun.COM 			 * break with error
3025*7836SJohn.Forte@Sun.COM 			 */
3026*7836SJohn.Forte@Sun.COM 			if (i == veCnt) {
3027*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
3028*7836SJohn.Forte@Sun.COM 				break;
3029*7836SJohn.Forte@Sun.COM 			}
3030*7836SJohn.Forte@Sun.COM 
3031*7836SJohn.Forte@Sun.COM 			if ((ret = iPsGetViewEntry(viewEntryPgName,
3032*7836SJohn.Forte@Sun.COM 			    &((*viewEntryList)->ve[i]))) != STMF_PS_SUCCESS) {
3033*7836SJohn.Forte@Sun.COM 				break;
3034*7836SJohn.Forte@Sun.COM 			}
3035*7836SJohn.Forte@Sun.COM 
3036*7836SJohn.Forte@Sun.COM 			i++;
3037*7836SJohn.Forte@Sun.COM 
3038*7836SJohn.Forte@Sun.COM 			/* set the list count */
3039*7836SJohn.Forte@Sun.COM 			(*viewEntryList)->cnt++;
3040*7836SJohn.Forte@Sun.COM 		} else {
3041*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf pg iter service failed - %s",
3042*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3043*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3044*7836SJohn.Forte@Sun.COM 			break;
3045*7836SJohn.Forte@Sun.COM 		}
3046*7836SJohn.Forte@Sun.COM 
3047*7836SJohn.Forte@Sun.COM 	}
3048*7836SJohn.Forte@Sun.COM 
3049*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3050*7836SJohn.Forte@Sun.COM 		free(*viewEntryList);
3051*7836SJohn.Forte@Sun.COM 		goto out;
3052*7836SJohn.Forte@Sun.COM 	}
3053*7836SJohn.Forte@Sun.COM 
3054*7836SJohn.Forte@Sun.COM 	/*
3055*7836SJohn.Forte@Sun.COM 	 * We're sorting the final list here based on the veIndex
3056*7836SJohn.Forte@Sun.COM 	 * If we don't, the caller is going to have to do it to reap
3057*7836SJohn.Forte@Sun.COM 	 * some intelligent output.
3058*7836SJohn.Forte@Sun.COM 	 */
3059*7836SJohn.Forte@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
3060*7836SJohn.Forte@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
3061*7836SJohn.Forte@Sun.COM 
3062*7836SJohn.Forte@Sun.COM out:
3063*7836SJohn.Forte@Sun.COM 	/*
3064*7836SJohn.Forte@Sun.COM 	 * Free resources
3065*7836SJohn.Forte@Sun.COM 	 */
3066*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
3067*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
3068*7836SJohn.Forte@Sun.COM 	}
3069*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
3070*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
3071*7836SJohn.Forte@Sun.COM 	}
3072*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
3073*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
3074*7836SJohn.Forte@Sun.COM 	}
3075*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
3076*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
3077*7836SJohn.Forte@Sun.COM 	}
3078*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
3079*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
3080*7836SJohn.Forte@Sun.COM 	}
3081*7836SJohn.Forte@Sun.COM 	if (propIter != NULL) {
3082*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(propIter);
3083*7836SJohn.Forte@Sun.COM 	}
3084*7836SJohn.Forte@Sun.COM 
3085*7836SJohn.Forte@Sun.COM 	return (ret);
3086*7836SJohn.Forte@Sun.COM }
3087*7836SJohn.Forte@Sun.COM 
3088*7836SJohn.Forte@Sun.COM /*
3089*7836SJohn.Forte@Sun.COM  * iPsGetViewEntry
3090*7836SJohn.Forte@Sun.COM  *
3091*7836SJohn.Forte@Sun.COM  * viewEntryPgName - view entry property group name to retrieve
3092*7836SJohn.Forte@Sun.COM  * viewEntry - pointer to stmfViewEntry structure allocated by the caller
3093*7836SJohn.Forte@Sun.COM  *
3094*7836SJohn.Forte@Sun.COM  * returns:
3095*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
3096*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
3097*7836SJohn.Forte@Sun.COM  */
3098*7836SJohn.Forte@Sun.COM static int
3099*7836SJohn.Forte@Sun.COM iPsGetViewEntry(char *viewEntryPgName, stmfViewEntry *viewEntry)
3100*7836SJohn.Forte@Sun.COM {
3101*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
3102*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
3103*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
3104*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
3105*7836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
3106*7836SJohn.Forte@Sun.COM 	uint8_t scfBool;
3107*7836SJohn.Forte@Sun.COM 	char *indexPtr;
3108*7836SJohn.Forte@Sun.COM 	char groupName[sizeof (stmfGroupName)];
3109*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
3110*7836SJohn.Forte@Sun.COM 
3111*7836SJohn.Forte@Sun.COM 
3112*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
3113*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3114*7836SJohn.Forte@Sun.COM 		goto out;
3115*7836SJohn.Forte@Sun.COM 	}
3116*7836SJohn.Forte@Sun.COM 
3117*7836SJohn.Forte@Sun.COM 	/*
3118*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
3119*7836SJohn.Forte@Sun.COM 	 */
3120*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
3121*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
3122*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL)) {
3123*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
3124*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3125*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3126*7836SJohn.Forte@Sun.COM 		goto out;
3127*7836SJohn.Forte@Sun.COM 	}
3128*7836SJohn.Forte@Sun.COM 
3129*7836SJohn.Forte@Sun.COM 	bzero(viewEntry, sizeof (stmfViewEntry));
3130*7836SJohn.Forte@Sun.COM 
3131*7836SJohn.Forte@Sun.COM 	/*
3132*7836SJohn.Forte@Sun.COM 	 * get the service property group view entry handle
3133*7836SJohn.Forte@Sun.COM 	 */
3134*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) {
3135*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
3136*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
3137*7836SJohn.Forte@Sun.COM 		} else {
3138*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
3139*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3140*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3141*7836SJohn.Forte@Sun.COM 		}
3142*7836SJohn.Forte@Sun.COM 		goto out;
3143*7836SJohn.Forte@Sun.COM 	}
3144*7836SJohn.Forte@Sun.COM 
3145*7836SJohn.Forte@Sun.COM 
3146*7836SJohn.Forte@Sun.COM 	/*
3147*7836SJohn.Forte@Sun.COM 	 * get index
3148*7836SJohn.Forte@Sun.COM 	 * format is: VE-<veIndex>-GUID
3149*7836SJohn.Forte@Sun.COM 	 */
3150*7836SJohn.Forte@Sun.COM 	indexPtr = strchr(viewEntryPgName, '-');
3151*7836SJohn.Forte@Sun.COM 	if (!indexPtr) {
3152*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3153*7836SJohn.Forte@Sun.COM 		goto out;
3154*7836SJohn.Forte@Sun.COM 	}
3155*7836SJohn.Forte@Sun.COM 
3156*7836SJohn.Forte@Sun.COM 	/* Set the index */
3157*7836SJohn.Forte@Sun.COM 	viewEntry->veIndex = atoi(strtok(++indexPtr, "-"));
3158*7836SJohn.Forte@Sun.COM 
3159*7836SJohn.Forte@Sun.COM 	viewEntry->veIndexValid = B_TRUE;
3160*7836SJohn.Forte@Sun.COM 
3161*7836SJohn.Forte@Sun.COM 	/* get allHosts property */
3162*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_ALLHOSTS,
3163*7836SJohn.Forte@Sun.COM 	    prop) == -1) {
3164*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3165*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3166*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3167*7836SJohn.Forte@Sun.COM 		goto out;
3168*7836SJohn.Forte@Sun.COM 	}
3169*7836SJohn.Forte@Sun.COM 
3170*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
3171*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3172*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3173*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3174*7836SJohn.Forte@Sun.COM 		goto out;
3175*7836SJohn.Forte@Sun.COM 	}
3176*7836SJohn.Forte@Sun.COM 
3177*7836SJohn.Forte@Sun.COM 	/* set allHosts */
3178*7836SJohn.Forte@Sun.COM 	if (scf_value_get_boolean(value, (uint8_t *)&scfBool) == -1) {
3179*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3180*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3181*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3182*7836SJohn.Forte@Sun.COM 		goto out;
3183*7836SJohn.Forte@Sun.COM 	}
3184*7836SJohn.Forte@Sun.COM 	viewEntry->allHosts = scfBool;
3185*7836SJohn.Forte@Sun.COM 
3186*7836SJohn.Forte@Sun.COM 	/* get hostGroup property */
3187*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_HOSTGROUP,
3188*7836SJohn.Forte@Sun.COM 	    prop) == -1) {
3189*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3190*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3191*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3192*7836SJohn.Forte@Sun.COM 		goto out;
3193*7836SJohn.Forte@Sun.COM 	}
3194*7836SJohn.Forte@Sun.COM 
3195*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
3196*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3197*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3198*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3199*7836SJohn.Forte@Sun.COM 		goto out;
3200*7836SJohn.Forte@Sun.COM 	}
3201*7836SJohn.Forte@Sun.COM 
3202*7836SJohn.Forte@Sun.COM 	if (scf_value_get_ustring(value, groupName,
3203*7836SJohn.Forte@Sun.COM 	    sizeof (groupName)) == -1) {
3204*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
3205*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3206*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3207*7836SJohn.Forte@Sun.COM 		goto out;
3208*7836SJohn.Forte@Sun.COM 	}
3209*7836SJohn.Forte@Sun.COM 	/* set hostGroup */
3210*7836SJohn.Forte@Sun.COM 	bcopy(groupName, viewEntry->hostGroup, strlen(groupName));
3211*7836SJohn.Forte@Sun.COM 
3212*7836SJohn.Forte@Sun.COM 	/* get allTargets property */
3213*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_ALLTARGETS,
3214*7836SJohn.Forte@Sun.COM 	    prop) == -1) {
3215*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3216*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3217*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3218*7836SJohn.Forte@Sun.COM 		goto out;
3219*7836SJohn.Forte@Sun.COM 	}
3220*7836SJohn.Forte@Sun.COM 
3221*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
3222*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3223*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3224*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3225*7836SJohn.Forte@Sun.COM 		goto out;
3226*7836SJohn.Forte@Sun.COM 	}
3227*7836SJohn.Forte@Sun.COM 
3228*7836SJohn.Forte@Sun.COM 	/* set allTargets */
3229*7836SJohn.Forte@Sun.COM 	if (scf_value_get_boolean(value, (uint8_t *)&scfBool) == -1) {
3230*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3231*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3232*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3233*7836SJohn.Forte@Sun.COM 		goto out;
3234*7836SJohn.Forte@Sun.COM 	}
3235*7836SJohn.Forte@Sun.COM 	viewEntry->allTargets = scfBool;
3236*7836SJohn.Forte@Sun.COM 
3237*7836SJohn.Forte@Sun.COM 	/* get targetGroup property */
3238*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_TARGETGROUP, prop) == -1) {
3239*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3240*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3241*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3242*7836SJohn.Forte@Sun.COM 		goto out;
3243*7836SJohn.Forte@Sun.COM 	}
3244*7836SJohn.Forte@Sun.COM 
3245*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
3246*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3247*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3248*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3249*7836SJohn.Forte@Sun.COM 		goto out;
3250*7836SJohn.Forte@Sun.COM 	}
3251*7836SJohn.Forte@Sun.COM 
3252*7836SJohn.Forte@Sun.COM 	if (scf_value_get_ustring(value, groupName,
3253*7836SJohn.Forte@Sun.COM 	    sizeof (groupName)) == -1) {
3254*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "set value failed - %s",
3255*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3256*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3257*7836SJohn.Forte@Sun.COM 		goto out;
3258*7836SJohn.Forte@Sun.COM 	}
3259*7836SJohn.Forte@Sun.COM 	/* set targetGroup */
3260*7836SJohn.Forte@Sun.COM 	bcopy(groupName, viewEntry->targetGroup, strlen(groupName));
3261*7836SJohn.Forte@Sun.COM 
3262*7836SJohn.Forte@Sun.COM 	/* get luNbr property */
3263*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_VE_LUNBR,
3264*7836SJohn.Forte@Sun.COM 	    prop) == -1) {
3265*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3266*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3267*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3268*7836SJohn.Forte@Sun.COM 		goto out;
3269*7836SJohn.Forte@Sun.COM 	}
3270*7836SJohn.Forte@Sun.COM 
3271*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
3272*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property value failed - %s",
3273*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3274*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3275*7836SJohn.Forte@Sun.COM 		goto out;
3276*7836SJohn.Forte@Sun.COM 	}
3277*7836SJohn.Forte@Sun.COM 
3278*7836SJohn.Forte@Sun.COM 	/* set luNbr */
3279*7836SJohn.Forte@Sun.COM 	if (scf_value_get_opaque(value, (char *)viewEntry->luNbr,
3280*7836SJohn.Forte@Sun.COM 	    sizeof (viewEntry->luNbr)) == -1) {
3281*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get opaque value failed - %s",
3282*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3283*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3284*7836SJohn.Forte@Sun.COM 		goto out;
3285*7836SJohn.Forte@Sun.COM 	}
3286*7836SJohn.Forte@Sun.COM 	/* set luNbrValid to true since we just got it */
3287*7836SJohn.Forte@Sun.COM 	viewEntry->luNbrValid = B_TRUE;
3288*7836SJohn.Forte@Sun.COM 
3289*7836SJohn.Forte@Sun.COM out:
3290*7836SJohn.Forte@Sun.COM 	/*
3291*7836SJohn.Forte@Sun.COM 	 * Free resources
3292*7836SJohn.Forte@Sun.COM 	 */
3293*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
3294*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
3295*7836SJohn.Forte@Sun.COM 	}
3296*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
3297*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
3298*7836SJohn.Forte@Sun.COM 	}
3299*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
3300*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
3301*7836SJohn.Forte@Sun.COM 	}
3302*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
3303*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
3304*7836SJohn.Forte@Sun.COM 	}
3305*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
3306*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
3307*7836SJohn.Forte@Sun.COM 	}
3308*7836SJohn.Forte@Sun.COM 
3309*7836SJohn.Forte@Sun.COM 	return (ret);
3310*7836SJohn.Forte@Sun.COM }
3311*7836SJohn.Forte@Sun.COM 
3312*7836SJohn.Forte@Sun.COM 
3313*7836SJohn.Forte@Sun.COM /*
3314*7836SJohn.Forte@Sun.COM  * psRemoveHostGroupMember
3315*7836SJohn.Forte@Sun.COM  *
3316*7836SJohn.Forte@Sun.COM  * Remove a host group member from a host group,
3317*7836SJohn.Forte@Sun.COM  *
3318*7836SJohn.Forte@Sun.COM  * groupName - name of group from which the member is removed
3319*7836SJohn.Forte@Sun.COM  * memberName - name of group member to remove
3320*7836SJohn.Forte@Sun.COM  *
3321*7836SJohn.Forte@Sun.COM  * returns:
3322*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
3323*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
3324*7836SJohn.Forte@Sun.COM  */
3325*7836SJohn.Forte@Sun.COM int
3326*7836SJohn.Forte@Sun.COM psRemoveHostGroupMember(char *groupName, char *memberName)
3327*7836SJohn.Forte@Sun.COM {
3328*7836SJohn.Forte@Sun.COM 	int ret;
3329*7836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
3330*7836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
3331*7836SJohn.Forte@Sun.COM 
3332*7836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_HOST_GROUPS, groupName,
3333*7836SJohn.Forte@Sun.COM 	    groupPropName);
3334*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3335*7836SJohn.Forte@Sun.COM 		return (ret);
3336*7836SJohn.Forte@Sun.COM 	}
3337*7836SJohn.Forte@Sun.COM 
3338*7836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
3339*7836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
3340*7836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
3341*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
3342*7836SJohn.Forte@Sun.COM 		    groupPropName);
3343*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
3344*7836SJohn.Forte@Sun.COM 	}
3345*7836SJohn.Forte@Sun.COM 
3346*7836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS, groupPropListName,
3347*7836SJohn.Forte@Sun.COM 	    memberName, REMOVE));
3348*7836SJohn.Forte@Sun.COM }
3349*7836SJohn.Forte@Sun.COM 
3350*7836SJohn.Forte@Sun.COM /*
3351*7836SJohn.Forte@Sun.COM  * psRemoveTargetGroupMember
3352*7836SJohn.Forte@Sun.COM  *
3353*7836SJohn.Forte@Sun.COM  * Remove a target port group member from an target port group,
3354*7836SJohn.Forte@Sun.COM  *
3355*7836SJohn.Forte@Sun.COM  * groupName - name of group from which the member is removed
3356*7836SJohn.Forte@Sun.COM  * memberName - name of group member to remove
3357*7836SJohn.Forte@Sun.COM  *
3358*7836SJohn.Forte@Sun.COM  * returns:
3359*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
3360*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
3361*7836SJohn.Forte@Sun.COM  */
3362*7836SJohn.Forte@Sun.COM int
3363*7836SJohn.Forte@Sun.COM psRemoveTargetGroupMember(char *groupName, char *memberName)
3364*7836SJohn.Forte@Sun.COM {
3365*7836SJohn.Forte@Sun.COM 	int ret;
3366*7836SJohn.Forte@Sun.COM 	char groupPropListName[MAXNAMELEN];
3367*7836SJohn.Forte@Sun.COM 	char groupPropName[MAXNAMELEN];
3368*7836SJohn.Forte@Sun.COM 
3369*7836SJohn.Forte@Sun.COM 	ret = iPsGetActualGroupName(STMF_TARGET_GROUPS, groupName,
3370*7836SJohn.Forte@Sun.COM 	    groupPropName);
3371*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3372*7836SJohn.Forte@Sun.COM 		return (ret);
3373*7836SJohn.Forte@Sun.COM 	}
3374*7836SJohn.Forte@Sun.COM 
3375*7836SJohn.Forte@Sun.COM 	if (snprintf(groupPropListName, sizeof (groupPropListName),
3376*7836SJohn.Forte@Sun.COM 	    "%s-%s", groupPropName, STMF_MEMBER_LIST_SUFFIX) >
3377*7836SJohn.Forte@Sun.COM 	    sizeof (groupPropListName)) {
3378*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "buffer overflow on property name %s",
3379*7836SJohn.Forte@Sun.COM 		    groupPropName);
3380*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
3381*7836SJohn.Forte@Sun.COM 	}
3382*7836SJohn.Forte@Sun.COM 
3383*7836SJohn.Forte@Sun.COM 	return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS, groupPropListName,
3384*7836SJohn.Forte@Sun.COM 	    memberName, REMOVE));
3385*7836SJohn.Forte@Sun.COM }
3386*7836SJohn.Forte@Sun.COM 
3387*7836SJohn.Forte@Sun.COM /*
3388*7836SJohn.Forte@Sun.COM  * psGetProviderData
3389*7836SJohn.Forte@Sun.COM  *
3390*7836SJohn.Forte@Sun.COM  * Retrieves an nvlist on a per provider basis
3391*7836SJohn.Forte@Sun.COM  *
3392*7836SJohn.Forte@Sun.COM  * providerName - property group name to use
3393*7836SJohn.Forte@Sun.COM  * nvl - nvlist to retrieve
3394*7836SJohn.Forte@Sun.COM  *
3395*7836SJohn.Forte@Sun.COM  */
3396*7836SJohn.Forte@Sun.COM int
3397*7836SJohn.Forte@Sun.COM psGetProviderData(char *providerName, nvlist_t **nvl, int providerType,
3398*7836SJohn.Forte@Sun.COM     uint64_t *setToken)
3399*7836SJohn.Forte@Sun.COM {
3400*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
3401*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
3402*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
3403*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
3404*7836SJohn.Forte@Sun.COM 	scf_value_t	*value = NULL;
3405*7836SJohn.Forte@Sun.COM 	uint64_t blockCnt = 0;
3406*7836SJohn.Forte@Sun.COM 	ssize_t blockOffset = 0;
3407*7836SJohn.Forte@Sun.COM 	ssize_t actualBlockSize = 0;
3408*7836SJohn.Forte@Sun.COM 	char pgName[MAXPATHLEN];
3409*7836SJohn.Forte@Sun.COM 	char dataPropertyName[STMF_PROVIDER_DATA_PROP_NAME_SIZE];
3410*7836SJohn.Forte@Sun.COM 	char *nvlistEncoded = NULL;
3411*7836SJohn.Forte@Sun.COM 	ssize_t nvlistEncodedSize = 0;
3412*7836SJohn.Forte@Sun.COM 	boolean_t foundSetCnt = B_TRUE;
3413*7836SJohn.Forte@Sun.COM 	int i;
3414*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
3415*7836SJohn.Forte@Sun.COM 
3416*7836SJohn.Forte@Sun.COM 	if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
3417*7836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE)) {
3418*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_INVALID_ARG;
3419*7836SJohn.Forte@Sun.COM 		goto out;
3420*7836SJohn.Forte@Sun.COM 	}
3421*7836SJohn.Forte@Sun.COM 
3422*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
3423*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3424*7836SJohn.Forte@Sun.COM 		goto out;
3425*7836SJohn.Forte@Sun.COM 	}
3426*7836SJohn.Forte@Sun.COM 
3427*7836SJohn.Forte@Sun.COM 	/*
3428*7836SJohn.Forte@Sun.COM 	 * create the property group name
3429*7836SJohn.Forte@Sun.COM 	 */
3430*7836SJohn.Forte@Sun.COM 	(void) snprintf(pgName, sizeof (pgName), "%s%s",
3431*7836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PREFIX, providerName);
3432*7836SJohn.Forte@Sun.COM 
3433*7836SJohn.Forte@Sun.COM 	/*
3434*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
3435*7836SJohn.Forte@Sun.COM 	 */
3436*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
3437*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL) ||
3438*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL)) {
3439*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
3440*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3441*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3442*7836SJohn.Forte@Sun.COM 		goto out;
3443*7836SJohn.Forte@Sun.COM 	}
3444*7836SJohn.Forte@Sun.COM 
3445*7836SJohn.Forte@Sun.COM 	/*
3446*7836SJohn.Forte@Sun.COM 	 * Retrieve the existing property group.
3447*7836SJohn.Forte@Sun.COM 	 */
3448*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
3449*7836SJohn.Forte@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
3450*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
3451*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3452*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3453*7836SJohn.Forte@Sun.COM 			goto out;
3454*7836SJohn.Forte@Sun.COM 		} else {
3455*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
3456*7836SJohn.Forte@Sun.COM 			goto out;
3457*7836SJohn.Forte@Sun.COM 		}
3458*7836SJohn.Forte@Sun.COM 	}
3459*7836SJohn.Forte@Sun.COM 
3460*7836SJohn.Forte@Sun.COM 	/*
3461*7836SJohn.Forte@Sun.COM 	 * Get the STMF_PROVIDER_DATA_PROP_COUNT property
3462*7836SJohn.Forte@Sun.COM 	 */
3463*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_COUNT,
3464*7836SJohn.Forte@Sun.COM 	    prop) == -1) {
3465*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property failed - %s",
3466*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3467*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3468*7836SJohn.Forte@Sun.COM 		goto out;
3469*7836SJohn.Forte@Sun.COM 	}
3470*7836SJohn.Forte@Sun.COM 
3471*7836SJohn.Forte@Sun.COM 	/*
3472*7836SJohn.Forte@Sun.COM 	 * Get the STMF_PROVIDER_DATA_PROP_COUNT value
3473*7836SJohn.Forte@Sun.COM 	 */
3474*7836SJohn.Forte@Sun.COM 	if (scf_property_get_value(prop, value) == -1) {
3475*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get property value failed - %s",
3476*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3477*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3478*7836SJohn.Forte@Sun.COM 		goto out;
3479*7836SJohn.Forte@Sun.COM 	}
3480*7836SJohn.Forte@Sun.COM 
3481*7836SJohn.Forte@Sun.COM 	/*
3482*7836SJohn.Forte@Sun.COM 	 * Now get the actual value from the value handle
3483*7836SJohn.Forte@Sun.COM 	 */
3484*7836SJohn.Forte@Sun.COM 	if (scf_value_get_count(value, &blockCnt) == -1) {
3485*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "get integer value failed - %s",
3486*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3487*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3488*7836SJohn.Forte@Sun.COM 		goto out;
3489*7836SJohn.Forte@Sun.COM 	}
3490*7836SJohn.Forte@Sun.COM 
3491*7836SJohn.Forte@Sun.COM 	/* Has the caller requested the token to be set? */
3492*7836SJohn.Forte@Sun.COM 	if (setToken) {
3493*7836SJohn.Forte@Sun.COM 		/*
3494*7836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
3495*7836SJohn.Forte@Sun.COM 		 * If it doesn't exist, we assume it to be zero.
3496*7836SJohn.Forte@Sun.COM 		 */
3497*7836SJohn.Forte@Sun.COM 		*setToken = 0;
3498*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_SET_COUNT,
3499*7836SJohn.Forte@Sun.COM 		    prop) == -1) {
3500*7836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_NOT_FOUND) {
3501*7836SJohn.Forte@Sun.COM 				foundSetCnt = B_FALSE;
3502*7836SJohn.Forte@Sun.COM 			} else {
3503*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "get property failed - %s",
3504*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
3505*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
3506*7836SJohn.Forte@Sun.COM 				goto out;
3507*7836SJohn.Forte@Sun.COM 			}
3508*7836SJohn.Forte@Sun.COM 		}
3509*7836SJohn.Forte@Sun.COM 
3510*7836SJohn.Forte@Sun.COM 		if (foundSetCnt) {
3511*7836SJohn.Forte@Sun.COM 			/*
3512*7836SJohn.Forte@Sun.COM 			 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
3513*7836SJohn.Forte@Sun.COM 			 */
3514*7836SJohn.Forte@Sun.COM 			if (scf_property_get_value(prop, value) == -1) {
3515*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
3516*7836SJohn.Forte@Sun.COM 				    "get property value failed - %s",
3517*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
3518*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
3519*7836SJohn.Forte@Sun.COM 				goto out;
3520*7836SJohn.Forte@Sun.COM 			}
3521*7836SJohn.Forte@Sun.COM 
3522*7836SJohn.Forte@Sun.COM 			/*
3523*7836SJohn.Forte@Sun.COM 			 * Now get the actual value from the value handle
3524*7836SJohn.Forte@Sun.COM 			 * and set the caller's token
3525*7836SJohn.Forte@Sun.COM 			 */
3526*7836SJohn.Forte@Sun.COM 			if (scf_value_get_count(value, setToken) == -1) {
3527*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
3528*7836SJohn.Forte@Sun.COM 				    "get integer value failed - %s",
3529*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
3530*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
3531*7836SJohn.Forte@Sun.COM 				goto out;
3532*7836SJohn.Forte@Sun.COM 			}
3533*7836SJohn.Forte@Sun.COM 		}
3534*7836SJohn.Forte@Sun.COM 	}
3535*7836SJohn.Forte@Sun.COM 
3536*7836SJohn.Forte@Sun.COM 	nvlistEncoded = (char *)calloc(1,
3537*7836SJohn.Forte@Sun.COM 	    blockCnt * STMF_PROVIDER_DATA_PROP_SIZE);
3538*7836SJohn.Forte@Sun.COM 	if (nvlistEncoded == NULL) {
3539*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "nvlistEncoded alloc failed");
3540*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
3541*7836SJohn.Forte@Sun.COM 		goto out;
3542*7836SJohn.Forte@Sun.COM 	}
3543*7836SJohn.Forte@Sun.COM 
3544*7836SJohn.Forte@Sun.COM 	for (i = 0; i < blockCnt; i++) {
3545*7836SJohn.Forte@Sun.COM 		bzero(dataPropertyName, sizeof (dataPropertyName));
3546*7836SJohn.Forte@Sun.COM 		/*
3547*7836SJohn.Forte@Sun.COM 		 * create the name to use for the property
3548*7836SJohn.Forte@Sun.COM 		 */
3549*7836SJohn.Forte@Sun.COM 		(void) snprintf(dataPropertyName, sizeof (dataPropertyName),
3550*7836SJohn.Forte@Sun.COM 		    "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
3551*7836SJohn.Forte@Sun.COM 
3552*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, dataPropertyName, prop) == -1) {
3553*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
3554*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3555*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3556*7836SJohn.Forte@Sun.COM 			goto out;
3557*7836SJohn.Forte@Sun.COM 		}
3558*7836SJohn.Forte@Sun.COM 
3559*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
3560*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
3561*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3562*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3563*7836SJohn.Forte@Sun.COM 			goto out;
3564*7836SJohn.Forte@Sun.COM 		}
3565*7836SJohn.Forte@Sun.COM 
3566*7836SJohn.Forte@Sun.COM 		/*
3567*7836SJohn.Forte@Sun.COM 		 * Set the data block offset
3568*7836SJohn.Forte@Sun.COM 		 */
3569*7836SJohn.Forte@Sun.COM 		blockOffset = STMF_PROVIDER_DATA_PROP_SIZE * i;
3570*7836SJohn.Forte@Sun.COM 		actualBlockSize = scf_value_get_opaque(value,
3571*7836SJohn.Forte@Sun.COM 		    &nvlistEncoded[blockOffset], STMF_PROVIDER_DATA_PROP_SIZE);
3572*7836SJohn.Forte@Sun.COM 		if (actualBlockSize == -1) {
3573*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get opaque property value failed - %s",
3574*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3575*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3576*7836SJohn.Forte@Sun.COM 			goto out;
3577*7836SJohn.Forte@Sun.COM 		}
3578*7836SJohn.Forte@Sun.COM 		nvlistEncodedSize += actualBlockSize;
3579*7836SJohn.Forte@Sun.COM 	}
3580*7836SJohn.Forte@Sun.COM 
3581*7836SJohn.Forte@Sun.COM 	if (nvlist_unpack(nvlistEncoded, nvlistEncodedSize, nvl, 0) != 0) {
3582*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "unable to unpack nvlist");
3583*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3584*7836SJohn.Forte@Sun.COM 		goto out;
3585*7836SJohn.Forte@Sun.COM 	}
3586*7836SJohn.Forte@Sun.COM 
3587*7836SJohn.Forte@Sun.COM 
3588*7836SJohn.Forte@Sun.COM out:
3589*7836SJohn.Forte@Sun.COM 	/*
3590*7836SJohn.Forte@Sun.COM 	 * Free resources
3591*7836SJohn.Forte@Sun.COM 	 */
3592*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
3593*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
3594*7836SJohn.Forte@Sun.COM 	}
3595*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
3596*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
3597*7836SJohn.Forte@Sun.COM 	}
3598*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
3599*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
3600*7836SJohn.Forte@Sun.COM 	}
3601*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
3602*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
3603*7836SJohn.Forte@Sun.COM 	}
3604*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
3605*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
3606*7836SJohn.Forte@Sun.COM 	}
3607*7836SJohn.Forte@Sun.COM 	if (nvlistEncoded != NULL) {
3608*7836SJohn.Forte@Sun.COM 		free(nvlistEncoded);
3609*7836SJohn.Forte@Sun.COM 	}
3610*7836SJohn.Forte@Sun.COM 
3611*7836SJohn.Forte@Sun.COM 	return (ret);
3612*7836SJohn.Forte@Sun.COM 
3613*7836SJohn.Forte@Sun.COM }
3614*7836SJohn.Forte@Sun.COM /*
3615*7836SJohn.Forte@Sun.COM  * psGetProviderDataList
3616*7836SJohn.Forte@Sun.COM  *
3617*7836SJohn.Forte@Sun.COM  * Retrieves the list of providers that currently store persistent data
3618*7836SJohn.Forte@Sun.COM  *
3619*7836SJohn.Forte@Sun.COM  * providerList - pointer to a pointer to an stmfProviderList structure
3620*7836SJohn.Forte@Sun.COM  *                On success, this will contain the list of providers
3621*7836SJohn.Forte@Sun.COM  *                currently storing persistent data.
3622*7836SJohn.Forte@Sun.COM  */
3623*7836SJohn.Forte@Sun.COM int
3624*7836SJohn.Forte@Sun.COM psGetProviderDataList(stmfProviderList **providerList)
3625*7836SJohn.Forte@Sun.COM {
3626*7836SJohn.Forte@Sun.COM 	scf_handle_t *handle = NULL;
3627*7836SJohn.Forte@Sun.COM 	scf_service_t *svc = NULL;
3628*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t *pg = NULL;
3629*7836SJohn.Forte@Sun.COM 	scf_property_t *prop = NULL;
3630*7836SJohn.Forte@Sun.COM 	scf_value_t *value = NULL;
3631*7836SJohn.Forte@Sun.COM 	scf_iter_t *pgIter = NULL;
3632*7836SJohn.Forte@Sun.COM 	char buf[MAXNAMELEN];
3633*7836SJohn.Forte@Sun.COM 	int providerCnt = 0;
3634*7836SJohn.Forte@Sun.COM 	int64_t providerType;
3635*7836SJohn.Forte@Sun.COM 	int i = 0, j;
3636*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
3637*7836SJohn.Forte@Sun.COM 
3638*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
3639*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3640*7836SJohn.Forte@Sun.COM 		goto out;
3641*7836SJohn.Forte@Sun.COM 	}
3642*7836SJohn.Forte@Sun.COM 
3643*7836SJohn.Forte@Sun.COM 	*providerList = NULL;
3644*7836SJohn.Forte@Sun.COM 
3645*7836SJohn.Forte@Sun.COM 	/*
3646*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
3647*7836SJohn.Forte@Sun.COM 	 */
3648*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
3649*7836SJohn.Forte@Sun.COM 	    ((value = scf_value_create(handle)) == NULL) ||
3650*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
3651*7836SJohn.Forte@Sun.COM 	    ((pgIter = scf_iter_create(handle)) == NULL)) {
3652*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
3653*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3654*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3655*7836SJohn.Forte@Sun.COM 		goto out;
3656*7836SJohn.Forte@Sun.COM 	}
3657*7836SJohn.Forte@Sun.COM 
3658*7836SJohn.Forte@Sun.COM 	/*
3659*7836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
3660*7836SJohn.Forte@Sun.COM 	 */
3661*7836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
3662*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
3663*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3664*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3665*7836SJohn.Forte@Sun.COM 		goto out;
3666*7836SJohn.Forte@Sun.COM 	}
3667*7836SJohn.Forte@Sun.COM 
3668*7836SJohn.Forte@Sun.COM 	while (scf_iter_next_pg(pgIter, pg) == 1) {
3669*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
3670*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
3671*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3672*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3673*7836SJohn.Forte@Sun.COM 			break;
3674*7836SJohn.Forte@Sun.COM 		}
3675*7836SJohn.Forte@Sun.COM 		/*
3676*7836SJohn.Forte@Sun.COM 		 * Only count LU property groups
3677*7836SJohn.Forte@Sun.COM 		 */
3678*7836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_PROVIDER_DATA_PREFIX,
3679*7836SJohn.Forte@Sun.COM 		    strlen(STMF_PROVIDER_DATA_PREFIX)) == 0) {
3680*7836SJohn.Forte@Sun.COM 			providerCnt++;
3681*7836SJohn.Forte@Sun.COM 		}
3682*7836SJohn.Forte@Sun.COM 	}
3683*7836SJohn.Forte@Sun.COM 
3684*7836SJohn.Forte@Sun.COM 	/*
3685*7836SJohn.Forte@Sun.COM 	 * pgIter is the iterator handle
3686*7836SJohn.Forte@Sun.COM 	 */
3687*7836SJohn.Forte@Sun.COM 	if (scf_iter_service_pgs(pgIter, svc) == -1) {
3688*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "iter property groups failed - %s",
3689*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3690*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3691*7836SJohn.Forte@Sun.COM 		goto out;
3692*7836SJohn.Forte@Sun.COM 	}
3693*7836SJohn.Forte@Sun.COM 
3694*7836SJohn.Forte@Sun.COM 	*providerList = (stmfProviderList *)calloc(1,
3695*7836SJohn.Forte@Sun.COM 	    sizeof (stmfProviderList) + providerCnt * sizeof (stmfProvider));
3696*7836SJohn.Forte@Sun.COM 	if (*providerList == NULL) {
3697*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
3698*7836SJohn.Forte@Sun.COM 		goto out;
3699*7836SJohn.Forte@Sun.COM 	}
3700*7836SJohn.Forte@Sun.COM 
3701*7836SJohn.Forte@Sun.COM 	/*
3702*7836SJohn.Forte@Sun.COM 	 * it's possible for entries to be added/removed while we're retrieving
3703*7836SJohn.Forte@Sun.COM 	 * the property groups. Just make sure we don't write beyond our
3704*7836SJohn.Forte@Sun.COM 	 * allocated buffer by checking to ensure i < providerCnt.
3705*7836SJohn.Forte@Sun.COM 	 */
3706*7836SJohn.Forte@Sun.COM 	while ((scf_iter_next_pg(pgIter, pg) == 1) && (i < providerCnt)) {
3707*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_name(pg, buf, sizeof (buf)) == -1) {
3708*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get name failed - %s",
3709*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3710*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3711*7836SJohn.Forte@Sun.COM 			break;
3712*7836SJohn.Forte@Sun.COM 		}
3713*7836SJohn.Forte@Sun.COM 		/*
3714*7836SJohn.Forte@Sun.COM 		 * Only use provider data property groups
3715*7836SJohn.Forte@Sun.COM 		 */
3716*7836SJohn.Forte@Sun.COM 		if (strncmp(buf, STMF_PROVIDER_DATA_PREFIX,
3717*7836SJohn.Forte@Sun.COM 		    strlen(STMF_PROVIDER_DATA_PREFIX)) != 0) {
3718*7836SJohn.Forte@Sun.COM 			continue;
3719*7836SJohn.Forte@Sun.COM 		}
3720*7836SJohn.Forte@Sun.COM 
3721*7836SJohn.Forte@Sun.COM 		/*
3722*7836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_TYPE property
3723*7836SJohn.Forte@Sun.COM 		 */
3724*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_TYPE,
3725*7836SJohn.Forte@Sun.COM 		    prop) == -1) {
3726*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
3727*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3728*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3729*7836SJohn.Forte@Sun.COM 			break;
3730*7836SJohn.Forte@Sun.COM 		}
3731*7836SJohn.Forte@Sun.COM 
3732*7836SJohn.Forte@Sun.COM 		/*
3733*7836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_TYPE value
3734*7836SJohn.Forte@Sun.COM 		 */
3735*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value) == -1) {
3736*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
3737*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3738*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3739*7836SJohn.Forte@Sun.COM 			break;
3740*7836SJohn.Forte@Sun.COM 		}
3741*7836SJohn.Forte@Sun.COM 
3742*7836SJohn.Forte@Sun.COM 		/*
3743*7836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
3744*7836SJohn.Forte@Sun.COM 		 */
3745*7836SJohn.Forte@Sun.COM 		if (scf_value_get_integer(value, &providerType) == -1) {
3746*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get integer value failed - %s",
3747*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3748*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3749*7836SJohn.Forte@Sun.COM 			break;
3750*7836SJohn.Forte@Sun.COM 		}
3751*7836SJohn.Forte@Sun.COM 
3752*7836SJohn.Forte@Sun.COM 		(*providerList)->provider[i].providerType = providerType;
3753*7836SJohn.Forte@Sun.COM 
3754*7836SJohn.Forte@Sun.COM 		/* determine offset for copy of provider name */
3755*7836SJohn.Forte@Sun.COM 		j = strlen(STMF_PROVIDER_DATA_PREFIX);
3756*7836SJohn.Forte@Sun.COM 
3757*7836SJohn.Forte@Sun.COM 		/* copy provider name to caller's list */
3758*7836SJohn.Forte@Sun.COM 		(void) strncpy((*providerList)->provider[i].name, buf + j,
3759*7836SJohn.Forte@Sun.COM 		    sizeof ((*providerList)->provider[i].name));
3760*7836SJohn.Forte@Sun.COM 		i++;
3761*7836SJohn.Forte@Sun.COM 		(*providerList)->cnt++;
3762*7836SJohn.Forte@Sun.COM 	}
3763*7836SJohn.Forte@Sun.COM 
3764*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3765*7836SJohn.Forte@Sun.COM 		free(*providerList);
3766*7836SJohn.Forte@Sun.COM 		goto out;
3767*7836SJohn.Forte@Sun.COM 	}
3768*7836SJohn.Forte@Sun.COM 
3769*7836SJohn.Forte@Sun.COM out:
3770*7836SJohn.Forte@Sun.COM 	/*
3771*7836SJohn.Forte@Sun.COM 	 * Free resources
3772*7836SJohn.Forte@Sun.COM 	 */
3773*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
3774*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
3775*7836SJohn.Forte@Sun.COM 	}
3776*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
3777*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
3778*7836SJohn.Forte@Sun.COM 	}
3779*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
3780*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
3781*7836SJohn.Forte@Sun.COM 	}
3782*7836SJohn.Forte@Sun.COM 	if (value != NULL) {
3783*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value);
3784*7836SJohn.Forte@Sun.COM 	}
3785*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
3786*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
3787*7836SJohn.Forte@Sun.COM 	}
3788*7836SJohn.Forte@Sun.COM 	if (pgIter != NULL) {
3789*7836SJohn.Forte@Sun.COM 		scf_iter_destroy(pgIter);
3790*7836SJohn.Forte@Sun.COM 	}
3791*7836SJohn.Forte@Sun.COM 
3792*7836SJohn.Forte@Sun.COM 	return (ret);
3793*7836SJohn.Forte@Sun.COM }
3794*7836SJohn.Forte@Sun.COM 
3795*7836SJohn.Forte@Sun.COM 
3796*7836SJohn.Forte@Sun.COM /*
3797*7836SJohn.Forte@Sun.COM  * psSetProviderData
3798*7836SJohn.Forte@Sun.COM  *
3799*7836SJohn.Forte@Sun.COM  * Stores a packed nvlist on a per provider basis
3800*7836SJohn.Forte@Sun.COM  *
3801*7836SJohn.Forte@Sun.COM  * providerName - property group name to use
3802*7836SJohn.Forte@Sun.COM  * nvl - nvlist to store
3803*7836SJohn.Forte@Sun.COM  * providerType - type of provider (logical unit or port)
3804*7836SJohn.Forte@Sun.COM  *
3805*7836SJohn.Forte@Sun.COM  */
3806*7836SJohn.Forte@Sun.COM int
3807*7836SJohn.Forte@Sun.COM psSetProviderData(char *providerName, nvlist_t *nvl, int providerType,
3808*7836SJohn.Forte@Sun.COM     uint64_t *setToken)
3809*7836SJohn.Forte@Sun.COM {
3810*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
3811*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
3812*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
3813*7836SJohn.Forte@Sun.COM 	scf_property_t	*prop = NULL;
3814*7836SJohn.Forte@Sun.COM 	scf_transaction_t *tran = NULL;
3815*7836SJohn.Forte@Sun.COM 	/* represents arrays of entry and value pointers for scf */
3816*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t	**addEntry = NULL;
3817*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t	**deleteEntry = NULL;
3818*7836SJohn.Forte@Sun.COM 	scf_value_t **addValue = NULL;
3819*7836SJohn.Forte@Sun.COM 
3820*7836SJohn.Forte@Sun.COM 	/*
3821*7836SJohn.Forte@Sun.COM 	 * These declarations are for known entry and value set/get
3822*7836SJohn.Forte@Sun.COM 	 * operations
3823*7836SJohn.Forte@Sun.COM 	 */
3824*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry1 = NULL;
3825*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry2 = NULL;
3826*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry3 = NULL;
3827*7836SJohn.Forte@Sun.COM 	scf_transaction_entry_t *entry5 = NULL;
3828*7836SJohn.Forte@Sun.COM 	scf_value_t *value1 = NULL;
3829*7836SJohn.Forte@Sun.COM 	scf_value_t *value2 = NULL;
3830*7836SJohn.Forte@Sun.COM 	scf_value_t *value3 = NULL;
3831*7836SJohn.Forte@Sun.COM 	scf_value_t *value4 = NULL;
3832*7836SJohn.Forte@Sun.COM 	scf_value_t *value5 = NULL;
3833*7836SJohn.Forte@Sun.COM 
3834*7836SJohn.Forte@Sun.COM 	boolean_t newPg = B_FALSE;
3835*7836SJohn.Forte@Sun.COM 	char pgName[MAXPATHLEN];
3836*7836SJohn.Forte@Sun.COM 	char dataPropertyName[STMF_PROVIDER_DATA_PROP_NAME_SIZE];
3837*7836SJohn.Forte@Sun.COM 	char *nvlistEncoded = NULL;
3838*7836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
3839*7836SJohn.Forte@Sun.COM 	size_t blockSize;
3840*7836SJohn.Forte@Sun.COM 	int i, j = 0;
3841*7836SJohn.Forte@Sun.COM 	int addEntryAlloc = 0, deleteEntryAlloc = 0, addValueAlloc = 0;
3842*7836SJohn.Forte@Sun.COM 	int blockOffset;
3843*7836SJohn.Forte@Sun.COM 	uint64_t oldBlockCnt = 0;
3844*7836SJohn.Forte@Sun.COM 	uint64_t blockCnt = 0;
3845*7836SJohn.Forte@Sun.COM 	uint64_t setCnt = 0;
3846*7836SJohn.Forte@Sun.COM 	boolean_t foundSetCnt = B_TRUE;
3847*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
3848*7836SJohn.Forte@Sun.COM 	int commitRet;
3849*7836SJohn.Forte@Sun.COM 
3850*7836SJohn.Forte@Sun.COM 	if (providerName == NULL || (providerType != STMF_LU_PROVIDER_TYPE &&
3851*7836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE)) {
3852*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_INVALID_ARG;
3853*7836SJohn.Forte@Sun.COM 		goto out;
3854*7836SJohn.Forte@Sun.COM 	}
3855*7836SJohn.Forte@Sun.COM 
3856*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
3857*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
3858*7836SJohn.Forte@Sun.COM 		goto out;
3859*7836SJohn.Forte@Sun.COM 	}
3860*7836SJohn.Forte@Sun.COM 
3861*7836SJohn.Forte@Sun.COM 	bzero(pgName, sizeof (pgName));
3862*7836SJohn.Forte@Sun.COM 	/*
3863*7836SJohn.Forte@Sun.COM 	 * create the property group name
3864*7836SJohn.Forte@Sun.COM 	 */
3865*7836SJohn.Forte@Sun.COM 	(void) snprintf(pgName, sizeof (pgName), "%s%s",
3866*7836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PREFIX, providerName);
3867*7836SJohn.Forte@Sun.COM 
3868*7836SJohn.Forte@Sun.COM 	/*
3869*7836SJohn.Forte@Sun.COM 	 * Allocate scf resources
3870*7836SJohn.Forte@Sun.COM 	 */
3871*7836SJohn.Forte@Sun.COM 	if (((pg = scf_pg_create(handle)) == NULL) ||
3872*7836SJohn.Forte@Sun.COM 	    ((entry1 = scf_entry_create(handle)) == NULL) ||
3873*7836SJohn.Forte@Sun.COM 	    ((entry2 = scf_entry_create(handle)) == NULL) ||
3874*7836SJohn.Forte@Sun.COM 	    ((entry3 = scf_entry_create(handle)) == NULL) ||
3875*7836SJohn.Forte@Sun.COM 	    ((entry5 = scf_entry_create(handle)) == NULL) ||
3876*7836SJohn.Forte@Sun.COM 	    ((value1 = scf_value_create(handle)) == NULL) ||
3877*7836SJohn.Forte@Sun.COM 	    ((value2 = scf_value_create(handle)) == NULL) ||
3878*7836SJohn.Forte@Sun.COM 	    ((value3 = scf_value_create(handle)) == NULL) ||
3879*7836SJohn.Forte@Sun.COM 	    ((value4 = scf_value_create(handle)) == NULL) ||
3880*7836SJohn.Forte@Sun.COM 	    ((value5 = scf_value_create(handle)) == NULL) ||
3881*7836SJohn.Forte@Sun.COM 	    ((prop = scf_property_create(handle)) == NULL) ||
3882*7836SJohn.Forte@Sun.COM 	    ((tran = scf_transaction_create(handle)) == NULL)) {
3883*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf alloc resource failed - %s",
3884*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3885*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3886*7836SJohn.Forte@Sun.COM 		goto out;
3887*7836SJohn.Forte@Sun.COM 	}
3888*7836SJohn.Forte@Sun.COM 
3889*7836SJohn.Forte@Sun.COM 	/*
3890*7836SJohn.Forte@Sun.COM 	 * Get the existing property group
3891*7836SJohn.Forte@Sun.COM 	 */
3892*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, pgName, pg) == -1) {
3893*7836SJohn.Forte@Sun.COM 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
3894*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
3895*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3896*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3897*7836SJohn.Forte@Sun.COM 			goto out;
3898*7836SJohn.Forte@Sun.COM 		} else {
3899*7836SJohn.Forte@Sun.COM 			/*
3900*7836SJohn.Forte@Sun.COM 			 * create the property group.
3901*7836SJohn.Forte@Sun.COM 			 */
3902*7836SJohn.Forte@Sun.COM 			if (scf_service_add_pg(svc, pgName,
3903*7836SJohn.Forte@Sun.COM 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
3904*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR, "add pg failed - %s",
3905*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
3906*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
3907*7836SJohn.Forte@Sun.COM 				goto out;
3908*7836SJohn.Forte@Sun.COM 			}
3909*7836SJohn.Forte@Sun.COM 			newPg = B_TRUE;
3910*7836SJohn.Forte@Sun.COM 		}
3911*7836SJohn.Forte@Sun.COM 	}
3912*7836SJohn.Forte@Sun.COM 
3913*7836SJohn.Forte@Sun.COM 	/*
3914*7836SJohn.Forte@Sun.COM 	 * Begin the transaction
3915*7836SJohn.Forte@Sun.COM 	 */
3916*7836SJohn.Forte@Sun.COM 	if (scf_transaction_start(tran, pg) == -1) {
3917*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "start transaction failed - %s",
3918*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
3919*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
3920*7836SJohn.Forte@Sun.COM 		goto out;
3921*7836SJohn.Forte@Sun.COM 	}
3922*7836SJohn.Forte@Sun.COM 
3923*7836SJohn.Forte@Sun.COM 	if (!newPg) {
3924*7836SJohn.Forte@Sun.COM 		/*
3925*7836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_COUNT property
3926*7836SJohn.Forte@Sun.COM 		 */
3927*7836SJohn.Forte@Sun.COM 		if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_COUNT,
3928*7836SJohn.Forte@Sun.COM 		    prop) == -1) {
3929*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
3930*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3931*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3932*7836SJohn.Forte@Sun.COM 			goto out;
3933*7836SJohn.Forte@Sun.COM 		}
3934*7836SJohn.Forte@Sun.COM 
3935*7836SJohn.Forte@Sun.COM 		/*
3936*7836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_COUNT value
3937*7836SJohn.Forte@Sun.COM 		 */
3938*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value4) == -1) {
3939*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property value failed - %s",
3940*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3941*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3942*7836SJohn.Forte@Sun.COM 			goto out;
3943*7836SJohn.Forte@Sun.COM 		}
3944*7836SJohn.Forte@Sun.COM 
3945*7836SJohn.Forte@Sun.COM 		/*
3946*7836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
3947*7836SJohn.Forte@Sun.COM 		 */
3948*7836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value4, &oldBlockCnt) == -1) {
3949*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get integer value failed - %s",
3950*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3951*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3952*7836SJohn.Forte@Sun.COM 			goto out;
3953*7836SJohn.Forte@Sun.COM 		}
3954*7836SJohn.Forte@Sun.COM 	}
3955*7836SJohn.Forte@Sun.COM 
3956*7836SJohn.Forte@Sun.COM 	/*
3957*7836SJohn.Forte@Sun.COM 	 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
3958*7836SJohn.Forte@Sun.COM 	 * If it doesn't exist, we'll create it later after successfully
3959*7836SJohn.Forte@Sun.COM 	 * setting the data.
3960*7836SJohn.Forte@Sun.COM 	 */
3961*7836SJohn.Forte@Sun.COM 	if (scf_pg_get_property(pg, STMF_PROVIDER_DATA_PROP_SET_COUNT,
3962*7836SJohn.Forte@Sun.COM 	    prop) == -1) {
3963*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
3964*7836SJohn.Forte@Sun.COM 			foundSetCnt = B_FALSE;
3965*7836SJohn.Forte@Sun.COM 		} else {
3966*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
3967*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3968*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3969*7836SJohn.Forte@Sun.COM 			goto out;
3970*7836SJohn.Forte@Sun.COM 		}
3971*7836SJohn.Forte@Sun.COM 	}
3972*7836SJohn.Forte@Sun.COM 
3973*7836SJohn.Forte@Sun.COM 	if (foundSetCnt) {
3974*7836SJohn.Forte@Sun.COM 		/*
3975*7836SJohn.Forte@Sun.COM 		 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
3976*7836SJohn.Forte@Sun.COM 		 */
3977*7836SJohn.Forte@Sun.COM 		if (scf_property_get_value(prop, value5) == -1) {
3978*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
3979*7836SJohn.Forte@Sun.COM 			    "get property value failed - %s",
3980*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3981*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3982*7836SJohn.Forte@Sun.COM 			goto out;
3983*7836SJohn.Forte@Sun.COM 		}
3984*7836SJohn.Forte@Sun.COM 
3985*7836SJohn.Forte@Sun.COM 		/*
3986*7836SJohn.Forte@Sun.COM 		 * Now get the actual value from the value handle
3987*7836SJohn.Forte@Sun.COM 		 */
3988*7836SJohn.Forte@Sun.COM 		if (scf_value_get_count(value5, &setCnt) == -1) {
3989*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR,
3990*7836SJohn.Forte@Sun.COM 			    "get integer value failed - %s",
3991*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
3992*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
3993*7836SJohn.Forte@Sun.COM 			goto out;
3994*7836SJohn.Forte@Sun.COM 		}
3995*7836SJohn.Forte@Sun.COM 
3996*7836SJohn.Forte@Sun.COM 		/*
3997*7836SJohn.Forte@Sun.COM 		 * Compare the setCnt prop to the caller's.
3998*7836SJohn.Forte@Sun.COM 		 */
3999*7836SJohn.Forte@Sun.COM 		if (setToken && (*setToken != setCnt)) {
4000*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_PROV_DATA_STALE;
4001*7836SJohn.Forte@Sun.COM 			goto out;
4002*7836SJohn.Forte@Sun.COM 		}
4003*7836SJohn.Forte@Sun.COM 	}
4004*7836SJohn.Forte@Sun.COM 
4005*7836SJohn.Forte@Sun.COM 	setCnt++;
4006*7836SJohn.Forte@Sun.COM 
4007*7836SJohn.Forte@Sun.COM 	/*
4008*7836SJohn.Forte@Sun.COM 	 * prepare the list for writing
4009*7836SJohn.Forte@Sun.COM 	 */
4010*7836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &nvlistEncoded, &nvlistEncodedSize,
4011*7836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
4012*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "nvlist_pack failed");
4013*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
4014*7836SJohn.Forte@Sun.COM 		goto out;
4015*7836SJohn.Forte@Sun.COM 	}
4016*7836SJohn.Forte@Sun.COM 
4017*7836SJohn.Forte@Sun.COM 	/* Determine how many chunks we need to write */
4018*7836SJohn.Forte@Sun.COM 	blockCnt = nvlistEncodedSize/STMF_PROVIDER_DATA_PROP_SIZE;
4019*7836SJohn.Forte@Sun.COM 	if (nvlistEncodedSize % STMF_PROVIDER_DATA_PROP_SIZE)
4020*7836SJohn.Forte@Sun.COM 		blockCnt++;
4021*7836SJohn.Forte@Sun.COM 
4022*7836SJohn.Forte@Sun.COM 	/* allocate entry and value resources for writing those chunks */
4023*7836SJohn.Forte@Sun.COM 	addEntry = (scf_transaction_entry_t **)calloc(1, sizeof (*addEntry)
4024*7836SJohn.Forte@Sun.COM 	    * blockCnt);
4025*7836SJohn.Forte@Sun.COM 	if (addEntry == NULL) {
4026*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "addEntry alloc failed");
4027*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
4028*7836SJohn.Forte@Sun.COM 		goto out;
4029*7836SJohn.Forte@Sun.COM 	}
4030*7836SJohn.Forte@Sun.COM 
4031*7836SJohn.Forte@Sun.COM 	addValue = (scf_value_t **)calloc(1, sizeof (*addValue)
4032*7836SJohn.Forte@Sun.COM 	    * blockCnt);
4033*7836SJohn.Forte@Sun.COM 	if (addValue == NULL) {
4034*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "value alloc failed");
4035*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR_NOMEM;
4036*7836SJohn.Forte@Sun.COM 		goto out;
4037*7836SJohn.Forte@Sun.COM 	}
4038*7836SJohn.Forte@Sun.COM 
4039*7836SJohn.Forte@Sun.COM 	/*
4040*7836SJohn.Forte@Sun.COM 	 * allocate entry delete resources for deleting anything existing
4041*7836SJohn.Forte@Sun.COM 	 * that is more than the new block count. We could leave them around
4042*7836SJohn.Forte@Sun.COM 	 * without suffering any ill effects but it will be cleaner to look at
4043*7836SJohn.Forte@Sun.COM 	 * in smf tools if they are deleted.
4044*7836SJohn.Forte@Sun.COM 	 */
4045*7836SJohn.Forte@Sun.COM 	if (oldBlockCnt > blockCnt) {
4046*7836SJohn.Forte@Sun.COM 		deleteEntry = (scf_transaction_entry_t **)calloc(1,
4047*7836SJohn.Forte@Sun.COM 		    sizeof (*deleteEntry) * (oldBlockCnt - blockCnt));
4048*7836SJohn.Forte@Sun.COM 		if (deleteEntry == NULL) {
4049*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "deleteEntry alloc failed");
4050*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOMEM;
4051*7836SJohn.Forte@Sun.COM 			goto out;
4052*7836SJohn.Forte@Sun.COM 		}
4053*7836SJohn.Forte@Sun.COM 		deleteEntryAlloc = oldBlockCnt - blockCnt;
4054*7836SJohn.Forte@Sun.COM 	}
4055*7836SJohn.Forte@Sun.COM 
4056*7836SJohn.Forte@Sun.COM 
4057*7836SJohn.Forte@Sun.COM 	for (i = 0; i < blockCnt; i++) {
4058*7836SJohn.Forte@Sun.COM 		/*
4059*7836SJohn.Forte@Sun.COM 		 * Create the entry resource for the prop
4060*7836SJohn.Forte@Sun.COM 		 */
4061*7836SJohn.Forte@Sun.COM 		addEntry[i] = scf_entry_create(handle);
4062*7836SJohn.Forte@Sun.COM 		if (addEntry[i] == NULL) {
4063*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
4064*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4065*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4066*7836SJohn.Forte@Sun.COM 			goto out;
4067*7836SJohn.Forte@Sun.COM 		}
4068*7836SJohn.Forte@Sun.COM 
4069*7836SJohn.Forte@Sun.COM 		/* bump alloc count for addEntry allocation */
4070*7836SJohn.Forte@Sun.COM 		addEntryAlloc++;
4071*7836SJohn.Forte@Sun.COM 
4072*7836SJohn.Forte@Sun.COM 		/*
4073*7836SJohn.Forte@Sun.COM 		 * create the name to use for the property
4074*7836SJohn.Forte@Sun.COM 		 */
4075*7836SJohn.Forte@Sun.COM 		(void) snprintf(dataPropertyName, sizeof (dataPropertyName),
4076*7836SJohn.Forte@Sun.COM 		    "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
4077*7836SJohn.Forte@Sun.COM 
4078*7836SJohn.Forte@Sun.COM 		/*
4079*7836SJohn.Forte@Sun.COM 		 * Create the new property
4080*7836SJohn.Forte@Sun.COM 		 */
4081*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, addEntry[i],
4082*7836SJohn.Forte@Sun.COM 		    dataPropertyName, SCF_TYPE_OPAQUE) == -1) {
4083*7836SJohn.Forte@Sun.COM 			if (scf_error() == SCF_ERROR_EXISTS) {
4084*7836SJohn.Forte@Sun.COM 				if (scf_transaction_property_change(tran,
4085*7836SJohn.Forte@Sun.COM 				    addEntry[i], dataPropertyName,
4086*7836SJohn.Forte@Sun.COM 				    SCF_TYPE_OPAQUE) == -1) {
4087*7836SJohn.Forte@Sun.COM 					syslog(LOG_ERR, "transaction property"
4088*7836SJohn.Forte@Sun.COM 					    "change failed - %s",
4089*7836SJohn.Forte@Sun.COM 					    scf_strerror(scf_error()));
4090*7836SJohn.Forte@Sun.COM 					ret = STMF_PS_ERROR;
4091*7836SJohn.Forte@Sun.COM 					goto out;
4092*7836SJohn.Forte@Sun.COM 				}
4093*7836SJohn.Forte@Sun.COM 			} else {
4094*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
4095*7836SJohn.Forte@Sun.COM 				    "transaction property new failed - %s",
4096*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
4097*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
4098*7836SJohn.Forte@Sun.COM 				goto out;
4099*7836SJohn.Forte@Sun.COM 			}
4100*7836SJohn.Forte@Sun.COM 		}
4101*7836SJohn.Forte@Sun.COM 		/*
4102*7836SJohn.Forte@Sun.COM 		 * Create the value resource for the prop
4103*7836SJohn.Forte@Sun.COM 		 */
4104*7836SJohn.Forte@Sun.COM 		addValue[i] = scf_value_create(handle);
4105*7836SJohn.Forte@Sun.COM 		if (addValue[i] == NULL) {
4106*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
4107*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4108*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4109*7836SJohn.Forte@Sun.COM 			goto out;
4110*7836SJohn.Forte@Sun.COM 		}
4111*7836SJohn.Forte@Sun.COM 
4112*7836SJohn.Forte@Sun.COM 		/* bump alloc count for addValue allocation */
4113*7836SJohn.Forte@Sun.COM 		addValueAlloc++;
4114*7836SJohn.Forte@Sun.COM 
4115*7836SJohn.Forte@Sun.COM 		/*
4116*7836SJohn.Forte@Sun.COM 		 * Set the data block offset and size
4117*7836SJohn.Forte@Sun.COM 		 */
4118*7836SJohn.Forte@Sun.COM 		if ((STMF_PROVIDER_DATA_PROP_SIZE * (i + 1))
4119*7836SJohn.Forte@Sun.COM 		    > nvlistEncodedSize) {
4120*7836SJohn.Forte@Sun.COM 			blockSize = nvlistEncodedSize
4121*7836SJohn.Forte@Sun.COM 			    - STMF_PROVIDER_DATA_PROP_SIZE * i;
4122*7836SJohn.Forte@Sun.COM 		} else {
4123*7836SJohn.Forte@Sun.COM 			blockSize = STMF_PROVIDER_DATA_PROP_SIZE;
4124*7836SJohn.Forte@Sun.COM 		}
4125*7836SJohn.Forte@Sun.COM 
4126*7836SJohn.Forte@Sun.COM 		blockOffset = STMF_PROVIDER_DATA_PROP_SIZE * i;
4127*7836SJohn.Forte@Sun.COM 		if (scf_value_set_opaque(addValue[i],
4128*7836SJohn.Forte@Sun.COM 		    &nvlistEncoded[blockOffset], blockSize) == -1) {
4129*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
4130*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4131*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4132*7836SJohn.Forte@Sun.COM 			goto out;
4133*7836SJohn.Forte@Sun.COM 		}
4134*7836SJohn.Forte@Sun.COM 
4135*7836SJohn.Forte@Sun.COM 		/*
4136*7836SJohn.Forte@Sun.COM 		 * Add the data block to the transaction entry
4137*7836SJohn.Forte@Sun.COM 		 */
4138*7836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(addEntry[i], addValue[i]) == -1) {
4139*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
4140*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4141*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4142*7836SJohn.Forte@Sun.COM 			goto out;
4143*7836SJohn.Forte@Sun.COM 		}
4144*7836SJohn.Forte@Sun.COM 	}
4145*7836SJohn.Forte@Sun.COM 
4146*7836SJohn.Forte@Sun.COM 	/*
4147*7836SJohn.Forte@Sun.COM 	 * Now we need to delete any chunks (properties) that are no longer
4148*7836SJohn.Forte@Sun.COM 	 * needed. Iterate through the rest of the chunks deleting each.
4149*7836SJohn.Forte@Sun.COM 	 */
4150*7836SJohn.Forte@Sun.COM 	for (i = blockCnt; i < oldBlockCnt; i++) {
4151*7836SJohn.Forte@Sun.COM 		/*
4152*7836SJohn.Forte@Sun.COM 		 * Create the entry resource for the prop
4153*7836SJohn.Forte@Sun.COM 		 */
4154*7836SJohn.Forte@Sun.COM 		deleteEntry[j] = scf_entry_create(handle);
4155*7836SJohn.Forte@Sun.COM 		if (deleteEntry[j] == NULL) {
4156*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "scf value alloc failed - %s",
4157*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4158*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4159*7836SJohn.Forte@Sun.COM 			goto out;
4160*7836SJohn.Forte@Sun.COM 		}
4161*7836SJohn.Forte@Sun.COM 
4162*7836SJohn.Forte@Sun.COM 		/*
4163*7836SJohn.Forte@Sun.COM 		 * create the name to use for the property
4164*7836SJohn.Forte@Sun.COM 		 */
4165*7836SJohn.Forte@Sun.COM 		(void) snprintf(dataPropertyName, sizeof (dataPropertyName),
4166*7836SJohn.Forte@Sun.COM 		    "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
4167*7836SJohn.Forte@Sun.COM 
4168*7836SJohn.Forte@Sun.COM 		/*
4169*7836SJohn.Forte@Sun.COM 		 * Delete the existing property
4170*7836SJohn.Forte@Sun.COM 		 */
4171*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_delete(tran, deleteEntry[j++],
4172*7836SJohn.Forte@Sun.COM 		    dataPropertyName) == -1) {
4173*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get property failed - %s",
4174*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4175*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4176*7836SJohn.Forte@Sun.COM 			goto out;
4177*7836SJohn.Forte@Sun.COM 		}
4178*7836SJohn.Forte@Sun.COM 	}
4179*7836SJohn.Forte@Sun.COM 
4180*7836SJohn.Forte@Sun.COM 	if (newPg) {
4181*7836SJohn.Forte@Sun.COM 		/*
4182*7836SJohn.Forte@Sun.COM 		 * Ensure the read_authorization property is set
4183*7836SJohn.Forte@Sun.COM 		 * for the group
4184*7836SJohn.Forte@Sun.COM 		 */
4185*7836SJohn.Forte@Sun.COM 		if (scf_transaction_property_new(tran, entry1,
4186*7836SJohn.Forte@Sun.COM 		    "read_authorization", SCF_TYPE_ASTRING) == -1) {
4187*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
4188*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4189*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4190*7836SJohn.Forte@Sun.COM 			goto out;
4191*7836SJohn.Forte@Sun.COM 		}
4192*7836SJohn.Forte@Sun.COM 
4193*7836SJohn.Forte@Sun.COM 		if (scf_value_set_astring(value1, STMF_SMF_READ_ATTR) == -1) {
4194*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "set value failed - %s",
4195*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4196*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4197*7836SJohn.Forte@Sun.COM 			goto out;
4198*7836SJohn.Forte@Sun.COM 		}
4199*7836SJohn.Forte@Sun.COM 
4200*7836SJohn.Forte@Sun.COM 		if (scf_entry_add_value(entry1, value1) == -1) {
4201*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add value failed - %s",
4202*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4203*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4204*7836SJohn.Forte@Sun.COM 			goto out;
4205*7836SJohn.Forte@Sun.COM 		}
4206*7836SJohn.Forte@Sun.COM 	}
4207*7836SJohn.Forte@Sun.COM 
4208*7836SJohn.Forte@Sun.COM 	/* create or change the count property */
4209*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry2,
4210*7836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PROP_COUNT, SCF_TYPE_COUNT) == -1) {
4211*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
4212*7836SJohn.Forte@Sun.COM 			if (scf_transaction_property_change(tran, entry2,
4213*7836SJohn.Forte@Sun.COM 			    STMF_PROVIDER_DATA_PROP_COUNT,
4214*7836SJohn.Forte@Sun.COM 			    SCF_TYPE_COUNT) == -1) {
4215*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
4216*7836SJohn.Forte@Sun.COM 				    "transaction property change failed - %s",
4217*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
4218*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
4219*7836SJohn.Forte@Sun.COM 				goto out;
4220*7836SJohn.Forte@Sun.COM 			}
4221*7836SJohn.Forte@Sun.COM 		} else {
4222*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
4223*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4224*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4225*7836SJohn.Forte@Sun.COM 			goto out;
4226*7836SJohn.Forte@Sun.COM 		}
4227*7836SJohn.Forte@Sun.COM 	}
4228*7836SJohn.Forte@Sun.COM 
4229*7836SJohn.Forte@Sun.COM 	scf_value_set_count(value2, blockCnt);
4230*7836SJohn.Forte@Sun.COM 
4231*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry2, value2) == -1) {
4232*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
4233*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4234*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4235*7836SJohn.Forte@Sun.COM 		goto out;
4236*7836SJohn.Forte@Sun.COM 	}
4237*7836SJohn.Forte@Sun.COM 
4238*7836SJohn.Forte@Sun.COM 	/* create or change the set count property */
4239*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry5,
4240*7836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PROP_SET_COUNT, SCF_TYPE_COUNT) == -1) {
4241*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
4242*7836SJohn.Forte@Sun.COM 			if (scf_transaction_property_change(tran, entry5,
4243*7836SJohn.Forte@Sun.COM 			    STMF_PROVIDER_DATA_PROP_SET_COUNT,
4244*7836SJohn.Forte@Sun.COM 			    SCF_TYPE_COUNT) == -1) {
4245*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
4246*7836SJohn.Forte@Sun.COM 				    "transaction property change failed - %s",
4247*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
4248*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
4249*7836SJohn.Forte@Sun.COM 				goto out;
4250*7836SJohn.Forte@Sun.COM 			}
4251*7836SJohn.Forte@Sun.COM 		} else {
4252*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
4253*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4254*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4255*7836SJohn.Forte@Sun.COM 			goto out;
4256*7836SJohn.Forte@Sun.COM 		}
4257*7836SJohn.Forte@Sun.COM 	}
4258*7836SJohn.Forte@Sun.COM 
4259*7836SJohn.Forte@Sun.COM 
4260*7836SJohn.Forte@Sun.COM 
4261*7836SJohn.Forte@Sun.COM 	scf_value_set_count(value5, setCnt);
4262*7836SJohn.Forte@Sun.COM 
4263*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry5, value5) == -1) {
4264*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
4265*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4266*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4267*7836SJohn.Forte@Sun.COM 		goto out;
4268*7836SJohn.Forte@Sun.COM 	}
4269*7836SJohn.Forte@Sun.COM 
4270*7836SJohn.Forte@Sun.COM 	/* create or change the provider type property */
4271*7836SJohn.Forte@Sun.COM 	if (scf_transaction_property_new(tran, entry3,
4272*7836SJohn.Forte@Sun.COM 	    STMF_PROVIDER_DATA_PROP_TYPE, SCF_TYPE_INTEGER) == -1) {
4273*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_EXISTS) {
4274*7836SJohn.Forte@Sun.COM 			if (scf_transaction_property_change(tran, entry3,
4275*7836SJohn.Forte@Sun.COM 			    STMF_PROVIDER_DATA_PROP_TYPE,
4276*7836SJohn.Forte@Sun.COM 			    SCF_TYPE_INTEGER) == -1) {
4277*7836SJohn.Forte@Sun.COM 				syslog(LOG_ERR,
4278*7836SJohn.Forte@Sun.COM 				    "transaction property change failed - %s",
4279*7836SJohn.Forte@Sun.COM 				    scf_strerror(scf_error()));
4280*7836SJohn.Forte@Sun.COM 				ret = STMF_PS_ERROR;
4281*7836SJohn.Forte@Sun.COM 				goto out;
4282*7836SJohn.Forte@Sun.COM 			}
4283*7836SJohn.Forte@Sun.COM 		} else {
4284*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "transaction property new failed - %s",
4285*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4286*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4287*7836SJohn.Forte@Sun.COM 			goto out;
4288*7836SJohn.Forte@Sun.COM 		}
4289*7836SJohn.Forte@Sun.COM 	}
4290*7836SJohn.Forte@Sun.COM 
4291*7836SJohn.Forte@Sun.COM 	switch (providerType) {
4292*7836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
4293*7836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
4294*7836SJohn.Forte@Sun.COM 			scf_value_set_integer(value3, providerType);
4295*7836SJohn.Forte@Sun.COM 			break;
4296*7836SJohn.Forte@Sun.COM 		default:
4297*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4298*7836SJohn.Forte@Sun.COM 			goto out;
4299*7836SJohn.Forte@Sun.COM 	}
4300*7836SJohn.Forte@Sun.COM 
4301*7836SJohn.Forte@Sun.COM 	if (scf_entry_add_value(entry3, value3) == -1) {
4302*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "add value failed - %s",
4303*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4304*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4305*7836SJohn.Forte@Sun.COM 		goto out;
4306*7836SJohn.Forte@Sun.COM 	}
4307*7836SJohn.Forte@Sun.COM 
4308*7836SJohn.Forte@Sun.COM 
4309*7836SJohn.Forte@Sun.COM 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
4310*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "transaction commit failed - %s",
4311*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4312*7836SJohn.Forte@Sun.COM 		if (commitRet == 0) {
4313*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_BUSY;
4314*7836SJohn.Forte@Sun.COM 		} else {
4315*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4316*7836SJohn.Forte@Sun.COM 		}
4317*7836SJohn.Forte@Sun.COM 		goto out;
4318*7836SJohn.Forte@Sun.COM 	}
4319*7836SJohn.Forte@Sun.COM 
4320*7836SJohn.Forte@Sun.COM 	/* pass the new token back to the caller if requested */
4321*7836SJohn.Forte@Sun.COM 	if (ret == STMF_PS_SUCCESS && setToken) {
4322*7836SJohn.Forte@Sun.COM 		*setToken = setCnt;
4323*7836SJohn.Forte@Sun.COM 	}
4324*7836SJohn.Forte@Sun.COM 
4325*7836SJohn.Forte@Sun.COM out:
4326*7836SJohn.Forte@Sun.COM 	/*
4327*7836SJohn.Forte@Sun.COM 	 * Free resources
4328*7836SJohn.Forte@Sun.COM 	 */
4329*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
4330*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
4331*7836SJohn.Forte@Sun.COM 	}
4332*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
4333*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
4334*7836SJohn.Forte@Sun.COM 	}
4335*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
4336*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
4337*7836SJohn.Forte@Sun.COM 	}
4338*7836SJohn.Forte@Sun.COM 	if (prop != NULL) {
4339*7836SJohn.Forte@Sun.COM 		scf_property_destroy(prop);
4340*7836SJohn.Forte@Sun.COM 	}
4341*7836SJohn.Forte@Sun.COM 	if (tran != NULL) {
4342*7836SJohn.Forte@Sun.COM 		scf_transaction_destroy(tran);
4343*7836SJohn.Forte@Sun.COM 	}
4344*7836SJohn.Forte@Sun.COM 	for (i = 0; i < addEntryAlloc; i++) {
4345*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(addEntry[i]);
4346*7836SJohn.Forte@Sun.COM 	}
4347*7836SJohn.Forte@Sun.COM 	for (i = 0; i < addValueAlloc; i++) {
4348*7836SJohn.Forte@Sun.COM 		scf_value_destroy(addValue[i]);
4349*7836SJohn.Forte@Sun.COM 	}
4350*7836SJohn.Forte@Sun.COM 	free(addValue);
4351*7836SJohn.Forte@Sun.COM 	free(addEntry);
4352*7836SJohn.Forte@Sun.COM 	for (i = 0; i < deleteEntryAlloc; i++) {
4353*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(deleteEntry[i]);
4354*7836SJohn.Forte@Sun.COM 	}
4355*7836SJohn.Forte@Sun.COM 	free(deleteEntry);
4356*7836SJohn.Forte@Sun.COM 	if (entry1 != NULL) {
4357*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry1);
4358*7836SJohn.Forte@Sun.COM 	}
4359*7836SJohn.Forte@Sun.COM 	if (entry2 != NULL) {
4360*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry2);
4361*7836SJohn.Forte@Sun.COM 	}
4362*7836SJohn.Forte@Sun.COM 	if (entry3 != NULL) {
4363*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry3);
4364*7836SJohn.Forte@Sun.COM 	}
4365*7836SJohn.Forte@Sun.COM 	if (entry5 != NULL) {
4366*7836SJohn.Forte@Sun.COM 		scf_entry_destroy(entry5);
4367*7836SJohn.Forte@Sun.COM 	}
4368*7836SJohn.Forte@Sun.COM 	if (value1 != NULL) {
4369*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value1);
4370*7836SJohn.Forte@Sun.COM 	}
4371*7836SJohn.Forte@Sun.COM 	if (value2 != NULL) {
4372*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value2);
4373*7836SJohn.Forte@Sun.COM 	}
4374*7836SJohn.Forte@Sun.COM 	if (value3 != NULL) {
4375*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value3);
4376*7836SJohn.Forte@Sun.COM 	}
4377*7836SJohn.Forte@Sun.COM 	if (value4 != NULL) {
4378*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value4);
4379*7836SJohn.Forte@Sun.COM 	}
4380*7836SJohn.Forte@Sun.COM 	if (value5 != NULL) {
4381*7836SJohn.Forte@Sun.COM 		scf_value_destroy(value5);
4382*7836SJohn.Forte@Sun.COM 	}
4383*7836SJohn.Forte@Sun.COM 	if (nvlistEncoded != NULL) {
4384*7836SJohn.Forte@Sun.COM 		free(nvlistEncoded);
4385*7836SJohn.Forte@Sun.COM 	}
4386*7836SJohn.Forte@Sun.COM 
4387*7836SJohn.Forte@Sun.COM 	return (ret);
4388*7836SJohn.Forte@Sun.COM }
4389*7836SJohn.Forte@Sun.COM 
4390*7836SJohn.Forte@Sun.COM /*
4391*7836SJohn.Forte@Sun.COM  * psGetViewEntry
4392*7836SJohn.Forte@Sun.COM  *
4393*7836SJohn.Forte@Sun.COM  * Purpose: Get a single view entry based on the logical unit identifier and
4394*7836SJohn.Forte@Sun.COM  *          view entry index
4395*7836SJohn.Forte@Sun.COM  *
4396*7836SJohn.Forte@Sun.COM  * lu - logical unit identifier
4397*7836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry
4398*7836SJohn.Forte@Sun.COM  * ve - caller allocated stmfViewEntry structure. On success, this will
4399*7836SJohn.Forte@Sun.COM  *      contain the retrieved view entry
4400*7836SJohn.Forte@Sun.COM  */
4401*7836SJohn.Forte@Sun.COM int
4402*7836SJohn.Forte@Sun.COM psGetViewEntry(stmfGuid *lu, uint32_t viewEntryIndex, stmfViewEntry *ve)
4403*7836SJohn.Forte@Sun.COM {
4404*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
4405*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
4406*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
4407*7836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
4408*7836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
4409*7836SJohn.Forte@Sun.COM 	char luPgName[LOGICAL_UNIT_PG_SIZE];
4410*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
4411*7836SJohn.Forte@Sun.COM 
4412*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
4413*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
4414*7836SJohn.Forte@Sun.COM 		goto out;
4415*7836SJohn.Forte@Sun.COM 	}
4416*7836SJohn.Forte@Sun.COM 
4417*7836SJohn.Forte@Sun.COM 	pg = scf_pg_create(handle);
4418*7836SJohn.Forte@Sun.COM 	if (pg == NULL) {
4419*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf pg alloc failed - %s",
4420*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4421*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4422*7836SJohn.Forte@Sun.COM 		goto out;
4423*7836SJohn.Forte@Sun.COM 	}
4424*7836SJohn.Forte@Sun.COM 
4425*7836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
4426*7836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
4427*7836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
4428*7836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
4429*7836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
4430*7836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
4431*7836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
4432*7836SJohn.Forte@Sun.COM 
4433*7836SJohn.Forte@Sun.COM 	(void) snprintf(luPgName, sizeof (luPgName), "%s-%s",
4434*7836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
4435*7836SJohn.Forte@Sun.COM 
4436*7836SJohn.Forte@Sun.COM 	/*
4437*7836SJohn.Forte@Sun.COM 	 * Format of view entry property group name:
4438*7836SJohn.Forte@Sun.COM 	 *	VE-<view_entry_index>-<lu_name>
4439*7836SJohn.Forte@Sun.COM 	 */
4440*7836SJohn.Forte@Sun.COM 	(void) snprintf(viewEntryPgName, sizeof (viewEntryPgName),
4441*7836SJohn.Forte@Sun.COM 	    "%s-%d-%s", STMF_VE_PREFIX, viewEntryIndex, guidAsciiBuf);
4442*7836SJohn.Forte@Sun.COM 
4443*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) {
4444*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
4445*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
4446*7836SJohn.Forte@Sun.COM 		} else {
4447*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
4448*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4449*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4450*7836SJohn.Forte@Sun.COM 		}
4451*7836SJohn.Forte@Sun.COM 		goto out;
4452*7836SJohn.Forte@Sun.COM 	}
4453*7836SJohn.Forte@Sun.COM 
4454*7836SJohn.Forte@Sun.COM 
4455*7836SJohn.Forte@Sun.COM 	if ((ret = iPsGetViewEntry(viewEntryPgName, ve)) != STMF_PS_SUCCESS) {
4456*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4457*7836SJohn.Forte@Sun.COM 		goto out;
4458*7836SJohn.Forte@Sun.COM 	}
4459*7836SJohn.Forte@Sun.COM 
4460*7836SJohn.Forte@Sun.COM out:
4461*7836SJohn.Forte@Sun.COM 	/*
4462*7836SJohn.Forte@Sun.COM 	 * Free resources
4463*7836SJohn.Forte@Sun.COM 	 */
4464*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
4465*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
4466*7836SJohn.Forte@Sun.COM 	}
4467*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
4468*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
4469*7836SJohn.Forte@Sun.COM 	}
4470*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
4471*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
4472*7836SJohn.Forte@Sun.COM 	}
4473*7836SJohn.Forte@Sun.COM 
4474*7836SJohn.Forte@Sun.COM 	return (ret);
4475*7836SJohn.Forte@Sun.COM }
4476*7836SJohn.Forte@Sun.COM 
4477*7836SJohn.Forte@Sun.COM /*
4478*7836SJohn.Forte@Sun.COM  * psRemoveViewEntry
4479*7836SJohn.Forte@Sun.COM  *
4480*7836SJohn.Forte@Sun.COM  * Remove a view entry
4481*7836SJohn.Forte@Sun.COM  *
4482*7836SJohn.Forte@Sun.COM  * luGuid - identifier of logical unit from which to remove view entry
4483*7836SJohn.Forte@Sun.COM  * viewEntryIndex - view entry name to remove
4484*7836SJohn.Forte@Sun.COM  *
4485*7836SJohn.Forte@Sun.COM  * returns:
4486*7836SJohn.Forte@Sun.COM  *  STMF_PS_SUCCESS on success
4487*7836SJohn.Forte@Sun.COM  *  STMF_PS_ERROR_* on failure
4488*7836SJohn.Forte@Sun.COM  */
4489*7836SJohn.Forte@Sun.COM int
4490*7836SJohn.Forte@Sun.COM psRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
4491*7836SJohn.Forte@Sun.COM {
4492*7836SJohn.Forte@Sun.COM 	scf_handle_t	*handle = NULL;
4493*7836SJohn.Forte@Sun.COM 	scf_service_t	*svc = NULL;
4494*7836SJohn.Forte@Sun.COM 	scf_propertygroup_t	*pg = NULL;
4495*7836SJohn.Forte@Sun.COM 	char guidAsciiBuf[33]; /* size of ascii hex 16 byte guid with NULL */
4496*7836SJohn.Forte@Sun.COM 	char viewEntryPgName[VIEW_ENTRY_PG_SIZE];
4497*7836SJohn.Forte@Sun.COM 	char luPgName[LOGICAL_UNIT_PG_SIZE];
4498*7836SJohn.Forte@Sun.COM 	int ret = STMF_PS_SUCCESS;
4499*7836SJohn.Forte@Sun.COM 	sigset_t sigmaskRestore;
4500*7836SJohn.Forte@Sun.COM 
4501*7836SJohn.Forte@Sun.COM 	/* grab the signal hold lock */
4502*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_lock(&sigSetLock);
4503*7836SJohn.Forte@Sun.COM 
4504*7836SJohn.Forte@Sun.COM 	/*
4505*7836SJohn.Forte@Sun.COM 	 * hold signals until we're done
4506*7836SJohn.Forte@Sun.COM 	 */
4507*7836SJohn.Forte@Sun.COM 	if (holdSignal(&sigmaskRestore) != 0) {
4508*7836SJohn.Forte@Sun.COM 		(void) pthread_mutex_unlock(&sigSetLock);
4509*7836SJohn.Forte@Sun.COM 		return (STMF_PS_ERROR);
4510*7836SJohn.Forte@Sun.COM 	}
4511*7836SJohn.Forte@Sun.COM 
4512*7836SJohn.Forte@Sun.COM 	ret = iPsInit(&handle, &svc);
4513*7836SJohn.Forte@Sun.COM 	if (ret != STMF_PS_SUCCESS) {
4514*7836SJohn.Forte@Sun.COM 		goto out;
4515*7836SJohn.Forte@Sun.COM 	}
4516*7836SJohn.Forte@Sun.COM 
4517*7836SJohn.Forte@Sun.COM 	pg = scf_pg_create(handle);
4518*7836SJohn.Forte@Sun.COM 	if (pg == NULL) {
4519*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "scf pg alloc failed - %s",
4520*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4521*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4522*7836SJohn.Forte@Sun.COM 		goto out;
4523*7836SJohn.Forte@Sun.COM 	}
4524*7836SJohn.Forte@Sun.COM 
4525*7836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
4526*7836SJohn.Forte@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
4527*7836SJohn.Forte@Sun.COM 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
4528*7836SJohn.Forte@Sun.COM 	    lu->guid[0], lu->guid[1], lu->guid[2], lu->guid[3], lu->guid[4],
4529*7836SJohn.Forte@Sun.COM 	    lu->guid[5], lu->guid[6], lu->guid[7], lu->guid[8], lu->guid[9],
4530*7836SJohn.Forte@Sun.COM 	    lu->guid[10], lu->guid[11], lu->guid[12], lu->guid[13],
4531*7836SJohn.Forte@Sun.COM 	    lu->guid[14], lu->guid[15]);
4532*7836SJohn.Forte@Sun.COM 
4533*7836SJohn.Forte@Sun.COM 	(void) snprintf(luPgName, sizeof (luPgName), "%s-%s",
4534*7836SJohn.Forte@Sun.COM 	    STMF_LU_PREFIX, guidAsciiBuf);
4535*7836SJohn.Forte@Sun.COM 
4536*7836SJohn.Forte@Sun.COM 	/*
4537*7836SJohn.Forte@Sun.COM 	 * Format of view entry property group name:
4538*7836SJohn.Forte@Sun.COM 	 *	VE-<view_entry_index>-<lu_name>
4539*7836SJohn.Forte@Sun.COM 	 */
4540*7836SJohn.Forte@Sun.COM 	(void) snprintf(viewEntryPgName, sizeof (viewEntryPgName),
4541*7836SJohn.Forte@Sun.COM 	    "%s-%d-%s", STMF_VE_PREFIX, viewEntryIndex, guidAsciiBuf);
4542*7836SJohn.Forte@Sun.COM 
4543*7836SJohn.Forte@Sun.COM 	if (scf_service_get_pg(svc, viewEntryPgName, pg) == -1) {
4544*7836SJohn.Forte@Sun.COM 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
4545*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR_NOT_FOUND;
4546*7836SJohn.Forte@Sun.COM 		} else {
4547*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "get pg failed - %s",
4548*7836SJohn.Forte@Sun.COM 			    scf_strerror(scf_error()));
4549*7836SJohn.Forte@Sun.COM 			ret = STMF_PS_ERROR;
4550*7836SJohn.Forte@Sun.COM 		}
4551*7836SJohn.Forte@Sun.COM 		goto out;
4552*7836SJohn.Forte@Sun.COM 	}
4553*7836SJohn.Forte@Sun.COM 
4554*7836SJohn.Forte@Sun.COM 	/*
4555*7836SJohn.Forte@Sun.COM 	 * update the logical unit property group to remove
4556*7836SJohn.Forte@Sun.COM 	 * the view entry and update the view entry count
4557*7836SJohn.Forte@Sun.COM 	 * If it fails, we won't delete the property group so that
4558*7836SJohn.Forte@Sun.COM 	 * we maintain consistency.
4559*7836SJohn.Forte@Sun.COM 	 */
4560*7836SJohn.Forte@Sun.COM 	if ((ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
4561*7836SJohn.Forte@Sun.COM 	    REMOVE)) != STMF_PS_SUCCESS) {
4562*7836SJohn.Forte@Sun.COM 		goto out;
4563*7836SJohn.Forte@Sun.COM 	}
4564*7836SJohn.Forte@Sun.COM 
4565*7836SJohn.Forte@Sun.COM 	/*
4566*7836SJohn.Forte@Sun.COM 	 * Delete the view entry. If this fails, we should try to add
4567*7836SJohn.Forte@Sun.COM 	 * the logical unit view entry property group back otherwise
4568*7836SJohn.Forte@Sun.COM 	 * we're inconsistent.
4569*7836SJohn.Forte@Sun.COM 	 */
4570*7836SJohn.Forte@Sun.COM 	if (scf_pg_delete(pg) == -1) {
4571*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "delete pg failed - %s",
4572*7836SJohn.Forte@Sun.COM 		    scf_strerror(scf_error()));
4573*7836SJohn.Forte@Sun.COM 		if ((ret = iPsAddRemoveLuViewEntry(luPgName, viewEntryPgName,
4574*7836SJohn.Forte@Sun.COM 		    ADD)) != STMF_PS_SUCCESS) {
4575*7836SJohn.Forte@Sun.COM 			syslog(LOG_ERR, "add of view entry failed, possible"
4576*7836SJohn.Forte@Sun.COM 			    "inconsistency - %s", scf_strerror(scf_error()));
4577*7836SJohn.Forte@Sun.COM 		}
4578*7836SJohn.Forte@Sun.COM 		ret = STMF_PS_ERROR;
4579*7836SJohn.Forte@Sun.COM 		goto out;
4580*7836SJohn.Forte@Sun.COM 	}
4581*7836SJohn.Forte@Sun.COM 
4582*7836SJohn.Forte@Sun.COM out:
4583*7836SJohn.Forte@Sun.COM 	/*
4584*7836SJohn.Forte@Sun.COM 	 * Okay, we're done. Release the signals
4585*7836SJohn.Forte@Sun.COM 	 */
4586*7836SJohn.Forte@Sun.COM 	if (releaseSignal(&sigmaskRestore) != 0) {
4587*7836SJohn.Forte@Sun.COM 		/*
4588*7836SJohn.Forte@Sun.COM 		 * Don't set this as an STMF_PS_ERROR_*. We succeeded
4589*7836SJohn.Forte@Sun.COM 		 * the requested operation. But we do need to log it.
4590*7836SJohn.Forte@Sun.COM 		 */
4591*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "Unable to release one or more signals - %s",
4592*7836SJohn.Forte@Sun.COM 		    strerror(errno));
4593*7836SJohn.Forte@Sun.COM 	}
4594*7836SJohn.Forte@Sun.COM 
4595*7836SJohn.Forte@Sun.COM 	/*
4596*7836SJohn.Forte@Sun.COM 	 * Free resources
4597*7836SJohn.Forte@Sun.COM 	 */
4598*7836SJohn.Forte@Sun.COM 	if (handle != NULL) {
4599*7836SJohn.Forte@Sun.COM 		scf_handle_destroy(handle);
4600*7836SJohn.Forte@Sun.COM 	}
4601*7836SJohn.Forte@Sun.COM 	if (svc != NULL) {
4602*7836SJohn.Forte@Sun.COM 		scf_service_destroy(svc);
4603*7836SJohn.Forte@Sun.COM 	}
4604*7836SJohn.Forte@Sun.COM 	if (pg != NULL) {
4605*7836SJohn.Forte@Sun.COM 		scf_pg_destroy(pg);
4606*7836SJohn.Forte@Sun.COM 	}
4607*7836SJohn.Forte@Sun.COM 
4608*7836SJohn.Forte@Sun.COM 	/* release the signal hold lock */
4609*7836SJohn.Forte@Sun.COM 	(void) pthread_mutex_unlock(&sigSetLock);
4610*7836SJohn.Forte@Sun.COM 
4611*7836SJohn.Forte@Sun.COM 	return (ret);
4612*7836SJohn.Forte@Sun.COM }
4613*7836SJohn.Forte@Sun.COM 
4614*7836SJohn.Forte@Sun.COM 
4615*7836SJohn.Forte@Sun.COM 
4616*7836SJohn.Forte@Sun.COM /*
4617*7836SJohn.Forte@Sun.COM  * holdSignal
4618*7836SJohn.Forte@Sun.COM  *
4619*7836SJohn.Forte@Sun.COM  * Hold SIGINT, SIGTERM, SIGQUIT until further notice.
4620*7836SJohn.Forte@Sun.COM  *
4621*7836SJohn.Forte@Sun.COM  * Saves old signal mask on a per thread basis
4622*7836SJohn.Forte@Sun.COM  * and saves action for the process.
4623*7836SJohn.Forte@Sun.COM  *
4624*7836SJohn.Forte@Sun.COM  * Installs action for above signals.
4625*7836SJohn.Forte@Sun.COM  *
4626*7836SJohn.Forte@Sun.COM  * locks held: sigSetLock
4627*7836SJohn.Forte@Sun.COM  *
4628*7836SJohn.Forte@Sun.COM  * returns:
4629*7836SJohn.Forte@Sun.COM  *  0 on success
4630*7836SJohn.Forte@Sun.COM  *  non-zero otherwise
4631*7836SJohn.Forte@Sun.COM  */
4632*7836SJohn.Forte@Sun.COM static int
4633*7836SJohn.Forte@Sun.COM holdSignal(sigset_t *sigmaskRestore)
4634*7836SJohn.Forte@Sun.COM {
4635*7836SJohn.Forte@Sun.COM 	struct sigaction act;
4636*7836SJohn.Forte@Sun.COM 	sigset_t sigmask;
4637*7836SJohn.Forte@Sun.COM 
4638*7836SJohn.Forte@Sun.COM 	/*
4639*7836SJohn.Forte@Sun.COM 	 * Return existing signal mask for this thread
4640*7836SJohn.Forte@Sun.COM 	 */
4641*7836SJohn.Forte@Sun.COM 	if (pthread_sigmask(0, NULL, sigmaskRestore) != 0) {
4642*7836SJohn.Forte@Sun.COM 		return (1);
4643*7836SJohn.Forte@Sun.COM 	}
4644*7836SJohn.Forte@Sun.COM 
4645*7836SJohn.Forte@Sun.COM 	(void) sigemptyset(&act.sa_mask);
4646*7836SJohn.Forte@Sun.COM 	act.sa_handler = sigHandler;
4647*7836SJohn.Forte@Sun.COM 	act.sa_flags = 0;
4648*7836SJohn.Forte@Sun.COM 
4649*7836SJohn.Forte@Sun.COM 	/*
4650*7836SJohn.Forte@Sun.COM 	 * Have we set the actions for the signals we want to catch?
4651*7836SJohn.Forte@Sun.COM 	 */
4652*7836SJohn.Forte@Sun.COM 	if (!actionSet) {
4653*7836SJohn.Forte@Sun.COM 		if (sigaction(SIGQUIT, &act, &currentActionQuit) != 0) {
4654*7836SJohn.Forte@Sun.COM 			return (1);
4655*7836SJohn.Forte@Sun.COM 		}
4656*7836SJohn.Forte@Sun.COM 
4657*7836SJohn.Forte@Sun.COM 		if (sigaction(SIGINT, &act, &currentActionInt) != 0) {
4658*7836SJohn.Forte@Sun.COM 			return (1);
4659*7836SJohn.Forte@Sun.COM 		}
4660*7836SJohn.Forte@Sun.COM 
4661*7836SJohn.Forte@Sun.COM 		if (sigaction(SIGTERM, &act, &currentActionTerm) != 0) {
4662*7836SJohn.Forte@Sun.COM 			return (1);
4663*7836SJohn.Forte@Sun.COM 		}
4664*7836SJohn.Forte@Sun.COM 
4665*7836SJohn.Forte@Sun.COM 		actionSet = B_TRUE;
4666*7836SJohn.Forte@Sun.COM 	}
4667*7836SJohn.Forte@Sun.COM 
4668*7836SJohn.Forte@Sun.COM 	/*
4669*7836SJohn.Forte@Sun.COM 	 * We still need to change the mask for the current thread
4670*7836SJohn.Forte@Sun.COM 	 */
4671*7836SJohn.Forte@Sun.COM 	if (sigfillset(&sigmask) != 0) {
4672*7836SJohn.Forte@Sun.COM 		return (1);
4673*7836SJohn.Forte@Sun.COM 	}
4674*7836SJohn.Forte@Sun.COM 
4675*7836SJohn.Forte@Sun.COM 	(void) sigdelset(&sigmask, SIGQUIT);
4676*7836SJohn.Forte@Sun.COM 
4677*7836SJohn.Forte@Sun.COM 	(void) sigdelset(&sigmask, SIGINT);
4678*7836SJohn.Forte@Sun.COM 
4679*7836SJohn.Forte@Sun.COM 	(void) sigdelset(&sigmask, SIGTERM);
4680*7836SJohn.Forte@Sun.COM 
4681*7836SJohn.Forte@Sun.COM 	if (pthread_sigmask(SIG_SETMASK, &sigmask, NULL) != 0) {
4682*7836SJohn.Forte@Sun.COM 		return (1);
4683*7836SJohn.Forte@Sun.COM 	}
4684*7836SJohn.Forte@Sun.COM 
4685*7836SJohn.Forte@Sun.COM 	return (0);
4686*7836SJohn.Forte@Sun.COM }
4687*7836SJohn.Forte@Sun.COM 
4688*7836SJohn.Forte@Sun.COM /*
4689*7836SJohn.Forte@Sun.COM  * releaseSignal
4690*7836SJohn.Forte@Sun.COM  *
4691*7836SJohn.Forte@Sun.COM  * Re-install the original signal mask and signal actions
4692*7836SJohn.Forte@Sun.COM  *
4693*7836SJohn.Forte@Sun.COM  * Also, raise any signals that were caught during the hold period and clear
4694*7836SJohn.Forte@Sun.COM  * the signal from the caught set (signalsCaught).
4695*7836SJohn.Forte@Sun.COM  *
4696*7836SJohn.Forte@Sun.COM  * locks held: sigSetLock
4697*7836SJohn.Forte@Sun.COM  *
4698*7836SJohn.Forte@Sun.COM  * Returns
4699*7836SJohn.Forte@Sun.COM  *  0 on success
4700*7836SJohn.Forte@Sun.COM  *  non-zero otherwise
4701*7836SJohn.Forte@Sun.COM  */
4702*7836SJohn.Forte@Sun.COM static int
4703*7836SJohn.Forte@Sun.COM releaseSignal(sigset_t *sigmaskRestore)
4704*7836SJohn.Forte@Sun.COM {
4705*7836SJohn.Forte@Sun.COM 	int ret = 0;
4706*7836SJohn.Forte@Sun.COM 
4707*7836SJohn.Forte@Sun.COM 	if (sigaction(SIGQUIT, &currentActionQuit, NULL) != 0) {
4708*7836SJohn.Forte@Sun.COM 		ret = 1;
4709*7836SJohn.Forte@Sun.COM 	}
4710*7836SJohn.Forte@Sun.COM 
4711*7836SJohn.Forte@Sun.COM 	if (sigaction(SIGINT, &currentActionInt, NULL) != 0) {
4712*7836SJohn.Forte@Sun.COM 		ret = 1;
4713*7836SJohn.Forte@Sun.COM 	}
4714*7836SJohn.Forte@Sun.COM 
4715*7836SJohn.Forte@Sun.COM 	if (sigaction(SIGTERM, &currentActionTerm, NULL) != 0) {
4716*7836SJohn.Forte@Sun.COM 		ret = 1;
4717*7836SJohn.Forte@Sun.COM 	}
4718*7836SJohn.Forte@Sun.COM 
4719*7836SJohn.Forte@Sun.COM 	actionSet = B_FALSE;
4720*7836SJohn.Forte@Sun.COM 
4721*7836SJohn.Forte@Sun.COM 	/*
4722*7836SJohn.Forte@Sun.COM 	 * Restore previous signal mask for this thread
4723*7836SJohn.Forte@Sun.COM 	 */
4724*7836SJohn.Forte@Sun.COM 	if (pthread_sigmask(SIG_SETMASK, sigmaskRestore, NULL) != 0) {
4725*7836SJohn.Forte@Sun.COM 		syslog(LOG_ERR, "Unable to restore sigmask");
4726*7836SJohn.Forte@Sun.COM 	}
4727*7836SJohn.Forte@Sun.COM 
4728*7836SJohn.Forte@Sun.COM 	/*
4729*7836SJohn.Forte@Sun.COM 	 * Now raise signals that were raised while we were held
4730*7836SJohn.Forte@Sun.COM 	 */
4731*7836SJohn.Forte@Sun.COM 	if (sigismember(&signalsCaught, SIGTERM)) {
4732*7836SJohn.Forte@Sun.COM 		(void) sigdelset(&signalsCaught, SIGTERM);
4733*7836SJohn.Forte@Sun.COM 		(void) raise(SIGTERM);
4734*7836SJohn.Forte@Sun.COM 	}
4735*7836SJohn.Forte@Sun.COM 
4736*7836SJohn.Forte@Sun.COM 	if (sigismember(&signalsCaught, SIGINT)) {
4737*7836SJohn.Forte@Sun.COM 		(void) sigdelset(&signalsCaught, SIGINT);
4738*7836SJohn.Forte@Sun.COM 		(void) raise(SIGINT);
4739*7836SJohn.Forte@Sun.COM 	}
4740*7836SJohn.Forte@Sun.COM 
4741*7836SJohn.Forte@Sun.COM 	if (sigismember(&signalsCaught, SIGQUIT)) {
4742*7836SJohn.Forte@Sun.COM 		(void) sigdelset(&signalsCaught, SIGQUIT);
4743*7836SJohn.Forte@Sun.COM 		(void) raise(SIGQUIT);
4744*7836SJohn.Forte@Sun.COM 	}
4745*7836SJohn.Forte@Sun.COM 
4746*7836SJohn.Forte@Sun.COM 	return (ret);
4747*7836SJohn.Forte@Sun.COM }
4748