libzfs_dataset.c (208684) | libzfs_dataset.c (209962) |
---|---|
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 23 unchanged lines hidden (view full) --- 32#include <stdio.h> 33#include <stdlib.h> 34#include <strings.h> 35#include <unistd.h> 36#include <stddef.h> 37#include <zone.h> 38#include <fcntl.h> 39#include <sys/mntent.h> | 1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 23 unchanged lines hidden (view full) --- 32#include <stdio.h> 33#include <stdlib.h> 34#include <strings.h> 35#include <unistd.h> 36#include <stddef.h> 37#include <zone.h> 38#include <fcntl.h> 39#include <sys/mntent.h> |
40#include <sys/mnttab.h> | |
41#include <sys/mount.h> 42#include <sys/avl.h> 43#include <priv.h> 44#include <pwd.h> 45#include <grp.h> 46#include <stddef.h> | 40#include <sys/mount.h> 41#include <sys/avl.h> 42#include <priv.h> 43#include <pwd.h> 44#include <grp.h> 45#include <stddef.h> |
46#include <idmap.h> |
|
47 48#include <sys/spa.h> 49#include <sys/zap.h> | 47 48#include <sys/spa.h> 49#include <sys/zap.h> |
50#include <sys/misc.h> |
|
50#include <libzfs.h> 51 52#include "zfs_namecheck.h" 53#include "zfs_prop.h" 54#include "libzfs_impl.h" 55#include "zfs_deleg.h" 56 57static int zvol_create_link_common(libzfs_handle_t *, const char *, int); | 51#include <libzfs.h> 52 53#include "zfs_namecheck.h" 54#include "zfs_prop.h" 55#include "libzfs_impl.h" 56#include "zfs_deleg.h" 57 58static int zvol_create_link_common(libzfs_handle_t *, const char *, int); |
59static int userquota_propname_decode(const char *propname, boolean_t zoned, 60 zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp); |
|
58 59/* 60 * Given a single type (not a mask of types), return the type in a human 61 * readable form. 62 */ 63const char * 64zfs_type_to_name(zfs_type_t type) 65{ --- 35 unchanged lines hidden (view full) --- 101 * snapshot attribute and try again. 102 */ 103 if (types & ZFS_TYPE_SNAPSHOT) { 104 if (strchr(path, '@') != NULL) 105 return (dgettext(TEXT_DOMAIN, "snapshot")); 106 return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 107 } 108 | 61 62/* 63 * Given a single type (not a mask of types), return the type in a human 64 * readable form. 65 */ 66const char * 67zfs_type_to_name(zfs_type_t type) 68{ --- 35 unchanged lines hidden (view full) --- 104 * snapshot attribute and try again. 105 */ 106 if (types & ZFS_TYPE_SNAPSHOT) { 107 if (strchr(path, '@') != NULL) 108 return (dgettext(TEXT_DOMAIN, "snapshot")); 109 return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 110 } 111 |
109 | |
110 /* 111 * The user has requested either filesystems or volumes. 112 * We have no way of knowing a priori what type this would be, so always 113 * report it as "filesystem" or "volume", our two primitive types. 114 */ 115 if (types & ZFS_TYPE_FILESYSTEM) 116 return (dgettext(TEXT_DOMAIN, "filesystem")); 117 118 assert(types & ZFS_TYPE_VOLUME); 119 return (dgettext(TEXT_DOMAIN, "volume")); 120} 121 122/* 123 * Validate a ZFS path. This is used even before trying to open the dataset, to | 112 /* 113 * The user has requested either filesystems or volumes. 114 * We have no way of knowing a priori what type this would be, so always 115 * report it as "filesystem" or "volume", our two primitive types. 116 */ 117 if (types & ZFS_TYPE_FILESYSTEM) 118 return (dgettext(TEXT_DOMAIN, "filesystem")); 119 120 assert(types & ZFS_TYPE_VOLUME); 121 return (dgettext(TEXT_DOMAIN, "volume")); 122} 123 124/* 125 * Validate a ZFS path. This is used even before trying to open the dataset, to |
124 * provide a more meaningful error message. We place a more useful message in 125 * 'buf' detailing exactly why the name was not valid. | 126 * provide a more meaningful error message. We call zfs_error_aux() to 127 * explain exactly why the name was not valid. |
126 */ 127static int 128zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, 129 boolean_t modifying) 130{ 131 namecheck_err_t why; 132 char what; 133 --- 177 unchanged lines hidden (view full) --- 311 zph = next; 312 } 313 hdl->libzfs_pool_handles = NULL; 314} 315 316/* 317 * Utility function to gather stats (objset and zpl) for the given object. 318 */ | 128 */ 129static int 130zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, 131 boolean_t modifying) 132{ 133 namecheck_err_t why; 134 char what; 135 --- 177 unchanged lines hidden (view full) --- 313 zph = next; 314 } 315 hdl->libzfs_pool_handles = NULL; 316} 317 318/* 319 * Utility function to gather stats (objset and zpl) for the given object. 320 */ |
319static int 320get_stats(zfs_handle_t *zhp) | 321get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc) |
321{ | 322{ |
322 zfs_cmd_t zc = { 0 }; | |
323 libzfs_handle_t *hdl = zhp->zfs_hdl; | 323 libzfs_handle_t *hdl = zhp->zfs_hdl; |
324 nvlist_t *allprops, *userprops; | |
325 | 324 |
326 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); | 325 (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); |
327 | 326 |
328 if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 329 return (-1); 330 331 while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { | 327 while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) { |
332 if (errno == ENOMEM) { | 328 if (errno == ENOMEM) { |
333 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 334 zcmd_free_nvlists(&zc); | 329 if (zcmd_expand_dst_nvlist(hdl, zc) != 0) { |
335 return (-1); 336 } 337 } else { | 330 return (-1); 331 } 332 } else { |
338 zcmd_free_nvlists(&zc); | |
339 return (-1); 340 } 341 } | 333 return (-1); 334 } 335 } |
336 return (0); 337} |
|
342 | 338 |
343 zhp->zfs_dmustats = zc.zc_objset_stats; /* structure assignment */ | 339static int 340put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc) 341{ 342 nvlist_t *allprops, *userprops; |
344 | 343 |
345 if (zcmd_read_dst_nvlist(hdl, &zc, &allprops) != 0) { 346 zcmd_free_nvlists(&zc); | 344 zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */ 345 346 if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) { |
347 return (-1); 348 } 349 | 347 return (-1); 348 } 349 |
350 zcmd_free_nvlists(&zc); 351 | 350 /* 351 * XXX Why do we store the user props separately, in addition to 352 * storing them in zfs_props? 353 */ |
352 if ((userprops = process_user_props(zhp, allprops)) == NULL) { 353 nvlist_free(allprops); 354 return (-1); 355 } 356 357 nvlist_free(zhp->zfs_props); 358 nvlist_free(zhp->zfs_user_props); 359 360 zhp->zfs_props = allprops; 361 zhp->zfs_user_props = userprops; 362 363 return (0); 364} 365 | 354 if ((userprops = process_user_props(zhp, allprops)) == NULL) { 355 nvlist_free(allprops); 356 return (-1); 357 } 358 359 nvlist_free(zhp->zfs_props); 360 nvlist_free(zhp->zfs_user_props); 361 362 zhp->zfs_props = allprops; 363 zhp->zfs_user_props = userprops; 364 365 return (0); 366} 367 |
368static int 369get_stats(zfs_handle_t *zhp) 370{ 371 int rc = 0; 372 zfs_cmd_t zc = { 0 }; 373 374 if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 375 return (-1); 376 if (get_stats_ioctl(zhp, &zc) != 0) 377 rc = -1; 378 else if (put_stats_zhdl(zhp, &zc) != 0) 379 rc = -1; 380 zcmd_free_nvlists(&zc); 381 return (rc); 382} 383 |
|
366/* 367 * Refresh the properties currently stored in the handle. 368 */ 369void 370zfs_refresh_properties(zfs_handle_t *zhp) 371{ 372 (void) get_stats(zhp); 373} 374 375/* 376 * Makes a handle from the given dataset name. Used by zfs_open() and 377 * zfs_iter_* to create child handles on the fly. 378 */ | 384/* 385 * Refresh the properties currently stored in the handle. 386 */ 387void 388zfs_refresh_properties(zfs_handle_t *zhp) 389{ 390 (void) get_stats(zhp); 391} 392 393/* 394 * Makes a handle from the given dataset name. Used by zfs_open() and 395 * zfs_iter_* to create child handles on the fly. 396 */ |
379zfs_handle_t * 380make_dataset_handle(libzfs_handle_t *hdl, const char *path) | 397static int 398make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc) |
381{ | 399{ |
382 zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); | |
383 char *logstr; | 400 char *logstr; |
401 libzfs_handle_t *hdl = zhp->zfs_hdl; |
|
384 | 402 |
385 if (zhp == NULL) 386 return (NULL); 387 388 zhp->zfs_hdl = hdl; 389 | |
390 /* 391 * Preserve history log string. 392 * any changes performed here will be 393 * logged as an internal event. 394 */ 395 logstr = zhp->zfs_hdl->libzfs_log_str; 396 zhp->zfs_hdl->libzfs_log_str = NULL; | 403 /* 404 * Preserve history log string. 405 * any changes performed here will be 406 * logged as an internal event. 407 */ 408 logstr = zhp->zfs_hdl->libzfs_log_str; 409 zhp->zfs_hdl->libzfs_log_str = NULL; |
397top: 398 (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); | |
399 | 410 |
400 if (get_stats(zhp) != 0) { | 411top: 412 if (put_stats_zhdl(zhp, zc) != 0) { |
401 zhp->zfs_hdl->libzfs_log_str = logstr; | 413 zhp->zfs_hdl->libzfs_log_str = logstr; |
402 free(zhp); 403 return (NULL); | 414 return (-1); |
404 } 405 | 415 } 416 |
417 |
|
406 if (zhp->zfs_dmustats.dds_inconsistent) { | 418 if (zhp->zfs_dmustats.dds_inconsistent) { |
407 zfs_cmd_t zc = { 0 }; | 419 zfs_cmd_t zc2 = { 0 }; |
408 409 /* 410 * If it is dds_inconsistent, then we've caught it in 411 * the middle of a 'zfs receive' or 'zfs destroy', and 412 * it is inconsistent from the ZPL's point of view, so 413 * can't be mounted. However, it could also be that we 414 * have crashed in the middle of one of those 415 * operations, in which case we need to get rid of the 416 * inconsistent state. We do that by either rolling 417 * back to the previous snapshot (which will fail if 418 * there is none), or destroying the filesystem. Note 419 * that if we are still in the middle of an active 420 * 'receive' or 'destroy', then the rollback and destroy 421 * will fail with EBUSY and we will drive on as usual. 422 */ 423 | 420 421 /* 422 * If it is dds_inconsistent, then we've caught it in 423 * the middle of a 'zfs receive' or 'zfs destroy', and 424 * it is inconsistent from the ZPL's point of view, so 425 * can't be mounted. However, it could also be that we 426 * have crashed in the middle of one of those 427 * operations, in which case we need to get rid of the 428 * inconsistent state. We do that by either rolling 429 * back to the previous snapshot (which will fail if 430 * there is none), or destroying the filesystem. Note 431 * that if we are still in the middle of an active 432 * 'receive' or 'destroy', then the rollback and destroy 433 * will fail with EBUSY and we will drive on as usual. 434 */ 435 |
424 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); | 436 (void) strlcpy(zc2.zc_name, zhp->zfs_name, 437 sizeof (zc2.zc_name)); |
425 426 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { 427 (void) zvol_remove_link(hdl, zhp->zfs_name); | 438 439 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { 440 (void) zvol_remove_link(hdl, zhp->zfs_name); |
428 zc.zc_objset_type = DMU_OST_ZVOL; | 441 zc2.zc_objset_type = DMU_OST_ZVOL; |
429 } else { | 442 } else { |
430 zc.zc_objset_type = DMU_OST_ZFS; | 443 zc2.zc_objset_type = DMU_OST_ZFS; |
431 } 432 433 /* 434 * If we can successfully destroy it, pretend that it 435 * never existed. 436 */ | 444 } 445 446 /* 447 * If we can successfully destroy it, pretend that it 448 * never existed. 449 */ |
437 if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) { | 450 if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc2) == 0) { |
438 zhp->zfs_hdl->libzfs_log_str = logstr; | 451 zhp->zfs_hdl->libzfs_log_str = logstr; |
439 free(zhp); | |
440 errno = ENOENT; | 452 errno = ENOENT; |
441 return (NULL); | 453 return (-1); |
442 } | 454 } |
443 /* If we can successfully roll it back, reget the stats */ 444 if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0) | 455 /* If we can successfully roll it back, reset the stats */ 456 if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc2) == 0) { 457 if (get_stats_ioctl(zhp, zc) != 0) { 458 zhp->zfs_hdl->libzfs_log_str = logstr; 459 return (-1); 460 } |
445 goto top; | 461 goto top; |
462 } |
|
446 } 447 448 /* 449 * We've managed to open the dataset and gather statistics. Determine 450 * the high-level type. 451 */ 452 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 453 zhp->zfs_head_type = ZFS_TYPE_VOLUME; --- 8 unchanged lines hidden (view full) --- 462 zhp->zfs_type = ZFS_TYPE_VOLUME; 463 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 464 zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 465 else 466 abort(); /* we should never see any other types */ 467 468 zhp->zfs_hdl->libzfs_log_str = logstr; 469 zhp->zpool_hdl = zpool_handle(zhp); | 463 } 464 465 /* 466 * We've managed to open the dataset and gather statistics. Determine 467 * the high-level type. 468 */ 469 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 470 zhp->zfs_head_type = ZFS_TYPE_VOLUME; --- 8 unchanged lines hidden (view full) --- 479 zhp->zfs_type = ZFS_TYPE_VOLUME; 480 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 481 zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 482 else 483 abort(); /* we should never see any other types */ 484 485 zhp->zfs_hdl->libzfs_log_str = logstr; 486 zhp->zpool_hdl = zpool_handle(zhp); |
487 return (0); 488} 489 490zfs_handle_t * 491make_dataset_handle(libzfs_handle_t *hdl, const char *path) 492{ 493 zfs_cmd_t zc = { 0 }; 494 495 zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 496 497 if (zhp == NULL) 498 return (NULL); 499 500 zhp->zfs_hdl = hdl; 501 (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 502 if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) { 503 free(zhp); 504 return (NULL); 505 } 506 if (get_stats_ioctl(zhp, &zc) == -1) { 507 zcmd_free_nvlists(&zc); 508 free(zhp); 509 return (NULL); 510 } 511 if (make_dataset_handle_common(zhp, &zc) == -1) { 512 free(zhp); 513 zhp = NULL; 514 } 515 zcmd_free_nvlists(&zc); |
|
470 return (zhp); 471} 472 | 516 return (zhp); 517} 518 |
519static zfs_handle_t * 520make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc) 521{ 522 zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 523 524 if (zhp == NULL) 525 return (NULL); 526 527 zhp->zfs_hdl = hdl; 528 (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name)); 529 if (make_dataset_handle_common(zhp, zc) == -1) { 530 free(zhp); 531 return (NULL); 532 } 533 return (zhp); 534} 535 |
|
473/* 474 * Opens the given snapshot, filesystem, or volume. The 'types' 475 * argument is a mask of acceptable types. The function will print an 476 * appropriate error message and return NULL if it can't be opened. 477 */ 478zfs_handle_t * 479zfs_open(libzfs_handle_t *hdl, const char *path, int types) 480{ --- 39 unchanged lines hidden (view full) --- 520{ 521 if (zhp->zfs_mntopts) 522 free(zhp->zfs_mntopts); 523 nvlist_free(zhp->zfs_props); 524 nvlist_free(zhp->zfs_user_props); 525 free(zhp); 526} 527 | 536/* 537 * Opens the given snapshot, filesystem, or volume. The 'types' 538 * argument is a mask of acceptable types. The function will print an 539 * appropriate error message and return NULL if it can't be opened. 540 */ 541zfs_handle_t * 542zfs_open(libzfs_handle_t *hdl, const char *path, int types) 543{ --- 39 unchanged lines hidden (view full) --- 583{ 584 if (zhp->zfs_mntopts) 585 free(zhp->zfs_mntopts); 586 nvlist_free(zhp->zfs_props); 587 nvlist_free(zhp->zfs_user_props); 588 free(zhp); 589} 590 |
591typedef struct mnttab_node { 592 struct mnttab mtn_mt; 593 avl_node_t mtn_node; 594} mnttab_node_t; 595 596static int 597libzfs_mnttab_cache_compare(const void *arg1, const void *arg2) 598{ 599 const mnttab_node_t *mtn1 = arg1; 600 const mnttab_node_t *mtn2 = arg2; 601 int rv; 602 603 rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special); 604 605 if (rv == 0) 606 return (0); 607 return (rv > 0 ? 1 : -1); 608} 609 610void 611libzfs_mnttab_init(libzfs_handle_t *hdl) 612{ 613 assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0); 614 avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare, 615 sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node)); 616} 617 618void 619libzfs_mnttab_update(libzfs_handle_t *hdl) 620{ 621 struct mnttab entry; 622 623 rewind(hdl->libzfs_mnttab); 624 while (getmntent(hdl->libzfs_mnttab, &entry) == 0) { 625 mnttab_node_t *mtn; 626 627 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) 628 continue; 629 mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); 630 mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special); 631 mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp); 632 mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype); 633 mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts); 634 avl_add(&hdl->libzfs_mnttab_cache, mtn); 635 } 636} 637 638void 639libzfs_mnttab_fini(libzfs_handle_t *hdl) 640{ 641 void *cookie = NULL; 642 mnttab_node_t *mtn; 643 644 while (mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) { 645 free(mtn->mtn_mt.mnt_special); 646 free(mtn->mtn_mt.mnt_mountp); 647 free(mtn->mtn_mt.mnt_fstype); 648 free(mtn->mtn_mt.mnt_mntopts); 649 free(mtn); 650 } 651 avl_destroy(&hdl->libzfs_mnttab_cache); 652} 653 654void 655libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable) 656{ 657 hdl->libzfs_mnttab_enable = enable; 658} 659 |
|
528int | 660int |
661libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname, 662 struct mnttab *entry) 663{ 664 mnttab_node_t find; 665 mnttab_node_t *mtn; 666 667 if (!hdl->libzfs_mnttab_enable) { 668 struct mnttab srch = { 0 }; 669 670 if (avl_numnodes(&hdl->libzfs_mnttab_cache)) 671 libzfs_mnttab_fini(hdl); 672 rewind(hdl->libzfs_mnttab); 673 srch.mnt_special = (char *)fsname; 674 srch.mnt_fstype = MNTTYPE_ZFS; 675 if (getmntany(hdl->libzfs_mnttab, entry, &srch) == 0) 676 return (0); 677 else 678 return (ENOENT); 679 } 680 681 if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) 682 libzfs_mnttab_update(hdl); 683 684 find.mtn_mt.mnt_special = (char *)fsname; 685 mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL); 686 if (mtn) { 687 *entry = mtn->mtn_mt; 688 return (0); 689 } 690 return (ENOENT); 691} 692 693void 694libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special, 695 const char *mountp, const char *mntopts) 696{ 697 mnttab_node_t *mtn; 698 699 if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) 700 return; 701 mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); 702 mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special); 703 mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp); 704 mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS); 705 mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts); 706 avl_add(&hdl->libzfs_mnttab_cache, mtn); 707} 708 709void 710libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname) 711{ 712 mnttab_node_t find; 713 mnttab_node_t *ret; 714 715 find.mtn_mt.mnt_special = (char *)fsname; 716 if (ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) { 717 avl_remove(&hdl->libzfs_mnttab_cache, ret); 718 free(ret->mtn_mt.mnt_special); 719 free(ret->mtn_mt.mnt_mountp); 720 free(ret->mtn_mt.mnt_fstype); 721 free(ret->mtn_mt.mnt_mntopts); 722 free(ret); 723 } 724} 725 726int |
|
529zfs_spa_version(zfs_handle_t *zhp, int *spa_version) 530{ 531 zpool_handle_t *zpool_handle = zhp->zpool_hdl; 532 533 if (zpool_handle == NULL) 534 return (-1); 535 536 *spa_version = zpool_get_prop_int(zpool_handle, --- 37 unchanged lines hidden (view full) --- 574 int chosen_normal = -1; 575 int chosen_utf = -1; 576 577 if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 578 (void) no_memory(hdl); 579 return (NULL); 580 } 581 | 727zfs_spa_version(zfs_handle_t *zhp, int *spa_version) 728{ 729 zpool_handle_t *zpool_handle = zhp->zpool_hdl; 730 731 if (zpool_handle == NULL) 732 return (-1); 733 734 *spa_version = zpool_get_prop_int(zpool_handle, --- 37 unchanged lines hidden (view full) --- 772 int chosen_normal = -1; 773 int chosen_utf = -1; 774 775 if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 776 (void) no_memory(hdl); 777 return (NULL); 778 } 779 |
780 /* 781 * Make sure this property is valid and applies to this type. 782 */ 783 |
|
582 elem = NULL; 583 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 584 const char *propname = nvpair_name(elem); 585 | 784 elem = NULL; 785 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 786 const char *propname = nvpair_name(elem); 787 |
586 /* 587 * Make sure this property is valid and applies to this type. 588 */ 589 if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) { 590 if (!zfs_prop_user(propname)) { 591 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 592 "invalid property '%s'"), propname); 593 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 594 goto error; 595 } 596 | 788 prop = zfs_name_to_prop(propname); 789 if (prop == ZPROP_INVAL && zfs_prop_user(propname)) { |
597 /* | 790 /* |
598 * If this is a user property, make sure it's a | 791 * This is a user property: make sure it's a |
599 * string, and that it's less than ZAP_MAXNAMELEN. 600 */ 601 if (nvpair_type(elem) != DATA_TYPE_STRING) { 602 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 603 "'%s' must be a string"), propname); 604 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 605 goto error; 606 } --- 9 unchanged lines hidden (view full) --- 616 (void) nvpair_value_string(elem, &strval); 617 if (nvlist_add_string(ret, propname, strval) != 0) { 618 (void) no_memory(hdl); 619 goto error; 620 } 621 continue; 622 } 623 | 792 * string, and that it's less than ZAP_MAXNAMELEN. 793 */ 794 if (nvpair_type(elem) != DATA_TYPE_STRING) { 795 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 796 "'%s' must be a string"), propname); 797 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 798 goto error; 799 } --- 9 unchanged lines hidden (view full) --- 809 (void) nvpair_value_string(elem, &strval); 810 if (nvlist_add_string(ret, propname, strval) != 0) { 811 (void) no_memory(hdl); 812 goto error; 813 } 814 continue; 815 } 816 |
817 /* 818 * Currently, only user properties can be modified on 819 * snapshots. 820 */ |
|
624 if (type == ZFS_TYPE_SNAPSHOT) { 625 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 626 "this property can not be modified for snapshots")); 627 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 628 goto error; 629 } 630 | 821 if (type == ZFS_TYPE_SNAPSHOT) { 822 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 823 "this property can not be modified for snapshots")); 824 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 825 goto error; 826 } 827 |
828 if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) { 829 zfs_userquota_prop_t uqtype; 830 char newpropname[128]; 831 char domain[128]; 832 uint64_t rid; 833 uint64_t valary[3]; 834 835 if (userquota_propname_decode(propname, zoned, 836 &uqtype, domain, sizeof (domain), &rid) != 0) { 837 zfs_error_aux(hdl, 838 dgettext(TEXT_DOMAIN, 839 "'%s' has an invalid user/group name"), 840 propname); 841 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 842 goto error; 843 } 844 845 if (uqtype != ZFS_PROP_USERQUOTA && 846 uqtype != ZFS_PROP_GROUPQUOTA) { 847 zfs_error_aux(hdl, 848 dgettext(TEXT_DOMAIN, "'%s' is readonly"), 849 propname); 850 (void) zfs_error(hdl, EZFS_PROPREADONLY, 851 errbuf); 852 goto error; 853 } 854 855 if (nvpair_type(elem) == DATA_TYPE_STRING) { 856 (void) nvpair_value_string(elem, &strval); 857 if (strcmp(strval, "none") == 0) { 858 intval = 0; 859 } else if (zfs_nicestrtonum(hdl, 860 strval, &intval) != 0) { 861 (void) zfs_error(hdl, 862 EZFS_BADPROP, errbuf); 863 goto error; 864 } 865 } else if (nvpair_type(elem) == 866 DATA_TYPE_UINT64) { 867 (void) nvpair_value_uint64(elem, &intval); 868 if (intval == 0) { 869 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 870 "use 'none' to disable " 871 "userquota/groupquota")); 872 goto error; 873 } 874 } else { 875 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 876 "'%s' must be a number"), propname); 877 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 878 goto error; 879 } 880 881 (void) snprintf(newpropname, sizeof (newpropname), 882 "%s%s", zfs_userquota_prop_prefixes[uqtype], 883 domain); 884 valary[0] = uqtype; 885 valary[1] = rid; 886 valary[2] = intval; 887 if (nvlist_add_uint64_array(ret, newpropname, 888 valary, 3) != 0) { 889 (void) no_memory(hdl); 890 goto error; 891 } 892 continue; 893 } 894 895 if (prop == ZPROP_INVAL) { 896 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 897 "invalid property '%s'"), propname); 898 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 899 goto error; 900 } 901 |
|
631 if (!zfs_prop_valid_for_type(prop, type)) { 632 zfs_error_aux(hdl, 633 dgettext(TEXT_DOMAIN, "'%s' does not " 634 "apply to datasets of this type"), propname); 635 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 636 goto error; 637 } 638 --- 123 unchanged lines hidden (view full) --- 762 "a non-global zone"), propname); 763 (void) zfs_error(hdl, EZFS_ZONED, 764 errbuf); 765 goto error; 766 } 767 } else if (getzoneid() != GLOBAL_ZONEID) { 768 /* 769 * If zoned property is 'off', this must be in | 902 if (!zfs_prop_valid_for_type(prop, type)) { 903 zfs_error_aux(hdl, 904 dgettext(TEXT_DOMAIN, "'%s' does not " 905 "apply to datasets of this type"), propname); 906 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 907 goto error; 908 } 909 --- 123 unchanged lines hidden (view full) --- 1033 "a non-global zone"), propname); 1034 (void) zfs_error(hdl, EZFS_ZONED, 1035 errbuf); 1036 goto error; 1037 } 1038 } else if (getzoneid() != GLOBAL_ZONEID) { 1039 /* 1040 * If zoned property is 'off', this must be in |
770 * a globle zone. If not, something is wrong. | 1041 * a global zone. If not, something is wrong. |
771 */ 772 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 773 "'%s' cannot be set while dataset " 774 "'zoned' property is set"), propname); 775 (void) zfs_error(hdl, EZFS_ZONED, errbuf); 776 goto error; 777 } 778 --- 167 unchanged lines hidden (view full) --- 946 } 947 return (ret); 948 949error: 950 nvlist_free(ret); 951 return (NULL); 952} 953 | 1042 */ 1043 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1044 "'%s' cannot be set while dataset " 1045 "'zoned' property is set"), propname); 1046 (void) zfs_error(hdl, EZFS_ZONED, errbuf); 1047 goto error; 1048 } 1049 --- 167 unchanged lines hidden (view full) --- 1217 } 1218 return (ret); 1219 1220error: 1221 nvlist_free(ret); 1222 return (NULL); 1223} 1224 |
954static int 955zfs_get_perm_who(const char *who, zfs_deleg_who_type_t *who_type, 956 uint64_t *ret_who) 957{ 958 struct passwd *pwd; 959 struct group *grp; 960 uid_t id; 961 962 if (*who_type == ZFS_DELEG_EVERYONE || *who_type == ZFS_DELEG_CREATE || 963 *who_type == ZFS_DELEG_NAMED_SET) { 964 *ret_who = -1; 965 return (0); 966 } 967 if (who == NULL && !(*who_type == ZFS_DELEG_EVERYONE)) 968 return (EZFS_BADWHO); 969 970 if (*who_type == ZFS_DELEG_WHO_UNKNOWN && 971 strcmp(who, "everyone") == 0) { 972 *ret_who = -1; 973 *who_type = ZFS_DELEG_EVERYONE; 974 return (0); 975 } 976 977 pwd = getpwnam(who); 978 grp = getgrnam(who); 979 980 if ((*who_type == ZFS_DELEG_USER) && pwd) { 981 *ret_who = pwd->pw_uid; 982 } else if ((*who_type == ZFS_DELEG_GROUP) && grp) { 983 *ret_who = grp->gr_gid; 984 } else if (pwd) { 985 *ret_who = pwd->pw_uid; 986 *who_type = ZFS_DELEG_USER; 987 } else if (grp) { 988 *ret_who = grp->gr_gid; 989 *who_type = ZFS_DELEG_GROUP; 990 } else { 991 char *end; 992 993 id = strtol(who, &end, 10); 994 if (errno != 0 || *end != '\0') { 995 return (EZFS_BADWHO); 996 } else { 997 *ret_who = id; 998 if (*who_type == ZFS_DELEG_WHO_UNKNOWN) 999 *who_type = ZFS_DELEG_USER; 1000 } 1001 } 1002 1003 return (0); 1004} 1005 1006static void 1007zfs_perms_add_to_nvlist(nvlist_t *who_nvp, char *name, nvlist_t *perms_nvp) 1008{ 1009 if (perms_nvp != NULL) { 1010 verify(nvlist_add_nvlist(who_nvp, 1011 name, perms_nvp) == 0); 1012 } else { 1013 verify(nvlist_add_boolean(who_nvp, name) == 0); 1014 } 1015} 1016 1017static void 1018helper(zfs_deleg_who_type_t who_type, uint64_t whoid, char *whostr, 1019 zfs_deleg_inherit_t inherit, nvlist_t *who_nvp, nvlist_t *perms_nvp, 1020 nvlist_t *sets_nvp) 1021{ 1022 boolean_t do_perms, do_sets; 1023 char name[ZFS_MAX_DELEG_NAME]; 1024 1025 do_perms = (nvlist_next_nvpair(perms_nvp, NULL) != NULL); 1026 do_sets = (nvlist_next_nvpair(sets_nvp, NULL) != NULL); 1027 1028 if (!do_perms && !do_sets) 1029 do_perms = do_sets = B_TRUE; 1030 1031 if (do_perms) { 1032 zfs_deleg_whokey(name, who_type, inherit, 1033 (who_type == ZFS_DELEG_NAMED_SET) ? 1034 whostr : (void *)&whoid); 1035 zfs_perms_add_to_nvlist(who_nvp, name, perms_nvp); 1036 } 1037 if (do_sets) { 1038 zfs_deleg_whokey(name, toupper(who_type), inherit, 1039 (who_type == ZFS_DELEG_NAMED_SET) ? 1040 whostr : (void *)&whoid); 1041 zfs_perms_add_to_nvlist(who_nvp, name, sets_nvp); 1042 } 1043} 1044 1045static void 1046zfs_perms_add_who_nvlist(nvlist_t *who_nvp, uint64_t whoid, void *whostr, 1047 nvlist_t *perms_nvp, nvlist_t *sets_nvp, 1048 zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit) 1049{ 1050 if (who_type == ZFS_DELEG_NAMED_SET || who_type == ZFS_DELEG_CREATE) { 1051 helper(who_type, whoid, whostr, 0, 1052 who_nvp, perms_nvp, sets_nvp); 1053 } else { 1054 if (inherit & ZFS_DELEG_PERM_LOCAL) { 1055 helper(who_type, whoid, whostr, ZFS_DELEG_LOCAL, 1056 who_nvp, perms_nvp, sets_nvp); 1057 } 1058 if (inherit & ZFS_DELEG_PERM_DESCENDENT) { 1059 helper(who_type, whoid, whostr, ZFS_DELEG_DESCENDENT, 1060 who_nvp, perms_nvp, sets_nvp); 1061 } 1062 } 1063} 1064 | |
1065/* | 1225/* |
1066 * Construct nvlist to pass down to kernel for setting/removing permissions. 1067 * 1068 * The nvlist is constructed as a series of nvpairs with an optional embedded 1069 * nvlist of permissions to remove or set. The topmost nvpairs are the actual 1070 * base attribute named stored in the dsl. 1071 * Arguments: 1072 * 1073 * whostr: is a comma separated list of users, groups, or a single set name. 1074 * whostr may be null for everyone or create perms. 1075 * who_type: is the type of entry in whostr. Typically this will be 1076 * ZFS_DELEG_WHO_UNKNOWN. 1077 * perms: common separated list of permissions. May be null if user 1078 * is requested to remove permissions by who. 1079 * inherit: Specifies the inheritance of the permissions. Will be either 1080 * ZFS_DELEG_PERM_LOCAL and/or ZFS_DELEG_PERM_DESCENDENT. 1081 * nvp The constructed nvlist to pass to zfs_perm_set(). 1082 * The output nvp will look something like this. 1083 * ul$1234 -> {create ; destroy } 1084 * Ul$1234 -> { @myset } 1085 * s-$@myset - { snapshot; checksum; compression } 1086 */ 1087int 1088zfs_build_perms(zfs_handle_t *zhp, char *whostr, char *perms, 1089 zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit, nvlist_t **nvp) 1090{ 1091 nvlist_t *who_nvp; 1092 nvlist_t *perms_nvp = NULL; 1093 nvlist_t *sets_nvp = NULL; 1094 char errbuf[1024]; 1095 char *who_tok, *perm; 1096 int error; 1097 1098 *nvp = NULL; 1099 1100 if (perms) { 1101 if ((error = nvlist_alloc(&perms_nvp, 1102 NV_UNIQUE_NAME, 0)) != 0) { 1103 return (1); 1104 } 1105 if ((error = nvlist_alloc(&sets_nvp, 1106 NV_UNIQUE_NAME, 0)) != 0) { 1107 nvlist_free(perms_nvp); 1108 return (1); 1109 } 1110 } 1111 1112 if ((error = nvlist_alloc(&who_nvp, NV_UNIQUE_NAME, 0)) != 0) { 1113 if (perms_nvp) 1114 nvlist_free(perms_nvp); 1115 if (sets_nvp) 1116 nvlist_free(sets_nvp); 1117 return (1); 1118 } 1119 1120 if (who_type == ZFS_DELEG_NAMED_SET) { 1121 namecheck_err_t why; 1122 char what; 1123 1124 if ((error = permset_namecheck(whostr, &why, &what)) != 0) { 1125 nvlist_free(who_nvp); 1126 if (perms_nvp) 1127 nvlist_free(perms_nvp); 1128 if (sets_nvp) 1129 nvlist_free(sets_nvp); 1130 1131 switch (why) { 1132 case NAME_ERR_NO_AT: 1133 zfs_error_aux(zhp->zfs_hdl, 1134 dgettext(TEXT_DOMAIN, 1135 "set definition must begin with an '@' " 1136 "character")); 1137 } 1138 return (zfs_error(zhp->zfs_hdl, 1139 EZFS_BADPERMSET, whostr)); 1140 } 1141 } 1142 1143 /* 1144 * Build up nvlist(s) of permissions. Two nvlists are maintained. 1145 * The first nvlist perms_nvp will have normal permissions and the 1146 * other sets_nvp will have only permssion set names in it. 1147 */ 1148 for (perm = strtok(perms, ","); perm; perm = strtok(NULL, ",")) { 1149 const char *perm_canonical = zfs_deleg_canonicalize_perm(perm); 1150 1151 if (perm_canonical) { 1152 verify(nvlist_add_boolean(perms_nvp, 1153 perm_canonical) == 0); 1154 } else if (perm[0] == '@') { 1155 verify(nvlist_add_boolean(sets_nvp, perm) == 0); 1156 } else { 1157 nvlist_free(who_nvp); 1158 nvlist_free(perms_nvp); 1159 nvlist_free(sets_nvp); 1160 return (zfs_error(zhp->zfs_hdl, EZFS_BADPERM, perm)); 1161 } 1162 } 1163 1164 if (whostr && who_type != ZFS_DELEG_CREATE) { 1165 who_tok = strtok(whostr, ","); 1166 if (who_tok == NULL) { 1167 nvlist_free(who_nvp); 1168 if (perms_nvp) 1169 nvlist_free(perms_nvp); 1170 if (sets_nvp) 1171 nvlist_free(sets_nvp); 1172 (void) snprintf(errbuf, sizeof (errbuf), 1173 dgettext(TEXT_DOMAIN, "Who string is NULL"), 1174 whostr); 1175 return (zfs_error(zhp->zfs_hdl, EZFS_BADWHO, errbuf)); 1176 } 1177 } 1178 1179 /* 1180 * Now create the nvlist(s) 1181 */ 1182 do { 1183 uint64_t who_id; 1184 1185 error = zfs_get_perm_who(who_tok, &who_type, 1186 &who_id); 1187 if (error) { 1188 nvlist_free(who_nvp); 1189 if (perms_nvp) 1190 nvlist_free(perms_nvp); 1191 if (sets_nvp) 1192 nvlist_free(sets_nvp); 1193 (void) snprintf(errbuf, sizeof (errbuf), 1194 dgettext(TEXT_DOMAIN, 1195 "Unable to determine uid/gid for " 1196 "%s "), who_tok); 1197 return (zfs_error(zhp->zfs_hdl, EZFS_BADWHO, errbuf)); 1198 } 1199 1200 /* 1201 * add entries for both local and descendent when required 1202 */ 1203 zfs_perms_add_who_nvlist(who_nvp, who_id, who_tok, 1204 perms_nvp, sets_nvp, who_type, inherit); 1205 1206 } while (who_tok = strtok(NULL, ",")); 1207 *nvp = who_nvp; 1208 return (0); 1209} 1210 1211static int 1212zfs_perm_set_common(zfs_handle_t *zhp, nvlist_t *nvp, boolean_t unset) 1213{ 1214 zfs_cmd_t zc = { 0 }; 1215 int error; 1216 char errbuf[1024]; 1217 1218 (void) snprintf(errbuf, sizeof (errbuf), 1219 dgettext(TEXT_DOMAIN, "Cannot update 'allows' for '%s'"), 1220 zhp->zfs_name); 1221 1222 if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, nvp)) 1223 return (-1); 1224 1225 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1226 zc.zc_perm_action = unset; 1227 1228 error = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SET_FSACL, &zc); 1229 if (error && errno == ENOTSUP) { 1230 (void) snprintf(errbuf, sizeof (errbuf), 1231 gettext("Pool must be upgraded to use 'allow/unallow'")); 1232 zcmd_free_nvlists(&zc); 1233 return (zfs_error(zhp->zfs_hdl, EZFS_BADVERSION, errbuf)); 1234 } else if (error) { 1235 return (zfs_standard_error(zhp->zfs_hdl, errno, errbuf)); 1236 } 1237 zcmd_free_nvlists(&zc); 1238 1239 return (error); 1240} 1241 1242int 1243zfs_perm_set(zfs_handle_t *zhp, nvlist_t *nvp) 1244{ 1245 return (zfs_perm_set_common(zhp, nvp, B_FALSE)); 1246} 1247 1248int 1249zfs_perm_remove(zfs_handle_t *zhp, nvlist_t *perms) 1250{ 1251 return (zfs_perm_set_common(zhp, perms, B_TRUE)); 1252} 1253 1254static int 1255perm_compare(const void *arg1, const void *arg2) 1256{ 1257 const zfs_perm_node_t *node1 = arg1; 1258 const zfs_perm_node_t *node2 = arg2; 1259 int ret; 1260 1261 ret = strcmp(node1->z_pname, node2->z_pname); 1262 1263 if (ret > 0) 1264 return (1); 1265 if (ret < 0) 1266 return (-1); 1267 else 1268 return (0); 1269} 1270 1271static void 1272zfs_destroy_perm_tree(avl_tree_t *tree) 1273{ 1274 zfs_perm_node_t *permnode; 1275 void *cookie = NULL; 1276 1277 while ((permnode = avl_destroy_nodes(tree, &cookie)) != NULL) 1278 free(permnode); 1279 avl_destroy(tree); 1280} 1281 1282static void 1283zfs_destroy_tree(avl_tree_t *tree) 1284{ 1285 zfs_allow_node_t *allownode; 1286 void *cookie = NULL; 1287 1288 while ((allownode = avl_destroy_nodes(tree, &cookie)) != NULL) { 1289 zfs_destroy_perm_tree(&allownode->z_localdescend); 1290 zfs_destroy_perm_tree(&allownode->z_local); 1291 zfs_destroy_perm_tree(&allownode->z_descend); 1292 free(allownode); 1293 } 1294 avl_destroy(tree); 1295} 1296 1297void 1298zfs_free_allows(zfs_allow_t *allow) 1299{ 1300 zfs_allow_t *allownext; 1301 zfs_allow_t *freeallow; 1302 1303 allownext = allow; 1304 while (allownext) { 1305 zfs_destroy_tree(&allownext->z_sets); 1306 zfs_destroy_tree(&allownext->z_crperms); 1307 zfs_destroy_tree(&allownext->z_user); 1308 zfs_destroy_tree(&allownext->z_group); 1309 zfs_destroy_tree(&allownext->z_everyone); 1310 freeallow = allownext; 1311 allownext = allownext->z_next; 1312 free(freeallow); 1313 } 1314} 1315 1316static zfs_allow_t * 1317zfs_alloc_perm_tree(zfs_handle_t *zhp, zfs_allow_t *prev, char *setpoint) 1318{ 1319 zfs_allow_t *ptree; 1320 1321 if ((ptree = zfs_alloc(zhp->zfs_hdl, 1322 sizeof (zfs_allow_t))) == NULL) { 1323 return (NULL); 1324 } 1325 1326 (void) strlcpy(ptree->z_setpoint, setpoint, sizeof (ptree->z_setpoint)); 1327 avl_create(&ptree->z_sets, 1328 perm_compare, sizeof (zfs_allow_node_t), 1329 offsetof(zfs_allow_node_t, z_node)); 1330 avl_create(&ptree->z_crperms, 1331 perm_compare, sizeof (zfs_allow_node_t), 1332 offsetof(zfs_allow_node_t, z_node)); 1333 avl_create(&ptree->z_user, 1334 perm_compare, sizeof (zfs_allow_node_t), 1335 offsetof(zfs_allow_node_t, z_node)); 1336 avl_create(&ptree->z_group, 1337 perm_compare, sizeof (zfs_allow_node_t), 1338 offsetof(zfs_allow_node_t, z_node)); 1339 avl_create(&ptree->z_everyone, 1340 perm_compare, sizeof (zfs_allow_node_t), 1341 offsetof(zfs_allow_node_t, z_node)); 1342 1343 if (prev) 1344 prev->z_next = ptree; 1345 ptree->z_next = NULL; 1346 return (ptree); 1347} 1348 1349/* 1350 * Add permissions to the appropriate AVL permission tree. 1351 * The appropriate tree may not be the requested tree. 1352 * For example if ld indicates a local permission, but 1353 * same permission also exists as a descendent permission 1354 * then the permission will be removed from the descendent 1355 * tree and add the the local+descendent tree. 1356 */ 1357static int 1358zfs_coalesce_perm(zfs_handle_t *zhp, zfs_allow_node_t *allownode, 1359 char *perm, char ld) 1360{ 1361 zfs_perm_node_t pnode, *permnode, *permnode2; 1362 zfs_perm_node_t *newnode; 1363 avl_index_t where, where2; 1364 avl_tree_t *tree, *altree; 1365 1366 (void) strlcpy(pnode.z_pname, perm, sizeof (pnode.z_pname)); 1367 1368 if (ld == ZFS_DELEG_NA) { 1369 tree = &allownode->z_localdescend; 1370 altree = &allownode->z_descend; 1371 } else if (ld == ZFS_DELEG_LOCAL) { 1372 tree = &allownode->z_local; 1373 altree = &allownode->z_descend; 1374 } else { 1375 tree = &allownode->z_descend; 1376 altree = &allownode->z_local; 1377 } 1378 permnode = avl_find(tree, &pnode, &where); 1379 permnode2 = avl_find(altree, &pnode, &where2); 1380 1381 if (permnode2) { 1382 avl_remove(altree, permnode2); 1383 free(permnode2); 1384 if (permnode == NULL) { 1385 tree = &allownode->z_localdescend; 1386 } 1387 } 1388 1389 /* 1390 * Now insert new permission in either requested location 1391 * local/descendent or into ld when perm will exist in both. 1392 */ 1393 if (permnode == NULL) { 1394 if ((newnode = zfs_alloc(zhp->zfs_hdl, 1395 sizeof (zfs_perm_node_t))) == NULL) { 1396 return (-1); 1397 } 1398 *newnode = pnode; 1399 avl_add(tree, newnode); 1400 } 1401 return (0); 1402} 1403 1404/* 1405 * Uggh, this is going to be a bit complicated. 1406 * we have an nvlist coming out of the kernel that 1407 * will indicate where the permission is set and then 1408 * it will contain allow of the various "who's", and what 1409 * their permissions are. To further complicate this 1410 * we will then have to coalesce the local,descendent 1411 * and local+descendent permissions where appropriate. 1412 * The kernel only knows about a permission as being local 1413 * or descendent, but not both. 1414 * 1415 * In order to make this easier for zfs_main to deal with 1416 * a series of AVL trees will be used to maintain 1417 * all of this, primarily for sorting purposes as well 1418 * as the ability to quickly locate a specific entry. 1419 * 1420 * What we end up with are tree's for sets, create perms, 1421 * user, groups and everyone. With each of those trees 1422 * we have subtrees for local, descendent and local+descendent 1423 * permissions. 1424 */ 1425int 1426zfs_perm_get(zfs_handle_t *zhp, zfs_allow_t **zfs_perms) 1427{ 1428 zfs_cmd_t zc = { 0 }; 1429 int error; 1430 nvlist_t *nvlist; 1431 nvlist_t *permnv, *sourcenv; 1432 nvpair_t *who_pair, *source_pair; 1433 nvpair_t *perm_pair; 1434 char errbuf[1024]; 1435 zfs_allow_t *zallowp, *newallowp; 1436 char ld; 1437 char *nvpname; 1438 uid_t uid; 1439 gid_t gid; 1440 avl_tree_t *tree; 1441 avl_index_t where; 1442 1443 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1444 1445 if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 1446 return (-1); 1447 1448 while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) { 1449 if (errno == ENOMEM) { 1450 if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, &zc) != 0) { 1451 zcmd_free_nvlists(&zc); 1452 return (-1); 1453 } 1454 } else if (errno == ENOTSUP) { 1455 zcmd_free_nvlists(&zc); 1456 (void) snprintf(errbuf, sizeof (errbuf), 1457 gettext("Pool must be upgraded to use 'allow'")); 1458 return (zfs_error(zhp->zfs_hdl, 1459 EZFS_BADVERSION, errbuf)); 1460 } else { 1461 zcmd_free_nvlists(&zc); 1462 return (-1); 1463 } 1464 } 1465 1466 if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &nvlist) != 0) { 1467 zcmd_free_nvlists(&zc); 1468 return (-1); 1469 } 1470 1471 zcmd_free_nvlists(&zc); 1472 1473 source_pair = nvlist_next_nvpair(nvlist, NULL); 1474 1475 if (source_pair == NULL) { 1476 *zfs_perms = NULL; 1477 return (0); 1478 } 1479 1480 *zfs_perms = zfs_alloc_perm_tree(zhp, NULL, nvpair_name(source_pair)); 1481 if (*zfs_perms == NULL) { 1482 return (0); 1483 } 1484 1485 zallowp = *zfs_perms; 1486 1487 for (;;) { 1488 struct passwd *pwd; 1489 struct group *grp; 1490 zfs_allow_node_t *allownode; 1491 zfs_allow_node_t findallownode; 1492 zfs_allow_node_t *newallownode; 1493 1494 (void) strlcpy(zallowp->z_setpoint, 1495 nvpair_name(source_pair), 1496 sizeof (zallowp->z_setpoint)); 1497 1498 if ((error = nvpair_value_nvlist(source_pair, &sourcenv)) != 0) 1499 goto abort; 1500 1501 /* 1502 * Make sure nvlist is composed correctly 1503 */ 1504 if (zfs_deleg_verify_nvlist(sourcenv)) { 1505 goto abort; 1506 } 1507 1508 who_pair = nvlist_next_nvpair(sourcenv, NULL); 1509 if (who_pair == NULL) { 1510 goto abort; 1511 } 1512 1513 do { 1514 error = nvpair_value_nvlist(who_pair, &permnv); 1515 if (error) { 1516 goto abort; 1517 } 1518 1519 /* 1520 * First build up the key to use 1521 * for looking up in the various 1522 * who trees. 1523 */ 1524 ld = nvpair_name(who_pair)[1]; 1525 nvpname = nvpair_name(who_pair); 1526 switch (nvpair_name(who_pair)[0]) { 1527 case ZFS_DELEG_USER: 1528 case ZFS_DELEG_USER_SETS: 1529 tree = &zallowp->z_user; 1530 uid = atol(&nvpname[3]); 1531 pwd = getpwuid(uid); 1532 (void) snprintf(findallownode.z_key, 1533 sizeof (findallownode.z_key), "user %s", 1534 (pwd) ? pwd->pw_name : 1535 &nvpair_name(who_pair)[3]); 1536 break; 1537 case ZFS_DELEG_GROUP: 1538 case ZFS_DELEG_GROUP_SETS: 1539 tree = &zallowp->z_group; 1540 gid = atol(&nvpname[3]); 1541 grp = getgrgid(gid); 1542 (void) snprintf(findallownode.z_key, 1543 sizeof (findallownode.z_key), "group %s", 1544 (grp) ? grp->gr_name : 1545 &nvpair_name(who_pair)[3]); 1546 break; 1547 case ZFS_DELEG_CREATE: 1548 case ZFS_DELEG_CREATE_SETS: 1549 tree = &zallowp->z_crperms; 1550 (void) strlcpy(findallownode.z_key, "", 1551 sizeof (findallownode.z_key)); 1552 break; 1553 case ZFS_DELEG_EVERYONE: 1554 case ZFS_DELEG_EVERYONE_SETS: 1555 (void) snprintf(findallownode.z_key, 1556 sizeof (findallownode.z_key), "everyone"); 1557 tree = &zallowp->z_everyone; 1558 break; 1559 case ZFS_DELEG_NAMED_SET: 1560 case ZFS_DELEG_NAMED_SET_SETS: 1561 (void) snprintf(findallownode.z_key, 1562 sizeof (findallownode.z_key), "%s", 1563 &nvpair_name(who_pair)[3]); 1564 tree = &zallowp->z_sets; 1565 break; 1566 } 1567 1568 /* 1569 * Place who in tree 1570 */ 1571 allownode = avl_find(tree, &findallownode, &where); 1572 if (allownode == NULL) { 1573 if ((newallownode = zfs_alloc(zhp->zfs_hdl, 1574 sizeof (zfs_allow_node_t))) == NULL) { 1575 goto abort; 1576 } 1577 avl_create(&newallownode->z_localdescend, 1578 perm_compare, 1579 sizeof (zfs_perm_node_t), 1580 offsetof(zfs_perm_node_t, z_node)); 1581 avl_create(&newallownode->z_local, 1582 perm_compare, 1583 sizeof (zfs_perm_node_t), 1584 offsetof(zfs_perm_node_t, z_node)); 1585 avl_create(&newallownode->z_descend, 1586 perm_compare, 1587 sizeof (zfs_perm_node_t), 1588 offsetof(zfs_perm_node_t, z_node)); 1589 (void) strlcpy(newallownode->z_key, 1590 findallownode.z_key, 1591 sizeof (findallownode.z_key)); 1592 avl_insert(tree, newallownode, where); 1593 allownode = newallownode; 1594 } 1595 1596 /* 1597 * Now iterate over the permissions and 1598 * place them in the appropriate local, 1599 * descendent or local+descendent tree. 1600 * 1601 * The permissions are added to the tree 1602 * via zfs_coalesce_perm(). 1603 */ 1604 perm_pair = nvlist_next_nvpair(permnv, NULL); 1605 if (perm_pair == NULL) 1606 goto abort; 1607 do { 1608 if (zfs_coalesce_perm(zhp, allownode, 1609 nvpair_name(perm_pair), ld) != 0) 1610 goto abort; 1611 } while (perm_pair = nvlist_next_nvpair(permnv, 1612 perm_pair)); 1613 } while (who_pair = nvlist_next_nvpair(sourcenv, who_pair)); 1614 1615 source_pair = nvlist_next_nvpair(nvlist, source_pair); 1616 if (source_pair == NULL) 1617 break; 1618 1619 /* 1620 * allocate another node from the link list of 1621 * zfs_allow_t structures 1622 */ 1623 newallowp = zfs_alloc_perm_tree(zhp, zallowp, 1624 nvpair_name(source_pair)); 1625 if (newallowp == NULL) { 1626 goto abort; 1627 } 1628 zallowp = newallowp; 1629 } 1630 nvlist_free(nvlist); 1631 return (0); 1632abort: 1633 zfs_free_allows(*zfs_perms); 1634 nvlist_free(nvlist); 1635 return (-1); 1636} 1637 1638static char * 1639zfs_deleg_perm_note(zfs_deleg_note_t note) 1640{ 1641 /* 1642 * Don't put newlines on end of lines 1643 */ 1644 switch (note) { 1645 case ZFS_DELEG_NOTE_CREATE: 1646 return (dgettext(TEXT_DOMAIN, 1647 "Must also have the 'mount' ability")); 1648 case ZFS_DELEG_NOTE_DESTROY: 1649 return (dgettext(TEXT_DOMAIN, 1650 "Must also have the 'mount' ability")); 1651 case ZFS_DELEG_NOTE_SNAPSHOT: 1652 return (dgettext(TEXT_DOMAIN, 1653 "Must also have the 'mount' ability")); 1654 case ZFS_DELEG_NOTE_ROLLBACK: 1655 return (dgettext(TEXT_DOMAIN, 1656 "Must also have the 'mount' ability")); 1657 case ZFS_DELEG_NOTE_CLONE: 1658 return (dgettext(TEXT_DOMAIN, "Must also have the 'create' " 1659 "ability and 'mount'\n" 1660 "\t\t\t\tability in the origin file system")); 1661 case ZFS_DELEG_NOTE_PROMOTE: 1662 return (dgettext(TEXT_DOMAIN, "Must also have the 'mount'\n" 1663 "\t\t\t\tand 'promote' ability in the origin file system")); 1664 case ZFS_DELEG_NOTE_RENAME: 1665 return (dgettext(TEXT_DOMAIN, "Must also have the 'mount' " 1666 "and 'create' \n\t\t\t\tability in the new parent")); 1667 case ZFS_DELEG_NOTE_RECEIVE: 1668 return (dgettext(TEXT_DOMAIN, "Must also have the 'mount'" 1669 " and 'create' ability")); 1670 case ZFS_DELEG_NOTE_USERPROP: 1671 return (dgettext(TEXT_DOMAIN, 1672 "Allows changing any user property")); 1673 case ZFS_DELEG_NOTE_ALLOW: 1674 return (dgettext(TEXT_DOMAIN, 1675 "Must also have the permission that is being\n" 1676 "\t\t\t\tallowed")); 1677 case ZFS_DELEG_NOTE_MOUNT: 1678 return (dgettext(TEXT_DOMAIN, 1679 "Allows mount/umount of ZFS datasets")); 1680 case ZFS_DELEG_NOTE_SHARE: 1681 return (dgettext(TEXT_DOMAIN, 1682 "Allows sharing file systems over NFS or SMB\n" 1683 "\t\t\t\tprotocols")); 1684 case ZFS_DELEG_NOTE_NONE: 1685 default: 1686 return (dgettext(TEXT_DOMAIN, "")); 1687 } 1688} 1689 1690typedef enum { 1691 ZFS_DELEG_SUBCOMMAND, 1692 ZFS_DELEG_PROP, 1693 ZFS_DELEG_OTHER 1694} zfs_deleg_perm_type_t; 1695 1696/* 1697 * is the permission a subcommand or other? 1698 */ 1699zfs_deleg_perm_type_t 1700zfs_deleg_perm_type(const char *perm) 1701{ 1702 if (strcmp(perm, "userprop") == 0) 1703 return (ZFS_DELEG_OTHER); 1704 else 1705 return (ZFS_DELEG_SUBCOMMAND); 1706} 1707 1708static char * 1709zfs_deleg_perm_type_str(zfs_deleg_perm_type_t type) 1710{ 1711 switch (type) { 1712 case ZFS_DELEG_SUBCOMMAND: 1713 return (dgettext(TEXT_DOMAIN, "subcommand")); 1714 case ZFS_DELEG_PROP: 1715 return (dgettext(TEXT_DOMAIN, "property")); 1716 case ZFS_DELEG_OTHER: 1717 return (dgettext(TEXT_DOMAIN, "other")); 1718 } 1719 return (""); 1720} 1721 1722/*ARGSUSED*/ 1723static int 1724zfs_deleg_prop_cb(int prop, void *cb) 1725{ 1726 if (zfs_prop_delegatable(prop)) 1727 (void) fprintf(stderr, "%-15s %-15s\n", zfs_prop_to_name(prop), 1728 zfs_deleg_perm_type_str(ZFS_DELEG_PROP)); 1729 1730 return (ZPROP_CONT); 1731} 1732 1733void 1734zfs_deleg_permissions(void) 1735{ 1736 int i; 1737 1738 (void) fprintf(stderr, "\n%-15s %-15s\t%s\n\n", "NAME", 1739 "TYPE", "NOTES"); 1740 1741 /* 1742 * First print out the subcommands 1743 */ 1744 for (i = 0; zfs_deleg_perm_tab[i].z_perm != NULL; i++) { 1745 (void) fprintf(stderr, "%-15s %-15s\t%s\n", 1746 zfs_deleg_perm_tab[i].z_perm, 1747 zfs_deleg_perm_type_str( 1748 zfs_deleg_perm_type(zfs_deleg_perm_tab[i].z_perm)), 1749 zfs_deleg_perm_note(zfs_deleg_perm_tab[i].z_note)); 1750 } 1751 1752 (void) zprop_iter(zfs_deleg_prop_cb, NULL, B_FALSE, B_TRUE, 1753 ZFS_TYPE_DATASET|ZFS_TYPE_VOLUME); 1754} 1755 1756/* | |
1757 * Given a property name and value, set the property for the given dataset. 1758 */ 1759int 1760zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1761{ 1762 zfs_cmd_t zc = { 0 }; 1763 int ret = -1; 1764 prop_changelist_t *cl = NULL; --- 64 unchanged lines hidden (view full) --- 1829 * Execute the corresponding ioctl() to set this property. 1830 */ 1831 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1832 1833 if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0) 1834 goto error; 1835 1836 ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); | 1226 * Given a property name and value, set the property for the given dataset. 1227 */ 1228int 1229zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1230{ 1231 zfs_cmd_t zc = { 0 }; 1232 int ret = -1; 1233 prop_changelist_t *cl = NULL; --- 64 unchanged lines hidden (view full) --- 1298 * Execute the corresponding ioctl() to set this property. 1299 */ 1300 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1301 1302 if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0) 1303 goto error; 1304 1305 ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); |
1306 |
|
1837 if (ret != 0) { 1838 switch (errno) { 1839 1840 case ENOSPC: 1841 /* 1842 * For quotas and reservations, ENOSPC indicates 1843 * something different; setting a quota or reservation 1844 * doesn't use any disk space. --- 290 unchanged lines hidden (view full) --- 2135 2136 /* 2137 * Because looking up the mount options is potentially expensive 2138 * (iterating over all of /etc/mnttab), we defer its calculation until 2139 * we're looking up a property which requires its presence. 2140 */ 2141 if (!zhp->zfs_mntcheck && 2142 (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { | 1307 if (ret != 0) { 1308 switch (errno) { 1309 1310 case ENOSPC: 1311 /* 1312 * For quotas and reservations, ENOSPC indicates 1313 * something different; setting a quota or reservation 1314 * doesn't use any disk space. --- 290 unchanged lines hidden (view full) --- 1605 1606 /* 1607 * Because looking up the mount options is potentially expensive 1608 * (iterating over all of /etc/mnttab), we defer its calculation until 1609 * we're looking up a property which requires its presence. 1610 */ 1611 if (!zhp->zfs_mntcheck && 1612 (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { |
2143 struct mnttab entry, search = { 0 }; 2144 FILE *mnttab = zhp->zfs_hdl->libzfs_mnttab; | 1613 libzfs_handle_t *hdl = zhp->zfs_hdl; 1614 struct mnttab entry; |
2145 | 1615 |
2146 search.mnt_special = (char *)zhp->zfs_name; 2147 search.mnt_fstype = MNTTYPE_ZFS; 2148 rewind(mnttab); 2149 2150 if (getmntany(mnttab, &entry, &search) == 0) { 2151 zhp->zfs_mntopts = zfs_strdup(zhp->zfs_hdl, | 1616 if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) { 1617 zhp->zfs_mntopts = zfs_strdup(hdl, |
2152 entry.mnt_mntopts); 2153 if (zhp->zfs_mntopts == NULL) 2154 return (-1); 2155 } 2156 2157 zhp->zfs_mntcheck = B_TRUE; 2158 } 2159 --- 82 unchanged lines hidden (view full) --- 2242 break; 2243 2244 default: 2245 switch (zfs_prop_get_type(prop)) { 2246 case PROP_TYPE_NUMBER: 2247 case PROP_TYPE_INDEX: 2248 *val = getprop_uint64(zhp, prop, source); 2249 /* | 1618 entry.mnt_mntopts); 1619 if (zhp->zfs_mntopts == NULL) 1620 return (-1); 1621 } 1622 1623 zhp->zfs_mntcheck = B_TRUE; 1624 } 1625 --- 82 unchanged lines hidden (view full) --- 1708 break; 1709 1710 default: 1711 switch (zfs_prop_get_type(prop)) { 1712 case PROP_TYPE_NUMBER: 1713 case PROP_TYPE_INDEX: 1714 *val = getprop_uint64(zhp, prop, source); 1715 /* |
2250 * If we tried to use a defalut value for a | 1716 * If we tried to use a default value for a |
2251 * readonly property, it means that it was not 2252 * present; return an error. 2253 */ 2254 if (zfs_prop_readonly(prop) && 2255 *source && (*source)[0] == '\0') { 2256 return (-1); 2257 } 2258 break; --- 277 unchanged lines hidden (view full) --- 2536 return (val); 2537} 2538 2539int 2540zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val) 2541{ 2542 char buf[64]; 2543 | 1717 * readonly property, it means that it was not 1718 * present; return an error. 1719 */ 1720 if (zfs_prop_readonly(prop) && 1721 *source && (*source)[0] == '\0') { 1722 return (-1); 1723 } 1724 break; --- 277 unchanged lines hidden (view full) --- 2002 return (val); 2003} 2004 2005int 2006zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val) 2007{ 2008 char buf[64]; 2009 |
2544 zfs_nicenum(val, buf, sizeof (buf)); | 2010 (void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val); |
2545 return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf)); 2546} 2547 2548/* 2549 * Similar to zfs_prop_get(), but returns the value as an integer. 2550 */ 2551int 2552zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, --- 16 unchanged lines hidden (view full) --- 2569 if (get_numeric_property(zhp, prop, src, &source, value) != 0) 2570 return (-1); 2571 2572 get_source(zhp, src, source, statbuf, statlen); 2573 2574 return (0); 2575} 2576 | 2011 return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf)); 2012} 2013 2014/* 2015 * Similar to zfs_prop_get(), but returns the value as an integer. 2016 */ 2017int 2018zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, --- 16 unchanged lines hidden (view full) --- 2035 if (get_numeric_property(zhp, prop, src, &source, value) != 0) 2036 return (-1); 2037 2038 get_source(zhp, src, source, statbuf, statlen); 2039 2040 return (0); 2041} 2042 |
2043static int 2044idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, 2045 char **domainp, idmap_rid_t *ridp) 2046{ 2047#ifdef sun 2048 idmap_handle_t *idmap_hdl = NULL; 2049 idmap_get_handle_t *get_hdl = NULL; 2050 idmap_stat status; 2051 int err = EINVAL; 2052 2053 if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS) 2054 goto out; 2055 if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS) 2056 goto out; 2057 2058 if (isuser) { 2059 err = idmap_get_sidbyuid(get_hdl, id, 2060 IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status); 2061 } else { 2062 err = idmap_get_sidbygid(get_hdl, id, 2063 IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status); 2064 } 2065 if (err == IDMAP_SUCCESS && 2066 idmap_get_mappings(get_hdl) == IDMAP_SUCCESS && 2067 status == IDMAP_SUCCESS) 2068 err = 0; 2069 else 2070 err = EINVAL; 2071out: 2072 if (get_hdl) 2073 idmap_get_destroy(get_hdl); 2074 if (idmap_hdl) 2075 (void) idmap_fini(idmap_hdl); 2076 return (err); 2077#else /* !sun */ 2078 assert(!"invalid code path"); 2079#endif /* !sun */ 2080} 2081 2082#ifndef sun 2083/* Check if a string contains only digits */ 2084static int 2085string_is_digits(char *cp) 2086{ 2087 int i; 2088 2089 for(i = 0; i < strlen(cp); i++) 2090 if(!isdigit(cp[i])) 2091 return (0); 2092 return (1); 2093} 2094 2095#endif /* !sun */ 2096 |
|
2577/* | 2097/* |
2098 * convert the propname into parameters needed by kernel 2099 * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829 2100 * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789 2101 */ 2102static int 2103userquota_propname_decode(const char *propname, boolean_t zoned, 2104 zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp) 2105{ 2106 zfs_userquota_prop_t type; 2107 char *cp, *end; 2108 char *numericsid = NULL; 2109 boolean_t isuser; 2110 2111 domain[0] = '\0'; 2112 2113 /* Figure out the property type ({user|group}{quota|space}) */ 2114 for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) { 2115 if (strncmp(propname, zfs_userquota_prop_prefixes[type], 2116 strlen(zfs_userquota_prop_prefixes[type])) == 0) 2117 break; 2118 } 2119 if (type == ZFS_NUM_USERQUOTA_PROPS) 2120 return (EINVAL); 2121 *typep = type; 2122 2123 isuser = (type == ZFS_PROP_USERQUOTA || 2124 type == ZFS_PROP_USERUSED); 2125 2126 cp = strchr(propname, '@') + 1; 2127 2128 if (strchr(cp, '@')) { 2129#ifdef sun 2130 /* 2131 * It's a SID name (eg "user@domain") that needs to be 2132 * turned into S-1-domainID-RID. 2133 */ 2134 directory_error_t e; 2135 2136 if (zoned && getzoneid() == GLOBAL_ZONEID) 2137 return (ENOENT); 2138 if (isuser) { 2139 e = directory_sid_from_user_name(NULL, 2140 cp, &numericsid); 2141 } else { 2142 e = directory_sid_from_group_name(NULL, 2143 cp, &numericsid); 2144 } 2145 if (e != NULL) { 2146 directory_error_free(e); 2147 return (ENOENT); 2148 } 2149 if (numericsid == NULL) 2150 return (ENOENT); 2151 cp = numericsid; 2152 /* will be further decoded below */ 2153#else /* !sun */ 2154 return (ENOENT); 2155#endif /* !sun */ 2156 } 2157 2158 if (strncmp(cp, "S-1-", 4) == 0) { 2159 /* It's a numeric SID (eg "S-1-234-567-89") */ 2160 (void) strlcpy(domain, cp, domainlen); 2161 cp = strrchr(domain, '-'); 2162 *cp = '\0'; 2163 cp++; 2164 2165 errno = 0; 2166 *ridp = strtoull(cp, &end, 10); 2167 if (numericsid) { 2168 free(numericsid); 2169 numericsid = NULL; 2170 } 2171 if (errno != 0 || *end != '\0') 2172 return (EINVAL); 2173#ifdef sun 2174 } else if (!isdigit(*cp)) { 2175#else /* sun */ 2176 /* 2177 * In FreeBSD user and group names can begin with a digit so treat 2178 * as a uid/gid if string contains digits only 2179 */ 2180 } else if (!string_is_digits(cp)) { 2181#endif /* sun */ 2182 /* 2183 * It's a user/group name (eg "user") that needs to be 2184 * turned into a uid/gid 2185 */ 2186 if (zoned && getzoneid() == GLOBAL_ZONEID) 2187 return (ENOENT); 2188 if (isuser) { 2189 struct passwd *pw; 2190 pw = getpwnam(cp); 2191 if (pw == NULL) 2192 return (ENOENT); 2193 *ridp = pw->pw_uid; 2194 } else { 2195 struct group *gr; 2196 gr = getgrnam(cp); 2197 if (gr == NULL) 2198 return (ENOENT); 2199 *ridp = gr->gr_gid; 2200 } 2201 } else { 2202 /* It's a user/group ID (eg "12345"). */ 2203 uid_t id = strtoul(cp, &end, 10); 2204 idmap_rid_t rid; 2205 char *mapdomain; 2206 2207 if (*end != '\0') 2208 return (EINVAL); 2209 if (id > MAXUID) { 2210 /* It's an ephemeral ID. */ 2211 if (idmap_id_to_numeric_domain_rid(id, isuser, 2212 &mapdomain, &rid) != 0) 2213 return (ENOENT); 2214 (void) strlcpy(domain, mapdomain, domainlen); 2215 *ridp = rid; 2216 } else { 2217 *ridp = id; 2218 } 2219 } 2220 2221 ASSERT3P(numericsid, ==, NULL); 2222 return (0); 2223} 2224 2225static int 2226zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname, 2227 uint64_t *propvalue, zfs_userquota_prop_t *typep) 2228{ 2229 int err; 2230 zfs_cmd_t zc = { 0 }; 2231 2232 (void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2233 2234 err = userquota_propname_decode(propname, 2235 zfs_prop_get_int(zhp, ZFS_PROP_ZONED), 2236 typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid); 2237 zc.zc_objset_type = *typep; 2238 if (err) 2239 return (err); 2240 2241 err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc); 2242 if (err) 2243 return (err); 2244 2245 *propvalue = zc.zc_cookie; 2246 return (0); 2247} 2248 2249int 2250zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname, 2251 uint64_t *propvalue) 2252{ 2253 zfs_userquota_prop_t type; 2254 2255 return (zfs_prop_get_userquota_common(zhp, propname, propvalue, 2256 &type)); 2257} 2258 2259int 2260zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname, 2261 char *propbuf, int proplen, boolean_t literal) 2262{ 2263 int err; 2264 uint64_t propvalue; 2265 zfs_userquota_prop_t type; 2266 2267 err = zfs_prop_get_userquota_common(zhp, propname, &propvalue, 2268 &type); 2269 2270 if (err) 2271 return (err); 2272 2273 if (literal) { 2274 (void) snprintf(propbuf, proplen, "%llu", propvalue); 2275 } else if (propvalue == 0 && 2276 (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) { 2277 (void) strlcpy(propbuf, "none", proplen); 2278 } else { 2279 zfs_nicenum(propvalue, propbuf, proplen); 2280 } 2281 return (0); 2282} 2283 2284/* |
|
2578 * Returns the name of the given zfs handle. 2579 */ 2580const char * 2581zfs_get_name(const zfs_handle_t *zhp) 2582{ 2583 return (zhp->zfs_name); 2584} 2585 2586/* 2587 * Returns the type of the given zfs handle. 2588 */ 2589zfs_type_t 2590zfs_get_type(const zfs_handle_t *zhp) 2591{ 2592 return (zhp->zfs_type); 2593} 2594 | 2285 * Returns the name of the given zfs handle. 2286 */ 2287const char * 2288zfs_get_name(const zfs_handle_t *zhp) 2289{ 2290 return (zhp->zfs_name); 2291} 2292 2293/* 2294 * Returns the type of the given zfs handle. 2295 */ 2296zfs_type_t 2297zfs_get_type(const zfs_handle_t *zhp) 2298{ 2299 return (zhp->zfs_type); 2300} 2301 |
2302static int 2303zfs_do_list_ioctl(zfs_handle_t *zhp, unsigned long arg, zfs_cmd_t *zc) 2304{ 2305 int rc; 2306 uint64_t orig_cookie; 2307 2308 orig_cookie = zc->zc_cookie; 2309top: 2310 (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); 2311 rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc); 2312 2313 /* 2314 * FreeBSD compatibility with pre-v15 kernel module. 2315 * Ignore private dataset names. 2316 */ 2317 if (strchr(zc->zc_name, '$') != NULL) 2318 rc = 0; 2319 2320 if (rc == -1) { 2321 switch (errno) { 2322 case ENOMEM: 2323 /* expand nvlist memory and try again */ 2324 if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) { 2325 zcmd_free_nvlists(zc); 2326 return (-1); 2327 } 2328 zc->zc_cookie = orig_cookie; 2329 goto top; 2330 /* 2331 * An errno value of ESRCH indicates normal completion. 2332 * If ENOENT is returned, then the underlying dataset 2333 * has been removed since we obtained the handle. 2334 */ 2335 case ESRCH: 2336 case ENOENT: 2337 rc = 1; 2338 break; 2339 default: 2340 rc = zfs_standard_error(zhp->zfs_hdl, errno, 2341 dgettext(TEXT_DOMAIN, 2342 "cannot iterate filesystems")); 2343 break; 2344 } 2345 } 2346 return (rc); 2347} 2348 |
|
2595/* 2596 * Iterate over all child filesystems 2597 */ 2598int 2599zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2600{ 2601 zfs_cmd_t zc = { 0 }; 2602 zfs_handle_t *nzhp; 2603 int ret; 2604 2605 if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM) 2606 return (0); 2607 | 2349/* 2350 * Iterate over all child filesystems 2351 */ 2352int 2353zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2354{ 2355 zfs_cmd_t zc = { 0 }; 2356 zfs_handle_t *nzhp; 2357 int ret; 2358 2359 if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM) 2360 return (0); 2361 |
2608 for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2609 ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 2610 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { | 2362 if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 2363 return (-1); 2364 2365 while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT, 2366 &zc)) == 0) { 2367 |
2611 /* | 2368 /* |
2369 * FreeBSD compatibility with pre-v15 kernel module. |
|
2612 * Ignore private dataset names. 2613 */ | 2370 * Ignore private dataset names. 2371 */ |
2614 if (dataset_name_hidden(zc.zc_name)) | 2372 if (strchr(zc.zc_name, '$') != NULL) |
2615 continue; 2616 2617 /* 2618 * Silently ignore errors, as the only plausible explanation is 2619 * that the pool has since been removed. 2620 */ | 2373 continue; 2374 2375 /* 2376 * Silently ignore errors, as the only plausible explanation is 2377 * that the pool has since been removed. 2378 */ |
2621 if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 2622 zc.zc_name)) == NULL) | 2379 if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl, 2380 &zc)) == NULL) { |
2623 continue; | 2381 continue; |
2382 } |
|
2624 | 2383 |
2625 if ((ret = func(nzhp, data)) != 0) | 2384 if ((ret = func(nzhp, data)) != 0) { 2385 zcmd_free_nvlists(&zc); |
2626 return (ret); | 2386 return (ret); |
2387 } |
|
2627 } | 2388 } |
2628 2629 /* 2630 * An errno value of ESRCH indicates normal completion. If ENOENT is 2631 * returned, then the underlying dataset has been removed since we 2632 * obtained the handle. 2633 */ 2634 if (errno != ESRCH && errno != ENOENT) 2635 return (zfs_standard_error(zhp->zfs_hdl, errno, 2636 dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 2637 2638 return (0); | 2389 zcmd_free_nvlists(&zc); 2390 return ((ret < 0) ? ret : 0); |
2639} 2640 2641/* 2642 * Iterate over all snapshots 2643 */ 2644int 2645zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2646{ 2647 zfs_cmd_t zc = { 0 }; 2648 zfs_handle_t *nzhp; 2649 int ret; 2650 2651 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) 2652 return (0); 2653 | 2391} 2392 2393/* 2394 * Iterate over all snapshots 2395 */ 2396int 2397zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2398{ 2399 zfs_cmd_t zc = { 0 }; 2400 zfs_handle_t *nzhp; 2401 int ret; 2402 2403 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) 2404 return (0); 2405 |
2654 for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2655 ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, 2656 &zc) == 0; 2657 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { | 2406 if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 2407 return (-1); 2408 while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT, 2409 &zc)) == 0) { |
2658 | 2410 |
2659 if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 2660 zc.zc_name)) == NULL) | 2411 /* 2412 * FreeBSD compatibility with pre-v15 kernel module. 2413 * Ignore private dataset names. 2414 */ 2415 if (strchr(zc.zc_name, '$') != NULL) |
2661 continue; 2662 | 2416 continue; 2417 |
2663 if ((ret = func(nzhp, data)) != 0) | 2418 if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl, 2419 &zc)) == NULL) { 2420 continue; 2421 } 2422 2423 if ((ret = func(nzhp, data)) != 0) { 2424 zcmd_free_nvlists(&zc); |
2664 return (ret); | 2425 return (ret); |
2426 } |
|
2665 } | 2427 } |
2666 2667 /* 2668 * An errno value of ESRCH indicates normal completion. If ENOENT is 2669 * returned, then the underlying dataset has been removed since we 2670 * obtained the handle. Silently ignore this case, and return success. 2671 */ 2672 if (errno != ESRCH && errno != ENOENT) 2673 return (zfs_standard_error(zhp->zfs_hdl, errno, 2674 dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 2675 2676 return (0); | 2428 zcmd_free_nvlists(&zc); 2429 return ((ret < 0) ? ret : 0); |
2677} 2678 2679/* 2680 * Iterate over all children, snapshots and filesystems 2681 */ 2682int 2683zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2684{ --- 36 unchanged lines hidden (view full) --- 2721 boolean_t accept_ancestor, int *prefixlen) 2722{ 2723 zfs_cmd_t zc = { 0 }; 2724 char parent[ZFS_MAXNAMELEN]; 2725 char *slash; 2726 zfs_handle_t *zhp; 2727 char errbuf[1024]; 2728 | 2430} 2431 2432/* 2433 * Iterate over all children, snapshots and filesystems 2434 */ 2435int 2436zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2437{ --- 36 unchanged lines hidden (view full) --- 2474 boolean_t accept_ancestor, int *prefixlen) 2475{ 2476 zfs_cmd_t zc = { 0 }; 2477 char parent[ZFS_MAXNAMELEN]; 2478 char *slash; 2479 zfs_handle_t *zhp; 2480 char errbuf[1024]; 2481 |
2729 (void) snprintf(errbuf, sizeof (errbuf), "cannot create '%s'", 2730 path); | 2482 (void) snprintf(errbuf, sizeof (errbuf), 2483 dgettext(TEXT_DOMAIN, "cannot create '%s'"), path); |
2731 2732 /* get parent, and check to see if this is just a pool */ 2733 if (parent_name(path, parent, sizeof (parent)) != 0) { 2734 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2735 "missing dataset name")); 2736 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2737 } 2738 --- 1510 unchanged lines hidden (view full) --- 4249 error = ioctl(hdl->libzfs_fd, ZFS_IOC_ISCSI_PERM_CHECK, &zc); 4250 nvlist_free(nvp); 4251 return (error); 4252} 4253#endif 4254 4255int 4256zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path, | 2484 2485 /* get parent, and check to see if this is just a pool */ 2486 if (parent_name(path, parent, sizeof (parent)) != 0) { 2487 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2488 "missing dataset name")); 2489 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2490 } 2491 --- 1510 unchanged lines hidden (view full) --- 4002 error = ioctl(hdl->libzfs_fd, ZFS_IOC_ISCSI_PERM_CHECK, &zc); 4003 nvlist_free(nvp); 4004 return (error); 4005} 4006#endif 4007 4008int 4009zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path, |
4257 void *export, void *sharetab, int sharemax, zfs_share_op_t operation) | 4010 char *resource, void *export, void *sharetab, 4011 int sharemax, zfs_share_op_t operation) |
4258{ 4259 zfs_cmd_t zc = { 0 }; 4260 int error; 4261 4262 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 4263 (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value)); | 4012{ 4013 zfs_cmd_t zc = { 0 }; 4014 int error; 4015 4016 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 4017 (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value)); |
4018 if (resource) 4019 (void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string)); |
|
4264 zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab; 4265 zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export; 4266 zc.zc_share.z_sharetype = operation; 4267 zc.zc_share.z_sharemax = sharemax; | 4020 zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab; 4021 zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export; 4022 zc.zc_share.z_sharetype = operation; 4023 zc.zc_share.z_sharemax = sharemax; |
4268 | |
4269 error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc); 4270 return (error); 4271} 4272 4273void 4274zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props) 4275{ 4276 nvpair_t *curr; --- 17 unchanged lines hidden (view full) --- 4294 */ 4295 if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE) 4296 (void) nvlist_remove(zhp->zfs_props, 4297 nvpair_name(curr), nvpair_type(curr)); 4298 curr = next; 4299 } 4300} 4301 | 4024 error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc); 4025 return (error); 4026} 4027 4028void 4029zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props) 4030{ 4031 nvpair_t *curr; --- 17 unchanged lines hidden (view full) --- 4049 */ 4050 if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE) 4051 (void) nvlist_remove(zhp->zfs_props, 4052 nvpair_name(curr), nvpair_type(curr)); 4053 curr = next; 4054 } 4055} 4056 |
4057#ifdef sun 4058static int 4059zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path, 4060 zfs_smb_acl_op_t cmd, char *resource1, char *resource2) 4061{ 4062 zfs_cmd_t zc = { 0 }; 4063 nvlist_t *nvlist = NULL; 4064 int error; 4065 4066 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 4067 (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value)); 4068 zc.zc_cookie = (uint64_t)cmd; 4069 4070 if (cmd == ZFS_SMB_ACL_RENAME) { 4071 if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) { 4072 (void) no_memory(hdl); 4073 return (NULL); 4074 } 4075 } 4076 4077 switch (cmd) { 4078 case ZFS_SMB_ACL_ADD: 4079 case ZFS_SMB_ACL_REMOVE: 4080 (void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string)); 4081 break; 4082 case ZFS_SMB_ACL_RENAME: 4083 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC, 4084 resource1) != 0) { 4085 (void) no_memory(hdl); 4086 return (-1); 4087 } 4088 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET, 4089 resource2) != 0) { 4090 (void) no_memory(hdl); 4091 return (-1); 4092 } 4093 if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) { 4094 nvlist_free(nvlist); 4095 return (-1); 4096 } 4097 break; 4098 case ZFS_SMB_ACL_PURGE: 4099 break; 4100 default: 4101 return (-1); 4102 } 4103 error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc); 4104 if (nvlist) 4105 nvlist_free(nvlist); 4106 return (error); 4107} 4108 4109int 4110zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset, 4111 char *path, char *resource) 4112{ 4113 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD, 4114 resource, NULL)); 4115} 4116 4117int 4118zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset, 4119 char *path, char *resource) 4120{ 4121 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE, 4122 resource, NULL)); 4123} 4124 4125int 4126zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path) 4127{ 4128 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE, 4129 NULL, NULL)); 4130} 4131 4132int 4133zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path, 4134 char *oldname, char *newname) 4135{ 4136 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME, 4137 oldname, newname)); 4138} 4139#endif /* sun */ 4140 4141int 4142zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type, 4143 zfs_userspace_cb_t func, void *arg) 4144{ 4145 zfs_cmd_t zc = { 0 }; 4146 int error; 4147 zfs_useracct_t buf[100]; 4148 4149 (void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 4150 4151 zc.zc_objset_type = type; 4152 zc.zc_nvlist_dst = (uintptr_t)buf; 4153 4154 /* CONSTCOND */ 4155 while (1) { 4156 zfs_useracct_t *zua = buf; 4157 4158 zc.zc_nvlist_dst_size = sizeof (buf); 4159 error = ioctl(zhp->zfs_hdl->libzfs_fd, 4160 ZFS_IOC_USERSPACE_MANY, &zc); 4161 if (error || zc.zc_nvlist_dst_size == 0) 4162 break; 4163 4164 while (zc.zc_nvlist_dst_size > 0) { 4165 error = func(arg, zua->zu_domain, zua->zu_rid, 4166 zua->zu_space); 4167 if (error != 0) 4168 return (error); 4169 zua++; 4170 zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 4171 } 4172 } 4173 4174 return (error); 4175} 4176 |
|
4302/* 4303 * Attach/detach the given filesystem to/from the given jail. 4304 */ 4305int 4306zfs_jail(zfs_handle_t *zhp, int jailid, int attach) 4307{ 4308 libzfs_handle_t *hdl = zhp->zfs_hdl; 4309 zfs_cmd_t zc = { 0 }; --- 33 unchanged lines hidden --- | 4177/* 4178 * Attach/detach the given filesystem to/from the given jail. 4179 */ 4180int 4181zfs_jail(zfs_handle_t *zhp, int jailid, int attach) 4182{ 4183 libzfs_handle_t *hdl = zhp->zfs_hdl; 4184 zfs_cmd_t zc = { 0 }; --- 33 unchanged lines hidden --- |