Print this page
4095 minor cleanup up libshare
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libshare/common/scfutil.c
+++ new/usr/src/lib/libshare/common/scfutil.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 +/*
28 + * Copyright (c) 2013 RackTop Systems.
29 + */
30 +
27 31 /* helper functions for using libscf with sharemgr */
28 32
29 33 #include <libscf.h>
30 34 #include <libxml/parser.h>
31 35 #include <libxml/tree.h>
32 36 #include "libshare.h"
33 37 #include "libshare_impl.h"
34 38 #include "scfutil.h"
35 39 #include <string.h>
36 40 #include <ctype.h>
37 41 #include <errno.h>
38 42 #include <uuid/uuid.h>
39 43 #include <sys/param.h>
40 44 #include <signal.h>
41 45 #include <sys/time.h>
42 46 #include <libintl.h>
43 47
44 48 ssize_t scf_max_name_len;
45 49 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);
50 +extern sa_handle_t get_handle_for_root(xmlNodePtr);
51 +static void set_transaction_tstamp(sa_handle_t);
48 52 /*
49 53 * The SMF facility uses some properties that must exist. We want to
50 54 * skip over these when processing protocol options.
51 55 */
52 56 static char *skip_props[] = {
53 57 "modify_authorization",
54 58 "action_authorization",
55 59 "value_authorization",
56 60 NULL
57 61 };
58 62
59 63 /*
60 64 * sa_scf_fini(handle)
61 65 *
62 66 * Must be called when done. Called with the handle allocated in
63 67 * sa_scf_init(), it cleans up the state and frees any SCF resources
64 68 * still in use. Called by sa_fini().
65 69 */
66 70
67 71 void
68 72 sa_scf_fini(scfutilhandle_t *handle)
69 73 {
70 74 if (handle != NULL) {
71 75 int unbind = 0;
72 76 if (handle->scope != NULL) {
73 77 unbind = 1;
74 78 scf_scope_destroy(handle->scope);
75 79 }
76 80 if (handle->instance != NULL)
77 81 scf_instance_destroy(handle->instance);
78 82 if (handle->service != NULL)
79 83 scf_service_destroy(handle->service);
80 84 if (handle->pg != NULL)
81 85 scf_pg_destroy(handle->pg);
82 86 if (handle->handle != NULL) {
83 87 handle->scf_state = SCH_STATE_UNINIT;
84 88 if (unbind)
85 89 (void) scf_handle_unbind(handle->handle);
86 90 scf_handle_destroy(handle->handle);
87 91 }
88 92 free(handle);
89 93 }
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
90 94 }
91 95
92 96 /*
93 97 * sa_scf_init()
94 98 *
95 99 * Must be called before using any of the SCF functions. Called by
96 100 * sa_init() during the API setup.
97 101 */
98 102
99 103 scfutilhandle_t *
100 -sa_scf_init(sa_handle_impl_t ihandle)
104 +sa_scf_init(sa_handle_t ihandle)
101 105 {
102 106 scfutilhandle_t *handle;
103 107
104 108 scf_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
105 109 if (scf_max_name_len <= 0)
106 110 scf_max_name_len = SA_MAX_NAME_LEN + 1;
107 111
108 112 handle = calloc(1, sizeof (scfutilhandle_t));
109 113 if (handle == NULL)
110 114 return (handle);
111 115
112 116 ihandle->scfhandle = handle;
113 117 handle->scf_state = SCH_STATE_INITIALIZING;
114 118 handle->handle = scf_handle_create(SCF_VERSION);
115 119 if (handle->handle == NULL) {
116 120 free(handle);
117 121 handle = NULL;
118 122 (void) printf("libshare could not access SMF repository: %s\n",
119 123 scf_strerror(scf_error()));
120 124 return (handle);
121 125 }
122 126 if (scf_handle_bind(handle->handle) != 0)
123 127 goto err;
124 128
125 129 handle->scope = scf_scope_create(handle->handle);
126 130 handle->service = scf_service_create(handle->handle);
127 131 handle->pg = scf_pg_create(handle->handle);
128 132
129 133 /* Make sure we have sufficient SMF running */
130 134 handle->instance = scf_instance_create(handle->handle);
131 135 if (handle->scope == NULL || handle->service == NULL ||
132 136 handle->pg == NULL || handle->instance == NULL)
133 137 goto err;
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
134 138 if (scf_handle_get_scope(handle->handle,
135 139 SCF_SCOPE_LOCAL, handle->scope) != 0)
136 140 goto err;
137 141 if (scf_scope_get_service(handle->scope,
138 142 SA_GROUP_SVC_NAME, handle->service) != 0)
139 143 goto err;
140 144
141 145 handle->scf_state = SCH_STATE_INIT;
142 146 if (sa_get_instance(handle, "default") != SA_OK) {
143 147 sa_group_t defgrp;
144 - defgrp = sa_create_group((sa_handle_t)ihandle, "default", NULL);
148 + defgrp = sa_create_group(ihandle, "default", NULL);
145 149 /* Only NFS enabled for "default" group. */
146 150 if (defgrp != NULL)
147 151 (void) sa_create_optionset(defgrp, "nfs");
148 152 }
149 153
150 154 return (handle);
151 155
152 156 /* Error handling/unwinding */
153 157 err:
154 158 (void) sa_scf_fini(handle);
155 159 (void) printf("libshare SMF initialization problem: %s\n",
156 160 scf_strerror(scf_error()));
157 161 return (NULL);
158 162 }
159 163
160 164 /*
161 165 * get_scf_limit(name)
162 166 *
163 167 * Since we use scf_limit a lot and do the same check and return the
164 168 * same value if it fails, implement as a function for code
165 169 * simplification. Basically, if name isn't found, return MAXPATHLEN
166 170 * (1024) so we have a reasonable default buffer size.
167 171 */
168 172 static ssize_t
169 173 get_scf_limit(uint32_t name)
170 174 {
171 175 ssize_t vallen;
172 176
173 177 vallen = scf_limit(name);
174 178 if (vallen == (ssize_t)-1)
175 179 vallen = MAXPATHLEN;
176 180 return (vallen);
177 181 }
178 182
179 183 /*
180 184 * skip_property(name)
181 185 *
182 186 * Internal function to check to see if a property is an SMF magic
183 187 * property that needs to be skipped.
184 188 */
185 189 static int
186 190 skip_property(char *name)
187 191 {
188 192 int i;
189 193
190 194 for (i = 0; skip_props[i] != NULL; i++)
191 195 if (strcmp(name, skip_props[i]) == 0)
192 196 return (1);
193 197 return (0);
194 198 }
195 199
196 200 /*
197 201 * generate_unique_sharename(sharename)
198 202 *
199 203 * Shares are represented in SMF as property groups. Due to share
200 204 * paths containing characters that are not allowed in SMF names and
201 205 * the need to be unique, we use UUIDs to construct a unique name.
202 206 */
203 207
204 208 static void
205 209 generate_unique_sharename(char *sharename)
206 210 {
207 211 uuid_t uuid;
208 212
209 213 uuid_generate(uuid);
210 214 (void) strcpy(sharename, "S-");
211 215 uuid_unparse(uuid, sharename + 2);
212 216 }
213 217
214 218 /*
215 219 * valid_protocol(proto)
216 220 *
217 221 * Check to see if the specified protocol is a valid one for the
218 222 * general sharemgr facility. We determine this by checking which
219 223 * plugin protocols were found.
220 224 */
221 225
222 226 static int
223 227 valid_protocol(char *proto)
224 228 {
225 229 struct sa_proto_plugin *plugin;
226 230 for (plugin = sap_proto_list; plugin != NULL;
227 231 plugin = plugin->plugin_next)
228 232 if (strcmp(proto, plugin->plugin_ops->sa_protocol) == 0)
229 233 return (1);
230 234 return (0);
231 235 }
232 236
233 237 /*
234 238 * sa_extract_pgroup(root, handle, pg, nodetype, proto, sectype)
235 239 *
236 240 * Extract the name property group and create the specified type of
237 241 * node on the provided group. type will be optionset or security.
238 242 */
239 243
240 244 static int
241 245 sa_extract_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
242 246 scf_propertygroup_t *pg,
243 247 char *nodetype, char *proto, char *sectype)
244 248 {
245 249 xmlNodePtr node;
246 250 scf_iter_t *iter;
247 251 scf_property_t *prop;
248 252 scf_value_t *value;
249 253 char *name;
250 254 char *valuestr;
251 255 ssize_t vallen;
252 256 int ret = SA_OK;
253 257
254 258 vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
255 259
256 260 node = xmlNewChild(root, NULL, (xmlChar *)nodetype, NULL);
257 261 if (node == NULL)
258 262 return (ret);
259 263
260 264 if (proto != NULL)
261 265 (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
262 266 if (sectype != NULL)
263 267 (void) xmlSetProp(node, (xmlChar *)"sectype",
264 268 (xmlChar *)sectype);
265 269 /*
266 270 * Have node to work with so iterate over the properties
267 271 * in the pg and create option sub nodes.
268 272 */
269 273 iter = scf_iter_create(handle->handle);
270 274 value = scf_value_create(handle->handle);
271 275 prop = scf_property_create(handle->handle);
272 276 name = malloc(scf_max_name_len);
273 277 valuestr = malloc(vallen);
274 278 /*
275 279 * Want to iterate through the properties and add them
276 280 * to the base optionset.
277 281 */
278 282 if (iter == NULL || value == NULL || prop == NULL ||
279 283 valuestr == NULL || name == NULL) {
280 284 ret = SA_NO_MEMORY;
281 285 goto out;
282 286 }
283 287 if (scf_iter_pg_properties(iter, pg) == 0) {
284 288 /* Now iterate the properties in the group */
285 289 while (scf_iter_next_property(iter, prop) > 0) {
286 290 /* have a property */
287 291 if (scf_property_get_name(prop, name,
288 292 scf_max_name_len) > 0) {
289 293 sa_property_t saprop;
290 294 /* Some properties are part of the framework */
291 295 if (skip_property(name))
292 296 continue;
293 297 if (scf_property_get_value(prop, value) != 0)
294 298 continue;
295 299 if (scf_value_get_astring(value, valuestr,
296 300 vallen) < 0)
297 301 continue;
298 302 saprop = sa_create_property(name, valuestr);
299 303 if (saprop != NULL) {
300 304 /*
301 305 * Since in SMF, don't
302 306 * recurse. Use xmlAddChild
303 307 * directly, instead.
304 308 */
305 309 (void) xmlAddChild(node,
306 310 (xmlNodePtr) saprop);
307 311 }
308 312 }
309 313 }
310 314 }
311 315 out:
312 316 /* cleanup to avoid memory leaks */
313 317 if (value != NULL)
314 318 scf_value_destroy(value);
315 319 if (iter != NULL)
316 320 scf_iter_destroy(iter);
317 321 if (prop != NULL)
318 322 scf_property_destroy(prop);
319 323 if (name != NULL)
320 324 free(name);
321 325 if (valuestr != NULL)
322 326 free(valuestr);
323 327
324 328 return (ret);
325 329 }
326 330
327 331 /*
328 332 * sa_extract_attrs(root, handle, instance)
329 333 *
330 334 * Local function to extract the actual attributes/properties from the
331 335 * property group of the service instance. These are the well known
332 336 * attributes of "state" and "zfs". If additional attributes are
333 337 * added, they should be added here.
334 338 */
335 339
336 340 static void
337 341 sa_extract_attrs(xmlNodePtr root, scfutilhandle_t *handle,
338 342 scf_instance_t *instance)
339 343 {
340 344 scf_property_t *prop;
341 345 scf_value_t *value;
342 346 char *valuestr;
343 347 ssize_t vallen;
344 348
345 349 vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
346 350 prop = scf_property_create(handle->handle);
347 351 value = scf_value_create(handle->handle);
348 352 valuestr = malloc(vallen);
349 353 if (prop == NULL || value == NULL || valuestr == NULL ||
350 354 scf_instance_get_pg(instance, "operation", handle->pg) != 0) {
351 355 goto out;
352 356 }
353 357 /*
354 358 * Have a property group with desired name so now get
355 359 * the known attributes.
356 360 */
357 361 if (scf_pg_get_property(handle->pg, "state", prop) == 0) {
358 362 /* Found the property so get the value */
359 363 if (scf_property_get_value(prop, value) == 0) {
360 364 if (scf_value_get_astring(value, valuestr,
361 365 vallen) >= 0) {
362 366 (void) xmlSetProp(root, (xmlChar *)"state",
363 367 (xmlChar *)valuestr);
364 368 }
365 369 }
366 370 }
367 371 if (scf_pg_get_property(handle->pg, "zfs", prop) == 0) {
368 372 /* Found the property so get the value */
369 373 if (scf_property_get_value(prop, value) == 0) {
370 374 if (scf_value_get_astring(value, valuestr,
371 375 vallen) > 0) {
372 376 (void) xmlSetProp(root, (xmlChar *)"zfs",
373 377 (xmlChar *)valuestr);
374 378 }
375 379 }
376 380 }
377 381 out:
378 382 if (valuestr != NULL)
379 383 free(valuestr);
380 384 if (value != NULL)
381 385 scf_value_destroy(value);
382 386 if (prop != NULL)
383 387 scf_property_destroy(prop);
384 388 }
385 389
386 390 /*
387 391 * List of known share attributes.
388 392 */
389 393
390 394 static char *share_attr[] = {
391 395 "path",
392 396 "id",
393 397 "drive-letter",
394 398 "exclude",
395 399 NULL,
396 400 };
397 401
398 402 static int
399 403 is_share_attr(char *name)
400 404 {
401 405 int i;
402 406 for (i = 0; share_attr[i] != NULL; i++)
403 407 if (strcmp(name, share_attr[i]) == 0)
404 408 return (1);
405 409 return (0);
406 410 }
407 411
408 412 /*
409 413 * _sa_make_resource(node, valuestr)
410 414 *
411 415 * Make a resource node on the share node. The valusestr will either
412 416 * be old format (SMF acceptable string) or new format (pretty much an
413 417 * arbitrary string with "nnn:" prefixing in order to persist
414 418 * mapping). The input valuestr will get modified in place. This is
415 419 * only used in SMF repository parsing. A possible third field will be
416 420 * a "description" string.
417 421 */
418 422
419 423 static void
420 424 _sa_make_resource(xmlNodePtr node, char *valuestr)
421 425 {
422 426 char *idx;
423 427 char *name;
424 428 char *description = NULL;
425 429
426 430 idx = valuestr;
427 431 name = strchr(valuestr, ':');
428 432 if (name == NULL) {
429 433 /* this is old form so give an index of "0" */
430 434 idx = "0";
431 435 name = valuestr;
432 436 } else {
433 437 /* NUL the ':' and move past it */
434 438 *name++ = '\0';
435 439 /* There could also be a description string */
436 440 description = strchr(name, ':');
437 441 if (description != NULL)
438 442 *description++ = '\0';
439 443 }
440 444 node = xmlNewChild(node, NULL, (xmlChar *)"resource", NULL);
441 445 if (node != NULL) {
442 446 (void) xmlSetProp(node, (xmlChar *)"name", (xmlChar *)name);
443 447 (void) xmlSetProp(node, (xmlChar *)"id", (xmlChar *)idx);
444 448 /* SMF values are always persistent */
445 449 (void) xmlSetProp(node, (xmlChar *)"type",
446 450 (xmlChar *)"persist");
447 451 if (description != NULL && strlen(description) > 0) {
448 452 (void) xmlNewChild(node, NULL, (xmlChar *)"description",
449 453 (xmlChar *)description);
450 454 }
451 455 }
452 456 }
453 457
454 458
455 459 /*
456 460 * sa_share_from_pgroup
457 461 *
458 462 * Extract the share definition from the share property group. We do
459 463 * some sanity checking to avoid bad data.
460 464 *
461 465 * Since this is only constructing the internal data structures, we
462 466 * don't use the sa_* functions most of the time.
463 467 */
464 468 void
465 469 sa_share_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
466 470 scf_propertygroup_t *pg, char *id)
467 471 {
468 472 xmlNodePtr node;
469 473 char *name;
470 474 scf_iter_t *iter;
471 475 scf_property_t *prop;
472 476 scf_value_t *value;
473 477 ssize_t vallen;
474 478 char *valuestr;
475 479 int ret = SA_OK;
476 480 int have_path = 0;
477 481
478 482 /*
479 483 * While preliminary check (starts with 'S') passed before
480 484 * getting here. Need to make sure it is in ID syntax
481 485 * (Snnnnnn). Note that shares with properties have similar
482 486 * pgroups.
483 487 */
484 488 vallen = strlen(id);
485 489 if (*id == SA_SHARE_PG_PREFIX[0] && vallen == SA_SHARE_PG_LEN) {
486 490 uuid_t uuid;
487 491 if (strncmp(id, SA_SHARE_PG_PREFIX,
488 492 SA_SHARE_PG_PREFIXLEN) != 0 ||
489 493 uuid_parse(id + 2, uuid) < 0)
490 494 return;
491 495 } else {
492 496 return;
493 497 }
494 498
495 499 vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
496 500
497 501 iter = scf_iter_create(handle->handle);
498 502 value = scf_value_create(handle->handle);
499 503 prop = scf_property_create(handle->handle);
500 504 name = malloc(scf_max_name_len);
501 505 valuestr = malloc(vallen);
502 506
503 507 /*
504 508 * Construct the share XML node. It is similar to sa_add_share
505 509 * but never changes the repository. Also, there won't be any
506 510 * ZFS or transient shares. Root will be the group it is
507 511 * associated with.
508 512 */
509 513 node = xmlNewChild(root, NULL, (xmlChar *)"share", NULL);
510 514 if (node != NULL) {
511 515 /*
512 516 * Make sure the UUID part of the property group is
513 517 * stored in the share "id" property. We use this
514 518 * later.
515 519 */
516 520 (void) xmlSetProp(node, (xmlChar *)"id", (xmlChar *)id);
517 521 (void) xmlSetProp(node, (xmlChar *)"type",
518 522 (xmlChar *)"persist");
519 523 }
520 524
521 525 if (iter == NULL || value == NULL || prop == NULL || name == NULL)
522 526 goto out;
523 527
524 528 /* Iterate over the share pg properties */
525 529 if (scf_iter_pg_properties(iter, pg) != 0)
526 530 goto out;
527 531
528 532 while (scf_iter_next_property(iter, prop) > 0) {
529 533 ret = SA_SYSTEM_ERR; /* assume the worst */
530 534 if (scf_property_get_name(prop, name, scf_max_name_len) > 0) {
531 535 if (scf_property_get_value(prop, value) == 0) {
532 536 if (scf_value_get_astring(value, valuestr,
533 537 vallen) >= 0) {
534 538 ret = SA_OK;
535 539 }
536 540 } else if (strcmp(name, "resource") == 0) {
537 541 ret = SA_OK;
538 542 }
539 543 }
540 544 if (ret != SA_OK)
541 545 continue;
542 546 /*
543 547 * Check that we have the "path" property in
544 548 * name. The string in name will always be nul
545 549 * terminated if scf_property_get_name()
546 550 * succeeded.
547 551 */
548 552 if (strcmp(name, "path") == 0)
549 553 have_path = 1;
550 554 if (is_share_attr(name)) {
551 555 /*
552 556 * If a share attr, then simple -
553 557 * usually path and id name
554 558 */
555 559 (void) xmlSetProp(node, (xmlChar *)name,
556 560 (xmlChar *)valuestr);
557 561 } else if (strcmp(name, "resource") == 0) {
558 562 /*
559 563 * Resource names handled differently since
560 564 * there can be multiple on each share. The
561 565 * "resource" id must be preserved since this
562 566 * will be used by some protocols in mapping
563 567 * "property spaces" to names and is always
564 568 * used to create SMF property groups specific
565 569 * to resources. CIFS needs this. The first
566 570 * value is present so add and then loop for
567 571 * any additional. Since this is new and
568 572 * previous values may exist, handle
569 573 * conversions.
570 574 */
571 575 scf_iter_t *viter;
572 576 viter = scf_iter_create(handle->handle);
573 577 if (viter != NULL &&
574 578 scf_iter_property_values(viter, prop) == 0) {
575 579 while (scf_iter_next_value(viter, value) > 0) {
576 580 /* Have a value so process it */
577 581 if (scf_value_get_ustring(value,
578 582 valuestr, vallen) >= 0) {
579 583 /* have a ustring */
580 584 _sa_make_resource(node,
581 585 valuestr);
582 586 } else if (scf_value_get_astring(value,
583 587 valuestr, vallen) >= 0) {
584 588 /* have an astring */
585 589 _sa_make_resource(node,
586 590 valuestr);
587 591 }
588 592 }
589 593 scf_iter_destroy(viter);
590 594 }
591 595 } else {
592 596 if (strcmp(name, "description") == 0) {
593 597 /* We have a description node */
594 598 xmlNodePtr desc;
595 599 desc = xmlNewChild(node, NULL,
596 600 (xmlChar *)"description", NULL);
597 601 if (desc != NULL)
598 602 xmlNodeSetContent(desc,
599 603 (xmlChar *)valuestr);
600 604 }
601 605 }
602 606 }
603 607 out:
604 608 /*
605 609 * A share without a path is broken so we want to not include
606 610 * these. They shouldn't happen but if you kill a sharemgr in
607 611 * the process of creating a share, it could happen. They
608 612 * should be harmless. It is also possible that another
609 613 * sharemgr is running and in the process of creating a share.
610 614 */
611 615 if (have_path == 0 && node != NULL) {
612 616 xmlUnlinkNode(node);
613 617 xmlFreeNode(node);
614 618 }
615 619 if (name != NULL)
616 620 free(name);
617 621 if (valuestr != NULL)
618 622 free(valuestr);
619 623 if (value != NULL)
620 624 scf_value_destroy(value);
621 625 if (iter != NULL)
622 626 scf_iter_destroy(iter);
623 627 if (prop != NULL)
624 628 scf_property_destroy(prop);
625 629 }
626 630
627 631 /*
628 632 * find_share_by_id(shareid)
629 633 *
630 634 * Search all shares in all groups until we find the share represented
631 635 * by "id".
632 636 */
633 637
634 638 static sa_share_t
635 639 find_share_by_id(sa_handle_t handle, char *shareid)
636 640 {
637 641 sa_group_t group;
638 642 sa_share_t share = NULL;
639 643 char *id = NULL;
640 644 int done = 0;
641 645
642 646 for (group = sa_get_group(handle, NULL);
643 647 group != NULL && !done;
644 648 group = sa_get_next_group(group)) {
645 649 for (share = sa_get_share(group, NULL);
646 650 share != NULL;
647 651 share = sa_get_next_share(share)) {
648 652 id = sa_get_share_attr(share, "id");
649 653 if (id != NULL && strcmp(id, shareid) == 0) {
650 654 sa_free_attr_string(id);
651 655 id = NULL;
652 656 done++;
653 657 break;
654 658 }
655 659 if (id != NULL) {
656 660 sa_free_attr_string(id);
657 661 id = NULL;
658 662 }
659 663 }
660 664 }
661 665 return (share);
662 666 }
663 667
664 668 /*
665 669 * find_resource_by_index(share, index)
666 670 *
667 671 * Search the resource records on the share for the id index.
668 672 */
669 673 static sa_resource_t
670 674 find_resource_by_index(sa_share_t share, char *index)
671 675 {
672 676 sa_resource_t resource;
673 677 sa_resource_t found = NULL;
674 678 char *id;
675 679
676 680 for (resource = sa_get_share_resource(share, NULL);
677 681 resource != NULL && found == NULL;
678 682 resource = sa_get_next_resource(resource)) {
679 683 id = (char *)xmlGetProp((xmlNodePtr)resource, (xmlChar *)"id");
680 684 if (id != NULL) {
681 685 if (strcmp(id, index) == 0) {
682 686 /* found it so save in "found" */
683 687 found = resource;
684 688 }
685 689 sa_free_attr_string(id);
686 690 }
687 691 }
688 692 return (found);
689 693 }
690 694
691 695 /*
692 696 * sa_share_props_from_pgroup(root, handle, pg, id, sahandle)
693 697 *
694 698 * Extract share properties from the SMF property group. More sanity
695 699 * checks are done and the share object is created. We ignore some
696 700 * errors that could exist in the repository and only worry about
697 701 * property groups that validate in naming.
698 702 */
699 703
700 704 static int
701 705 sa_share_props_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
702 706 scf_propertygroup_t *pg, char *id, sa_handle_t sahandle)
703 707 {
704 708 xmlNodePtr node;
705 709 char *name = NULL;
706 710 scf_iter_t *iter = NULL;
707 711 scf_property_t *prop = NULL;
708 712 scf_value_t *value = NULL;
709 713 ssize_t vallen;
710 714 char *valuestr = NULL;
711 715 int ret = SA_OK;
712 716 char *sectype = NULL;
713 717 char *proto;
714 718 sa_share_t share;
715 719 uuid_t uuid;
716 720
717 721 /*
718 722 * While preliminary check (starts with 'S') passed before
719 723 * getting here. Need to make sure it is in ID syntax
720 724 * (Snnnnnn). Note that shares with properties have similar
721 725 * pgroups. If the pg name is more than SA_SHARE_PG_LEN
722 726 * characters, it is likely one of the protocol/security
723 727 * versions.
724 728 */
725 729 vallen = strlen(id);
726 730 if (*id != SA_SHARE_PG_PREFIX[0] || vallen <= SA_SHARE_PG_LEN) {
727 731 /*
728 732 * It is ok to not have what we thought since someone might
729 733 * have added a name via SMF.
730 734 */
731 735 return (ret);
732 736 }
733 737 if (strncmp(id, SA_SHARE_PG_PREFIX, SA_SHARE_PG_PREFIXLEN) == 0) {
734 738 proto = strchr(id, '_');
735 739 if (proto == NULL)
736 740 return (ret);
737 741 *proto++ = '\0';
738 742 if (uuid_parse(id + SA_SHARE_PG_PREFIXLEN, uuid) < 0)
739 743 return (ret);
740 744 /*
741 745 * probably a legal optionset so check a few more
742 746 * syntax points below.
743 747 */
744 748 if (*proto == '\0') {
745 749 /* not a valid proto (null) */
746 750 return (ret);
747 751 }
748 752
749 753 sectype = strchr(proto, '_');
750 754 if (sectype != NULL)
751 755 *sectype++ = '\0';
752 756 if (!valid_protocol(proto))
753 757 return (ret);
754 758 }
755 759
756 760 /*
757 761 * To get here, we have a valid protocol and possibly a
758 762 * security. We now have to find the share that it is really
759 763 * associated with. The "id" portion of the pgroup name will
760 764 * match.
761 765 */
762 766
763 767 share = find_share_by_id(sahandle, id);
764 768 if (share == NULL)
765 769 return (SA_BAD_PATH);
766 770
767 771 root = (xmlNodePtr)share;
768 772
769 773 vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
770 774
771 775 if (sectype == NULL)
772 776 node = xmlNewChild(root, NULL, (xmlChar *)"optionset", NULL);
773 777 else {
774 778 if (isdigit((int)*sectype)) {
775 779 sa_resource_t resource;
776 780 /*
777 781 * If sectype[0] is a digit, then it is an index into
778 782 * the resource names. We need to find a resource
779 783 * record and then get the properties into an
780 784 * optionset. The optionset becomes the "node" and the
781 785 * rest is hung off of the share.
782 786 */
783 787 resource = find_resource_by_index(share, sectype);
784 788 if (resource != NULL) {
785 789 node = xmlNewChild(resource, NULL,
786 790 (xmlChar *)"optionset", NULL);
787 791 } else {
788 792 /* This shouldn't happen. */
789 793 ret = SA_SYSTEM_ERR;
790 794 goto out;
791 795 }
792 796 } else {
793 797 /*
794 798 * If not a digit, then it is a security type
795 799 * (alternate option space). Security types start with
796 800 * an alphabetic.
797 801 */
798 802 node = xmlNewChild(root, NULL, (xmlChar *)"security",
799 803 NULL);
800 804 if (node != NULL)
801 805 (void) xmlSetProp(node, (xmlChar *)"sectype",
802 806 (xmlChar *)sectype);
803 807 }
804 808 }
805 809 if (node == NULL) {
806 810 ret = SA_NO_MEMORY;
807 811 goto out;
808 812 }
809 813
810 814 (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
811 815 /* now find the properties */
812 816 iter = scf_iter_create(handle->handle);
813 817 value = scf_value_create(handle->handle);
814 818 prop = scf_property_create(handle->handle);
815 819 name = malloc(scf_max_name_len);
816 820 valuestr = malloc(vallen);
817 821
818 822 if (iter == NULL || value == NULL || prop == NULL || name == NULL)
819 823 goto out;
820 824
821 825 /* iterate over the share pg properties */
822 826 if (scf_iter_pg_properties(iter, pg) == 0) {
823 827 while (scf_iter_next_property(iter, prop) > 0) {
824 828 ret = SA_SYSTEM_ERR; /* assume the worst */
825 829 if (scf_property_get_name(prop, name,
826 830 scf_max_name_len) > 0) {
827 831 if (scf_property_get_value(prop, value) == 0) {
828 832 if (scf_value_get_astring(value,
829 833 valuestr, vallen) >= 0) {
830 834 ret = SA_OK;
831 835 }
832 836 }
833 837 } else {
834 838 ret = SA_SYSTEM_ERR;
835 839 }
836 840 if (ret == SA_OK) {
837 841 sa_property_t prop;
838 842 prop = sa_create_property(name, valuestr);
839 843 if (prop != NULL)
840 844 prop = (sa_property_t)xmlAddChild(node,
841 845 (xmlNodePtr)prop);
842 846 else
843 847 ret = SA_NO_MEMORY;
844 848 }
845 849 }
846 850 } else {
847 851 ret = SA_SYSTEM_ERR;
848 852 }
849 853 out:
850 854 if (iter != NULL)
851 855 scf_iter_destroy(iter);
852 856 if (value != NULL)
853 857 scf_value_destroy(value);
854 858 if (prop != NULL)
855 859 scf_property_destroy(prop);
856 860 if (name != NULL)
857 861 free(name);
858 862 if (valuestr != NULL)
859 863 free(valuestr);
860 864 return (ret);
861 865 }
862 866
863 867 /*
864 868 * sa_extract_group(root, handle, instance)
865 869 *
866 870 * Get the config info for this instance of a group and create the XML
867 871 * subtree from it.
868 872 */
869 873
870 874 static int
871 875 sa_extract_group(xmlNodePtr root, scfutilhandle_t *handle,
872 876 scf_instance_t *instance, sa_handle_t sahandle)
873 877 {
874 878 char *buff;
875 879 xmlNodePtr node;
876 880 scf_iter_t *iter;
877 881 char *proto;
878 882 char *sectype;
879 883 boolean_t have_shares = B_FALSE;
880 884 boolean_t is_default = B_FALSE;
881 885 boolean_t is_nfs = B_FALSE;
882 886 int ret = SA_OK;
883 887 int err;
884 888
885 889 buff = malloc(scf_max_name_len);
886 890 if (buff == NULL)
887 891 return (SA_NO_MEMORY);
888 892
889 893 iter = scf_iter_create(handle->handle);
890 894 if (iter == NULL) {
891 895 ret = SA_NO_MEMORY;
892 896 goto out;
893 897 }
894 898
895 899 if (scf_instance_get_name(instance, buff, scf_max_name_len) > 0) {
896 900 node = xmlNewChild(root, NULL, (xmlChar *)"group", NULL);
897 901 if (node == NULL) {
898 902 ret = SA_NO_MEMORY;
899 903 goto out;
900 904 }
901 905 (void) xmlSetProp(node, (xmlChar *)"name", (xmlChar *)buff);
902 906 if (strcmp(buff, "default") == 0)
903 907 is_default = B_TRUE;
904 908
905 909 sa_extract_attrs(node, handle, instance);
906 910 /*
907 911 * Iterate through all the property groups
908 912 * looking for those with security or
909 913 * optionset prefixes. The names of the
910 914 * matching pgroups are parsed to get the
911 915 * protocol, and for security, the sectype.
912 916 * Syntax is as follows:
913 917 * optionset | optionset_<proto>
914 918 * security_default | security_<proto>_<sectype>
915 919 * "operation" is handled by
916 920 * sa_extract_attrs().
917 921 */
918 922 if (scf_iter_instance_pgs(iter, instance) != 0) {
919 923 ret = SA_NO_MEMORY;
920 924 goto out;
921 925 }
922 926 while (scf_iter_next_pg(iter, handle->pg) > 0) {
923 927 /* Have a pgroup so sort it out */
924 928 ret = scf_pg_get_name(handle->pg, buff,
925 929 scf_max_name_len);
926 930 if (ret <= 0)
927 931 continue;
928 932 is_nfs = B_FALSE;
929 933
930 934 if (buff[0] == SA_SHARE_PG_PREFIX[0]) {
931 935 sa_share_from_pgroup(node, handle,
932 936 handle->pg, buff);
933 937 have_shares = B_TRUE;
934 938 } else if (strncmp(buff, "optionset", 9) == 0) {
935 939 char *nodetype = "optionset";
936 940 /* Have an optionset */
937 941 sectype = NULL;
938 942 proto = strchr(buff, '_');
939 943 if (proto != NULL) {
940 944 *proto++ = '\0';
941 945 sectype = strchr(proto, '_');
942 946 if (sectype != NULL) {
943 947 *sectype++ = '\0';
944 948 nodetype = "security";
945 949 }
946 950 is_nfs = strcmp(proto, "nfs") == 0;
947 951 } else if (strlen(buff) > 9) {
948 952 /*
949 953 * This can only occur if
950 954 * someone has made changes
951 955 * via an SMF command. Since
952 956 * this would be an unknown
953 957 * syntax, we just ignore it.
954 958 */
955 959 continue;
956 960 }
957 961 /*
958 962 * If the group is not "default" or is
959 963 * "default" and is_nfs, then extract the
960 964 * pgroup. If it is_default and !is_nfs,
961 965 * then we have an error and should remove
962 966 * the extraneous protocols. We don't care
963 967 * about errors on scf_pg_delete since we
964 968 * might not have permission during an
965 969 * extract only.
966 970 */
967 971 if (!is_default || is_nfs) {
968 972 ret = sa_extract_pgroup(node, handle,
969 973 handle->pg, nodetype, proto,
970 974 sectype);
971 975 } else {
972 976 err = scf_pg_delete(handle->pg);
973 977 if (err == 0)
974 978 (void) fprintf(stderr,
975 979 dgettext(TEXT_DOMAIN,
976 980 "Removed protocol \"%s\" "
977 981 "from group \"default\"\n"),
978 982 proto);
979 983 }
980 984 } else if (strncmp(buff, "security", 8) == 0) {
981 985 /*
982 986 * Have a security (note that
983 987 * this should change in the
984 988 * future)
985 989 */
986 990 proto = strchr(buff, '_');
987 991 sectype = NULL;
988 992 if (proto != NULL) {
989 993 *proto++ = '\0';
990 994 sectype = strchr(proto, '_');
991 995 if (sectype != NULL)
992 996 *sectype++ = '\0';
993 997 if (strcmp(proto, "default") == 0)
994 998 proto = NULL;
995 999 }
996 1000 ret = sa_extract_pgroup(node, handle,
997 1001 handle->pg, "security", proto, sectype);
998 1002 }
999 1003 /* Ignore everything else */
1000 1004 }
1001 1005 /*
1002 1006 * Make sure we have a valid default group.
1003 1007 * On first boot, default won't have any
1004 1008 * protocols defined and won't be enabled (but
1005 1009 * should be). "default" only has NFS enabled on it.
1006 1010 */
1007 1011 if (is_default) {
1008 1012 char *state = sa_get_group_attr((sa_group_t)node,
1009 1013 "state");
1010 1014
1011 1015 if (state == NULL) {
1012 1016 /* set attribute to enabled */
1013 1017 (void) sa_set_group_attr((sa_group_t)node,
1014 1018 "state", "enabled");
1015 1019 (void) sa_create_optionset((sa_group_t)node,
1016 1020 "nfs");
1017 1021 } else {
1018 1022 sa_free_attr_string(state);
1019 1023 }
1020 1024 }
1021 1025 /* Do a second pass if shares were found */
1022 1026 if (have_shares && scf_iter_instance_pgs(iter, instance) == 0) {
1023 1027 while (scf_iter_next_pg(iter, handle->pg) > 0) {
1024 1028 /*
1025 1029 * Have a pgroup so see if it is a
1026 1030 * share optionset
1027 1031 */
1028 1032 err = scf_pg_get_name(handle->pg, buff,
1029 1033 scf_max_name_len);
1030 1034 if (err <= 0)
1031 1035 continue;
1032 1036 if (buff[0] == SA_SHARE_PG_PREFIX[0]) {
1033 1037 ret = sa_share_props_from_pgroup(node,
1034 1038 handle, handle->pg, buff,
1035 1039 sahandle);
1036 1040 }
1037 1041 }
1038 1042 }
1039 1043 }
1040 1044 out:
1041 1045 if (iter != NULL)
1042 1046 scf_iter_destroy(iter);
1043 1047 if (buff != NULL)
1044 1048 free(buff);
1045 1049 return (ret);
1046 1050 }
1047 1051
1048 1052 /*
1049 1053 * sa_extract_defaults(root, handle, instance)
1050 1054 *
1051 1055 * Local function to find the default properties that live in the
1052 1056 * default instance's "operation" property group.
1053 1057 */
1054 1058
1055 1059 static void
1056 1060 sa_extract_defaults(xmlNodePtr root, scfutilhandle_t *handle,
1057 1061 scf_instance_t *instance)
1058 1062 {
1059 1063 xmlNodePtr node;
1060 1064 scf_property_t *prop;
1061 1065 scf_value_t *value;
1062 1066 char *valuestr;
1063 1067 ssize_t vallen;
1064 1068
1065 1069 vallen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1066 1070 prop = scf_property_create(handle->handle);
1067 1071 value = scf_value_create(handle->handle);
1068 1072 valuestr = malloc(vallen);
1069 1073
1070 1074 if (prop == NULL || value == NULL || vallen == 0 ||
1071 1075 scf_instance_get_pg(instance, "operation", handle->pg) != 0)
1072 1076 goto out;
1073 1077
1074 1078 if (scf_pg_get_property(handle->pg, "legacy-timestamp", prop) != 0)
1075 1079 goto out;
1076 1080
1077 1081 /* Found the property so get the value */
1078 1082 if (scf_property_get_value(prop, value) == 0) {
1079 1083 if (scf_value_get_astring(value, valuestr, vallen) > 0) {
1080 1084 node = xmlNewChild(root, NULL, (xmlChar *)"legacy",
1081 1085 NULL);
1082 1086 if (node != NULL) {
1083 1087 (void) xmlSetProp(node, (xmlChar *)"timestamp",
1084 1088 (xmlChar *)valuestr);
1085 1089 (void) xmlSetProp(node, (xmlChar *)"path",
1086 1090 (xmlChar *)SA_LEGACY_DFSTAB);
1087 1091 }
1088 1092 }
1089 1093 }
1090 1094 out:
1091 1095 if (valuestr != NULL)
1092 1096 free(valuestr);
1093 1097 if (value != NULL)
1094 1098 scf_value_destroy(value);
1095 1099 if (prop != NULL)
1096 1100 scf_property_destroy(prop);
1097 1101 }
1098 1102
1099 1103
1100 1104 /*
1101 1105 * sa_get_config(handle, root, doc, sahandle)
1102 1106 *
1103 1107 * Walk the SMF repository for /network/shares/group and find all the
1104 1108 * instances. These become group names. Then add the XML structure
1105 1109 * below the groups based on property groups and properties.
1106 1110 */
1107 1111 int
1108 1112 sa_get_config(scfutilhandle_t *handle, xmlNodePtr root, sa_handle_t sahandle)
1109 1113 {
1110 1114 int ret = SA_OK;
1111 1115 scf_instance_t *instance;
1112 1116 scf_iter_t *iter;
1113 1117 char buff[BUFSIZ * 2];
1114 1118
1115 1119 instance = scf_instance_create(handle->handle);
1116 1120 iter = scf_iter_create(handle->handle);
1117 1121 if (instance != NULL && iter != NULL) {
1118 1122 if ((ret = scf_iter_service_instances(iter,
1119 1123 handle->service)) == 0) {
1120 1124 while ((ret = scf_iter_next_instance(iter,
1121 1125 instance)) > 0) {
1122 1126 if (scf_instance_get_name(instance, buff,
1123 1127 sizeof (buff)) > 0) {
1124 1128 if (strcmp(buff, "default") == 0)
1125 1129 sa_extract_defaults(root,
1126 1130 handle, instance);
1127 1131 ret = sa_extract_group(root, handle,
1128 1132 instance, sahandle);
1129 1133 }
1130 1134 }
1131 1135 }
1132 1136 }
1133 1137
1134 1138 /* Always cleanup these */
1135 1139 if (instance != NULL)
1136 1140 scf_instance_destroy(instance);
1137 1141 if (iter != NULL)
1138 1142 scf_iter_destroy(iter);
1139 1143 return (ret);
1140 1144 }
1141 1145
1142 1146 /*
1143 1147 * sa_get_instance(handle, instance)
1144 1148 *
1145 1149 * Get the instance of the group service. This is actually the
1146 1150 * specific group name. The instance is needed for all property and
1147 1151 * control operations.
1148 1152 */
1149 1153
1150 1154 int
1151 1155 sa_get_instance(scfutilhandle_t *handle, char *instname)
1152 1156 {
1153 1157 if (scf_service_get_instance(handle->service, instname,
1154 1158 handle->instance) != 0) {
1155 1159 return (SA_NO_SUCH_GROUP);
1156 1160 }
1157 1161 return (SA_OK);
1158 1162 }
1159 1163
1160 1164 /*
1161 1165 * sa_create_instance(handle, instname)
1162 1166 *
1163 1167 * Create a new SMF service instance. There can only be one with a
1164 1168 * given name.
1165 1169 */
1166 1170
1167 1171 int
1168 1172 sa_create_instance(scfutilhandle_t *handle, char *instname)
1169 1173 {
1170 1174 int ret = SA_OK;
1171 1175 char instance[SA_GROUP_INST_LEN];
1172 1176 if (scf_service_add_instance(handle->service, instname,
1173 1177 handle->instance) != 0) {
1174 1178 /* better error returns need to be added based on real error */
1175 1179 if (scf_error() == SCF_ERROR_PERMISSION_DENIED)
1176 1180 ret = SA_NO_PERMISSION;
1177 1181 else
1178 1182 ret = SA_DUPLICATE_NAME;
1179 1183 } else {
1180 1184 /* have the service created, so enable it */
1181 1185 (void) snprintf(instance, sizeof (instance), "%s:%s",
1182 1186 SA_SVC_FMRI_BASE, instname);
1183 1187 (void) smf_enable_instance(instance, 0);
1184 1188 }
1185 1189 return (ret);
1186 1190 }
1187 1191
1188 1192 /*
1189 1193 * sa_delete_instance(handle, instname)
1190 1194 *
1191 1195 * When a group goes away, we also remove the service instance.
1192 1196 */
1193 1197
1194 1198 int
1195 1199 sa_delete_instance(scfutilhandle_t *handle, char *instname)
1196 1200 {
1197 1201 int ret;
1198 1202
1199 1203 if (strcmp(instname, "default") == 0) {
1200 1204 ret = SA_NO_PERMISSION;
1201 1205 } else {
1202 1206 if ((ret = sa_get_instance(handle, instname)) == SA_OK) {
1203 1207 if (scf_instance_delete(handle->instance) != 0)
1204 1208 /* need better analysis */
1205 1209 ret = SA_NO_PERMISSION;
1206 1210 }
1207 1211 }
1208 1212 return (ret);
1209 1213 }
1210 1214
1211 1215 /*
1212 1216 * sa_create_pgroup(handle, pgroup)
1213 1217 *
1214 1218 * create a new property group
1215 1219 */
1216 1220
1217 1221 int
1218 1222 sa_create_pgroup(scfutilhandle_t *handle, char *pgroup)
1219 1223 {
1220 1224 int ret = SA_OK;
1221 1225 int persist = 0;
1222 1226
1223 1227 /*
1224 1228 * Only create a handle if it doesn't exist. It is ok to exist
1225 1229 * since the pg handle will be set as a side effect.
1226 1230 */
1227 1231 if (handle->pg == NULL)
1228 1232 handle->pg = scf_pg_create(handle->handle);
1229 1233
1230 1234 /*
1231 1235 * Special case for a non-persistent property group. This is
1232 1236 * internal use only.
1233 1237 */
1234 1238 if (*pgroup == '*') {
1235 1239 persist = SCF_PG_FLAG_NONPERSISTENT;
1236 1240 pgroup++;
1237 1241 }
1238 1242
1239 1243 /*
1240 1244 * If the pgroup exists, we are done. If it doesn't, then we
1241 1245 * need to actually add one to the service instance.
1242 1246 */
1243 1247 if (scf_instance_get_pg(handle->instance,
1244 1248 pgroup, handle->pg) != 0) {
1245 1249
1246 1250 /* Doesn't exist so create one */
1247 1251 if (scf_instance_add_pg(handle->instance, pgroup,
1248 1252 SCF_GROUP_APPLICATION, persist, handle->pg) != 0) {
1249 1253 switch (scf_error()) {
1250 1254 case SCF_ERROR_PERMISSION_DENIED:
1251 1255 ret = SA_NO_PERMISSION;
1252 1256 break;
1253 1257 default:
1254 1258 ret = SA_SYSTEM_ERR;
1255 1259 break;
1256 1260 }
1257 1261 }
1258 1262 }
1259 1263 return (ret);
1260 1264 }
1261 1265
1262 1266 /*
1263 1267 * sa_delete_pgroup(handle, pgroup)
1264 1268 *
1265 1269 * Remove the property group from the current instance of the service,
1266 1270 * but only if it actually exists.
1267 1271 */
1268 1272
1269 1273 int
1270 1274 sa_delete_pgroup(scfutilhandle_t *handle, char *pgroup)
1271 1275 {
1272 1276 int ret = SA_OK;
1273 1277 /*
1274 1278 * Only delete if it does exist.
1275 1279 */
1276 1280 if (scf_instance_get_pg(handle->instance, pgroup, handle->pg) == 0) {
1277 1281 /* does exist so delete it */
1278 1282 if (scf_pg_delete(handle->pg) != 0)
1279 1283 ret = SA_SYSTEM_ERR;
1280 1284 } else {
1281 1285 ret = SA_SYSTEM_ERR;
1282 1286 }
1283 1287 if (ret == SA_SYSTEM_ERR &&
1284 1288 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
1285 1289 ret = SA_NO_PERMISSION;
1286 1290 }
1287 1291 return (ret);
1288 1292 }
1289 1293
1290 1294 /*
1291 1295 * sa_start_transaction(handle, pgroup)
1292 1296 *
1293 1297 * Start an SMF transaction so we can deal with properties. it would
1294 1298 * be nice to not have to expose this, but we have to in order to
1295 1299 * optimize.
1296 1300 *
1297 1301 * Basic model is to hold the transaction in the handle and allow
1298 1302 * property adds/deletes/updates to be added then close the
1299 1303 * transaction (or abort). There may eventually be a need to handle
1300 1304 * other types of transaction mechanisms but we don't do that now.
1301 1305 *
1302 1306 * An sa_start_transaction must be followed by either an
1303 1307 * sa_end_transaction or sa_abort_transaction before another
1304 1308 * sa_start_transaction can be done.
1305 1309 */
1306 1310
1307 1311 int
1308 1312 sa_start_transaction(scfutilhandle_t *handle, char *propgroup)
1309 1313 {
1310 1314 int ret = SA_OK;
1311 1315 /*
1312 1316 * Lookup the property group and create it if it doesn't already
1313 1317 * exist.
1314 1318 */
1315 1319 if (handle == NULL)
1316 1320 return (SA_CONFIG_ERR);
1317 1321
1318 1322 if (handle->scf_state == SCH_STATE_INIT) {
1319 1323 ret = sa_create_pgroup(handle, propgroup);
1320 1324 if (ret == SA_OK) {
1321 1325 handle->trans = scf_transaction_create(handle->handle);
1322 1326 if (handle->trans != NULL) {
1323 1327 if (scf_transaction_start(handle->trans,
1324 1328 handle->pg) != 0) {
1325 1329 ret = SA_SYSTEM_ERR;
1326 1330 }
1327 1331 if (ret != SA_OK) {
1328 1332 scf_transaction_destroy(handle->trans);
1329 1333 handle->trans = NULL;
1330 1334 }
1331 1335 } else {
1332 1336 ret = SA_SYSTEM_ERR;
1333 1337 }
1334 1338 }
1335 1339 }
1336 1340 if (ret == SA_SYSTEM_ERR &&
1337 1341 scf_error() == SCF_ERROR_PERMISSION_DENIED) {
1338 1342 ret = SA_NO_PERMISSION;
1339 1343 }
1340 1344 return (ret);
1341 1345 }
↓ open down ↓ |
1187 lines elided |
↑ open up ↑ |
1342 1346
1343 1347
1344 1348 /*
1345 1349 * sa_end_transaction(scfhandle, sahandle)
1346 1350 *
1347 1351 * Commit the changes that were added to the transaction in the
1348 1352 * handle. Do all necessary cleanup.
1349 1353 */
1350 1354
1351 1355 int
1352 -sa_end_transaction(scfutilhandle_t *handle, sa_handle_impl_t sahandle)
1356 +sa_end_transaction(scfutilhandle_t *handle, sa_handle_t sahandle)
1353 1357 {
1354 1358 int ret = SA_OK;
1355 1359
1356 1360 if (handle == NULL || handle->trans == NULL || sahandle == NULL) {
1357 1361 ret = SA_SYSTEM_ERR;
1358 1362 } else {
1359 1363 if (scf_transaction_commit(handle->trans) < 0)
1360 1364 ret = SA_SYSTEM_ERR;
1361 1365 scf_transaction_destroy_children(handle->trans);
1362 1366 scf_transaction_destroy(handle->trans);
1363 1367 if (ret == SA_OK)
1364 1368 set_transaction_tstamp(sahandle);
1365 1369 handle->trans = NULL;
1366 1370 }
1367 1371 return (ret);
1368 1372 }
1369 1373
1370 1374 /*
1371 1375 * sa_abort_transaction(handle)
1372 1376 *
1373 1377 * Abort the changes that were added to the transaction in the
1374 1378 * handle. Do all necessary cleanup.
1375 1379 */
1376 1380
1377 1381 void
1378 1382 sa_abort_transaction(scfutilhandle_t *handle)
1379 1383 {
1380 1384 if (handle->trans != NULL) {
1381 1385 scf_transaction_reset_all(handle->trans);
1382 1386 scf_transaction_destroy_children(handle->trans);
1383 1387 scf_transaction_destroy(handle->trans);
1384 1388 handle->trans = NULL;
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
1385 1389 }
1386 1390 }
1387 1391
1388 1392 /*
1389 1393 * set_transaction_tstamp(sahandle)
1390 1394 *
1391 1395 * After a successful transaction commit, update the timestamp of the
1392 1396 * last transaction. This lets us detect changes from other processes.
1393 1397 */
1394 1398 static void
1395 -set_transaction_tstamp(sa_handle_impl_t sahandle)
1399 +set_transaction_tstamp(sa_handle_t sahandle)
1396 1400 {
1397 1401 char tstring[32];
1398 1402 struct timeval tv;
1399 1403 scfutilhandle_t *scfhandle;
1400 1404
1401 1405 if (sahandle == NULL || sahandle->scfhandle == NULL)
1402 1406 return;
1403 1407
1404 1408 scfhandle = sahandle->scfhandle;
1405 1409
1406 1410 if (sa_get_instance(scfhandle, "default") != SA_OK)
1407 1411 return;
1408 1412
1409 1413 if (gettimeofday(&tv, NULL) != 0)
1410 1414 return;
1411 1415
1412 1416 if (sa_start_transaction(scfhandle, "*state") != SA_OK)
1413 1417 return;
1414 1418
1415 1419 sahandle->tstrans = TSTAMP((*(timestruc_t *)&tv));
1416 1420 (void) snprintf(tstring, sizeof (tstring), "%lld", sahandle->tstrans);
1417 1421 if (sa_set_property(sahandle->scfhandle, "lastupdate", tstring) ==
1418 1422 SA_OK) {
1419 1423 /*
1420 1424 * While best if it succeeds, a failure doesn't cause
1421 1425 * problems and we will ignore it anyway.
1422 1426 */
1423 1427 (void) scf_transaction_commit(scfhandle->trans);
1424 1428 scf_transaction_destroy_children(scfhandle->trans);
1425 1429 scf_transaction_destroy(scfhandle->trans);
1426 1430 } else {
1427 1431 sa_abort_transaction(scfhandle);
1428 1432 }
1429 1433 }
1430 1434
1431 1435 /*
1432 1436 * sa_set_property(handle, prop, value)
1433 1437 *
1434 1438 * Set a property transaction entry into the pending SMF transaction.
1435 1439 */
1436 1440
1437 1441 int
1438 1442 sa_set_property(scfutilhandle_t *handle, char *propname, char *valstr)
1439 1443 {
1440 1444 int ret = SA_OK;
1441 1445 scf_value_t *value;
1442 1446 scf_transaction_entry_t *entry;
1443 1447 /*
1444 1448 * Properties must be set in transactions and don't take
1445 1449 * effect until the transaction has been ended/committed.
1446 1450 */
1447 1451 value = scf_value_create(handle->handle);
1448 1452 entry = scf_entry_create(handle->handle);
1449 1453 if (value != NULL && entry != NULL) {
1450 1454 if (scf_transaction_property_change(handle->trans, entry,
1451 1455 propname, SCF_TYPE_ASTRING) == 0 ||
1452 1456 scf_transaction_property_new(handle->trans, entry,
1453 1457 propname, SCF_TYPE_ASTRING) == 0) {
1454 1458 if (scf_value_set_astring(value, valstr) == 0) {
1455 1459 if (scf_entry_add_value(entry, value) != 0) {
1456 1460 ret = SA_SYSTEM_ERR;
1457 1461 scf_value_destroy(value);
1458 1462 }
1459 1463 /* The value is in the transaction */
1460 1464 value = NULL;
1461 1465 } else {
1462 1466 /* Value couldn't be constructed */
1463 1467 ret = SA_SYSTEM_ERR;
1464 1468 }
1465 1469 /* The entry is in the transaction */
1466 1470 entry = NULL;
1467 1471 } else {
1468 1472 ret = SA_SYSTEM_ERR;
1469 1473 }
1470 1474 } else {
1471 1475 ret = SA_SYSTEM_ERR;
1472 1476 }
1473 1477 if (ret == SA_SYSTEM_ERR) {
1474 1478 switch (scf_error()) {
1475 1479 case SCF_ERROR_PERMISSION_DENIED:
1476 1480 ret = SA_NO_PERMISSION;
1477 1481 break;
1478 1482 }
1479 1483 }
1480 1484 /*
1481 1485 * Cleanup if there were any errors that didn't leave these
1482 1486 * values where they would be cleaned up later.
1483 1487 */
1484 1488 if (value != NULL)
1485 1489 scf_value_destroy(value);
1486 1490 if (entry != NULL)
1487 1491 scf_entry_destroy(entry);
1488 1492 return (ret);
1489 1493 }
1490 1494
1491 1495 /*
1492 1496 * check_resource(share)
1493 1497 *
1494 1498 * Check to see if share has any persistent resources. We don't want
1495 1499 * to save if they are all transient.
1496 1500 */
1497 1501 static int
1498 1502 check_resource(sa_share_t share)
1499 1503 {
1500 1504 sa_resource_t resource;
1501 1505 int ret = B_FALSE;
1502 1506
1503 1507 for (resource = sa_get_share_resource(share, NULL);
1504 1508 resource != NULL && ret == B_FALSE;
1505 1509 resource = sa_get_next_resource(resource)) {
1506 1510 char *type;
1507 1511 type = sa_get_resource_attr(resource, "type");
1508 1512 if (type != NULL) {
1509 1513 if (strcmp(type, "transient") != 0) {
1510 1514 ret = B_TRUE;
1511 1515 }
1512 1516 sa_free_attr_string(type);
1513 1517 }
1514 1518 }
1515 1519 return (ret);
1516 1520 }
1517 1521
1518 1522 /*
1519 1523 * sa_set_resource_property(handle, prop, value)
1520 1524 *
1521 1525 * set a property transaction entry into the pending SMF
1522 1526 * transaction. We don't want to include any transient resources
1523 1527 */
1524 1528
1525 1529 static int
1526 1530 sa_set_resource_property(scfutilhandle_t *handle, sa_share_t share)
1527 1531 {
1528 1532 int ret = SA_OK;
1529 1533 scf_value_t *value;
1530 1534 scf_transaction_entry_t *entry;
1531 1535 sa_resource_t resource;
1532 1536 char *valstr;
1533 1537 char *idstr;
1534 1538 char *description;
1535 1539 char *propstr = NULL;
1536 1540 size_t strsize;
1537 1541
1538 1542 /* don't bother if no persistent resources */
1539 1543 if (check_resource(share) == B_FALSE)
1540 1544 return (ret);
1541 1545
1542 1546 /*
1543 1547 * properties must be set in transactions and don't take
1544 1548 * effect until the transaction has been ended/committed.
1545 1549 */
1546 1550 entry = scf_entry_create(handle->handle);
1547 1551 if (entry == NULL)
1548 1552 return (SA_SYSTEM_ERR);
1549 1553
1550 1554 if (scf_transaction_property_change(handle->trans, entry,
1551 1555 "resource", SCF_TYPE_ASTRING) != 0 &&
1552 1556 scf_transaction_property_new(handle->trans, entry,
1553 1557 "resource", SCF_TYPE_ASTRING) != 0) {
1554 1558 scf_entry_destroy(entry);
1555 1559 return (SA_SYSTEM_ERR);
1556 1560
1557 1561 }
1558 1562 for (resource = sa_get_share_resource(share, NULL);
1559 1563 resource != NULL;
1560 1564 resource = sa_get_next_resource(resource)) {
1561 1565 value = scf_value_create(handle->handle);
1562 1566 if (value == NULL) {
1563 1567 ret = SA_NO_MEMORY;
1564 1568 break;
1565 1569 }
1566 1570 /* Get size of complete string */
1567 1571 valstr = sa_get_resource_attr(resource, "name");
1568 1572 idstr = sa_get_resource_attr(resource, "id");
1569 1573 description = sa_get_resource_description(resource);
1570 1574 strsize = (valstr != NULL) ? strlen(valstr) : 0;
1571 1575 strsize += (idstr != NULL) ? strlen(idstr) : 0;
1572 1576 strsize += (description != NULL) ? strlen(description) : 0;
1573 1577 if (strsize > 0) {
1574 1578 strsize += 3; /* add nul and ':' */
1575 1579 propstr = (char *)malloc(strsize);
1576 1580 if (propstr == NULL) {
1577 1581 scf_value_destroy(value);
1578 1582 ret = SA_NO_MEMORY;
1579 1583 goto err;
1580 1584 }
1581 1585 if (idstr == NULL)
1582 1586 (void) snprintf(propstr, strsize, "%s",
1583 1587 valstr ? valstr : "");
1584 1588 else
1585 1589 (void) snprintf(propstr, strsize, "%s:%s:%s",
1586 1590 idstr, valstr ? valstr : "",
1587 1591 description ? description : "");
1588 1592 if (scf_value_set_astring(value, propstr) != 0) {
1589 1593 ret = SA_SYSTEM_ERR;
1590 1594 free(propstr);
1591 1595 scf_value_destroy(value);
1592 1596 break;
1593 1597 }
1594 1598 if (scf_entry_add_value(entry, value) != 0) {
1595 1599 ret = SA_SYSTEM_ERR;
1596 1600 free(propstr);
1597 1601 scf_value_destroy(value);
1598 1602 break;
1599 1603 }
1600 1604 /* the value is in the transaction */
1601 1605 value = NULL;
1602 1606 free(propstr);
1603 1607 }
1604 1608 err:
1605 1609 if (valstr != NULL) {
1606 1610 sa_free_attr_string(valstr);
1607 1611 valstr = NULL;
1608 1612 }
1609 1613 if (idstr != NULL) {
1610 1614 sa_free_attr_string(idstr);
1611 1615 idstr = NULL;
1612 1616 }
1613 1617 if (description != NULL) {
1614 1618 sa_free_share_description(description);
1615 1619 description = NULL;
1616 1620 }
1617 1621 }
1618 1622 /* the entry is in the transaction */
1619 1623 entry = NULL;
1620 1624
1621 1625 if (valstr != NULL)
1622 1626 sa_free_attr_string(valstr);
1623 1627 if (idstr != NULL)
1624 1628 sa_free_attr_string(idstr);
1625 1629 if (description != NULL)
1626 1630 sa_free_share_description(description);
1627 1631
1628 1632 if (ret == SA_SYSTEM_ERR) {
1629 1633 switch (scf_error()) {
1630 1634 case SCF_ERROR_PERMISSION_DENIED:
1631 1635 ret = SA_NO_PERMISSION;
1632 1636 break;
1633 1637 }
1634 1638 }
1635 1639 /*
1636 1640 * cleanup if there were any errors that didn't leave
1637 1641 * these values where they would be cleaned up later.
1638 1642 */
1639 1643 if (entry != NULL)
1640 1644 scf_entry_destroy(entry);
1641 1645
1642 1646 return (ret);
1643 1647 }
1644 1648
1645 1649 /*
1646 1650 * sa_commit_share(handle, group, share)
1647 1651 *
1648 1652 * Commit this share to the repository.
1649 1653 * properties are added if they exist but can be added later.
1650 1654 * Need to add to dfstab and sharetab, if appropriate.
1651 1655 */
1652 1656 int
1653 1657 sa_commit_share(scfutilhandle_t *handle, sa_group_t group, sa_share_t share)
1654 1658 {
1655 1659 int ret = SA_OK;
1656 1660 char *groupname;
1657 1661 char *name;
1658 1662 char *description;
1659 1663 char *sharename;
1660 1664 ssize_t proplen;
1661 1665 char *propstring;
1662 1666
1663 1667 /*
1664 1668 * Don't commit in the zfs group. We do commit legacy
1665 1669 * (default) and all other groups/shares. ZFS is handled
1666 1670 * through the ZFS configuration rather than SMF.
1667 1671 */
1668 1672
1669 1673 groupname = sa_get_group_attr(group, "name");
1670 1674 if (groupname != NULL) {
1671 1675 if (strcmp(groupname, "zfs") == 0) {
1672 1676 /*
1673 1677 * Adding to the ZFS group will result in the sharenfs
1674 1678 * property being set but we don't want to do anything
1675 1679 * SMF related at this point.
1676 1680 */
1677 1681 sa_free_attr_string(groupname);
1678 1682 return (ret);
1679 1683 }
1680 1684 }
1681 1685
1682 1686 proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1683 1687 propstring = malloc(proplen);
1684 1688 if (propstring == NULL)
1685 1689 ret = SA_NO_MEMORY;
1686 1690
1687 1691 if (groupname != NULL && ret == SA_OK) {
1688 1692 ret = sa_get_instance(handle, groupname);
1689 1693 sa_free_attr_string(groupname);
1690 1694 groupname = NULL;
1691 1695 sharename = sa_get_share_attr(share, "id");
1692 1696 if (sharename == NULL) {
1693 1697 /* slipped by */
1694 1698 char shname[SA_SHARE_UUID_BUFLEN];
1695 1699 generate_unique_sharename(shname);
1696 1700 (void) xmlSetProp((xmlNodePtr)share, (xmlChar *)"id",
1697 1701 (xmlChar *)shname);
1698 1702 sharename = strdup(shname);
1699 1703 }
1700 1704 if (sharename != NULL) {
1701 1705 sigset_t old, new;
1702 1706 /*
1703 1707 * Have a share name allocated so create a pgroup for
1704 1708 * it. It may already exist, but that is OK. In order
1705 1709 * to avoid creating a share pgroup that doesn't have
1706 1710 * a path property, block signals around the critical
1707 1711 * region of creating the share pgroup and props.
1708 1712 */
1709 1713 (void) sigprocmask(SIG_BLOCK, NULL, &new);
1710 1714 (void) sigaddset(&new, SIGHUP);
1711 1715 (void) sigaddset(&new, SIGINT);
1712 1716 (void) sigaddset(&new, SIGQUIT);
1713 1717 (void) sigaddset(&new, SIGTSTP);
1714 1718 (void) sigprocmask(SIG_SETMASK, &new, &old);
1715 1719
1716 1720 ret = sa_create_pgroup(handle, sharename);
1717 1721 if (ret == SA_OK) {
1718 1722 /*
1719 1723 * Now start the transaction for the
1720 1724 * properties that define this share. They may
1721 1725 * exist so attempt to update before create.
1722 1726 */
1723 1727 ret = sa_start_transaction(handle, sharename);
1724 1728 }
1725 1729 if (ret == SA_OK) {
1726 1730 name = sa_get_share_attr(share, "path");
1727 1731 if (name != NULL) {
1728 1732 /*
1729 1733 * There needs to be a path
1730 1734 * for a share to exist.
1731 1735 */
1732 1736 ret = sa_set_property(handle, "path",
1733 1737 name);
1734 1738 sa_free_attr_string(name);
1735 1739 } else {
1736 1740 ret = SA_NO_MEMORY;
1737 1741 }
1738 1742 }
1739 1743 if (ret == SA_OK) {
1740 1744 name = sa_get_share_attr(share, "drive-letter");
1741 1745 if (name != NULL) {
1742 1746 /* A drive letter may exist for SMB */
1743 1747 ret = sa_set_property(handle,
1744 1748 "drive-letter", name);
1745 1749 sa_free_attr_string(name);
1746 1750 }
1747 1751 }
1748 1752 if (ret == SA_OK) {
1749 1753 name = sa_get_share_attr(share, "exclude");
1750 1754 if (name != NULL) {
1751 1755 /*
1752 1756 * In special cases need to
1753 1757 * exclude proto enable.
1754 1758 */
1755 1759 ret = sa_set_property(handle,
1756 1760 "exclude", name);
1757 1761 sa_free_attr_string(name);
1758 1762 }
1759 1763 }
1760 1764 if (ret == SA_OK) {
1761 1765 /*
1762 1766 * If there are resource names, bundle them up
1763 1767 * and save appropriately.
1764 1768 */
1765 1769 ret = sa_set_resource_property(handle, share);
1766 1770 }
1767 1771
1768 1772 if (ret == SA_OK) {
↓ open down ↓ |
363 lines elided |
↑ open up ↑ |
1769 1773 description = sa_get_share_description(share);
1770 1774 if (description != NULL) {
1771 1775 ret = sa_set_property(handle,
1772 1776 "description",
1773 1777 description);
1774 1778 sa_free_share_description(description);
1775 1779 }
1776 1780 }
1777 1781 /* Make sure we cleanup the transaction */
1778 1782 if (ret == SA_OK) {
1779 - sa_handle_impl_t sahandle;
1780 - sahandle = (sa_handle_impl_t)
1781 - sa_find_group_handle(group);
1783 + sa_handle_t sahandle;
1784 + sahandle = sa_find_group_handle(group);
1782 1785 if (sahandle != NULL)
1783 1786 ret = sa_end_transaction(handle,
1784 1787 sahandle);
1785 1788 else
1786 1789 ret = SA_SYSTEM_ERR;
1787 1790 } else {
1788 1791 sa_abort_transaction(handle);
1789 1792 }
1790 1793
1791 1794 (void) sigprocmask(SIG_SETMASK, &old, NULL);
1792 1795
1793 1796 free(sharename);
1794 1797 }
1795 1798 }
1796 1799 if (ret == SA_SYSTEM_ERR) {
1797 1800 int err = scf_error();
1798 1801 if (err == SCF_ERROR_PERMISSION_DENIED)
1799 1802 ret = SA_NO_PERMISSION;
1800 1803 }
1801 1804 if (propstring != NULL)
1802 1805 free(propstring);
1803 1806 if (groupname != NULL)
1804 1807 sa_free_attr_string(groupname);
1805 1808
1806 1809 return (ret);
1807 1810 }
1808 1811
1809 1812 /*
1810 1813 * remove_resources(handle, share, shareid)
1811 1814 *
1812 1815 * If the share has resources, remove all of them and their
1813 1816 * optionsets.
1814 1817 */
1815 1818 static int
1816 1819 remove_resources(scfutilhandle_t *handle, sa_share_t share, char *shareid)
1817 1820 {
1818 1821 sa_resource_t resource;
1819 1822 sa_optionset_t opt;
1820 1823 char *proto;
1821 1824 char *id;
1822 1825 ssize_t proplen;
1823 1826 char *propstring;
1824 1827 int ret = SA_OK;
1825 1828
1826 1829 proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1827 1830 propstring = malloc(proplen);
1828 1831 if (propstring == NULL)
1829 1832 return (SA_NO_MEMORY);
1830 1833
1831 1834 for (resource = sa_get_share_resource(share, NULL);
1832 1835 resource != NULL; resource = sa_get_next_resource(resource)) {
1833 1836 id = sa_get_resource_attr(resource, "id");
1834 1837 if (id == NULL)
1835 1838 continue;
1836 1839 for (opt = sa_get_optionset(resource, NULL);
1837 1840 opt != NULL; opt = sa_get_next_optionset(resource)) {
1838 1841 proto = sa_get_optionset_attr(opt, "type");
1839 1842 if (proto != NULL) {
1840 1843 (void) snprintf(propstring, proplen,
1841 1844 "%s_%s_%s", shareid, proto, id);
1842 1845 ret = sa_delete_pgroup(handle, propstring);
1843 1846 sa_free_attr_string(proto);
1844 1847 }
1845 1848 }
1846 1849 sa_free_attr_string(id);
1847 1850 }
1848 1851 free(propstring);
1849 1852 return (ret);
1850 1853 }
1851 1854
1852 1855 /*
1853 1856 * sa_delete_share(handle, group, share)
1854 1857 *
1855 1858 * Remove the specified share from the group (and service instance).
1856 1859 */
1857 1860
1858 1861 int
1859 1862 sa_delete_share(scfutilhandle_t *handle, sa_group_t group, sa_share_t share)
1860 1863 {
1861 1864 int ret = SA_OK;
1862 1865 char *groupname = NULL;
1863 1866 char *shareid = NULL;
1864 1867 sa_optionset_t opt;
1865 1868 sa_security_t sec;
1866 1869 ssize_t proplen;
1867 1870 char *propstring;
1868 1871
1869 1872 proplen = get_scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1870 1873 propstring = malloc(proplen);
1871 1874 if (propstring == NULL)
1872 1875 ret = SA_NO_MEMORY;
1873 1876
1874 1877 if (ret == SA_OK) {
1875 1878 groupname = sa_get_group_attr(group, "name");
1876 1879 shareid = sa_get_share_attr(share, "id");
1877 1880 if (groupname == NULL || shareid == NULL) {
1878 1881 ret = SA_CONFIG_ERR;
1879 1882 goto out;
1880 1883 }
1881 1884 ret = sa_get_instance(handle, groupname);
1882 1885 if (ret == SA_OK) {
1883 1886 /* If a share has resources, remove them */
1884 1887 ret = remove_resources(handle, share, shareid);
1885 1888 /* If a share has properties, remove them */
1886 1889 ret = sa_delete_pgroup(handle, shareid);
1887 1890 for (opt = sa_get_optionset(share, NULL);
1888 1891 opt != NULL;
1889 1892 opt = sa_get_next_optionset(opt)) {
1890 1893 char *proto;
1891 1894 proto = sa_get_optionset_attr(opt, "type");
1892 1895 if (proto != NULL) {
1893 1896 (void) snprintf(propstring,
1894 1897 proplen, "%s_%s", shareid,
1895 1898 proto);
1896 1899 ret = sa_delete_pgroup(handle,
1897 1900 propstring);
1898 1901 sa_free_attr_string(proto);
1899 1902 } else {
1900 1903 ret = SA_NO_MEMORY;
1901 1904 }
1902 1905 }
1903 1906 /*
1904 1907 * If a share has security/negotiable
1905 1908 * properties, remove them.
1906 1909 */
1907 1910 for (sec = sa_get_security(share, NULL, NULL);
1908 1911 sec != NULL;
1909 1912 sec = sa_get_next_security(sec)) {
1910 1913 char *proto;
1911 1914 char *sectype;
1912 1915 proto = sa_get_security_attr(sec, "type");
1913 1916 sectype = sa_get_security_attr(sec, "sectype");
1914 1917 if (proto != NULL && sectype != NULL) {
1915 1918 (void) snprintf(propstring, proplen,
1916 1919 "%s_%s_%s", shareid, proto,
1917 1920 sectype);
1918 1921 ret = sa_delete_pgroup(handle,
1919 1922 propstring);
1920 1923 } else {
1921 1924 ret = SA_NO_MEMORY;
1922 1925 }
1923 1926 if (proto != NULL)
1924 1927 sa_free_attr_string(proto);
1925 1928 if (sectype != NULL)
1926 1929 sa_free_attr_string(sectype);
1927 1930 }
1928 1931 }
1929 1932 }
1930 1933 out:
1931 1934 if (groupname != NULL)
1932 1935 sa_free_attr_string(groupname);
1933 1936 if (shareid != NULL)
1934 1937 sa_free_attr_string(shareid);
1935 1938 if (propstring != NULL)
1936 1939 free(propstring);
1937 1940
1938 1941 return (ret);
1939 1942 }
↓ open down ↓ |
148 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX