components/visual-panels/smf/src/cmd/rad/mod/smf/common.c
branchs11-update
changeset 2805 4888f6212f94
parent 2804 7546c836fd87
child 2806 8ac3cbf66125
equal deleted inserted replaced
2804:7546c836fd87 2805:4888f6212f94
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 #include <stdio.h>
       
    27 #include <string.h>
       
    28 #include <rad/adr.h>
       
    29 #include <rad/adr_object.h>
       
    30 #include <rad/rad_modapi.h>
       
    31 #include "api_smf.h"
       
    32 #include "smfutil.h"
       
    33 #include "rhandle.h"
       
    34 #include "datatype.h"
       
    35 
       
    36 /*ARGSUSED*/
       
    37 conerr_t
       
    38 interface_Entity_read_fmri(rad_instance_t *inst, adr_attribute_t *attr,
       
    39     adr_data_t **data, adr_data_t **error)
       
    40 {
       
    41 	smfobj_t *smfo = instance_getdata(inst);
       
    42 	*data = adr_data_new_string(smfo->fmri, LT_COPY);
       
    43 	return (*data == NULL ? ce_nomem : ce_ok);
       
    44 }
       
    45 
       
    46 /*ARGSUSED*/
       
    47 conerr_t
       
    48 interface_Entity_read_scope(rad_instance_t *inst, adr_attribute_t *attr,
       
    49     adr_data_t **data, adr_data_t **error)
       
    50 {
       
    51 	*data = adr_data_new_string("localhost", LT_CONST);
       
    52 	return (*data == NULL ? ce_nomem : ce_ok);
       
    53 }
       
    54 
       
    55 /*ARGSUSED*/
       
    56 conerr_t
       
    57 interface_Entity_read_service(rad_instance_t *inst, adr_attribute_t *attr,
       
    58     adr_data_t **data, adr_data_t **error)
       
    59 {
       
    60 	smfobj_t *smfo = instance_getdata(inst);
       
    61 	*data = adr_data_new_string(smfo->sname, LT_COPY);
       
    62 	return (*data == NULL ? ce_nomem : ce_ok);
       
    63 }
       
    64 
       
    65 
       
    66 /*
       
    67  * Common retry callback for collecting data from property groups
       
    68  * directly attached to a service or in the running snapshot of an
       
    69  * instance.  Will scan only property groups of the specified type,
       
    70  * and will return an array of the specified ADR type.
       
    71  *
       
    72  * An error of SE_NOTFOUND from a callback routine indicates the
       
    73  * property group isn't of interest and should be skipped.
       
    74  */
       
    75 
       
    76 struct pgargs {
       
    77 	smfobj_t *smfo;
       
    78 	adr_type_t *type;
       
    79 	const char *pgtype;
       
    80 	svcerr_t (*cb)(scf_handle_t *, scf_propertygroup_t *, adr_data_t **);
       
    81 };
       
    82 
       
    83 /*ARGSUSED*/
       
    84 static svcerr_t
       
    85 rt_collect_pgs(scf_handle_t *h, void *arg, adr_data_t **ret, adr_data_t **error)
       
    86 {
       
    87 	struct pgargs *pga = arg;
       
    88 	smfobj_t *smfo = pga->smfo;
       
    89 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
    90 	svcerr_t se = SE_OK;
       
    91 	adr_data_t *result = adr_data_new_array(pga->type, 5);
       
    92 	scf_propertygroup_t *pg = scf_pg_create(h);
       
    93 	scf_iter_t *iter = scf_iter_create(h);
       
    94 
       
    95 	if (pg == NULL || iter == NULL) {
       
    96 		se = SE_FATAL;
       
    97 		goto done;
       
    98 	}
       
    99 
       
   100 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   101 		goto done;
       
   102 
       
   103 	if ((se = smfu_iter_pg_r(h, &entity, pga->pgtype, iter)) != SE_OK)
       
   104 		goto done;
       
   105 
       
   106 	int err;
       
   107 	while ((err = scf_iter_next_pg(iter, pg)) > 0) {
       
   108 		adr_data_t *item = NULL;
       
   109 		se = pga->cb(h, pg, &item);
       
   110 		if (se == SE_OK)
       
   111 			(void) adr_array_add(result, item);
       
   112 		else if (se != SE_NOTFOUND)
       
   113 			goto done;
       
   114 	}
       
   115 	se = (err != 0) ? smfu_maperr(scf_error()) : SE_OK;
       
   116 
       
   117 done:
       
   118 	scf_iter_destroy(iter);
       
   119 	smfu_entity_destroy(&entity);
       
   120 	scf_pg_destroy(pg);
       
   121 
       
   122 	*ret = result;
       
   123 	return (se);
       
   124 }
       
   125 
       
   126 /*ARGSUSED*/
       
   127 conerr_t
       
   128 interface_Entity_read_dependencies(rad_instance_t *inst, adr_attribute_t *attr,
       
   129     adr_data_t **data, adr_data_t **error)
       
   130 {
       
   131 	struct pgargs pga = {
       
   132 		.smfo = instance_getdata(inst),
       
   133 		.type = &t_array__Dependency,
       
   134 		.pgtype = SCF_GROUP_DEPENDENCY,
       
   135 		.cb = create_Dependency
       
   136 	};
       
   137 	return (smfu_rtrun(rt_collect_pgs, &pga, data, error));
       
   138 }
       
   139 
       
   140 /*ARGSUSED*/
       
   141 conerr_t
       
   142 interface_Entity_read_manpages(rad_instance_t *inst, adr_attribute_t *attr,
       
   143     adr_data_t **data, adr_data_t **error)
       
   144 {
       
   145 	struct pgargs pga = {
       
   146 		.smfo = instance_getdata(inst),
       
   147 		.type = &t_array__Manpage,
       
   148 		.pgtype = SCF_GROUP_TEMPLATE,
       
   149 		.cb = create_Manpage
       
   150 	};
       
   151 	return (smfu_rtrun(rt_collect_pgs, &pga, data, error));
       
   152 }
       
   153 
       
   154 /*ARGSUSED*/
       
   155 conerr_t
       
   156 interface_Entity_read_doclinks(rad_instance_t *inst, adr_attribute_t *attr,
       
   157     adr_data_t **data, adr_data_t **error)
       
   158 {
       
   159 	struct pgargs pga = {
       
   160 		.smfo = instance_getdata(inst),
       
   161 		.type = &t_array__Doclink,
       
   162 		.pgtype = SCF_GROUP_TEMPLATE,
       
   163 		.cb = create_Doclink
       
   164 	};
       
   165 	return (smfu_rtrun(rt_collect_pgs, &pga, data, error));
       
   166 }
       
   167 
       
   168 /*ARGSUSED*/
       
   169 static svcerr_t
       
   170 rt_read_pgs(scf_handle_t *h, void *arg, adr_data_t **ret, adr_data_t **error)
       
   171 {
       
   172 	smfobj_t *smfo = arg;
       
   173 	svcerr_t se = SE_OK;
       
   174 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   175 
       
   176 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   177 	scf_iter_t *iter = scf_iter_create(h);
       
   178 	adr_data_t *result = adr_data_new_array(&t_array__PropertyGroup, 5);
       
   179 
       
   180 	if (pg == NULL || iter == NULL) {
       
   181 		se = SE_FATAL;
       
   182 		goto done;
       
   183 	}
       
   184 
       
   185 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   186 		goto done;
       
   187 
       
   188 	if ((se = smfu_iter_pg(&entity, NULL, iter)) != SE_OK)
       
   189 		goto done;
       
   190 
       
   191 	int e;
       
   192 	while ((e = scf_iter_next_pg(iter, pg)) > 0) {
       
   193 		adr_data_t *pgdata;
       
   194 		if ((se = create_PropertyGroup(pg, &pgdata)) != SE_OK)
       
   195 			goto done;
       
   196 		(void) adr_array_add(result, pgdata);
       
   197 	}
       
   198 	if (e != 0)
       
   199 		se = smfu_maperr(scf_error());
       
   200 
       
   201 done:
       
   202 	scf_iter_destroy(iter);
       
   203 	scf_pg_destroy(pg);
       
   204 	smfu_entity_destroy(&entity);
       
   205 
       
   206 	*ret = result;
       
   207 	return (se);
       
   208 }
       
   209 
       
   210 /*ARGSUSED*/
       
   211 conerr_t
       
   212 interface_Entity_read_pgs(rad_instance_t *inst, adr_attribute_t *attr,
       
   213     adr_data_t **data, adr_data_t **error)
       
   214 {
       
   215 	return (smfu_rtrun(rt_read_pgs, instance_getdata(inst), data, error));
       
   216 }
       
   217 
       
   218 
       
   219 /*ARGSUSED*/
       
   220 static svcerr_t
       
   221 rt_invoke_delete(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   222     adr_data_t **error)
       
   223 {
       
   224 	smfobj_t *smfo = arg;
       
   225 	svcerr_t se = SE_OK;
       
   226 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   227 
       
   228 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   229 		goto done;
       
   230 
       
   231 	int e = (entity.instance != NULL) ?
       
   232 	    scf_instance_delete(entity.instance) :
       
   233 	    scf_service_delete(entity.service);
       
   234 
       
   235 	if (e != 0) {
       
   236 		switch (scf_error()) {
       
   237 		case SCF_ERROR_PERMISSION_DENIED:
       
   238 			se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   239 			    NULL, NULL);
       
   240 			break;
       
   241 		case SCF_ERROR_BACKEND_READONLY:
       
   242 			se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   243 			    NULL, NULL);
       
   244 			break;
       
   245 		case SCF_ERROR_EXISTS:
       
   246 			se = error_scf(error, &e__ErrorCode_EXISTS, NULL,
       
   247 			    NULL, NULL);
       
   248 			break;
       
   249 		default:
       
   250 			se = smfu_maperr(scf_error());
       
   251 		}
       
   252 	}
       
   253 done:
       
   254 	smfu_entity_destroy(&entity);
       
   255 	return (se);
       
   256 }
       
   257 
       
   258 /*ARGSUSED*/
       
   259 conerr_t
       
   260 interface_Entity_invoke_delete(rad_instance_t *inst, adr_method_t *meth,
       
   261     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   262 {
       
   263 	return (smfu_rtrun(rt_invoke_delete, instance_getdata(inst), NULL,
       
   264 	    error));
       
   265 }
       
   266 
       
   267 
       
   268 /*ARGSUSED*/
       
   269 static svcerr_t
       
   270 rt_invoke_deleteCust(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   271     adr_data_t **error)
       
   272 {
       
   273 	smfobj_t *smfo = arg;
       
   274 	svcerr_t se = SE_OK;
       
   275 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   276 
       
   277 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   278 		goto done;
       
   279 
       
   280 	int e = (entity.instance != NULL) ?
       
   281 	    scf_instance_delcust(entity.instance) :
       
   282 	    scf_service_delcust(entity.service);
       
   283 
       
   284 	if (e != 0) {
       
   285 		switch (scf_error()) {
       
   286 		case SCF_ERROR_PERMISSION_DENIED:
       
   287 			se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   288 			    NULL, NULL);
       
   289 			break;
       
   290 		case SCF_ERROR_BACKEND_READONLY:
       
   291 			se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   292 			    NULL, NULL);
       
   293 			break;
       
   294 		case SCF_ERROR_DELETED:
       
   295 			se = error_scf(error, &e__ErrorCode_NOTFOUND, NULL,
       
   296 			    (entity.instance != NULL) ? smfo->iname :
       
   297 			    smfo->sname, NULL);
       
   298 			break;
       
   299 		default:
       
   300 			se = smfu_maperr(scf_error());
       
   301 		}
       
   302 	}
       
   303 done:
       
   304 	smfu_entity_destroy(&entity);
       
   305 	return (se);
       
   306 }
       
   307 
       
   308 /*ARGSUSED*/
       
   309 conerr_t
       
   310 interface_Entity_invoke_deleteCust(rad_instance_t *inst, adr_method_t *meth,
       
   311     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   312 {
       
   313 	return (smfu_rtrun(rt_invoke_deleteCust, instance_getdata(inst), NULL,
       
   314 	    error));
       
   315 }
       
   316 
       
   317 /*ARGSUSED*/
       
   318 static svcerr_t
       
   319 rt_invoke_createPG(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   320     adr_data_t **error)
       
   321 {
       
   322 	radarg_t *ra = arg;
       
   323 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   324 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   325 	const char *pgtype = adr_data_to_string(ra->args[1]);
       
   326 	unsigned int pgflags = adr_data_to_uinteger(ra->args[2]);
       
   327 	svcerr_t se = SE_OK;
       
   328 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   329 
       
   330 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   331 		goto done;
       
   332 
       
   333 	int e = (entity.instance != NULL) ?
       
   334 	    scf_instance_add_pg(entity.instance, pgname, pgtype,
       
   335 	    pgflags, NULL) :
       
   336 	    scf_service_add_pg(entity.service, pgname, pgtype,
       
   337 	    pgflags, NULL);
       
   338 
       
   339 	if (e != 0) {
       
   340 		switch (scf_error()) {
       
   341 		case SCF_ERROR_INVALID_ARGUMENT:
       
   342 			se = error_scf(error, &e__ErrorCode_BADVALUE,
       
   343 			    &e__ErrorTarget_PROPERTYGROUP, NULL, NULL);
       
   344 			break;
       
   345 		case SCF_ERROR_PERMISSION_DENIED:
       
   346 			se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   347 			    NULL, NULL);
       
   348 			break;
       
   349 		case SCF_ERROR_BACKEND_READONLY:
       
   350 			se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   351 			    NULL, NULL);
       
   352 			break;
       
   353 		case SCF_ERROR_EXISTS:
       
   354 			se = error_scf(error, &e__ErrorCode_EXISTS,
       
   355 			    &e__ErrorTarget_PROPERTYGROUP, NULL, NULL);
       
   356 			break;
       
   357 		default:
       
   358 			se = smfu_maperr(scf_error());
       
   359 		}
       
   360 	}
       
   361 done:
       
   362 	smfu_entity_destroy(&entity);
       
   363 	return (se);
       
   364 }
       
   365 
       
   366 /*ARGSUSED*/
       
   367 conerr_t
       
   368 interface_Entity_invoke_createPG(rad_instance_t *inst, adr_method_t *meth,
       
   369     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   370 {
       
   371 	radarg_t ra = { .inst = inst, .args = args };
       
   372 	return (smfu_rtrun(rt_invoke_createPG, &ra, NULL, error));
       
   373 }
       
   374 
       
   375 
       
   376 /*ARGSUSED*/
       
   377 static svcerr_t
       
   378 rt_invoke_deletePG(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   379     adr_data_t **error)
       
   380 {
       
   381 	radarg_t *ra = arg;
       
   382 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   383 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   384 	svcerr_t se = SE_OK;
       
   385 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   386 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   387 
       
   388 	if (pg == NULL) {
       
   389 		se = SE_FATAL;
       
   390 		goto done;
       
   391 	}
       
   392 
       
   393 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   394 		goto done;
       
   395 
       
   396 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   397 		goto done;
       
   398 
       
   399 	if (scf_pg_delete(pg) != 0) {
       
   400 		switch (scf_error()) {
       
   401 		case SCF_ERROR_PERMISSION_DENIED:
       
   402 			se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   403 			    NULL, NULL);
       
   404 			break;
       
   405 		case SCF_ERROR_BACKEND_READONLY:
       
   406 			se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   407 			    NULL, NULL);
       
   408 			break;
       
   409 		default:
       
   410 			se = smfu_maperr(scf_error());
       
   411 		}
       
   412 	}
       
   413 
       
   414 done:
       
   415 	scf_pg_destroy(pg);
       
   416 	smfu_entity_destroy(&entity);
       
   417 	return (se);
       
   418 }
       
   419 
       
   420 /*ARGSUSED*/
       
   421 conerr_t
       
   422 interface_Entity_invoke_deletePG(rad_instance_t *inst, adr_method_t *meth,
       
   423     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   424 {
       
   425 	radarg_t ra = { .inst = inst, .args = args };
       
   426 	return (smfu_rtrun(rt_invoke_deletePG, &ra, NULL, error));
       
   427 }
       
   428 
       
   429 
       
   430 /*ARGSUSED*/
       
   431 static svcerr_t
       
   432 rt_invoke_deletePGCust(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   433     adr_data_t **error)
       
   434 {
       
   435 	radarg_t *ra = arg;
       
   436 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   437 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   438 	svcerr_t se = SE_OK;
       
   439 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   440 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   441 
       
   442 	if (pg == NULL) {
       
   443 		se = SE_FATAL;
       
   444 		goto done;
       
   445 	}
       
   446 
       
   447 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   448 		goto done;
       
   449 
       
   450 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   451 		goto done;
       
   452 
       
   453 	if (scf_pg_delcust(pg) != 0) {
       
   454 		switch (scf_error()) {
       
   455 		case SCF_ERROR_PERMISSION_DENIED:
       
   456 			se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   457 			    NULL, NULL);
       
   458 			break;
       
   459 		case SCF_ERROR_BACKEND_READONLY:
       
   460 			se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   461 			    NULL, NULL);
       
   462 			break;
       
   463 		case SCF_ERROR_DELETED:
       
   464 			se = error_scf(error, &e__ErrorCode_NOTFOUND,
       
   465 			    &e__ErrorTarget_PROPERTYGROUP, pgname, NULL);
       
   466 			break;
       
   467 		default:
       
   468 			se = smfu_maperr(scf_error());
       
   469 		}
       
   470 	}
       
   471 
       
   472 done:
       
   473 	scf_pg_destroy(pg);
       
   474 	smfu_entity_destroy(&entity);
       
   475 	return (se);
       
   476 }
       
   477 
       
   478 /*ARGSUSED*/
       
   479 conerr_t
       
   480 interface_Entity_invoke_deletePGCust(rad_instance_t *inst, adr_method_t *meth,
       
   481     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   482 {
       
   483 	radarg_t ra = { .inst = inst, .args = args };
       
   484 	return (smfu_rtrun(rt_invoke_deletePGCust, &ra, NULL, error));
       
   485 }
       
   486 
       
   487 static svcerr_t
       
   488 rt_invoke_readProperties(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   489     adr_data_t **error)
       
   490 {
       
   491 	radarg_t *ra = arg;
       
   492 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   493 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   494 	svcerr_t se = SE_OK;
       
   495 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   496 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   497 
       
   498 	if (pg == NULL) {
       
   499 		se = SE_FATAL;
       
   500 		goto done;
       
   501 	}
       
   502 
       
   503 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   504 		goto done;
       
   505 
       
   506 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   507 		goto done;
       
   508 
       
   509 	se = create_Properties(h, pg, ret, error);
       
   510 done:
       
   511 	scf_pg_destroy(pg);
       
   512 	smfu_entity_destroy(&entity);
       
   513 	return (se);
       
   514 }
       
   515 
       
   516 /*ARGSUSED*/
       
   517 conerr_t
       
   518 interface_Entity_invoke_readProperties(rad_instance_t *inst, adr_method_t *meth,
       
   519     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   520 {
       
   521 	radarg_t ra = { .inst = inst, .args = args };
       
   522 	return (smfu_rtrun(rt_invoke_readProperties, &ra, ret, error));
       
   523 }
       
   524 
       
   525 /*ARGSUSED*/
       
   526 static svcerr_t
       
   527 tx_write_prop(scf_handle_t *h, scf_transaction_t *tx,
       
   528     const char *name, scf_type_t type, adr_data_t *values, adr_data_t **error)
       
   529 {
       
   530 	scf_transaction_entry_t *entry = scf_entry_create(h);
       
   531 
       
   532 	if (entry == NULL)
       
   533 		return (SE_FATAL);
       
   534 
       
   535 	int r = scf_transaction_property_change(tx, entry, name, type);
       
   536 	if (r == -1) {
       
   537 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
       
   538 			r = scf_transaction_property_new(tx, entry, name, type);
       
   539 		} else if (scf_error() == SCF_ERROR_TYPE_MISMATCH) {
       
   540 			r = scf_transaction_property_change_type(tx, entry,
       
   541 			    name, type);
       
   542 		}
       
   543 
       
   544 		if (r == -1) {
       
   545 			int e = scf_error();
       
   546 			scf_entry_destroy(entry);
       
   547 			if (e == SCF_ERROR_INVALID_ARGUMENT)
       
   548 				return (error_scf(error, &e__ErrorCode_BADVALUE,
       
   549 				    &e__ErrorTarget_PROPERTY, name, NULL));
       
   550 			else if (e == SCF_ERROR_IN_USE)
       
   551 				return (error_scf(error, &e__ErrorCode_INVALID,
       
   552 				    &e__ErrorTarget_PROPERTY, name, NULL));
       
   553 			return (smfu_maperr(e));
       
   554 		}
       
   555 	}
       
   556 
       
   557 	int nvalues = adr_array_size(values);
       
   558 	for (int i = 0; i < nvalues; i++) {
       
   559 		const char *vstr = adr_data_to_string(adr_array_get(values, i));
       
   560 		scf_value_t *v = scf_value_create(h);
       
   561 		if (v == NULL)
       
   562 			return (SE_FATAL);
       
   563 		if (scf_value_set_from_string(v, type, vstr) == -1 ||
       
   564 		    scf_entry_add_value(entry, v) == -1) {
       
   565 			int e = scf_error();
       
   566 			scf_value_destroy(v);
       
   567 			if (e == SCF_ERROR_INVALID_ARGUMENT)
       
   568 				return (error_scf(error, &e__ErrorCode_BADVALUE,
       
   569 				    &e__ErrorTarget_VALUE, name, NULL));
       
   570 			return (smfu_maperr(e));
       
   571 		}
       
   572 	}
       
   573 
       
   574 	return (SE_OK);
       
   575 }
       
   576 
       
   577 /*ARGSUSED*/
       
   578 static svcerr_t
       
   579 rt_invoke_writeProperties(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   580     adr_data_t **error)
       
   581 {
       
   582 	radarg_t *ra = arg;
       
   583 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   584 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   585 	adr_data_t *data = ra->args[1];
       
   586 	svcerr_t se = SE_OK;
       
   587 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   588 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   589 	scf_transaction_t *tx = scf_transaction_create(h);
       
   590 
       
   591 	if (pg == NULL || tx == NULL) {
       
   592 		se = SE_FATAL;
       
   593 		goto done;
       
   594 	}
       
   595 
       
   596 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   597 		goto done;
       
   598 
       
   599 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   600 		goto done;
       
   601 
       
   602 top:
       
   603 	if (scf_transaction_start(tx, pg) == -1)
       
   604 		goto txerror;
       
   605 
       
   606 	int nprops = adr_array_size(data);
       
   607 	for (int i = 0; i < nprops; i++) {
       
   608 		adr_data_t *propdata = adr_array_get(data, i);
       
   609 		const char *propname =
       
   610 		    adr_data_to_string(adr_struct_get(propdata, "name"));
       
   611 		scf_type_t proptype =
       
   612 		    from_PropertyType(adr_struct_get(propdata, "type"));
       
   613 		adr_data_t *values = adr_struct_get(propdata, "values");
       
   614 
       
   615 		se = tx_write_prop(h, tx, propname, proptype, values, error);
       
   616 		if (se != SE_OK)
       
   617 			goto done;
       
   618 	}
       
   619 
       
   620 	int r;
       
   621 	if ((r = scf_transaction_commit(tx)) == 1)
       
   622 		goto done;
       
   623 
       
   624 	if (r == 0 && scf_pg_update(pg) != -1) {
       
   625 		scf_transaction_destroy_children(tx);
       
   626 		scf_transaction_reset(tx);
       
   627 		goto top;
       
   628 	}
       
   629 
       
   630 txerror:
       
   631 	switch (scf_error()) {
       
   632 	case SCF_ERROR_PERMISSION_DENIED:
       
   633 		se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   634 		    NULL, NULL);
       
   635 		break;
       
   636 	case SCF_ERROR_BACKEND_READONLY:
       
   637 		se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   638 		    NULL, NULL);
       
   639 		break;
       
   640 	default:
       
   641 		se = smfu_maperr(scf_error());
       
   642 	}
       
   643 
       
   644 done:
       
   645 	scf_transaction_destroy_children(tx);
       
   646 	scf_transaction_destroy(tx);
       
   647 	scf_pg_destroy(pg);
       
   648 
       
   649 	return (se);
       
   650 }
       
   651 
       
   652 /*ARGSUSED*/
       
   653 conerr_t
       
   654 interface_Entity_invoke_writeProperties(rad_instance_t *inst,
       
   655     adr_method_t *meth, adr_data_t **ret, adr_data_t **args, int count,
       
   656     adr_data_t **error)
       
   657 {
       
   658 	radarg_t ra = { .inst = inst, .args = args };
       
   659 	return (smfu_rtrun(rt_invoke_writeProperties, &ra, NULL, error));
       
   660 }
       
   661 
       
   662 static svcerr_t
       
   663 rt_invoke_readProperty(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   664     adr_data_t **error)
       
   665 {
       
   666 	radarg_t *ra = arg;
       
   667 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   668 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   669 	const char *propname = adr_data_to_string(ra->args[1]);
       
   670 	svcerr_t se = SE_OK;
       
   671 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   672 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   673 	scf_property_t *prop = scf_property_create(h);
       
   674 	scf_iter_t *iter = scf_iter_create(h);
       
   675 	scf_value_t *value = scf_value_create(h);
       
   676 
       
   677 	if (pg == NULL || prop == NULL || iter == NULL || value == NULL) {
       
   678 		se = SE_FATAL;
       
   679 		goto done;
       
   680 	}
       
   681 
       
   682 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   683 		goto done;
       
   684 
       
   685 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   686 		goto done;
       
   687 
       
   688 	if (scf_pg_get_property(pg, propname, prop) == -1) {
       
   689 		if ((se = smfu_maperr(scf_error())) == SE_NOTFOUND)
       
   690 			(void) error_scf(error, &e__ErrorCode_NOTFOUND,
       
   691 			    &e__ErrorTarget_PROPERTY, NULL, NULL);
       
   692 		goto done;
       
   693 	}
       
   694 	se = create_Property(prop, iter, value, ret, error);
       
   695 done:
       
   696 	scf_value_destroy(value);
       
   697 	scf_iter_destroy(iter);
       
   698 	scf_property_destroy(prop);
       
   699 	scf_pg_destroy(pg);
       
   700 	smfu_entity_destroy(&entity);
       
   701 	return (se);
       
   702 }
       
   703 
       
   704 /*ARGSUSED*/
       
   705 conerr_t
       
   706 interface_Entity_invoke_readProperty(rad_instance_t *inst, adr_method_t *meth,
       
   707     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   708 {
       
   709 	radarg_t ra = { .inst = inst, .args = args };
       
   710 	return (smfu_rtrun(rt_invoke_readProperty, &ra, ret, error));
       
   711 }
       
   712 
       
   713 
       
   714 /*ARGSUSED*/
       
   715 static svcerr_t
       
   716 rt_invoke_writeProperty(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   717     adr_data_t **error)
       
   718 {
       
   719 	radarg_t *ra = arg;
       
   720 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   721 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   722 	const char *propname = adr_data_to_string(ra->args[1]);
       
   723 	scf_type_t proptype = from_PropertyType(ra->args[2]);
       
   724 	adr_data_t *data = ra->args[3];
       
   725 	svcerr_t se = SE_OK;
       
   726 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   727 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   728 	scf_transaction_t *tx = scf_transaction_create(h);
       
   729 
       
   730 	if (pg == NULL || tx == NULL) {
       
   731 		se = internal_error(error, NULL);
       
   732 		goto done;
       
   733 	}
       
   734 
       
   735 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   736 		goto done;
       
   737 
       
   738 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   739 		goto done;
       
   740 
       
   741 top:
       
   742 	if (scf_transaction_start(tx, pg) == -1)
       
   743 		goto txerror;
       
   744 
       
   745 	if ((se = tx_write_prop(h, tx, propname, proptype, data, error))
       
   746 	    != SE_OK)
       
   747 		goto done;
       
   748 
       
   749 	int r;
       
   750 	if ((r = scf_transaction_commit(tx)) == 1)
       
   751 		goto done;
       
   752 
       
   753 	if (r == 0 && scf_pg_update(pg) != -1) {
       
   754 		scf_transaction_destroy_children(tx);
       
   755 		scf_transaction_reset(tx);
       
   756 		goto top;
       
   757 	}
       
   758 
       
   759 txerror:
       
   760 	switch (scf_error()) {
       
   761 	case SCF_ERROR_PERMISSION_DENIED:
       
   762 		se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   763 		    NULL, NULL);
       
   764 		break;
       
   765 	case SCF_ERROR_BACKEND_READONLY:
       
   766 		se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   767 		    NULL, NULL);
       
   768 		break;
       
   769 	default:
       
   770 		se = smfu_maperr(scf_error());
       
   771 	}
       
   772 
       
   773 done:
       
   774 	scf_transaction_destroy_children(tx);
       
   775 	scf_transaction_destroy(tx);
       
   776 	scf_pg_destroy(pg);
       
   777 
       
   778 	return (se);
       
   779 }
       
   780 
       
   781 /*ARGSUSED*/
       
   782 conerr_t
       
   783 interface_Entity_invoke_writeProperty(rad_instance_t *inst, adr_method_t *meth,
       
   784     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   785 {
       
   786 	radarg_t ra = { .inst = inst, .args = args };
       
   787 	return (smfu_rtrun(rt_invoke_writeProperty, &ra, NULL, error));
       
   788 }
       
   789 
       
   790 static svcerr_t
       
   791 tx_delete_prop(scf_handle_t *h, scf_transaction_t *tx,
       
   792     const char *name, adr_data_t **error)
       
   793 {
       
   794 	scf_transaction_entry_t *entry = scf_entry_create(h);
       
   795 
       
   796 	if (entry == NULL)
       
   797 		return (SE_FATAL);
       
   798 
       
   799 	if (scf_transaction_property_delete(tx, entry, name) == -1) {
       
   800 		int e = scf_error();
       
   801 		scf_entry_destroy(entry);
       
   802 		switch (e) {
       
   803 		case SCF_ERROR_NOT_FOUND:
       
   804 			return (error_scf(error, &e__ErrorCode_NOTFOUND,
       
   805 			    &e__ErrorTarget_PROPERTY, name, NULL));
       
   806 		case SCF_ERROR_INVALID_ARGUMENT:
       
   807 			return (error_scf(error, &e__ErrorCode_BADVALUE,
       
   808 			    &e__ErrorTarget_PROPERTY, name, NULL));
       
   809 		case SCF_ERROR_IN_USE:
       
   810 			return (error_scf(error, &e__ErrorCode_INVALID,
       
   811 			    &e__ErrorTarget_PROPERTY, name, NULL));
       
   812 		}
       
   813 		return (smfu_maperr(e));
       
   814 	}
       
   815 	return (SE_OK);
       
   816 }
       
   817 
       
   818 /*ARGSUSED*/
       
   819 static svcerr_t
       
   820 rt_invoke_deleteProperty(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   821     adr_data_t **error)
       
   822 {
       
   823 	radarg_t *ra = arg;
       
   824 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   825 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   826 	const char *propname = adr_data_to_string(ra->args[1]);
       
   827 	svcerr_t se = SE_OK;
       
   828 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   829 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   830 	scf_transaction_t *tx = scf_transaction_create(h);
       
   831 
       
   832 	if (pg == NULL || tx == NULL) {
       
   833 		se = internal_error(error, NULL);
       
   834 		goto done;
       
   835 	}
       
   836 
       
   837 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   838 		goto done;
       
   839 
       
   840 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   841 		goto done;
       
   842 
       
   843 top:
       
   844 	if (scf_transaction_start(tx, pg) == -1)
       
   845 		goto txerror;
       
   846 
       
   847 	if ((se = tx_delete_prop(h, tx, propname, error)) != SE_OK)
       
   848 		goto done;
       
   849 
       
   850 	int r;
       
   851 	if ((r = scf_transaction_commit(tx)) == 1)
       
   852 		goto done;
       
   853 
       
   854 	if (r == 0 && scf_pg_update(pg) != -1) {
       
   855 		scf_transaction_destroy_children(tx);
       
   856 		scf_transaction_reset(tx);
       
   857 		goto top;
       
   858 	}
       
   859 
       
   860 txerror:
       
   861 	switch (scf_error()) {
       
   862 	case SCF_ERROR_PERMISSION_DENIED:
       
   863 		se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   864 		    NULL, NULL);
       
   865 		break;
       
   866 	case SCF_ERROR_BACKEND_READONLY:
       
   867 		se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   868 		    NULL, NULL);
       
   869 		break;
       
   870 	default:
       
   871 		se = smfu_maperr(scf_error());
       
   872 	}
       
   873 
       
   874 done:
       
   875 	scf_transaction_destroy_children(tx);
       
   876 	scf_transaction_destroy(tx);
       
   877 	scf_pg_destroy(pg);
       
   878 
       
   879 	return (se);
       
   880 }
       
   881 
       
   882 /*ARGSUSED*/
       
   883 conerr_t
       
   884 interface_Entity_invoke_deleteProperty(rad_instance_t *inst, adr_method_t *meth,
       
   885     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
   886 {
       
   887 	radarg_t ra = { .inst = inst, .args = args };
       
   888 	return (smfu_rtrun(rt_invoke_deleteProperty, &ra, NULL, error));
       
   889 }
       
   890 
       
   891 static svcerr_t
       
   892 tx_delete_propcust(scf_handle_t *h, scf_transaction_t *tx,
       
   893     const char *name, adr_data_t **error)
       
   894 {
       
   895 	svcerr_t se = SE_OK;
       
   896 	scf_transaction_entry_t *entry = scf_entry_create(h);
       
   897 
       
   898 	if (entry == NULL)
       
   899 		return (SE_FATAL);
       
   900 
       
   901 	if (scf_transaction_property_delcust(tx, entry, name) == -1) {
       
   902 		int e = scf_error();
       
   903 		scf_entry_destroy(entry);
       
   904 		switch (e) {
       
   905 		case SCF_ERROR_PERMISSION_DENIED:
       
   906 			se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   907 			    NULL, NULL);
       
   908 			break;
       
   909 		case SCF_ERROR_BACKEND_READONLY:
       
   910 			se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   911 			    NULL, NULL);
       
   912 			break;
       
   913 		case SCF_ERROR_DELETED:
       
   914 			se = error_scf(error, &e__ErrorCode_NOTFOUND,
       
   915 			    &e__ErrorTarget_PROPERTY, name, NULL);
       
   916 			break;
       
   917 		default:
       
   918 			se = smfu_maperr(e);
       
   919 		}
       
   920 	}
       
   921 	return (se);
       
   922 }
       
   923 
       
   924 /*ARGSUSED*/
       
   925 static svcerr_t
       
   926 rt_invoke_deletePropertyCust(scf_handle_t *h, void *arg, adr_data_t **ret,
       
   927     adr_data_t **error)
       
   928 {
       
   929 	radarg_t *ra = arg;
       
   930 	smfobj_t *smfo = instance_getdata(ra->inst);
       
   931 	const char *pgname = adr_data_to_string(ra->args[0]);
       
   932 	const char *propname = adr_data_to_string(ra->args[1]);
       
   933 	svcerr_t se = SE_OK;
       
   934 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
   935 	scf_propertygroup_t *pg = scf_pg_create(h);
       
   936 	scf_transaction_t *tx = scf_transaction_create(h);
       
   937 
       
   938 	if (pg == NULL || tx == NULL) {
       
   939 		se = internal_error(error, NULL);
       
   940 		goto done;
       
   941 	}
       
   942 
       
   943 	if ((se = smfu_lookup(h, smfo->sname, smfo->iname, &entity)) != SE_OK)
       
   944 		goto done;
       
   945 
       
   946 	if ((se = smfu_get_pg(&entity, pgname, pg, error)) != SE_OK)
       
   947 		goto done;
       
   948 
       
   949 top:
       
   950 	if (scf_transaction_start(tx, pg) == -1)
       
   951 		goto txerror;
       
   952 
       
   953 	if ((se = tx_delete_propcust(h, tx, propname, error)) != SE_OK)
       
   954 		goto done;
       
   955 
       
   956 	int r;
       
   957 	if ((r = scf_transaction_commit(tx)) == 1)
       
   958 		goto done;
       
   959 
       
   960 	if (r == 0 && scf_pg_update(pg) != -1) {
       
   961 		scf_transaction_destroy_children(tx);
       
   962 		scf_transaction_reset(tx);
       
   963 		goto top;
       
   964 	}
       
   965 
       
   966 txerror:
       
   967 	switch (scf_error()) {
       
   968 	case SCF_ERROR_PERMISSION_DENIED:
       
   969 		se = error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   970 		    NULL, NULL);
       
   971 		break;
       
   972 	case SCF_ERROR_BACKEND_READONLY:
       
   973 		se = error_scf(error, &e__ErrorCode_READONLY, NULL,
       
   974 		    NULL, NULL);
       
   975 		break;
       
   976 	default:
       
   977 		se = smfu_maperr(scf_error());
       
   978 	}
       
   979 
       
   980 done:
       
   981 	scf_transaction_destroy_children(tx);
       
   982 	scf_transaction_destroy(tx);
       
   983 	scf_pg_destroy(pg);
       
   984 
       
   985 	return (se);
       
   986 }
       
   987 
       
   988 /*ARGSUSED*/
       
   989 conerr_t
       
   990 interface_Entity_invoke_deletePropertyCust(rad_instance_t *inst,
       
   991     adr_method_t *meth, adr_data_t **ret, adr_data_t **args, int count,
       
   992     adr_data_t **error)
       
   993 {
       
   994 	radarg_t ra = { .inst = inst, .args = args };
       
   995 	return (smfu_rtrun(rt_invoke_deletePropertyCust, &ra, NULL, error));
       
   996 }
       
   997 
       
   998 /*
       
   999  * Common retry callback for reading old-style template data from
       
  1000  * either a service's directly-attached property groups or an
       
  1001  * instance's running snapshot.
       
  1002  */
       
  1003 
       
  1004 struct tmplarg {
       
  1005 	smfobj_t *smfo;
       
  1006 	const char *pgname;
       
  1007 	const char *locale;
       
  1008 };
       
  1009 
       
  1010 /*ARGSUSED*/
       
  1011 static svcerr_t
       
  1012 rt_get_template(scf_handle_t *h, void *arg, adr_data_t **ret,
       
  1013     adr_data_t **error)
       
  1014 {
       
  1015 	struct tmplarg *ta = arg;
       
  1016 	svcerr_t se = SE_OK;
       
  1017 	smfu_entity_t entity = SMFU_ENTITY_INIT;
       
  1018 	scf_propertygroup_t *pg = scf_pg_create(h);
       
  1019 	char *str = NULL;
       
  1020 
       
  1021 	if (pg == NULL) {
       
  1022 		se = SE_FATAL;
       
  1023 		goto done;
       
  1024 	}
       
  1025 
       
  1026 	if ((se = smfu_lookup(h, ta->smfo->sname, ta->smfo->iname,
       
  1027 	    &entity)) != SE_OK)
       
  1028 		goto done;
       
  1029 
       
  1030 	if ((se = smfu_get_pg_r(h, &entity, ta->pgname, pg)) == SE_OK &&
       
  1031 	    (se = smfu_get_l10n_str(h, pg, ta->locale, &str)) == SE_OK) {
       
  1032 		if ((*ret = adr_data_new_string(str, LT_FREE)) == NULL)
       
  1033 			se = SE_FATAL;
       
  1034 	} else if (se == SE_NOTFOUND) {
       
  1035 		se = SE_OK;
       
  1036 	}
       
  1037 
       
  1038 done:
       
  1039 	smfu_entity_destroy(&entity);
       
  1040 	scf_pg_destroy(pg);
       
  1041 
       
  1042 	return (se);
       
  1043 }
       
  1044 
       
  1045 /*ARGSUSED*/
       
  1046 conerr_t
       
  1047 interface_Entity_invoke_getCommonName(rad_instance_t *inst, adr_method_t *meth,
       
  1048     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
  1049 {
       
  1050 	struct tmplarg ta = {
       
  1051 	    .smfo = instance_getdata(inst),
       
  1052 	    .pgname = SCF_PG_TM_COMMON_NAME,
       
  1053 	    .locale = adr_data_to_string(args[0])
       
  1054 	};
       
  1055 	return (smfu_rtrun_opt(rt_get_template, &ta, ret, error));
       
  1056 }
       
  1057 
       
  1058 /*ARGSUSED*/
       
  1059 conerr_t
       
  1060 interface_Entity_invoke_getDescription(rad_instance_t *inst, adr_method_t *meth,
       
  1061     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
  1062 {
       
  1063 	struct tmplarg ta = {
       
  1064 	    .smfo = instance_getdata(inst),
       
  1065 	    .pgname = SCF_PG_TM_DESCRIPTION,
       
  1066 	    .locale = adr_data_to_string(args[0])
       
  1067 	};
       
  1068 	return (smfu_rtrun_opt(rt_get_template, &ta, ret, error));
       
  1069 }
       
  1070 
       
  1071 
       
  1072 /*ARGSUSED*/
       
  1073 static svcerr_t
       
  1074 rt_invoke_getPGTemplates(scf_handle_t *h, void *arg, adr_data_t **ret,
       
  1075     adr_data_t **error)
       
  1076 {
       
  1077 	radarg_t *ra = arg;
       
  1078 	smfobj_t *smfo = instance_getdata(ra->inst);
       
  1079 	const char *locale = adr_data_to_string(ra->args[0]);
       
  1080 	svcerr_t se = SE_OK;
       
  1081 	adr_data_t *result = adr_data_new_array(&t_array__PGTemplate, 5);
       
  1082 
       
  1083 	scf_pg_tmpl_t *pgtmpl = scf_tmpl_pg_create(h);
       
  1084 	if (pgtmpl == NULL) {
       
  1085 		se = SE_FATAL;
       
  1086 		goto done;
       
  1087 	}
       
  1088 
       
  1089 	int e;
       
  1090 	while ((e = scf_tmpl_iter_pgs(pgtmpl, smfo->fmri, NULL, NULL,
       
  1091 	    SCF_PG_TMPL_FLAG_CURRENT)) == 1) {
       
  1092 		adr_data_t *t = NULL;
       
  1093 		if ((se = create_PGTemplate(pgtmpl, locale, &t)) != SE_OK)
       
  1094 			goto done;
       
  1095 		(void) adr_array_add(result, t);
       
  1096 	}
       
  1097 	if (e == -1)
       
  1098 		se = smfu_maperr(scf_error());
       
  1099 done:
       
  1100 	*ret = result;
       
  1101 	scf_tmpl_pg_destroy(pgtmpl);
       
  1102 
       
  1103 	return (se);
       
  1104 }
       
  1105 
       
  1106 /*ARGSUSED*/
       
  1107 conerr_t
       
  1108 interface_Entity_invoke_getPGTemplates(rad_instance_t *inst, adr_method_t *meth,
       
  1109     adr_data_t **ret, adr_data_t **args, int count, adr_data_t **error)
       
  1110 {
       
  1111 	radarg_t ra = { .inst = inst, .args = args };
       
  1112 	return (smfu_rtrun(rt_invoke_getPGTemplates, &ra, ret, error));
       
  1113 }
       
  1114 
       
  1115 
       
  1116 /*ARGSUSED*/
       
  1117 static svcerr_t
       
  1118 rt_invoke_getPropTemplates(scf_handle_t *h, void *arg, adr_data_t **ret,
       
  1119     adr_data_t **error)
       
  1120 {
       
  1121 	radarg_t *ra = arg;
       
  1122 	smfobj_t *smfo = instance_getdata(ra->inst);
       
  1123 	const char *pgname = adr_data_to_string(ra->args[0]);
       
  1124 	const char *pgtype = adr_data_to_string(ra->args[1]);
       
  1125 	const char *locale = adr_data_to_string(ra->args[2]);
       
  1126 	svcerr_t se = SE_OK;
       
  1127 	adr_data_t *result = adr_data_new_array(&t_array__PropTemplate, 5);
       
  1128 
       
  1129 	scf_pg_tmpl_t *pgtmpl = scf_tmpl_pg_create(h);
       
  1130 	scf_prop_tmpl_t *proptmpl = scf_tmpl_prop_create(h);
       
  1131 
       
  1132 	if (pgtmpl == NULL || proptmpl == NULL) {
       
  1133 		se = SE_FATAL;
       
  1134 		goto done;
       
  1135 	}
       
  1136 
       
  1137 	if (scf_tmpl_get_by_pg_name(smfo->fmri, NULL, pgname, pgtype, pgtmpl,
       
  1138 	    0) == -1) {
       
  1139 		se = smfu_maperr(scf_error());
       
  1140 		goto done;
       
  1141 	}
       
  1142 
       
  1143 	int e;
       
  1144 	while ((e = scf_tmpl_iter_props(pgtmpl, proptmpl, 0)) == 0) {
       
  1145 		adr_data_t *t = NULL;
       
  1146 		if ((se = create_PropTemplate(proptmpl, locale, &t)) != SE_OK)
       
  1147 			goto done;
       
  1148 		(void) adr_array_add(result, t);
       
  1149 	}
       
  1150 	if (e == -1)
       
  1151 		se = smfu_maperr(scf_error());
       
  1152 done:
       
  1153 	*ret = result;
       
  1154 	scf_tmpl_prop_destroy(proptmpl);
       
  1155 	scf_tmpl_pg_destroy(pgtmpl);
       
  1156 
       
  1157 	return (se);
       
  1158 }
       
  1159 
       
  1160 /*ARGSUSED*/
       
  1161 conerr_t
       
  1162 interface_Entity_invoke_getPropTemplates(rad_instance_t *inst,
       
  1163     adr_method_t *meth, adr_data_t **ret, adr_data_t **args, int count,
       
  1164     adr_data_t **error)
       
  1165 {
       
  1166 	radarg_t ra = { .inst = inst, .args = args };
       
  1167 	return (smfu_rtrun(rt_invoke_getPropTemplates, &ra, ret, error));
       
  1168 }