Print this page
4095 minor cleanup up libshare
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libshare/common/libshare_zfs.c
+++ new/usr/src/lib/libshare/common/libshare_zfs.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 - */
25 -/*
26 24 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright (c) 2013 RackTop Systems.
27 26 */
28 27
29 28 #include <stdio.h>
30 29 #include <libzfs.h>
31 30 #include <string.h>
32 31 #include <strings.h>
33 32 #include <errno.h>
34 33 #include <libshare.h>
35 34 #include "libshare_impl.h"
36 35 #include <libintl.h>
37 36 #include <sys/mnttab.h>
38 37 #include <sys/mntent.h>
39 38
40 39 extern sa_share_t _sa_add_share(sa_group_t, char *, int, int *, uint64_t);
41 40 extern sa_group_t _sa_create_zfs_group(sa_group_t, char *);
42 41 extern char *sa_fstype(char *);
43 42 extern void set_node_attr(void *, char *, char *);
44 -extern int sa_is_share(void *);
43 +extern boolean_t sa_is_share(void *);
45 44 extern void sa_update_sharetab_ts(sa_handle_t);
46 45
47 46 /*
48 47 * File system specific code for ZFS. The original code was stolen
49 48 * from the "zfs" command and modified to better suit this library's
50 49 * usage.
51 50 */
52 51
53 52 typedef struct get_all_cbdata {
54 53 zfs_handle_t **cb_handles;
55 54 size_t cb_alloc;
56 55 size_t cb_used;
57 56 uint_t cb_types;
58 57 } get_all_cbdata_t;
59 58
60 59 /*
61 - * sa_zfs_init(impl_handle)
60 + * sa_zfs_init(handle)
62 61 *
63 62 * Initialize an access handle into libzfs. The handle needs to stay
64 63 * around until sa_zfs_fini() in order to maintain the cache of
65 64 * mounts.
66 65 */
67 66
68 67 int
69 -sa_zfs_init(sa_handle_impl_t impl_handle)
68 +sa_zfs_init(sa_handle_t handle)
70 69 {
71 - impl_handle->zfs_libhandle = libzfs_init();
72 - if (impl_handle->zfs_libhandle != NULL) {
73 - libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE);
70 + handle->zfs_libhandle = libzfs_init();
71 + if (handle->zfs_libhandle != NULL) {
72 + libzfs_print_on_error(handle->zfs_libhandle, B_TRUE);
74 73 return (B_TRUE);
75 74 }
76 75 return (B_FALSE);
77 76 }
78 77
79 78 /*
80 - * sa_zfs_fini(impl_handle)
79 + * sa_zfs_fini(handle)
81 80 *
82 81 * cleanup data structures and the libzfs handle used for accessing
83 82 * zfs file share info.
84 83 */
85 84
86 85 void
87 -sa_zfs_fini(sa_handle_impl_t impl_handle)
86 +sa_zfs_fini(sa_handle_t handle)
88 87 {
89 - if (impl_handle->zfs_libhandle != NULL) {
90 - if (impl_handle->zfs_list != NULL) {
91 - zfs_handle_t **zhp = impl_handle->zfs_list;
88 + if (handle->zfs_libhandle != NULL) {
89 + if (handle->zfs_list != NULL) {
90 + zfs_handle_t **zhp = handle->zfs_list;
92 91 size_t i;
93 92
94 93 /*
95 94 * Contents of zfs_list need to be freed so we
96 95 * don't lose ZFS handles.
97 96 */
98 - for (i = 0; i < impl_handle->zfs_list_count; i++) {
97 + for (i = 0; i < handle->zfs_list_count; i++) {
99 98 zfs_close(zhp[i]);
100 99 }
101 - free(impl_handle->zfs_list);
102 - impl_handle->zfs_list = NULL;
103 - impl_handle->zfs_list_count = 0;
100 + free(handle->zfs_list);
101 + handle->zfs_list = NULL;
102 + handle->zfs_list_count = 0;
104 103 }
105 104
106 - libzfs_fini(impl_handle->zfs_libhandle);
107 - impl_handle->zfs_libhandle = NULL;
105 + libzfs_fini(handle->zfs_libhandle);
106 + handle->zfs_libhandle = NULL;
108 107 }
109 108 }
110 109
111 110 /*
112 111 * get_one_filesystem(zfs_handle_t, data)
113 112 *
114 113 * an iterator function called while iterating through the ZFS
115 114 * root. It accumulates into an array of file system handles that can
116 115 * be used to derive info about those file systems.
117 116 *
118 117 * Note that as this function is called, we close all zhp handles that
119 118 * are not going to be places into the cp_handles list. We don't want
120 119 * to close the ones we are keeping, but all others would be leaked if
121 120 * not closed here.
122 121 */
123 122
124 123 static int
125 124 get_one_filesystem(zfs_handle_t *zhp, void *data)
126 125 {
127 126 get_all_cbdata_t *cbp = data;
128 127 zfs_type_t type = zfs_get_type(zhp);
129 128
130 129 /*
131 130 * Interate over any nested datasets.
132 131 */
133 132 if (type == ZFS_TYPE_FILESYSTEM &&
134 133 zfs_iter_filesystems(zhp, get_one_filesystem, data) != 0) {
135 134 zfs_close(zhp);
136 135 return (1);
137 136 }
138 137
139 138 /*
140 139 * Skip any datasets whose type does not match.
141 140 */
142 141 if ((type & cbp->cb_types) == 0) {
143 142 zfs_close(zhp);
144 143 return (0);
145 144 }
146 145
147 146 if (cbp->cb_alloc == cbp->cb_used) {
148 147 zfs_handle_t **handles;
149 148
150 149 if (cbp->cb_alloc == 0)
151 150 cbp->cb_alloc = 64;
152 151 else
153 152 cbp->cb_alloc *= 2;
154 153
155 154 handles = (zfs_handle_t **)calloc(1,
156 155 cbp->cb_alloc * sizeof (void *));
157 156
158 157 if (handles == NULL) {
159 158 zfs_close(zhp);
160 159 return (0);
161 160 }
162 161 if (cbp->cb_handles) {
163 162 bcopy(cbp->cb_handles, handles,
164 163 cbp->cb_used * sizeof (void *));
165 164 free(cbp->cb_handles);
166 165 }
167 166
168 167 cbp->cb_handles = handles;
169 168 }
170 169
171 170 cbp->cb_handles[cbp->cb_used++] = zhp;
172 171
173 172 return (0);
174 173 }
175 174
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
176 175 /*
177 176 * get_all_filesystems(zfs_handle_t ***fslist, size_t *count)
178 177 *
179 178 * iterate through all ZFS file systems starting at the root. Returns
180 179 * a count and an array of handle pointers. Allocating is only done
181 180 * once. The caller does not need to free since it will be done at
182 181 * sa_zfs_fini() time.
183 182 */
184 183
185 184 static void
186 -get_all_filesystems(sa_handle_impl_t impl_handle,
185 +get_all_filesystems(sa_handle_t handle,
187 186 zfs_handle_t ***fslist, size_t *count)
188 187 {
189 188 get_all_cbdata_t cb = { 0 };
190 189 cb.cb_types = ZFS_TYPE_FILESYSTEM;
191 190
192 - if (impl_handle->zfs_list != NULL) {
193 - *fslist = impl_handle->zfs_list;
194 - *count = impl_handle->zfs_list_count;
191 + if (handle->zfs_list != NULL) {
192 + *fslist = handle->zfs_list;
193 + *count = handle->zfs_list_count;
195 194 return;
196 195 }
197 196
198 - (void) zfs_iter_root(impl_handle->zfs_libhandle,
197 + (void) zfs_iter_root(handle->zfs_libhandle,
199 198 get_one_filesystem, &cb);
200 199
201 - impl_handle->zfs_list = *fslist = cb.cb_handles;
202 - impl_handle->zfs_list_count = *count = cb.cb_used;
200 + handle->zfs_list = *fslist = cb.cb_handles;
201 + handle->zfs_list_count = *count = cb.cb_used;
203 202 }
204 203
205 204 /*
206 205 * mountpoint_compare(a, b)
207 206 *
208 207 * compares the mountpoint on two zfs file systems handles.
209 208 * returns values following strcmp() model.
210 209 */
211 210
212 211 static int
213 212 mountpoint_compare(const void *a, const void *b)
214 213 {
215 214 zfs_handle_t **za = (zfs_handle_t **)a;
216 215 zfs_handle_t **zb = (zfs_handle_t **)b;
217 216 char mounta[MAXPATHLEN];
218 217 char mountb[MAXPATHLEN];
219 218
220 219 verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
221 220 sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
222 221 verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
223 222 sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
224 223
225 224 return (strcmp(mounta, mountb));
226 225 }
227 226
228 227 /*
229 228 * return legacy mountpoint. Caller provides space for mountpoint and
230 229 * dataset.
231 230 */
232 231 int
233 232 get_legacy_mountpoint(char *path, char *dataset, size_t dlen,
234 233 char *mountpoint, size_t mlen)
235 234 {
236 235 FILE *fp;
237 236 struct mnttab entry;
238 237
239 238 if ((fp = fopen(MNTTAB, "r")) == NULL) {
240 239 return (1);
241 240 }
242 241
243 242 while (getmntent(fp, &entry) == 0) {
244 243
245 244 if (entry.mnt_fstype == NULL ||
246 245 strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
247 246 continue;
248 247
249 248 if (strcmp(entry.mnt_mountp, path) == 0) {
250 249 if (mlen > 0)
251 250 (void) strlcpy(mountpoint, entry.mnt_mountp,
252 251 mlen);
253 252 if (dlen > 0)
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
254 253 (void) strlcpy(dataset, entry.mnt_special,
255 254 dlen);
256 255 break;
257 256 }
258 257 }
259 258 (void) fclose(fp);
260 259 return (1);
261 260 }
262 261
263 262 /*
264 - * get_zfs_dataset(impl_handle, path)
263 + * get_zfs_dataset(handle, path)
265 264 *
266 265 * get the name of the ZFS dataset the path is equivalent to. The
267 266 * dataset name is used for get/set of ZFS properties since libzfs
268 267 * requires a dataset to do a zfs_open().
269 268 */
270 269
271 270 static char *
272 -get_zfs_dataset(sa_handle_impl_t impl_handle, char *path,
271 +get_zfs_dataset(sa_handle_t handle, char *path,
273 272 boolean_t search_mnttab)
274 273 {
275 274 size_t i, count = 0;
276 275 char *dataset = NULL;
277 276 zfs_handle_t **zlist;
278 277 char mountpoint[ZFS_MAXPROPLEN];
279 278 char canmount[ZFS_MAXPROPLEN];
280 279
281 - get_all_filesystems(impl_handle, &zlist, &count);
280 + get_all_filesystems(handle, &zlist, &count);
282 281 qsort(zlist, count, sizeof (void *), mountpoint_compare);
283 282 for (i = 0; i < count; i++) {
284 283 /* must have a mountpoint */
285 284 if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT, mountpoint,
286 285 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) {
287 286 /* no mountpoint */
288 287 continue;
289 288 }
290 289
291 290 /* mountpoint must be a path */
292 291 if (strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) == 0 ||
293 292 strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
294 293 /*
295 294 * Search mmttab for mountpoint and get dataset.
296 295 */
297 296
298 297 if (search_mnttab == B_TRUE &&
299 298 get_legacy_mountpoint(path, mountpoint,
300 299 sizeof (mountpoint), NULL, 0) == 0) {
301 300 dataset = mountpoint;
302 301 break;
303 302 }
304 303 continue;
305 304 }
306 305
307 306 /* canmount must be set */
308 307 canmount[0] = '\0';
309 308 if (zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount,
310 309 sizeof (canmount), NULL, NULL, 0, B_FALSE) != 0 ||
311 310 strcmp(canmount, "off") == 0)
312 311 continue;
313 312
314 313 /*
315 314 * have a mountable handle but want to skip those marked none
316 315 * and legacy
317 316 */
318 317 if (strcmp(mountpoint, path) == 0) {
319 318 dataset = (char *)zfs_get_name(zlist[i]);
320 319 break;
321 320 }
322 321
323 322 }
324 323
325 324 if (dataset != NULL)
326 325 dataset = strdup(dataset);
327 326
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
328 327 return (dataset);
329 328 }
330 329
331 330 /*
332 331 * get_zfs_property(dataset, property)
333 332 *
334 333 * Get the file system property specified from the ZFS dataset.
335 334 */
336 335
337 336 static char *
338 -get_zfs_property(char *dataset, zfs_prop_t property)
337 +get_zfs_property(sa_handle_t handle, char *dataset, zfs_prop_t property)
339 338 {
340 - zfs_handle_t *handle = NULL;
339 + zfs_handle_t *z_fs;
341 340 char shareopts[ZFS_MAXPROPLEN];
342 - libzfs_handle_t *libhandle;
343 341
344 - libhandle = libzfs_init();
345 - if (libhandle != NULL) {
346 - handle = zfs_open(libhandle, dataset, ZFS_TYPE_FILESYSTEM);
347 - if (handle != NULL) {
348 - if (zfs_prop_get(handle, property, shareopts,
349 - sizeof (shareopts), NULL, NULL, 0,
350 - B_FALSE) == 0) {
351 - zfs_close(handle);
352 - libzfs_fini(libhandle);
353 - return (strdup(shareopts));
354 - }
355 - zfs_close(handle);
342 + z_fs = zfs_open(handle->zfs_libhandle, dataset, ZFS_TYPE_FILESYSTEM);
343 + if (z_fs != NULL) {
344 + if (zfs_prop_get(z_fs, property, shareopts,
345 + sizeof (shareopts), NULL, NULL, 0,
346 + B_FALSE) == 0) {
347 + zfs_close(z_fs);
348 + return (strdup(shareopts));
356 349 }
357 - libzfs_fini(libhandle);
350 + zfs_close(z_fs);
358 351 }
359 352 return (NULL);
360 353 }
361 354
362 355 /*
363 356 * sa_zfs_is_shared(handle, path)
364 357 *
365 358 * Check to see if the ZFS path provided has the sharenfs option set
366 359 * or not.
367 360 */
368 361
369 -int
370 -sa_zfs_is_shared(sa_handle_t sahandle, char *path)
362 +boolean_t
363 +sa_zfs_is_shared(sa_handle_t handle, char *path)
371 364 {
372 - int ret = 0;
365 + int ret = B_FALSE;
373 366 char *dataset;
374 - zfs_handle_t *handle = NULL;
367 + zfs_handle_t *z_fs = NULL;
375 368 char shareopts[ZFS_MAXPROPLEN];
376 - libzfs_handle_t *libhandle;
377 369
378 - dataset = get_zfs_dataset((sa_handle_t)sahandle, path, B_FALSE);
370 + dataset = get_zfs_dataset(handle, path, B_FALSE);
379 371 if (dataset != NULL) {
380 - libhandle = libzfs_init();
381 - if (libhandle != NULL) {
382 - handle = zfs_open(libhandle, dataset,
383 - ZFS_TYPE_FILESYSTEM);
384 - if (handle != NULL) {
385 - if (zfs_prop_get(handle, ZFS_PROP_SHARENFS,
386 - shareopts, sizeof (shareopts), NULL, NULL,
387 - 0, B_FALSE) == 0 &&
388 - strcmp(shareopts, "off") != 0) {
389 - ret = 1; /* it is shared */
390 - }
391 - zfs_close(handle);
372 + z_fs = zfs_open(handle->zfs_libhandle, dataset,
373 + ZFS_TYPE_FILESYSTEM);
374 + if (z_fs != NULL) {
375 + if (zfs_prop_get(z_fs, ZFS_PROP_SHARENFS,
376 + shareopts, sizeof (shareopts), NULL, NULL,
377 + 0, B_FALSE) == 0 &&
378 + strcmp(shareopts, "off") != 0) {
379 + ret = B_TRUE; /* it is shared */
392 380 }
393 - libzfs_fini(libhandle);
381 + zfs_close(z_fs);
394 382 }
395 383 free(dataset);
396 384 }
397 385 return (ret);
398 386 }
399 387
400 388 /*
401 389 * find_or_create_group(handle, groupname, proto, *err)
402 390 *
403 391 * While walking the ZFS tree, we need to add shares to a defined
404 392 * group. If the group doesn't exist, create it first, making sure it
405 393 * is marked as a ZFS group.
406 394 *
407 395 * Note that all ZFS shares are in a subgroup of the top level group
408 396 * called "zfs".
409 397 */
410 398
411 399 static sa_group_t
412 400 find_or_create_group(sa_handle_t handle, char *groupname, char *proto, int *err)
413 401 {
414 402 sa_group_t group;
415 403 sa_optionset_t optionset;
416 404 int ret = SA_OK;
417 405
418 406 /*
419 407 * we check to see if the "zfs" group exists. Since this
420 408 * should be the top level group, we don't want the
421 409 * parent. This is to make sure the zfs group has been created
422 410 * and to created if it hasn't been.
423 411 */
424 412 group = sa_get_group(handle, groupname);
425 413 if (group == NULL) {
426 414 group = sa_create_group(handle, groupname, &ret);
427 415
428 416 /* make sure this is flagged as a ZFS group */
429 417 if (group != NULL)
430 418 ret = sa_set_group_attr(group, "zfs", "true");
431 419 }
432 420 if (group != NULL) {
433 421 if (proto != NULL) {
434 422 optionset = sa_get_optionset(group, proto);
435 423 if (optionset == NULL)
436 424 optionset = sa_create_optionset(group, proto);
437 425 }
438 426 }
439 427 if (err != NULL)
440 428 *err = ret;
441 429 return (group);
442 430 }
443 431
444 432 /*
445 433 * find_or_create_zfs_subgroup(groupname, optstring, *err)
446 434 *
447 435 * ZFS shares will be in a subgroup of the "zfs" master group. This
448 436 * function looks to see if the groupname exists and returns it if it
449 437 * does or else creates a new one with the specified name and returns
450 438 * that. The "zfs" group will exist before we get here, but we make
451 439 * sure just in case.
452 440 *
453 441 * err must be a valid pointer.
454 442 */
455 443
456 444 static sa_group_t
457 445 find_or_create_zfs_subgroup(sa_handle_t handle, char *groupname, char *proto,
458 446 char *optstring, int *err)
459 447 {
460 448 sa_group_t group = NULL;
461 449 sa_group_t zfs;
462 450 char *name;
463 451 char *options;
464 452
465 453 /* start with the top-level "zfs" group */
466 454 zfs = sa_get_group(handle, "zfs");
467 455 *err = SA_OK;
468 456 if (zfs != NULL) {
469 457 for (group = sa_get_sub_group(zfs); group != NULL;
470 458 group = sa_get_next_group(group)) {
471 459 name = sa_get_group_attr(group, "name");
472 460 if (name != NULL && strcmp(name, groupname) == 0) {
473 461 /* have the group so break out of here */
474 462 sa_free_attr_string(name);
475 463 break;
476 464 }
477 465 if (name != NULL)
478 466 sa_free_attr_string(name);
479 467 }
480 468
481 469 if (group == NULL) {
482 470 /*
483 471 * Need to create the sub-group since it doesn't exist
484 472 */
485 473 group = _sa_create_zfs_group(zfs, groupname);
486 474 if (group == NULL) {
487 475 *err = SA_NO_MEMORY;
488 476 return (NULL);
489 477 }
490 478 set_node_attr(group, "zfs", "true");
491 479 }
492 480 if (strcmp(optstring, "on") == 0)
493 481 optstring = "rw";
494 482 options = strdup(optstring);
495 483 if (options != NULL) {
496 484 *err = sa_parse_legacy_options(group, options,
497 485 proto);
498 486 /* If no optionset, add one. */
499 487 if (sa_get_optionset(group, proto) == NULL)
500 488 (void) sa_create_optionset(group, proto);
501 489
502 490 /*
503 491 * Do not forget to update an optionset of
504 492 * the parent group so that it contains
505 493 * all protocols its subgroups have.
506 494 */
507 495 if (sa_get_optionset(zfs, proto) == NULL)
508 496 (void) sa_create_optionset(zfs, proto);
509 497
510 498 free(options);
511 499 } else {
512 500 *err = SA_NO_MEMORY;
513 501 }
514 502 }
515 503 return (group);
516 504 }
517 505
518 506 /*
519 507 * zfs_construct_resource(share, name, base, dataset)
520 508 *
521 509 * Add a resource to the share using name as a template. If name ==
522 510 * NULL, then construct a name based on the dataset value.
523 511 * name.
524 512 */
525 513 static void
526 514 zfs_construct_resource(sa_share_t share, char *dataset)
527 515 {
528 516 char buff[SA_MAX_RESOURCE_NAME + 1];
529 517 int ret = SA_OK;
530 518
531 519 (void) snprintf(buff, SA_MAX_RESOURCE_NAME, "%s", dataset);
532 520 sa_fix_resource_name(buff);
533 521 (void) sa_add_resource(share, buff, SA_SHARE_TRANSIENT, &ret);
534 522 }
535 523
536 524 /*
537 525 * zfs_inherited(handle, source, sourcestr)
538 526 *
539 527 * handle case of inherited share{nfs,smb}. Pulled out of sa_get_zfs_shares
540 528 * for readability.
541 529 */
542 530 static int
543 531 zfs_inherited(sa_handle_t handle, sa_share_t share, char *sourcestr,
544 532 char *shareopts, char *mountpoint, char *proto, char *dataset)
545 533 {
546 534 int doshopt = 0;
547 535 int err = SA_OK;
548 536 sa_group_t group;
549 537 sa_resource_t resource;
550 538 uint64_t features;
551 539
552 540 /*
553 541 * Need to find the "real" parent sub-group. It may not be
554 542 * mounted, but it was identified in the "sourcestr"
555 543 * variable. The real parent not mounted can occur if
556 544 * "canmount=off and sharenfs=on".
557 545 */
558 546 group = find_or_create_zfs_subgroup(handle, sourcestr, proto,
559 547 shareopts, &doshopt);
560 548 if (group != NULL) {
561 549 /*
562 550 * We may need the first share for resource
563 551 * prototype. We only care about it if it has a
564 552 * resource that sets a prefix value.
565 553 */
566 554 if (share == NULL)
567 555 share = _sa_add_share(group, mountpoint,
568 556 SA_SHARE_TRANSIENT, &err,
569 557 (uint64_t)SA_FEATURE_NONE);
570 558 /*
571 559 * some options may only be on shares. If the opt
572 560 * string contains one of those, we put it just on the
573 561 * share.
574 562 */
575 563 if (share != NULL && doshopt == SA_PROP_SHARE_ONLY) {
576 564 char *options;
577 565 options = strdup(shareopts);
578 566 if (options != NULL) {
579 567 set_node_attr(share, "dataset", dataset);
580 568 err = sa_parse_legacy_options(share, options,
581 569 proto);
582 570 set_node_attr(share, "dataset", NULL);
583 571 free(options);
584 572 }
585 573 if (sa_get_optionset(group, proto) == NULL)
586 574 (void) sa_create_optionset(group, proto);
587 575 }
588 576 features = sa_proto_get_featureset(proto);
589 577 if (share != NULL && features & SA_FEATURE_RESOURCE) {
590 578 /*
591 579 * We have a share and the protocol requires
592 580 * that at least one resource exist (probably
593 581 * SMB). We need to make sure that there is at
594 582 * least one.
595 583 */
596 584 resource = sa_get_share_resource(share, NULL);
597 585 if (resource == NULL) {
598 586 zfs_construct_resource(share, dataset);
599 587 }
600 588 }
601 589 } else {
602 590 err = SA_NO_MEMORY;
603 591 }
604 592 return (err);
605 593 }
606 594
607 595 /*
608 596 * zfs_notinherited(group, share, mountpoint, shareopts, proto, dataset,
609 597 * grouperr)
610 598 *
611 599 * handle case where this is the top of a sub-group in ZFS. Pulled out
612 600 * of sa_get_zfs_shares for readability. We need the grouperr from the
613 601 * creation of the subgroup to know whether to add the public
614 602 * property, etc. to the specific share.
615 603 */
616 604 static int
617 605 zfs_notinherited(sa_group_t group, sa_share_t share, char *mountpoint,
618 606 char *shareopts, char *proto, char *dataset, int grouperr)
619 607 {
620 608 int err = SA_OK;
621 609 sa_resource_t resource;
622 610 uint64_t features;
623 611
624 612 set_node_attr(group, "zfs", "true");
625 613 if (share == NULL)
626 614 share = _sa_add_share(group, mountpoint, SA_SHARE_TRANSIENT,
627 615 &err, (uint64_t)SA_FEATURE_NONE);
628 616
629 617 if (err != SA_OK)
630 618 return (err);
631 619
632 620 if (strcmp(shareopts, "on") == 0)
633 621 shareopts = "";
634 622 if (shareopts != NULL) {
635 623 char *options;
636 624 if (grouperr == SA_PROP_SHARE_ONLY) {
637 625 /*
638 626 * Some properties may only be on shares, but
639 627 * due to the ZFS sub-groups being artificial,
640 628 * we sometimes get this and have to deal with
641 629 * it. We do it by attempting to put it on the
642 630 * share.
643 631 */
644 632 options = strdup(shareopts);
645 633 if (options != NULL) {
646 634 err = sa_parse_legacy_options(share,
647 635 options, proto);
648 636 free(options);
649 637 }
650 638 }
651 639 /* Unmark the share's changed state */
652 640 set_node_attr(share, "changed", NULL);
653 641 }
654 642 features = sa_proto_get_featureset(proto);
655 643 if (share != NULL && features & SA_FEATURE_RESOURCE) {
656 644 /*
657 645 * We have a share and the protocol requires that at
658 646 * least one resource exist (probably SMB). We need to
659 647 * make sure that there is at least one.
660 648 */
661 649 resource = sa_get_share_resource(share, NULL);
662 650 if (resource == NULL) {
663 651 zfs_construct_resource(share, dataset);
664 652 }
665 653 }
666 654 return (err);
667 655 }
668 656
669 657 /*
670 658 * zfs_grp_error(err)
671 659 *
672 660 * Print group create error, but only once. If err is 0 do the
673 661 * print else don't.
674 662 */
675 663
676 664 static void
677 665 zfs_grp_error(int err)
678 666 {
679 667 if (err == 0) {
680 668 /* only print error once */
681 669 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
682 670 "Cannot create ZFS subgroup during initialization:"
683 671 " %s\n"), sa_errorstr(SA_SYSTEM_ERR));
684 672 }
685 673 }
686 674
687 675 /*
688 676 * zfs_process_share(handle, share, mountpoint, proto, source,
689 677 * shareopts, sourcestr)
690 678 *
691 679 * Creates the subgroup, if necessary and adds shares, resources
692 680 * and properties.
693 681 */
694 682 int
695 683 sa_zfs_process_share(sa_handle_t handle, sa_group_t group, sa_share_t share,
696 684 char *mountpoint, char *proto, zprop_source_t source, char *shareopts,
697 685 char *sourcestr, char *dataset)
698 686 {
699 687 int err = SA_OK;
700 688
701 689 if (source & ZPROP_SRC_INHERITED) {
702 690 err = zfs_inherited(handle, share, sourcestr, shareopts,
703 691 mountpoint, proto, dataset);
704 692 } else {
705 693 group = find_or_create_zfs_subgroup(handle, dataset, proto,
706 694 shareopts, &err);
707 695 if (group == NULL) {
708 696 static boolean_t reported_error = B_FALSE;
709 697 /*
710 698 * There is a problem, but we can't do
711 699 * anything about it at this point so we issue
712 700 * a warning and move on.
713 701 */
714 702 zfs_grp_error(reported_error);
715 703 reported_error = B_TRUE;
716 704 }
717 705 set_node_attr(group, "zfs", "true");
718 706 /*
719 707 * Add share with local opts via zfs_notinherited.
720 708 */
721 709 err = zfs_notinherited(group, share, mountpoint, shareopts,
722 710 proto, dataset, err);
723 711 }
724 712 return (err);
725 713 }
726 714
727 715 /*
728 716 * sa_get_zfs_shares(handle, groupname)
729 717 *
730 718 * Walk the mnttab for all zfs mounts and determine which are
731 719 * shared. Find or create the appropriate group/sub-group to contain
732 720 * the shares.
733 721 *
734 722 * All shares are in a sub-group that will hold the properties. This
735 723 * allows representing the inherited property model.
736 724 *
737 725 * One area of complication is if "sharenfs" is set at one level of
738 726 * the directory tree and "sharesmb" is set at a different level, the
739 727 * a sub-group must be formed at the lower level for both
740 728 * protocols. That is the nature of the problem in CR 6667349.
741 729 */
742 730
743 731 int
744 732 sa_get_zfs_shares(sa_handle_t handle, char *groupname)
745 733 {
746 734 sa_group_t zfsgroup;
747 735 boolean_t nfs;
748 736 boolean_t nfs_inherited;
749 737 boolean_t smb;
750 738 boolean_t smb_inherited;
751 739 zfs_handle_t **zlist;
752 740 char nfsshareopts[ZFS_MAXPROPLEN];
753 741 char smbshareopts[ZFS_MAXPROPLEN];
754 742 sa_share_t share;
755 743 zprop_source_t source;
↓ open down ↓ |
352 lines elided |
↑ open up ↑ |
756 744 char nfssourcestr[ZFS_MAXPROPLEN];
757 745 char smbsourcestr[ZFS_MAXPROPLEN];
758 746 char mountpoint[ZFS_MAXPROPLEN];
759 747 size_t count = 0, i;
760 748 libzfs_handle_t *zfs_libhandle;
761 749 int err = SA_OK;
762 750
763 751 /*
764 752 * If we can't access libzfs, don't bother doing anything.
765 753 */
766 - zfs_libhandle = ((sa_handle_impl_t)handle)->zfs_libhandle;
754 + zfs_libhandle = handle->zfs_libhandle;
767 755 if (zfs_libhandle == NULL)
768 756 return (SA_SYSTEM_ERR);
769 757
770 758 zfsgroup = find_or_create_group(handle, groupname, NULL, &err);
771 759 /* Not an error, this could be a legacy condition */
772 760 if (zfsgroup == NULL)
773 761 return (SA_OK);
774 762
775 763 /*
776 764 * need to walk the mounted ZFS pools and datasets to
777 765 * find shares that are possible.
778 766 */
779 - get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count);
767 + get_all_filesystems(handle, &zlist, &count);
780 768 qsort(zlist, count, sizeof (void *), mountpoint_compare);
781 769
782 770 for (i = 0; i < count; i++) {
783 771 char *dataset;
784 772
785 773 source = ZPROP_SRC_ALL;
786 774 /* If no mountpoint, skip. */
787 775 if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT,
788 776 mountpoint, sizeof (mountpoint), NULL, NULL, 0,
789 777 B_FALSE) != 0)
790 778 continue;
791 779
792 780 /*
793 781 * zfs_get_name value must not be freed. It is just a
794 782 * pointer to a value in the handle.
795 783 */
796 784 if ((dataset = (char *)zfs_get_name(zlist[i])) == NULL)
797 785 continue;
798 786
799 787 /*
800 788 * only deal with "mounted" file systems since
801 789 * unmounted file systems can't actually be shared.
802 790 */
803 791
804 792 if (!zfs_is_mounted(zlist[i], NULL))
805 793 continue;
806 794
807 795 nfs = nfs_inherited = B_FALSE;
808 796
809 797 if (zfs_prop_get(zlist[i], ZFS_PROP_SHARENFS, nfsshareopts,
810 798 sizeof (nfsshareopts), &source, nfssourcestr,
811 799 ZFS_MAXPROPLEN, B_FALSE) == 0 &&
812 800 strcmp(nfsshareopts, "off") != 0) {
813 801 if (source & ZPROP_SRC_INHERITED)
814 802 nfs_inherited = B_TRUE;
815 803 else
816 804 nfs = B_TRUE;
817 805 }
818 806
819 807 smb = smb_inherited = B_FALSE;
820 808 if (zfs_prop_get(zlist[i], ZFS_PROP_SHARESMB, smbshareopts,
821 809 sizeof (smbshareopts), &source, smbsourcestr,
822 810 ZFS_MAXPROPLEN, B_FALSE) == 0 &&
823 811 strcmp(smbshareopts, "off") != 0) {
824 812 if (source & ZPROP_SRC_INHERITED)
825 813 smb_inherited = B_TRUE;
826 814 else
827 815 smb = B_TRUE;
828 816 }
829 817
830 818 /*
831 819 * If the mountpoint is already shared, it must be a
832 820 * non-ZFS share. We want to remove the share from its
833 821 * parent group and reshare it under ZFS.
834 822 */
835 823 share = sa_find_share(handle, mountpoint);
836 824 if (share != NULL &&
837 825 (nfs || smb || nfs_inherited || smb_inherited)) {
838 826 err = sa_remove_share(share);
839 827 share = NULL;
840 828 }
841 829
842 830 /*
843 831 * At this point, we have the information needed to
844 832 * determine what to do with the share.
845 833 *
846 834 * If smb or nfs is set, we have a new sub-group.
847 835 * If smb_inherit and/or nfs_inherit is set, then
848 836 * place on an existing sub-group. If both are set,
849 837 * the existing sub-group is the closest up the tree.
850 838 */
851 839 if (nfs || smb) {
852 840 /*
853 841 * Non-inherited is the straightforward
854 842 * case. sa_zfs_process_share handles it
855 843 * directly. Make sure that if the "other"
856 844 * protocol is inherited, that we treat it as
857 845 * non-inherited as well.
858 846 */
859 847 if (nfs || nfs_inherited) {
860 848 err = sa_zfs_process_share(handle, zfsgroup,
861 849 share, mountpoint, "nfs",
862 850 0, nfsshareopts,
863 851 nfssourcestr, dataset);
864 852 share = sa_find_share(handle, mountpoint);
865 853 }
866 854 if (smb || smb_inherited) {
867 855 err = sa_zfs_process_share(handle, zfsgroup,
868 856 share, mountpoint, "smb",
869 857 0, smbshareopts,
870 858 smbsourcestr, dataset);
871 859 }
872 860 } else if (nfs_inherited || smb_inherited) {
873 861 char *grpdataset;
874 862 /*
875 863 * If we only have inherited groups, it is
876 864 * important to find the closer of the two if
877 865 * the protocols are set at different
878 866 * levels. The closest sub-group is the one we
879 867 * want to work with.
880 868 */
881 869 if (nfs_inherited && smb_inherited) {
882 870 if (strcmp(nfssourcestr, smbsourcestr) <= 0)
883 871 grpdataset = nfssourcestr;
884 872 else
885 873 grpdataset = smbsourcestr;
886 874 } else if (nfs_inherited) {
887 875 grpdataset = nfssourcestr;
888 876 } else if (smb_inherited) {
889 877 grpdataset = smbsourcestr;
890 878 }
891 879 if (nfs_inherited) {
892 880 err = sa_zfs_process_share(handle, zfsgroup,
893 881 share, mountpoint, "nfs",
894 882 ZPROP_SRC_INHERITED, nfsshareopts,
895 883 grpdataset, dataset);
896 884 share = sa_find_share(handle, mountpoint);
897 885 }
898 886 if (smb_inherited) {
899 887 err = sa_zfs_process_share(handle, zfsgroup,
900 888 share, mountpoint, "smb",
901 889 ZPROP_SRC_INHERITED, smbshareopts,
902 890 grpdataset, dataset);
903 891 }
904 892 }
905 893 }
906 894 /*
907 895 * Don't need to free the "zlist" variable since it is only a
908 896 * pointer to a cached value that will be freed when
909 897 * sa_fini() is called.
910 898 */
911 899 return (err);
912 900 }
913 901
914 902 #define COMMAND "/usr/sbin/zfs"
915 903
916 904 /*
917 905 * sa_zfs_set_sharenfs(group, path, on)
918 906 *
919 907 * Update the "sharenfs" property on the path. If on is true, then set
920 908 * to the properties on the group or "on" if no properties are
921 909 * defined. Set to "off" if on is false.
922 910 */
923 911
924 912 int
↓ open down ↓ |
135 lines elided |
↑ open up ↑ |
925 913 sa_zfs_set_sharenfs(sa_group_t group, char *path, int on)
926 914 {
927 915 int ret = SA_NOT_IMPLEMENTED;
928 916 char *command;
929 917
930 918 command = malloc(ZFS_MAXPROPLEN * 2);
931 919 if (command != NULL) {
932 920 char *opts = NULL;
933 921 char *dataset = NULL;
934 922 FILE *pfile;
935 - sa_handle_impl_t impl_handle;
923 + sa_handle_t handle;
936 924 /* for now, NFS is always available for "zfs" */
937 925 if (on) {
938 926 opts = sa_proto_legacy_format("nfs", group, 1);
939 927 if (opts != NULL && strlen(opts) == 0) {
940 928 free(opts);
941 929 opts = strdup("on");
942 930 }
943 931 }
944 932
945 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
946 - assert(impl_handle != NULL);
947 - if (impl_handle != NULL)
948 - dataset = get_zfs_dataset(impl_handle, path, B_FALSE);
933 + handle = sa_find_group_handle(group);
934 + assert(handle != NULL);
935 + if (handle != NULL)
936 + dataset = get_zfs_dataset(handle, path, B_FALSE);
949 937 else
950 938 ret = SA_SYSTEM_ERR;
951 939
952 940 if (dataset != NULL) {
953 941 (void) snprintf(command, ZFS_MAXPROPLEN * 2,
954 942 "%s set sharenfs=\"%s\" %s", COMMAND,
955 943 opts != NULL ? opts : "off", dataset);
956 944 pfile = popen(command, "r");
957 945 if (pfile != NULL) {
958 946 ret = pclose(pfile);
959 947 if (ret != 0)
960 948 ret = SA_SYSTEM_ERR;
961 949 }
962 950 }
963 951 if (opts != NULL)
964 952 free(opts);
965 953 if (dataset != NULL)
966 954 free(dataset);
967 955 free(command);
968 956 }
969 957 return (ret);
970 958 }
971 959
972 960 /*
973 961 * add_resources(share, opt)
974 962 *
975 963 * Add resource properties to those in "opt". Resources are prefixed
976 964 * with name=resourcename.
977 965 */
978 966 static char *
979 967 add_resources(sa_share_t share, char *opt)
980 968 {
981 969 char *newopt = NULL;
982 970 char *propstr;
983 971 sa_resource_t resource;
984 972
985 973 newopt = strdup(opt);
986 974 if (newopt == NULL)
987 975 return (newopt);
988 976
989 977 for (resource = sa_get_share_resource(share, NULL);
990 978 resource != NULL;
991 979 resource = sa_get_next_resource(resource)) {
992 980 char *name;
993 981 size_t size;
994 982
995 983 name = sa_get_resource_attr(resource, "name");
996 984 if (name == NULL) {
997 985 free(newopt);
998 986 return (NULL);
999 987 }
1000 988 size = strlen(name) + strlen(opt) + sizeof ("name=") + 1;
1001 989 newopt = calloc(1, size);
1002 990 if (newopt != NULL)
1003 991 (void) snprintf(newopt, size, "%s,name=%s", opt, name);
1004 992 sa_free_attr_string(name);
1005 993 free(opt);
1006 994 opt = newopt;
1007 995 propstr = sa_proto_legacy_format("smb", resource, 0);
1008 996 if (propstr == NULL) {
1009 997 free(opt);
1010 998 return (NULL);
1011 999 }
1012 1000 size = strlen(propstr) + strlen(opt) + 2;
1013 1001 newopt = calloc(1, size);
1014 1002 if (newopt != NULL)
1015 1003 (void) snprintf(newopt, size, "%s,%s", opt, propstr);
1016 1004 free(opt);
1017 1005 opt = newopt;
1018 1006 }
1019 1007 return (opt);
1020 1008 }
1021 1009
1022 1010 /*
1023 1011 * sa_zfs_set_sharesmb(group, path, on)
1024 1012 *
1025 1013 * Update the "sharesmb" property on the path. If on is true, then set
1026 1014 * to the properties on the group or "on" if no properties are
1027 1015 * defined. Set to "off" if on is false.
1028 1016 */
1029 1017
1030 1018 int
1031 1019 sa_zfs_set_sharesmb(sa_group_t group, char *path, int on)
1032 1020 {
1033 1021 int ret = SA_NOT_IMPLEMENTED;
1034 1022 char *command;
1035 1023 sa_share_t share;
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
1036 1024
1037 1025 /* In case SMB not enabled */
1038 1026 if (sa_get_optionset(group, "smb") == NULL)
1039 1027 return (SA_NOT_SUPPORTED);
1040 1028
1041 1029 command = malloc(ZFS_MAXPROPLEN * 2);
1042 1030 if (command != NULL) {
1043 1031 char *opts = NULL;
1044 1032 char *dataset = NULL;
1045 1033 FILE *pfile;
1046 - sa_handle_impl_t impl_handle;
1034 + sa_handle_t handle;
1047 1035
1048 1036 if (on) {
1049 1037 char *newopt;
1050 1038
1051 1039 share = sa_get_share(group, NULL);
1052 1040 opts = sa_proto_legacy_format("smb", share, 1);
1053 1041 if (opts != NULL && strlen(opts) == 0) {
1054 1042 free(opts);
1055 1043 opts = strdup("on");
1056 1044 }
1057 1045 newopt = add_resources(opts, share);
1058 1046 free(opts);
1059 1047 opts = newopt;
1060 1048 }
1061 1049
1062 - impl_handle = (sa_handle_impl_t)sa_find_group_handle(group);
1063 - assert(impl_handle != NULL);
1064 - if (impl_handle != NULL)
1065 - dataset = get_zfs_dataset(impl_handle, path, B_FALSE);
1050 + handle = sa_find_group_handle(group);
1051 + assert(handle != NULL);
1052 + if (handle != NULL)
1053 + dataset = get_zfs_dataset(handle, path, B_FALSE);
1066 1054 else
1067 1055 ret = SA_SYSTEM_ERR;
1068 1056
1069 1057 if (dataset != NULL) {
1070 1058 (void) snprintf(command, ZFS_MAXPROPLEN * 2,
1071 1059 "echo %s set sharesmb=\"%s\" %s", COMMAND,
1072 1060 opts != NULL ? opts : "off", dataset);
1073 1061 pfile = popen(command, "r");
1074 1062 if (pfile != NULL) {
1075 1063 ret = pclose(pfile);
1076 1064 if (ret != 0)
1077 1065 ret = SA_SYSTEM_ERR;
1078 1066 }
1079 1067 }
1080 1068 if (opts != NULL)
1081 1069 free(opts);
1082 1070 if (dataset != NULL)
1083 1071 free(dataset);
1084 1072 free(command);
1085 1073 }
1086 1074 return (ret);
1087 1075 }
1088 1076
1089 1077 /*
1090 1078 * sa_zfs_update(group)
1091 1079 *
1092 1080 * call back to ZFS to update the share if necessary.
1093 1081 * Don't do it if it isn't a real change.
1094 1082 */
1095 1083 int
1096 1084 sa_zfs_update(sa_group_t group)
1097 1085 {
1098 1086 sa_optionset_t protopt;
1099 1087 sa_group_t parent;
1100 1088 char *command;
1101 1089 char *optstring;
1102 1090 int ret = SA_OK;
1103 1091 int doupdate = 0;
1104 1092 FILE *pfile;
1105 1093
1106 1094 if (sa_is_share(group))
1107 1095 parent = sa_get_parent_group(group);
1108 1096 else
1109 1097 parent = group;
1110 1098
1111 1099 if (parent != NULL) {
1112 1100 command = malloc(ZFS_MAXPROPLEN * 2);
1113 1101 if (command == NULL)
1114 1102 return (SA_NO_MEMORY);
1115 1103
1116 1104 *command = '\0';
1117 1105 for (protopt = sa_get_optionset(parent, NULL); protopt != NULL;
1118 1106 protopt = sa_get_next_optionset(protopt)) {
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
1119 1107
1120 1108 char *proto = sa_get_optionset_attr(protopt, "type");
1121 1109 char *path;
1122 1110 char *dataset = NULL;
1123 1111 char *zfsopts = NULL;
1124 1112
1125 1113 if (sa_is_share(group)) {
1126 1114 path = sa_get_share_attr((sa_share_t)group,
1127 1115 "path");
1128 1116 if (path != NULL) {
1129 - sa_handle_impl_t impl_handle;
1117 + sa_handle_t handle;
1130 1118
1131 - impl_handle = sa_find_group_handle(
1119 + handle = sa_find_group_handle(
1132 1120 group);
1133 - if (impl_handle != NULL)
1121 + if (handle != NULL)
1134 1122 dataset = get_zfs_dataset(
1135 - impl_handle, path, B_FALSE);
1123 + handle, path, B_FALSE);
1136 1124 else
1137 1125 ret = SA_SYSTEM_ERR;
1138 1126
1139 1127 sa_free_attr_string(path);
1140 1128 }
1141 1129 } else {
1142 1130 dataset = sa_get_group_attr(group, "name");
1143 1131 }
1144 1132 /* update only when there is an optstring found */
1145 1133 doupdate = 0;
1146 1134 if (proto != NULL && dataset != NULL) {
1135 + sa_handle_t handle;
1136 +
1147 1137 optstring = sa_proto_legacy_format(proto,
1148 1138 group, 1);
1149 - zfsopts = get_zfs_property(dataset,
1139 + handle = sa_find_group_handle(group);
1140 + zfsopts = get_zfs_property(handle, dataset,
1150 1141 ZFS_PROP_SHARENFS);
1151 1142
1152 1143 if (optstring != NULL && zfsopts != NULL) {
1153 1144 if (strcmp(optstring, zfsopts) != 0)
1154 1145 doupdate++;
1155 1146 }
1156 1147 if (doupdate) {
1157 1148 if (optstring != NULL &&
1158 1149 strlen(optstring) > 0) {
1159 1150 (void) snprintf(command,
1160 1151 ZFS_MAXPROPLEN * 2,
1161 1152 "%s set share%s=%s %s",
1162 1153 COMMAND, proto,
1163 1154 optstring, dataset);
1164 1155 } else {
1165 1156 (void) snprintf(command,
1166 1157 ZFS_MAXPROPLEN * 2,
1167 1158 "%s set share%s=on %s",
1168 1159 COMMAND, proto,
1169 1160 dataset);
1170 1161 }
1171 1162 pfile = popen(command, "r");
1172 1163 if (pfile != NULL)
1173 1164 ret = pclose(pfile);
1174 1165 switch (ret) {
1175 1166 default:
1176 1167 case 1:
1177 1168 ret = SA_SYSTEM_ERR;
1178 1169 break;
1179 1170 case 2:
1180 1171 ret = SA_SYNTAX_ERR;
1181 1172 break;
1182 1173 case 0:
1183 1174 break;
1184 1175 }
1185 1176 }
1186 1177 if (optstring != NULL)
1187 1178 free(optstring);
1188 1179 if (zfsopts != NULL)
1189 1180 free(zfsopts);
1190 1181 }
1191 1182 if (proto != NULL)
1192 1183 sa_free_attr_string(proto);
1193 1184 if (dataset != NULL)
1194 1185 free(dataset);
1195 1186 }
1196 1187 free(command);
↓ open down ↓ |
37 lines elided |
↑ open up ↑ |
1197 1188 }
1198 1189 return (ret);
1199 1190 }
1200 1191
1201 1192 /*
1202 1193 * sa_group_is_zfs(group)
1203 1194 *
1204 1195 * Given the group, determine if the zfs attribute is set.
1205 1196 */
1206 1197
1207 -int
1198 +boolean_t
1208 1199 sa_group_is_zfs(sa_group_t group)
1209 1200 {
1210 1201 char *zfs;
1211 - int ret = 0;
1202 + int ret = B_FALSE;
1212 1203
1213 1204 zfs = sa_get_group_attr(group, "zfs");
1214 1205 if (zfs != NULL) {
1215 - ret = 1;
1206 + ret = B_TRUE;
1216 1207 sa_free_attr_string(zfs);
1217 1208 }
1218 1209 return (ret);
1219 1210 }
1220 1211
1221 1212 /*
1222 1213 * sa_path_is_zfs(path)
1223 1214 *
1224 1215 * Check to see if the file system path represents is of type "zfs".
1225 1216 */
1226 1217
1227 -int
1218 +boolean_t
1228 1219 sa_path_is_zfs(char *path)
1229 1220 {
1230 1221 char *fstype;
1231 - int ret = 0;
1222 + int ret = B_FALSE;
1232 1223
1233 1224 fstype = sa_fstype(path);
1234 1225 if (fstype != NULL && strcmp(fstype, "zfs") == 0)
1235 - ret = 1;
1226 + ret = B_TRUE;
1236 1227 if (fstype != NULL)
1237 1228 sa_free_fstype(fstype);
1238 1229 return (ret);
1239 1230 }
1240 1231
1241 1232 int
1242 1233 sa_sharetab_fill_zfs(sa_share_t share, share_t *sh, char *proto)
1243 1234 {
1244 1235 char *path;
1245 1236
1246 1237 /* Make sure path is valid */
1247 1238
1248 1239 path = sa_get_share_attr(share, "path");
1249 1240 if (path != NULL) {
1250 1241 (void) memset(sh, 0, sizeof (sh));
1251 1242 (void) sa_fillshare(share, proto, sh);
1252 1243 sa_free_attr_string(path);
1253 1244 return (0);
1254 1245 } else
1255 1246 return (1);
1256 1247 }
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1257 1248
1258 1249 #define SMAX(i, j) \
1259 1250 if ((j) > (i)) { \
1260 1251 (i) = (j); \
1261 1252 }
1262 1253
1263 1254 int
1264 1255 sa_share_zfs(sa_share_t share, sa_resource_t resource, char *path, share_t *sh,
1265 1256 void *exportdata, zfs_share_op_t operation)
1266 1257 {
1267 - libzfs_handle_t *libhandle;
1268 1258 sa_group_t group;
1269 - sa_handle_t sahandle;
1259 + sa_handle_t handle;
1270 1260 char *dataset;
1271 1261 int err = EINVAL;
1272 1262 int i, j;
1273 1263 char newpath[MAXPATHLEN];
1274 1264 char *pathp;
1265 + char *resource_name;
1275 1266
1276 1267 /*
1277 1268 * First find the dataset name
1278 1269 */
1279 1270 if ((group = sa_get_parent_group(share)) == NULL) {
1280 1271 return (EINVAL);
1281 1272 }
1282 - if ((sahandle = sa_find_group_handle(group)) == NULL) {
1273 + if ((handle = sa_find_group_handle(group)) == NULL) {
1283 1274 return (EINVAL);
1284 1275 }
1285 1276
1286 1277 /*
1287 1278 * If get_zfs_dataset fails, see if it is a subdirectory
1288 1279 */
1289 1280
1290 1281 pathp = path;
1291 - while ((dataset = get_zfs_dataset(sahandle, pathp, B_TRUE)) == NULL) {
1282 + while ((dataset = get_zfs_dataset(handle, pathp, B_TRUE)) == NULL) {
1292 1283 char *p;
1293 1284
1294 1285 if (pathp == path) {
1295 1286 (void) strlcpy(newpath, path, sizeof (newpath));
1296 1287 pathp = newpath;
1297 1288 }
1298 1289
1299 1290 /*
1300 1291 * Make sure only one leading '/' This condition came
1301 1292 * about when using HAStoragePlus which insisted on
1302 1293 * putting an extra leading '/' in the ZFS path
1303 1294 * name. The problem is fixed in other areas, but this
1304 1295 * will catch any other ways that a double slash might
1305 1296 * get introduced.
1306 1297 */
1307 1298 while (*pathp == '/' && *(pathp + 1) == '/')
1308 1299 pathp++;
1309 1300
1310 1301 /*
1311 1302 * chop off part of path, but if we are at root then
1312 1303 * make sure path is a /
1313 1304 */
1314 1305 if ((strlen(pathp) > 1) && (p = strrchr(pathp, '/'))) {
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
1315 1306 if (pathp == p) {
1316 1307 *(p + 1) = '\0'; /* skip over /, root case */
1317 1308 } else {
1318 1309 *p = '\0';
1319 1310 }
1320 1311 } else {
1321 1312 return (EINVAL);
1322 1313 }
1323 1314 }
1324 1315
1325 - libhandle = libzfs_init();
1326 - if (libhandle != NULL) {
1327 - char *resource_name;
1328 -
1329 - i = (sh->sh_path ? strlen(sh->sh_path) : 0);
1330 - sh->sh_size = i;
1331 -
1332 - j = (sh->sh_res ? strlen(sh->sh_res) : 0);
1333 - sh->sh_size += j;
1334 - SMAX(i, j);
1335 -
1336 - j = (sh->sh_fstype ? strlen(sh->sh_fstype) : 0);
1337 - sh->sh_size += j;
1338 - SMAX(i, j);
1339 -
1340 - j = (sh->sh_opts ? strlen(sh->sh_opts) : 0);
1341 - sh->sh_size += j;
1342 - SMAX(i, j);
1343 -
1344 - j = (sh->sh_descr ? strlen(sh->sh_descr) : 0);
1345 - sh->sh_size += j;
1346 - SMAX(i, j);
1347 -
1348 - resource_name = sa_get_resource_attr(resource, "name");
1349 -
1350 - err = zfs_deleg_share_nfs(libhandle, dataset, path,
1351 - resource_name, exportdata, sh, i, operation);
1352 - if (err == SA_OK)
1353 - sa_update_sharetab_ts(sahandle);
1354 - else
1355 - err = errno;
1356 - if (resource_name)
1357 - sa_free_attr_string(resource_name);
1316 + i = (sh->sh_path ? strlen(sh->sh_path) : 0);
1317 + sh->sh_size = i;
1318 +
1319 + j = (sh->sh_res ? strlen(sh->sh_res) : 0);
1320 + sh->sh_size += j;
1321 + SMAX(i, j);
1322 +
1323 + j = (sh->sh_fstype ? strlen(sh->sh_fstype) : 0);
1324 + sh->sh_size += j;
1325 + SMAX(i, j);
1326 +
1327 + j = (sh->sh_opts ? strlen(sh->sh_opts) : 0);
1328 + sh->sh_size += j;
1329 + SMAX(i, j);
1330 +
1331 + j = (sh->sh_descr ? strlen(sh->sh_descr) : 0);
1332 + sh->sh_size += j;
1333 + SMAX(i, j);
1334 +
1335 + resource_name = sa_get_resource_attr(resource, "name");
1336 +
1337 + err = zfs_deleg_share_nfs(handle->zfs_libhandle, dataset, path,
1338 + resource_name, exportdata, sh, i, operation);
1339 + if (err == SA_OK)
1340 + sa_update_sharetab_ts(handle);
1341 + else
1342 + err = errno;
1343 + if (resource_name != NULL)
1344 + sa_free_attr_string(resource_name);
1358 1345
1359 - libzfs_fini(libhandle);
1360 - }
1361 1346 free(dataset);
1362 1347 return (err);
1363 1348 }
1364 1349
1365 1350 /*
1366 1351 * sa_get_zfs_handle(handle)
1367 1352 *
1368 1353 * Given an sa_handle_t, return the libzfs_handle_t *. This is only
1369 1354 * used internally by libzfs. Needed in order to avoid including
1370 1355 * libshare_impl.h in libzfs.
1371 1356 */
1372 1357
1373 1358 libzfs_handle_t *
1374 1359 sa_get_zfs_handle(sa_handle_t handle)
1375 1360 {
1376 - sa_handle_impl_t implhandle = (sa_handle_impl_t)handle;
1377 -
1378 - return (implhandle->zfs_libhandle);
1379 -}
1380 -
1381 -/*
1382 - * sa_get_zfs_info(libzfs, path, mountpoint, dataset)
1383 - *
1384 - * Find the ZFS dataset and mountpoint for a given path
1385 - */
1386 -int
1387 -sa_zfs_get_info(libzfs_handle_t *libzfs, char *path, char *mountpointp,
1388 - char *datasetp)
1389 -{
1390 - get_all_cbdata_t cb = { 0 };
1391 - int i;
1392 - char mountpoint[ZFS_MAXPROPLEN];
1393 - char dataset[ZFS_MAXPROPLEN];
1394 - char canmount[ZFS_MAXPROPLEN];
1395 - char *dp;
1396 - int count;
1397 - int ret = 0;
1398 -
1399 - cb.cb_types = ZFS_TYPE_FILESYSTEM;
1400 -
1401 - if (libzfs == NULL)
1402 - return (0);
1403 -
1404 - (void) zfs_iter_root(libzfs, get_one_filesystem, &cb);
1405 - count = cb.cb_used;
1406 -
1407 - qsort(cb.cb_handles, count, sizeof (void *), mountpoint_compare);
1408 - for (i = 0; i < count; i++) {
1409 - /* must have a mountpoint */
1410 - if (zfs_prop_get(cb.cb_handles[i], ZFS_PROP_MOUNTPOINT,
1411 - mountpoint, sizeof (mountpoint),
1412 - NULL, NULL, 0, B_FALSE) != 0) {
1413 - /* no mountpoint */
1414 - continue;
1415 - }
1416 -
1417 - /* mountpoint must be a path */
1418 - if (strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) == 0 ||
1419 - strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
1420 - /*
1421 - * Search mmttab for mountpoint
1422 - */
1423 -
1424 - if (get_legacy_mountpoint(path, dataset,
1425 - ZFS_MAXPROPLEN, mountpoint,
1426 - ZFS_MAXPROPLEN) == 0) {
1427 - ret = 1;
1428 - break;
1429 - }
1430 - continue;
1431 - }
1432 -
1433 - /* canmount must be set */
1434 - canmount[0] = '\0';
1435 - if (zfs_prop_get(cb.cb_handles[i], ZFS_PROP_CANMOUNT, canmount,
1436 - sizeof (canmount), NULL, NULL, 0, B_FALSE) != 0 ||
1437 - strcmp(canmount, "off") == 0)
1438 - continue;
1439 -
1440 - /*
1441 - * have a mountable handle but want to skip those marked none
1442 - * and legacy
1443 - */
1444 - if (strcmp(mountpoint, path) == 0) {
1445 - dp = (char *)zfs_get_name(cb.cb_handles[i]);
1446 - if (dp != NULL) {
1447 - if (datasetp != NULL)
1448 - (void) strcpy(datasetp, dp);
1449 - if (mountpointp != NULL)
1450 - (void) strcpy(mountpointp, mountpoint);
1451 - ret = 1;
1452 - }
1453 - break;
1454 - }
1455 -
1456 - }
1457 -
1458 - return (ret);
1361 + return (handle->zfs_libhandle);
1459 1362 }
1460 1363
1461 1364 /*
1462 1365 * This method builds values for "sharesmb" property from the
1463 1366 * nvlist argument. The values are returned in sharesmb_val variable.
1464 1367 */
1465 1368 static int
1466 1369 sa_zfs_sprintf_new_prop(nvlist_t *nvl, char *sharesmb_val)
1467 1370 {
1468 - char cur_val[MAXPATHLEN];
1371 + char cur_val[ZFS_MAXPROPLEN];
1469 1372 char *name, *val;
1470 1373 nvpair_t *cur;
1471 1374 int err = 0;
1472 1375
1473 1376 cur = nvlist_next_nvpair(nvl, NULL);
1474 1377 while (cur != NULL) {
1475 1378 name = nvpair_name(cur);
1476 1379 err = nvpair_value_string(cur, &val);
1477 1380 if ((err != 0) || (name == NULL) || (val == NULL))
1478 1381 return (-1);
1479 1382
1480 - (void) snprintf(cur_val, MAXPATHLEN, "%s=%s,", name, val);
1481 - (void) strlcat(sharesmb_val, cur_val, MAXPATHLEN);
1383 + (void) snprintf(cur_val, ZFS_MAXPROPLEN, "%s=%s,", name, val);
1384 + (void) strlcat(sharesmb_val, cur_val, ZFS_MAXPROPLEN);
1482 1385
1483 1386 cur = nvlist_next_nvpair(nvl, cur);
1484 1387 }
1485 1388
1486 1389 return (0);
1487 1390 }
1488 1391
1489 1392 /*
1490 1393 * This method builds values for "sharesmb" property from values
1491 1394 * already existing on the share. The properties set via sa_zfs_sprint_new_prop
1492 1395 * method are passed in sharesmb_val. If a existing property is already
1493 1396 * set via sa_zfs_sprint_new_prop method, then they are not appended
1494 1397 * to the sharesmb_val string. The returned sharesmb_val string is a combination
1495 1398 * of new and existing values for 'sharesmb' property.
1496 1399 */
1497 1400 static int
1498 1401 sa_zfs_sprintf_existing_prop(zfs_handle_t *handle, char *sharesmb_val)
1499 1402 {
1500 - char shareopts[ZFS_MAXPROPLEN], cur_val[MAXPATHLEN];
1403 + char shareopts[ZFS_MAXPROPLEN], cur_val[ZFS_MAXPROPLEN];
1501 1404 char *token, *last, *value;
1502 1405
1503 1406 if (zfs_prop_get(handle, ZFS_PROP_SHARESMB, shareopts,
1504 1407 sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0)
1505 1408 return (-1);
1506 1409
1507 1410 if (strstr(shareopts, "=") == NULL)
1508 1411 return (0);
1509 1412
1510 1413 for (token = strtok_r(shareopts, ",", &last); token != NULL;
1511 1414 token = strtok_r(NULL, ",", &last)) {
1512 1415 value = strchr(token, '=');
1513 1416 if (value == NULL)
1514 1417 return (-1);
1515 1418 *value++ = '\0';
1516 1419
1517 - (void) snprintf(cur_val, MAXPATHLEN, "%s=", token);
1420 + (void) snprintf(cur_val, ZFS_MAXPROPLEN, "%s=", token);
1518 1421 if (strstr(sharesmb_val, cur_val) == NULL) {
1519 - (void) strlcat(cur_val, value, MAXPATHLEN);
1520 - (void) strlcat(cur_val, ",", MAXPATHLEN);
1521 - (void) strlcat(sharesmb_val, cur_val, MAXPATHLEN);
1422 + (void) strlcat(cur_val, value, ZFS_MAXPROPLEN);
1423 + (void) strlcat(cur_val, ",", ZFS_MAXPROPLEN);
1424 + (void) strlcat(sharesmb_val, cur_val, ZFS_MAXPROPLEN);
1522 1425 }
1523 1426 }
1524 1427
1525 1428 return (0);
1526 1429 }
1527 1430
1528 1431 /*
1529 1432 * Sets the share properties on a ZFS share. For now, this method sets only
1530 1433 * the "sharesmb" property.
1531 1434 *
1532 1435 * This method includes building a comma seperated name-value string to be
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
1533 1436 * set on the "sharesmb" property of a ZFS share. This name-value string is
1534 1437 * build in 2 steps:
1535 1438 * - New property values given as name-value pair are set first.
1536 1439 * - Existing optionset properties, which are not part of the new properties
1537 1440 * passed in step 1, are appended to the newly set properties.
1538 1441 */
1539 1442 int
1540 1443 sa_zfs_setprop(sa_handle_t handle, char *path, nvlist_t *nvl)
1541 1444 {
1542 1445 zfs_handle_t *z_fs;
1543 - libzfs_handle_t *z_lib;
1544 - char sharesmb_val[MAXPATHLEN];
1446 + char sharesmb_val[ZFS_MAXPROPLEN];
1545 1447 char *dataset, *lastcomma;
1546 1448
1547 1449 if (nvlist_empty(nvl))
1548 1450 return (0);
1549 1451
1550 1452 if ((handle == NULL) || (path == NULL))
1551 1453 return (-1);
1552 1454
1553 1455 if ((dataset = get_zfs_dataset(handle, path, B_FALSE)) == NULL)
1554 1456 return (-1);
1555 1457
1556 - if ((z_lib = libzfs_init()) == NULL) {
1557 - free(dataset);
1558 - return (-1);
1559 - }
1560 -
1561 - z_fs = zfs_open(z_lib, dataset, ZFS_TYPE_DATASET);
1458 + z_fs = zfs_open(handle->zfs_libhandle, dataset, ZFS_TYPE_DATASET);
1562 1459 if (z_fs == NULL) {
1563 1460 free(dataset);
1564 - libzfs_fini(z_lib);
1565 1461 return (-1);
1566 1462 }
1567 1463
1568 - bzero(sharesmb_val, MAXPATHLEN);
1464 + bzero(sharesmb_val, ZFS_MAXPROPLEN);
1569 1465 if (sa_zfs_sprintf_new_prop(nvl, sharesmb_val) != 0) {
1570 1466 free(dataset);
1571 1467 zfs_close(z_fs);
1572 - libzfs_fini(z_lib);
1573 1468 return (-1);
1574 1469 }
1575 1470
1576 1471 if (sa_zfs_sprintf_existing_prop(z_fs, sharesmb_val) != 0) {
1577 1472 free(dataset);
1578 1473 zfs_close(z_fs);
1579 - libzfs_fini(z_lib);
1580 1474 return (-1);
1581 1475 }
1582 1476
1583 1477 lastcomma = strrchr(sharesmb_val, ',');
1584 1478 if ((lastcomma != NULL) && (lastcomma[1] == '\0'))
1585 1479 *lastcomma = '\0';
1586 1480
1587 1481 (void) zfs_prop_set(z_fs, zfs_prop_to_name(ZFS_PROP_SHARESMB),
1588 1482 sharesmb_val);
1589 1483 free(dataset);
1590 1484 zfs_close(z_fs);
1591 - libzfs_fini(z_lib);
1592 1485
1593 1486 return (0);
1594 1487 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX