|
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 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
|
23 */ |
|
24 #include <stdio.h> |
|
25 #include <stdlib.h> |
|
26 #include <syslog.h> |
|
27 #include <stdarg.h> |
|
28 #include "smfcfg.h" |
|
29 |
|
30 fs_smfhandle_t * |
|
31 fs_smf_init(char *fmri, char *instance) |
|
32 { |
|
33 fs_smfhandle_t *handle = NULL; |
|
34 char *svcname, srv[MAXPATHLEN]; |
|
35 |
|
36 /* |
|
37 * svc name is of the form svc://network/fs/server:instance1 |
|
38 * FMRI portion is /network/fs/server |
|
39 */ |
|
40 snprintf(srv, MAXPATHLEN, "%s", fmri + strlen("svc:/")); |
|
41 svcname = strrchr(srv, ':'); |
|
42 if (svcname != NULL) |
|
43 *svcname = '\0'; |
|
44 svcname = srv; |
|
45 |
|
46 handle = calloc(1, sizeof (fs_smfhandle_t)); |
|
47 if (handle != NULL) { |
|
48 handle->fs_handle = scf_handle_create(SCF_VERSION); |
|
49 if (handle->fs_handle == NULL) |
|
50 goto out; |
|
51 if (scf_handle_bind(handle->fs_handle) != 0) |
|
52 goto out; |
|
53 handle->fs_service = |
|
54 scf_service_create(handle->fs_handle); |
|
55 handle->fs_scope = |
|
56 scf_scope_create(handle->fs_handle); |
|
57 if (scf_handle_get_local_scope(handle->fs_handle, |
|
58 handle->fs_scope) != 0) |
|
59 goto out; |
|
60 if (scf_scope_get_service(handle->fs_scope, |
|
61 svcname, handle->fs_service) != SCF_SUCCESS) { |
|
62 goto out; |
|
63 } |
|
64 handle->fs_pg = |
|
65 scf_pg_create(handle->fs_handle); |
|
66 handle->fs_instance = |
|
67 scf_instance_create(handle->fs_handle); |
|
68 handle->fs_property = |
|
69 scf_property_create(handle->fs_handle); |
|
70 handle->fs_value = |
|
71 scf_value_create(handle->fs_handle); |
|
72 } else { |
|
73 fprintf(stderr, |
|
74 gettext("Cannot access SMF repository: %s\n"), fmri); |
|
75 } |
|
76 return (handle); |
|
77 |
|
78 out: |
|
79 fs_smf_fini(handle); |
|
80 fprintf(stderr, gettext("SMF Initialization problems..%s\n"), fmri); |
|
81 return (NULL); |
|
82 } |
|
83 |
|
84 |
|
85 void |
|
86 fs_smf_fini(fs_smfhandle_t *handle) |
|
87 { |
|
88 if (handle != NULL) { |
|
89 scf_scope_destroy(handle->fs_scope); |
|
90 scf_instance_destroy(handle->fs_instance); |
|
91 scf_service_destroy(handle->fs_service); |
|
92 scf_pg_destroy(handle->fs_pg); |
|
93 scf_property_destroy(handle->fs_property); |
|
94 scf_value_destroy(handle->fs_value); |
|
95 if (handle->fs_handle != NULL) { |
|
96 scf_handle_unbind(handle->fs_handle); |
|
97 scf_handle_destroy(handle->fs_handle); |
|
98 } |
|
99 free(handle); |
|
100 } |
|
101 } |
|
102 |
|
103 int |
|
104 fs_smf_set_prop(smf_fstype_t fstype, char *prop_name, char *valbuf, |
|
105 char *instance, scf_type_t sctype, char *fmri) |
|
106 { |
|
107 fs_smfhandle_t *phandle; |
|
108 scf_handle_t *handle; |
|
109 scf_propertygroup_t *pg; |
|
110 scf_property_t *prop; |
|
111 scf_transaction_t *tran; |
|
112 scf_transaction_entry_t *entry; |
|
113 scf_instance_t *inst; |
|
114 scf_value_t *val; |
|
115 int valint; |
|
116 int index = 0; |
|
117 int ret = 0; |
|
118 char *p = NULL; |
|
119 char *svcname, srv[MAXPATHLEN]; |
|
120 const char *pgname; |
|
121 |
|
122 /* |
|
123 * The SVC names we are using currently are already |
|
124 * appended by default. Fix this for instances project. |
|
125 */ |
|
126 snprintf(srv, MAXPATHLEN, "%s", fmri); |
|
127 p = strstr(fmri, ":default"); |
|
128 if (p == NULL) { |
|
129 strcat(srv, ":"); |
|
130 if (instance == NULL) |
|
131 instance = "default"; |
|
132 if (strlen(srv) + strlen(instance) > MAXPATHLEN) |
|
133 goto out; |
|
134 strncat(srv, instance, strlen(instance)); |
|
135 } |
|
136 svcname = srv; |
|
137 phandle = fs_smf_init(fmri, instance); |
|
138 if (phandle == NULL) { |
|
139 return (SMF_SYSTEM_ERR); |
|
140 } |
|
141 handle = phandle->fs_handle; |
|
142 pg = phandle->fs_pg; |
|
143 prop = phandle->fs_property; |
|
144 inst = phandle->fs_instance; |
|
145 val = phandle->fs_value; |
|
146 tran = scf_transaction_create(handle); |
|
147 entry = scf_entry_create(handle); |
|
148 |
|
149 if (handle == NULL || pg == NULL || prop == NULL || |
|
150 val == NULL|| tran == NULL || entry == NULL || inst == NULL) { |
|
151 ret = SMF_SYSTEM_ERR; |
|
152 goto out; |
|
153 } |
|
154 |
|
155 if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope, |
|
156 phandle->fs_service, inst, NULL, NULL, 0) != 0) { |
|
157 ret = scf_error(); |
|
158 goto out; |
|
159 } |
|
160 if (fstype == AUTOFS_SMF) |
|
161 pgname = AUTOFS_PROPS_PGNAME; |
|
162 else |
|
163 pgname = NFS_PROPS_PGNAME; |
|
164 |
|
165 if (scf_instance_get_pg(inst, pgname, |
|
166 pg) != -1) { |
|
167 uint8_t vint; |
|
168 if (scf_transaction_start(tran, pg) == -1) { |
|
169 ret = scf_error(); |
|
170 goto out; |
|
171 } |
|
172 switch (sctype) { |
|
173 case SCF_TYPE_INTEGER: |
|
174 errno = 0; |
|
175 valint = strtoul(valbuf, NULL, 0); |
|
176 if (errno != 0) { |
|
177 ret = SMF_SYSTEM_ERR; |
|
178 goto out; |
|
179 } |
|
180 if (scf_transaction_property_change(tran, |
|
181 entry, prop_name, SCF_TYPE_INTEGER) == 0) { |
|
182 scf_value_set_integer(val, valint); |
|
183 if (scf_entry_add_value(entry, val) < 0) { |
|
184 ret = scf_error(); |
|
185 goto out; |
|
186 } |
|
187 } |
|
188 break; |
|
189 case SCF_TYPE_ASTRING: |
|
190 if (scf_transaction_property_change(tran, entry, |
|
191 prop_name, SCF_TYPE_ASTRING) == 0) { |
|
192 if (scf_value_set_astring(val, |
|
193 valbuf) == 0) { |
|
194 if (scf_entry_add_value(entry, |
|
195 val) != 0) { |
|
196 ret = scf_error(); |
|
197 goto out; |
|
198 } |
|
199 } else |
|
200 ret = SMF_SYSTEM_ERR; |
|
201 } else |
|
202 ret = SMF_SYSTEM_ERR; |
|
203 break; |
|
204 case SCF_TYPE_BOOLEAN: |
|
205 if (strcmp(valbuf, "1") == 0) { |
|
206 vint = 1; |
|
207 } else if (strcmp(valbuf, "0") == 0) { |
|
208 vint = 0; |
|
209 } else { |
|
210 ret = SMF_SYSTEM_ERR; |
|
211 break; |
|
212 } |
|
213 if (scf_transaction_property_change(tran, entry, |
|
214 prop_name, SCF_TYPE_BOOLEAN) == 0) { |
|
215 scf_value_set_boolean(val, (uint8_t)vint); |
|
216 if (scf_entry_add_value(entry, val) != 0) { |
|
217 ret = scf_error(); |
|
218 goto out; |
|
219 } |
|
220 } else { |
|
221 ret = SMF_SYSTEM_ERR; |
|
222 } |
|
223 break; |
|
224 } |
|
225 if (ret != SMF_SYSTEM_ERR) |
|
226 scf_transaction_commit(tran); |
|
227 } |
|
228 out: |
|
229 if (tran != NULL) |
|
230 scf_transaction_destroy(tran); |
|
231 if (entry != NULL) |
|
232 scf_entry_destroy(entry); |
|
233 fs_smf_fini(phandle); |
|
234 return (ret); |
|
235 } |
|
236 |
|
237 int |
|
238 fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf, |
|
239 char *instance, scf_type_t sctype, char *fmri, int *bufsz) |
|
240 { |
|
241 fs_smfhandle_t *phandle; |
|
242 scf_handle_t *handle; |
|
243 scf_propertygroup_t *pg; |
|
244 scf_property_t *prop; |
|
245 scf_value_t *val; |
|
246 scf_instance_t *inst; |
|
247 int ret = 0, len = 0, length; |
|
248 int64_t valint = 0; |
|
249 char srv[MAXPATHLEN], *p, *svcname; |
|
250 const char *pgname; |
|
251 uint8_t bval; |
|
252 |
|
253 /* |
|
254 * The SVC names we are using currently are already |
|
255 * appended by default. Fix this for instances project. |
|
256 */ |
|
257 snprintf(srv, MAXPATHLEN, "%s", fmri); |
|
258 p = strstr(fmri, ":default"); |
|
259 if (p == NULL) { |
|
260 strcat(srv, ":"); |
|
261 if (instance == NULL) |
|
262 instance = "default"; |
|
263 if (strlen(srv) + strlen(instance) > MAXPATHLEN) |
|
264 goto out; |
|
265 strncat(srv, instance, strlen(instance)); |
|
266 } |
|
267 svcname = srv; |
|
268 phandle = fs_smf_init(fmri, instance); |
|
269 if (phandle == NULL) |
|
270 return (SMF_SYSTEM_ERR); |
|
271 handle = phandle->fs_handle; |
|
272 pg = phandle->fs_pg; |
|
273 inst = phandle->fs_instance; |
|
274 prop = phandle->fs_property; |
|
275 val = phandle->fs_value; |
|
276 |
|
277 if (handle == NULL || pg == NULL || prop == NULL || val == NULL || |
|
278 inst == NULL) { |
|
279 return (SMF_SYSTEM_ERR); |
|
280 } |
|
281 |
|
282 |
|
283 if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope, |
|
284 phandle->fs_service, inst, NULL, NULL, 0) != 0) { |
|
285 ret = scf_error(); |
|
286 goto out; |
|
287 } |
|
288 |
|
289 if (fstype == AUTOFS_SMF) |
|
290 pgname = AUTOFS_PROPS_PGNAME; |
|
291 else |
|
292 pgname = NFS_PROPS_PGNAME; |
|
293 |
|
294 if (scf_instance_get_pg(inst, pgname, pg) != -1) { |
|
295 if (scf_pg_get_property(pg, prop_name, |
|
296 prop) != SCF_SUCCESS) { |
|
297 ret = scf_error(); |
|
298 goto out; |
|
299 } |
|
300 if (scf_property_get_value(prop, val) != SCF_SUCCESS) { |
|
301 ret = scf_error(); |
|
302 goto out; |
|
303 } |
|
304 switch (sctype) { |
|
305 case SCF_TYPE_ASTRING: |
|
306 len = scf_value_get_astring(val, cbuf, *bufsz); |
|
307 if (len < 0 || len > *bufsz) { |
|
308 ret = scf_error(); |
|
309 goto out; |
|
310 } |
|
311 ret = 0; |
|
312 *bufsz = len; |
|
313 break; |
|
314 case SCF_TYPE_INTEGER: |
|
315 if (scf_value_get_integer(val, &valint) != 0) { |
|
316 ret = scf_error(); |
|
317 goto out; |
|
318 } |
|
319 length = snprintf(cbuf, *bufsz, "%lld", valint); |
|
320 if (length < 0 || length > *bufsz) { |
|
321 ret = SA_BAD_VALUE; |
|
322 goto out; |
|
323 } |
|
324 ret = 0; |
|
325 break; |
|
326 case SCF_TYPE_BOOLEAN: |
|
327 if (scf_value_get_boolean(val, &bval) != 0) { |
|
328 ret = scf_error(); |
|
329 goto out; |
|
330 } |
|
331 if (bval == 1) { |
|
332 length = snprintf(cbuf, *bufsz, "%s", "true"); |
|
333 } else { |
|
334 length = snprintf(cbuf, *bufsz, "%s", "false"); |
|
335 } |
|
336 if (length < 0 || length > *bufsz) { |
|
337 ret = SA_BAD_VALUE; |
|
338 goto out; |
|
339 } |
|
340 break; |
|
341 } |
|
342 } else { |
|
343 ret = scf_error(); |
|
344 } |
|
345 if ((ret != 0) && scf_error() != SCF_ERROR_NONE) |
|
346 fprintf(stdout, gettext("%s\n"), scf_strerror(ret)); |
|
347 out: |
|
348 fs_smf_fini(phandle); |
|
349 return (ret); |
|
350 } |
|
351 |
|
352 |
|
353 int |
|
354 nfs_smf_get_prop(char *prop_name, char *propbuf, char *instance, |
|
355 scf_type_t sctype, char *svc_name, int *bufsz) |
|
356 { |
|
357 return (fs_smf_get_prop(NFS_SMF, prop_name, propbuf, |
|
358 instance, sctype, svc_name, bufsz)); |
|
359 } |
|
360 |
|
361 int |
|
362 nfs_smf_set_prop(char *prop_name, char *value, char *instance, |
|
363 scf_type_t type, char *svc_name) |
|
364 { |
|
365 return (fs_smf_set_prop(NFS_SMF, prop_name, value, instance, |
|
366 type, svc_name)); |
|
367 } |
|
368 |
|
369 int |
|
370 autofs_smf_set_prop(char *prop_name, char *value, char *instance, |
|
371 scf_type_t type, char *svc_name) |
|
372 { |
|
373 return (fs_smf_set_prop(AUTOFS_SMF, prop_name, value, instance, |
|
374 type, svc_name)); |
|
375 } |
|
376 |
|
377 int |
|
378 autofs_smf_get_prop(char *prop_name, char *propbuf, char *instance, |
|
379 scf_type_t sctype, char *svc_name, int *bufsz) |
|
380 { |
|
381 return (fs_smf_get_prop(AUTOFS_SMF, prop_name, propbuf, |
|
382 instance, sctype, svc_name, bufsz)); |
|
383 } |
|
384 |
|
385 boolean_t |
|
386 string_to_boolean(const char *str) |
|
387 { |
|
388 if (strcasecmp(str, "true") == 0 || atoi(str) == 1 || |
|
389 strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) { |
|
390 return (B_TRUE); |
|
391 } else |
|
392 return (B_FALSE); |
|
393 } |