xref: /illumos-gate/usr/src/lib/libshare/smbfs/smbfs_scfutil.c (revision 4bff34e37def8a90f9194d81bc345c52ba20086a)
1*4bff34e3Sthurlow /*
2*4bff34e3Sthurlow  * CDDL HEADER START
3*4bff34e3Sthurlow  *
4*4bff34e3Sthurlow  * The contents of this file are subject to the terms of the
5*4bff34e3Sthurlow  * Common Development and Distribution License (the "License").
6*4bff34e3Sthurlow  * You may not use this file except in compliance with the License.
7*4bff34e3Sthurlow  *
8*4bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
10*4bff34e3Sthurlow  * See the License for the specific language governing permissions
11*4bff34e3Sthurlow  * and limitations under the License.
12*4bff34e3Sthurlow  *
13*4bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
14*4bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
16*4bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
17*4bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4bff34e3Sthurlow  *
19*4bff34e3Sthurlow  * CDDL HEADER END
20*4bff34e3Sthurlow  */
21*4bff34e3Sthurlow 
22*4bff34e3Sthurlow /*
23*4bff34e3Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*4bff34e3Sthurlow  * Use is subject to license terms.
25*4bff34e3Sthurlow  */
26*4bff34e3Sthurlow 
27*4bff34e3Sthurlow #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*4bff34e3Sthurlow 
29*4bff34e3Sthurlow /* helper functions for using libscf with CIFS */
30*4bff34e3Sthurlow 
31*4bff34e3Sthurlow #include <libscf.h>
32*4bff34e3Sthurlow #include <string.h>
33*4bff34e3Sthurlow #include <stdio.h>
34*4bff34e3Sthurlow #include <stdlib.h>
35*4bff34e3Sthurlow #include <syslog.h>
36*4bff34e3Sthurlow #include <errno.h>
37*4bff34e3Sthurlow #include <uuid/uuid.h>
38*4bff34e3Sthurlow #include <sys/param.h>
39*4bff34e3Sthurlow #include <libintl.h>
40*4bff34e3Sthurlow #include <assert.h>
41*4bff34e3Sthurlow #include <strings.h>
42*4bff34e3Sthurlow 
43*4bff34e3Sthurlow #include "libshare.h"
44*4bff34e3Sthurlow #include "libshare_smbfs.h"
45*4bff34e3Sthurlow 
46*4bff34e3Sthurlow /*
47*4bff34e3Sthurlow  * smb_smf_scf_log_error(msg)
48*4bff34e3Sthurlow  * Logs error messages from scf API's
49*4bff34e3Sthurlow  */
50*4bff34e3Sthurlow static void
51*4bff34e3Sthurlow smb_smf_scf_log_error(char *msg)
52*4bff34e3Sthurlow {
53*4bff34e3Sthurlow 	if (!msg) {
54*4bff34e3Sthurlow 		syslog(LOG_ERR, " SMBC SMF problem: %s\n",
55*4bff34e3Sthurlow 		    scf_strerror(scf_error()));
56*4bff34e3Sthurlow 	} else { /*LINTED E_SEC_PRINTF_E_VAR_FMT*/
57*4bff34e3Sthurlow 		syslog(LOG_ERR, msg, scf_strerror(scf_error()));
58*4bff34e3Sthurlow 	}
59*4bff34e3Sthurlow }
60*4bff34e3Sthurlow 
61*4bff34e3Sthurlow /*
62*4bff34e3Sthurlow  * smb_smf_scf_fini(handle)
63*4bff34e3Sthurlow  *
64*4bff34e3Sthurlow  * must be called when done. Called with the handle allocated in
65*4bff34e3Sthurlow  * smb_smf_scf_init(), it cleans up the state and frees any SCF resources
66*4bff34e3Sthurlow  * still in use.
67*4bff34e3Sthurlow  */
68*4bff34e3Sthurlow void
69*4bff34e3Sthurlow smb_smf_scf_fini(smb_scfhandle_t *handle)
70*4bff34e3Sthurlow {
71*4bff34e3Sthurlow 	if (handle != NULL) {
72*4bff34e3Sthurlow 		int unbind = 0;
73*4bff34e3Sthurlow 		if (handle->scf_pg_iter != NULL) {
74*4bff34e3Sthurlow 			scf_iter_destroy(handle->scf_pg_iter);
75*4bff34e3Sthurlow 			handle->scf_pg_iter = NULL;
76*4bff34e3Sthurlow 		}
77*4bff34e3Sthurlow 		if (handle->scf_inst_iter != NULL) {
78*4bff34e3Sthurlow 			scf_iter_destroy(handle->scf_inst_iter);
79*4bff34e3Sthurlow 			handle->scf_inst_iter = NULL;
80*4bff34e3Sthurlow 		}
81*4bff34e3Sthurlow 		if (handle->scf_scope != NULL) {
82*4bff34e3Sthurlow 			unbind = 1;
83*4bff34e3Sthurlow 			scf_scope_destroy(handle->scf_scope);
84*4bff34e3Sthurlow 			handle->scf_scope = NULL;
85*4bff34e3Sthurlow 		}
86*4bff34e3Sthurlow 		if (handle->scf_instance != NULL) {
87*4bff34e3Sthurlow 			scf_instance_destroy(handle->scf_instance);
88*4bff34e3Sthurlow 			handle->scf_instance = NULL;
89*4bff34e3Sthurlow 		}
90*4bff34e3Sthurlow 		if (handle->scf_service != NULL) {
91*4bff34e3Sthurlow 			scf_service_destroy(handle->scf_service);
92*4bff34e3Sthurlow 			handle->scf_service = NULL;
93*4bff34e3Sthurlow 		}
94*4bff34e3Sthurlow 		if (handle->scf_pg != NULL) {
95*4bff34e3Sthurlow 			scf_pg_destroy(handle->scf_pg);
96*4bff34e3Sthurlow 			handle->scf_pg = NULL;
97*4bff34e3Sthurlow 		}
98*4bff34e3Sthurlow 		if (handle->scf_handle != NULL) {
99*4bff34e3Sthurlow 			handle->scf_state = SCH_STATE_UNINIT;
100*4bff34e3Sthurlow 			if (unbind)
101*4bff34e3Sthurlow 				(void) scf_handle_unbind(handle->scf_handle);
102*4bff34e3Sthurlow 			scf_handle_destroy(handle->scf_handle);
103*4bff34e3Sthurlow 			handle->scf_handle = NULL;
104*4bff34e3Sthurlow 		}
105*4bff34e3Sthurlow 		free(handle);
106*4bff34e3Sthurlow 	}
107*4bff34e3Sthurlow }
108*4bff34e3Sthurlow 
109*4bff34e3Sthurlow 
110*4bff34e3Sthurlow /*
111*4bff34e3Sthurlow  * Check if instance with given name exists for a service.
112*4bff34e3Sthurlow  * Returns 0 is instance exist
113*4bff34e3Sthurlow  */
114*4bff34e3Sthurlow int
115*4bff34e3Sthurlow smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name)
116*4bff34e3Sthurlow {
117*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
118*4bff34e3Sthurlow 	if (handle == NULL) {
119*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
120*4bff34e3Sthurlow 	}
121*4bff34e3Sthurlow 
122*4bff34e3Sthurlow 	handle->scf_instance = scf_instance_create(handle->scf_handle);
123*4bff34e3Sthurlow 	if (scf_service_get_instance(handle->scf_service, inst_name,
124*4bff34e3Sthurlow 	    handle->scf_instance) != SCF_SUCCESS) {
125*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
126*4bff34e3Sthurlow 	}
127*4bff34e3Sthurlow 	scf_instance_destroy(handle->scf_instance);
128*4bff34e3Sthurlow 	handle->scf_instance = NULL;
129*4bff34e3Sthurlow 	return (ret);
130*4bff34e3Sthurlow }
131*4bff34e3Sthurlow 
132*4bff34e3Sthurlow /*
133*4bff34e3Sthurlow  * Create a service instance. returns 0 if successful.
134*4bff34e3Sthurlow  * If instance already exists enable it.
135*4bff34e3Sthurlow  */
136*4bff34e3Sthurlow int
137*4bff34e3Sthurlow smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix,
138*4bff34e3Sthurlow 	char *inst_name)
139*4bff34e3Sthurlow {
140*4bff34e3Sthurlow 	char *instance;
141*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
142*4bff34e3Sthurlow 	int sz;
143*4bff34e3Sthurlow 
144*4bff34e3Sthurlow 	if (handle == NULL) {
145*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
146*4bff34e3Sthurlow 	}
147*4bff34e3Sthurlow 
148*4bff34e3Sthurlow 	if (!serv_prefix || !inst_name) {
149*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
150*4bff34e3Sthurlow 	}
151*4bff34e3Sthurlow 	sz = strlen(serv_prefix) + strlen(inst_name) + 2;
152*4bff34e3Sthurlow 	instance = malloc(sz);
153*4bff34e3Sthurlow 	if (!instance) {
154*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
155*4bff34e3Sthurlow 	}
156*4bff34e3Sthurlow 	(void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name);
157*4bff34e3Sthurlow 	handle->scf_instance = scf_instance_create(handle->scf_handle);
158*4bff34e3Sthurlow 	if (scf_service_get_instance(handle->scf_service, inst_name,
159*4bff34e3Sthurlow 	    handle->scf_instance) != SCF_SUCCESS) {
160*4bff34e3Sthurlow 		if (scf_service_add_instance(handle->scf_service,
161*4bff34e3Sthurlow 		    inst_name, handle->scf_instance) == SCF_SUCCESS) {
162*4bff34e3Sthurlow 			if (smf_enable_instance(instance, 0))
163*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
164*4bff34e3Sthurlow 		} else {
165*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
166*4bff34e3Sthurlow 		}
167*4bff34e3Sthurlow 	} else {
168*4bff34e3Sthurlow 		if (smf_enable_instance(instance, 0))
169*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
170*4bff34e3Sthurlow 	}
171*4bff34e3Sthurlow 	free(instance);
172*4bff34e3Sthurlow 	return (ret);
173*4bff34e3Sthurlow }
174*4bff34e3Sthurlow 
175*4bff34e3Sthurlow /*
176*4bff34e3Sthurlow  * Delete a specified instance. Return SMBC_SMF_OK for success.
177*4bff34e3Sthurlow  */
178*4bff34e3Sthurlow int
179*4bff34e3Sthurlow smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name)
180*4bff34e3Sthurlow {
181*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
182*4bff34e3Sthurlow 
183*4bff34e3Sthurlow 	if (handle == NULL) {
184*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
185*4bff34e3Sthurlow 	}
186*4bff34e3Sthurlow 
187*4bff34e3Sthurlow 	handle->scf_instance = scf_instance_create(handle->scf_handle);
188*4bff34e3Sthurlow 	if (scf_service_get_instance(handle->scf_service, inst_name,
189*4bff34e3Sthurlow 	    handle->scf_instance) == SCF_SUCCESS) {
190*4bff34e3Sthurlow 		if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) {
191*4bff34e3Sthurlow 			return (ret);
192*4bff34e3Sthurlow 		} else {
193*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
194*4bff34e3Sthurlow 		}
195*4bff34e3Sthurlow 	} else {
196*4bff34e3Sthurlow 		smb_smf_scf_log_error(NULL);
197*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
198*4bff34e3Sthurlow 	}
199*4bff34e3Sthurlow 	return (ret);
200*4bff34e3Sthurlow }
201*4bff34e3Sthurlow 
202*4bff34e3Sthurlow /*
203*4bff34e3Sthurlow  * smb_smf_scf_init()
204*4bff34e3Sthurlow  *
205*4bff34e3Sthurlow  * must be called before using any of the SCF functions.
206*4bff34e3Sthurlow  * Returns smb_scfhandle_t pointer if success.
207*4bff34e3Sthurlow  */
208*4bff34e3Sthurlow smb_scfhandle_t *
209*4bff34e3Sthurlow smb_smf_scf_init(char *svc_name)
210*4bff34e3Sthurlow {
211*4bff34e3Sthurlow 	smb_scfhandle_t *handle;
212*4bff34e3Sthurlow 
213*4bff34e3Sthurlow 	handle = malloc(sizeof (smb_scfhandle_t));
214*4bff34e3Sthurlow 	if (handle != NULL) {
215*4bff34e3Sthurlow 		bzero((char *)handle, sizeof (smb_scfhandle_t));
216*4bff34e3Sthurlow 		handle->scf_state = SCH_STATE_INITIALIZING;
217*4bff34e3Sthurlow 		handle->scf_handle = scf_handle_create(SCF_VERSION);
218*4bff34e3Sthurlow 		if (handle->scf_handle != NULL) {
219*4bff34e3Sthurlow 			if (scf_handle_bind(handle->scf_handle) == 0) {
220*4bff34e3Sthurlow 				handle->scf_scope =
221*4bff34e3Sthurlow 				    scf_scope_create(handle->scf_handle);
222*4bff34e3Sthurlow 				if (scf_handle_get_local_scope(
223*4bff34e3Sthurlow 				    handle->scf_handle, handle->scf_scope) != 0)
224*4bff34e3Sthurlow 					goto err;
225*4bff34e3Sthurlow 
226*4bff34e3Sthurlow 				handle->scf_service =
227*4bff34e3Sthurlow 				    scf_service_create(handle->scf_handle);
228*4bff34e3Sthurlow 
229*4bff34e3Sthurlow 				if (scf_scope_get_service(handle->scf_scope,
230*4bff34e3Sthurlow 				    svc_name, handle->scf_service)
231*4bff34e3Sthurlow 				    != SCF_SUCCESS) {
232*4bff34e3Sthurlow 					goto err;
233*4bff34e3Sthurlow 				}
234*4bff34e3Sthurlow 				handle->scf_pg =
235*4bff34e3Sthurlow 				    scf_pg_create(handle->scf_handle);
236*4bff34e3Sthurlow 				handle->scf_state = SCH_STATE_INIT;
237*4bff34e3Sthurlow 			} else {
238*4bff34e3Sthurlow 				goto err;
239*4bff34e3Sthurlow 			}
240*4bff34e3Sthurlow 		} else {
241*4bff34e3Sthurlow 			free(handle);
242*4bff34e3Sthurlow 			handle = NULL;
243*4bff34e3Sthurlow 			smb_smf_scf_log_error("Could not access SMF "
244*4bff34e3Sthurlow 			    "repository: %s\n");
245*4bff34e3Sthurlow 		}
246*4bff34e3Sthurlow 	}
247*4bff34e3Sthurlow 	return (handle);
248*4bff34e3Sthurlow 
249*4bff34e3Sthurlow 	/* error handling/unwinding */
250*4bff34e3Sthurlow err:
251*4bff34e3Sthurlow 	(void) smb_smf_scf_fini(handle);
252*4bff34e3Sthurlow 	(void) smb_smf_scf_log_error("SMF initialization problem: %s\n");
253*4bff34e3Sthurlow 	return (NULL);
254*4bff34e3Sthurlow }
255*4bff34e3Sthurlow 
256*4bff34e3Sthurlow /*
257*4bff34e3Sthurlow  * smb_smf_create_service_pgroup(handle, pgroup)
258*4bff34e3Sthurlow  *
259*4bff34e3Sthurlow  * create a new property group at service level.
260*4bff34e3Sthurlow  */
261*4bff34e3Sthurlow int
262*4bff34e3Sthurlow smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
263*4bff34e3Sthurlow {
264*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
265*4bff34e3Sthurlow 	int err;
266*4bff34e3Sthurlow 
267*4bff34e3Sthurlow 	if (handle == NULL) {
268*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
269*4bff34e3Sthurlow 	}
270*4bff34e3Sthurlow 
271*4bff34e3Sthurlow 	/*
272*4bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
273*4bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
274*4bff34e3Sthurlow 	 */
275*4bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
276*4bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
277*4bff34e3Sthurlow 	}
278*4bff34e3Sthurlow 	/*
279*4bff34e3Sthurlow 	 * if the pgroup exists, we are done. If it doesn't, then we
280*4bff34e3Sthurlow 	 * need to actually add one to the service instance.
281*4bff34e3Sthurlow 	 */
282*4bff34e3Sthurlow 	if (scf_service_get_pg(handle->scf_service,
283*4bff34e3Sthurlow 	    pgroup, handle->scf_pg) != 0) {
284*4bff34e3Sthurlow 		/* doesn't exist so create one */
285*4bff34e3Sthurlow 		if (scf_service_add_pg(handle->scf_service, pgroup,
286*4bff34e3Sthurlow 		    SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
287*4bff34e3Sthurlow 			err = scf_error();
288*4bff34e3Sthurlow 			if (err != SCF_ERROR_NONE)
289*4bff34e3Sthurlow 				smb_smf_scf_log_error(NULL);
290*4bff34e3Sthurlow 			switch (err) {
291*4bff34e3Sthurlow 			case SCF_ERROR_PERMISSION_DENIED:
292*4bff34e3Sthurlow 				ret = SMBC_SMF_NO_PERMISSION;
293*4bff34e3Sthurlow 				break;
294*4bff34e3Sthurlow 			default:
295*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
296*4bff34e3Sthurlow 				break;
297*4bff34e3Sthurlow 			}
298*4bff34e3Sthurlow 		}
299*4bff34e3Sthurlow 	}
300*4bff34e3Sthurlow 	return (ret);
301*4bff34e3Sthurlow }
302*4bff34e3Sthurlow 
303*4bff34e3Sthurlow /*
304*4bff34e3Sthurlow  * smb_smf_create_instance_pgroup(handle, pgroup)
305*4bff34e3Sthurlow  *
306*4bff34e3Sthurlow  * create a new property group at instance level.
307*4bff34e3Sthurlow  */
308*4bff34e3Sthurlow int
309*4bff34e3Sthurlow smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
310*4bff34e3Sthurlow {
311*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
312*4bff34e3Sthurlow 	int err;
313*4bff34e3Sthurlow 
314*4bff34e3Sthurlow 	if (handle == NULL) {
315*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
316*4bff34e3Sthurlow 	}
317*4bff34e3Sthurlow 
318*4bff34e3Sthurlow 	/*
319*4bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
320*4bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
321*4bff34e3Sthurlow 	 */
322*4bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
323*4bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
324*4bff34e3Sthurlow 	}
325*4bff34e3Sthurlow 
326*4bff34e3Sthurlow 	/*
327*4bff34e3Sthurlow 	 * if the pgroup exists, we are done. If it doesn't, then we
328*4bff34e3Sthurlow 	 * need to actually add one to the service instance.
329*4bff34e3Sthurlow 	 */
330*4bff34e3Sthurlow 	if (scf_instance_get_pg(handle->scf_instance,
331*4bff34e3Sthurlow 	    pgroup, handle->scf_pg) != 0) {
332*4bff34e3Sthurlow 		/* doesn't exist so create one */
333*4bff34e3Sthurlow 		if (scf_instance_add_pg(handle->scf_instance, pgroup,
334*4bff34e3Sthurlow 		    SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
335*4bff34e3Sthurlow 			err = scf_error();
336*4bff34e3Sthurlow 			if (err != SCF_ERROR_NONE)
337*4bff34e3Sthurlow 				smb_smf_scf_log_error(NULL);
338*4bff34e3Sthurlow 			switch (err) {
339*4bff34e3Sthurlow 			case SCF_ERROR_PERMISSION_DENIED:
340*4bff34e3Sthurlow 				ret = SMBC_SMF_NO_PERMISSION;
341*4bff34e3Sthurlow 				break;
342*4bff34e3Sthurlow 			default:
343*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
344*4bff34e3Sthurlow 				break;
345*4bff34e3Sthurlow 			}
346*4bff34e3Sthurlow 		}
347*4bff34e3Sthurlow 	}
348*4bff34e3Sthurlow 	return (ret);
349*4bff34e3Sthurlow }
350*4bff34e3Sthurlow 
351*4bff34e3Sthurlow /*
352*4bff34e3Sthurlow  * smb_smf_delete_service_pgroup(handle, pgroup)
353*4bff34e3Sthurlow  *
354*4bff34e3Sthurlow  * remove the property group from the current service.
355*4bff34e3Sthurlow  * but only if it actually exists.
356*4bff34e3Sthurlow  */
357*4bff34e3Sthurlow int
358*4bff34e3Sthurlow smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
359*4bff34e3Sthurlow {
360*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
361*4bff34e3Sthurlow 	int err;
362*4bff34e3Sthurlow 
363*4bff34e3Sthurlow 	if (handle == NULL) {
364*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
365*4bff34e3Sthurlow 	}
366*4bff34e3Sthurlow 
367*4bff34e3Sthurlow 	/*
368*4bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
369*4bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
370*4bff34e3Sthurlow 	 */
371*4bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
372*4bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
373*4bff34e3Sthurlow 	}
374*4bff34e3Sthurlow 
375*4bff34e3Sthurlow 	/*
376*4bff34e3Sthurlow 	 * only delete if it does exist.
377*4bff34e3Sthurlow 	 */
378*4bff34e3Sthurlow 	if (scf_service_get_pg(handle->scf_service,
379*4bff34e3Sthurlow 	    pgroup, handle->scf_pg) == 0) {
380*4bff34e3Sthurlow 		/* does exist so delete it */
381*4bff34e3Sthurlow 		if (scf_pg_delete(handle->scf_pg) != 0) {
382*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
383*4bff34e3Sthurlow 			err = scf_error();
384*4bff34e3Sthurlow 			if (err != SCF_ERROR_NONE) {
385*4bff34e3Sthurlow 				smb_smf_scf_log_error("SMF delpg "
386*4bff34e3Sthurlow 				    "problem: %s\n");
387*4bff34e3Sthurlow 			}
388*4bff34e3Sthurlow 		}
389*4bff34e3Sthurlow 	} else {
390*4bff34e3Sthurlow 		err = scf_error();
391*4bff34e3Sthurlow 		if (err != SCF_ERROR_NONE)
392*4bff34e3Sthurlow 			smb_smf_scf_log_error("SMF getpg problem: %s\n");
393*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
394*4bff34e3Sthurlow 	}
395*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR &&
396*4bff34e3Sthurlow 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
397*4bff34e3Sthurlow 		ret = SMBC_SMF_NO_PERMISSION;
398*4bff34e3Sthurlow 	}
399*4bff34e3Sthurlow 	return (ret);
400*4bff34e3Sthurlow }
401*4bff34e3Sthurlow 
402*4bff34e3Sthurlow /*
403*4bff34e3Sthurlow  * smb_smf_delete_instance_pgroup(handle, pgroup)
404*4bff34e3Sthurlow  *
405*4bff34e3Sthurlow  * remove the property group from the current instance.
406*4bff34e3Sthurlow  * but only if it actually exists.
407*4bff34e3Sthurlow  */
408*4bff34e3Sthurlow int
409*4bff34e3Sthurlow smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
410*4bff34e3Sthurlow {
411*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
412*4bff34e3Sthurlow 	int err;
413*4bff34e3Sthurlow 
414*4bff34e3Sthurlow 	if (handle == NULL) {
415*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
416*4bff34e3Sthurlow 	}
417*4bff34e3Sthurlow 
418*4bff34e3Sthurlow 	/*
419*4bff34e3Sthurlow 	 * only create a handle if it doesn't exist. It is ok to exist
420*4bff34e3Sthurlow 	 * since the pg handle will be set as a side effect.
421*4bff34e3Sthurlow 	 */
422*4bff34e3Sthurlow 	if (handle->scf_pg == NULL) {
423*4bff34e3Sthurlow 		handle->scf_pg = scf_pg_create(handle->scf_handle);
424*4bff34e3Sthurlow 	}
425*4bff34e3Sthurlow 
426*4bff34e3Sthurlow 	/*
427*4bff34e3Sthurlow 	 * only delete if it does exist.
428*4bff34e3Sthurlow 	 */
429*4bff34e3Sthurlow 	if (scf_instance_get_pg(handle->scf_instance,
430*4bff34e3Sthurlow 	    pgroup, handle->scf_pg) == 0) {
431*4bff34e3Sthurlow 		/* does exist so delete it */
432*4bff34e3Sthurlow 		if (scf_pg_delete(handle->scf_pg) != 0) {
433*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
434*4bff34e3Sthurlow 			err = scf_error();
435*4bff34e3Sthurlow 			if (err != SCF_ERROR_NONE) {
436*4bff34e3Sthurlow 				smb_smf_scf_log_error("SMF delpg "
437*4bff34e3Sthurlow 				    "problem: %s\n");
438*4bff34e3Sthurlow 			}
439*4bff34e3Sthurlow 		}
440*4bff34e3Sthurlow 	} else {
441*4bff34e3Sthurlow 		err = scf_error();
442*4bff34e3Sthurlow 		if (err != SCF_ERROR_NONE)
443*4bff34e3Sthurlow 			smb_smf_scf_log_error("SMF getpg problem: %s\n");
444*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
445*4bff34e3Sthurlow 	}
446*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR &&
447*4bff34e3Sthurlow 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
448*4bff34e3Sthurlow 		ret = SMBC_SMF_NO_PERMISSION;
449*4bff34e3Sthurlow 	}
450*4bff34e3Sthurlow 	return (ret);
451*4bff34e3Sthurlow }
452*4bff34e3Sthurlow 
453*4bff34e3Sthurlow /*
454*4bff34e3Sthurlow  * Start transaction on current pg in handle.
455*4bff34e3Sthurlow  * The pg could be service or instance level.
456*4bff34e3Sthurlow  * Must be called after pg handle is obtained
457*4bff34e3Sthurlow  * from create or get.
458*4bff34e3Sthurlow  */
459*4bff34e3Sthurlow int
460*4bff34e3Sthurlow smb_smf_start_transaction(smb_scfhandle_t *handle)
461*4bff34e3Sthurlow {
462*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
463*4bff34e3Sthurlow 
464*4bff34e3Sthurlow 	if (!handle || (!handle->scf_pg)) {
465*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
466*4bff34e3Sthurlow 	}
467*4bff34e3Sthurlow 	/*
468*4bff34e3Sthurlow 	 * lookup the property group and create it if it doesn't already
469*4bff34e3Sthurlow 	 * exist.
470*4bff34e3Sthurlow 	 */
471*4bff34e3Sthurlow 	if (handle->scf_state == SCH_STATE_INIT) {
472*4bff34e3Sthurlow 		if (ret == SMBC_SMF_OK) {
473*4bff34e3Sthurlow 			handle->scf_trans =
474*4bff34e3Sthurlow 			    scf_transaction_create(handle->scf_handle);
475*4bff34e3Sthurlow 			if (handle->scf_trans != NULL) {
476*4bff34e3Sthurlow 				if (scf_transaction_start(handle->scf_trans,
477*4bff34e3Sthurlow 				    handle->scf_pg) != 0) {
478*4bff34e3Sthurlow 					ret = SMBC_SMF_SYSTEM_ERR;
479*4bff34e3Sthurlow 					scf_transaction_destroy(
480*4bff34e3Sthurlow 					    handle->scf_trans);
481*4bff34e3Sthurlow 					handle->scf_trans = NULL;
482*4bff34e3Sthurlow 				}
483*4bff34e3Sthurlow 			} else {
484*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
485*4bff34e3Sthurlow 			}
486*4bff34e3Sthurlow 		}
487*4bff34e3Sthurlow 	}
488*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR &&
489*4bff34e3Sthurlow 	    scf_error() == SCF_ERROR_PERMISSION_DENIED) {
490*4bff34e3Sthurlow 		ret = SMBC_SMF_NO_PERMISSION;
491*4bff34e3Sthurlow 	}
492*4bff34e3Sthurlow 	return (ret);
493*4bff34e3Sthurlow }
494*4bff34e3Sthurlow 
495*4bff34e3Sthurlow /*
496*4bff34e3Sthurlow  * smb_smf_end_transaction(handle)
497*4bff34e3Sthurlow  *
498*4bff34e3Sthurlow  * Commit the changes that were added to the transaction in the
499*4bff34e3Sthurlow  * handle. Do all necessary cleanup.
500*4bff34e3Sthurlow  */
501*4bff34e3Sthurlow int
502*4bff34e3Sthurlow smb_smf_end_transaction(smb_scfhandle_t *handle)
503*4bff34e3Sthurlow {
504*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
505*4bff34e3Sthurlow 
506*4bff34e3Sthurlow 	if (handle == NULL) {
507*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
508*4bff34e3Sthurlow 	}
509*4bff34e3Sthurlow 
510*4bff34e3Sthurlow 	if (handle->scf_trans == NULL) {
511*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
512*4bff34e3Sthurlow 	} else {
513*4bff34e3Sthurlow 		if (scf_transaction_commit(handle->scf_trans) < 0) {
514*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
515*4bff34e3Sthurlow 			smb_smf_scf_log_error("Failed to commit "
516*4bff34e3Sthurlow 			    "transaction: %s");
517*4bff34e3Sthurlow 		}
518*4bff34e3Sthurlow 		scf_transaction_destroy_children(handle->scf_trans);
519*4bff34e3Sthurlow 		scf_transaction_destroy(handle->scf_trans);
520*4bff34e3Sthurlow 		handle->scf_trans = NULL;
521*4bff34e3Sthurlow 	}
522*4bff34e3Sthurlow 	return (ret);
523*4bff34e3Sthurlow }
524*4bff34e3Sthurlow 
525*4bff34e3Sthurlow /*
526*4bff34e3Sthurlow  * Deletes property in current pg
527*4bff34e3Sthurlow  */
528*4bff34e3Sthurlow int
529*4bff34e3Sthurlow smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
530*4bff34e3Sthurlow {
531*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
532*4bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
533*4bff34e3Sthurlow 
534*4bff34e3Sthurlow 	if (handle == NULL) {
535*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
536*4bff34e3Sthurlow 	}
537*4bff34e3Sthurlow 
538*4bff34e3Sthurlow 	/*
539*4bff34e3Sthurlow 	 * properties must be set in transactions and don't take
540*4bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
541*4bff34e3Sthurlow 	 */
542*4bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
543*4bff34e3Sthurlow 	if (entry != NULL) {
544*4bff34e3Sthurlow 		if (scf_transaction_property_delete(handle->scf_trans, entry,
545*4bff34e3Sthurlow 		    propname) != 0) {
546*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
547*4bff34e3Sthurlow 		}
548*4bff34e3Sthurlow 	} else {
549*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
550*4bff34e3Sthurlow 	}
551*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
552*4bff34e3Sthurlow 		switch (scf_error()) {
553*4bff34e3Sthurlow 		case SCF_ERROR_PERMISSION_DENIED:
554*4bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
555*4bff34e3Sthurlow 			break;
556*4bff34e3Sthurlow 		}
557*4bff34e3Sthurlow 	}
558*4bff34e3Sthurlow 
559*4bff34e3Sthurlow 	/*
560*4bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
561*4bff34e3Sthurlow 	 * values where they would be cleaned up later.
562*4bff34e3Sthurlow 	 */
563*4bff34e3Sthurlow 	if ((ret != SMBC_SMF_OK) && (entry != NULL)) {
564*4bff34e3Sthurlow 		scf_entry_destroy(entry);
565*4bff34e3Sthurlow 	}
566*4bff34e3Sthurlow 	return (ret);
567*4bff34e3Sthurlow }
568*4bff34e3Sthurlow 
569*4bff34e3Sthurlow /*
570*4bff34e3Sthurlow  * Sets string property in current pg
571*4bff34e3Sthurlow  */
572*4bff34e3Sthurlow int
573*4bff34e3Sthurlow smb_smf_set_string_property(smb_scfhandle_t *handle,
574*4bff34e3Sthurlow     char *propname, char *valstr)
575*4bff34e3Sthurlow {
576*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
577*4bff34e3Sthurlow 	scf_value_t *value = NULL;
578*4bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
579*4bff34e3Sthurlow 
580*4bff34e3Sthurlow 	if (handle == NULL) {
581*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
582*4bff34e3Sthurlow 	}
583*4bff34e3Sthurlow 
584*4bff34e3Sthurlow 	/*
585*4bff34e3Sthurlow 	 * properties must be set in transactions and don't take
586*4bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
587*4bff34e3Sthurlow 	 */
588*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
589*4bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
590*4bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
591*4bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
592*4bff34e3Sthurlow 		    propname, SCF_TYPE_ASTRING) == 0 ||
593*4bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
594*4bff34e3Sthurlow 		    propname, SCF_TYPE_ASTRING) == 0) {
595*4bff34e3Sthurlow 			if (scf_value_set_astring(value, valstr) == 0) {
596*4bff34e3Sthurlow 				if (scf_entry_add_value(entry, value) != 0) {
597*4bff34e3Sthurlow 					ret = SMBC_SMF_SYSTEM_ERR;
598*4bff34e3Sthurlow 					scf_value_destroy(value);
599*4bff34e3Sthurlow 				}
600*4bff34e3Sthurlow 				/* the value is in the transaction */
601*4bff34e3Sthurlow 				value = NULL;
602*4bff34e3Sthurlow 			} else {
603*4bff34e3Sthurlow 				/* value couldn't be constructed */
604*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
605*4bff34e3Sthurlow 			}
606*4bff34e3Sthurlow 			/* the entry is in the transaction */
607*4bff34e3Sthurlow 			entry = NULL;
608*4bff34e3Sthurlow 		} else {
609*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
610*4bff34e3Sthurlow 		}
611*4bff34e3Sthurlow 	} else {
612*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
613*4bff34e3Sthurlow 	}
614*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
615*4bff34e3Sthurlow 		switch (scf_error()) {
616*4bff34e3Sthurlow 		case SCF_ERROR_PERMISSION_DENIED:
617*4bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
618*4bff34e3Sthurlow 			break;
619*4bff34e3Sthurlow 		}
620*4bff34e3Sthurlow 	}
621*4bff34e3Sthurlow 
622*4bff34e3Sthurlow 	/*
623*4bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
624*4bff34e3Sthurlow 	 * values where they would be cleaned up later.
625*4bff34e3Sthurlow 	 */
626*4bff34e3Sthurlow 	if (value != NULL)
627*4bff34e3Sthurlow 		scf_value_destroy(value);
628*4bff34e3Sthurlow 	if (entry != NULL)
629*4bff34e3Sthurlow 		scf_entry_destroy(entry);
630*4bff34e3Sthurlow 	return (ret);
631*4bff34e3Sthurlow }
632*4bff34e3Sthurlow 
633*4bff34e3Sthurlow /*
634*4bff34e3Sthurlow  * Gets string property value.upto sz size.
635*4bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
636*4bff34e3Sthurlow  */
637*4bff34e3Sthurlow int
638*4bff34e3Sthurlow smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
639*4bff34e3Sthurlow     char *valstr, size_t sz)
640*4bff34e3Sthurlow {
641*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
642*4bff34e3Sthurlow 	scf_value_t *value;
643*4bff34e3Sthurlow 	scf_property_t *prop;
644*4bff34e3Sthurlow 
645*4bff34e3Sthurlow 	if (handle == NULL) {
646*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
647*4bff34e3Sthurlow 	}
648*4bff34e3Sthurlow 
649*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
650*4bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
651*4bff34e3Sthurlow 	if (value && prop &&
652*4bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
653*4bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
654*4bff34e3Sthurlow 			if (scf_value_get_astring(value, valstr, sz) < 0) {
655*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
656*4bff34e3Sthurlow 			}
657*4bff34e3Sthurlow 		} else {
658*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
659*4bff34e3Sthurlow 		}
660*4bff34e3Sthurlow 	} else {
661*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
662*4bff34e3Sthurlow 	}
663*4bff34e3Sthurlow 	if (value != NULL)
664*4bff34e3Sthurlow 		scf_value_destroy(value);
665*4bff34e3Sthurlow 	if (prop != NULL)
666*4bff34e3Sthurlow 		scf_property_destroy(prop);
667*4bff34e3Sthurlow 	return (ret);
668*4bff34e3Sthurlow }
669*4bff34e3Sthurlow 
670*4bff34e3Sthurlow /*
671*4bff34e3Sthurlow  * Get integer value of property.
672*4bff34e3Sthurlow  * The value is returned as int64_t value
673*4bff34e3Sthurlow  * Caller ensures appropriate translation.
674*4bff34e3Sthurlow  */
675*4bff34e3Sthurlow int
676*4bff34e3Sthurlow smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
677*4bff34e3Sthurlow     int64_t valint)
678*4bff34e3Sthurlow {
679*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
680*4bff34e3Sthurlow 	scf_value_t *value = NULL;
681*4bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
682*4bff34e3Sthurlow 
683*4bff34e3Sthurlow 	if (handle == NULL) {
684*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
685*4bff34e3Sthurlow 	}
686*4bff34e3Sthurlow 
687*4bff34e3Sthurlow 	/*
688*4bff34e3Sthurlow 	 * properties must be set in transactions and don't take
689*4bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
690*4bff34e3Sthurlow 	 */
691*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
692*4bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
693*4bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
694*4bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
695*4bff34e3Sthurlow 		    propname, SCF_TYPE_INTEGER) == 0 ||
696*4bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
697*4bff34e3Sthurlow 		    propname, SCF_TYPE_INTEGER) == 0) {
698*4bff34e3Sthurlow 			scf_value_set_integer(value, valint);
699*4bff34e3Sthurlow 			if (scf_entry_add_value(entry, value) != 0) {
700*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
701*4bff34e3Sthurlow 				scf_value_destroy(value);
702*4bff34e3Sthurlow 			}
703*4bff34e3Sthurlow 			/* the value is in the transaction */
704*4bff34e3Sthurlow 			value = NULL;
705*4bff34e3Sthurlow 		}
706*4bff34e3Sthurlow 		/* the entry is in the transaction */
707*4bff34e3Sthurlow 		entry = NULL;
708*4bff34e3Sthurlow 	} else {
709*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
710*4bff34e3Sthurlow 	}
711*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
712*4bff34e3Sthurlow 		switch (scf_error()) {
713*4bff34e3Sthurlow 		case SCF_ERROR_PERMISSION_DENIED:
714*4bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
715*4bff34e3Sthurlow 			break;
716*4bff34e3Sthurlow 		}
717*4bff34e3Sthurlow 	}
718*4bff34e3Sthurlow 	/*
719*4bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
720*4bff34e3Sthurlow 	 * values where they would be cleaned up later.
721*4bff34e3Sthurlow 	 */
722*4bff34e3Sthurlow 	if (value != NULL)
723*4bff34e3Sthurlow 		scf_value_destroy(value);
724*4bff34e3Sthurlow 	if (entry != NULL)
725*4bff34e3Sthurlow 		scf_entry_destroy(entry);
726*4bff34e3Sthurlow 	return (ret);
727*4bff34e3Sthurlow }
728*4bff34e3Sthurlow 
729*4bff34e3Sthurlow /*
730*4bff34e3Sthurlow  * Sets integer property value.
731*4bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
732*4bff34e3Sthurlow  */
733*4bff34e3Sthurlow int
734*4bff34e3Sthurlow smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
735*4bff34e3Sthurlow     int64_t *valint)
736*4bff34e3Sthurlow {
737*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
738*4bff34e3Sthurlow 	scf_value_t *value = NULL;
739*4bff34e3Sthurlow 	scf_property_t *prop = NULL;
740*4bff34e3Sthurlow 
741*4bff34e3Sthurlow 	if (handle == NULL) {
742*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
743*4bff34e3Sthurlow 	}
744*4bff34e3Sthurlow 
745*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
746*4bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
747*4bff34e3Sthurlow 	if ((prop) && (value) &&
748*4bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
749*4bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
750*4bff34e3Sthurlow 			if (scf_value_get_integer(value,
751*4bff34e3Sthurlow 			    valint) != 0) {
752*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
753*4bff34e3Sthurlow 			}
754*4bff34e3Sthurlow 		} else {
755*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
756*4bff34e3Sthurlow 		}
757*4bff34e3Sthurlow 	} else {
758*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
759*4bff34e3Sthurlow 	}
760*4bff34e3Sthurlow 	if (value != NULL)
761*4bff34e3Sthurlow 		scf_value_destroy(value);
762*4bff34e3Sthurlow 	if (prop != NULL)
763*4bff34e3Sthurlow 		scf_property_destroy(prop);
764*4bff34e3Sthurlow 	return (ret);
765*4bff34e3Sthurlow }
766*4bff34e3Sthurlow 
767*4bff34e3Sthurlow /*
768*4bff34e3Sthurlow  * Get boolean value of property.
769*4bff34e3Sthurlow  * The value is returned as int64_t value
770*4bff34e3Sthurlow  * Caller ensures appropriate translation.
771*4bff34e3Sthurlow  */
772*4bff34e3Sthurlow int
773*4bff34e3Sthurlow smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
774*4bff34e3Sthurlow     uint8_t valbool)
775*4bff34e3Sthurlow {
776*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
777*4bff34e3Sthurlow 	scf_value_t *value = NULL;
778*4bff34e3Sthurlow 	scf_transaction_entry_t *entry = NULL;
779*4bff34e3Sthurlow 
780*4bff34e3Sthurlow 	if (handle == NULL) {
781*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
782*4bff34e3Sthurlow 	}
783*4bff34e3Sthurlow 
784*4bff34e3Sthurlow 	/*
785*4bff34e3Sthurlow 	 * properties must be set in transactions and don't take
786*4bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
787*4bff34e3Sthurlow 	 */
788*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
789*4bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
790*4bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
791*4bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
792*4bff34e3Sthurlow 		    propname, SCF_TYPE_BOOLEAN) == 0 ||
793*4bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
794*4bff34e3Sthurlow 		    propname, SCF_TYPE_BOOLEAN) == 0) {
795*4bff34e3Sthurlow 			scf_value_set_boolean(value, valbool);
796*4bff34e3Sthurlow 			if (scf_entry_add_value(entry, value) != 0) {
797*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
798*4bff34e3Sthurlow 				scf_value_destroy(value);
799*4bff34e3Sthurlow 			}
800*4bff34e3Sthurlow 			/* the value is in the transaction */
801*4bff34e3Sthurlow 			value = NULL;
802*4bff34e3Sthurlow 		}
803*4bff34e3Sthurlow 		/* the entry is in the transaction */
804*4bff34e3Sthurlow 		entry = NULL;
805*4bff34e3Sthurlow 	} else {
806*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
807*4bff34e3Sthurlow 	}
808*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
809*4bff34e3Sthurlow 		switch (scf_error()) {
810*4bff34e3Sthurlow 		case SCF_ERROR_PERMISSION_DENIED:
811*4bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
812*4bff34e3Sthurlow 			break;
813*4bff34e3Sthurlow 		}
814*4bff34e3Sthurlow 	}
815*4bff34e3Sthurlow 	/*
816*4bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
817*4bff34e3Sthurlow 	 * values where they would be cleaned up later.
818*4bff34e3Sthurlow 	 */
819*4bff34e3Sthurlow 	if (value != NULL)
820*4bff34e3Sthurlow 		scf_value_destroy(value);
821*4bff34e3Sthurlow 	if (entry != NULL)
822*4bff34e3Sthurlow 		scf_entry_destroy(entry);
823*4bff34e3Sthurlow 	return (ret);
824*4bff34e3Sthurlow }
825*4bff34e3Sthurlow 
826*4bff34e3Sthurlow /*
827*4bff34e3Sthurlow  * Sets boolean property value.
828*4bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
829*4bff34e3Sthurlow  */
830*4bff34e3Sthurlow int
831*4bff34e3Sthurlow smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
832*4bff34e3Sthurlow     uint8_t *valbool)
833*4bff34e3Sthurlow {
834*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
835*4bff34e3Sthurlow 	scf_value_t *value = NULL;
836*4bff34e3Sthurlow 	scf_property_t *prop = NULL;
837*4bff34e3Sthurlow 
838*4bff34e3Sthurlow 	if (handle == NULL) {
839*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
840*4bff34e3Sthurlow 	}
841*4bff34e3Sthurlow 
842*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
843*4bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
844*4bff34e3Sthurlow 	if ((prop) && (value) &&
845*4bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
846*4bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
847*4bff34e3Sthurlow 			if (scf_value_get_boolean(value,
848*4bff34e3Sthurlow 			    valbool) != 0) {
849*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
850*4bff34e3Sthurlow 			}
851*4bff34e3Sthurlow 		} else {
852*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
853*4bff34e3Sthurlow 		}
854*4bff34e3Sthurlow 	} else {
855*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
856*4bff34e3Sthurlow 	}
857*4bff34e3Sthurlow 	if (value != NULL)
858*4bff34e3Sthurlow 		scf_value_destroy(value);
859*4bff34e3Sthurlow 	if (prop != NULL)
860*4bff34e3Sthurlow 		scf_property_destroy(prop);
861*4bff34e3Sthurlow 	return (ret);
862*4bff34e3Sthurlow }
863*4bff34e3Sthurlow 
864*4bff34e3Sthurlow /*
865*4bff34e3Sthurlow  * Sets a blob property value.
866*4bff34e3Sthurlow  */
867*4bff34e3Sthurlow int
868*4bff34e3Sthurlow smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
869*4bff34e3Sthurlow     void *voidval, size_t sz)
870*4bff34e3Sthurlow {
871*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
872*4bff34e3Sthurlow 	scf_value_t *value;
873*4bff34e3Sthurlow 	scf_transaction_entry_t *entry;
874*4bff34e3Sthurlow 
875*4bff34e3Sthurlow 	if (handle == NULL) {
876*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
877*4bff34e3Sthurlow 	}
878*4bff34e3Sthurlow 
879*4bff34e3Sthurlow 	/*
880*4bff34e3Sthurlow 	 * properties must be set in transactions and don't take
881*4bff34e3Sthurlow 	 * effect until the transaction has been ended/committed.
882*4bff34e3Sthurlow 	 */
883*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
884*4bff34e3Sthurlow 	entry = scf_entry_create(handle->scf_handle);
885*4bff34e3Sthurlow 	if (value != NULL && entry != NULL) {
886*4bff34e3Sthurlow 		if (scf_transaction_property_change(handle->scf_trans, entry,
887*4bff34e3Sthurlow 		    propname, SCF_TYPE_OPAQUE) == 0 ||
888*4bff34e3Sthurlow 		    scf_transaction_property_new(handle->scf_trans, entry,
889*4bff34e3Sthurlow 		    propname, SCF_TYPE_OPAQUE) == 0) {
890*4bff34e3Sthurlow 			if (scf_value_set_opaque(value, voidval, sz) == 0) {
891*4bff34e3Sthurlow 				if (scf_entry_add_value(entry, value) != 0) {
892*4bff34e3Sthurlow 					ret = SMBC_SMF_SYSTEM_ERR;
893*4bff34e3Sthurlow 					scf_value_destroy(value);
894*4bff34e3Sthurlow 				}
895*4bff34e3Sthurlow 				/* the value is in the transaction */
896*4bff34e3Sthurlow 				value = NULL;
897*4bff34e3Sthurlow 			} else {
898*4bff34e3Sthurlow 				/* value couldn't be constructed */
899*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
900*4bff34e3Sthurlow 			}
901*4bff34e3Sthurlow 			/* the entry is in the transaction */
902*4bff34e3Sthurlow 			entry = NULL;
903*4bff34e3Sthurlow 		} else {
904*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
905*4bff34e3Sthurlow 		}
906*4bff34e3Sthurlow 	} else {
907*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
908*4bff34e3Sthurlow 	}
909*4bff34e3Sthurlow 	if (ret == SMBC_SMF_SYSTEM_ERR) {
910*4bff34e3Sthurlow 		switch (scf_error()) {
911*4bff34e3Sthurlow 		case SCF_ERROR_PERMISSION_DENIED:
912*4bff34e3Sthurlow 			ret = SMBC_SMF_NO_PERMISSION;
913*4bff34e3Sthurlow 			break;
914*4bff34e3Sthurlow 		}
915*4bff34e3Sthurlow 	}
916*4bff34e3Sthurlow 	/*
917*4bff34e3Sthurlow 	 * cleanup if there were any errors that didn't leave these
918*4bff34e3Sthurlow 	 * values where they would be cleaned up later.
919*4bff34e3Sthurlow 	 */
920*4bff34e3Sthurlow 	if (value != NULL)
921*4bff34e3Sthurlow 		scf_value_destroy(value);
922*4bff34e3Sthurlow 	if (entry != NULL)
923*4bff34e3Sthurlow 		scf_entry_destroy(entry);
924*4bff34e3Sthurlow 	return (ret);
925*4bff34e3Sthurlow }
926*4bff34e3Sthurlow 
927*4bff34e3Sthurlow /*
928*4bff34e3Sthurlow  * Gets a blob property value.
929*4bff34e3Sthurlow  * Caller is responsible to have enough memory allocated.
930*4bff34e3Sthurlow  */
931*4bff34e3Sthurlow int
932*4bff34e3Sthurlow smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
933*4bff34e3Sthurlow     void *v, size_t sz)
934*4bff34e3Sthurlow {
935*4bff34e3Sthurlow 	int ret = SMBC_SMF_OK;
936*4bff34e3Sthurlow 	scf_value_t *value = NULL;
937*4bff34e3Sthurlow 	scf_property_t *prop = NULL;
938*4bff34e3Sthurlow 
939*4bff34e3Sthurlow 	if (handle == NULL) {
940*4bff34e3Sthurlow 		return (SMBC_SMF_SYSTEM_ERR);
941*4bff34e3Sthurlow 	}
942*4bff34e3Sthurlow 
943*4bff34e3Sthurlow 	value = scf_value_create(handle->scf_handle);
944*4bff34e3Sthurlow 	prop = scf_property_create(handle->scf_handle);
945*4bff34e3Sthurlow 	if ((prop) && (value) &&
946*4bff34e3Sthurlow 	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
947*4bff34e3Sthurlow 		if (scf_property_get_value(prop, value) == 0) {
948*4bff34e3Sthurlow 			if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
949*4bff34e3Sthurlow 				ret = SMBC_SMF_SYSTEM_ERR;
950*4bff34e3Sthurlow 			}
951*4bff34e3Sthurlow 		} else {
952*4bff34e3Sthurlow 			ret = SMBC_SMF_SYSTEM_ERR;
953*4bff34e3Sthurlow 		}
954*4bff34e3Sthurlow 	} else {
955*4bff34e3Sthurlow 		ret = SMBC_SMF_SYSTEM_ERR;
956*4bff34e3Sthurlow 	}
957*4bff34e3Sthurlow 	if (value != NULL)
958*4bff34e3Sthurlow 		scf_value_destroy(value);
959*4bff34e3Sthurlow 	if (prop != NULL)
960*4bff34e3Sthurlow 		scf_property_destroy(prop);
961*4bff34e3Sthurlow 	return (ret);
962*4bff34e3Sthurlow }
963*4bff34e3Sthurlow 
964*4bff34e3Sthurlow /*
965*4bff34e3Sthurlow  * Gets an instance iterator for the service specified.
966*4bff34e3Sthurlow  */
967*4bff34e3Sthurlow smb_scfhandle_t *
968*4bff34e3Sthurlow smb_smf_get_iterator(char *svc_name)
969*4bff34e3Sthurlow {
970*4bff34e3Sthurlow 	smb_scfhandle_t *handle = NULL;
971*4bff34e3Sthurlow 
972*4bff34e3Sthurlow 	handle = smb_smf_scf_init(svc_name);
973*4bff34e3Sthurlow 	if (!handle) {
974*4bff34e3Sthurlow 		return (NULL);
975*4bff34e3Sthurlow 	}
976*4bff34e3Sthurlow 
977*4bff34e3Sthurlow 	handle->scf_inst_iter = scf_iter_create(handle->scf_handle);
978*4bff34e3Sthurlow 	if (handle->scf_inst_iter) {
979*4bff34e3Sthurlow 		if (scf_iter_service_instances(handle->scf_inst_iter,
980*4bff34e3Sthurlow 		    handle->scf_service) != 0) {
981*4bff34e3Sthurlow 			smb_smf_scf_fini(handle);
982*4bff34e3Sthurlow 			handle = NULL;
983*4bff34e3Sthurlow 		} else {
984*4bff34e3Sthurlow 			handle->scf_instance = NULL;
985*4bff34e3Sthurlow 		}
986*4bff34e3Sthurlow 	} else {
987*4bff34e3Sthurlow 		smb_smf_scf_fini(handle);
988*4bff34e3Sthurlow 		handle = NULL;
989*4bff34e3Sthurlow 	}
990*4bff34e3Sthurlow 	return (handle);
991*4bff34e3Sthurlow }
992