Print this page
4095 minor cleanup up libshare
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libshare/common/libshare.c
+++ new/usr/src/lib/libshare/common/libshare.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
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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
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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2013 RackTop Systems.
24 25 */
25 26
26 27 /*
27 28 * Share control API
28 29 */
29 30 #include <stdio.h>
30 31 #include <string.h>
31 32 #include <ctype.h>
32 33 #include <sys/types.h>
33 34 #include <sys/stat.h>
34 35 #include <fcntl.h>
35 36 #include <unistd.h>
36 37 #include <libxml/parser.h>
37 38 #include <libxml/tree.h>
38 39 #include "libshare.h"
39 40 #include "libshare_impl.h"
40 41 #include <libscf.h>
41 42 #include "scfutil.h"
42 43 #include <ctype.h>
43 44 #include <libintl.h>
44 45 #include <thread.h>
45 46 #include <synch.h>
46 47
47 48 #define DFS_LOCK_FILE "/etc/dfs/fstypes"
48 49 #define SA_STRSIZE 256 /* max string size for names */
49 50
50 51 /*
51 52 * internal object type values returned by sa_get_object_type()
52 53 */
53 54 #define SA_TYPE_UNKNOWN 0
54 55 #define SA_TYPE_GROUP 1
55 56 #define SA_TYPE_SHARE 2
56 57 #define SA_TYPE_RESOURCE 3
57 58 #define SA_TYPE_OPTIONSET 4
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
58 59 #define SA_TYPE_ALTSPACE 5
59 60
60 61 /*
61 62 * internal data structures
62 63 */
63 64
64 65 extern struct sa_proto_plugin *sap_proto_list;
65 66
66 67 /* current SMF/SVC repository handle */
67 68 extern void getlegacyconfig(sa_handle_t, char *, xmlNodePtr *);
68 -extern int gettransients(sa_handle_impl_t, xmlNodePtr *);
69 +extern int gettransients(sa_handle_t, xmlNodePtr *);
69 70 extern char *sa_fstype(char *);
70 -extern int sa_is_share(void *);
71 -extern int sa_is_resource(void *);
71 +extern boolean_t sa_is_share(void *);
72 +extern boolean_t sa_is_resource(void *);
72 73 extern ssize_t scf_max_name_len; /* defined in scfutil during initialization */
73 -extern int sa_group_is_zfs(sa_group_t);
74 -extern int sa_path_is_zfs(char *);
74 +extern boolean_t sa_group_is_zfs(sa_group_t);
75 +extern boolean_t sa_path_is_zfs(char *);
75 76 extern int sa_zfs_set_sharenfs(sa_group_t, char *, int);
76 77 extern int sa_zfs_set_sharesmb(sa_group_t, char *, int);
77 78 extern void update_legacy_config(sa_handle_t);
78 79 extern int issubdir(char *, char *);
79 -extern int sa_zfs_init(sa_handle_impl_t);
80 -extern void sa_zfs_fini(sa_handle_impl_t);
80 +extern int sa_zfs_init(sa_handle_t);
81 +extern void sa_zfs_fini(sa_handle_t);
81 82 extern void sablocksigs(sigset_t *);
82 83 extern void saunblocksigs(sigset_t *);
83 84 static sa_group_t sa_get_optionset_parent(sa_optionset_t);
84 85 static char *get_node_attr(void *, char *);
85 86 extern void sa_update_sharetab_ts(sa_handle_t);
86 87
87 88 /*
88 89 * Data structures for finding/managing the document root to access
89 90 * handle mapping. The list isn't expected to grow very large so a
90 91 * simple list is acceptable. The purpose is to provide a way to start
91 92 * with a group or share and find the library handle needed for
92 93 * various operations.
93 94 */
94 95 mutex_t sa_global_lock;
95 96 struct doc2handle {
96 97 struct doc2handle *next;
97 98 xmlNodePtr root;
98 - sa_handle_impl_t handle;
99 + sa_handle_t handle;
99 100 };
100 101
101 102 mutex_t sa_dfstab_lock;
102 103
103 104 /* definitions used in a couple of property functions */
104 105 #define SA_PROP_OP_REMOVE 1
105 106 #define SA_PROP_OP_ADD 2
106 107 #define SA_PROP_OP_UPDATE 3
107 108
108 109 static struct doc2handle *sa_global_handles = NULL;
109 110
110 111 /* helper functions */
111 112
112 113 /*
113 114 * sa_errorstr(err)
114 115 *
115 116 * convert an error value to an error string
116 117 */
117 118
118 119 char *
119 120 sa_errorstr(int err)
120 121 {
121 122 static char errstr[32];
122 123 char *ret = NULL;
123 124
124 125 switch (err) {
125 126 case SA_OK:
126 127 ret = dgettext(TEXT_DOMAIN, "ok");
127 128 break;
128 129 case SA_NO_SUCH_PATH:
129 130 ret = dgettext(TEXT_DOMAIN, "path doesn't exist");
130 131 break;
131 132 case SA_NO_MEMORY:
132 133 ret = dgettext(TEXT_DOMAIN, "no memory");
133 134 break;
134 135 case SA_DUPLICATE_NAME:
135 136 ret = dgettext(TEXT_DOMAIN, "name in use");
136 137 break;
137 138 case SA_BAD_PATH:
138 139 ret = dgettext(TEXT_DOMAIN, "bad path");
139 140 break;
140 141 case SA_NO_SUCH_GROUP:
141 142 ret = dgettext(TEXT_DOMAIN, "no such group");
142 143 break;
143 144 case SA_CONFIG_ERR:
144 145 ret = dgettext(TEXT_DOMAIN, "configuration error");
145 146 break;
146 147 case SA_SYSTEM_ERR:
147 148 ret = dgettext(TEXT_DOMAIN, "system error");
148 149 break;
149 150 case SA_SYNTAX_ERR:
150 151 ret = dgettext(TEXT_DOMAIN, "syntax error");
151 152 break;
152 153 case SA_NO_PERMISSION:
153 154 ret = dgettext(TEXT_DOMAIN, "no permission");
154 155 break;
155 156 case SA_BUSY:
156 157 ret = dgettext(TEXT_DOMAIN, "busy");
157 158 break;
158 159 case SA_NO_SUCH_PROP:
159 160 ret = dgettext(TEXT_DOMAIN, "no such property");
160 161 break;
161 162 case SA_INVALID_NAME:
162 163 ret = dgettext(TEXT_DOMAIN, "invalid name");
163 164 break;
164 165 case SA_INVALID_PROTOCOL:
165 166 ret = dgettext(TEXT_DOMAIN, "invalid protocol");
166 167 break;
167 168 case SA_NOT_ALLOWED:
168 169 ret = dgettext(TEXT_DOMAIN, "operation not allowed");
169 170 break;
170 171 case SA_BAD_VALUE:
171 172 ret = dgettext(TEXT_DOMAIN, "bad property value");
172 173 break;
173 174 case SA_INVALID_SECURITY:
174 175 ret = dgettext(TEXT_DOMAIN, "invalid security type");
175 176 break;
176 177 case SA_NO_SUCH_SECURITY:
177 178 ret = dgettext(TEXT_DOMAIN, "security type not found");
178 179 break;
179 180 case SA_VALUE_CONFLICT:
180 181 ret = dgettext(TEXT_DOMAIN, "property value conflict");
181 182 break;
182 183 case SA_NOT_IMPLEMENTED:
183 184 ret = dgettext(TEXT_DOMAIN, "not implemented");
184 185 break;
185 186 case SA_INVALID_PATH:
186 187 ret = dgettext(TEXT_DOMAIN, "invalid path");
187 188 break;
188 189 case SA_NOT_SUPPORTED:
189 190 ret = dgettext(TEXT_DOMAIN, "operation not supported");
190 191 break;
191 192 case SA_PROP_SHARE_ONLY:
192 193 ret = dgettext(TEXT_DOMAIN, "property not valid for group");
193 194 break;
194 195 case SA_NOT_SHARED:
195 196 ret = dgettext(TEXT_DOMAIN, "not shared");
196 197 break;
197 198 case SA_NO_SUCH_RESOURCE:
198 199 ret = dgettext(TEXT_DOMAIN, "no such resource");
199 200 break;
200 201 case SA_RESOURCE_REQUIRED:
201 202 ret = dgettext(TEXT_DOMAIN, "resource name required");
202 203 break;
203 204 case SA_MULTIPLE_ERROR:
204 205 ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols");
205 206 break;
206 207 case SA_PATH_IS_SUBDIR:
207 208 ret = dgettext(TEXT_DOMAIN, "path is a subpath of share");
208 209 break;
209 210 case SA_PATH_IS_PARENTDIR:
210 211 ret = dgettext(TEXT_DOMAIN, "path is parent of a share");
211 212 break;
212 213 case SA_NO_SECTION:
213 214 ret = dgettext(TEXT_DOMAIN, "protocol requires a section");
214 215 break;
215 216 case SA_NO_PROPERTIES:
216 217 ret = dgettext(TEXT_DOMAIN, "properties not found");
217 218 break;
218 219 case SA_NO_SUCH_SECTION:
219 220 ret = dgettext(TEXT_DOMAIN, "section not found");
220 221 break;
221 222 case SA_PASSWORD_ENC:
222 223 ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted");
223 224 break;
224 225 case SA_SHARE_EXISTS:
225 226 ret = dgettext(TEXT_DOMAIN, "path or file is already shared");
226 227 break;
227 228 default:
228 229 (void) snprintf(errstr, sizeof (errstr),
229 230 dgettext(TEXT_DOMAIN, "unknown %d"), err);
230 231 ret = errstr;
231 232 }
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
232 233 return (ret);
233 234 }
234 235
235 236 /*
236 237 * Document root to active handle mapping functions. These are only
237 238 * used internally. A mutex is used to prevent access while the list
238 239 * is changing. In general, the list will be relatively short - one
239 240 * item per thread that has called sa_init().
240 241 */
241 242
242 -sa_handle_impl_t
243 +sa_handle_t
243 244 get_handle_for_root(xmlNodePtr root)
244 245 {
245 246 struct doc2handle *item;
246 247
247 248 (void) mutex_lock(&sa_global_lock);
248 249 for (item = sa_global_handles; item != NULL; item = item->next) {
249 250 if (item->root == root)
250 251 break;
251 252 }
252 253 (void) mutex_unlock(&sa_global_lock);
253 254 if (item != NULL)
254 255 return (item->handle);
255 256 return (NULL);
256 257 }
257 258
258 259 static int
259 -add_handle_for_root(xmlNodePtr root, sa_handle_impl_t handle)
260 +add_handle_for_root(xmlNodePtr root, sa_handle_t handle)
260 261 {
261 262 struct doc2handle *item;
262 263 int ret = SA_NO_MEMORY;
263 264
264 265 item = (struct doc2handle *)calloc(sizeof (struct doc2handle), 1);
265 266 if (item != NULL) {
266 267 item->root = root;
267 268 item->handle = handle;
268 269 (void) mutex_lock(&sa_global_lock);
269 270 item->next = sa_global_handles;
270 271 sa_global_handles = item;
271 272 (void) mutex_unlock(&sa_global_lock);
272 273 ret = SA_OK;
273 274 }
274 275 return (ret);
275 276 }
276 277
277 278 /*
278 279 * remove_handle_for_root(root)
279 280 *
280 281 * Walks the list of handles and removes the one for this "root" from
281 282 * the list. It is up to the caller to free the data.
282 283 */
283 284
284 285 static void
285 286 remove_handle_for_root(xmlNodePtr root)
286 287 {
287 288 struct doc2handle *item, *prev;
288 289
289 290 (void) mutex_lock(&sa_global_lock);
290 291 for (prev = NULL, item = sa_global_handles; item != NULL;
291 292 item = item->next) {
292 293 if (item->root == root) {
293 294 /* first in the list */
294 295 if (prev == NULL)
295 296 sa_global_handles = sa_global_handles->next;
296 297 else
297 298 prev->next = item->next;
298 299 /* Item is out of the list so free the list structure */
299 300 free(item);
300 301 break;
301 302 }
302 303 prev = item;
303 304 }
304 305 (void) mutex_unlock(&sa_global_lock);
305 306 }
306 307
307 308 /*
308 309 * sa_find_group_handle(sa_group_t group)
309 310 *
310 311 * Find the sa_handle_t for the configuration associated with this
311 312 * group.
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
312 313 */
313 314 sa_handle_t
314 315 sa_find_group_handle(sa_group_t group)
315 316 {
316 317 xmlNodePtr node = (xmlNodePtr)group;
317 318 sa_handle_t handle;
318 319
319 320 while (node != NULL) {
320 321 if (strcmp((char *)(node->name), "sharecfg") == 0) {
321 322 /* have the root so get the handle */
322 - handle = (sa_handle_t)get_handle_for_root(node);
323 + handle = get_handle_for_root(node);
323 324 return (handle);
324 325 }
325 326 node = node->parent;
326 327 }
327 328 return (NULL);
328 329 }
329 330
330 331 /*
331 332 * set_legacy_timestamp(root, path, timevalue)
332 333 *
333 334 * add the current timestamp value to the configuration for use in
334 335 * determining when to update the legacy files. For SMF, this
335 336 * property is kept in default/operation/legacy_timestamp
336 337 */
337 338
338 339 static void
339 340 set_legacy_timestamp(xmlNodePtr root, char *path, uint64_t tval)
340 341 {
341 342 xmlNodePtr node;
342 343 xmlChar *lpath = NULL;
343 - sa_handle_impl_t handle;
344 + sa_handle_t handle;
344 345
345 346 /* Have to have a handle or else we weren't initialized. */
346 347 handle = get_handle_for_root(root);
347 348 if (handle == NULL)
348 349 return;
349 350
350 351 for (node = root->xmlChildrenNode; node != NULL;
351 352 node = node->next) {
352 353 if (xmlStrcmp(node->name, (xmlChar *)"legacy") == 0) {
353 354 /* a possible legacy node for this path */
354 355 lpath = xmlGetProp(node, (xmlChar *)"path");
355 356 if (lpath != NULL &&
356 357 xmlStrcmp(lpath, (xmlChar *)path) == 0) {
357 358 xmlFree(lpath);
358 359 break;
359 360 }
360 361 if (lpath != NULL)
361 362 xmlFree(lpath);
362 363 }
363 364 }
364 365 if (node == NULL) {
365 366 /* need to create the first legacy timestamp node */
366 367 node = xmlNewChild(root, NULL, (xmlChar *)"legacy", NULL);
367 368 }
368 369 if (node != NULL) {
369 370 char tstring[32];
370 371 int ret;
371 372
372 373 (void) snprintf(tstring, sizeof (tstring), "%lld", tval);
373 374 (void) xmlSetProp(node, (xmlChar *)"timestamp",
374 375 (xmlChar *)tstring);
375 376 (void) xmlSetProp(node, (xmlChar *)"path", (xmlChar *)path);
376 377 /* now commit to SMF */
377 378 ret = sa_get_instance(handle->scfhandle, "default");
378 379 if (ret == SA_OK) {
379 380 ret = sa_start_transaction(handle->scfhandle,
380 381 "operation");
381 382 if (ret == SA_OK) {
382 383 ret = sa_set_property(handle->scfhandle,
383 384 "legacy-timestamp", tstring);
384 385 if (ret == SA_OK) {
385 386 (void) sa_end_transaction(
386 387 handle->scfhandle, handle);
387 388 } else {
388 389 sa_abort_transaction(handle->scfhandle);
389 390 }
390 391 }
391 392 }
392 393 }
393 394 }
394 395
395 396 /*
396 397 * is_shared(share)
397 398 *
398 399 * determine if the specified share is currently shared or not.
399 400 */
400 401 static int
401 402 is_shared(sa_share_t share)
402 403 {
403 404 char *shared;
404 405 int result = 0; /* assume not */
405 406
406 407 shared = sa_get_share_attr(share, "shared");
407 408 if (shared != NULL) {
408 409 if (strcmp(shared, "true") == 0)
409 410 result = 1;
410 411 sa_free_attr_string(shared);
411 412 }
412 413 return (result);
413 414 }
414 415
415 416 /*
416 417 * excluded_protocol(share, proto)
417 418 *
418 419 * Returns B_TRUE if the specified protocol appears in the "exclude"
419 420 * property. This is used to prevent sharing special case shares
420 421 * (e.g. subdirs when SMB wants a subdir and NFS doesn't. B_FALSE is
421 422 * returned if the protocol isn't in the list.
422 423 */
423 424 static boolean_t
424 425 excluded_protocol(sa_share_t share, char *proto)
425 426 {
426 427 char *protolist;
427 428 char *str;
428 429 char *token;
429 430
430 431 protolist = sa_get_share_attr(share, "exclude");
431 432 if (protolist != NULL) {
432 433 str = protolist;
433 434 while ((token = strtok(str, ",")) != NULL) {
434 435 if (strcmp(token, proto) == 0) {
435 436 sa_free_attr_string(protolist);
436 437 return (B_TRUE);
437 438 }
438 439 str = NULL;
439 440 }
440 441 sa_free_attr_string(protolist);
441 442 }
442 443 return (B_FALSE);
443 444 }
444 445
445 446 /*
446 447 * checksubdirgroup(group, newpath, strictness)
447 448 *
448 449 * check all the specified newpath against all the paths in the
449 450 * group. This is a helper function for checksubdir to make it easier
450 451 * to also check ZFS subgroups.
451 452 * The strictness values mean:
452 453 * SA_CHECK_NORMAL == only check newpath against shares that are active
453 454 * SA_CHECK_STRICT == check newpath against both active shares and those
454 455 * stored in the repository
455 456 */
456 457 static int
457 458 checksubdirgroup(sa_group_t group, char *newpath, int strictness)
458 459 {
459 460 sa_share_t share;
460 461 char *path;
461 462 int issub = SA_OK;
462 463 int subdir;
463 464 int parent;
464 465
465 466 if (newpath == NULL)
466 467 return (SA_INVALID_PATH);
467 468
468 469 for (share = sa_get_share(group, NULL); share != NULL;
469 470 share = sa_get_next_share(share)) {
470 471 /*
471 472 * The original behavior of share never checked
472 473 * against the permanent configuration
473 474 * (/etc/dfs/dfstab). PIT has a number of cases where
474 475 * it depends on this older behavior even though it
475 476 * could be considered incorrect. We may tighten this
476 477 * up in the future.
477 478 */
478 479 if (strictness == SA_CHECK_NORMAL && !is_shared(share))
479 480 continue;
480 481
481 482 path = sa_get_share_attr(share, "path");
482 483 /*
483 484 * If path is NULL, then a share is in the process of
484 485 * construction or someone has modified the property
485 486 * group inappropriately. It should be
486 487 * ignored. issubdir() comes from the original share
487 488 * implementation and does the difficult part of
488 489 * checking subdirectories.
489 490 */
490 491 if (path == NULL)
491 492 continue;
492 493
493 494 if (strcmp(path, newpath) == 0) {
494 495 issub = SA_INVALID_PATH;
495 496 } else {
496 497 subdir = issubdir(newpath, path);
497 498 parent = issubdir(path, newpath);
498 499 if (subdir || parent) {
499 500 sa_free_attr_string(path);
500 501 path = NULL;
501 502 return (subdir ?
502 503 SA_PATH_IS_SUBDIR : SA_PATH_IS_PARENTDIR);
503 504 }
504 505 }
505 506 sa_free_attr_string(path);
506 507 path = NULL;
507 508 }
508 509 return (issub);
509 510 }
510 511
511 512 /*
512 513 * checksubdir(newpath, strictness)
513 514 *
514 515 * checksubdir determines if the specified path (newpath) is a
515 516 * subdirectory of another share. It calls checksubdirgroup() to do
516 517 * the complicated work. The strictness parameter determines how
517 518 * strict a check to make against the path. The strictness values
518 519 * mean: SA_CHECK_NORMAL == only check newpath against shares that are
519 520 * active SA_CHECK_STRICT == check newpath against both active shares
520 521 * and those * stored in the repository
521 522 */
522 523 static int
523 524 checksubdir(sa_handle_t handle, char *newpath, int strictness)
524 525 {
525 526 sa_group_t group;
526 527 int issub = SA_OK;
527 528 char *path = NULL;
528 529
529 530 for (group = sa_get_group(handle, NULL);
530 531 group != NULL && issub == SA_OK;
531 532 group = sa_get_next_group(group)) {
532 533 if (sa_group_is_zfs(group)) {
533 534 sa_group_t subgroup;
534 535 for (subgroup = sa_get_sub_group(group);
535 536 subgroup != NULL && issub == SA_OK;
536 537 subgroup = sa_get_next_group(subgroup))
537 538 issub = checksubdirgroup(subgroup, newpath,
538 539 strictness);
539 540 } else {
540 541 issub = checksubdirgroup(group, newpath, strictness);
541 542 }
542 543 }
543 544 if (path != NULL)
544 545 sa_free_attr_string(path);
545 546 return (issub);
546 547 }
547 548
548 549 /*
549 550 * validpath(path, strictness)
550 551 * determine if the provided path is valid for a share. It shouldn't
551 552 * be a sub-dir of an already shared path or the parent directory of a
552 553 * share path.
553 554 */
554 555 static int
555 556 validpath(sa_handle_t handle, char *path, int strictness)
556 557 {
557 558 int error = SA_OK;
558 559 struct stat st;
559 560 sa_share_t share;
560 561 char *fstype;
561 562
562 563 if (*path != '/')
563 564 return (SA_BAD_PATH);
564 565
565 566 if (stat(path, &st) < 0) {
566 567 error = SA_NO_SUCH_PATH;
567 568 } else {
568 569 share = sa_find_share(handle, path);
569 570 if (share != NULL)
570 571 error = SA_DUPLICATE_NAME;
571 572
572 573 if (error == SA_OK) {
573 574 /*
574 575 * check for special case with file system
575 576 * that might have restrictions. For now, ZFS
576 577 * is the only case since it has its own idea
577 578 * of how to configure shares. We do this
578 579 * before subdir checking since things like
579 580 * ZFS will do that for us. This should also
580 581 * be done via plugin interface.
581 582 */
582 583 fstype = sa_fstype(path);
583 584 if (fstype != NULL && strcmp(fstype, "zfs") == 0) {
584 585 if (sa_zfs_is_shared(handle, path))
585 586 error = SA_INVALID_NAME;
586 587 }
587 588 if (fstype != NULL)
588 589 sa_free_fstype(fstype);
589 590 }
590 591 if (error == SA_OK)
591 592 error = checksubdir(handle, path, strictness);
592 593 }
↓ open down ↓ |
239 lines elided |
↑ open up ↑ |
593 594 return (error);
594 595 }
595 596
596 597 /*
597 598 * check to see if group/share is persistent.
598 599 *
599 600 * "group" can be either an sa_group_t or an sa_share_t. (void *)
600 601 * works since both thse types are also void *.
601 602 * If the share is a ZFS share, mark it as persistent.
602 603 */
603 -int
604 +boolean_t
604 605 sa_is_persistent(void *group)
605 606 {
606 607 char *type;
607 - int persist = 1;
608 + boolean_t persist = B_TRUE;
608 609 sa_group_t grp;
609 610
610 611 type = sa_get_group_attr((sa_group_t)group, "type");
611 612 if (type != NULL) {
612 613 if (strcmp(type, "transient") == 0)
613 - persist = 0;
614 + persist = B_FALSE;
614 615 sa_free_attr_string(type);
615 616 }
616 617
617 618 grp = (sa_is_share(group)) ? sa_get_parent_group(group) : group;
618 619 if (sa_group_is_zfs(grp))
619 - persist = 1;
620 + persist = B_TRUE;
620 621
621 622 return (persist);
622 623 }
623 624
624 625 /*
625 626 * sa_valid_group_name(name)
626 627 *
627 628 * check that the "name" contains only valid characters and otherwise
628 629 * fits the required naming conventions. Valid names must start with
629 630 * an alphabetic and the remainder may consist of only alphanumeric
630 631 * plus the '-' and '_' characters. This name limitation comes from
631 632 * inherent limitations in SMF.
632 633 */
633 634
634 635 int
635 636 sa_valid_group_name(char *name)
636 637 {
637 638 int ret = 1;
638 639 ssize_t len;
639 640
640 641 if (name != NULL && isalpha(*name)) {
641 642 char c;
642 643 len = strlen(name);
643 644 if (len < (scf_max_name_len - sizeof ("group:"))) {
644 645 for (c = *name++; c != '\0' && ret != 0; c = *name++) {
645 646 if (!isalnum(c) && c != '-' && c != '_')
646 647 ret = 0;
647 648 }
648 649 } else {
649 650 ret = 0;
650 651 }
651 652 } else {
652 653 ret = 0;
653 654 }
654 655 return (ret);
655 656 }
656 657
657 658
658 659 /*
659 660 * is_zfs_group(group)
660 661 * Determine if the specified group is a ZFS sharenfs group
661 662 */
662 663 static int
663 664 is_zfs_group(sa_group_t group)
664 665 {
665 666 int ret = 0;
666 667 xmlNodePtr parent;
667 668 xmlChar *zfs;
668 669
669 670 if (strcmp((char *)((xmlNodePtr)group)->name, "share") == 0)
670 671 parent = (xmlNodePtr)sa_get_parent_group(group);
671 672 else
672 673 parent = (xmlNodePtr)group;
673 674 zfs = xmlGetProp(parent, (xmlChar *)"zfs");
674 675 if (zfs != NULL) {
675 676 xmlFree(zfs);
676 677 ret = 1;
677 678 }
678 679 return (ret);
679 680 }
680 681
681 682 /*
682 683 * sa_get_object_type(object)
683 684 *
684 685 * This function returns a numeric value representing the object
685 686 * type. This allows using simpler checks when doing type specific
686 687 * operations.
687 688 */
688 689
689 690 static int
690 691 sa_get_object_type(void *object)
691 692 {
692 693 xmlNodePtr node = (xmlNodePtr)object;
693 694 int type;
694 695
695 696 if (xmlStrcmp(node->name, (xmlChar *)"group") == 0)
696 697 type = SA_TYPE_GROUP;
697 698 else if (xmlStrcmp(node->name, (xmlChar *)"share") == 0)
698 699 type = SA_TYPE_SHARE;
699 700 else if (xmlStrcmp(node->name, (xmlChar *)"resource") == 0)
700 701 type = SA_TYPE_RESOURCE;
701 702 else if (xmlStrcmp(node->name, (xmlChar *)"optionset") == 0)
702 703 type = SA_TYPE_OPTIONSET;
703 704 else if (xmlStrcmp(node->name, (xmlChar *)"security") == 0)
704 705 type = SA_TYPE_ALTSPACE;
705 706 else
706 707 assert(0);
707 708 return (type);
708 709 }
709 710
710 711 /*
711 712 * sa_optionset_name(optionset, oname, len, id)
712 713 * return the SMF name for the optionset. If id is not NULL, it
713 714 * will have the GUID value for a share and should be used
714 715 * instead of the keyword "optionset" which is used for
715 716 * groups. If the optionset doesn't have a protocol type
716 717 * associated with it, "default" is used. This shouldn't happen
717 718 * at this point but may be desirable in the future if there are
718 719 * protocol independent properties added. The name is returned in
719 720 * oname.
720 721 */
721 722
722 723 static int
723 724 sa_optionset_name(sa_optionset_t optionset, char *oname, size_t len, char *id)
724 725 {
725 726 char *proto;
726 727 void *parent;
727 728 int ptype;
728 729
729 730 if (id == NULL)
730 731 id = "optionset";
731 732
732 733 parent = sa_get_optionset_parent(optionset);
733 734 if (parent != NULL) {
734 735 ptype = sa_get_object_type(parent);
735 736 proto = sa_get_optionset_attr(optionset, "type");
736 737 if (ptype != SA_TYPE_RESOURCE) {
737 738 len = snprintf(oname, len, "%s_%s", id,
738 739 proto ? proto : "default");
739 740 } else {
740 741 char *index;
741 742 index = get_node_attr((void *)parent, "id");
742 743 if (index != NULL) {
743 744 len = snprintf(oname, len, "%s_%s_%s", id,
744 745 proto ? proto : "default", index);
745 746 sa_free_attr_string(index);
746 747 } else {
747 748 len = 0;
748 749 }
749 750 }
750 751
751 752 if (proto != NULL)
752 753 sa_free_attr_string(proto);
753 754 } else {
754 755 len = 0;
755 756 }
756 757 return (len);
757 758 }
758 759
759 760 /*
760 761 * sa_security_name(optionset, oname, len, id)
761 762 *
762 763 * return the SMF name for the security. If id is not NULL, it will
763 764 * have the GUID value for a share and should be used instead of the
764 765 * keyword "optionset" which is used for groups. If the optionset
765 766 * doesn't have a protocol type associated with it, "default" is
766 767 * used. This shouldn't happen at this point but may be desirable in
767 768 * the future if there are protocol independent properties added. The
768 769 * name is returned in oname. The security type is also encoded into
769 770 * the name. In the future, this wil *be handled a bit differently.
770 771 */
771 772
772 773 static int
773 774 sa_security_name(sa_security_t security, char *oname, size_t len, char *id)
774 775 {
775 776 char *proto;
776 777 char *sectype;
777 778
778 779 if (id == NULL)
779 780 id = "optionset";
780 781
781 782 proto = sa_get_security_attr(security, "type");
782 783 sectype = sa_get_security_attr(security, "sectype");
783 784 len = snprintf(oname, len, "%s_%s_%s", id, proto ? proto : "default",
784 785 sectype ? sectype : "default");
785 786 if (proto != NULL)
786 787 sa_free_attr_string(proto);
787 788 if (sectype != NULL)
788 789 sa_free_attr_string(sectype);
789 790 return (len);
790 791 }
791 792
792 793 /*
793 794 * verifydefgroupopts(handle)
794 795 *
795 796 * Make sure a "default" group exists and has default protocols enabled.
796 797 */
797 798 static void
798 799 verifydefgroupopts(sa_handle_t handle)
799 800 {
800 801 sa_group_t defgrp;
801 802 sa_optionset_t opt;
802 803
803 804 defgrp = sa_get_group(handle, "default");
804 805 if (defgrp != NULL) {
805 806 opt = sa_get_optionset(defgrp, NULL);
806 807 /*
807 808 * NFS is the default for default group
808 809 */
809 810 if (opt == NULL)
810 811 opt = sa_create_optionset(defgrp, "nfs");
811 812 }
812 813 }
813 814
814 815 /*
815 816 * sa_init(init_service)
816 817 * Initialize the API
817 818 * find all the shared objects
818 819 * init the tables with all objects
819 820 * read in the current configuration
820 821 */
821 822
822 823 #define GETPROP(prop) scf_simple_prop_next_astring(prop)
823 824 #define CHECKTSTAMP(st, tval) stat(SA_LEGACY_DFSTAB, &st) >= 0 && \
824 825 tval != TSTAMP(st.st_ctim)
825 826
↓ open down ↓ |
196 lines elided |
↑ open up ↑ |
826 827 sa_handle_t
827 828 sa_init(int init_service)
828 829 {
829 830 struct stat st;
830 831 int legacy = 0;
831 832 uint64_t tval = 0;
832 833 int lockfd;
833 834 sigset_t old;
834 835 int updatelegacy = B_FALSE;
835 836 scf_simple_prop_t *prop;
836 - sa_handle_impl_t handle;
837 + sa_handle_t handle;
837 838 int err;
838 839
839 - handle = calloc(sizeof (struct sa_handle_impl), 1);
840 + handle = calloc(sizeof (struct sa_handle), 1);
840 841
841 842 if (handle != NULL) {
842 843 /*
843 844 * Get protocol specific structures, but only if this
844 845 * is the only handle.
845 846 */
846 847 (void) mutex_lock(&sa_global_lock);
847 848 if (sa_global_handles == NULL)
848 849 (void) proto_plugin_init();
849 850 (void) mutex_unlock(&sa_global_lock);
850 851 if (init_service & SA_INIT_SHARE_API) {
851 852 /*
852 853 * initialize access into libzfs. We use this
853 854 * when collecting info about ZFS datasets and
854 855 * shares.
855 856 */
856 857 if (sa_zfs_init(handle) == B_FALSE) {
857 858 free(handle);
858 859 (void) mutex_lock(&sa_global_lock);
859 860 (void) proto_plugin_fini();
860 861 (void) mutex_unlock(&sa_global_lock);
861 862 return (NULL);
862 863 }
863 864 /*
864 865 * since we want to use SMF, initialize an svc handle
865 866 * and find out what is there.
866 867 */
867 868 handle->scfhandle = sa_scf_init(handle);
868 869 if (handle->scfhandle != NULL) {
869 870 /*
870 871 * Need to lock the extraction of the
871 872 * configuration if the dfstab file has
872 873 * changed. Lock everything now and release if
873 874 * not needed. Use a file that isn't being
874 875 * manipulated by other parts of the system in
875 876 * order to not interfere with locking. Using
876 877 * dfstab doesn't work.
877 878 */
878 879 sablocksigs(&old);
879 880 lockfd = open(DFS_LOCK_FILE, O_RDWR);
880 881 if (lockfd >= 0) {
881 882 extern int errno;
882 883 errno = 0;
883 884 (void) lockf(lockfd, F_LOCK, 0);
884 885 (void) mutex_lock(&sa_dfstab_lock);
885 886 /*
886 887 * Check whether we are going to need
887 888 * to merge any dfstab changes. This
888 889 * is done by comparing the value of
889 890 * legacy-timestamp with the current
890 891 * st_ctim of the file. If they are
891 892 * different, an update is needed and
892 893 * the file must remain locked until
893 894 * the merge is done in order to
894 895 * prevent multiple startups from
895 896 * changing the SMF repository at the
896 897 * same time. The first to get the
897 898 * lock will make any changes before
898 899 * the others can read the repository.
899 900 */
900 901 prop = scf_simple_prop_get
901 902 (handle->scfhandle->handle,
902 903 (const char *)SA_SVC_FMRI_BASE
903 904 ":default", "operation",
904 905 "legacy-timestamp");
905 906 if (prop != NULL) {
906 907 char *i64;
907 908 i64 = GETPROP(prop);
908 909 if (i64 != NULL)
909 910 tval = strtoull(i64,
910 911 NULL, 0);
911 912 if (CHECKTSTAMP(st, tval))
912 913 updatelegacy = B_TRUE;
913 914 scf_simple_prop_free(prop);
914 915 } else {
915 916 /*
916 917 * We haven't set the
917 918 * timestamp before so do it.
918 919 */
919 920 updatelegacy = B_TRUE;
920 921 }
921 922 if (updatelegacy == B_FALSE) {
922 923 (void) mutex_unlock(
923 924 &sa_dfstab_lock);
924 925 (void) lockf(lockfd, F_ULOCK,
925 926 0);
926 927 (void) close(lockfd);
927 928 }
928 929
929 930 }
930 931 /*
931 932 * It is essential that the document tree and
932 933 * the internal list of roots to handles be
933 934 * setup before anything that might try to
934 935 * create a new object is called. The document
935 936 * tree is the combination of handle->doc and
936 937 * handle->tree. This allows searches,
937 938 * etc. when all you have is an object in the
938 939 * tree.
939 940 */
940 941 handle->doc = xmlNewDoc((xmlChar *)"1.0");
941 942 handle->tree = xmlNewNode(NULL,
942 943 (xmlChar *)"sharecfg");
943 944 if (handle->doc != NULL &&
944 945 handle->tree != NULL) {
945 946 (void) xmlDocSetRootElement(handle->doc,
946 947 handle->tree);
947 948 err = add_handle_for_root(handle->tree,
948 949 handle);
949 950 if (err == SA_OK)
950 951 err = sa_get_config(
951 952 handle->scfhandle,
952 953 handle->tree, handle);
953 954 } else {
954 955 if (handle->doc != NULL)
955 956 xmlFreeDoc(handle->doc);
956 957 if (handle->tree != NULL)
957 958 xmlFreeNode(handle->tree);
958 959 err = SA_NO_MEMORY;
959 960 }
960 961
961 962 saunblocksigs(&old);
962 963
963 964 if (err != SA_OK) {
964 965 /*
965 966 * If we couldn't add the tree handle
966 967 * to the list, then things are going
967 968 * to fail badly. Might as well undo
968 969 * everything now and fail the
969 970 * sa_init().
970 971 */
971 972 sa_fini(handle);
972 973 if (updatelegacy == B_TRUE) {
973 974 (void) mutex_unlock(
974 975 &sa_dfstab_lock);
975 976 (void) lockf(lockfd,
976 977 F_ULOCK, 0);
977 978 (void) close(lockfd);
978 979 }
979 980 return (NULL);
980 981 }
981 982
↓ open down ↓ |
132 lines elided |
↑ open up ↑ |
982 983 if (tval == 0) {
983 984 /*
984 985 * first time so make sure
985 986 * default is setup
986 987 */
987 988 verifydefgroupopts(handle);
988 989 }
989 990
990 991 if (updatelegacy == B_TRUE) {
991 992 sablocksigs(&old);
992 - getlegacyconfig((sa_handle_t)handle,
993 + getlegacyconfig(handle,
993 994 SA_LEGACY_DFSTAB, &handle->tree);
994 995 if (stat(SA_LEGACY_DFSTAB, &st) >= 0)
995 996 set_legacy_timestamp(
996 997 handle->tree,
997 998 SA_LEGACY_DFSTAB,
998 999 TSTAMP(st.st_ctim));
999 1000 saunblocksigs(&old);
1000 1001 /*
1001 1002 * Safe to unlock now to allow
1002 1003 * others to run
1003 1004 */
1004 1005 (void) mutex_unlock(&sa_dfstab_lock);
1005 1006 (void) lockf(lockfd, F_ULOCK, 0);
1006 1007 (void) close(lockfd);
1007 1008 }
1008 1009 /* Get sharetab timestamp */
1009 - sa_update_sharetab_ts((sa_handle_t)handle);
1010 + sa_update_sharetab_ts(handle);
1010 1011
1011 1012 /* Get lastupdate (transaction) timestamp */
1012 1013 prop = scf_simple_prop_get(
1013 1014 handle->scfhandle->handle,
1014 1015 (const char *)SA_SVC_FMRI_BASE ":default",
1015 1016 "state", "lastupdate");
1016 1017 if (prop != NULL) {
1017 1018 char *str;
1018 1019 str =
1019 1020 scf_simple_prop_next_astring(prop);
1020 1021 if (str != NULL)
1021 1022 handle->tstrans =
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1022 1023 strtoull(str, NULL, 0);
1023 1024 else
1024 1025 handle->tstrans = 0;
1025 1026 scf_simple_prop_free(prop);
1026 1027 }
1027 1028 legacy |= sa_get_zfs_shares(handle, "zfs");
1028 1029 legacy |= gettransients(handle, &handle->tree);
1029 1030 }
1030 1031 }
1031 1032 }
1032 - return ((sa_handle_t)handle);
1033 + return (handle);
1033 1034 }
1034 1035
1035 1036 /*
1036 1037 * sa_fini(handle)
1037 1038 * Uninitialize the API structures including the configuration
1038 1039 * data structures and ZFS related data.
1039 1040 */
1040 1041
1041 1042 void
1042 1043 sa_fini(sa_handle_t handle)
1043 1044 {
1044 - sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle;
1045 -
1046 - if (impl_handle != NULL) {
1045 + if (handle != NULL) {
1047 1046 /*
1048 1047 * Free the config trees and any other data structures
1049 1048 * used in the handle.
1050 1049 */
1051 - if (impl_handle->doc != NULL)
1052 - xmlFreeDoc(impl_handle->doc);
1050 + if (handle->doc != NULL)
1051 + xmlFreeDoc(handle->doc);
1053 1052
1054 1053 /* Remove and free the entry in the global list. */
1055 - remove_handle_for_root(impl_handle->tree);
1054 + remove_handle_for_root(handle->tree);
1056 1055
1057 1056 /*
1058 1057 * If this was the last handle to release, unload the
1059 1058 * plugins that were loaded. Use a mutex in case
1060 1059 * another thread is reinitializing.
1061 1060 */
1062 1061 (void) mutex_lock(&sa_global_lock);
1063 1062 if (sa_global_handles == NULL)
1064 1063 (void) proto_plugin_fini();
1065 1064 (void) mutex_unlock(&sa_global_lock);
1066 1065
1067 - sa_scf_fini(impl_handle->scfhandle);
1068 - sa_zfs_fini(impl_handle);
1066 + sa_scf_fini(handle->scfhandle);
1067 + sa_zfs_fini(handle);
1069 1068
1070 1069 /* Make sure we free the handle */
1071 - free(impl_handle);
1070 + free(handle);
1072 1071
1073 1072 }
1074 1073 }
1075 1074
1076 1075 /*
1077 1076 * sa_get_protocols(char **protocol)
1078 1077 * Get array of protocols that are supported
1079 1078 * Returns pointer to an allocated and NULL terminated
1080 1079 * array of strings. Caller must free.
1081 1080 * This really should be determined dynamically.
1082 1081 * If there aren't any defined, return -1.
1083 1082 * Use free() to return memory.
1084 1083 */
1085 1084
1086 1085 int
1087 1086 sa_get_protocols(char ***protocols)
1088 1087 {
1089 1088 int numproto = -1;
1090 1089
1091 1090 if (protocols != NULL) {
1092 1091 struct sa_proto_plugin *plug;
1093 1092 for (numproto = 0, plug = sap_proto_list; plug != NULL;
1094 1093 plug = plug->plugin_next) {
1095 1094 numproto++;
1096 1095 }
1097 1096
1098 1097 *protocols = calloc(numproto + 1, sizeof (char *));
1099 1098 if (*protocols != NULL) {
1100 1099 int ret = 0;
1101 1100 for (plug = sap_proto_list; plug != NULL;
1102 1101 plug = plug->plugin_next) {
1103 1102 /* faking for now */
1104 1103 (*protocols)[ret++] =
1105 1104 plug->plugin_ops->sa_protocol;
1106 1105 }
1107 1106 } else {
1108 1107 numproto = -1;
1109 1108 }
1110 1109 }
1111 1110 return (numproto);
1112 1111 }
1113 1112
1114 1113 /*
1115 1114 * find_group_by_name(node, group)
1116 1115 *
1117 1116 * search the XML document subtree specified by node to find the group
1118 1117 * specified by group. Searching subtree allows subgroups to be
1119 1118 * searched for.
1120 1119 */
1121 1120
1122 1121 static xmlNodePtr
1123 1122 find_group_by_name(xmlNodePtr node, xmlChar *group)
1124 1123 {
1125 1124 xmlChar *name = NULL;
1126 1125
1127 1126 for (node = node->xmlChildrenNode; node != NULL;
1128 1127 node = node->next) {
1129 1128 if (xmlStrcmp(node->name, (xmlChar *)"group") == 0) {
1130 1129 /* if no groupname, return the first found */
1131 1130 if (group == NULL)
1132 1131 break;
1133 1132 name = xmlGetProp(node, (xmlChar *)"name");
1134 1133 if (name != NULL && xmlStrcmp(name, group) == 0)
1135 1134 break;
1136 1135 if (name != NULL) {
1137 1136 xmlFree(name);
1138 1137 name = NULL;
1139 1138 }
1140 1139 }
1141 1140 }
1142 1141 if (name != NULL)
1143 1142 xmlFree(name);
1144 1143 return (node);
1145 1144 }
1146 1145
1147 1146 /*
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
1148 1147 * sa_get_group(groupname)
1149 1148 * Return the "group" specified. If groupname is NULL,
1150 1149 * return the first group of the list of groups.
1151 1150 */
1152 1151 sa_group_t
1153 1152 sa_get_group(sa_handle_t handle, char *groupname)
1154 1153 {
1155 1154 xmlNodePtr node = NULL;
1156 1155 char *subgroup = NULL;
1157 1156 char *group = NULL;
1158 - sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle;
1159 1157
1160 - if (impl_handle != NULL && impl_handle->tree != NULL) {
1158 + if (handle != NULL && handle->tree != NULL) {
1161 1159 if (groupname != NULL) {
1162 1160 group = strdup(groupname);
1163 1161 if (group != NULL) {
1164 1162 subgroup = strchr(group, '/');
1165 1163 if (subgroup != NULL)
1166 1164 *subgroup++ = '\0';
1167 1165 }
1168 1166 }
1169 1167 /*
1170 1168 * We want to find the, possibly, named group. If
1171 1169 * group is not NULL, then lookup the name. If it is
1172 1170 * NULL, we only do the find if groupname is also
1173 1171 * NULL. This allows lookup of the "first" group in
1174 1172 * the internal list.
1175 1173 */
1176 1174 if (group != NULL || groupname == NULL)
1177 - node = find_group_by_name(impl_handle->tree,
1175 + node = find_group_by_name(handle->tree,
1178 1176 (xmlChar *)group);
1179 1177
1180 1178 /* if a subgroup, find it before returning */
1181 1179 if (subgroup != NULL && node != NULL)
1182 1180 node = find_group_by_name(node, (xmlChar *)subgroup);
1183 1181 }
1184 1182 if (node != NULL && (char *)group != NULL)
1185 - (void) sa_get_instance(impl_handle->scfhandle, (char *)group);
1183 + (void) sa_get_instance(handle->scfhandle, (char *)group);
1186 1184 if (group != NULL)
1187 1185 free(group);
1188 1186 return ((sa_group_t)(node));
1189 1187 }
1190 1188
1191 1189 /*
1192 1190 * sa_get_next_group(group)
1193 1191 * Return the "next" group after the specified group from
1194 1192 * the internal group list. NULL if there are no more.
1195 1193 */
1196 1194 sa_group_t
1197 1195 sa_get_next_group(sa_group_t group)
1198 1196 {
1199 1197 xmlNodePtr ngroup = NULL;
1200 1198 if (group != NULL) {
1201 1199 for (ngroup = ((xmlNodePtr)group)->next; ngroup != NULL;
1202 1200 ngroup = ngroup->next) {
1203 1201 if (xmlStrcmp(ngroup->name, (xmlChar *)"group") == 0)
1204 1202 break;
1205 1203 }
1206 1204 }
1207 1205 return ((sa_group_t)ngroup);
1208 1206 }
1209 1207
1210 1208 /*
1211 1209 * sa_get_share(group, sharepath)
1212 1210 * Return the share object for the share specified. The share
1213 1211 * must be in the specified group. Return NULL if not found.
1214 1212 */
1215 1213 sa_share_t
1216 1214 sa_get_share(sa_group_t group, char *sharepath)
1217 1215 {
1218 1216 xmlNodePtr node = NULL;
1219 1217 xmlChar *path;
1220 1218
1221 1219 /*
1222 1220 * For future scalability, this should end up building a cache
1223 1221 * since it will get called regularly by the mountd and info
1224 1222 * services.
1225 1223 */
1226 1224 if (group != NULL) {
1227 1225 for (node = ((xmlNodePtr)group)->children; node != NULL;
1228 1226 node = node->next) {
1229 1227 if (xmlStrcmp(node->name, (xmlChar *)"share") == 0) {
1230 1228 if (sharepath == NULL) {
1231 1229 break;
1232 1230 } else {
1233 1231 /* is it the correct share? */
1234 1232 path = xmlGetProp(node,
1235 1233 (xmlChar *)"path");
1236 1234 if (path != NULL &&
1237 1235 xmlStrcmp(path,
1238 1236 (xmlChar *)sharepath) == 0) {
1239 1237 xmlFree(path);
1240 1238 break;
1241 1239 }
1242 1240 xmlFree(path);
1243 1241 }
1244 1242 }
1245 1243 }
1246 1244 }
1247 1245 return ((sa_share_t)node);
1248 1246 }
1249 1247
1250 1248 /*
1251 1249 * sa_get_next_share(share)
1252 1250 * Return the next share following the specified share
1253 1251 * from the internal list of shares. Returns NULL if there
1254 1252 * are no more shares. The list is relative to the same
1255 1253 * group.
1256 1254 */
1257 1255 sa_share_t
1258 1256 sa_get_next_share(sa_share_t share)
1259 1257 {
1260 1258 xmlNodePtr node = NULL;
1261 1259
1262 1260 if (share != NULL) {
1263 1261 for (node = ((xmlNodePtr)share)->next; node != NULL;
1264 1262 node = node->next) {
1265 1263 if (xmlStrcmp(node->name, (xmlChar *)"share") == 0) {
1266 1264 break;
1267 1265 }
1268 1266 }
1269 1267 }
1270 1268 return ((sa_share_t)node);
1271 1269 }
1272 1270
1273 1271 /*
1274 1272 * _sa_get_child_node(node, type)
1275 1273 *
1276 1274 * find the child node of the specified node that has "type". This is
1277 1275 * used to implement several internal functions.
1278 1276 */
1279 1277
1280 1278 static xmlNodePtr
1281 1279 _sa_get_child_node(xmlNodePtr node, xmlChar *type)
1282 1280 {
1283 1281 xmlNodePtr child;
1284 1282 for (child = node->xmlChildrenNode; child != NULL;
1285 1283 child = child->next)
1286 1284 if (xmlStrcmp(child->name, type) == 0)
1287 1285 return (child);
1288 1286 return ((xmlNodePtr)NULL);
1289 1287 }
1290 1288
1291 1289 /*
1292 1290 * find_share(group, path)
1293 1291 *
1294 1292 * Search all the shares in the specified group for one that has the
1295 1293 * specified path.
1296 1294 */
1297 1295
1298 1296 static sa_share_t
1299 1297 find_share(sa_group_t group, char *sharepath)
1300 1298 {
1301 1299 sa_share_t share;
1302 1300 char *path;
1303 1301
1304 1302 for (share = sa_get_share(group, NULL); share != NULL;
1305 1303 share = sa_get_next_share(share)) {
1306 1304 path = sa_get_share_attr(share, "path");
1307 1305 if (path != NULL && strcmp(path, sharepath) == 0) {
1308 1306 sa_free_attr_string(path);
1309 1307 break;
1310 1308 }
1311 1309 if (path != NULL)
1312 1310 sa_free_attr_string(path);
1313 1311 }
1314 1312 return (share);
1315 1313 }
1316 1314
1317 1315 /*
1318 1316 * sa_get_sub_group(group)
1319 1317 *
1320 1318 * Get the first sub-group of group. The sa_get_next_group() function
1321 1319 * can be used to get the rest. This is currently only used for ZFS
1322 1320 * sub-groups but could be used to implement a more general mechanism.
1323 1321 */
1324 1322
1325 1323 sa_group_t
1326 1324 sa_get_sub_group(sa_group_t group)
1327 1325 {
1328 1326 return ((sa_group_t)_sa_get_child_node((xmlNodePtr)group,
1329 1327 (xmlChar *)"group"));
1330 1328 }
1331 1329
1332 1330 /*
1333 1331 * sa_find_share(sharepath)
1334 1332 * Finds a share regardless of group. In the future, this
1335 1333 * function should utilize a cache and hash table of some kind.
1336 1334 * The current assumption is that a path will only be shared
1337 1335 * once. In the future, this may change as implementation of
1338 1336 * resource names comes into being.
1339 1337 */
1340 1338 sa_share_t
1341 1339 sa_find_share(sa_handle_t handle, char *sharepath)
1342 1340 {
1343 1341 sa_group_t group;
1344 1342 sa_group_t zgroup;
1345 1343 sa_share_t share = NULL;
1346 1344 int done = 0;
1347 1345
1348 1346 for (group = sa_get_group(handle, NULL); group != NULL && !done;
1349 1347 group = sa_get_next_group(group)) {
1350 1348 if (is_zfs_group(group)) {
1351 1349 for (zgroup =
1352 1350 (sa_group_t)_sa_get_child_node((xmlNodePtr)group,
1353 1351 (xmlChar *)"group");
1354 1352 zgroup != NULL;
1355 1353 zgroup = sa_get_next_group(zgroup)) {
1356 1354 share = find_share(zgroup, sharepath);
1357 1355 if (share != NULL)
1358 1356 break;
1359 1357 }
1360 1358 } else {
1361 1359 share = find_share(group, sharepath);
1362 1360 }
1363 1361 if (share != NULL)
1364 1362 break;
1365 1363 }
1366 1364 return (share);
1367 1365 }
1368 1366
1369 1367 /*
1370 1368 * sa_check_path(group, path, strictness)
1371 1369 *
1372 1370 * Check that path is a valid path relative to the group. Currently,
1373 1371 * we are ignoring the group and checking only the NFS rules. Later,
1374 1372 * we may want to use the group to then check against the protocols
1375 1373 * enabled on the group. The strictness values mean:
1376 1374 * SA_CHECK_NORMAL == only check newpath against shares that are active
1377 1375 * SA_CHECK_STRICT == check newpath against both active shares and those
1378 1376 * stored in the repository
1379 1377 */
1380 1378
1381 1379 int
1382 1380 sa_check_path(sa_group_t group, char *path, int strictness)
1383 1381 {
1384 1382 sa_handle_t handle;
1385 1383
1386 1384 handle = sa_find_group_handle(group);
1387 1385 if (handle == NULL)
1388 1386 return (SA_BAD_PATH);
1389 1387
1390 1388 return (validpath(handle, path, strictness));
1391 1389 }
1392 1390
1393 1391 /*
1394 1392 * mark_excluded_protos(group, share, flags)
1395 1393 *
1396 1394 * Walk through all the protocols enabled for the group and check to
1397 1395 * see if the share has any of them should be in the exclude list
1398 1396 * based on the featureset of the protocol. If there are any, add the
1399 1397 * "exclude" property to the share.
1400 1398 */
1401 1399 static void
1402 1400 mark_excluded_protos(sa_group_t group, xmlNodePtr share, uint64_t flags)
1403 1401 {
1404 1402 sa_optionset_t optionset;
1405 1403 char exclude_list[SA_STRSIZE];
1406 1404 char *sep = "";
1407 1405
1408 1406 exclude_list[0] = '\0';
1409 1407 for (optionset = sa_get_optionset(group, NULL);
1410 1408 optionset != NULL;
1411 1409 optionset = sa_get_next_optionset(optionset)) {
1412 1410 char *value;
1413 1411 uint64_t features;
1414 1412 value = sa_get_optionset_attr(optionset, "type");
1415 1413 if (value == NULL)
1416 1414 continue;
1417 1415 features = sa_proto_get_featureset(value);
1418 1416 if (!(features & flags)) {
1419 1417 (void) strlcat(exclude_list, sep,
1420 1418 sizeof (exclude_list));
1421 1419 (void) strlcat(exclude_list, value,
1422 1420 sizeof (exclude_list));
1423 1421 sep = ",";
1424 1422 }
1425 1423 sa_free_attr_string(value);
1426 1424 }
1427 1425 if (exclude_list[0] != '\0')
1428 1426 (void) xmlSetProp(share, (xmlChar *)"exclude",
1429 1427 (xmlChar *)exclude_list);
1430 1428 }
1431 1429
1432 1430 /*
1433 1431 * get_all_features(group)
1434 1432 *
1435 1433 * Walk through all the protocols on the group and collect all
1436 1434 * possible enabled features. This is the OR of all the featuresets.
1437 1435 */
1438 1436 static uint64_t
1439 1437 get_all_features(sa_group_t group)
1440 1438 {
1441 1439 sa_optionset_t optionset;
1442 1440 uint64_t features = 0;
1443 1441
1444 1442 for (optionset = sa_get_optionset(group, NULL);
1445 1443 optionset != NULL;
1446 1444 optionset = sa_get_next_optionset(optionset)) {
1447 1445 char *value;
1448 1446 value = sa_get_optionset_attr(optionset, "type");
1449 1447 if (value == NULL)
1450 1448 continue;
1451 1449 features |= sa_proto_get_featureset(value);
1452 1450 sa_free_attr_string(value);
1453 1451 }
1454 1452 return (features);
1455 1453 }
1456 1454
1457 1455
1458 1456 /*
1459 1457 * _sa_add_share(group, sharepath, persist, *error, flags)
1460 1458 *
1461 1459 * Common code for all types of add_share. sa_add_share() is the
1462 1460 * public API, we also need to be able to do this when parsing legacy
1463 1461 * files and construction of the internal configuration while
1464 1462 * extracting config info from SMF. "flags" indicates if some
1465 1463 * protocols need relaxed rules while other don't. These values are
1466 1464 * the featureset values defined in libshare.h.
1467 1465 */
1468 1466
1469 1467 sa_share_t
1470 1468 _sa_add_share(sa_group_t group, char *sharepath, int persist, int *error,
1471 1469 uint64_t flags)
1472 1470 {
1473 1471 xmlNodePtr node = NULL;
1474 1472 int err;
1475 1473
1476 1474 err = SA_OK; /* assume success */
1477 1475
1478 1476 node = xmlNewChild((xmlNodePtr)group, NULL, (xmlChar *)"share", NULL);
1479 1477 if (node == NULL) {
1480 1478 if (error != NULL)
1481 1479 *error = SA_NO_MEMORY;
1482 1480 return (node);
1483 1481 }
1484 1482
1485 1483 (void) xmlSetProp(node, (xmlChar *)"path", (xmlChar *)sharepath);
1486 1484 (void) xmlSetProp(node, (xmlChar *)"type",
1487 1485 persist ? (xmlChar *)"persist" : (xmlChar *)"transient");
1488 1486 if (flags != 0)
1489 1487 mark_excluded_protos(group, node, flags);
1490 1488 if (persist != SA_SHARE_TRANSIENT) {
1491 1489 /*
1492 1490 * persistent shares come in two flavors: SMF and
1493 1491 * ZFS. Sort this one out based on target group and
1494 1492 * path type. Both NFS and SMB are supported. First,
↓ open down ↓ |
299 lines elided |
↑ open up ↑ |
1495 1493 * check to see if the protocol is enabled on the
1496 1494 * subgroup and then setup the share appropriately.
1497 1495 */
1498 1496 if (sa_group_is_zfs(group) &&
1499 1497 sa_path_is_zfs(sharepath)) {
1500 1498 if (sa_get_optionset(group, "nfs") != NULL)
1501 1499 err = sa_zfs_set_sharenfs(group, sharepath, 1);
1502 1500 else if (sa_get_optionset(group, "smb") != NULL)
1503 1501 err = sa_zfs_set_sharesmb(group, sharepath, 1);
1504 1502 } else {
1505 - sa_handle_impl_t impl_handle;
1506 - impl_handle =
1507 - (sa_handle_impl_t)sa_find_group_handle(group);
1508 - if (impl_handle != NULL) {
1509 - err = sa_commit_share(impl_handle->scfhandle,
1503 + sa_handle_t handle = sa_find_group_handle(group);
1504 + if (handle != NULL) {
1505 + err = sa_commit_share(handle->scfhandle,
1510 1506 group, (sa_share_t)node);
1511 1507 } else {
1512 1508 err = SA_SYSTEM_ERR;
1513 1509 }
1514 1510 }
1515 1511 }
1516 1512 if (err == SA_NO_PERMISSION && persist & SA_SHARE_PARSER)
1517 1513 /* called by the dfstab parser so could be a show */
1518 1514 err = SA_OK;
1519 1515
1520 1516 if (err != SA_OK) {
1521 1517 /*
1522 1518 * we couldn't commit to the repository so undo
1523 1519 * our internal state to reflect reality.
1524 1520 */
1525 1521 xmlUnlinkNode(node);
1526 1522 xmlFreeNode(node);
1527 1523 node = NULL;
1528 1524 }
1529 1525
1530 1526 if (error != NULL)
1531 1527 *error = err;
1532 1528
1533 1529 return (node);
1534 1530 }
1535 1531
1536 1532 /*
1537 1533 * sa_add_share(group, sharepath, persist, *error)
1538 1534 *
1539 1535 * Add a new share object to the specified group. The share will
1540 1536 * have the specified sharepath and will only be constructed if
1541 1537 * it is a valid path to be shared. NULL is returned on error
1542 1538 * and a detailed error value will be returned via the error
1543 1539 * pointer.
1544 1540 */
1545 1541 sa_share_t
1546 1542 sa_add_share(sa_group_t group, char *sharepath, int persist, int *error)
1547 1543 {
1548 1544 xmlNodePtr node = NULL;
1549 1545 int strictness = SA_CHECK_NORMAL;
1550 1546 sa_handle_t handle;
1551 1547 uint64_t special = 0;
1552 1548 uint64_t features;
1553 1549
1554 1550 /*
1555 1551 * If the share is to be permanent, use strict checking so a
1556 1552 * bad config doesn't get created. Transient shares only need
1557 1553 * to check against the currently active
1558 1554 * shares. SA_SHARE_PARSER is a modifier used internally to
1559 1555 * indicate that we are being called by the dfstab parser and
1560 1556 * that we need strict checking in all cases. Normally persist
1561 1557 * is in integer value but SA_SHARE_PARSER may be or'd into
1562 1558 * it as an override.
1563 1559 */
1564 1560 if (persist & SA_SHARE_PARSER || persist == SA_SHARE_PERMANENT)
1565 1561 strictness = SA_CHECK_STRICT;
1566 1562
1567 1563 handle = sa_find_group_handle(group);
1568 1564
1569 1565 /*
1570 1566 * need to determine if the share is valid. The rules are:
1571 1567 * - The path must not already exist
1572 1568 * - The path must not be a subdir or parent dir of an
1573 1569 * existing path unless at least one protocol allows it.
1574 1570 * The sub/parent check is done in sa_check_path().
1575 1571 */
1576 1572
1577 1573 if (sa_find_share(handle, sharepath) == NULL) {
1578 1574 *error = sa_check_path(group, sharepath, strictness);
1579 1575 features = get_all_features(group);
1580 1576 switch (*error) {
1581 1577 case SA_PATH_IS_SUBDIR:
1582 1578 if (features & SA_FEATURE_ALLOWSUBDIRS)
1583 1579 special |= SA_FEATURE_ALLOWSUBDIRS;
1584 1580 break;
1585 1581 case SA_PATH_IS_PARENTDIR:
1586 1582 if (features & SA_FEATURE_ALLOWPARDIRS)
1587 1583 special |= SA_FEATURE_ALLOWPARDIRS;
1588 1584 break;
1589 1585 }
1590 1586 if (*error == SA_OK || special != SA_FEATURE_NONE)
1591 1587 node = _sa_add_share(group, sharepath, persist,
1592 1588 error, special);
1593 1589 } else {
1594 1590 *error = SA_DUPLICATE_NAME;
1595 1591 }
1596 1592
1597 1593 return ((sa_share_t)node);
1598 1594 }
1599 1595
1600 1596 /*
1601 1597 * sa_enable_share(share, protocol)
1602 1598 * Enable the specified share to the specified protocol.
1603 1599 * If protocol is NULL, then all protocols.
1604 1600 */
1605 1601 int
1606 1602 sa_enable_share(sa_share_t share, char *protocol)
1607 1603 {
1608 1604 char *sharepath;
1609 1605 struct stat st;
1610 1606 int err = SA_OK;
1611 1607 int ret;
1612 1608
1613 1609 sharepath = sa_get_share_attr(share, "path");
1614 1610 if (sharepath == NULL)
1615 1611 return (SA_NO_MEMORY);
1616 1612 if (stat(sharepath, &st) < 0) {
1617 1613 err = SA_NO_SUCH_PATH;
1618 1614 } else {
1619 1615 /* tell the server about the share */
1620 1616 if (protocol != NULL) {
1621 1617 if (excluded_protocol(share, protocol))
1622 1618 goto done;
1623 1619
1624 1620 /* lookup protocol specific handler */
1625 1621 err = sa_proto_share(protocol, share);
1626 1622 if (err == SA_OK)
1627 1623 (void) sa_set_share_attr(share,
1628 1624 "shared", "true");
1629 1625 } else {
1630 1626 /* Tell all protocols about the share */
1631 1627 sa_group_t group;
1632 1628 sa_optionset_t optionset;
1633 1629
1634 1630 group = sa_get_parent_group(share);
1635 1631
1636 1632 for (optionset = sa_get_optionset(group, NULL);
1637 1633 optionset != NULL;
1638 1634 optionset = sa_get_next_optionset(optionset)) {
1639 1635 char *proto;
1640 1636 proto = sa_get_optionset_attr(optionset,
1641 1637 "type");
1642 1638 if (proto != NULL) {
1643 1639 if (!excluded_protocol(share, proto)) {
1644 1640 ret = sa_proto_share(proto,
1645 1641 share);
1646 1642 if (ret != SA_OK)
1647 1643 err = ret;
1648 1644 }
1649 1645 sa_free_attr_string(proto);
1650 1646 }
1651 1647 }
1652 1648 (void) sa_set_share_attr(share, "shared", "true");
1653 1649 }
1654 1650 }
1655 1651 done:
1656 1652 if (sharepath != NULL)
1657 1653 sa_free_attr_string(sharepath);
1658 1654 return (err);
1659 1655 }
1660 1656
1661 1657 /*
1662 1658 * sa_disable_share(share, protocol)
1663 1659 * Disable the specified share to the specified protocol. If
1664 1660 * protocol is NULL, then all protocols that are enabled for the
1665 1661 * share should be disabled.
1666 1662 */
1667 1663 int
1668 1664 sa_disable_share(sa_share_t share, char *protocol)
1669 1665 {
1670 1666 char *path;
1671 1667 int err = SA_OK;
1672 1668 int ret = SA_OK;
1673 1669
1674 1670 path = sa_get_share_attr(share, "path");
1675 1671
1676 1672 if (protocol != NULL) {
1677 1673 ret = sa_proto_unshare(share, protocol, path);
1678 1674 } else {
1679 1675 /* need to do all protocols */
1680 1676 sa_group_t group;
1681 1677 sa_optionset_t optionset;
1682 1678
1683 1679 group = sa_get_parent_group(share);
1684 1680
1685 1681 /* Tell all protocols about the share */
1686 1682 for (optionset = sa_get_optionset(group, NULL);
1687 1683 optionset != NULL;
1688 1684 optionset = sa_get_next_optionset(optionset)) {
1689 1685 char *proto;
1690 1686
1691 1687 proto = sa_get_optionset_attr(optionset, "type");
1692 1688 if (proto != NULL) {
1693 1689 err = sa_proto_unshare(share, proto, path);
1694 1690 if (err != SA_OK)
1695 1691 ret = err;
1696 1692 sa_free_attr_string(proto);
1697 1693 }
1698 1694 }
1699 1695 }
1700 1696 if (ret == SA_OK)
1701 1697 (void) sa_set_share_attr(share, "shared", NULL);
1702 1698 if (path != NULL)
1703 1699 sa_free_attr_string(path);
1704 1700 return (ret);
1705 1701 }
1706 1702
1707 1703 /*
1708 1704 * sa_remove_share(share)
1709 1705 *
1710 1706 * remove the specified share from its containing group.
1711 1707 * Remove from the SMF or ZFS configuration space.
1712 1708 */
1713 1709
1714 1710 int
1715 1711 sa_remove_share(sa_share_t share)
1716 1712 {
1717 1713 sa_group_t group;
1718 1714 int ret = SA_OK;
1719 1715 char *type;
1720 1716 int transient = 0;
1721 1717 char *groupname;
1722 1718 char *zfs;
1723 1719
1724 1720 type = sa_get_share_attr(share, "type");
1725 1721 group = sa_get_parent_group(share);
1726 1722 zfs = sa_get_group_attr(group, "zfs");
1727 1723 groupname = sa_get_group_attr(group, "name");
1728 1724 if (type != NULL && strcmp(type, "persist") != 0)
1729 1725 transient = 1;
1730 1726 if (type != NULL)
1731 1727 sa_free_attr_string(type);
1732 1728
1733 1729 /* remove the node from its group then free the memory */
↓ open down ↓ |
214 lines elided |
↑ open up ↑ |
1734 1730
1735 1731 /*
1736 1732 * need to test if "busy"
1737 1733 */
1738 1734 /* only do SMF action if permanent */
1739 1735 if (!transient || zfs != NULL) {
1740 1736 /* remove from legacy dfstab as well as possible SMF */
1741 1737 ret = sa_delete_legacy(share, NULL);
1742 1738 if (ret == SA_OK) {
1743 1739 if (!sa_group_is_zfs(group)) {
1744 - sa_handle_impl_t impl_handle;
1745 - impl_handle = (sa_handle_impl_t)
1740 + sa_handle_t handle =
1746 1741 sa_find_group_handle(group);
1747 - if (impl_handle != NULL) {
1742 + if (handle != NULL) {
1748 1743 ret = sa_delete_share(
1749 - impl_handle->scfhandle, group,
1744 + handle->scfhandle, group,
1750 1745 share);
1751 1746 } else {
1752 1747 ret = SA_SYSTEM_ERR;
1753 1748 }
1754 1749 } else {
1755 1750 char *sharepath = sa_get_share_attr(share,
1756 1751 "path");
1757 1752 if (sharepath != NULL) {
1758 1753 ret = sa_zfs_set_sharenfs(group,
1759 1754 sharepath, 0);
1760 1755 sa_free_attr_string(sharepath);
1761 1756 }
1762 1757 }
1763 1758 }
1764 1759 }
1765 1760 if (groupname != NULL)
1766 1761 sa_free_attr_string(groupname);
1767 1762 if (zfs != NULL)
1768 1763 sa_free_attr_string(zfs);
1769 1764
1770 1765 xmlUnlinkNode((xmlNodePtr)share);
1771 1766 xmlFreeNode((xmlNodePtr)share);
1772 1767 return (ret);
1773 1768 }
1774 1769
1775 1770 /*
1776 1771 * sa_move_share(group, share)
1777 1772 *
1778 1773 * move the specified share to the specified group. Update SMF
1779 1774 * appropriately.
1780 1775 */
1781 1776
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
1782 1777 int
1783 1778 sa_move_share(sa_group_t group, sa_share_t share)
1784 1779 {
1785 1780 sa_group_t oldgroup;
1786 1781 int ret = SA_OK;
1787 1782
1788 1783 /* remove the node from its group then free the memory */
1789 1784
1790 1785 oldgroup = sa_get_parent_group(share);
1791 1786 if (oldgroup != group) {
1792 - sa_handle_impl_t impl_handle;
1787 + sa_handle_t handle;
1793 1788 xmlUnlinkNode((xmlNodePtr)share);
1794 1789 /*
1795 1790 * now that the share isn't in its old group, add to
1796 1791 * the new one
1797 1792 */
1798 1793 (void) xmlAddChild((xmlNodePtr)group, (xmlNodePtr)share);
1799 1794 /* need to deal with SMF */
1800 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
1801 - if (impl_handle != NULL) {
1795 + handle = sa_find_group_handle(group);
1796 + if (handle != NULL) {
1802 1797 /*
1803 1798 * need to remove from old group first and then add to
1804 1799 * new group. Ideally, we would do the other order but
1805 1800 * need to avoid having the share in two groups at the
1806 1801 * same time.
1807 1802 */
1808 - ret = sa_delete_share(impl_handle->scfhandle, oldgroup,
1803 + ret = sa_delete_share(handle->scfhandle, oldgroup,
1809 1804 share);
1810 1805 if (ret == SA_OK)
1811 - ret = sa_commit_share(impl_handle->scfhandle,
1806 + ret = sa_commit_share(handle->scfhandle,
1812 1807 group, share);
1813 1808 } else {
1814 1809 ret = SA_SYSTEM_ERR;
1815 1810 }
1816 1811 }
1817 1812 return (ret);
1818 1813 }
1819 1814
1820 1815 /*
1821 1816 * sa_get_parent_group(share)
1822 1817 *
1823 1818 * Return the containing group for the share. If a group was actually
1824 1819 * passed in, we don't want a parent so return NULL.
1825 1820 */
1826 1821
1827 1822 sa_group_t
1828 1823 sa_get_parent_group(sa_share_t share)
1829 1824 {
1830 1825 xmlNodePtr node = NULL;
1831 1826 if (share != NULL) {
1832 1827 node = ((xmlNodePtr)share)->parent;
1833 1828 /*
1834 1829 * make sure parent is a group and not sharecfg since
1835 1830 * we may be cheating and passing in a group.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
1836 1831 * Eventually, groups of groups might come into being.
1837 1832 */
1838 1833 if (node == NULL ||
1839 1834 xmlStrcmp(node->name, (xmlChar *)"sharecfg") == 0)
1840 1835 node = NULL;
1841 1836 }
1842 1837 return ((sa_group_t)node);
1843 1838 }
1844 1839
1845 1840 /*
1846 - * _sa_create_group(impl_handle, groupname)
1841 + * _sa_create_group(handle, groupname)
1847 1842 *
1848 1843 * Create a group in the document. The caller will need to deal with
1849 1844 * configuration store and activation.
1850 1845 */
1851 1846
1852 1847 sa_group_t
1853 -_sa_create_group(sa_handle_impl_t impl_handle, char *groupname)
1848 +_sa_create_group(sa_handle_t handle, char *groupname)
1854 1849 {
1855 1850 xmlNodePtr node = NULL;
1856 1851
1857 1852 if (sa_valid_group_name(groupname)) {
1858 - node = xmlNewChild(impl_handle->tree, NULL, (xmlChar *)"group",
1853 + node = xmlNewChild(handle->tree, NULL, (xmlChar *)"group",
1859 1854 NULL);
1860 1855 if (node != NULL) {
1861 1856 (void) xmlSetProp(node, (xmlChar *)"name",
1862 1857 (xmlChar *)groupname);
1863 1858 (void) xmlSetProp(node, (xmlChar *)"state",
1864 1859 (xmlChar *)"enabled");
1865 1860 }
1866 1861 }
1867 1862 return ((sa_group_t)node);
1868 1863 }
1869 1864
1870 1865 /*
1871 1866 * _sa_create_zfs_group(group, groupname)
1872 1867 *
1873 1868 * Create a ZFS subgroup under the specified group. This may
1874 1869 * eventually form the basis of general sub-groups, but is currently
1875 1870 * restricted to ZFS.
1876 1871 */
1877 1872 sa_group_t
1878 1873 _sa_create_zfs_group(sa_group_t group, char *groupname)
1879 1874 {
1880 1875 xmlNodePtr node = NULL;
1881 1876
1882 1877 node = xmlNewChild((xmlNodePtr)group, NULL, (xmlChar *)"group", NULL);
1883 1878 if (node != NULL) {
1884 1879 (void) xmlSetProp(node, (xmlChar *)"name",
1885 1880 (xmlChar *)groupname);
1886 1881 (void) xmlSetProp(node, (xmlChar *)"state",
1887 1882 (xmlChar *)"enabled");
1888 1883 }
1889 1884
1890 1885 return ((sa_group_t)node);
1891 1886 }
1892 1887
1893 1888 /*
1894 1889 * sa_create_group(groupname, *error)
1895 1890 *
1896 1891 * Create a new group with groupname. Need to validate that it is a
1897 1892 * legal name for SMF and the construct the SMF service instance of
1898 1893 * svc:/network/shares/group to implement the group. All necessary
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
1899 1894 * operational properties must be added to the group at this point
1900 1895 * (via the SMF transaction model).
1901 1896 */
1902 1897 sa_group_t
1903 1898 sa_create_group(sa_handle_t handle, char *groupname, int *error)
1904 1899 {
1905 1900 xmlNodePtr node = NULL;
1906 1901 sa_group_t group;
1907 1902 int ret;
1908 1903 char rbacstr[SA_STRSIZE];
1909 - sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle;
1910 1904
1911 1905 ret = SA_OK;
1912 1906
1913 - if (impl_handle == NULL || impl_handle->scfhandle == NULL) {
1907 + if (handle == NULL || handle->scfhandle == NULL) {
1914 1908 ret = SA_SYSTEM_ERR;
1915 1909 goto err;
1916 1910 }
1917 1911
1918 1912 group = sa_get_group(handle, groupname);
1919 1913 if (group != NULL) {
1920 1914 ret = SA_DUPLICATE_NAME;
1921 1915 } else {
1922 1916 if (sa_valid_group_name(groupname)) {
1923 - node = xmlNewChild(impl_handle->tree, NULL,
1917 + node = xmlNewChild(handle->tree, NULL,
1924 1918 (xmlChar *)"group", NULL);
1925 1919 if (node != NULL) {
1926 1920 (void) xmlSetProp(node, (xmlChar *)"name",
1927 1921 (xmlChar *)groupname);
1928 1922 /* default to the group being enabled */
1929 1923 (void) xmlSetProp(node, (xmlChar *)"state",
1930 1924 (xmlChar *)"enabled");
1931 - ret = sa_create_instance(impl_handle->scfhandle,
1925 + ret = sa_create_instance(handle->scfhandle,
1932 1926 groupname);
1933 1927 if (ret == SA_OK) {
1934 1928 ret = sa_start_transaction(
1935 - impl_handle->scfhandle,
1929 + handle->scfhandle,
1936 1930 "operation");
1937 1931 }
1938 1932 if (ret == SA_OK) {
1939 1933 ret = sa_set_property(
1940 - impl_handle->scfhandle,
1934 + handle->scfhandle,
1941 1935 "state", "enabled");
1942 1936 if (ret == SA_OK) {
1943 1937 ret = sa_end_transaction(
1944 - impl_handle->scfhandle,
1945 - impl_handle);
1938 + handle->scfhandle,
1939 + handle);
1946 1940 } else {
1947 1941 sa_abort_transaction(
1948 - impl_handle->scfhandle);
1942 + handle->scfhandle);
1949 1943 }
1950 1944 }
1951 1945 if (ret == SA_OK) {
1952 1946 /* initialize the RBAC strings */
1953 1947 ret = sa_start_transaction(
1954 - impl_handle->scfhandle,
1948 + handle->scfhandle,
1955 1949 "general");
1956 1950 if (ret == SA_OK) {
1957 1951 (void) snprintf(rbacstr,
1958 1952 sizeof (rbacstr), "%s.%s",
1959 1953 SA_RBAC_MANAGE, groupname);
1960 1954 ret = sa_set_property(
1961 - impl_handle->scfhandle,
1955 + handle->scfhandle,
1962 1956 "action_authorization",
1963 1957 rbacstr);
1964 1958 }
1965 1959 if (ret == SA_OK) {
1966 1960 (void) snprintf(rbacstr,
1967 1961 sizeof (rbacstr), "%s.%s",
1968 1962 SA_RBAC_VALUE, groupname);
1969 1963 ret = sa_set_property(
1970 - impl_handle->scfhandle,
1964 + handle->scfhandle,
1971 1965 "value_authorization",
1972 1966 rbacstr);
1973 1967 }
1974 1968 if (ret == SA_OK) {
1975 1969 ret = sa_end_transaction(
1976 - impl_handle->scfhandle,
1977 - impl_handle);
1970 + handle->scfhandle,
1971 + handle);
1978 1972 } else {
1979 1973 sa_abort_transaction(
1980 - impl_handle->scfhandle);
1974 + handle->scfhandle);
1981 1975 }
1982 1976 }
1983 1977 if (ret != SA_OK) {
1984 1978 /*
1985 1979 * Couldn't commit the group
1986 1980 * so we need to undo
1987 1981 * internally.
1988 1982 */
1989 1983 xmlUnlinkNode(node);
1990 1984 xmlFreeNode(node);
1991 1985 node = NULL;
1992 1986 }
1993 1987 } else {
1994 1988 ret = SA_NO_MEMORY;
1995 1989 }
1996 1990 } else {
1997 1991 ret = SA_INVALID_NAME;
1998 1992 }
1999 1993 }
2000 1994 err:
2001 1995 if (error != NULL)
2002 1996 *error = ret;
2003 1997 return ((sa_group_t)node);
2004 1998 }
2005 1999
2006 2000 /*
2007 2001 * sa_remove_group(group)
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
2008 2002 *
2009 2003 * Remove the specified group. This deletes from the SMF repository.
2010 2004 * All property groups and properties are removed.
2011 2005 */
2012 2006
2013 2007 int
2014 2008 sa_remove_group(sa_group_t group)
2015 2009 {
2016 2010 char *name;
2017 2011 int ret = SA_OK;
2018 - sa_handle_impl_t impl_handle;
2012 + sa_handle_t handle;
2019 2013
2020 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
2021 - if (impl_handle != NULL) {
2014 + handle = sa_find_group_handle(group);
2015 + if (handle != NULL) {
2022 2016 name = sa_get_group_attr(group, "name");
2023 2017 if (name != NULL) {
2024 - ret = sa_delete_instance(impl_handle->scfhandle, name);
2018 + ret = sa_delete_instance(handle->scfhandle, name);
2025 2019 sa_free_attr_string(name);
2026 2020 }
2027 2021 xmlUnlinkNode((xmlNodePtr)group); /* make sure unlinked */
2028 2022 xmlFreeNode((xmlNodePtr)group); /* now it is gone */
2029 2023 } else {
2030 2024 ret = SA_SYSTEM_ERR;
2031 2025 }
2032 2026 return (ret);
2033 2027 }
2034 2028
2035 2029 /*
2036 2030 * sa_update_config()
2037 2031 *
2038 2032 * Used to update legacy files that need to be updated in bulk
2039 2033 * Currently, this is a placeholder and will go away in a future
2040 2034 * release.
2041 2035 */
2042 2036
2043 2037 int
2044 2038 sa_update_config(sa_handle_t handle)
2045 2039 {
2046 2040 /*
2047 2041 * do legacy files first so we can tell when they change.
2048 2042 * This will go away when we start updating individual records
2049 2043 * rather than the whole file.
2050 2044 */
2051 2045 update_legacy_config(handle);
2052 2046 return (SA_OK);
2053 2047 }
2054 2048
2055 2049 /*
2056 2050 * get_node_attr(node, tag)
2057 2051 *
2058 2052 * Get the specified tag(attribute) if it exists on the node. This is
2059 2053 * used internally by a number of attribute oriented functions.
2060 2054 */
2061 2055
2062 2056 static char *
2063 2057 get_node_attr(void *nodehdl, char *tag)
2064 2058 {
2065 2059 xmlNodePtr node = (xmlNodePtr)nodehdl;
2066 2060 xmlChar *name = NULL;
2067 2061
2068 2062 if (node != NULL)
2069 2063 name = xmlGetProp(node, (xmlChar *)tag);
2070 2064 return ((char *)name);
2071 2065 }
2072 2066
2073 2067 /*
2074 2068 * set_node_attr(node, tag)
2075 2069 *
2076 2070 * Set the specified tag(attribute) to the specified value This is
2077 2071 * used internally by a number of attribute oriented functions. It
2078 2072 * doesn't update the repository, only the internal document state.
2079 2073 */
2080 2074
2081 2075 void
2082 2076 set_node_attr(void *nodehdl, char *tag, char *value)
2083 2077 {
2084 2078 xmlNodePtr node = (xmlNodePtr)nodehdl;
2085 2079 if (node != NULL && tag != NULL) {
2086 2080 if (value != NULL)
2087 2081 (void) xmlSetProp(node, (xmlChar *)tag,
2088 2082 (xmlChar *)value);
2089 2083 else
2090 2084 (void) xmlUnsetProp(node, (xmlChar *)tag);
2091 2085 }
2092 2086 }
2093 2087
2094 2088 /*
2095 2089 * sa_get_group_attr(group, tag)
2096 2090 *
2097 2091 * Get the specied attribute, if defined, for the group.
2098 2092 */
2099 2093
2100 2094 char *
2101 2095 sa_get_group_attr(sa_group_t group, char *tag)
2102 2096 {
2103 2097 return (get_node_attr((void *)group, tag));
2104 2098 }
2105 2099
2106 2100 /*
2107 2101 * sa_set_group_attr(group, tag, value)
2108 2102 *
2109 2103 * set the specified tag/attribute on the group using value as its
2110 2104 * value.
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
2111 2105 *
2112 2106 * This will result in setting the property in the SMF repository as
2113 2107 * well as in the internal document.
2114 2108 */
2115 2109
2116 2110 int
2117 2111 sa_set_group_attr(sa_group_t group, char *tag, char *value)
2118 2112 {
2119 2113 int ret;
2120 2114 char *groupname;
2121 - sa_handle_impl_t impl_handle;
2115 + sa_handle_t handle;
2122 2116
2123 2117 /*
2124 2118 * ZFS group/subgroup doesn't need the handle so shortcut.
2125 2119 */
2126 2120 if (sa_group_is_zfs(group)) {
2127 2121 set_node_attr((void *)group, tag, value);
2128 2122 return (SA_OK);
2129 2123 }
2130 2124
2131 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
2132 - if (impl_handle != NULL) {
2125 + handle = sa_find_group_handle(group);
2126 + if (handle != NULL) {
2133 2127 groupname = sa_get_group_attr(group, "name");
2134 - ret = sa_get_instance(impl_handle->scfhandle, groupname);
2128 + ret = sa_get_instance(handle->scfhandle, groupname);
2135 2129 if (ret == SA_OK) {
2136 2130 set_node_attr((void *)group, tag, value);
2137 - ret = sa_start_transaction(impl_handle->scfhandle,
2131 + ret = sa_start_transaction(handle->scfhandle,
2138 2132 "operation");
2139 2133 if (ret == SA_OK) {
2140 - ret = sa_set_property(impl_handle->scfhandle,
2134 + ret = sa_set_property(handle->scfhandle,
2141 2135 tag, value);
2142 2136 if (ret == SA_OK)
2143 2137 ret = sa_end_transaction(
2144 - impl_handle->scfhandle,
2145 - impl_handle);
2138 + handle->scfhandle,
2139 + handle);
2146 2140 else
2147 2141 sa_abort_transaction(
2148 - impl_handle->scfhandle);
2142 + handle->scfhandle);
2149 2143 }
2150 2144 if (ret == SA_SYSTEM_ERR)
2151 2145 ret = SA_NO_PERMISSION;
2152 2146 }
2153 2147 if (groupname != NULL)
2154 2148 sa_free_attr_string(groupname);
2155 2149 } else {
2156 2150 ret = SA_SYSTEM_ERR;
2157 2151 }
2158 2152 return (ret);
2159 2153 }
2160 2154
2161 2155 /*
2162 2156 * sa_get_share_attr(share, tag)
2163 2157 *
2164 2158 * Return the value of the tag/attribute set on the specified
2165 2159 * share. Returns NULL if the tag doesn't exist.
2166 2160 */
2167 2161
2168 2162 char *
2169 2163 sa_get_share_attr(sa_share_t share, char *tag)
2170 2164 {
2171 2165 return (get_node_attr((void *)share, tag));
2172 2166 }
2173 2167
2174 2168 /*
2175 2169 * _sa_set_share_description(share, description)
2176 2170 *
2177 2171 * Add a description tag with text contents to the specified share. A
2178 2172 * separate XML tag is used rather than a property. This can also be
2179 2173 * used with resources.
2180 2174 */
2181 2175
2182 2176 xmlNodePtr
2183 2177 _sa_set_share_description(void *share, char *content)
2184 2178 {
2185 2179 xmlNodePtr node;
2186 2180 node = xmlNewChild((xmlNodePtr)share, NULL, (xmlChar *)"description",
2187 2181 NULL);
2188 2182 xmlNodeSetContent(node, (xmlChar *)content);
2189 2183 return (node);
2190 2184 }
2191 2185
2192 2186 /*
2193 2187 * sa_set_share_attr(share, tag, value)
2194 2188 *
2195 2189 * Set the share attribute specified by tag to the specified value. In
2196 2190 * the case of "resource", enforce a no duplicates in a group rule. If
2197 2191 * the share is not transient, commit the changes to the repository
2198 2192 * else just update the share internally.
2199 2193 */
2200 2194
2201 2195 int
2202 2196 sa_set_share_attr(sa_share_t share, char *tag, char *value)
2203 2197 {
2204 2198 sa_group_t group;
2205 2199 sa_share_t resource;
2206 2200 int ret = SA_OK;
2207 2201
2208 2202 group = sa_get_parent_group(share);
2209 2203
2210 2204 /*
2211 2205 * There are some attributes that may have specific
2212 2206 * restrictions on them. Initially, only "resource" has
2213 2207 * special meaning that needs to be checked. Only one instance
2214 2208 * of a resource name may exist within a group.
2215 2209 */
2216 2210
2217 2211 if (strcmp(tag, "resource") == 0) {
2218 2212 resource = sa_get_resource(group, value);
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
2219 2213 if (resource != share && resource != NULL)
2220 2214 ret = SA_DUPLICATE_NAME;
2221 2215 }
2222 2216 if (ret == SA_OK) {
2223 2217 set_node_attr((void *)share, tag, value);
2224 2218 if (group != NULL) {
2225 2219 char *type;
2226 2220 /* we can probably optimize this some */
2227 2221 type = sa_get_share_attr(share, "type");
2228 2222 if (type == NULL || strcmp(type, "transient") != 0) {
2229 - sa_handle_impl_t impl_handle;
2230 - impl_handle =
2231 - (sa_handle_impl_t)sa_find_group_handle(
2223 + sa_handle_t handle = sa_find_group_handle(
2232 2224 group);
2233 - if (impl_handle != NULL) {
2225 + if (handle != NULL) {
2234 2226 ret = sa_commit_share(
2235 - impl_handle->scfhandle, group,
2227 + handle->scfhandle, group,
2236 2228 share);
2237 2229 } else {
2238 2230 ret = SA_SYSTEM_ERR;
2239 2231 }
2240 2232 }
2241 2233 if (type != NULL)
2242 2234 sa_free_attr_string(type);
2243 2235 }
2244 2236 }
2245 2237 return (ret);
2246 2238 }
2247 2239
2248 2240 /*
2249 2241 * sa_get_property_attr(prop, tag)
2250 2242 *
2251 2243 * Get the value of the specified property attribute. Standard
2252 2244 * attributes are "type" and "value".
2253 2245 */
2254 2246
2255 2247 char *
2256 2248 sa_get_property_attr(sa_property_t prop, char *tag)
2257 2249 {
2258 2250 return (get_node_attr((void *)prop, tag));
2259 2251 }
2260 2252
2261 2253 /*
2262 2254 * sa_get_optionset_attr(prop, tag)
2263 2255 *
2264 2256 * Get the value of the specified property attribute. Standard
2265 2257 * attribute is "type".
2266 2258 */
2267 2259
2268 2260 char *
2269 2261 sa_get_optionset_attr(sa_property_t optionset, char *tag)
2270 2262 {
2271 2263 return (get_node_attr((void *)optionset, tag));
2272 2264
2273 2265 }
2274 2266
2275 2267 /*
2276 2268 * sa_set_optionset_attr(optionset, tag, value)
2277 2269 *
2278 2270 * Set the specified attribute(tag) to the specified value on the
2279 2271 * optionset.
2280 2272 */
2281 2273
2282 2274 void
2283 2275 sa_set_optionset_attr(sa_group_t optionset, char *tag, char *value)
2284 2276 {
2285 2277 set_node_attr((void *)optionset, tag, value);
2286 2278 }
2287 2279
2288 2280 /*
2289 2281 * sa_free_attr_string(string)
2290 2282 *
2291 2283 * Free the string that was returned in one of the sa_get_*_attr()
2292 2284 * functions.
2293 2285 */
2294 2286
2295 2287 void
2296 2288 sa_free_attr_string(char *string)
2297 2289 {
2298 2290 xmlFree((xmlChar *)string);
2299 2291 }
2300 2292
2301 2293 /*
2302 2294 * sa_get_optionset(group, proto)
2303 2295 *
2304 2296 * Return the optionset, if it exists, that is associated with the
2305 2297 * specified protocol.
2306 2298 */
2307 2299
2308 2300 sa_optionset_t
2309 2301 sa_get_optionset(void *group, char *proto)
2310 2302 {
2311 2303 xmlNodePtr node;
2312 2304 xmlChar *value = NULL;
2313 2305
2314 2306 for (node = ((xmlNodePtr)group)->children; node != NULL;
2315 2307 node = node->next) {
2316 2308 if (xmlStrcmp(node->name, (xmlChar *)"optionset") == 0) {
2317 2309 value = xmlGetProp(node, (xmlChar *)"type");
2318 2310 if (proto != NULL) {
2319 2311 if (value != NULL &&
2320 2312 xmlStrcmp(value, (xmlChar *)proto) == 0) {
2321 2313 break;
2322 2314 }
2323 2315 if (value != NULL) {
2324 2316 xmlFree(value);
2325 2317 value = NULL;
2326 2318 }
2327 2319 } else {
2328 2320 break;
2329 2321 }
2330 2322 }
2331 2323 }
2332 2324 if (value != NULL)
2333 2325 xmlFree(value);
2334 2326 return ((sa_optionset_t)node);
2335 2327 }
2336 2328
2337 2329 /*
2338 2330 * sa_get_next_optionset(optionset)
2339 2331 *
2340 2332 * Return the next optionset in the group. NULL if this was the last.
2341 2333 */
2342 2334
2343 2335 sa_optionset_t
2344 2336 sa_get_next_optionset(sa_optionset_t optionset)
2345 2337 {
2346 2338 xmlNodePtr node;
2347 2339
2348 2340 for (node = ((xmlNodePtr)optionset)->next; node != NULL;
2349 2341 node = node->next) {
2350 2342 if (xmlStrcmp(node->name, (xmlChar *)"optionset") == 0) {
2351 2343 break;
2352 2344 }
2353 2345 }
2354 2346 return ((sa_optionset_t)node);
2355 2347 }
2356 2348
2357 2349 /*
2358 2350 * sa_get_security(group, sectype, proto)
2359 2351 *
2360 2352 * Return the security optionset. The internal name is a hold over
2361 2353 * from the implementation and will be changed before the API is
2362 2354 * finalized. This is really a named optionset that can be negotiated
2363 2355 * as a group of properties (like NFS security options).
2364 2356 */
2365 2357
2366 2358 sa_security_t
2367 2359 sa_get_security(sa_group_t group, char *sectype, char *proto)
2368 2360 {
2369 2361 xmlNodePtr node;
2370 2362 xmlChar *value = NULL;
2371 2363
2372 2364 for (node = ((xmlNodePtr)group)->children; node != NULL;
2373 2365 node = node->next) {
2374 2366 if (xmlStrcmp(node->name, (xmlChar *)"security") == 0) {
2375 2367 if (proto != NULL) {
2376 2368 value = xmlGetProp(node, (xmlChar *)"type");
2377 2369 if (value == NULL ||
2378 2370 (value != NULL &&
2379 2371 xmlStrcmp(value, (xmlChar *)proto) != 0)) {
2380 2372 /* it doesn't match so continue */
2381 2373 xmlFree(value);
2382 2374 value = NULL;
2383 2375 continue;
2384 2376 }
2385 2377 }
2386 2378 if (value != NULL) {
2387 2379 xmlFree(value);
2388 2380 value = NULL;
2389 2381 }
2390 2382 /* potential match */
2391 2383 if (sectype != NULL) {
2392 2384 value = xmlGetProp(node, (xmlChar *)"sectype");
2393 2385 if (value != NULL &&
2394 2386 xmlStrcmp(value, (xmlChar *)sectype) == 0) {
2395 2387 break;
2396 2388 }
2397 2389 } else {
2398 2390 break;
2399 2391 }
2400 2392 }
2401 2393 if (value != NULL) {
2402 2394 xmlFree(value);
2403 2395 value = NULL;
2404 2396 }
2405 2397 }
2406 2398 if (value != NULL)
2407 2399 xmlFree(value);
2408 2400 return ((sa_security_t)node);
2409 2401 }
2410 2402
2411 2403 /*
2412 2404 * sa_get_next_security(security)
2413 2405 *
2414 2406 * Get the next security optionset if one exists.
2415 2407 */
2416 2408
2417 2409 sa_security_t
2418 2410 sa_get_next_security(sa_security_t security)
2419 2411 {
2420 2412 xmlNodePtr node;
2421 2413
2422 2414 for (node = ((xmlNodePtr)security)->next; node != NULL;
2423 2415 node = node->next) {
2424 2416 if (xmlStrcmp(node->name, (xmlChar *)"security") == 0) {
2425 2417 break;
2426 2418 }
2427 2419 }
2428 2420 return ((sa_security_t)node);
2429 2421 }
2430 2422
2431 2423 /*
2432 2424 * sa_get_property(optionset, prop)
2433 2425 *
2434 2426 * Get the property object with the name specified in prop from the
2435 2427 * optionset.
2436 2428 */
2437 2429
2438 2430 sa_property_t
2439 2431 sa_get_property(sa_optionset_t optionset, char *prop)
2440 2432 {
2441 2433 xmlNodePtr node = (xmlNodePtr)optionset;
2442 2434 xmlChar *value = NULL;
2443 2435
2444 2436 if (optionset == NULL)
2445 2437 return (NULL);
2446 2438
2447 2439 for (node = node->children; node != NULL;
2448 2440 node = node->next) {
2449 2441 if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
2450 2442 if (prop == NULL)
2451 2443 break;
2452 2444 value = xmlGetProp(node, (xmlChar *)"type");
2453 2445 if (value != NULL &&
2454 2446 xmlStrcmp(value, (xmlChar *)prop) == 0) {
2455 2447 break;
2456 2448 }
2457 2449 if (value != NULL) {
2458 2450 xmlFree(value);
2459 2451 value = NULL;
2460 2452 }
2461 2453 }
2462 2454 }
2463 2455 if (value != NULL)
2464 2456 xmlFree(value);
2465 2457 if (node != NULL && xmlStrcmp(node->name, (xmlChar *)"option") != 0) {
2466 2458 /*
2467 2459 * avoid a non option node -- it is possible to be a
2468 2460 * text node
2469 2461 */
2470 2462 node = NULL;
2471 2463 }
2472 2464 return ((sa_property_t)node);
2473 2465 }
2474 2466
2475 2467 /*
2476 2468 * sa_get_next_property(property)
2477 2469 *
2478 2470 * Get the next property following the specified property. NULL if
2479 2471 * this was the last.
2480 2472 */
2481 2473
2482 2474 sa_property_t
2483 2475 sa_get_next_property(sa_property_t property)
2484 2476 {
2485 2477 xmlNodePtr node;
2486 2478
2487 2479 for (node = ((xmlNodePtr)property)->next; node != NULL;
2488 2480 node = node->next) {
2489 2481 if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
2490 2482 break;
2491 2483 }
2492 2484 }
2493 2485 return ((sa_property_t)node);
2494 2486 }
2495 2487
2496 2488 /*
2497 2489 * sa_set_share_description(share, content)
2498 2490 *
2499 2491 * Set the description of share to content.
2500 2492 */
2501 2493
2502 2494 int
2503 2495 sa_set_share_description(sa_share_t share, char *content)
2504 2496 {
2505 2497 xmlNodePtr node;
2506 2498 sa_group_t group;
2507 2499 int ret = SA_OK;
2508 2500
2509 2501 for (node = ((xmlNodePtr)share)->children; node != NULL;
2510 2502 node = node->next) {
2511 2503 if (xmlStrcmp(node->name, (xmlChar *)"description") == 0) {
2512 2504 break;
2513 2505 }
2514 2506 }
2515 2507 /* no existing description but want to add */
2516 2508 if (node == NULL && content != NULL) {
2517 2509 /* add a description */
2518 2510 node = _sa_set_share_description(share, content);
2519 2511 } else if (node != NULL && content != NULL) {
↓ open down ↓ |
274 lines elided |
↑ open up ↑ |
2520 2512 /* update a description */
2521 2513 xmlNodeSetContent(node, (xmlChar *)content);
2522 2514 } else if (node != NULL && content == NULL) {
2523 2515 /* remove an existing description */
2524 2516 xmlUnlinkNode(node);
2525 2517 xmlFreeNode(node);
2526 2518 }
2527 2519 group = sa_get_parent_group(share);
2528 2520 if (group != NULL &&
2529 2521 sa_is_persistent(share) && (!sa_group_is_zfs(group))) {
2530 - sa_handle_impl_t impl_handle;
2531 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
2532 - if (impl_handle != NULL) {
2533 - ret = sa_commit_share(impl_handle->scfhandle, group,
2522 + sa_handle_t handle = sa_find_group_handle(group);
2523 + if (handle != NULL) {
2524 + ret = sa_commit_share(handle->scfhandle, group,
2534 2525 share);
2535 2526 } else {
2536 2527 ret = SA_SYSTEM_ERR;
2537 2528 }
2538 2529 }
2539 2530 return (ret);
2540 2531 }
2541 2532
2542 2533 /*
2543 2534 * fixproblemchars(string)
2544 2535 *
2545 2536 * don't want any newline or tab characters in the text since these
2546 2537 * could break display of data and legacy file formats.
2547 2538 */
2548 2539 static void
2549 2540 fixproblemchars(char *str)
2550 2541 {
2551 2542 int c;
2552 2543 for (c = *str; c != '\0'; c = *++str) {
2553 2544 if (c == '\t' || c == '\n')
2554 2545 *str = ' ';
2555 2546 else if (c == '"')
2556 2547 *str = '\'';
2557 2548 }
2558 2549 }
2559 2550
2560 2551 /*
2561 2552 * sa_get_share_description(share)
2562 2553 *
2563 2554 * Return the description text for the specified share if it
2564 2555 * exists. NULL if no description exists.
2565 2556 */
2566 2557
2567 2558 char *
2568 2559 sa_get_share_description(sa_share_t share)
2569 2560 {
2570 2561 xmlChar *description = NULL;
2571 2562 xmlNodePtr node;
2572 2563
2573 2564 for (node = ((xmlNodePtr)share)->children; node != NULL;
2574 2565 node = node->next) {
2575 2566 if (xmlStrcmp(node->name, (xmlChar *)"description") == 0) {
2576 2567 break;
2577 2568 }
2578 2569 }
2579 2570 if (node != NULL) {
2580 2571 description = xmlNodeGetContent(node);
2581 2572 fixproblemchars((char *)description);
2582 2573 }
2583 2574 return ((char *)description);
2584 2575 }
2585 2576
2586 2577 /*
2587 2578 * sa_free(share_description(description)
2588 2579 *
2589 2580 * Free the description string.
2590 2581 */
2591 2582
2592 2583 void
2593 2584 sa_free_share_description(char *description)
2594 2585 {
2595 2586 xmlFree((xmlChar *)description);
2596 2587 }
2597 2588
2598 2589 /*
2599 2590 * sa_create_optionset(group, proto)
2600 2591 *
2601 2592 * Create an optionset for the specified protocol in the specied
2602 2593 * group. This is manifested as a property group within SMF.
2603 2594 */
2604 2595
2605 2596 sa_optionset_t
2606 2597 sa_create_optionset(sa_group_t group, char *proto)
2607 2598 {
2608 2599 sa_optionset_t optionset;
2609 2600 sa_group_t parent = group;
2610 2601 sa_share_t share = NULL;
2611 2602 int err = SA_OK;
2612 2603 char *id = NULL;
2613 2604
2614 2605 optionset = sa_get_optionset(group, proto);
2615 2606 if (optionset != NULL) {
2616 2607 /* can't have a duplicate protocol */
2617 2608 optionset = NULL;
2618 2609 } else {
2619 2610 /*
2620 2611 * Account for resource names being slightly
2621 2612 * different.
2622 2613 */
2623 2614 if (sa_is_share(group)) {
2624 2615 /*
2625 2616 * Transient shares do not have an "id" so not an
2626 2617 * error to not find one.
2627 2618 */
2628 2619 id = sa_get_share_attr((sa_share_t)group, "id");
2629 2620 } else if (sa_is_resource(group)) {
2630 2621 share = sa_get_resource_parent(
2631 2622 (sa_resource_t)group);
2632 2623 id = sa_get_resource_attr(share, "id");
2633 2624
2634 2625 /* id can be NULL if the group is transient (ZFS) */
2635 2626 if (id == NULL && sa_is_persistent(group))
2636 2627 err = SA_NO_MEMORY;
2637 2628 }
2638 2629 if (err == SA_NO_MEMORY) {
2639 2630 /*
2640 2631 * Couldn't get the id for the share or
2641 2632 * resource. While this could be a
2642 2633 * configuration issue, it is most likely an
2643 2634 * out of memory. In any case, fail the create.
2644 2635 */
2645 2636 return (NULL);
2646 2637 }
2647 2638
2648 2639 optionset = (sa_optionset_t)xmlNewChild((xmlNodePtr)group,
2649 2640 NULL, (xmlChar *)"optionset", NULL);
2650 2641 /*
2651 2642 * only put to repository if on a group and we were
2652 2643 * able to create an optionset.
2653 2644 */
2654 2645 if (optionset != NULL) {
2655 2646 char oname[SA_STRSIZE];
2656 2647 char *groupname;
2657 2648
2658 2649 /*
2659 2650 * Need to get parent group in all cases, but also get
2660 2651 * the share if this is a resource.
2661 2652 */
2662 2653 if (sa_is_share(group)) {
2663 2654 parent = sa_get_parent_group((sa_share_t)group);
2664 2655 } else if (sa_is_resource(group)) {
2665 2656 share = sa_get_resource_parent(
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
2666 2657 (sa_resource_t)group);
2667 2658 parent = sa_get_parent_group(share);
2668 2659 }
2669 2660
2670 2661 sa_set_optionset_attr(optionset, "type", proto);
2671 2662
2672 2663 (void) sa_optionset_name(optionset, oname,
2673 2664 sizeof (oname), id);
2674 2665 groupname = sa_get_group_attr(parent, "name");
2675 2666 if (groupname != NULL && sa_is_persistent(group)) {
2676 - sa_handle_impl_t impl_handle;
2677 - impl_handle =
2678 - (sa_handle_impl_t)sa_find_group_handle(
2667 + sa_handle_t handle = sa_find_group_handle(
2679 2668 group);
2680 - assert(impl_handle != NULL);
2681 - if (impl_handle != NULL) {
2669 + assert(handle != NULL);
2670 + if (handle != NULL) {
2682 2671 (void) sa_get_instance(
2683 - impl_handle->scfhandle, groupname);
2672 + handle->scfhandle, groupname);
2684 2673 (void) sa_create_pgroup(
2685 - impl_handle->scfhandle, oname);
2674 + handle->scfhandle, oname);
2686 2675 }
2687 2676 }
2688 2677 if (groupname != NULL)
2689 2678 sa_free_attr_string(groupname);
2690 2679 }
2691 2680 }
2692 2681
2693 2682 if (id != NULL)
2694 2683 sa_free_attr_string(id);
2695 2684 return (optionset);
2696 2685 }
2697 2686
2698 2687 /*
2699 2688 * sa_get_property_parent(property)
2700 2689 *
2701 2690 * Given a property, return the object it is a property of. This will
2702 2691 * be an optionset of some type.
2703 2692 */
2704 2693
2705 2694 static sa_optionset_t
2706 2695 sa_get_property_parent(sa_property_t property)
2707 2696 {
2708 2697 xmlNodePtr node = NULL;
2709 2698
2710 2699 if (property != NULL)
2711 2700 node = ((xmlNodePtr)property)->parent;
2712 2701 return ((sa_optionset_t)node);
2713 2702 }
2714 2703
2715 2704 /*
2716 2705 * sa_get_optionset_parent(optionset)
2717 2706 *
2718 2707 * Return the parent of the specified optionset. This could be a group
2719 2708 * or a share.
2720 2709 */
2721 2710
2722 2711 static sa_group_t
2723 2712 sa_get_optionset_parent(sa_optionset_t optionset)
2724 2713 {
2725 2714 xmlNodePtr node = NULL;
2726 2715
2727 2716 if (optionset != NULL)
2728 2717 node = ((xmlNodePtr)optionset)->parent;
2729 2718 return ((sa_group_t)node);
2730 2719 }
2731 2720
2732 2721 /*
2733 2722 * zfs_needs_update(share)
2734 2723 *
2735 2724 * In order to avoid making multiple updates to a ZFS share when
2736 2725 * setting properties, the share attribute "changed" will be set to
2737 2726 * true when a property is added or modified. When done adding
2738 2727 * properties, we can then detect that an update is needed. We then
2739 2728 * clear the state here to detect additional changes.
2740 2729 */
2741 2730
2742 2731 static int
2743 2732 zfs_needs_update(sa_share_t share)
2744 2733 {
2745 2734 char *attr;
2746 2735 int result = 0;
2747 2736
2748 2737 attr = sa_get_share_attr(share, "changed");
2749 2738 if (attr != NULL) {
2750 2739 sa_free_attr_string(attr);
2751 2740 result = 1;
2752 2741 }
2753 2742 set_node_attr((void *)share, "changed", NULL);
2754 2743 return (result);
2755 2744 }
2756 2745
2757 2746 /*
2758 2747 * zfs_set_update(share)
2759 2748 *
2760 2749 * Set the changed attribute of the share to true.
2761 2750 */
2762 2751
2763 2752 static void
2764 2753 zfs_set_update(sa_share_t share)
2765 2754 {
2766 2755 set_node_attr((void *)share, "changed", "true");
2767 2756 }
2768 2757
2769 2758 /*
2770 2759 * sa_commit_properties(optionset, clear)
2771 2760 *
2772 2761 * Check if SMF or ZFS config and either update or abort the pending
2773 2762 * changes.
↓ open down ↓ |
78 lines elided |
↑ open up ↑ |
2774 2763 */
2775 2764
2776 2765 int
2777 2766 sa_commit_properties(sa_optionset_t optionset, int clear)
2778 2767 {
2779 2768 sa_group_t group;
2780 2769 sa_group_t parent;
2781 2770 int zfs = 0;
2782 2771 int needsupdate = 0;
2783 2772 int ret = SA_OK;
2784 - sa_handle_impl_t impl_handle;
2773 + sa_handle_t handle;
2785 2774
2786 2775 group = sa_get_optionset_parent(optionset);
2787 2776 if (group != NULL && (sa_is_share(group) || is_zfs_group(group))) {
2788 2777 /* only update ZFS if on a share */
2789 2778 parent = sa_get_parent_group(group);
2790 2779 zfs++;
2791 2780 if (parent != NULL && is_zfs_group(parent))
2792 2781 needsupdate = zfs_needs_update(group);
2793 2782 else
2794 2783 zfs = 0;
2795 2784 }
2796 2785 if (zfs) {
2797 2786 if (!clear && needsupdate)
2798 2787 ret = sa_zfs_update((sa_share_t)group);
2799 2788 } else {
2800 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
2801 - if (impl_handle != NULL) {
2789 + handle = sa_find_group_handle(group);
2790 + if (handle != NULL) {
2802 2791 if (clear) {
2803 2792 (void) sa_abort_transaction(
2804 - impl_handle->scfhandle);
2793 + handle->scfhandle);
2805 2794 } else {
2806 2795 ret = sa_end_transaction(
2807 - impl_handle->scfhandle, impl_handle);
2796 + handle->scfhandle, handle);
2808 2797 }
2809 2798 } else {
2810 2799 ret = SA_SYSTEM_ERR;
2811 2800 }
2812 2801 }
2813 2802 return (ret);
2814 2803 }
2815 2804
2816 2805 /*
2817 2806 * sa_destroy_optionset(optionset)
2818 2807 *
2819 2808 * Remove the optionset from its group. Update the repository to
2820 2809 * reflect this change.
2821 2810 */
2822 2811
2823 2812 int
2824 2813 sa_destroy_optionset(sa_optionset_t optionset)
2825 2814 {
2826 2815 char name[SA_STRSIZE];
2827 2816 int len;
2828 2817 int ret;
2829 2818 char *id = NULL;
2830 2819 sa_group_t group;
2831 2820 int ispersist = 1;
2832 2821
2833 2822 /* now delete the prop group */
2834 2823 group = sa_get_optionset_parent(optionset);
2835 2824 if (group != NULL) {
2836 2825 if (sa_is_resource(group)) {
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
2837 2826 sa_resource_t resource = group;
2838 2827 sa_share_t share = sa_get_resource_parent(resource);
2839 2828 group = sa_get_parent_group(share);
2840 2829 id = sa_get_share_attr(share, "id");
2841 2830 } else if (sa_is_share(group)) {
2842 2831 id = sa_get_share_attr((sa_share_t)group, "id");
2843 2832 }
2844 2833 ispersist = sa_is_persistent(group);
2845 2834 }
2846 2835 if (ispersist) {
2847 - sa_handle_impl_t impl_handle;
2836 + sa_handle_t handle = sa_find_group_handle(group);
2848 2837 len = sa_optionset_name(optionset, name, sizeof (name), id);
2849 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
2850 - if (impl_handle != NULL) {
2838 + if (handle != NULL) {
2851 2839 if (len > 0) {
2852 - ret = sa_delete_pgroup(impl_handle->scfhandle,
2840 + ret = sa_delete_pgroup(handle->scfhandle,
2853 2841 name);
2854 2842 }
2855 2843 } else {
2856 2844 ret = SA_SYSTEM_ERR;
2857 2845 }
2858 2846 }
2859 2847 xmlUnlinkNode((xmlNodePtr)optionset);
2860 2848 xmlFreeNode((xmlNodePtr)optionset);
2861 2849 if (id != NULL)
2862 2850 sa_free_attr_string(id);
2863 2851 return (ret);
2864 2852 }
2865 2853
2866 2854 /* private to the implementation */
2867 2855 int
2868 2856 _sa_remove_optionset(sa_optionset_t optionset)
2869 2857 {
2870 2858 int ret = SA_OK;
2871 2859
2872 2860 xmlUnlinkNode((xmlNodePtr)optionset);
2873 2861 xmlFreeNode((xmlNodePtr)optionset);
2874 2862 return (ret);
2875 2863 }
2876 2864
2877 2865 /*
2878 2866 * sa_create_security(group, sectype, proto)
2879 2867 *
2880 2868 * Create a security optionset (one that has a type name and a
2881 2869 * proto). Security is left over from a pure NFS implementation. The
2882 2870 * naming will change in the future when the API is released.
2883 2871 */
2884 2872 sa_security_t
2885 2873 sa_create_security(sa_group_t group, char *sectype, char *proto)
2886 2874 {
2887 2875 sa_security_t security;
2888 2876 char *id = NULL;
2889 2877 sa_group_t parent;
2890 2878 char *groupname = NULL;
2891 2879
2892 2880 if (group != NULL && sa_is_share(group)) {
2893 2881 id = sa_get_share_attr((sa_share_t)group, "id");
2894 2882 parent = sa_get_parent_group(group);
2895 2883 if (parent != NULL)
2896 2884 groupname = sa_get_group_attr(parent, "name");
2897 2885 } else if (group != NULL) {
2898 2886 groupname = sa_get_group_attr(group, "name");
2899 2887 }
2900 2888
2901 2889 security = sa_get_security(group, sectype, proto);
2902 2890 if (security != NULL) {
2903 2891 /* can't have a duplicate security option */
2904 2892 security = NULL;
2905 2893 } else {
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
2906 2894 security = (sa_security_t)xmlNewChild((xmlNodePtr)group,
2907 2895 NULL, (xmlChar *)"security", NULL);
2908 2896 if (security != NULL) {
2909 2897 char oname[SA_STRSIZE];
2910 2898 sa_set_security_attr(security, "type", proto);
2911 2899
2912 2900 sa_set_security_attr(security, "sectype", sectype);
2913 2901 (void) sa_security_name(security, oname,
2914 2902 sizeof (oname), id);
2915 2903 if (groupname != NULL && sa_is_persistent(group)) {
2916 - sa_handle_impl_t impl_handle;
2917 - impl_handle =
2918 - (sa_handle_impl_t)sa_find_group_handle(
2904 + sa_handle_t handle = sa_find_group_handle(
2919 2905 group);
2920 - if (impl_handle != NULL) {
2906 + if (handle != NULL) {
2921 2907 (void) sa_get_instance(
2922 - impl_handle->scfhandle, groupname);
2908 + handle->scfhandle, groupname);
2923 2909 (void) sa_create_pgroup(
2924 - impl_handle->scfhandle, oname);
2910 + handle->scfhandle, oname);
2925 2911 }
2926 2912 }
2927 2913 }
2928 2914 }
2929 2915 if (id != NULL)
2930 2916 sa_free_attr_string(id);
2931 2917 if (groupname != NULL)
2932 2918 sa_free_attr_string(groupname);
2933 2919 return (security);
2934 2920 }
2935 2921
2936 2922 /*
2937 2923 * sa_destroy_security(security)
2938 2924 *
2939 2925 * Remove the specified optionset from the document and the
2940 2926 * configuration.
2941 2927 */
2942 2928
2943 2929 int
2944 2930 sa_destroy_security(sa_security_t security)
2945 2931 {
2946 2932 char name[SA_STRSIZE];
2947 2933 int len;
2948 2934 int ret = SA_OK;
2949 2935 char *id = NULL;
2950 2936 sa_group_t group;
2951 2937 int iszfs = 0;
2952 2938 int ispersist = 1;
2953 2939
2954 2940 group = sa_get_optionset_parent(security);
2955 2941
2956 2942 if (group != NULL)
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
2957 2943 iszfs = sa_group_is_zfs(group);
2958 2944
2959 2945 if (group != NULL && !iszfs) {
2960 2946 if (sa_is_share(group))
2961 2947 ispersist = sa_is_persistent(group);
2962 2948 id = sa_get_share_attr((sa_share_t)group, "id");
2963 2949 }
2964 2950 if (ispersist) {
2965 2951 len = sa_security_name(security, name, sizeof (name), id);
2966 2952 if (!iszfs && len > 0) {
2967 - sa_handle_impl_t impl_handle;
2968 - impl_handle =
2969 - (sa_handle_impl_t)sa_find_group_handle(group);
2970 - if (impl_handle != NULL) {
2971 - ret = sa_delete_pgroup(impl_handle->scfhandle,
2953 + sa_handle_t handle = sa_find_group_handle(group);
2954 + if (handle != NULL) {
2955 + ret = sa_delete_pgroup(handle->scfhandle,
2972 2956 name);
2973 2957 } else {
2974 2958 ret = SA_SYSTEM_ERR;
2975 2959 }
2976 2960 }
2977 2961 }
2978 2962 xmlUnlinkNode((xmlNodePtr)security);
2979 2963 xmlFreeNode((xmlNodePtr)security);
2980 2964 if (iszfs)
2981 2965 ret = sa_zfs_update(group);
2982 2966 if (id != NULL)
2983 2967 sa_free_attr_string(id);
2984 2968 return (ret);
2985 2969 }
2986 2970
2987 2971 /*
2988 2972 * sa_get_security_attr(optionset, tag)
2989 2973 *
2990 2974 * Return the specified attribute value from the optionset.
2991 2975 */
2992 2976
2993 2977 char *
2994 2978 sa_get_security_attr(sa_property_t optionset, char *tag)
2995 2979 {
2996 2980 return (get_node_attr((void *)optionset, tag));
2997 2981
2998 2982 }
2999 2983
3000 2984 /*
3001 2985 * sa_set_security_attr(optionset, tag, value)
3002 2986 *
3003 2987 * Set the optioset attribute specied by tag to the specified value.
3004 2988 */
3005 2989
3006 2990 void
3007 2991 sa_set_security_attr(sa_group_t optionset, char *tag, char *value)
3008 2992 {
3009 2993 set_node_attr((void *)optionset, tag, value);
3010 2994 }
3011 2995
3012 2996 /*
3013 2997 * is_nodetype(node, type)
3014 2998 *
3015 2999 * Check to see if node is of the type specified.
3016 3000 */
3017 3001
3018 3002 static int
3019 3003 is_nodetype(void *node, char *type)
3020 3004 {
3021 3005 return (strcmp((char *)((xmlNodePtr)node)->name, type) == 0);
3022 3006 }
3023 3007
3024 3008 /*
3025 3009 * add_or_update()
3026 3010 *
3027 3011 * Add or update a property. Pulled out of sa_set_prop_by_prop for
3028 3012 * readability.
3029 3013 */
3030 3014 static int
3031 3015 add_or_update(scfutilhandle_t *scf_handle, int type, scf_value_t *value,
3032 3016 scf_transaction_entry_t *entry, char *name, char *valstr)
3033 3017 {
3034 3018 int ret = SA_SYSTEM_ERR;
3035 3019
3036 3020 if (value != NULL) {
3037 3021 if (type == SA_PROP_OP_ADD)
3038 3022 ret = scf_transaction_property_new(scf_handle->trans,
3039 3023 entry, name, SCF_TYPE_ASTRING);
3040 3024 else
3041 3025 ret = scf_transaction_property_change(scf_handle->trans,
3042 3026 entry, name, SCF_TYPE_ASTRING);
3043 3027 if (ret == 0) {
3044 3028 ret = scf_value_set_astring(value, valstr);
3045 3029 if (ret == 0)
3046 3030 ret = scf_entry_add_value(entry, value);
3047 3031 if (ret == 0)
3048 3032 return (ret);
3049 3033 scf_value_destroy(value);
3050 3034 } else {
3051 3035 scf_entry_destroy(entry);
3052 3036 }
3053 3037 }
3054 3038 return (SA_SYSTEM_ERR);
3055 3039 }
3056 3040
3057 3041 /*
3058 3042 * sa_set_prop_by_prop(optionset, group, prop, type)
3059 3043 *
3060 3044 * Add/remove/update the specified property prop into the optionset or
3061 3045 * share. If a share, sort out which property group based on GUID. In
3062 3046 * all cases, the appropriate transaction is set (or ZFS share is
3063 3047 * marked as needing an update)
3064 3048 */
3065 3049
3066 3050 static int
3067 3051 sa_set_prop_by_prop(sa_optionset_t optionset, sa_group_t group,
3068 3052 sa_property_t prop, int type)
3069 3053 {
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
3070 3054 char *name;
3071 3055 char *valstr;
3072 3056 int ret = SA_OK;
3073 3057 scf_transaction_entry_t *entry;
3074 3058 scf_value_t *value;
3075 3059 int opttype; /* 1 == optionset, 0 == security */
3076 3060 char *id = NULL;
3077 3061 int iszfs = 0;
3078 3062 sa_group_t parent = NULL;
3079 3063 sa_share_t share = NULL;
3080 - sa_handle_impl_t impl_handle;
3064 + sa_handle_t handle;
3081 3065 scfutilhandle_t *scf_handle;
3082 3066
3083 3067 if (!sa_is_persistent(group)) {
3084 3068 /*
3085 3069 * if the group/share is not persistent we don't need
3086 3070 * to do anything here
3087 3071 */
3088 3072 return (SA_OK);
3089 3073 }
3090 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
3091 - if (impl_handle == NULL || impl_handle->scfhandle == NULL)
3074 + handle = sa_find_group_handle(group);
3075 + if (handle == NULL || handle->scfhandle == NULL)
3092 3076 return (SA_SYSTEM_ERR);
3093 - scf_handle = impl_handle->scfhandle;
3077 + scf_handle = handle->scfhandle;
3094 3078 name = sa_get_property_attr(prop, "type");
3095 3079 valstr = sa_get_property_attr(prop, "value");
3096 3080 entry = scf_entry_create(scf_handle->handle);
3097 3081 opttype = is_nodetype((void *)optionset, "optionset");
3098 3082
3099 3083 /*
3100 3084 * Check for share vs. resource since they need slightly
3101 3085 * different treatment given the hierarchy.
3102 3086 */
3103 3087 if (valstr != NULL && entry != NULL) {
3104 3088 if (sa_is_share(group)) {
3105 3089 parent = sa_get_parent_group(group);
3106 3090 share = (sa_share_t)group;
3107 3091 if (parent != NULL)
3108 3092 iszfs = is_zfs_group(parent);
3109 3093 } else if (sa_is_resource(group)) {
3110 3094 share = sa_get_parent_group(group);
3111 3095 if (share != NULL)
3112 3096 parent = sa_get_parent_group(share);
3113 3097 } else {
3114 3098 iszfs = is_zfs_group(group);
3115 3099 }
3116 3100 if (!iszfs) {
3117 3101 if (scf_handle->trans == NULL) {
3118 3102 char oname[SA_STRSIZE];
3119 3103 char *groupname = NULL;
3120 3104 if (share != NULL) {
3121 3105 if (parent != NULL)
3122 3106 groupname =
3123 3107 sa_get_group_attr(parent,
3124 3108 "name");
3125 3109 id = sa_get_share_attr(
3126 3110 (sa_share_t)share, "id");
3127 3111 } else {
3128 3112 groupname = sa_get_group_attr(group,
3129 3113 "name");
3130 3114 }
3131 3115 if (groupname != NULL) {
3132 3116 ret = sa_get_instance(scf_handle,
3133 3117 groupname);
3134 3118 sa_free_attr_string(groupname);
3135 3119 }
3136 3120 if (opttype)
3137 3121 (void) sa_optionset_name(optionset,
3138 3122 oname, sizeof (oname), id);
3139 3123 else
3140 3124 (void) sa_security_name(optionset,
3141 3125 oname, sizeof (oname), id);
3142 3126 ret = sa_start_transaction(scf_handle, oname);
3143 3127 if (id != NULL)
3144 3128 sa_free_attr_string(id);
3145 3129 }
3146 3130 if (ret == SA_OK) {
3147 3131 switch (type) {
3148 3132 case SA_PROP_OP_REMOVE:
3149 3133 ret = scf_transaction_property_delete(
3150 3134 scf_handle->trans, entry, name);
3151 3135 break;
3152 3136 case SA_PROP_OP_ADD:
3153 3137 case SA_PROP_OP_UPDATE:
3154 3138 value = scf_value_create(
3155 3139 scf_handle->handle);
3156 3140 ret = add_or_update(scf_handle, type,
3157 3141 value, entry, name, valstr);
3158 3142 break;
3159 3143 }
3160 3144 }
3161 3145 } else {
3162 3146 /*
3163 3147 * ZFS update. The calling function would have updated
3164 3148 * the internal XML structure. Just need to flag it as
3165 3149 * changed for ZFS.
3166 3150 */
3167 3151 zfs_set_update((sa_share_t)group);
3168 3152 }
3169 3153 }
3170 3154
3171 3155 if (name != NULL)
3172 3156 sa_free_attr_string(name);
3173 3157 if (valstr != NULL)
3174 3158 sa_free_attr_string(valstr);
3175 3159 else if (entry != NULL)
3176 3160 scf_entry_destroy(entry);
3177 3161
3178 3162 if (ret == -1)
3179 3163 ret = SA_SYSTEM_ERR;
3180 3164
3181 3165 return (ret);
3182 3166 }
3183 3167
3184 3168 /*
3185 3169 * sa_create_section(name, value)
3186 3170 *
3187 3171 * Create a new section with the specified name and extra data.
3188 3172 */
3189 3173
3190 3174 sa_property_t
3191 3175 sa_create_section(char *name, char *extra)
3192 3176 {
3193 3177 xmlNodePtr node;
3194 3178
3195 3179 node = xmlNewNode(NULL, (xmlChar *)"section");
3196 3180 if (node != NULL) {
3197 3181 if (name != NULL)
3198 3182 (void) xmlSetProp(node, (xmlChar *)"name",
3199 3183 (xmlChar *)name);
3200 3184 if (extra != NULL)
3201 3185 (void) xmlSetProp(node, (xmlChar *)"extra",
3202 3186 (xmlChar *)extra);
3203 3187 }
3204 3188 return ((sa_property_t)node);
3205 3189 }
3206 3190
3207 3191 void
3208 3192 sa_set_section_attr(sa_property_t sect, char *name, char *value)
3209 3193 {
3210 3194 (void) xmlSetProp(sect, (xmlChar *)name, (xmlChar *)value);
3211 3195 }
3212 3196
3213 3197 /*
3214 3198 * sa_create_property(section, name, value)
3215 3199 *
3216 3200 * Create a new property with the specified name and value.
3217 3201 */
3218 3202
3219 3203 sa_property_t
3220 3204 sa_create_property(char *name, char *value)
3221 3205 {
3222 3206 xmlNodePtr node;
3223 3207
3224 3208 node = xmlNewNode(NULL, (xmlChar *)"option");
3225 3209 if (node != NULL) {
3226 3210 (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)name);
3227 3211 (void) xmlSetProp(node, (xmlChar *)"value", (xmlChar *)value);
3228 3212 }
3229 3213 return ((sa_property_t)node);
3230 3214 }
3231 3215
3232 3216 /*
3233 3217 * sa_add_property(object, property)
3234 3218 *
3235 3219 * Add the specified property to the object. Issue the appropriate
3236 3220 * transaction or mark a ZFS object as needing an update.
3237 3221 */
3238 3222
3239 3223 int
3240 3224 sa_add_property(void *object, sa_property_t property)
3241 3225 {
3242 3226 int ret = SA_OK;
3243 3227 sa_group_t parent;
3244 3228 sa_group_t group;
3245 3229 char *proto;
3246 3230
3247 3231 if (property != NULL) {
3248 3232 sa_handle_t handle;
3249 3233 handle = sa_find_group_handle((sa_group_t)object);
3250 3234 /* It is legitimate to not find a handle */
3251 3235 proto = sa_get_optionset_attr(object, "type");
3252 3236 if ((ret = sa_valid_property(handle, object, proto,
3253 3237 property)) == SA_OK) {
3254 3238 property = (sa_property_t)xmlAddChild(
3255 3239 (xmlNodePtr)object, (xmlNodePtr)property);
3256 3240 } else {
3257 3241 if (proto != NULL)
3258 3242 sa_free_attr_string(proto);
3259 3243 return (ret);
3260 3244 }
3261 3245 if (proto != NULL)
3262 3246 sa_free_attr_string(proto);
3263 3247 }
3264 3248
3265 3249
3266 3250 parent = sa_get_parent_group(object);
3267 3251 if (!sa_is_persistent(parent))
3268 3252 return (ret);
3269 3253
3270 3254 if (sa_is_resource(parent)) {
3271 3255 /*
3272 3256 * Resources are children of share. Need to go up two
3273 3257 * levels to find the group but the parent needs to be
3274 3258 * the share at this point in order to get the "id".
3275 3259 */
3276 3260 parent = sa_get_parent_group(parent);
3277 3261 group = sa_get_parent_group(parent);
3278 3262 } else if (sa_is_share(parent)) {
3279 3263 group = sa_get_parent_group(parent);
3280 3264 } else {
↓ open down ↓ |
177 lines elided |
↑ open up ↑ |
3281 3265 group = parent;
3282 3266 }
3283 3267
3284 3268 if (property == NULL) {
3285 3269 ret = SA_NO_MEMORY;
3286 3270 } else {
3287 3271 char oname[SA_STRSIZE];
3288 3272
3289 3273 if (!is_zfs_group(group)) {
3290 3274 char *id = NULL;
3291 - sa_handle_impl_t impl_handle;
3275 + sa_handle_t handle;
3292 3276 scfutilhandle_t *scf_handle;
3293 3277
3294 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(
3295 - group);
3296 - if (impl_handle == NULL ||
3297 - impl_handle->scfhandle == NULL)
3278 + handle = sa_find_group_handle(group);
3279 + if (handle == NULL ||
3280 + handle->scfhandle == NULL)
3298 3281 ret = SA_SYSTEM_ERR;
3299 3282 if (ret == SA_OK) {
3300 - scf_handle = impl_handle->scfhandle;
3283 + scf_handle = handle->scfhandle;
3301 3284 if (sa_is_share((sa_group_t)parent)) {
3302 3285 id = sa_get_share_attr(
3303 3286 (sa_share_t)parent, "id");
3304 3287 }
3305 3288 if (scf_handle->trans == NULL) {
3306 3289 if (is_nodetype(object, "optionset")) {
3307 3290 (void) sa_optionset_name(
3308 3291 (sa_optionset_t)object,
3309 3292 oname, sizeof (oname), id);
3310 3293 } else {
3311 3294 (void) sa_security_name(
3312 3295 (sa_optionset_t)object,
3313 3296 oname, sizeof (oname), id);
3314 3297 }
3315 3298 ret = sa_start_transaction(scf_handle,
3316 3299 oname);
3317 3300 }
3318 3301 if (ret == SA_OK) {
3319 3302 char *name;
3320 3303 char *value;
3321 3304 name = sa_get_property_attr(property,
3322 3305 "type");
3323 3306 value = sa_get_property_attr(property,
3324 3307 "value");
3325 3308 if (name != NULL && value != NULL) {
3326 3309 if (scf_handle->scf_state ==
3327 3310 SCH_STATE_INIT) {
3328 3311 ret = sa_set_property(
3329 3312 scf_handle, name,
3330 3313 value);
3331 3314 }
3332 3315 } else {
3333 3316 ret = SA_CONFIG_ERR;
3334 3317 }
3335 3318 if (name != NULL)
3336 3319 sa_free_attr_string(
3337 3320 name);
3338 3321 if (value != NULL)
3339 3322 sa_free_attr_string(value);
3340 3323 }
3341 3324 if (id != NULL)
3342 3325 sa_free_attr_string(id);
3343 3326 }
3344 3327 } else {
3345 3328 /*
3346 3329 * ZFS is a special case. We do want
3347 3330 * to allow editing property/security
3348 3331 * lists since we can have a better
3349 3332 * syntax and we also want to keep
3350 3333 * things consistent when possible.
3351 3334 *
3352 3335 * Right now, we defer until the
3353 3336 * sa_commit_properties so we can get
3354 3337 * them all at once. We do need to
3355 3338 * mark the share as "changed"
3356 3339 */
3357 3340 zfs_set_update((sa_share_t)parent);
3358 3341 }
3359 3342 }
3360 3343 return (ret);
3361 3344 }
3362 3345
3363 3346 /*
3364 3347 * sa_remove_property(property)
3365 3348 *
3366 3349 * Remove the specied property from its containing object. Update the
3367 3350 * repository as appropriate.
3368 3351 */
3369 3352
3370 3353 int
3371 3354 sa_remove_property(sa_property_t property)
3372 3355 {
3373 3356 int ret = SA_OK;
3374 3357
3375 3358 if (property != NULL) {
3376 3359 sa_optionset_t optionset;
3377 3360 sa_group_t group;
3378 3361 optionset = sa_get_property_parent(property);
3379 3362 if (optionset != NULL) {
3380 3363 group = sa_get_optionset_parent(optionset);
3381 3364 if (group != NULL) {
3382 3365 ret = sa_set_prop_by_prop(optionset, group,
3383 3366 property, SA_PROP_OP_REMOVE);
3384 3367 }
3385 3368 }
3386 3369 xmlUnlinkNode((xmlNodePtr)property);
3387 3370 xmlFreeNode((xmlNodePtr)property);
3388 3371 } else {
3389 3372 ret = SA_NO_SUCH_PROP;
3390 3373 }
3391 3374 return (ret);
3392 3375 }
3393 3376
3394 3377 /*
3395 3378 * sa_update_property(property, value)
3396 3379 *
3397 3380 * Update the specified property to the new value. If value is NULL,
3398 3381 * we currently treat this as a remove.
3399 3382 */
3400 3383
3401 3384 int
3402 3385 sa_update_property(sa_property_t property, char *value)
3403 3386 {
3404 3387 int ret = SA_OK;
3405 3388 if (value == NULL) {
3406 3389 return (sa_remove_property(property));
3407 3390 } else {
3408 3391 sa_optionset_t optionset;
3409 3392 sa_group_t group;
3410 3393 set_node_attr((void *)property, "value", value);
3411 3394 optionset = sa_get_property_parent(property);
3412 3395 if (optionset != NULL) {
3413 3396 group = sa_get_optionset_parent(optionset);
3414 3397 if (group != NULL) {
3415 3398 ret = sa_set_prop_by_prop(optionset, group,
3416 3399 property, SA_PROP_OP_UPDATE);
3417 3400 }
3418 3401 } else {
3419 3402 ret = SA_NO_SUCH_PROP;
3420 3403 }
3421 3404 }
3422 3405 return (ret);
3423 3406 }
3424 3407
3425 3408 /*
3426 3409 * sa_get_protocol_section(propset, prop)
3427 3410 *
3428 3411 * Get the specified protocol specific section. These are global to
3429 3412 * the protocol and not specific to a group or share.
3430 3413 */
3431 3414
3432 3415 sa_protocol_properties_t
3433 3416 sa_get_protocol_section(sa_protocol_properties_t propset, char *section)
3434 3417 {
3435 3418 xmlNodePtr node = (xmlNodePtr)propset;
3436 3419 xmlChar *value = NULL;
3437 3420 char *proto;
3438 3421
3439 3422 proto = sa_get_optionset_attr(propset, "type");
3440 3423 if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0) {
3441 3424 if (proto != NULL)
3442 3425 sa_free_attr_string(proto);
3443 3426 return (propset);
3444 3427 }
3445 3428
3446 3429 for (node = node->children; node != NULL;
3447 3430 node = node->next) {
3448 3431 if (xmlStrcmp(node->name, (xmlChar *)"section") == 0) {
3449 3432 if (section == NULL)
3450 3433 break;
3451 3434 value = xmlGetProp(node, (xmlChar *)"name");
3452 3435 if (value != NULL &&
3453 3436 xmlStrcasecmp(value, (xmlChar *)section) == 0) {
3454 3437 break;
3455 3438 }
3456 3439 if (value != NULL) {
3457 3440 xmlFree(value);
3458 3441 value = NULL;
3459 3442 }
3460 3443 }
3461 3444 }
3462 3445 if (value != NULL)
3463 3446 xmlFree(value);
3464 3447 if (proto != NULL)
3465 3448 sa_free_attr_string(proto);
3466 3449 if (node != NULL && xmlStrcmp(node->name, (xmlChar *)"section") != 0) {
3467 3450 /*
3468 3451 * avoid a non option node -- it is possible to be a
3469 3452 * text node
3470 3453 */
3471 3454 node = NULL;
3472 3455 }
3473 3456 return ((sa_protocol_properties_t)node);
3474 3457 }
3475 3458
3476 3459 /*
3477 3460 * sa_get_next_protocol_section(prop, find)
3478 3461 *
3479 3462 * Get the next protocol specific section in the list.
3480 3463 */
3481 3464
3482 3465 sa_property_t
3483 3466 sa_get_next_protocol_section(sa_property_t prop, char *find)
3484 3467 {
3485 3468 xmlNodePtr node;
3486 3469 xmlChar *value = NULL;
3487 3470 char *proto;
3488 3471
3489 3472 proto = sa_get_optionset_attr(prop, "type");
3490 3473 if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0) {
3491 3474 if (proto != NULL)
3492 3475 sa_free_attr_string(proto);
3493 3476 return ((sa_property_t)NULL);
3494 3477 }
3495 3478
3496 3479 for (node = ((xmlNodePtr)prop)->next; node != NULL;
3497 3480 node = node->next) {
3498 3481 if (xmlStrcmp(node->name, (xmlChar *)"section") == 0) {
3499 3482 if (find == NULL)
3500 3483 break;
3501 3484 value = xmlGetProp(node, (xmlChar *)"name");
3502 3485 if (value != NULL &&
3503 3486 xmlStrcasecmp(value, (xmlChar *)find) == 0) {
3504 3487 break;
3505 3488 }
3506 3489 if (value != NULL) {
3507 3490 xmlFree(value);
3508 3491 value = NULL;
3509 3492 }
3510 3493
3511 3494 }
3512 3495 }
3513 3496 if (value != NULL)
3514 3497 xmlFree(value);
3515 3498 if (proto != NULL)
3516 3499 sa_free_attr_string(proto);
3517 3500 return ((sa_property_t)node);
3518 3501 }
3519 3502
3520 3503 /*
3521 3504 * sa_get_protocol_property(propset, prop)
3522 3505 *
3523 3506 * Get the specified protocol specific property. These are global to
3524 3507 * the protocol and not specific to a group or share.
3525 3508 */
3526 3509
3527 3510 sa_property_t
3528 3511 sa_get_protocol_property(sa_protocol_properties_t propset, char *prop)
3529 3512 {
3530 3513 xmlNodePtr node = (xmlNodePtr)propset;
3531 3514 xmlChar *value = NULL;
3532 3515
3533 3516 if (propset == NULL)
3534 3517 return (NULL);
3535 3518
3536 3519 for (node = node->children; node != NULL;
3537 3520 node = node->next) {
3538 3521 if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
3539 3522 if (prop == NULL)
3540 3523 break;
3541 3524 value = xmlGetProp(node, (xmlChar *)"type");
3542 3525 if (value != NULL &&
3543 3526 xmlStrcasecmp(value, (xmlChar *)prop) == 0) {
3544 3527 break;
3545 3528 }
3546 3529 if (value != NULL) {
3547 3530 xmlFree(value);
3548 3531 value = NULL;
3549 3532 }
3550 3533 }
3551 3534 }
3552 3535 if (value != NULL)
3553 3536 xmlFree(value);
3554 3537 if (node != NULL && xmlStrcmp(node->name, (xmlChar *)"option") != 0) {
3555 3538 /*
3556 3539 * avoid a non option node -- it is possible to be a
3557 3540 * text node
3558 3541 */
3559 3542 node = NULL;
3560 3543 }
3561 3544 return ((sa_property_t)node);
3562 3545 }
3563 3546
3564 3547 /*
3565 3548 * sa_get_next_protocol_property(prop)
3566 3549 *
3567 3550 * Get the next protocol specific property in the list.
3568 3551 */
3569 3552
3570 3553 sa_property_t
3571 3554 sa_get_next_protocol_property(sa_property_t prop, char *find)
3572 3555 {
3573 3556 xmlNodePtr node;
3574 3557 xmlChar *value = NULL;
3575 3558
3576 3559 for (node = ((xmlNodePtr)prop)->next; node != NULL;
3577 3560 node = node->next) {
3578 3561 if (xmlStrcmp(node->name, (xmlChar *)"option") == 0) {
3579 3562 if (find == NULL)
3580 3563 break;
3581 3564 value = xmlGetProp(node, (xmlChar *)"type");
3582 3565 if (value != NULL &&
3583 3566 xmlStrcasecmp(value, (xmlChar *)find) == 0) {
3584 3567 break;
3585 3568 }
3586 3569 if (value != NULL) {
3587 3570 xmlFree(value);
3588 3571 value = NULL;
3589 3572 }
3590 3573
3591 3574 }
3592 3575 }
3593 3576 if (value != NULL)
3594 3577 xmlFree(value);
3595 3578 return ((sa_property_t)node);
3596 3579 }
3597 3580
3598 3581 /*
3599 3582 * sa_set_protocol_property(prop, value)
3600 3583 *
3601 3584 * Set the specified property to have the new value. The protocol
3602 3585 * specific plugin will then be called to update the property.
3603 3586 */
3604 3587
3605 3588 int
3606 3589 sa_set_protocol_property(sa_property_t prop, char *section, char *value)
3607 3590 {
3608 3591 sa_protocol_properties_t propset;
3609 3592 char *proto;
3610 3593 int ret = SA_INVALID_PROTOCOL;
3611 3594
3612 3595 propset = ((xmlNodePtr)prop)->parent;
3613 3596 if (propset != NULL) {
3614 3597 proto = sa_get_optionset_attr(propset, "type");
3615 3598 if (proto != NULL) {
3616 3599 if (section != NULL)
3617 3600 set_node_attr((xmlNodePtr)prop, "section",
3618 3601 section);
3619 3602 set_node_attr((xmlNodePtr)prop, "value", value);
3620 3603 ret = sa_proto_set_property(proto, prop);
3621 3604 sa_free_attr_string(proto);
3622 3605 }
3623 3606 }
3624 3607 return (ret);
3625 3608 }
3626 3609
3627 3610 /*
3628 3611 * sa_add_protocol_property(propset, prop)
3629 3612 *
3630 3613 * Add a new property to the protocol specific property set.
3631 3614 */
3632 3615
3633 3616 int
3634 3617 sa_add_protocol_property(sa_protocol_properties_t propset, sa_property_t prop)
3635 3618 {
3636 3619 xmlNodePtr node;
3637 3620
3638 3621 /* should check for legitimacy */
3639 3622 node = xmlAddChild((xmlNodePtr)propset, (xmlNodePtr)prop);
3640 3623 if (node != NULL)
3641 3624 return (SA_OK);
3642 3625 return (SA_NO_MEMORY);
3643 3626 }
3644 3627
3645 3628 /*
3646 3629 * sa_create_protocol_properties(proto)
3647 3630 *
3648 3631 * Create a protocol specific property set.
3649 3632 */
3650 3633
3651 3634 sa_protocol_properties_t
3652 3635 sa_create_protocol_properties(char *proto)
3653 3636 {
3654 3637 xmlNodePtr node;
3655 3638
3656 3639 node = xmlNewNode(NULL, (xmlChar *)"propertyset");
3657 3640 if (node != NULL)
3658 3641 (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)proto);
3659 3642 return (node);
3660 3643 }
3661 3644
3662 3645 /*
3663 3646 * sa_get_share_resource(share, resource)
3664 3647 *
3665 3648 * Get the named resource from the share, if it exists. If resource is
3666 3649 * NULL, get the first resource.
3667 3650 */
3668 3651
3669 3652 sa_resource_t
3670 3653 sa_get_share_resource(sa_share_t share, char *resource)
3671 3654 {
3672 3655 xmlNodePtr node = NULL;
3673 3656 xmlChar *name;
3674 3657
3675 3658 if (share != NULL) {
3676 3659 for (node = ((xmlNodePtr)share)->children; node != NULL;
3677 3660 node = node->next) {
3678 3661 if (xmlStrcmp(node->name, (xmlChar *)"resource") == 0) {
3679 3662 if (resource == NULL) {
3680 3663 /*
3681 3664 * We are looking for the first
3682 3665 * resource node and not a names
3683 3666 * resource.
3684 3667 */
3685 3668 break;
3686 3669 } else {
3687 3670 /* is it the correct share? */
3688 3671 name = xmlGetProp(node,
3689 3672 (xmlChar *)"name");
3690 3673 if (name != NULL &&
3691 3674 xmlStrcasecmp(name,
3692 3675 (xmlChar *)resource) == 0) {
3693 3676 xmlFree(name);
3694 3677 break;
3695 3678 }
3696 3679 xmlFree(name);
3697 3680 }
3698 3681 }
3699 3682 }
3700 3683 }
3701 3684 return ((sa_resource_t)node);
3702 3685 }
3703 3686
3704 3687 /*
3705 3688 * sa_get_next_resource(resource)
3706 3689 * Return the next share following the specified share
3707 3690 * from the internal list of shares. Returns NULL if there
3708 3691 * are no more shares. The list is relative to the same
3709 3692 * group.
3710 3693 */
3711 3694 sa_share_t
3712 3695 sa_get_next_resource(sa_resource_t resource)
3713 3696 {
3714 3697 xmlNodePtr node = NULL;
3715 3698
3716 3699 if (resource != NULL) {
3717 3700 for (node = ((xmlNodePtr)resource)->next; node != NULL;
3718 3701 node = node->next) {
3719 3702 if (xmlStrcmp(node->name, (xmlChar *)"resource") == 0)
3720 3703 break;
3721 3704 }
3722 3705 }
3723 3706 return ((sa_share_t)node);
3724 3707 }
3725 3708
3726 3709 /*
3727 3710 * _sa_get_next_resource_index(share)
3728 3711 *
3729 3712 * get the next resource index number (one greater then current largest)
3730 3713 */
3731 3714
3732 3715 static int
3733 3716 _sa_get_next_resource_index(sa_share_t share)
3734 3717 {
3735 3718 sa_resource_t resource;
3736 3719 int index = 0;
3737 3720 char *id;
3738 3721
3739 3722 for (resource = sa_get_share_resource(share, NULL);
3740 3723 resource != NULL;
3741 3724 resource = sa_get_next_resource(resource)) {
3742 3725 id = get_node_attr((void *)resource, "id");
3743 3726 if (id != NULL) {
3744 3727 int val;
3745 3728 val = atoi(id);
3746 3729 if (val > index)
3747 3730 index = val;
3748 3731 sa_free_attr_string(id);
3749 3732 }
3750 3733 }
3751 3734 return (index + 1);
3752 3735 }
3753 3736
3754 3737
3755 3738 /*
3756 3739 * sa_add_resource(share, resource, persist, &err)
3757 3740 *
3758 3741 * Adds a new resource name associated with share. The resource name
3759 3742 * must be unique in the system and will be case insensitive (eventually).
3760 3743 */
3761 3744
3762 3745 sa_resource_t
3763 3746 sa_add_resource(sa_share_t share, char *resource, int persist, int *error)
3764 3747 {
3765 3748 xmlNodePtr node;
3766 3749 int err = SA_OK;
3767 3750 sa_resource_t res;
3768 3751 sa_group_t group;
3769 3752 sa_handle_t handle;
3770 3753 char istring[8]; /* just big enough for an integer value */
3771 3754 int index;
3772 3755
3773 3756 group = sa_get_parent_group(share);
3774 3757 handle = sa_find_group_handle(group);
3775 3758 res = sa_find_resource(handle, resource);
3776 3759 if (res != NULL) {
3777 3760 err = SA_DUPLICATE_NAME;
3778 3761 res = NULL;
3779 3762 } else {
3780 3763 node = xmlNewChild((xmlNodePtr)share, NULL,
3781 3764 (xmlChar *)"resource", NULL);
3782 3765 if (node != NULL) {
3783 3766 (void) xmlSetProp(node, (xmlChar *)"name",
3784 3767 (xmlChar *)resource);
3785 3768 (void) xmlSetProp(node, (xmlChar *)"type", persist ?
3786 3769 (xmlChar *)"persist" : (xmlChar *)"transient");
3787 3770 if (persist != SA_SHARE_TRANSIENT) {
3788 3771 index = _sa_get_next_resource_index(share);
↓ open down ↓ |
478 lines elided |
↑ open up ↑ |
3789 3772 (void) snprintf(istring, sizeof (istring), "%d",
3790 3773 index);
3791 3774 (void) xmlSetProp(node, (xmlChar *)"id",
3792 3775 (xmlChar *)istring);
3793 3776
3794 3777 if (!sa_is_persistent((sa_group_t)share))
3795 3778 goto done;
3796 3779
3797 3780 if (!sa_group_is_zfs(group)) {
3798 3781 /* ZFS doesn't use resource names */
3799 - sa_handle_impl_t ihandle;
3782 + sa_handle_t handle;
3800 3783
3801 - ihandle = (sa_handle_impl_t)
3802 - sa_find_group_handle(
3784 + handle = sa_find_group_handle(
3803 3785 group);
3804 - if (ihandle != NULL)
3786 + if (handle != NULL)
3805 3787 err = sa_commit_share(
3806 - ihandle->scfhandle, group,
3788 + handle->scfhandle, group,
3807 3789 share);
3808 3790 else
3809 3791 err = SA_SYSTEM_ERR;
3810 3792 } else {
3811 3793 err = sa_zfs_update((sa_share_t)group);
3812 3794 }
3813 3795 }
3814 3796 }
3815 3797 }
3816 3798 done:
3817 3799 if (error != NULL)
3818 3800 *error = err;
3819 3801 return ((sa_resource_t)node);
3820 3802 }
3821 3803
3822 3804 /*
3823 3805 * sa_remove_resource(resource)
3824 3806 *
3825 3807 * Remove the resource name from the share (and the system)
3826 3808 */
3827 3809
3828 3810 int
3829 3811 sa_remove_resource(sa_resource_t resource)
3830 3812 {
3831 3813 sa_share_t share;
3832 3814 sa_group_t group;
3833 3815 char *type;
3834 3816 int ret = SA_OK;
3835 3817 boolean_t transient = B_FALSE;
3836 3818 sa_optionset_t opt;
3837 3819
3838 3820 share = sa_get_resource_parent(resource);
3839 3821 type = sa_get_share_attr(share, "type");
3840 3822 group = sa_get_parent_group(share);
3841 3823
3842 3824
3843 3825 if (type != NULL) {
3844 3826 if (strcmp(type, "persist") != 0)
3845 3827 transient = B_TRUE;
3846 3828 sa_free_attr_string(type);
3847 3829 }
3848 3830
3849 3831 /* Disable the resource for all protocols. */
3850 3832 (void) sa_disable_resource(resource, NULL);
3851 3833
3852 3834 /* Remove any optionsets from the resource. */
3853 3835 for (opt = sa_get_optionset(resource, NULL);
3854 3836 opt != NULL;
3855 3837 opt = sa_get_next_optionset(opt))
3856 3838 (void) sa_destroy_optionset(opt);
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
3857 3839
3858 3840 /* Remove from the share */
3859 3841 xmlUnlinkNode((xmlNode *)resource);
3860 3842 xmlFreeNode((xmlNode *)resource);
3861 3843
3862 3844 /* only do SMF action if permanent and not ZFS */
3863 3845 if (transient)
3864 3846 return (ret);
3865 3847
3866 3848 if (!sa_group_is_zfs(group)) {
3867 - sa_handle_impl_t ihandle;
3868 - ihandle = (sa_handle_impl_t)sa_find_group_handle(group);
3869 - if (ihandle != NULL)
3870 - ret = sa_commit_share(ihandle->scfhandle, group, share);
3849 + sa_handle_t handle = sa_find_group_handle(group);
3850 + if (handle != NULL)
3851 + ret = sa_commit_share(handle->scfhandle, group, share);
3871 3852 else
3872 3853 ret = SA_SYSTEM_ERR;
3873 3854 } else {
3874 3855 ret = sa_zfs_update((sa_share_t)group);
3875 3856 }
3876 3857
3877 3858 return (ret);
3878 3859 }
3879 3860
3880 3861 /*
3881 3862 * proto_rename_resource(handle, group, resource, newname)
3882 3863 *
3883 3864 * Helper function for sa_rename_resource that notifies the protocol
3884 3865 * of a resource name change prior to a config repository update.
3885 3866 */
3886 3867 static int
3887 3868 proto_rename_resource(sa_handle_t handle, sa_group_t group,
3888 3869 sa_resource_t resource, char *newname)
3889 3870 {
3890 3871 sa_optionset_t optionset;
3891 3872 int ret = SA_OK;
3892 3873 int err;
3893 3874
3894 3875 for (optionset = sa_get_optionset(group, NULL);
3895 3876 optionset != NULL;
3896 3877 optionset = sa_get_next_optionset(optionset)) {
3897 3878 char *type;
3898 3879 type = sa_get_optionset_attr(optionset, "type");
3899 3880 if (type != NULL) {
3900 3881 err = sa_proto_rename_resource(handle, type, resource,
3901 3882 newname);
3902 3883 if (err != SA_OK)
3903 3884 ret = err;
3904 3885 sa_free_attr_string(type);
3905 3886 }
3906 3887 }
3907 3888 return (ret);
3908 3889 }
3909 3890
3910 3891 /*
3911 3892 * sa_rename_resource(resource, newname)
3912 3893 *
3913 3894 * Rename the resource to the new name, if it is unique.
3914 3895 */
3915 3896
3916 3897 int
3917 3898 sa_rename_resource(sa_resource_t resource, char *newname)
3918 3899 {
3919 3900 sa_share_t share;
3920 3901 sa_group_t group = NULL;
3921 3902 sa_resource_t target;
3922 3903 int ret = SA_CONFIG_ERR;
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
3923 3904 sa_handle_t handle = NULL;
3924 3905
3925 3906 share = sa_get_resource_parent(resource);
3926 3907 if (share == NULL)
3927 3908 return (ret);
3928 3909
3929 3910 group = sa_get_parent_group(share);
3930 3911 if (group == NULL)
3931 3912 return (ret);
3932 3913
3933 - handle = (sa_handle_impl_t)sa_find_group_handle(group);
3914 + handle = sa_find_group_handle(group);
3934 3915 if (handle == NULL)
3935 3916 return (ret);
3936 3917
3937 3918 target = sa_find_resource(handle, newname);
3938 3919 if (target != NULL) {
3939 3920 ret = SA_DUPLICATE_NAME;
3940 3921 } else {
3941 3922 /*
3942 3923 * Everything appears to be valid at this
3943 3924 * point. Change the name of the active share and then
3944 3925 * update the share in the appropriate repository.
3945 3926 */
3946 3927 ret = proto_rename_resource(handle, group, resource, newname);
3947 3928 set_node_attr(resource, "name", newname);
3948 3929
3949 3930 if (!sa_is_persistent((sa_group_t)share))
3950 3931 return (ret);
3951 3932
3952 3933 if (!sa_group_is_zfs(group)) {
3953 - sa_handle_impl_t ihandle = (sa_handle_impl_t)handle;
3954 - ret = sa_commit_share(ihandle->scfhandle, group,
3934 + ret = sa_commit_share(handle->scfhandle, group,
3955 3935 share);
3956 3936 } else {
3957 3937 ret = sa_zfs_update((sa_share_t)group);
3958 3938 }
3959 3939 }
3960 3940 return (ret);
3961 3941 }
3962 3942
3963 3943 /*
3964 3944 * sa_get_resource_attr(resource, tag)
3965 3945 *
3966 3946 * Get the named attribute of the resource. "name" and "id" are
3967 3947 * currently defined. NULL if tag not defined.
3968 3948 */
3969 3949
3970 3950 char *
3971 3951 sa_get_resource_attr(sa_resource_t resource, char *tag)
3972 3952 {
3973 3953 return (get_node_attr((void *)resource, tag));
3974 3954 }
3975 3955
3976 3956 /*
3977 3957 * sa_set_resource_attr(resource, tag, value)
3978 3958 *
3979 3959 * Get the named attribute of the resource. "name" and "id" are
3980 3960 * currently defined. NULL if tag not defined. Currently we don't do
3981 3961 * much, but additional checking may be needed in the future.
3982 3962 */
3983 3963
3984 3964 int
3985 3965 sa_set_resource_attr(sa_resource_t resource, char *tag, char *value)
3986 3966 {
3987 3967 set_node_attr((void *)resource, tag, value);
3988 3968 return (SA_OK);
3989 3969 }
3990 3970
3991 3971 /*
3992 3972 * sa_get_resource_parent(resource_t)
3993 3973 *
3994 3974 * Returns the share associated with the resource.
3995 3975 */
3996 3976
3997 3977 sa_share_t
3998 3978 sa_get_resource_parent(sa_resource_t resource)
3999 3979 {
4000 3980 sa_share_t share = NULL;
4001 3981
4002 3982 if (resource != NULL)
4003 3983 share = (sa_share_t)((xmlNodePtr)resource)->parent;
4004 3984 return (share);
4005 3985 }
4006 3986
4007 3987 /*
4008 3988 * find_resource(group, name)
4009 3989 *
4010 3990 * Find the resource within the group.
4011 3991 */
4012 3992
4013 3993 static sa_resource_t
4014 3994 find_resource(sa_group_t group, char *resname)
4015 3995 {
4016 3996 sa_share_t share;
4017 3997 sa_resource_t resource = NULL;
4018 3998 char *name;
4019 3999
4020 4000 /* Iterate over all the shares and resources in the group. */
4021 4001 for (share = sa_get_share(group, NULL);
4022 4002 share != NULL && resource == NULL;
4023 4003 share = sa_get_next_share(share)) {
4024 4004 for (resource = sa_get_share_resource(share, NULL);
4025 4005 resource != NULL;
4026 4006 resource = sa_get_next_resource(resource)) {
4027 4007 name = sa_get_resource_attr(resource, "name");
4028 4008 if (name != NULL && xmlStrcasecmp((xmlChar*)name,
4029 4009 (xmlChar*)resname) == 0) {
4030 4010 sa_free_attr_string(name);
4031 4011 break;
4032 4012 }
4033 4013 if (name != NULL) {
4034 4014 sa_free_attr_string(name);
4035 4015 }
4036 4016 }
4037 4017 }
4038 4018 return (resource);
4039 4019 }
4040 4020
4041 4021 /*
4042 4022 * sa_find_resource(name)
4043 4023 *
4044 4024 * Find the named resource in the system.
4045 4025 */
4046 4026
4047 4027 sa_resource_t
4048 4028 sa_find_resource(sa_handle_t handle, char *name)
4049 4029 {
4050 4030 sa_group_t group;
4051 4031 sa_group_t zgroup;
4052 4032 sa_resource_t resource = NULL;
4053 4033
4054 4034 /*
4055 4035 * Iterate over all groups and zfs subgroups and check for
4056 4036 * resource name in them.
4057 4037 */
4058 4038 for (group = sa_get_group(handle, NULL); group != NULL;
4059 4039 group = sa_get_next_group(group)) {
4060 4040
4061 4041 if (is_zfs_group(group)) {
4062 4042 for (zgroup =
4063 4043 (sa_group_t)_sa_get_child_node((xmlNodePtr)group,
4064 4044 (xmlChar *)"group");
4065 4045 zgroup != NULL && resource == NULL;
4066 4046 zgroup = sa_get_next_group(zgroup)) {
4067 4047 resource = find_resource(zgroup, name);
4068 4048 }
4069 4049 } else {
4070 4050 resource = find_resource(group, name);
4071 4051 }
4072 4052 if (resource != NULL)
4073 4053 break;
4074 4054 }
4075 4055 return (resource);
4076 4056 }
4077 4057
4078 4058 /*
4079 4059 * sa_get_resource(group, resource)
4080 4060 *
4081 4061 * Search all the shares in the specified group for a share with a
4082 4062 * resource name matching the one specified.
4083 4063 *
4084 4064 * In the future, it may be advantageous to allow group to be NULL and
4085 4065 * search all groups but that isn't needed at present.
4086 4066 */
4087 4067
4088 4068 sa_resource_t
4089 4069 sa_get_resource(sa_group_t group, char *resource)
4090 4070 {
4091 4071 sa_share_t share = NULL;
4092 4072 sa_resource_t res = NULL;
4093 4073
4094 4074 if (resource != NULL) {
4095 4075 for (share = sa_get_share(group, NULL);
4096 4076 share != NULL && res == NULL;
4097 4077 share = sa_get_next_share(share)) {
4098 4078 res = sa_get_share_resource(share, resource);
4099 4079 }
4100 4080 }
4101 4081 return (res);
4102 4082 }
4103 4083
4104 4084 /*
4105 4085 * get_protocol_list(optionset, object)
4106 4086 *
4107 4087 * Get the protocol optionset list for the object and add them as
4108 4088 * properties to optionset.
4109 4089 */
4110 4090 static int
4111 4091 get_protocol_list(sa_optionset_t optionset, void *object)
4112 4092 {
4113 4093 sa_property_t prop;
4114 4094 sa_optionset_t opts;
4115 4095 int ret = SA_OK;
4116 4096
4117 4097 for (opts = sa_get_optionset(object, NULL);
4118 4098 opts != NULL;
4119 4099 opts = sa_get_next_optionset(opts)) {
4120 4100 char *type;
4121 4101 type = sa_get_optionset_attr(opts, "type");
4122 4102 /*
4123 4103 * It is possible to have a non-protocol optionset. We
4124 4104 * skip any of those found.
4125 4105 */
4126 4106 if (type == NULL)
4127 4107 continue;
4128 4108 prop = sa_create_property(type, "true");
4129 4109 sa_free_attr_string(type);
4130 4110 if (prop != NULL)
4131 4111 prop = (sa_property_t)xmlAddChild((xmlNodePtr)optionset,
4132 4112 (xmlNodePtr)prop);
4133 4113 /* If prop is NULL, don't bother continuing */
4134 4114 if (prop == NULL) {
4135 4115 ret = SA_NO_MEMORY;
4136 4116 break;
4137 4117 }
4138 4118 }
4139 4119 return (ret);
4140 4120 }
4141 4121
4142 4122 /*
4143 4123 * sa_free_protoset(optionset)
4144 4124 *
4145 4125 * Free the protocol property optionset.
4146 4126 */
4147 4127 static void
4148 4128 sa_free_protoset(sa_optionset_t optionset)
4149 4129 {
4150 4130 if (optionset != NULL) {
4151 4131 xmlUnlinkNode((xmlNodePtr) optionset);
4152 4132 xmlFreeNode((xmlNodePtr) optionset);
4153 4133 }
4154 4134 }
4155 4135
4156 4136 /*
4157 4137 * sa_optionset_t sa_get_active_protocols(object)
4158 4138 *
4159 4139 * Return a list of the protocols that are active for the object.
4160 4140 * This is currently an internal helper function, but could be
4161 4141 * made visible if there is enough demand for it.
4162 4142 *
4163 4143 * The function finds the parent group and extracts the protocol
4164 4144 * optionsets creating a new optionset with the protocols as properties.
4165 4145 *
4166 4146 * The caller must free the returned optionset.
4167 4147 */
4168 4148
4169 4149 static sa_optionset_t
4170 4150 sa_get_active_protocols(void *object)
4171 4151 {
4172 4152 sa_optionset_t options;
4173 4153 sa_share_t share = NULL;
4174 4154 sa_group_t group = NULL;
4175 4155 sa_resource_t resource = NULL;
4176 4156 int ret = SA_OK;
4177 4157
4178 4158 if (object == NULL)
4179 4159 return (NULL);
4180 4160 options = (sa_optionset_t)xmlNewNode(NULL, (xmlChar *)"optionset");
4181 4161 if (options == NULL)
4182 4162 return (NULL);
4183 4163
4184 4164 /*
4185 4165 * Find the objects up the tree that might have protocols
4186 4166 * enabled on them.
4187 4167 */
4188 4168 if (sa_is_resource(object)) {
4189 4169 resource = (sa_resource_t)object;
4190 4170 share = sa_get_resource_parent(resource);
4191 4171 group = sa_get_parent_group(share);
4192 4172 } else if (sa_is_share(object)) {
4193 4173 share = (sa_share_t)object;
4194 4174 group = sa_get_parent_group(share);
4195 4175 } else {
4196 4176 group = (sa_group_t)group;
4197 4177 }
4198 4178 if (resource != NULL)
4199 4179 ret = get_protocol_list(options, resource);
4200 4180 if (ret == SA_OK && share != NULL)
4201 4181 ret = get_protocol_list(options, share);
4202 4182 if (ret == SA_OK && group != NULL)
4203 4183 ret = get_protocol_list(options, group);
4204 4184
4205 4185 /*
4206 4186 * If there was an error, we won't have a complete list so
4207 4187 * abandon everything. The caller will have to deal with the
4208 4188 * issue.
4209 4189 */
4210 4190 if (ret != SA_OK) {
4211 4191 sa_free_protoset(options);
4212 4192 options = NULL;
4213 4193 }
4214 4194 return (options);
4215 4195 }
4216 4196
4217 4197 /*
4218 4198 * sa_enable_resource, protocol)
4219 4199 * Disable the specified share to the specified protocol.
4220 4200 * If protocol is NULL, then all protocols.
4221 4201 */
4222 4202 int
4223 4203 sa_enable_resource(sa_resource_t resource, char *protocol)
4224 4204 {
4225 4205 int ret = SA_OK;
4226 4206
4227 4207 if (protocol != NULL) {
4228 4208 ret = sa_proto_share_resource(protocol, resource);
4229 4209 } else {
4230 4210 sa_optionset_t protoset;
4231 4211 sa_property_t prop;
4232 4212 char *proto;
4233 4213 int err;
4234 4214
4235 4215 /* need to do all protocols */
4236 4216 protoset = sa_get_active_protocols(resource);
4237 4217 if (protoset == NULL)
4238 4218 return (SA_NO_MEMORY);
4239 4219 for (prop = sa_get_property(protoset, NULL);
4240 4220 prop != NULL;
4241 4221 prop = sa_get_next_property(prop)) {
4242 4222 proto = sa_get_property_attr(prop, "type");
4243 4223 if (proto == NULL) {
4244 4224 ret = SA_NO_MEMORY;
4245 4225 continue;
4246 4226 }
4247 4227 err = sa_proto_share_resource(proto, resource);
4248 4228 if (err != SA_OK)
4249 4229 ret = err;
4250 4230 sa_free_attr_string(proto);
4251 4231 }
4252 4232 sa_free_protoset(protoset);
4253 4233 }
4254 4234 if (ret == SA_OK)
4255 4235 (void) sa_set_resource_attr(resource, "shared", NULL);
4256 4236
4257 4237 return (ret);
4258 4238 }
4259 4239
4260 4240 /*
4261 4241 * sa_disable_resource(resource, protocol)
4262 4242 *
4263 4243 * Disable the specified share for the specified protocol. If
4264 4244 * protocol is NULL, then all protocols. If the underlying
4265 4245 * protocol doesn't implement disable at the resource level, we
4266 4246 * disable at the share level.
4267 4247 */
4268 4248 int
4269 4249 sa_disable_resource(sa_resource_t resource, char *protocol)
4270 4250 {
4271 4251 int ret = SA_OK;
4272 4252
4273 4253 if (protocol != NULL) {
4274 4254 ret = sa_proto_unshare_resource(protocol, resource);
4275 4255 if (ret == SA_NOT_IMPLEMENTED) {
4276 4256 sa_share_t parent;
4277 4257 /*
4278 4258 * The protocol doesn't implement unshare
4279 4259 * resource. That implies that resource names are
4280 4260 * simple aliases for this protocol so we need to
4281 4261 * unshare the share.
4282 4262 */
4283 4263 parent = sa_get_resource_parent(resource);
4284 4264 if (parent != NULL)
4285 4265 ret = sa_disable_share(parent, protocol);
4286 4266 else
4287 4267 ret = SA_CONFIG_ERR;
4288 4268 }
4289 4269 } else {
4290 4270 sa_optionset_t protoset;
4291 4271 sa_property_t prop;
4292 4272 char *proto;
4293 4273 int err;
4294 4274
4295 4275 /* need to do all protocols */
4296 4276 protoset = sa_get_active_protocols(resource);
4297 4277 if (protoset == NULL)
4298 4278 return (SA_NO_MEMORY);
4299 4279 for (prop = sa_get_property(protoset, NULL);
4300 4280 prop != NULL;
4301 4281 prop = sa_get_next_property(prop)) {
4302 4282 proto = sa_get_property_attr(prop, "type");
4303 4283 if (proto == NULL) {
4304 4284 ret = SA_NO_MEMORY;
4305 4285 continue;
4306 4286 }
4307 4287 err = sa_proto_unshare_resource(proto, resource);
4308 4288 if (err == SA_NOT_SUPPORTED) {
4309 4289 sa_share_t parent;
4310 4290 parent = sa_get_resource_parent(resource);
4311 4291 if (parent != NULL)
4312 4292 err = sa_disable_share(parent, proto);
4313 4293 else
4314 4294 err = SA_CONFIG_ERR;
4315 4295 }
4316 4296 if (err != SA_OK)
4317 4297 ret = err;
4318 4298 sa_free_attr_string(proto);
4319 4299 }
4320 4300 sa_free_protoset(protoset);
4321 4301 }
4322 4302 if (ret == SA_OK)
4323 4303 (void) sa_set_resource_attr(resource, "shared", NULL);
4324 4304
4325 4305 return (ret);
4326 4306 }
4327 4307
4328 4308 /*
4329 4309 * sa_set_resource_description(resource, content)
4330 4310 *
4331 4311 * Set the description of share to content.
4332 4312 */
4333 4313
4334 4314 int
4335 4315 sa_set_resource_description(sa_resource_t resource, char *content)
4336 4316 {
4337 4317 xmlNodePtr node;
4338 4318 sa_group_t group;
4339 4319 sa_share_t share;
4340 4320 int ret = SA_OK;
4341 4321
4342 4322 for (node = ((xmlNodePtr)resource)->children;
4343 4323 node != NULL;
4344 4324 node = node->next) {
4345 4325 if (xmlStrcmp(node->name, (xmlChar *)"description") == 0) {
4346 4326 break;
4347 4327 }
4348 4328 }
4349 4329
4350 4330 /* no existing description but want to add */
4351 4331 if (node == NULL && content != NULL) {
4352 4332 /* add a description */
4353 4333 node = _sa_set_share_description(resource, content);
4354 4334 } else if (node != NULL && content != NULL) {
4355 4335 /* update a description */
4356 4336 xmlNodeSetContent(node, (xmlChar *)content);
↓ open down ↓ |
392 lines elided |
↑ open up ↑ |
4357 4337 } else if (node != NULL && content == NULL) {
4358 4338 /* remove an existing description */
4359 4339 xmlUnlinkNode(node);
4360 4340 xmlFreeNode(node);
4361 4341 }
4362 4342
4363 4343 share = sa_get_resource_parent(resource);
4364 4344 group = sa_get_parent_group(share);
4365 4345 if (group != NULL &&
4366 4346 sa_is_persistent(share) && (!sa_group_is_zfs(group))) {
4367 - sa_handle_impl_t impl_handle;
4368 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
4369 - if (impl_handle != NULL)
4370 - ret = sa_commit_share(impl_handle->scfhandle,
4347 + sa_handle_t handle = sa_find_group_handle(group);
4348 + if (handle != NULL)
4349 + ret = sa_commit_share(handle->scfhandle,
4371 4350 group, share);
4372 4351 else
4373 4352 ret = SA_SYSTEM_ERR;
4374 4353 }
4375 4354 return (ret);
4376 4355 }
4377 4356
4378 4357 /*
4379 4358 * sa_get_resource_description(share)
4380 4359 *
4381 4360 * Return the description text for the specified share if it
4382 4361 * exists. NULL if no description exists.
4383 4362 */
4384 4363
4385 4364 char *
4386 4365 sa_get_resource_description(sa_resource_t resource)
4387 4366 {
4388 4367 xmlChar *description = NULL;
4389 4368 xmlNodePtr node;
4390 4369
4391 4370 for (node = ((xmlNodePtr)resource)->children; node != NULL;
4392 4371 node = node->next) {
4393 4372 if (xmlStrcmp(node->name, (xmlChar *)"description") == 0)
4394 4373 break;
4395 4374 }
4396 4375 if (node != NULL) {
4397 4376 description = xmlNodeGetContent(node);
4398 4377 fixproblemchars((char *)description);
4399 4378 }
4400 4379 return ((char *)description);
4401 4380 }
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX