|
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 } |