components/visual-panels/smf/src/cmd/rad/mod/smf/datatype.c
changeset 827 0944d8c0158b
child 901 19b502ccabc8
equal deleted inserted replaced
826:c6aad84d2493 827:0944d8c0158b
       
     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 <sys/list.h>
       
    27 #include <sys/types.h>
       
    28 #include <sys/stat.h>
       
    29 #include <string.h>
       
    30 #include <stdio.h>
       
    31 #include <stdlib.h>
       
    32 #include <stddef.h>
       
    33 #include <unistd.h>
       
    34 #include <fcntl.h>
       
    35 #include <assert.h>
       
    36 #include <limits.h>
       
    37 
       
    38 #include <libscf.h>
       
    39 #include <libscf_priv.h>
       
    40 
       
    41 #include <rad/adr.h>
       
    42 #include <rad/rad_modapi.h>
       
    43 
       
    44 #include "api_smf.h"
       
    45 #include "rhandle.h"
       
    46 #include "smfutil.h"
       
    47 #include "datatype.h"
       
    48 
       
    49 /*
       
    50  * Routines for creating ADR data objects from SCF types or objects.
       
    51  * Consumed by the API entry points.
       
    52  */
       
    53 
       
    54 data_t *
       
    55 create_SMFState(const char *state)
       
    56 {
       
    57 	if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0) {
       
    58 		return (&e__SMFState_UNINIT);
       
    59 	} else if (strcmp(state, SCF_STATE_STRING_MAINT) == 0) {
       
    60 		return (&e__SMFState_MAINT);
       
    61 	} else if (strcmp(state, SCF_STATE_STRING_LEGACY) == 0) {
       
    62 		return (&e__SMFState_LEGACY);
       
    63 	} else {
       
    64 		return (data_new_enum_byname(&t__SMFState, state));
       
    65 	}
       
    66 }
       
    67 
       
    68 static data_t *
       
    69 create_DepGrouping(const char *grouping)
       
    70 {
       
    71 	if (strcmp(grouping, SCF_DEP_REQUIRE_ALL) == 0)
       
    72 		return (&e__DepGrouping_REQUIRE_ALL);
       
    73 	else if (strcmp(grouping, SCF_DEP_REQUIRE_ANY) == 0)
       
    74 		return (&e__DepGrouping_REQUIRE_ANY);
       
    75 	else if (strcmp(grouping, SCF_DEP_EXCLUDE_ALL) == 0)
       
    76 		return (&e__DepGrouping_EXCLUDE_ALL);
       
    77 	else if (strcmp(grouping, SCF_DEP_OPTIONAL_ALL) == 0)
       
    78 		return (&e__DepGrouping_OPTIONAL_ALL);
       
    79 	return (NULL);
       
    80 }
       
    81 
       
    82 static data_t *
       
    83 create_DepRestart(const char *restarton)
       
    84 {
       
    85 	if (strcmp(restarton, SCF_DEP_RESET_ON_ERROR) == 0)
       
    86 		return (&e__DepRestart_ERROR);
       
    87 	if (strcmp(restarton, SCF_DEP_RESET_ON_RESTART) == 0)
       
    88 		return (&e__DepRestart_RESTART);
       
    89 	if (strcmp(restarton, SCF_DEP_RESET_ON_REFRESH) == 0)
       
    90 		return (&e__DepRestart_REFRESH);
       
    91 	if (strcmp(restarton, SCF_DEP_RESET_ON_NONE) == 0)
       
    92 		return (&e__DepRestart_NONE);
       
    93 	return (NULL);
       
    94 }
       
    95 
       
    96 static data_t *
       
    97 create_PropertyType(scf_type_t type)
       
    98 {
       
    99 	data_t *result = data_new_enum(&t__PropertyType, type);
       
   100 	assert(result != NULL);
       
   101 	return (result);
       
   102 }
       
   103 
       
   104 scf_type_t
       
   105 from_PropertyType(data_t *type)
       
   106 {
       
   107 	return (enum_tovalue(type));
       
   108 }
       
   109 
       
   110 static data_t *
       
   111 create_PropertyVisibility(uint8_t visibility)
       
   112 {
       
   113 	switch (visibility) {
       
   114 	case SCF_TMPL_VISIBILITY_HIDDEN:
       
   115 		return (&e__PropertyVisibility_HIDDEN);
       
   116 	case SCF_TMPL_VISIBILITY_READONLY:
       
   117 		return (&e__PropertyVisibility_READONLY);
       
   118 	case SCF_TMPL_VISIBILITY_READWRITE:
       
   119 		return (&e__PropertyVisibility_READWRITE);
       
   120 	}
       
   121 	return (NULL);
       
   122 }
       
   123 
       
   124 /*
       
   125  * Creates a Dependency object.
       
   126  *
       
   127  * A return value of SE_NOTFOUND implies that the property group wasn't
       
   128  * a dependency and should be skipped.
       
   129  */
       
   130 svcerr_t
       
   131 create_Dependency(scf_handle_t *scfhandle, scf_propertygroup_t *pg,
       
   132     data_t **ret)
       
   133 {
       
   134 	svcerr_t se = SE_OK;
       
   135 	char type[max_pgtype + 1];
       
   136 	char grouping[max_value + 1];
       
   137 	char restarton[max_value + 1];
       
   138 	char pgname[max_name + 1];
       
   139 
       
   140 	scf_iter_t *iter = scf_iter_create(scfhandle);
       
   141 	scf_property_t *prop = scf_property_create(scfhandle);
       
   142 	scf_value_t *val = scf_value_create(scfhandle);
       
   143 
       
   144 	if (iter == NULL || prop == NULL || val == NULL) {
       
   145 		se = SE_FATAL;
       
   146 		goto out;
       
   147 	}
       
   148 
       
   149 	if (scf_pg_get_name(pg, pgname, sizeof (pgname)) == -1 ||
       
   150 	    scf_pg_get_property(pg, SCF_PROPERTY_GROUPING, prop) != 0 ||
       
   151 	    scf_property_get_value(prop, val) != 0 ||
       
   152 	    scf_value_get_as_string(val, grouping, sizeof (grouping)) == -1 ||
       
   153 	    scf_pg_get_property(pg, SCF_PROPERTY_RESTART_ON, prop) != 0 ||
       
   154 	    scf_property_get_value(prop, val) != 0 ||
       
   155 	    scf_value_get_as_string(val, restarton, sizeof (restarton)) == -1 ||
       
   156 	    scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, prop) != 0 ||
       
   157 	    scf_iter_property_values(iter, prop) != 0) {
       
   158 		se = smfu_maperr(scf_error());
       
   159 		goto out;
       
   160 	}
       
   161 
       
   162 	data_t *group = create_DepGrouping(grouping);
       
   163 	data_t *restart = create_DepRestart(restarton);
       
   164 	if (group == NULL || restart == NULL) {
       
   165 		se = SE_NOTFOUND;
       
   166 		goto out;
       
   167 	}
       
   168 
       
   169 	data_t *result = data_new_struct(&t__Dependency);
       
   170 	struct_set(result, "name", data_new_string(pgname, lt_copy));
       
   171 	struct_set(result, "grouping", group);
       
   172 	struct_set(result, "restartOn", restart);
       
   173 	data_t *array = data_new_array(&t_array_string, 5);
       
   174 	struct_set(result, "target", array);
       
   175 
       
   176 	while (scf_iter_next_value(iter, val) > 0) {
       
   177 		if (scf_value_get_as_string(val, type, sizeof (type)) == -1) {
       
   178 			se = smfu_maperr(scf_error());
       
   179 			data_free(result);
       
   180 			goto out;
       
   181 		}
       
   182 		(void) array_add(array, data_new_string(type, lt_copy));
       
   183 	}
       
   184 	if (!data_verify(result, NULL, B_TRUE)) {
       
   185 		se = SE_FATAL;
       
   186 		data_free(result);
       
   187 		goto out;
       
   188 	}
       
   189 
       
   190 	*ret = result;
       
   191 out:
       
   192 	scf_value_destroy(val);
       
   193 	scf_property_destroy(prop);
       
   194 	scf_iter_destroy(iter);
       
   195 	return (se);
       
   196 }
       
   197 
       
   198 /*
       
   199  * Creates a Manpage object.
       
   200  *
       
   201  * A return value of SE_NOTFOUND implies that the property group wasn't
       
   202  * a man page and should be skipped.
       
   203  */
       
   204 svcerr_t
       
   205 create_Manpage(scf_handle_t *scfhandle, scf_propertygroup_t *pg, data_t **ret)
       
   206 {
       
   207 	char manpath[max_value + 1];
       
   208 	char section[max_value + 1];
       
   209 	char title[max_name + 1];
       
   210 	char pgname[max_name + 1];
       
   211 	svcerr_t se = SE_OK;
       
   212 
       
   213 	if (scf_pg_get_name(pg, pgname, sizeof (pgname)) == -1)
       
   214 		return (smfu_maperr(scf_error()));
       
   215 
       
   216 	if (strncmp(SCF_PG_TM_MAN_PREFIX, pgname,
       
   217 	    strlen(SCF_PG_TM_MAN_PREFIX)) != 0)
       
   218 		return (SE_NOTFOUND);
       
   219 
       
   220 
       
   221 	scf_property_t *prop = scf_property_create(scfhandle);
       
   222 	scf_value_t *val = scf_value_create(scfhandle);
       
   223 
       
   224 	if (prop == NULL || val == NULL) {
       
   225 		se = SE_FATAL;
       
   226 		goto out;
       
   227 	}
       
   228 
       
   229 	if (scf_pg_get_property(pg, SCF_PROPERTY_TM_MANPATH, prop) != 0 ||
       
   230 	    scf_property_get_value(prop, val) != 0 ||
       
   231 	    scf_value_get_as_string(val, manpath, sizeof (manpath)) == -1 ||
       
   232 	    scf_pg_get_property(pg, SCF_PROPERTY_TM_TITLE, prop) != 0 ||
       
   233 	    scf_property_get_value(prop, val) != 0 ||
       
   234 	    scf_value_get_as_string(val, title, sizeof (title)) == -1 ||
       
   235 	    scf_pg_get_property(pg, SCF_PROPERTY_TM_SECTION, prop) != 0 ||
       
   236 	    scf_property_get_value(prop, val) != 0 ||
       
   237 	    scf_value_get_as_string(val, section, sizeof (section)) == -1) {
       
   238 		se = smfu_maperr(scf_error());
       
   239 		goto out;
       
   240 	}
       
   241 
       
   242 	data_t *result = data_new_struct(&t__Manpage);
       
   243 	struct_set(result, "title", data_new_string(title, lt_copy));
       
   244 	struct_set(result, "section", data_new_string(section, lt_copy));
       
   245 	if (strcmp(manpath, ":default") != 0) {
       
   246 		data_t *mp = data_new_string(manpath, lt_copy);
       
   247 		if (mp == NULL) {
       
   248 			se = SE_FATAL;
       
   249 			data_free(result);
       
   250 			goto out;
       
   251 		}
       
   252 		struct_set(result, "path", data_new_string(manpath, lt_copy));
       
   253 	}
       
   254 
       
   255 	if (!data_verify(result, NULL, B_TRUE)) {
       
   256 		se = SE_FATAL;
       
   257 		data_free(result);
       
   258 		goto out;
       
   259 	}
       
   260 
       
   261 	*ret = result;
       
   262 out:
       
   263 	scf_value_destroy(val);
       
   264 	scf_property_destroy(prop);
       
   265 	return (se);
       
   266 }
       
   267 
       
   268 /*
       
   269  * Creates a Doclink object.
       
   270  *
       
   271  * A return value of SE_NOTFOUND implies that the property group wasn't
       
   272  * a doclink and should be skipped.
       
   273  */
       
   274 svcerr_t
       
   275 create_Doclink(scf_handle_t *scfhandle, scf_propertygroup_t *pg, data_t **ret)
       
   276 {
       
   277 	char name[max_value + 1];
       
   278 	char uri[max_value + 1];
       
   279 	char pgname[max_name + 1];
       
   280 	svcerr_t se = SE_OK;
       
   281 
       
   282 	if (scf_pg_get_name(pg, pgname, sizeof (pgname)) == -1)
       
   283 		return (smfu_maperr(scf_error()));
       
   284 
       
   285 	if (strncmp(SCF_PG_TM_DOC_PREFIX, pgname,
       
   286 	    strlen(SCF_PG_TM_DOC_PREFIX)) != 0)
       
   287 		return (SE_NOTFOUND);
       
   288 
       
   289 	scf_property_t *prop = scf_property_create(scfhandle);
       
   290 	scf_value_t *val = scf_value_create(scfhandle);
       
   291 
       
   292 	if (prop == NULL || val == NULL) {
       
   293 		se = SE_FATAL;
       
   294 		goto out;
       
   295 	}
       
   296 
       
   297 	if (scf_pg_get_property(pg, SCF_PROPERTY_TM_NAME, prop) != 0 ||
       
   298 	    scf_property_get_value(prop, val) != 0 ||
       
   299 	    scf_value_get_as_string(val, name, sizeof (name)) == -1 ||
       
   300 	    scf_pg_get_property(pg, SCF_PROPERTY_TM_URI, prop) != 0 ||
       
   301 	    scf_property_get_value(prop, val) != 0 ||
       
   302 	    scf_value_get_as_string(val, uri, sizeof (uri)) == -1) {
       
   303 		se = smfu_maperr(scf_error());
       
   304 		goto out;
       
   305 	}
       
   306 
       
   307 	data_t *result = data_new_struct(&t__Doclink);
       
   308 	struct_set(result, "name", data_new_string(name, lt_copy));
       
   309 	struct_set(result, "uri", data_new_string(uri, lt_copy));
       
   310 
       
   311 	if (!data_verify(result, NULL, B_TRUE)) {
       
   312 		se = SE_FATAL;
       
   313 		data_free(result);
       
   314 		goto out;
       
   315 	}
       
   316 
       
   317 	*ret = result;
       
   318 out:
       
   319 	scf_value_destroy(val);
       
   320 	scf_property_destroy(prop);
       
   321 	return (se);
       
   322 }
       
   323 
       
   324 svcerr_t
       
   325 create_PropertyGroup(scf_propertygroup_t *pg, data_t **ret)
       
   326 {
       
   327 	char name[max_value + 1];
       
   328 	char type[max_pgtype + 1];
       
   329 	uint32_t flags;
       
   330 	svcerr_t se = SE_OK;
       
   331 
       
   332 	if (scf_pg_get_name(pg, name, sizeof (name)) == -1 ||
       
   333 	    scf_pg_get_type(pg, type, sizeof (type)) == -1 ||
       
   334 	    scf_pg_get_flags(pg, &flags) == -1) {
       
   335 		se = smfu_maperr(scf_error());
       
   336 		goto out;
       
   337 	}
       
   338 
       
   339 	data_t *result = data_new_struct(&t__PropertyGroup);
       
   340 	struct_set(result, "name", data_new_string(name, lt_copy));
       
   341 	struct_set(result, "type", data_new_string(type, lt_copy));
       
   342 	struct_set(result, "flags", data_new_uinteger(flags));
       
   343 
       
   344 	if (!data_verify(result, NULL, B_TRUE)) {
       
   345 		se = SE_FATAL;
       
   346 		data_free(result);
       
   347 		goto out;
       
   348 	}
       
   349 
       
   350 	*ret = result;
       
   351 out:
       
   352 	return (se);
       
   353 }
       
   354 
       
   355 svcerr_t
       
   356 create_Property(scf_property_t *prop, scf_iter_t *iter, scf_value_t *value,
       
   357     data_t **ret, data_t **error)
       
   358 {
       
   359 	char name[max_name + 1];
       
   360 	scf_type_t type;
       
   361 
       
   362 	if (scf_property_get_name(prop, name, sizeof (name)) == -1 ||
       
   363 	    scf_property_type(prop, &type) == -1 ||
       
   364 	    scf_iter_property_values(iter, prop))
       
   365 		return (smfu_maperr(scf_error()));
       
   366 
       
   367 	data_t *values = data_new_array(&t_array_string, 5);
       
   368 	int err;
       
   369 	while ((err = scf_iter_next_value(iter, value)) > 0) {
       
   370 		char *valstr;
       
   371 		if (smfu_value_get_string(value, &valstr) != 0) {
       
   372 			data_free(values);
       
   373 			return (SE_FATAL);
       
   374 		}
       
   375 		(void) array_add(values, data_new_string(valstr, lt_free));
       
   376 	}
       
   377 	if (err != 0) {
       
   378 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED)
       
   379 			return (error_scf(error, &e__ErrorCode_DENIED, NULL,
       
   380 			    NULL, NULL));
       
   381 		else
       
   382 			return (smfu_maperr(scf_error()));
       
   383 	}
       
   384 
       
   385 	data_t *result = data_new_struct(&t__Property);
       
   386 	struct_set(result, "name", data_new_string(name, lt_copy));
       
   387 	struct_set(result, "type", create_PropertyType(type));
       
   388 	struct_set(result, "values", values);
       
   389 	*ret = result;
       
   390 
       
   391 	return (SE_OK);
       
   392 }
       
   393 
       
   394 svcerr_t
       
   395 create_Properties(scf_handle_t *scfhandle, scf_propertygroup_t *pg,
       
   396     data_t **ret, data_t **error)
       
   397 {
       
   398 	svcerr_t se = SE_OK;
       
   399 	scf_iter_t *piter = scf_iter_create(scfhandle);
       
   400 	scf_iter_t *viter = scf_iter_create(scfhandle);
       
   401 	scf_value_t *value = scf_value_create(scfhandle);
       
   402 	scf_property_t *prop = scf_property_create(scfhandle);
       
   403 	data_t *result = data_new_array(&t_array__Property, 5);
       
   404 
       
   405 	if (piter == NULL || viter == NULL || value == NULL || prop == NULL) {
       
   406 		se = SE_FATAL;
       
   407 		goto out;
       
   408 	}
       
   409 
       
   410 	if (scf_iter_pg_properties(piter, pg) == -1) {
       
   411 		se = smfu_maperr(scf_error());
       
   412 		goto out;
       
   413 	}
       
   414 
       
   415 	int err;
       
   416 	while ((err = scf_iter_next_property(piter, prop)) > 0) {
       
   417 		data_t *propdata = NULL;
       
   418 		if ((se = create_Property(prop, viter, value, &propdata,
       
   419 		    error)) != SE_OK)
       
   420 			goto out;
       
   421 		(void) array_add(result, propdata);
       
   422 	}
       
   423 	if (err != 0)
       
   424 		se = smfu_maperr(scf_error());
       
   425 
       
   426 out:
       
   427 	if (se != SE_OK)
       
   428 		data_free(result);
       
   429 	else
       
   430 		*ret = result;
       
   431 
       
   432 	scf_iter_destroy(piter);
       
   433 	scf_iter_destroy(viter);
       
   434 	scf_value_destroy(value);
       
   435 	scf_property_destroy(prop);
       
   436 
       
   437 	return (se);
       
   438 }
       
   439 
       
   440 svcerr_t
       
   441 create_ExtendedState(scf_handle_t *scfhandle, scf_instance_t *instance,
       
   442     data_t **ret)
       
   443 {
       
   444 	scf_propertygroup_t *pg = scf_pg_create(scfhandle);
       
   445 	scf_property_t *prop = scf_property_create(scfhandle);
       
   446 	scf_value_t *value = scf_value_create(scfhandle);
       
   447 	data_t *result = data_new_struct(&t__ExtendedState);
       
   448 	svcerr_t se = SE_FATAL;
       
   449 	int serr;
       
   450 	data_t *dstr;
       
   451 	char *str;
       
   452 	int64_t sec;
       
   453 	int32_t nsec;
       
   454 	uint64_t ctid;
       
   455 	uint8_t bool;
       
   456 
       
   457 	if (pg == NULL || prop == NULL || value == NULL)
       
   458 		goto error;
       
   459 
       
   460 	if (scf_instance_get_pg(instance, SCF_PG_RESTARTER, pg) == -1)
       
   461 		goto scferror;
       
   462 
       
   463 	if (scf_pg_get_property(pg, SCF_PROPERTY_STATE, prop) == -1 ||
       
   464 	    scf_property_get_value(prop, value) == -1)
       
   465 		goto scferror;
       
   466 	if (smfu_value_get_string(value, &str) != 0)
       
   467 		goto error;
       
   468 	struct_set(result, "state", create_SMFState(str));
       
   469 	free(str);
       
   470 
       
   471 	if (scf_pg_get_property(pg, SCF_PROPERTY_NEXT_STATE, prop) == -1 ||
       
   472 	    scf_property_get_value(prop, value) == -1)
       
   473 		goto scferror;
       
   474 	if (smfu_value_get_string(value, &str) != 0)
       
   475 		goto error;
       
   476 	struct_set(result, "nextState", create_SMFState(str));
       
   477 	free(str);
       
   478 
       
   479 	if (scf_pg_get_property(pg, SCF_PROPERTY_AUX_STATE, prop) == -1 ||
       
   480 	    scf_property_get_value(prop, value) == -1)
       
   481 		goto scferror;
       
   482 	if (smfu_value_get_string(value, &str) != 0)
       
   483 		goto error;
       
   484 	if ((dstr = data_new_string(str, lt_free)) == NULL)
       
   485 		goto error;
       
   486 	struct_set(result, "auxstate", dstr);
       
   487 
       
   488 	if (scf_pg_get_property(pg, SCF_PROPERTY_STATE_TIMESTAMP, prop) == -1 ||
       
   489 	    scf_property_get_value(prop, value) == -1 ||
       
   490 	    scf_value_get_time(value, &sec, &nsec) == -1)
       
   491 		goto scferror;
       
   492 	struct_set(result, "stime", data_new_time(sec, nsec));
       
   493 
       
   494 	if (scf_pg_get_property(pg, SCF_PROPERTY_CONTRACT, prop) == -1 ||
       
   495 	    scf_property_get_value(prop, value) == -1) {
       
   496 		if (scf_error() == SCF_ERROR_NOT_FOUND)
       
   497 			struct_set(result, "contractid", data_new_integer(-1));
       
   498 		else
       
   499 			goto scferror;
       
   500 	} else if (scf_value_get_count(value, &ctid) == -1) {
       
   501 		goto scferror;
       
   502 	} else {
       
   503 		struct_set(result, "contractid",
       
   504 		    data_new_integer(ctid <= INT_MAX ? ctid : -1));
       
   505 	}
       
   506 
       
   507 	if ((serr = smfu_read_enabled(instance, pg, prop, value, SCF_PG_GENERAL,
       
   508 	    &bool)) != 0) {
       
   509 		se = smfu_maperr(serr);
       
   510 		goto error;
       
   511 	}
       
   512 	data_t *persist = data_new_boolean(bool > 0);
       
   513 	struct_set(result, "enabled", persist);
       
   514 
       
   515 	if ((serr = smfu_read_enabled(instance, pg, prop, value,
       
   516 	    SCF_PG_GENERAL_OVR, &bool)) == 0) {
       
   517 		struct_set(result, "enabled_temp", data_new_boolean(bool > 0));
       
   518 	} else if (serr == SCF_ERROR_NOT_FOUND) {
       
   519 		struct_set(result, "enabled_temp", data_ref(persist));
       
   520 	} else {
       
   521 		se = smfu_maperr(serr);
       
   522 		goto error;
       
   523 	}
       
   524 
       
   525 	*ret = result;
       
   526 
       
   527 	return (SE_OK);
       
   528 
       
   529 scferror:
       
   530 	se = smfu_maperr(scf_error());
       
   531 error:
       
   532 	data_free(result);
       
   533 	return (se);
       
   534 }
       
   535 
       
   536 svcerr_t
       
   537 create_PGTemplate(scf_pg_tmpl_t *pgtmpl, const char *locale, data_t **ret)
       
   538 {
       
   539 	data_t *pt = data_new_struct(&t__PGTemplate);
       
   540 	data_t *dstr;
       
   541 	char *str;
       
   542 	svcerr_t se = SE_FATAL;
       
   543 
       
   544 	if (scf_tmpl_pg_name(pgtmpl, &str) == -1)
       
   545 		goto scferror;
       
   546 	struct_set(pt, "pgname", data_new_string(str, lt_free));
       
   547 
       
   548 	if (scf_tmpl_pg_type(pgtmpl, &str) == -1)
       
   549 		goto scferror;
       
   550 	struct_set(pt, "pgtype", data_new_string(str, lt_free));
       
   551 
       
   552 	if (scf_tmpl_pg_common_name(pgtmpl, locale, &str) == -1) {
       
   553 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   554 			goto scferror;
       
   555 	} else {
       
   556 		if ((dstr = data_new_string(str, lt_free)) == NULL)
       
   557 			goto error;
       
   558 		struct_set(pt, "name", dstr);
       
   559 	}
       
   560 
       
   561 	if (scf_tmpl_pg_description(pgtmpl, locale, &str) == -1) {
       
   562 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   563 			goto scferror;
       
   564 	} else {
       
   565 		if ((dstr = data_new_string(str, lt_free)) == NULL)
       
   566 			goto error;
       
   567 		struct_set(pt, "description", dstr);
       
   568 	}
       
   569 
       
   570 	uint8_t req;
       
   571 	if (scf_tmpl_pg_required(pgtmpl, &req) == -1) {
       
   572 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   573 			goto scferror;
       
   574 		req = 0;
       
   575 	}
       
   576 	struct_set(pt, "required", data_new_boolean(req > 0));
       
   577 
       
   578 	*ret = pt;
       
   579 	return (SE_OK);
       
   580 
       
   581 scferror:
       
   582 	se = smfu_maperr(scf_error());
       
   583 error:
       
   584 	data_free(pt);
       
   585 	return (se);
       
   586 }
       
   587 
       
   588 svcerr_t
       
   589 create_PropTemplate(scf_prop_tmpl_t *proptmpl, const char *locale, data_t **ret)
       
   590 {
       
   591 	data_t *pt = data_new_struct(&t__PropTemplate);
       
   592 	data_t *dstr;
       
   593 	char *str;
       
   594 	svcerr_t se = SE_FATAL;
       
   595 
       
   596 	if (scf_tmpl_prop_name(proptmpl, &str) == -1)
       
   597 		goto error;
       
   598 	struct_set(pt, "propname", data_new_string(str, lt_free));
       
   599 
       
   600 	scf_type_t type;
       
   601 	if (scf_tmpl_prop_type(proptmpl, &type) == -1) {
       
   602 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   603 			goto scferror;
       
   604 		type = SCF_TYPE_INVALID;
       
   605 	}
       
   606 	struct_set(pt, "proptype", create_PropertyType(type));
       
   607 
       
   608 	if (scf_tmpl_prop_common_name(proptmpl, locale, &str) == -1) {
       
   609 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   610 			goto scferror;
       
   611 	} else {
       
   612 		if ((dstr = data_new_string(str, lt_free)) == NULL)
       
   613 			goto error;
       
   614 		struct_set(pt, "name", dstr);
       
   615 	}
       
   616 
       
   617 	if (scf_tmpl_prop_description(proptmpl, locale, &str) == -1) {
       
   618 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   619 			goto scferror;
       
   620 	} else {
       
   621 		if ((dstr = data_new_string(str, lt_free)) == NULL)
       
   622 			goto error;
       
   623 		struct_set(pt, "description", dstr);
       
   624 	}
       
   625 
       
   626 	if (scf_tmpl_prop_units(proptmpl, locale, &str) == -1) {
       
   627 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   628 			goto scferror;
       
   629 	} else {
       
   630 		if ((dstr = data_new_string(str, lt_free)) == NULL)
       
   631 			goto error;
       
   632 		struct_set(pt, "units", dstr);
       
   633 	}
       
   634 
       
   635 	uint8_t req;
       
   636 	if (scf_tmpl_prop_required(proptmpl, &req) == -1) {
       
   637 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   638 			goto scferror;
       
   639 		req = 0;
       
   640 	}
       
   641 	struct_set(pt, "required", data_new_boolean(req > 0));
       
   642 
       
   643 	uint64_t min, max;
       
   644 	if (scf_tmpl_prop_cardinality(proptmpl, &min, &max) == -1) {
       
   645 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   646 			goto scferror;
       
   647 		min = max = 0;
       
   648 	}
       
   649 	struct_set(pt, "cardinality_min", data_new_ulong(min));
       
   650 	struct_set(pt, "cardinality_max", data_new_ulong(max));
       
   651 
       
   652 	uint8_t vis;
       
   653 	if (scf_tmpl_prop_visibility(proptmpl, &vis) == -1) {
       
   654 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   655 			goto scferror;
       
   656 		vis = SCF_TMPL_VISIBILITY_READWRITE;
       
   657 	}
       
   658 	struct_set(pt, "visibility", create_PropertyVisibility(vis));
       
   659 
       
   660 	scf_values_t values;
       
   661 	if (scf_tmpl_prop_internal_seps(proptmpl, &values) == 0) {
       
   662 		data_t *array =
       
   663 		    data_new_array(&t_array_string, values.value_count);
       
   664 		for (int i = 0; i < values.value_count; i++)
       
   665 			(void) array_add(array, data_new_string(
       
   666 			    values.values_as_strings[i], lt_copy));
       
   667 		if (!data_verify(array, NULL, B_TRUE)) {
       
   668 			data_free(array);
       
   669 			goto error;
       
   670 		}
       
   671 		struct_set(pt, "separators", array);
       
   672 		scf_values_destroy(&values);
       
   673 	} else {
       
   674 		if (scf_error() != SCF_ERROR_NOT_FOUND)
       
   675 			goto scferror;
       
   676 	}
       
   677 
       
   678 	*ret = pt;
       
   679 	return (SE_OK);
       
   680 
       
   681 scferror:
       
   682 	se = smfu_maperr(scf_error());
       
   683 error:
       
   684 	data_free(pt);
       
   685 	return (se);
       
   686 }
       
   687 
       
   688 
       
   689 svcerr_t
       
   690 create_Instance(scf_instance_t *instance, const char *sname, const char *iname,
       
   691     data_t **data, scf_propertygroup_t *pg, scf_property_t *prop,
       
   692     scf_value_t *val)
       
   693 {
       
   694 	char statestr[MAX_SCF_STATE_STRING_SZ];
       
   695 	ssize_t len;
       
   696 	int64_t seconds;
       
   697 	int32_t nsec;
       
   698 
       
   699 	if (scf_instance_get_pg(instance, SCF_PG_RESTARTER, pg) != 0)
       
   700 		return (smfu_maperr(scf_error()));
       
   701 
       
   702 	if (scf_pg_get_property(pg, SCF_PROPERTY_STATE, prop) != 0 ||
       
   703 	    scf_property_get_value(prop, val) != 0 ||
       
   704 	    (len = scf_value_get_as_string(val, statestr,
       
   705 	    MAX_SCF_STATE_STRING_SZ)) == -1) {
       
   706 		return (smfu_maperr(scf_error()));
       
   707 	} else if (len > MAX_SCF_STATE_STRING_SZ - 1) {
       
   708 		return (SE_FATAL);
       
   709 	}
       
   710 
       
   711 	if (scf_pg_get_property(pg, SCF_PROPERTY_STATE_TIMESTAMP, prop) != 0 ||
       
   712 	    scf_property_get_value(prop, val) != 0 ||
       
   713 	    scf_value_get_time(val, &seconds, &nsec) != 0)
       
   714 		return (smfu_maperr(scf_error()));
       
   715 
       
   716 	data_t *inst = data_new_struct(&t__Instance);
       
   717 	struct_set(inst, "fmri",
       
   718 	    data_new_string(smfu_fmri_alloc(sname, iname), lt_free));
       
   719 	struct_set(inst, "objectName",
       
   720 	    data_new_name(smfu_name_alloc(sname, iname)));
       
   721 	struct_set(inst, "stime", data_new_time(seconds, nsec));
       
   722 	struct_set(inst, "state", create_SMFState(statestr));
       
   723 
       
   724 	if (!data_verify(inst, NULL, B_TRUE)) {
       
   725 		data_free(inst);
       
   726 		return (SE_FATAL);
       
   727 	}
       
   728 
       
   729 	*data = inst;
       
   730 	return (SE_OK);
       
   731 }