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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* helper functions for using libscf with sharemgr */
28
29 #include <libscf.h>
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 #include "libshare.h"
33 #include "libshare_impl.h"
34 #include "scfutil.h"
35 #include <string.h>
36 #include <ctype.h>
37 #include <errno.h>
38 #include <uuid/uuid.h>
39 #include <sys/param.h>
40 #include <signal.h>
41 #include <sys/time.h>
42 #include <libintl.h>
43
44 ssize_t scf_max_name_len;
45 extern struct sa_proto_plugin *sap_proto_list;
46 extern sa_handle_impl_t get_handle_for_root(xmlNodePtr);
47 static void set_transaction_tstamp(sa_handle_impl_t);
48 /*
49 * The SMF facility uses some properties that must exist. We want to
50 * skip over these when processing protocol options.
51 */
52 static char *skip_props[] = {
53 "modify_authorization",
54 "action_authorization",
55 "value_authorization",
56 NULL
57 };
58
59 /*
60 * sa_scf_fini(handle)
61 *
62 * Must be called when done. Called with the handle allocated in
63 * sa_scf_init(), it cleans up the state and frees any SCF resources
64 * still in use. Called by sa_fini().
65 */
66
67 void
80 if (handle->pg != NULL)
81 scf_pg_destroy(handle->pg);
82 if (handle->handle != NULL) {
83 handle->scf_state = SCH_STATE_UNINIT;
84 if (unbind)
85 (void) scf_handle_unbind(handle->handle);
86 scf_handle_destroy(handle->handle);
87 }
88 free(handle);
89 }
90 }
91
92 /*
93 * sa_scf_init()
94 *
95 * Must be called before using any of the SCF functions. Called by
96 * sa_init() during the API setup.
97 */
98
99 scfutilhandle_t *
100 sa_scf_init(sa_handle_impl_t ihandle)
101 {
102 scfutilhandle_t *handle;
103
104 scf_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
105 if (scf_max_name_len <= 0)
106 scf_max_name_len = SA_MAX_NAME_LEN + 1;
107
108 handle = calloc(1, sizeof (scfutilhandle_t));
109 if (handle == NULL)
110 return (handle);
111
112 ihandle->scfhandle = handle;
113 handle->scf_state = SCH_STATE_INITIALIZING;
114 handle->handle = scf_handle_create(SCF_VERSION);
115 if (handle->handle == NULL) {
116 free(handle);
117 handle = NULL;
118 (void) printf("libshare could not access SMF repository: %s\n",
119 scf_strerror(scf_error()));
120 return (handle);
124
125 handle->scope = scf_scope_create(handle->handle);
126 handle->service = scf_service_create(handle->handle);
127 handle->pg = scf_pg_create(handle->handle);
128
129 /* Make sure we have sufficient SMF running */
130 handle->instance = scf_instance_create(handle->handle);
131 if (handle->scope == NULL || handle->service == NULL ||
132 handle->pg == NULL || handle->instance == NULL)
133 goto err;
134 if (scf_handle_get_scope(handle->handle,
135 SCF_SCOPE_LOCAL, handle->scope) != 0)
136 goto err;
137 if (scf_scope_get_service(handle->scope,
138 SA_GROUP_SVC_NAME, handle->service) != 0)
139 goto err;
140
141 handle->scf_state = SCH_STATE_INIT;
142 if (sa_get_instance(handle, "default") != SA_OK) {
143 sa_group_t defgrp;
144 defgrp = sa_create_group((sa_handle_t)ihandle, "default", NULL);
145 /* Only NFS enabled for "default" group. */
146 if (defgrp != NULL)
147 (void) sa_create_optionset(defgrp, "nfs");
148 }
149
150 return (handle);
151
152 /* Error handling/unwinding */
153 err:
154 (void) sa_scf_fini(handle);
155 (void) printf("libshare SMF initialization problem: %s\n",
156 scf_strerror(scf_error()));
157 return (NULL);
158 }
159
160 /*
161 * get_scf_limit(name)
162 *
163 * Since we use scf_limit a lot and do the same check and return the
164 * same value if it fails, implement as a function for code
1332 ret = SA_SYSTEM_ERR;
1333 }
1334 }
1335 }
1336 if (ret == SA_SYSTEM_ERR &&
1337 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
1338 ret = SA_NO_PERMISSION;
1339 }
1340 return (ret);
1341 }
1342
1343
1344 /*
1345 * sa_end_transaction(scfhandle, sahandle)
1346 *
1347 * Commit the changes that were added to the transaction in the
1348 * handle. Do all necessary cleanup.
1349 */
1350
1351 int
1352 sa_end_transaction(scfutilhandle_t *handle, sa_handle_impl_t sahandle)
1353 {
1354 int ret = SA_OK;
1355
1356 if (handle == NULL || handle->trans == NULL || sahandle == NULL) {
1357 ret = SA_SYSTEM_ERR;
1358 } else {
1359 if (scf_transaction_commit(handle->trans) < 0)
1360 ret = SA_SYSTEM_ERR;
1361 scf_transaction_destroy_children(handle->trans);
1362 scf_transaction_destroy(handle->trans);
1363 if (ret == SA_OK)
1364 set_transaction_tstamp(sahandle);
1365 handle->trans = NULL;
1366 }
1367 return (ret);
1368 }
1369
1370 /*
1371 * sa_abort_transaction(handle)
1372 *
1375 */
1376
1377 void
1378 sa_abort_transaction(scfutilhandle_t *handle)
1379 {
1380 if (handle->trans != NULL) {
1381 scf_transaction_reset_all(handle->trans);
1382 scf_transaction_destroy_children(handle->trans);
1383 scf_transaction_destroy(handle->trans);
1384 handle->trans = NULL;
1385 }
1386 }
1387
1388 /*
1389 * set_transaction_tstamp(sahandle)
1390 *
1391 * After a successful transaction commit, update the timestamp of the
1392 * last transaction. This lets us detect changes from other processes.
1393 */
1394 static void
1395 set_transaction_tstamp(sa_handle_impl_t sahandle)
1396 {
1397 char tstring[32];
1398 struct timeval tv;
1399 scfutilhandle_t *scfhandle;
1400
1401 if (sahandle == NULL || sahandle->scfhandle == NULL)
1402 return;
1403
1404 scfhandle = sahandle->scfhandle;
1405
1406 if (sa_get_instance(scfhandle, "default") != SA_OK)
1407 return;
1408
1409 if (gettimeofday(&tv, NULL) != 0)
1410 return;
1411
1412 if (sa_start_transaction(scfhandle, "*state") != SA_OK)
1413 return;
1414
1415 sahandle->tstrans = TSTAMP((*(timestruc_t *)&tv));
1759 }
1760 if (ret == SA_OK) {
1761 /*
1762 * If there are resource names, bundle them up
1763 * and save appropriately.
1764 */
1765 ret = sa_set_resource_property(handle, share);
1766 }
1767
1768 if (ret == SA_OK) {
1769 description = sa_get_share_description(share);
1770 if (description != NULL) {
1771 ret = sa_set_property(handle,
1772 "description",
1773 description);
1774 sa_free_share_description(description);
1775 }
1776 }
1777 /* Make sure we cleanup the transaction */
1778 if (ret == SA_OK) {
1779 sa_handle_impl_t sahandle;
1780 sahandle = (sa_handle_impl_t)
1781 sa_find_group_handle(group);
1782 if (sahandle != NULL)
1783 ret = sa_end_transaction(handle,
1784 sahandle);
1785 else
1786 ret = SA_SYSTEM_ERR;
1787 } else {
1788 sa_abort_transaction(handle);
1789 }
1790
1791 (void) sigprocmask(SIG_SETMASK, &old, NULL);
1792
1793 free(sharename);
1794 }
1795 }
1796 if (ret == SA_SYSTEM_ERR) {
1797 int err = scf_error();
1798 if (err == SCF_ERROR_PERMISSION_DENIED)
1799 ret = SA_NO_PERMISSION;
1800 }
1801 if (propstring != NULL)
|
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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright (c) 2013 RackTop Systems.
29 */
30
31 /* helper functions for using libscf with sharemgr */
32
33 #include <libscf.h>
34 #include <libxml/parser.h>
35 #include <libxml/tree.h>
36 #include "libshare.h"
37 #include "libshare_impl.h"
38 #include "scfutil.h"
39 #include <string.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <uuid/uuid.h>
43 #include <sys/param.h>
44 #include <signal.h>
45 #include <sys/time.h>
46 #include <libintl.h>
47
48 ssize_t scf_max_name_len;
49 extern struct sa_proto_plugin *sap_proto_list;
50 extern sa_handle_t get_handle_for_root(xmlNodePtr);
51 static void set_transaction_tstamp(sa_handle_t);
52 /*
53 * The SMF facility uses some properties that must exist. We want to
54 * skip over these when processing protocol options.
55 */
56 static char *skip_props[] = {
57 "modify_authorization",
58 "action_authorization",
59 "value_authorization",
60 NULL
61 };
62
63 /*
64 * sa_scf_fini(handle)
65 *
66 * Must be called when done. Called with the handle allocated in
67 * sa_scf_init(), it cleans up the state and frees any SCF resources
68 * still in use. Called by sa_fini().
69 */
70
71 void
84 if (handle->pg != NULL)
85 scf_pg_destroy(handle->pg);
86 if (handle->handle != NULL) {
87 handle->scf_state = SCH_STATE_UNINIT;
88 if (unbind)
89 (void) scf_handle_unbind(handle->handle);
90 scf_handle_destroy(handle->handle);
91 }
92 free(handle);
93 }
94 }
95
96 /*
97 * sa_scf_init()
98 *
99 * Must be called before using any of the SCF functions. Called by
100 * sa_init() during the API setup.
101 */
102
103 scfutilhandle_t *
104 sa_scf_init(sa_handle_t ihandle)
105 {
106 scfutilhandle_t *handle;
107
108 scf_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
109 if (scf_max_name_len <= 0)
110 scf_max_name_len = SA_MAX_NAME_LEN + 1;
111
112 handle = calloc(1, sizeof (scfutilhandle_t));
113 if (handle == NULL)
114 return (handle);
115
116 ihandle->scfhandle = handle;
117 handle->scf_state = SCH_STATE_INITIALIZING;
118 handle->handle = scf_handle_create(SCF_VERSION);
119 if (handle->handle == NULL) {
120 free(handle);
121 handle = NULL;
122 (void) printf("libshare could not access SMF repository: %s\n",
123 scf_strerror(scf_error()));
124 return (handle);
128
129 handle->scope = scf_scope_create(handle->handle);
130 handle->service = scf_service_create(handle->handle);
131 handle->pg = scf_pg_create(handle->handle);
132
133 /* Make sure we have sufficient SMF running */
134 handle->instance = scf_instance_create(handle->handle);
135 if (handle->scope == NULL || handle->service == NULL ||
136 handle->pg == NULL || handle->instance == NULL)
137 goto err;
138 if (scf_handle_get_scope(handle->handle,
139 SCF_SCOPE_LOCAL, handle->scope) != 0)
140 goto err;
141 if (scf_scope_get_service(handle->scope,
142 SA_GROUP_SVC_NAME, handle->service) != 0)
143 goto err;
144
145 handle->scf_state = SCH_STATE_INIT;
146 if (sa_get_instance(handle, "default") != SA_OK) {
147 sa_group_t defgrp;
148 defgrp = sa_create_group(ihandle, "default", NULL);
149 /* Only NFS enabled for "default" group. */
150 if (defgrp != NULL)
151 (void) sa_create_optionset(defgrp, "nfs");
152 }
153
154 return (handle);
155
156 /* Error handling/unwinding */
157 err:
158 (void) sa_scf_fini(handle);
159 (void) printf("libshare SMF initialization problem: %s\n",
160 scf_strerror(scf_error()));
161 return (NULL);
162 }
163
164 /*
165 * get_scf_limit(name)
166 *
167 * Since we use scf_limit a lot and do the same check and return the
168 * same value if it fails, implement as a function for code
1336 ret = SA_SYSTEM_ERR;
1337 }
1338 }
1339 }
1340 if (ret == SA_SYSTEM_ERR &&
1341 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
1342 ret = SA_NO_PERMISSION;
1343 }
1344 return (ret);
1345 }
1346
1347
1348 /*
1349 * sa_end_transaction(scfhandle, sahandle)
1350 *
1351 * Commit the changes that were added to the transaction in the
1352 * handle. Do all necessary cleanup.
1353 */
1354
1355 int
1356 sa_end_transaction(scfutilhandle_t *handle, sa_handle_t sahandle)
1357 {
1358 int ret = SA_OK;
1359
1360 if (handle == NULL || handle->trans == NULL || sahandle == NULL) {
1361 ret = SA_SYSTEM_ERR;
1362 } else {
1363 if (scf_transaction_commit(handle->trans) < 0)
1364 ret = SA_SYSTEM_ERR;
1365 scf_transaction_destroy_children(handle->trans);
1366 scf_transaction_destroy(handle->trans);
1367 if (ret == SA_OK)
1368 set_transaction_tstamp(sahandle);
1369 handle->trans = NULL;
1370 }
1371 return (ret);
1372 }
1373
1374 /*
1375 * sa_abort_transaction(handle)
1376 *
1379 */
1380
1381 void
1382 sa_abort_transaction(scfutilhandle_t *handle)
1383 {
1384 if (handle->trans != NULL) {
1385 scf_transaction_reset_all(handle->trans);
1386 scf_transaction_destroy_children(handle->trans);
1387 scf_transaction_destroy(handle->trans);
1388 handle->trans = NULL;
1389 }
1390 }
1391
1392 /*
1393 * set_transaction_tstamp(sahandle)
1394 *
1395 * After a successful transaction commit, update the timestamp of the
1396 * last transaction. This lets us detect changes from other processes.
1397 */
1398 static void
1399 set_transaction_tstamp(sa_handle_t sahandle)
1400 {
1401 char tstring[32];
1402 struct timeval tv;
1403 scfutilhandle_t *scfhandle;
1404
1405 if (sahandle == NULL || sahandle->scfhandle == NULL)
1406 return;
1407
1408 scfhandle = sahandle->scfhandle;
1409
1410 if (sa_get_instance(scfhandle, "default") != SA_OK)
1411 return;
1412
1413 if (gettimeofday(&tv, NULL) != 0)
1414 return;
1415
1416 if (sa_start_transaction(scfhandle, "*state") != SA_OK)
1417 return;
1418
1419 sahandle->tstrans = TSTAMP((*(timestruc_t *)&tv));
1763 }
1764 if (ret == SA_OK) {
1765 /*
1766 * If there are resource names, bundle them up
1767 * and save appropriately.
1768 */
1769 ret = sa_set_resource_property(handle, share);
1770 }
1771
1772 if (ret == SA_OK) {
1773 description = sa_get_share_description(share);
1774 if (description != NULL) {
1775 ret = sa_set_property(handle,
1776 "description",
1777 description);
1778 sa_free_share_description(description);
1779 }
1780 }
1781 /* Make sure we cleanup the transaction */
1782 if (ret == SA_OK) {
1783 sa_handle_t sahandle;
1784 sahandle = sa_find_group_handle(group);
1785 if (sahandle != NULL)
1786 ret = sa_end_transaction(handle,
1787 sahandle);
1788 else
1789 ret = SA_SYSTEM_ERR;
1790 } else {
1791 sa_abort_transaction(handle);
1792 }
1793
1794 (void) sigprocmask(SIG_SETMASK, &old, NULL);
1795
1796 free(sharename);
1797 }
1798 }
1799 if (ret == SA_SYSTEM_ERR) {
1800 int err = scf_error();
1801 if (err == SCF_ERROR_PERMISSION_DENIED)
1802 ret = SA_NO_PERMISSION;
1803 }
1804 if (propstring != NULL)
|