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 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <assert.h> 30 #include <ctype.h> 31 #include <errno.h> 32 #include <libdevinfo.h> 33 #include <libintl.h> 34 #include <math.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <strings.h> 38 #include <unistd.h> 39 #include <stddef.h> 40 #include <zone.h> 41 #include <fcntl.h> 42 #include <sys/mntent.h> 43 #include <sys/mnttab.h> 44 #include <sys/mount.h> 45 #include <sys/avl.h> 46 #include <priv.h> 47 #include <pwd.h> 48 #include <grp.h> 49 #include <stddef.h> 50 #include <ucred.h> 51 52 #include <sys/spa.h> 53 #include <sys/zap.h> 54 #include <sys/zfs_i18n.h> 55 #include <libzfs.h> 56 57 #include "zfs_namecheck.h" 58 #include "zfs_prop.h" 59 #include "libzfs_impl.h" 60 #include "zfs_deleg.h" 61 62 static int zvol_create_link_common(libzfs_handle_t *, const char *, int); 63 64 /* 65 * Given a single type (not a mask of types), return the type in a human 66 * readable form. 67 */ 68 const char * 69 zfs_type_to_name(zfs_type_t type) 70 { 71 switch (type) { 72 case ZFS_TYPE_FILESYSTEM: 73 return (dgettext(TEXT_DOMAIN, "filesystem")); 74 case ZFS_TYPE_SNAPSHOT: 75 return (dgettext(TEXT_DOMAIN, "snapshot")); 76 case ZFS_TYPE_VOLUME: 77 return (dgettext(TEXT_DOMAIN, "volume")); 78 } 79 80 return (NULL); 81 } 82 83 /* 84 * Given a path and mask of ZFS types, return a string describing this dataset. 85 * This is used when we fail to open a dataset and we cannot get an exact type. 86 * We guess what the type would have been based on the path and the mask of 87 * acceptable types. 88 */ 89 static const char * 90 path_to_str(const char *path, int types) 91 { 92 /* 93 * When given a single type, always report the exact type. 94 */ 95 if (types == ZFS_TYPE_SNAPSHOT) 96 return (dgettext(TEXT_DOMAIN, "snapshot")); 97 if (types == ZFS_TYPE_FILESYSTEM) 98 return (dgettext(TEXT_DOMAIN, "filesystem")); 99 if (types == ZFS_TYPE_VOLUME) 100 return (dgettext(TEXT_DOMAIN, "volume")); 101 102 /* 103 * The user is requesting more than one type of dataset. If this is the 104 * case, consult the path itself. If we're looking for a snapshot, and 105 * a '@' is found, then report it as "snapshot". Otherwise, remove the 106 * snapshot attribute and try again. 107 */ 108 if (types & ZFS_TYPE_SNAPSHOT) { 109 if (strchr(path, '@') != NULL) 110 return (dgettext(TEXT_DOMAIN, "snapshot")); 111 return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 112 } 113 114 115 /* 116 * The user has requested either filesystems or volumes. 117 * We have no way of knowing a priori what type this would be, so always 118 * report it as "filesystem" or "volume", our two primitive types. 119 */ 120 if (types & ZFS_TYPE_FILESYSTEM) 121 return (dgettext(TEXT_DOMAIN, "filesystem")); 122 123 assert(types & ZFS_TYPE_VOLUME); 124 return (dgettext(TEXT_DOMAIN, "volume")); 125 } 126 127 /* 128 * Validate a ZFS path. This is used even before trying to open the dataset, to 129 * provide a more meaningful error message. We place a more useful message in 130 * 'buf' detailing exactly why the name was not valid. 131 */ 132 static int 133 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, 134 boolean_t modifying) 135 { 136 namecheck_err_t why; 137 char what; 138 139 if (dataset_namecheck(path, &why, &what) != 0) { 140 if (hdl != NULL) { 141 switch (why) { 142 case NAME_ERR_TOOLONG: 143 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 144 "name is too long")); 145 break; 146 147 case NAME_ERR_LEADING_SLASH: 148 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 149 "leading slash in name")); 150 break; 151 152 case NAME_ERR_EMPTY_COMPONENT: 153 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 154 "empty component in name")); 155 break; 156 157 case NAME_ERR_TRAILING_SLASH: 158 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 159 "trailing slash in name")); 160 break; 161 162 case NAME_ERR_INVALCHAR: 163 zfs_error_aux(hdl, 164 dgettext(TEXT_DOMAIN, "invalid character " 165 "'%c' in name"), what); 166 break; 167 168 case NAME_ERR_MULTIPLE_AT: 169 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 170 "multiple '@' delimiters in name")); 171 break; 172 173 case NAME_ERR_NOLETTER: 174 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 175 "pool doesn't begin with a letter")); 176 break; 177 178 case NAME_ERR_RESERVED: 179 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 180 "name is reserved")); 181 break; 182 183 case NAME_ERR_DISKLIKE: 184 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 185 "reserved disk name")); 186 break; 187 } 188 } 189 190 return (0); 191 } 192 193 if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 194 if (hdl != NULL) 195 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 196 "snapshot delimiter '@' in filesystem name")); 197 return (0); 198 } 199 200 if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) { 201 if (hdl != NULL) 202 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 203 "missing '@' delimiter in snapshot name")); 204 return (0); 205 } 206 207 if (modifying && strchr(path, '%') != NULL) { 208 if (hdl != NULL) 209 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 210 "invalid character %c in name"), '%'); 211 return (0); 212 } 213 214 return (-1); 215 } 216 217 int 218 zfs_name_valid(const char *name, zfs_type_t type) 219 { 220 return (zfs_validate_name(NULL, name, type, B_FALSE)); 221 } 222 223 /* 224 * This function takes the raw DSL properties, and filters out the user-defined 225 * properties into a separate nvlist. 226 */ 227 static nvlist_t * 228 process_user_props(zfs_handle_t *zhp, nvlist_t *props) 229 { 230 libzfs_handle_t *hdl = zhp->zfs_hdl; 231 nvpair_t *elem; 232 nvlist_t *propval; 233 nvlist_t *nvl; 234 235 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 236 (void) no_memory(hdl); 237 return (NULL); 238 } 239 240 elem = NULL; 241 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 242 if (!zfs_prop_user(nvpair_name(elem))) 243 continue; 244 245 verify(nvpair_value_nvlist(elem, &propval) == 0); 246 if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) { 247 nvlist_free(nvl); 248 (void) no_memory(hdl); 249 return (NULL); 250 } 251 } 252 253 return (nvl); 254 } 255 256 /* 257 * Utility function to gather stats (objset and zpl) for the given object. 258 */ 259 static int 260 get_stats(zfs_handle_t *zhp) 261 { 262 zfs_cmd_t zc = { 0 }; 263 libzfs_handle_t *hdl = zhp->zfs_hdl; 264 nvlist_t *allprops, *userprops; 265 266 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 267 268 if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 269 return (-1); 270 271 while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 272 if (errno == ENOMEM) { 273 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 274 zcmd_free_nvlists(&zc); 275 return (-1); 276 } 277 } else { 278 zcmd_free_nvlists(&zc); 279 return (-1); 280 } 281 } 282 283 zhp->zfs_dmustats = zc.zc_objset_stats; /* structure assignment */ 284 285 (void) strlcpy(zhp->zfs_root, zc.zc_value, sizeof (zhp->zfs_root)); 286 287 if (zcmd_read_dst_nvlist(hdl, &zc, &allprops) != 0) { 288 zcmd_free_nvlists(&zc); 289 return (-1); 290 } 291 292 zcmd_free_nvlists(&zc); 293 294 if ((userprops = process_user_props(zhp, allprops)) == NULL) { 295 nvlist_free(allprops); 296 return (-1); 297 } 298 299 nvlist_free(zhp->zfs_props); 300 nvlist_free(zhp->zfs_user_props); 301 302 zhp->zfs_props = allprops; 303 zhp->zfs_user_props = userprops; 304 305 return (0); 306 } 307 308 /* 309 * Refresh the properties currently stored in the handle. 310 */ 311 void 312 zfs_refresh_properties(zfs_handle_t *zhp) 313 { 314 (void) get_stats(zhp); 315 } 316 317 /* 318 * Makes a handle from the given dataset name. Used by zfs_open() and 319 * zfs_iter_* to create child handles on the fly. 320 */ 321 zfs_handle_t * 322 make_dataset_handle(libzfs_handle_t *hdl, const char *path) 323 { 324 zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 325 char *logstr; 326 327 if (zhp == NULL) 328 return (NULL); 329 330 zhp->zfs_hdl = hdl; 331 332 /* 333 * Preserve history log string. 334 * any changes performed here will be 335 * logged as an internal event. 336 */ 337 logstr = zhp->zfs_hdl->libzfs_log_str; 338 zhp->zfs_hdl->libzfs_log_str = NULL; 339 top: 340 (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 341 342 if (get_stats(zhp) != 0) { 343 zhp->zfs_hdl->libzfs_log_str = logstr; 344 free(zhp); 345 return (NULL); 346 } 347 348 if (zhp->zfs_dmustats.dds_inconsistent) { 349 zfs_cmd_t zc = { 0 }; 350 351 /* 352 * If it is dds_inconsistent, then we've caught it in 353 * the middle of a 'zfs receive' or 'zfs destroy', and 354 * it is inconsistent from the ZPL's point of view, so 355 * can't be mounted. However, it could also be that we 356 * have crashed in the middle of one of those 357 * operations, in which case we need to get rid of the 358 * inconsistent state. We do that by either rolling 359 * back to the previous snapshot (which will fail if 360 * there is none), or destroying the filesystem. Note 361 * that if we are still in the middle of an active 362 * 'receive' or 'destroy', then the rollback and destroy 363 * will fail with EBUSY and we will drive on as usual. 364 */ 365 366 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 367 368 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) { 369 (void) zvol_remove_link(hdl, zhp->zfs_name); 370 zc.zc_objset_type = DMU_OST_ZVOL; 371 } else { 372 zc.zc_objset_type = DMU_OST_ZFS; 373 } 374 375 /* 376 * If we can successfully destroy it, pretend that it 377 * never existed. 378 */ 379 if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) { 380 zhp->zfs_hdl->libzfs_log_str = logstr; 381 free(zhp); 382 errno = ENOENT; 383 return (NULL); 384 } 385 /* If we can successfully roll it back, reget the stats */ 386 if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0) 387 goto top; 388 } 389 390 /* 391 * We've managed to open the dataset and gather statistics. Determine 392 * the high-level type. 393 */ 394 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 395 zhp->zfs_head_type = ZFS_TYPE_VOLUME; 396 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 397 zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; 398 else 399 abort(); 400 401 if (zhp->zfs_dmustats.dds_is_snapshot) 402 zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 403 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 404 zhp->zfs_type = ZFS_TYPE_VOLUME; 405 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 406 zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 407 else 408 abort(); /* we should never see any other types */ 409 410 zhp->zfs_hdl->libzfs_log_str = logstr; 411 return (zhp); 412 } 413 414 /* 415 * Opens the given snapshot, filesystem, or volume. The 'types' 416 * argument is a mask of acceptable types. The function will print an 417 * appropriate error message and return NULL if it can't be opened. 418 */ 419 zfs_handle_t * 420 zfs_open(libzfs_handle_t *hdl, const char *path, int types) 421 { 422 zfs_handle_t *zhp; 423 char errbuf[1024]; 424 425 (void) snprintf(errbuf, sizeof (errbuf), 426 dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); 427 428 /* 429 * Validate the name before we even try to open it. 430 */ 431 if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) { 432 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 433 "invalid dataset name")); 434 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 435 return (NULL); 436 } 437 438 /* 439 * Try to get stats for the dataset, which will tell us if it exists. 440 */ 441 errno = 0; 442 if ((zhp = make_dataset_handle(hdl, path)) == NULL) { 443 (void) zfs_standard_error(hdl, errno, errbuf); 444 return (NULL); 445 } 446 447 if (!(types & zhp->zfs_type)) { 448 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 449 zfs_close(zhp); 450 return (NULL); 451 } 452 453 return (zhp); 454 } 455 456 /* 457 * Release a ZFS handle. Nothing to do but free the associated memory. 458 */ 459 void 460 zfs_close(zfs_handle_t *zhp) 461 { 462 if (zhp->zfs_mntopts) 463 free(zhp->zfs_mntopts); 464 nvlist_free(zhp->zfs_props); 465 nvlist_free(zhp->zfs_user_props); 466 free(zhp); 467 } 468 469 /* 470 * Given an nvlist of properties to set, validates that they are correct, and 471 * parses any numeric properties (index, boolean, etc) if they are specified as 472 * strings. 473 */ 474 static nvlist_t * 475 zfs_validate_properties(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl, 476 uint64_t zoned, zfs_handle_t *zhp, const char *errbuf) 477 { 478 nvpair_t *elem; 479 uint64_t intval; 480 char *strval; 481 zfs_prop_t prop; 482 nvlist_t *ret; 483 int chosen_sense = -1; 484 int chosen_normal = -1; 485 int chosen_utf = -1; 486 487 if (type == ZFS_TYPE_SNAPSHOT) { 488 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 489 "snapshot properties cannot be modified")); 490 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 491 return (NULL); 492 } 493 494 if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 495 (void) no_memory(hdl); 496 return (NULL); 497 } 498 499 elem = NULL; 500 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 501 const char *propname = nvpair_name(elem); 502 503 /* 504 * Make sure this property is valid and applies to this type. 505 */ 506 if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) { 507 if (!zfs_prop_user(propname)) { 508 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 509 "invalid property '%s'"), propname); 510 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 511 goto error; 512 } 513 514 /* 515 * If this is a user property, make sure it's a 516 * string, and that it's less than ZAP_MAXNAMELEN. 517 */ 518 if (nvpair_type(elem) != DATA_TYPE_STRING) { 519 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 520 "'%s' must be a string"), propname); 521 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 522 goto error; 523 } 524 525 if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { 526 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 527 "property name '%s' is too long"), 528 propname); 529 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 530 goto error; 531 } 532 533 (void) nvpair_value_string(elem, &strval); 534 if (nvlist_add_string(ret, propname, strval) != 0) { 535 (void) no_memory(hdl); 536 goto error; 537 } 538 continue; 539 } 540 541 if (!zfs_prop_valid_for_type(prop, type)) { 542 zfs_error_aux(hdl, 543 dgettext(TEXT_DOMAIN, "'%s' does not " 544 "apply to datasets of this type"), propname); 545 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 546 goto error; 547 } 548 549 if (zfs_prop_readonly(prop) && 550 (!zfs_prop_setonce(prop) || zhp != NULL)) { 551 zfs_error_aux(hdl, 552 dgettext(TEXT_DOMAIN, "'%s' is readonly"), 553 propname); 554 (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 555 goto error; 556 } 557 558 if (zprop_parse_value(hdl, elem, prop, type, ret, 559 &strval, &intval, errbuf) != 0) 560 goto error; 561 562 /* 563 * Perform some additional checks for specific properties. 564 */ 565 switch (prop) { 566 case ZFS_PROP_VERSION: 567 { 568 int version; 569 570 if (zhp == NULL) 571 break; 572 version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION); 573 if (intval < version) { 574 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 575 "Can not downgrade; already at version %u"), 576 version); 577 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 578 goto error; 579 } 580 break; 581 } 582 583 case ZFS_PROP_RECORDSIZE: 584 case ZFS_PROP_VOLBLOCKSIZE: 585 /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 586 if (intval < SPA_MINBLOCKSIZE || 587 intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) { 588 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 589 "'%s' must be power of 2 from %u " 590 "to %uk"), propname, 591 (uint_t)SPA_MINBLOCKSIZE, 592 (uint_t)SPA_MAXBLOCKSIZE >> 10); 593 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 594 goto error; 595 } 596 break; 597 598 case ZFS_PROP_SHAREISCSI: 599 if (strcmp(strval, "off") != 0 && 600 strcmp(strval, "on") != 0 && 601 strcmp(strval, "type=disk") != 0) { 602 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 603 "'%s' must be 'on', 'off', or 'type=disk'"), 604 propname); 605 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 606 goto error; 607 } 608 609 break; 610 611 case ZFS_PROP_MOUNTPOINT: 612 { 613 namecheck_err_t why; 614 615 if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || 616 strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) 617 break; 618 619 if (mountpoint_namecheck(strval, &why)) { 620 switch (why) { 621 case NAME_ERR_LEADING_SLASH: 622 zfs_error_aux(hdl, 623 dgettext(TEXT_DOMAIN, 624 "'%s' must be an absolute path, " 625 "'none', or 'legacy'"), propname); 626 break; 627 case NAME_ERR_TOOLONG: 628 zfs_error_aux(hdl, 629 dgettext(TEXT_DOMAIN, 630 "component of '%s' is too long"), 631 propname); 632 break; 633 } 634 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 635 goto error; 636 } 637 } 638 639 /*FALLTHRU*/ 640 641 case ZFS_PROP_SHARESMB: 642 case ZFS_PROP_SHARENFS: 643 /* 644 * For the mountpoint and sharenfs or sharesmb 645 * properties, check if it can be set in a 646 * global/non-global zone based on 647 * the zoned property value: 648 * 649 * global zone non-global zone 650 * -------------------------------------------------- 651 * zoned=on mountpoint (no) mountpoint (yes) 652 * sharenfs (no) sharenfs (no) 653 * sharesmb (no) sharesmb (no) 654 * 655 * zoned=off mountpoint (yes) N/A 656 * sharenfs (yes) 657 * sharesmb (yes) 658 */ 659 if (zoned) { 660 if (getzoneid() == GLOBAL_ZONEID) { 661 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 662 "'%s' cannot be set on " 663 "dataset in a non-global zone"), 664 propname); 665 (void) zfs_error(hdl, EZFS_ZONED, 666 errbuf); 667 goto error; 668 } else if (prop == ZFS_PROP_SHARENFS || 669 prop == ZFS_PROP_SHARESMB) { 670 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 671 "'%s' cannot be set in " 672 "a non-global zone"), propname); 673 (void) zfs_error(hdl, EZFS_ZONED, 674 errbuf); 675 goto error; 676 } 677 } else if (getzoneid() != GLOBAL_ZONEID) { 678 /* 679 * If zoned property is 'off', this must be in 680 * a globle zone. If not, something is wrong. 681 */ 682 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 683 "'%s' cannot be set while dataset " 684 "'zoned' property is set"), propname); 685 (void) zfs_error(hdl, EZFS_ZONED, errbuf); 686 goto error; 687 } 688 689 /* 690 * At this point, it is legitimate to set the 691 * property. Now we want to make sure that the 692 * property value is valid if it is sharenfs. 693 */ 694 if ((prop == ZFS_PROP_SHARENFS || 695 prop == ZFS_PROP_SHARESMB) && 696 strcmp(strval, "on") != 0 && 697 strcmp(strval, "off") != 0) { 698 zfs_share_proto_t proto; 699 700 if (prop == ZFS_PROP_SHARESMB) 701 proto = PROTO_SMB; 702 else 703 proto = PROTO_NFS; 704 705 /* 706 * Must be an valid sharing protocol 707 * option string so init the libshare 708 * in order to enable the parser and 709 * then parse the options. We use the 710 * control API since we don't care about 711 * the current configuration and don't 712 * want the overhead of loading it 713 * until we actually do something. 714 */ 715 716 if (zfs_init_libshare(hdl, 717 SA_INIT_CONTROL_API) != SA_OK) { 718 /* 719 * An error occurred so we can't do 720 * anything 721 */ 722 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 723 "'%s' cannot be set: problem " 724 "in share initialization"), 725 propname); 726 (void) zfs_error(hdl, EZFS_BADPROP, 727 errbuf); 728 goto error; 729 } 730 731 if (zfs_parse_options(strval, proto) != SA_OK) { 732 /* 733 * There was an error in parsing so 734 * deal with it by issuing an error 735 * message and leaving after 736 * uninitializing the the libshare 737 * interface. 738 */ 739 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 740 "'%s' cannot be set to invalid " 741 "options"), propname); 742 (void) zfs_error(hdl, EZFS_BADPROP, 743 errbuf); 744 zfs_uninit_libshare(hdl); 745 goto error; 746 } 747 zfs_uninit_libshare(hdl); 748 } 749 750 break; 751 case ZFS_PROP_CASE: 752 chosen_sense = (int)intval; 753 break; 754 case ZFS_PROP_UTF8ONLY: 755 chosen_utf = (int)intval; 756 break; 757 case ZFS_PROP_NORMALIZE: 758 chosen_normal = (int)intval; 759 break; 760 } 761 762 /* 763 * For changes to existing volumes, we have some additional 764 * checks to enforce. 765 */ 766 if (type == ZFS_TYPE_VOLUME && zhp != NULL) { 767 uint64_t volsize = zfs_prop_get_int(zhp, 768 ZFS_PROP_VOLSIZE); 769 uint64_t blocksize = zfs_prop_get_int(zhp, 770 ZFS_PROP_VOLBLOCKSIZE); 771 char buf[64]; 772 773 switch (prop) { 774 case ZFS_PROP_RESERVATION: 775 case ZFS_PROP_REFRESERVATION: 776 if (intval > volsize) { 777 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 778 "'%s' is greater than current " 779 "volume size"), propname); 780 (void) zfs_error(hdl, EZFS_BADPROP, 781 errbuf); 782 goto error; 783 } 784 break; 785 786 case ZFS_PROP_VOLSIZE: 787 if (intval % blocksize != 0) { 788 zfs_nicenum(blocksize, buf, 789 sizeof (buf)); 790 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 791 "'%s' must be a multiple of " 792 "volume block size (%s)"), 793 propname, buf); 794 (void) zfs_error(hdl, EZFS_BADPROP, 795 errbuf); 796 goto error; 797 } 798 799 if (intval == 0) { 800 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 801 "'%s' cannot be zero"), 802 propname); 803 (void) zfs_error(hdl, EZFS_BADPROP, 804 errbuf); 805 goto error; 806 } 807 break; 808 } 809 } 810 } 811 812 /* 813 * Temporarily disallow any non-default settings for 814 * casesensitivity, normalization, and/or utf8only. 815 */ 816 if (chosen_sense > ZFS_CASE_SENSITIVE || chosen_utf > 0 || 817 chosen_normal > ZFS_NORMALIZE_NONE) { 818 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 819 "Non-default values for casesensitivity, utf8only, and " 820 "normalization are (temporarily) disabled")); 821 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 822 goto error; 823 } 824 825 /* 826 * If normalization was chosen, but no UTF8 choice was made, 827 * enforce rejection of non-UTF8 names. 828 * 829 * If normalization was chosen, but rejecting non-UTF8 names 830 * was explicitly not chosen, it is an error. 831 */ 832 if (chosen_normal > ZFS_NORMALIZE_NONE && chosen_utf < 0) { 833 if (nvlist_add_uint64(ret, 834 zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) { 835 (void) no_memory(hdl); 836 goto error; 837 } 838 } else if (chosen_normal > ZFS_NORMALIZE_NONE && chosen_utf == 0) { 839 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 840 "'%s' must be set 'on' if normalization chosen"), 841 zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 842 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 843 goto error; 844 } 845 846 /* 847 * If this is an existing volume, and someone is setting the volsize, 848 * make sure that it matches the reservation, or add it if necessary. 849 */ 850 if (zhp != NULL && type == ZFS_TYPE_VOLUME && 851 nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE), 852 &intval) == 0) { 853 uint64_t old_volsize = zfs_prop_get_int(zhp, 854 ZFS_PROP_VOLSIZE); 855 uint64_t old_reservation = zfs_prop_get_int(zhp, 856 ZFS_PROP_RESERVATION); 857 uint64_t new_reservation; 858 859 if (old_volsize == old_reservation && 860 nvlist_lookup_uint64(ret, 861 zfs_prop_to_name(ZFS_PROP_RESERVATION), 862 &new_reservation) != 0) { 863 if (nvlist_add_uint64(ret, 864 zfs_prop_to_name(ZFS_PROP_RESERVATION), 865 intval) != 0) { 866 (void) no_memory(hdl); 867 goto error; 868 } 869 } 870 } 871 872 return (ret); 873 874 error: 875 nvlist_free(ret); 876 return (NULL); 877 } 878 879 static int 880 zfs_get_perm_who(const char *who, zfs_deleg_who_type_t *who_type, 881 uint64_t *ret_who) 882 { 883 struct passwd *pwd; 884 struct group *grp; 885 uid_t id; 886 887 if (*who_type == ZFS_DELEG_EVERYONE || *who_type == ZFS_DELEG_CREATE || 888 *who_type == ZFS_DELEG_NAMED_SET) { 889 *ret_who = -1; 890 return (0); 891 } 892 if (who == NULL && !(*who_type == ZFS_DELEG_EVERYONE)) 893 return (EZFS_BADWHO); 894 895 if (*who_type == ZFS_DELEG_WHO_UNKNOWN && 896 strcmp(who, "everyone") == 0) { 897 *ret_who = -1; 898 *who_type = ZFS_DELEG_EVERYONE; 899 return (0); 900 } 901 902 pwd = getpwnam(who); 903 grp = getgrnam(who); 904 905 if ((*who_type == ZFS_DELEG_USER) && pwd) { 906 *ret_who = pwd->pw_uid; 907 } else if ((*who_type == ZFS_DELEG_GROUP) && grp) { 908 *ret_who = grp->gr_gid; 909 } else if (pwd) { 910 *ret_who = pwd->pw_uid; 911 *who_type = ZFS_DELEG_USER; 912 } else if (grp) { 913 *ret_who = grp->gr_gid; 914 *who_type = ZFS_DELEG_GROUP; 915 } else { 916 char *end; 917 918 id = strtol(who, &end, 10); 919 if (errno != 0 || *end != '\0') { 920 return (EZFS_BADWHO); 921 } else { 922 *ret_who = id; 923 if (*who_type == ZFS_DELEG_WHO_UNKNOWN) 924 *who_type = ZFS_DELEG_USER; 925 } 926 } 927 928 return (0); 929 } 930 931 static void 932 zfs_perms_add_to_nvlist(nvlist_t *who_nvp, char *name, nvlist_t *perms_nvp) 933 { 934 if (perms_nvp != NULL) { 935 verify(nvlist_add_nvlist(who_nvp, 936 name, perms_nvp) == 0); 937 } else { 938 verify(nvlist_add_boolean(who_nvp, name) == 0); 939 } 940 } 941 942 static void 943 helper(zfs_deleg_who_type_t who_type, uint64_t whoid, char *whostr, 944 zfs_deleg_inherit_t inherit, nvlist_t *who_nvp, nvlist_t *perms_nvp, 945 nvlist_t *sets_nvp) 946 { 947 boolean_t do_perms, do_sets; 948 char name[ZFS_MAX_DELEG_NAME]; 949 950 do_perms = (nvlist_next_nvpair(perms_nvp, NULL) != NULL); 951 do_sets = (nvlist_next_nvpair(sets_nvp, NULL) != NULL); 952 953 if (!do_perms && !do_sets) 954 do_perms = do_sets = B_TRUE; 955 956 if (do_perms) { 957 zfs_deleg_whokey(name, who_type, inherit, 958 (who_type == ZFS_DELEG_NAMED_SET) ? 959 whostr : (void *)&whoid); 960 zfs_perms_add_to_nvlist(who_nvp, name, perms_nvp); 961 } 962 if (do_sets) { 963 zfs_deleg_whokey(name, toupper(who_type), inherit, 964 (who_type == ZFS_DELEG_NAMED_SET) ? 965 whostr : (void *)&whoid); 966 zfs_perms_add_to_nvlist(who_nvp, name, sets_nvp); 967 } 968 } 969 970 static void 971 zfs_perms_add_who_nvlist(nvlist_t *who_nvp, uint64_t whoid, void *whostr, 972 nvlist_t *perms_nvp, nvlist_t *sets_nvp, 973 zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit) 974 { 975 if (who_type == ZFS_DELEG_NAMED_SET || who_type == ZFS_DELEG_CREATE) { 976 helper(who_type, whoid, whostr, 0, 977 who_nvp, perms_nvp, sets_nvp); 978 } else { 979 if (inherit & ZFS_DELEG_PERM_LOCAL) { 980 helper(who_type, whoid, whostr, ZFS_DELEG_LOCAL, 981 who_nvp, perms_nvp, sets_nvp); 982 } 983 if (inherit & ZFS_DELEG_PERM_DESCENDENT) { 984 helper(who_type, whoid, whostr, ZFS_DELEG_DESCENDENT, 985 who_nvp, perms_nvp, sets_nvp); 986 } 987 } 988 } 989 990 /* 991 * Construct nvlist to pass down to kernel for setting/removing permissions. 992 * 993 * The nvlist is constructed as a series of nvpairs with an optional embedded 994 * nvlist of permissions to remove or set. The topmost nvpairs are the actual 995 * base attribute named stored in the dsl. 996 * Arguments: 997 * 998 * whostr: is a comma separated list of users, groups, or a single set name. 999 * whostr may be null for everyone or create perms. 1000 * who_type: is the type of entry in whostr. Typically this will be 1001 * ZFS_DELEG_WHO_UNKNOWN. 1002 * perms: common separated list of permissions. May be null if user 1003 * is requested to remove permissions by who. 1004 * inherit: Specifies the inheritance of the permissions. Will be either 1005 * ZFS_DELEG_PERM_LOCAL and/or ZFS_DELEG_PERM_DESCENDENT. 1006 * nvp The constructed nvlist to pass to zfs_perm_set(). 1007 * The output nvp will look something like this. 1008 * ul$1234 -> {create ; destroy } 1009 * Ul$1234 -> { @myset } 1010 * s-$@myset - { snapshot; checksum; compression } 1011 */ 1012 int 1013 zfs_build_perms(zfs_handle_t *zhp, char *whostr, char *perms, 1014 zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit, nvlist_t **nvp) 1015 { 1016 nvlist_t *who_nvp; 1017 nvlist_t *perms_nvp = NULL; 1018 nvlist_t *sets_nvp = NULL; 1019 char errbuf[1024]; 1020 char *who_tok, *perm; 1021 int error; 1022 1023 *nvp = NULL; 1024 1025 if (perms) { 1026 if ((error = nvlist_alloc(&perms_nvp, 1027 NV_UNIQUE_NAME, 0)) != 0) { 1028 return (1); 1029 } 1030 if ((error = nvlist_alloc(&sets_nvp, 1031 NV_UNIQUE_NAME, 0)) != 0) { 1032 nvlist_free(perms_nvp); 1033 return (1); 1034 } 1035 } 1036 1037 if ((error = nvlist_alloc(&who_nvp, NV_UNIQUE_NAME, 0)) != 0) { 1038 if (perms_nvp) 1039 nvlist_free(perms_nvp); 1040 if (sets_nvp) 1041 nvlist_free(sets_nvp); 1042 return (1); 1043 } 1044 1045 if (who_type == ZFS_DELEG_NAMED_SET) { 1046 namecheck_err_t why; 1047 char what; 1048 1049 if ((error = permset_namecheck(whostr, &why, &what)) != 0) { 1050 nvlist_free(who_nvp); 1051 if (perms_nvp) 1052 nvlist_free(perms_nvp); 1053 if (sets_nvp) 1054 nvlist_free(sets_nvp); 1055 1056 switch (why) { 1057 case NAME_ERR_NO_AT: 1058 zfs_error_aux(zhp->zfs_hdl, 1059 dgettext(TEXT_DOMAIN, 1060 "set definition must begin with an '@' " 1061 "character")); 1062 } 1063 return (zfs_error(zhp->zfs_hdl, 1064 EZFS_BADPERMSET, whostr)); 1065 } 1066 } 1067 1068 /* 1069 * Build up nvlist(s) of permissions. Two nvlists are maintained. 1070 * The first nvlist perms_nvp will have normal permissions and the 1071 * other sets_nvp will have only permssion set names in it. 1072 */ 1073 for (perm = strtok(perms, ","); perm; perm = strtok(NULL, ",")) { 1074 const char *perm_canonical = zfs_deleg_canonicalize_perm(perm); 1075 1076 if (perm_canonical) { 1077 verify(nvlist_add_boolean(perms_nvp, 1078 perm_canonical) == 0); 1079 } else if (perm[0] == '@') { 1080 verify(nvlist_add_boolean(sets_nvp, perm) == 0); 1081 } else { 1082 nvlist_free(who_nvp); 1083 nvlist_free(perms_nvp); 1084 nvlist_free(sets_nvp); 1085 return (zfs_error(zhp->zfs_hdl, EZFS_BADPERM, perm)); 1086 } 1087 } 1088 1089 if (whostr && who_type != ZFS_DELEG_CREATE) { 1090 who_tok = strtok(whostr, ","); 1091 if (who_tok == NULL) { 1092 nvlist_free(who_nvp); 1093 if (perms_nvp) 1094 nvlist_free(perms_nvp); 1095 if (sets_nvp) 1096 nvlist_free(sets_nvp); 1097 (void) snprintf(errbuf, sizeof (errbuf), 1098 dgettext(TEXT_DOMAIN, "Who string is NULL"), 1099 whostr); 1100 return (zfs_error(zhp->zfs_hdl, EZFS_BADWHO, errbuf)); 1101 } 1102 } 1103 1104 /* 1105 * Now create the nvlist(s) 1106 */ 1107 do { 1108 uint64_t who_id; 1109 1110 error = zfs_get_perm_who(who_tok, &who_type, 1111 &who_id); 1112 if (error) { 1113 nvlist_free(who_nvp); 1114 if (perms_nvp) 1115 nvlist_free(perms_nvp); 1116 if (sets_nvp) 1117 nvlist_free(sets_nvp); 1118 (void) snprintf(errbuf, sizeof (errbuf), 1119 dgettext(TEXT_DOMAIN, 1120 "Unable to determine uid/gid for " 1121 "%s "), who_tok); 1122 return (zfs_error(zhp->zfs_hdl, EZFS_BADWHO, errbuf)); 1123 } 1124 1125 /* 1126 * add entries for both local and descendent when required 1127 */ 1128 zfs_perms_add_who_nvlist(who_nvp, who_id, who_tok, 1129 perms_nvp, sets_nvp, who_type, inherit); 1130 1131 } while (who_tok = strtok(NULL, ",")); 1132 *nvp = who_nvp; 1133 return (0); 1134 } 1135 1136 static int 1137 zfs_perm_set_common(zfs_handle_t *zhp, nvlist_t *nvp, boolean_t unset) 1138 { 1139 zfs_cmd_t zc = { 0 }; 1140 int error; 1141 char errbuf[1024]; 1142 1143 (void) snprintf(errbuf, sizeof (errbuf), 1144 dgettext(TEXT_DOMAIN, "Cannot update 'allows' for '%s'"), 1145 zhp->zfs_name); 1146 1147 if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, nvp)) 1148 return (-1); 1149 1150 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1151 zc.zc_perm_action = unset; 1152 1153 error = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SET_FSACL, &zc); 1154 if (error && errno == ENOTSUP) { 1155 (void) snprintf(errbuf, sizeof (errbuf), 1156 gettext("Pool must be upgraded to use 'allow/unallow'")); 1157 zcmd_free_nvlists(&zc); 1158 return (zfs_error(zhp->zfs_hdl, EZFS_BADVERSION, errbuf)); 1159 } else if (error) { 1160 return (zfs_standard_error(zhp->zfs_hdl, errno, errbuf)); 1161 } 1162 zcmd_free_nvlists(&zc); 1163 1164 return (error); 1165 } 1166 1167 int 1168 zfs_perm_set(zfs_handle_t *zhp, nvlist_t *nvp) 1169 { 1170 return (zfs_perm_set_common(zhp, nvp, B_FALSE)); 1171 } 1172 1173 int 1174 zfs_perm_remove(zfs_handle_t *zhp, nvlist_t *perms) 1175 { 1176 return (zfs_perm_set_common(zhp, perms, B_TRUE)); 1177 } 1178 1179 static int 1180 perm_compare(const void *arg1, const void *arg2) 1181 { 1182 const zfs_perm_node_t *node1 = arg1; 1183 const zfs_perm_node_t *node2 = arg2; 1184 int ret; 1185 1186 ret = strcmp(node1->z_pname, node2->z_pname); 1187 1188 if (ret > 0) 1189 return (1); 1190 if (ret < 0) 1191 return (-1); 1192 else 1193 return (0); 1194 } 1195 1196 static void 1197 zfs_destroy_perm_tree(avl_tree_t *tree) 1198 { 1199 zfs_perm_node_t *permnode; 1200 void *cookie = NULL; 1201 1202 while ((permnode = avl_destroy_nodes(tree, &cookie)) != NULL) 1203 free(permnode); 1204 avl_destroy(tree); 1205 } 1206 1207 static void 1208 zfs_destroy_tree(avl_tree_t *tree) 1209 { 1210 zfs_allow_node_t *allownode; 1211 void *cookie = NULL; 1212 1213 while ((allownode = avl_destroy_nodes(tree, &cookie)) != NULL) { 1214 zfs_destroy_perm_tree(&allownode->z_localdescend); 1215 zfs_destroy_perm_tree(&allownode->z_local); 1216 zfs_destroy_perm_tree(&allownode->z_descend); 1217 free(allownode); 1218 } 1219 avl_destroy(tree); 1220 } 1221 1222 void 1223 zfs_free_allows(zfs_allow_t *allow) 1224 { 1225 zfs_allow_t *allownext; 1226 zfs_allow_t *freeallow; 1227 1228 allownext = allow; 1229 while (allownext) { 1230 zfs_destroy_tree(&allownext->z_sets); 1231 zfs_destroy_tree(&allownext->z_crperms); 1232 zfs_destroy_tree(&allownext->z_user); 1233 zfs_destroy_tree(&allownext->z_group); 1234 zfs_destroy_tree(&allownext->z_everyone); 1235 freeallow = allownext; 1236 allownext = allownext->z_next; 1237 free(freeallow); 1238 } 1239 } 1240 1241 static zfs_allow_t * 1242 zfs_alloc_perm_tree(zfs_handle_t *zhp, zfs_allow_t *prev, char *setpoint) 1243 { 1244 zfs_allow_t *ptree; 1245 1246 if ((ptree = zfs_alloc(zhp->zfs_hdl, 1247 sizeof (zfs_allow_t))) == NULL) { 1248 return (NULL); 1249 } 1250 1251 (void) strlcpy(ptree->z_setpoint, setpoint, sizeof (ptree->z_setpoint)); 1252 avl_create(&ptree->z_sets, 1253 perm_compare, sizeof (zfs_allow_node_t), 1254 offsetof(zfs_allow_node_t, z_node)); 1255 avl_create(&ptree->z_crperms, 1256 perm_compare, sizeof (zfs_allow_node_t), 1257 offsetof(zfs_allow_node_t, z_node)); 1258 avl_create(&ptree->z_user, 1259 perm_compare, sizeof (zfs_allow_node_t), 1260 offsetof(zfs_allow_node_t, z_node)); 1261 avl_create(&ptree->z_group, 1262 perm_compare, sizeof (zfs_allow_node_t), 1263 offsetof(zfs_allow_node_t, z_node)); 1264 avl_create(&ptree->z_everyone, 1265 perm_compare, sizeof (zfs_allow_node_t), 1266 offsetof(zfs_allow_node_t, z_node)); 1267 1268 if (prev) 1269 prev->z_next = ptree; 1270 ptree->z_next = NULL; 1271 return (ptree); 1272 } 1273 1274 /* 1275 * Add permissions to the appropriate AVL permission tree. 1276 * The appropriate tree may not be the requested tree. 1277 * For example if ld indicates a local permission, but 1278 * same permission also exists as a descendent permission 1279 * then the permission will be removed from the descendent 1280 * tree and add the the local+descendent tree. 1281 */ 1282 static int 1283 zfs_coalesce_perm(zfs_handle_t *zhp, zfs_allow_node_t *allownode, 1284 char *perm, char ld) 1285 { 1286 zfs_perm_node_t pnode, *permnode, *permnode2; 1287 zfs_perm_node_t *newnode; 1288 avl_index_t where, where2; 1289 avl_tree_t *tree, *altree; 1290 1291 (void) strlcpy(pnode.z_pname, perm, sizeof (pnode.z_pname)); 1292 1293 if (ld == ZFS_DELEG_NA) { 1294 tree = &allownode->z_localdescend; 1295 altree = &allownode->z_descend; 1296 } else if (ld == ZFS_DELEG_LOCAL) { 1297 tree = &allownode->z_local; 1298 altree = &allownode->z_descend; 1299 } else { 1300 tree = &allownode->z_descend; 1301 altree = &allownode->z_local; 1302 } 1303 permnode = avl_find(tree, &pnode, &where); 1304 permnode2 = avl_find(altree, &pnode, &where2); 1305 1306 if (permnode2) { 1307 avl_remove(altree, permnode2); 1308 free(permnode2); 1309 if (permnode == NULL) { 1310 tree = &allownode->z_localdescend; 1311 } 1312 } 1313 1314 /* 1315 * Now insert new permission in either requested location 1316 * local/descendent or into ld when perm will exist in both. 1317 */ 1318 if (permnode == NULL) { 1319 if ((newnode = zfs_alloc(zhp->zfs_hdl, 1320 sizeof (zfs_perm_node_t))) == NULL) { 1321 return (-1); 1322 } 1323 *newnode = pnode; 1324 avl_add(tree, newnode); 1325 } 1326 return (0); 1327 } 1328 1329 /* 1330 * Uggh, this is going to be a bit complicated. 1331 * we have an nvlist coming out of the kernel that 1332 * will indicate where the permission is set and then 1333 * it will contain allow of the various "who's", and what 1334 * their permissions are. To further complicate this 1335 * we will then have to coalesce the local,descendent 1336 * and local+descendent permissions where appropriate. 1337 * The kernel only knows about a permission as being local 1338 * or descendent, but not both. 1339 * 1340 * In order to make this easier for zfs_main to deal with 1341 * a series of AVL trees will be used to maintain 1342 * all of this, primarily for sorting purposes as well 1343 * as the ability to quickly locate a specific entry. 1344 * 1345 * What we end up with are tree's for sets, create perms, 1346 * user, groups and everyone. With each of those trees 1347 * we have subtrees for local, descendent and local+descendent 1348 * permissions. 1349 */ 1350 int 1351 zfs_perm_get(zfs_handle_t *zhp, zfs_allow_t **zfs_perms) 1352 { 1353 zfs_cmd_t zc = { 0 }; 1354 int error; 1355 nvlist_t *nvlist; 1356 nvlist_t *permnv, *sourcenv; 1357 nvpair_t *who_pair, *source_pair; 1358 nvpair_t *perm_pair; 1359 char errbuf[1024]; 1360 zfs_allow_t *zallowp, *newallowp; 1361 char ld; 1362 char *nvpname; 1363 uid_t uid; 1364 gid_t gid; 1365 avl_tree_t *tree; 1366 avl_index_t where; 1367 1368 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1369 1370 if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 1371 return (-1); 1372 1373 while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) { 1374 if (errno == ENOMEM) { 1375 if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, &zc) != 0) { 1376 zcmd_free_nvlists(&zc); 1377 return (-1); 1378 } 1379 } else if (errno == ENOTSUP) { 1380 zcmd_free_nvlists(&zc); 1381 (void) snprintf(errbuf, sizeof (errbuf), 1382 gettext("Pool must be upgraded to use 'allow'")); 1383 return (zfs_error(zhp->zfs_hdl, 1384 EZFS_BADVERSION, errbuf)); 1385 } else { 1386 zcmd_free_nvlists(&zc); 1387 return (-1); 1388 } 1389 } 1390 1391 if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &nvlist) != 0) { 1392 zcmd_free_nvlists(&zc); 1393 return (-1); 1394 } 1395 1396 zcmd_free_nvlists(&zc); 1397 1398 source_pair = nvlist_next_nvpair(nvlist, NULL); 1399 1400 if (source_pair == NULL) { 1401 *zfs_perms = NULL; 1402 return (0); 1403 } 1404 1405 *zfs_perms = zfs_alloc_perm_tree(zhp, NULL, nvpair_name(source_pair)); 1406 if (*zfs_perms == NULL) { 1407 return (0); 1408 } 1409 1410 zallowp = *zfs_perms; 1411 1412 for (;;) { 1413 struct passwd *pwd; 1414 struct group *grp; 1415 zfs_allow_node_t *allownode; 1416 zfs_allow_node_t findallownode; 1417 zfs_allow_node_t *newallownode; 1418 1419 (void) strlcpy(zallowp->z_setpoint, 1420 nvpair_name(source_pair), 1421 sizeof (zallowp->z_setpoint)); 1422 1423 if ((error = nvpair_value_nvlist(source_pair, &sourcenv)) != 0) 1424 goto abort; 1425 1426 /* 1427 * Make sure nvlist is composed correctly 1428 */ 1429 if (zfs_deleg_verify_nvlist(sourcenv)) { 1430 goto abort; 1431 } 1432 1433 who_pair = nvlist_next_nvpair(sourcenv, NULL); 1434 if (who_pair == NULL) { 1435 goto abort; 1436 } 1437 1438 do { 1439 error = nvpair_value_nvlist(who_pair, &permnv); 1440 if (error) { 1441 goto abort; 1442 } 1443 1444 /* 1445 * First build up the key to use 1446 * for looking up in the various 1447 * who trees. 1448 */ 1449 ld = nvpair_name(who_pair)[1]; 1450 nvpname = nvpair_name(who_pair); 1451 switch (nvpair_name(who_pair)[0]) { 1452 case ZFS_DELEG_USER: 1453 case ZFS_DELEG_USER_SETS: 1454 tree = &zallowp->z_user; 1455 uid = atol(&nvpname[3]); 1456 pwd = getpwuid(uid); 1457 (void) snprintf(findallownode.z_key, 1458 sizeof (findallownode.z_key), "user %s", 1459 (pwd) ? pwd->pw_name : 1460 &nvpair_name(who_pair)[3]); 1461 break; 1462 case ZFS_DELEG_GROUP: 1463 case ZFS_DELEG_GROUP_SETS: 1464 tree = &zallowp->z_group; 1465 gid = atol(&nvpname[3]); 1466 grp = getgrgid(gid); 1467 (void) snprintf(findallownode.z_key, 1468 sizeof (findallownode.z_key), "group %s", 1469 (grp) ? grp->gr_name : 1470 &nvpair_name(who_pair)[3]); 1471 break; 1472 case ZFS_DELEG_CREATE: 1473 case ZFS_DELEG_CREATE_SETS: 1474 tree = &zallowp->z_crperms; 1475 (void) strlcpy(findallownode.z_key, "", 1476 sizeof (findallownode.z_key)); 1477 break; 1478 case ZFS_DELEG_EVERYONE: 1479 case ZFS_DELEG_EVERYONE_SETS: 1480 (void) snprintf(findallownode.z_key, 1481 sizeof (findallownode.z_key), "everyone"); 1482 tree = &zallowp->z_everyone; 1483 break; 1484 case ZFS_DELEG_NAMED_SET: 1485 case ZFS_DELEG_NAMED_SET_SETS: 1486 (void) snprintf(findallownode.z_key, 1487 sizeof (findallownode.z_key), "%s", 1488 &nvpair_name(who_pair)[3]); 1489 tree = &zallowp->z_sets; 1490 break; 1491 } 1492 1493 /* 1494 * Place who in tree 1495 */ 1496 allownode = avl_find(tree, &findallownode, &where); 1497 if (allownode == NULL) { 1498 if ((newallownode = zfs_alloc(zhp->zfs_hdl, 1499 sizeof (zfs_allow_node_t))) == NULL) { 1500 goto abort; 1501 } 1502 avl_create(&newallownode->z_localdescend, 1503 perm_compare, 1504 sizeof (zfs_perm_node_t), 1505 offsetof(zfs_perm_node_t, z_node)); 1506 avl_create(&newallownode->z_local, 1507 perm_compare, 1508 sizeof (zfs_perm_node_t), 1509 offsetof(zfs_perm_node_t, z_node)); 1510 avl_create(&newallownode->z_descend, 1511 perm_compare, 1512 sizeof (zfs_perm_node_t), 1513 offsetof(zfs_perm_node_t, z_node)); 1514 (void) strlcpy(newallownode->z_key, 1515 findallownode.z_key, 1516 sizeof (findallownode.z_key)); 1517 avl_insert(tree, newallownode, where); 1518 allownode = newallownode; 1519 } 1520 1521 /* 1522 * Now iterate over the permissions and 1523 * place them in the appropriate local, 1524 * descendent or local+descendent tree. 1525 * 1526 * The permissions are added to the tree 1527 * via zfs_coalesce_perm(). 1528 */ 1529 perm_pair = nvlist_next_nvpair(permnv, NULL); 1530 if (perm_pair == NULL) 1531 goto abort; 1532 do { 1533 if (zfs_coalesce_perm(zhp, allownode, 1534 nvpair_name(perm_pair), ld) != 0) 1535 goto abort; 1536 } while (perm_pair = nvlist_next_nvpair(permnv, 1537 perm_pair)); 1538 } while (who_pair = nvlist_next_nvpair(sourcenv, who_pair)); 1539 1540 source_pair = nvlist_next_nvpair(nvlist, source_pair); 1541 if (source_pair == NULL) 1542 break; 1543 1544 /* 1545 * allocate another node from the link list of 1546 * zfs_allow_t structures 1547 */ 1548 newallowp = zfs_alloc_perm_tree(zhp, zallowp, 1549 nvpair_name(source_pair)); 1550 if (newallowp == NULL) { 1551 goto abort; 1552 } 1553 zallowp = newallowp; 1554 } 1555 nvlist_free(nvlist); 1556 return (0); 1557 abort: 1558 zfs_free_allows(*zfs_perms); 1559 nvlist_free(nvlist); 1560 return (-1); 1561 } 1562 1563 /* 1564 * Given a property name and value, set the property for the given dataset. 1565 */ 1566 int 1567 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1568 { 1569 zfs_cmd_t zc = { 0 }; 1570 int ret = -1; 1571 prop_changelist_t *cl = NULL; 1572 char errbuf[1024]; 1573 libzfs_handle_t *hdl = zhp->zfs_hdl; 1574 nvlist_t *nvl = NULL, *realprops; 1575 zfs_prop_t prop; 1576 1577 (void) snprintf(errbuf, sizeof (errbuf), 1578 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 1579 zhp->zfs_name); 1580 1581 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 1582 nvlist_add_string(nvl, propname, propval) != 0) { 1583 (void) no_memory(hdl); 1584 goto error; 1585 } 1586 1587 if ((realprops = zfs_validate_properties(hdl, zhp->zfs_type, nvl, 1588 zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL) 1589 goto error; 1590 1591 nvlist_free(nvl); 1592 nvl = realprops; 1593 1594 prop = zfs_name_to_prop(propname); 1595 1596 if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 1597 goto error; 1598 1599 if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 1600 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1601 "child dataset with inherited mountpoint is used " 1602 "in a non-global zone")); 1603 ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1604 goto error; 1605 } 1606 1607 if ((ret = changelist_prefix(cl)) != 0) 1608 goto error; 1609 1610 /* 1611 * Execute the corresponding ioctl() to set this property. 1612 */ 1613 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1614 1615 if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0) 1616 goto error; 1617 1618 ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); 1619 1620 if (ret != 0) { 1621 switch (errno) { 1622 1623 case ENOSPC: 1624 /* 1625 * For quotas and reservations, ENOSPC indicates 1626 * something different; setting a quota or reservation 1627 * doesn't use any disk space. 1628 */ 1629 switch (prop) { 1630 case ZFS_PROP_QUOTA: 1631 case ZFS_PROP_REFQUOTA: 1632 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1633 "size is less than current used or " 1634 "reserved space")); 1635 (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1636 break; 1637 1638 case ZFS_PROP_RESERVATION: 1639 case ZFS_PROP_REFRESERVATION: 1640 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1641 "size is greater than available space")); 1642 (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1643 break; 1644 1645 default: 1646 (void) zfs_standard_error(hdl, errno, errbuf); 1647 break; 1648 } 1649 break; 1650 1651 case EBUSY: 1652 if (prop == ZFS_PROP_VOLBLOCKSIZE) 1653 (void) zfs_error(hdl, EZFS_VOLHASDATA, errbuf); 1654 else 1655 (void) zfs_standard_error(hdl, EBUSY, errbuf); 1656 break; 1657 1658 case EROFS: 1659 (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf); 1660 break; 1661 1662 case ENOTSUP: 1663 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1664 "pool must be upgraded to set this " 1665 "property or value")); 1666 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 1667 break; 1668 1669 case EOVERFLOW: 1670 /* 1671 * This platform can't address a volume this big. 1672 */ 1673 #ifdef _ILP32 1674 if (prop == ZFS_PROP_VOLSIZE) { 1675 (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf); 1676 break; 1677 } 1678 #endif 1679 /* FALLTHROUGH */ 1680 default: 1681 (void) zfs_standard_error(hdl, errno, errbuf); 1682 } 1683 } else { 1684 /* 1685 * Refresh the statistics so the new property value 1686 * is reflected. 1687 */ 1688 if ((ret = changelist_postfix(cl)) == 0) 1689 (void) get_stats(zhp); 1690 } 1691 1692 error: 1693 nvlist_free(nvl); 1694 zcmd_free_nvlists(&zc); 1695 if (cl) 1696 changelist_free(cl); 1697 return (ret); 1698 } 1699 1700 /* 1701 * Given a property, inherit the value from the parent dataset. 1702 */ 1703 int 1704 zfs_prop_inherit(zfs_handle_t *zhp, const char *propname) 1705 { 1706 zfs_cmd_t zc = { 0 }; 1707 int ret; 1708 prop_changelist_t *cl; 1709 libzfs_handle_t *hdl = zhp->zfs_hdl; 1710 char errbuf[1024]; 1711 zfs_prop_t prop; 1712 1713 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1714 "cannot inherit %s for '%s'"), propname, zhp->zfs_name); 1715 1716 if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) { 1717 /* 1718 * For user properties, the amount of work we have to do is very 1719 * small, so just do it here. 1720 */ 1721 if (!zfs_prop_user(propname)) { 1722 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1723 "invalid property")); 1724 return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 1725 } 1726 1727 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1728 (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1729 1730 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0) 1731 return (zfs_standard_error(hdl, errno, errbuf)); 1732 1733 return (0); 1734 } 1735 1736 /* 1737 * Verify that this property is inheritable. 1738 */ 1739 if (zfs_prop_readonly(prop)) 1740 return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf)); 1741 1742 if (!zfs_prop_inheritable(prop)) 1743 return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf)); 1744 1745 /* 1746 * Check to see if the value applies to this type 1747 */ 1748 if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1749 return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); 1750 1751 /* 1752 * Normalize the name, to get rid of shorthand abbrevations. 1753 */ 1754 propname = zfs_prop_to_name(prop); 1755 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1756 (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1757 1758 if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 1759 zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 1760 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1761 "dataset is used in a non-global zone")); 1762 return (zfs_error(hdl, EZFS_ZONED, errbuf)); 1763 } 1764 1765 /* 1766 * Determine datasets which will be affected by this change, if any. 1767 */ 1768 if ((cl = changelist_gather(zhp, prop, 0)) == NULL) 1769 return (-1); 1770 1771 if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 1772 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1773 "child dataset with inherited mountpoint is used " 1774 "in a non-global zone")); 1775 ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1776 goto error; 1777 } 1778 1779 if ((ret = changelist_prefix(cl)) != 0) 1780 goto error; 1781 1782 if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) { 1783 return (zfs_standard_error(hdl, errno, errbuf)); 1784 } else { 1785 1786 if ((ret = changelist_postfix(cl)) != 0) 1787 goto error; 1788 1789 /* 1790 * Refresh the statistics so the new property is reflected. 1791 */ 1792 (void) get_stats(zhp); 1793 } 1794 1795 error: 1796 changelist_free(cl); 1797 return (ret); 1798 } 1799 1800 /* 1801 * True DSL properties are stored in an nvlist. The following two functions 1802 * extract them appropriately. 1803 */ 1804 static uint64_t 1805 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 1806 { 1807 nvlist_t *nv; 1808 uint64_t value; 1809 1810 *source = NULL; 1811 if (nvlist_lookup_nvlist(zhp->zfs_props, 1812 zfs_prop_to_name(prop), &nv) == 0) { 1813 verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0); 1814 (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source); 1815 } else { 1816 value = zfs_prop_default_numeric(prop); 1817 *source = ""; 1818 } 1819 1820 return (value); 1821 } 1822 1823 static char * 1824 getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 1825 { 1826 nvlist_t *nv; 1827 char *value; 1828 1829 *source = NULL; 1830 if (nvlist_lookup_nvlist(zhp->zfs_props, 1831 zfs_prop_to_name(prop), &nv) == 0) { 1832 verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); 1833 (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source); 1834 } else { 1835 if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 1836 value = ""; 1837 *source = ""; 1838 } 1839 1840 return (value); 1841 } 1842 1843 /* 1844 * Internal function for getting a numeric property. Both zfs_prop_get() and 1845 * zfs_prop_get_int() are built using this interface. 1846 * 1847 * Certain properties can be overridden using 'mount -o'. In this case, scan 1848 * the contents of the /etc/mnttab entry, searching for the appropriate options. 1849 * If they differ from the on-disk values, report the current values and mark 1850 * the source "temporary". 1851 */ 1852 static int 1853 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, 1854 char **source, uint64_t *val) 1855 { 1856 zfs_cmd_t zc = { 0 }; 1857 struct mnttab mnt; 1858 char *mntopt_on = NULL; 1859 char *mntopt_off = NULL; 1860 1861 *source = NULL; 1862 1863 switch (prop) { 1864 case ZFS_PROP_ATIME: 1865 mntopt_on = MNTOPT_ATIME; 1866 mntopt_off = MNTOPT_NOATIME; 1867 break; 1868 1869 case ZFS_PROP_DEVICES: 1870 mntopt_on = MNTOPT_DEVICES; 1871 mntopt_off = MNTOPT_NODEVICES; 1872 break; 1873 1874 case ZFS_PROP_EXEC: 1875 mntopt_on = MNTOPT_EXEC; 1876 mntopt_off = MNTOPT_NOEXEC; 1877 break; 1878 1879 case ZFS_PROP_READONLY: 1880 mntopt_on = MNTOPT_RO; 1881 mntopt_off = MNTOPT_RW; 1882 break; 1883 1884 case ZFS_PROP_SETUID: 1885 mntopt_on = MNTOPT_SETUID; 1886 mntopt_off = MNTOPT_NOSETUID; 1887 break; 1888 1889 case ZFS_PROP_XATTR: 1890 mntopt_on = MNTOPT_XATTR; 1891 mntopt_off = MNTOPT_NOXATTR; 1892 break; 1893 1894 case ZFS_PROP_NBMAND: 1895 mntopt_on = MNTOPT_NBMAND; 1896 mntopt_off = MNTOPT_NONBMAND; 1897 break; 1898 } 1899 1900 /* 1901 * Because looking up the mount options is potentially expensive 1902 * (iterating over all of /etc/mnttab), we defer its calculation until 1903 * we're looking up a property which requires its presence. 1904 */ 1905 if (!zhp->zfs_mntcheck && 1906 (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { 1907 struct mnttab entry, search = { 0 }; 1908 FILE *mnttab = zhp->zfs_hdl->libzfs_mnttab; 1909 1910 search.mnt_special = (char *)zhp->zfs_name; 1911 search.mnt_fstype = MNTTYPE_ZFS; 1912 rewind(mnttab); 1913 1914 if (getmntany(mnttab, &entry, &search) == 0) { 1915 zhp->zfs_mntopts = zfs_strdup(zhp->zfs_hdl, 1916 entry.mnt_mntopts); 1917 if (zhp->zfs_mntopts == NULL) 1918 return (-1); 1919 } 1920 1921 zhp->zfs_mntcheck = B_TRUE; 1922 } 1923 1924 if (zhp->zfs_mntopts == NULL) 1925 mnt.mnt_mntopts = ""; 1926 else 1927 mnt.mnt_mntopts = zhp->zfs_mntopts; 1928 1929 switch (prop) { 1930 case ZFS_PROP_ATIME: 1931 case ZFS_PROP_DEVICES: 1932 case ZFS_PROP_EXEC: 1933 case ZFS_PROP_READONLY: 1934 case ZFS_PROP_SETUID: 1935 case ZFS_PROP_XATTR: 1936 case ZFS_PROP_NBMAND: 1937 *val = getprop_uint64(zhp, prop, source); 1938 1939 if (hasmntopt(&mnt, mntopt_on) && !*val) { 1940 *val = B_TRUE; 1941 if (src) 1942 *src = ZPROP_SRC_TEMPORARY; 1943 } else if (hasmntopt(&mnt, mntopt_off) && *val) { 1944 *val = B_FALSE; 1945 if (src) 1946 *src = ZPROP_SRC_TEMPORARY; 1947 } 1948 break; 1949 1950 case ZFS_PROP_CANMOUNT: 1951 *val = getprop_uint64(zhp, prop, source); 1952 if (*val == 0) 1953 *source = zhp->zfs_name; 1954 else 1955 *source = ""; /* default */ 1956 break; 1957 1958 case ZFS_PROP_QUOTA: 1959 case ZFS_PROP_REFQUOTA: 1960 case ZFS_PROP_RESERVATION: 1961 case ZFS_PROP_REFRESERVATION: 1962 *val = getprop_uint64(zhp, prop, source); 1963 if (*val == 0) 1964 *source = ""; /* default */ 1965 else 1966 *source = zhp->zfs_name; 1967 break; 1968 1969 case ZFS_PROP_MOUNTED: 1970 *val = (zhp->zfs_mntopts != NULL); 1971 break; 1972 1973 case ZFS_PROP_NUMCLONES: 1974 *val = zhp->zfs_dmustats.dds_num_clones; 1975 break; 1976 1977 case ZFS_PROP_VERSION: 1978 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1979 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_VERSION, &zc) || 1980 (zc.zc_cookie == 0)) { 1981 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1982 "unable to get version property")); 1983 return (zfs_error(zhp->zfs_hdl, EZFS_BADVERSION, 1984 dgettext(TEXT_DOMAIN, "internal error"))); 1985 } 1986 *val = zc.zc_cookie; 1987 break; 1988 1989 default: 1990 switch (zfs_prop_get_type(prop)) { 1991 case PROP_TYPE_NUMBER: 1992 case PROP_TYPE_INDEX: 1993 *val = getprop_uint64(zhp, prop, source); 1994 break; 1995 1996 case PROP_TYPE_STRING: 1997 default: 1998 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1999 "cannot get non-numeric property")); 2000 return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP, 2001 dgettext(TEXT_DOMAIN, "internal error"))); 2002 } 2003 } 2004 2005 return (0); 2006 } 2007 2008 /* 2009 * Calculate the source type, given the raw source string. 2010 */ 2011 static void 2012 get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source, 2013 char *statbuf, size_t statlen) 2014 { 2015 if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY) 2016 return; 2017 2018 if (source == NULL) { 2019 *srctype = ZPROP_SRC_NONE; 2020 } else if (source[0] == '\0') { 2021 *srctype = ZPROP_SRC_DEFAULT; 2022 } else { 2023 if (strcmp(source, zhp->zfs_name) == 0) { 2024 *srctype = ZPROP_SRC_LOCAL; 2025 } else { 2026 (void) strlcpy(statbuf, source, statlen); 2027 *srctype = ZPROP_SRC_INHERITED; 2028 } 2029 } 2030 2031 } 2032 2033 /* 2034 * Retrieve a property from the given object. If 'literal' is specified, then 2035 * numbers are left as exact values. Otherwise, numbers are converted to a 2036 * human-readable form. 2037 * 2038 * Returns 0 on success, or -1 on error. 2039 */ 2040 int 2041 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 2042 zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal) 2043 { 2044 char *source = NULL; 2045 uint64_t val; 2046 char *str; 2047 const char *root; 2048 const char *strval; 2049 2050 /* 2051 * Check to see if this property applies to our object 2052 */ 2053 if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 2054 return (-1); 2055 2056 if (src) 2057 *src = ZPROP_SRC_NONE; 2058 2059 switch (prop) { 2060 case ZFS_PROP_CREATION: 2061 /* 2062 * 'creation' is a time_t stored in the statistics. We convert 2063 * this into a string unless 'literal' is specified. 2064 */ 2065 { 2066 val = getprop_uint64(zhp, prop, &source); 2067 time_t time = (time_t)val; 2068 struct tm t; 2069 2070 if (literal || 2071 localtime_r(&time, &t) == NULL || 2072 strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 2073 &t) == 0) 2074 (void) snprintf(propbuf, proplen, "%llu", val); 2075 } 2076 break; 2077 2078 case ZFS_PROP_MOUNTPOINT: 2079 /* 2080 * Getting the precise mountpoint can be tricky. 2081 * 2082 * - for 'none' or 'legacy', return those values. 2083 * - for default mountpoints, construct it as /zfs/<dataset> 2084 * - for inherited mountpoints, we want to take everything 2085 * after our ancestor and append it to the inherited value. 2086 * 2087 * If the pool has an alternate root, we want to prepend that 2088 * root to any values we return. 2089 */ 2090 root = zhp->zfs_root; 2091 str = getprop_string(zhp, prop, &source); 2092 2093 if (str[0] == '\0') { 2094 (void) snprintf(propbuf, proplen, "%s/zfs/%s", 2095 root, zhp->zfs_name); 2096 } else if (str[0] == '/') { 2097 const char *relpath = zhp->zfs_name + strlen(source); 2098 2099 if (relpath[0] == '/') 2100 relpath++; 2101 if (str[1] == '\0') 2102 str++; 2103 2104 if (relpath[0] == '\0') 2105 (void) snprintf(propbuf, proplen, "%s%s", 2106 root, str); 2107 else 2108 (void) snprintf(propbuf, proplen, "%s%s%s%s", 2109 root, str, relpath[0] == '@' ? "" : "/", 2110 relpath); 2111 } else { 2112 /* 'legacy' or 'none' */ 2113 (void) strlcpy(propbuf, str, proplen); 2114 } 2115 2116 break; 2117 2118 case ZFS_PROP_ORIGIN: 2119 (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 2120 proplen); 2121 /* 2122 * If there is no parent at all, return failure to indicate that 2123 * it doesn't apply to this dataset. 2124 */ 2125 if (propbuf[0] == '\0') 2126 return (-1); 2127 break; 2128 2129 case ZFS_PROP_QUOTA: 2130 case ZFS_PROP_REFQUOTA: 2131 case ZFS_PROP_RESERVATION: 2132 case ZFS_PROP_REFRESERVATION: 2133 2134 if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 2135 return (-1); 2136 2137 /* 2138 * If quota or reservation is 0, we translate this into 'none' 2139 * (unless literal is set), and indicate that it's the default 2140 * value. Otherwise, we print the number nicely and indicate 2141 * that its set locally. 2142 */ 2143 if (val == 0) { 2144 if (literal) 2145 (void) strlcpy(propbuf, "0", proplen); 2146 else 2147 (void) strlcpy(propbuf, "none", proplen); 2148 } else { 2149 if (literal) 2150 (void) snprintf(propbuf, proplen, "%llu", 2151 (u_longlong_t)val); 2152 else 2153 zfs_nicenum(val, propbuf, proplen); 2154 } 2155 break; 2156 2157 case ZFS_PROP_COMPRESSRATIO: 2158 if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 2159 return (-1); 2160 (void) snprintf(propbuf, proplen, "%lld.%02lldx", (longlong_t) 2161 val / 100, (longlong_t)val % 100); 2162 break; 2163 2164 case ZFS_PROP_TYPE: 2165 switch (zhp->zfs_type) { 2166 case ZFS_TYPE_FILESYSTEM: 2167 str = "filesystem"; 2168 break; 2169 case ZFS_TYPE_VOLUME: 2170 str = "volume"; 2171 break; 2172 case ZFS_TYPE_SNAPSHOT: 2173 str = "snapshot"; 2174 break; 2175 default: 2176 abort(); 2177 } 2178 (void) snprintf(propbuf, proplen, "%s", str); 2179 break; 2180 2181 case ZFS_PROP_MOUNTED: 2182 /* 2183 * The 'mounted' property is a pseudo-property that described 2184 * whether the filesystem is currently mounted. Even though 2185 * it's a boolean value, the typical values of "on" and "off" 2186 * don't make sense, so we translate to "yes" and "no". 2187 */ 2188 if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, 2189 src, &source, &val) != 0) 2190 return (-1); 2191 if (val) 2192 (void) strlcpy(propbuf, "yes", proplen); 2193 else 2194 (void) strlcpy(propbuf, "no", proplen); 2195 break; 2196 2197 case ZFS_PROP_NAME: 2198 /* 2199 * The 'name' property is a pseudo-property derived from the 2200 * dataset name. It is presented as a real property to simplify 2201 * consumers. 2202 */ 2203 (void) strlcpy(propbuf, zhp->zfs_name, proplen); 2204 break; 2205 2206 default: 2207 switch (zfs_prop_get_type(prop)) { 2208 case PROP_TYPE_NUMBER: 2209 if (get_numeric_property(zhp, prop, src, 2210 &source, &val) != 0) 2211 return (-1); 2212 if (literal) 2213 (void) snprintf(propbuf, proplen, "%llu", 2214 (u_longlong_t)val); 2215 else 2216 zfs_nicenum(val, propbuf, proplen); 2217 break; 2218 2219 case PROP_TYPE_STRING: 2220 (void) strlcpy(propbuf, 2221 getprop_string(zhp, prop, &source), proplen); 2222 break; 2223 2224 case PROP_TYPE_INDEX: 2225 if (get_numeric_property(zhp, prop, src, 2226 &source, &val) != 0) 2227 return (-1); 2228 if (zfs_prop_index_to_string(prop, val, &strval) != 0) 2229 return (-1); 2230 (void) strlcpy(propbuf, strval, proplen); 2231 break; 2232 2233 default: 2234 abort(); 2235 } 2236 } 2237 2238 get_source(zhp, src, source, statbuf, statlen); 2239 2240 return (0); 2241 } 2242 2243 /* 2244 * Utility function to get the given numeric property. Does no validation that 2245 * the given property is the appropriate type; should only be used with 2246 * hard-coded property types. 2247 */ 2248 uint64_t 2249 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 2250 { 2251 char *source; 2252 uint64_t val; 2253 2254 (void) get_numeric_property(zhp, prop, NULL, &source, &val); 2255 2256 return (val); 2257 } 2258 2259 /* 2260 * Similar to zfs_prop_get(), but returns the value as an integer. 2261 */ 2262 int 2263 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 2264 zprop_source_t *src, char *statbuf, size_t statlen) 2265 { 2266 char *source; 2267 2268 /* 2269 * Check to see if this property applies to our object 2270 */ 2271 if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 2272 return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE, 2273 dgettext(TEXT_DOMAIN, "cannot get property '%s'"), 2274 zfs_prop_to_name(prop))); 2275 } 2276 2277 if (src) 2278 *src = ZPROP_SRC_NONE; 2279 2280 if (get_numeric_property(zhp, prop, src, &source, value) != 0) 2281 return (-1); 2282 2283 get_source(zhp, src, source, statbuf, statlen); 2284 2285 return (0); 2286 } 2287 2288 /* 2289 * Returns the name of the given zfs handle. 2290 */ 2291 const char * 2292 zfs_get_name(const zfs_handle_t *zhp) 2293 { 2294 return (zhp->zfs_name); 2295 } 2296 2297 /* 2298 * Returns the type of the given zfs handle. 2299 */ 2300 zfs_type_t 2301 zfs_get_type(const zfs_handle_t *zhp) 2302 { 2303 return (zhp->zfs_type); 2304 } 2305 2306 /* 2307 * Iterate over all child filesystems 2308 */ 2309 int 2310 zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2311 { 2312 zfs_cmd_t zc = { 0 }; 2313 zfs_handle_t *nzhp; 2314 int ret; 2315 2316 if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM) 2317 return (0); 2318 2319 for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2320 ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 2321 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 2322 /* 2323 * Ignore private dataset names. 2324 */ 2325 if (dataset_name_hidden(zc.zc_name)) 2326 continue; 2327 2328 /* 2329 * Silently ignore errors, as the only plausible explanation is 2330 * that the pool has since been removed. 2331 */ 2332 if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 2333 zc.zc_name)) == NULL) 2334 continue; 2335 2336 if ((ret = func(nzhp, data)) != 0) 2337 return (ret); 2338 } 2339 2340 /* 2341 * An errno value of ESRCH indicates normal completion. If ENOENT is 2342 * returned, then the underlying dataset has been removed since we 2343 * obtained the handle. 2344 */ 2345 if (errno != ESRCH && errno != ENOENT) 2346 return (zfs_standard_error(zhp->zfs_hdl, errno, 2347 dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 2348 2349 return (0); 2350 } 2351 2352 /* 2353 * Iterate over all snapshots 2354 */ 2355 int 2356 zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2357 { 2358 zfs_cmd_t zc = { 0 }; 2359 zfs_handle_t *nzhp; 2360 int ret; 2361 2362 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) 2363 return (0); 2364 2365 for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2366 ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, 2367 &zc) == 0; 2368 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) { 2369 2370 if ((nzhp = make_dataset_handle(zhp->zfs_hdl, 2371 zc.zc_name)) == NULL) 2372 continue; 2373 2374 if ((ret = func(nzhp, data)) != 0) 2375 return (ret); 2376 } 2377 2378 /* 2379 * An errno value of ESRCH indicates normal completion. If ENOENT is 2380 * returned, then the underlying dataset has been removed since we 2381 * obtained the handle. Silently ignore this case, and return success. 2382 */ 2383 if (errno != ESRCH && errno != ENOENT) 2384 return (zfs_standard_error(zhp->zfs_hdl, errno, 2385 dgettext(TEXT_DOMAIN, "cannot iterate filesystems"))); 2386 2387 return (0); 2388 } 2389 2390 /* 2391 * Iterate over all children, snapshots and filesystems 2392 */ 2393 int 2394 zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2395 { 2396 int ret; 2397 2398 if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 2399 return (ret); 2400 2401 return (zfs_iter_snapshots(zhp, func, data)); 2402 } 2403 2404 /* 2405 * Given a complete name, return just the portion that refers to the parent. 2406 * Can return NULL if this is a pool. 2407 */ 2408 static int 2409 parent_name(const char *path, char *buf, size_t buflen) 2410 { 2411 char *loc; 2412 2413 if ((loc = strrchr(path, '/')) == NULL) 2414 return (-1); 2415 2416 (void) strncpy(buf, path, MIN(buflen, loc - path)); 2417 buf[loc - path] = '\0'; 2418 2419 return (0); 2420 } 2421 2422 /* 2423 * If accept_ancestor is false, then check to make sure that the given path has 2424 * a parent, and that it exists. If accept_ancestor is true, then find the 2425 * closest existing ancestor for the given path. In prefixlen return the 2426 * length of already existing prefix of the given path. We also fetch the 2427 * 'zoned' property, which is used to validate property settings when creating 2428 * new datasets. 2429 */ 2430 static int 2431 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned, 2432 boolean_t accept_ancestor, int *prefixlen) 2433 { 2434 zfs_cmd_t zc = { 0 }; 2435 char parent[ZFS_MAXNAMELEN]; 2436 char *slash; 2437 zfs_handle_t *zhp; 2438 char errbuf[1024]; 2439 2440 (void) snprintf(errbuf, sizeof (errbuf), "cannot create '%s'", 2441 path); 2442 2443 /* get parent, and check to see if this is just a pool */ 2444 if (parent_name(path, parent, sizeof (parent)) != 0) { 2445 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2446 "missing dataset name")); 2447 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2448 } 2449 2450 /* check to see if the pool exists */ 2451 if ((slash = strchr(parent, '/')) == NULL) 2452 slash = parent + strlen(parent); 2453 (void) strncpy(zc.zc_name, parent, slash - parent); 2454 zc.zc_name[slash - parent] = '\0'; 2455 if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 2456 errno == ENOENT) { 2457 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2458 "no such pool '%s'"), zc.zc_name); 2459 return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2460 } 2461 2462 /* check to see if the parent dataset exists */ 2463 while ((zhp = make_dataset_handle(hdl, parent)) == NULL) { 2464 if (errno == ENOENT && accept_ancestor) { 2465 /* 2466 * Go deeper to find an ancestor, give up on top level. 2467 */ 2468 if (parent_name(parent, parent, sizeof (parent)) != 0) { 2469 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2470 "no such pool '%s'"), zc.zc_name); 2471 return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2472 } 2473 } else if (errno == ENOENT) { 2474 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2475 "parent does not exist")); 2476 return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2477 } else 2478 return (zfs_standard_error(hdl, errno, errbuf)); 2479 } 2480 2481 *zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 2482 /* we are in a non-global zone, but parent is in the global zone */ 2483 if (getzoneid() != GLOBAL_ZONEID && !(*zoned)) { 2484 (void) zfs_standard_error(hdl, EPERM, errbuf); 2485 zfs_close(zhp); 2486 return (-1); 2487 } 2488 2489 /* make sure parent is a filesystem */ 2490 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 2491 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2492 "parent is not a filesystem")); 2493 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 2494 zfs_close(zhp); 2495 return (-1); 2496 } 2497 2498 zfs_close(zhp); 2499 if (prefixlen != NULL) 2500 *prefixlen = strlen(parent); 2501 return (0); 2502 } 2503 2504 /* 2505 * Finds whether the dataset of the given type(s) exists. 2506 */ 2507 boolean_t 2508 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types) 2509 { 2510 zfs_handle_t *zhp; 2511 2512 if (!zfs_validate_name(hdl, path, types, B_FALSE)) 2513 return (B_FALSE); 2514 2515 /* 2516 * Try to get stats for the dataset, which will tell us if it exists. 2517 */ 2518 if ((zhp = make_dataset_handle(hdl, path)) != NULL) { 2519 int ds_type = zhp->zfs_type; 2520 2521 zfs_close(zhp); 2522 if (types & ds_type) 2523 return (B_TRUE); 2524 } 2525 return (B_FALSE); 2526 } 2527 2528 /* 2529 * Given a path to 'target', create all the ancestors between 2530 * the prefixlen portion of the path, and the target itself. 2531 * Fail if the initial prefixlen-ancestor does not already exist. 2532 */ 2533 int 2534 create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) 2535 { 2536 zfs_handle_t *h; 2537 char *cp; 2538 const char *opname; 2539 2540 /* make sure prefix exists */ 2541 cp = target + prefixlen; 2542 if (*cp != '/') { 2543 assert(strchr(cp, '/') == NULL); 2544 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 2545 } else { 2546 *cp = '\0'; 2547 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 2548 *cp = '/'; 2549 } 2550 if (h == NULL) 2551 return (-1); 2552 zfs_close(h); 2553 2554 /* 2555 * Attempt to create, mount, and share any ancestor filesystems, 2556 * up to the prefixlen-long one. 2557 */ 2558 for (cp = target + prefixlen + 1; 2559 cp = strchr(cp, '/'); *cp = '/', cp++) { 2560 char *logstr; 2561 2562 *cp = '\0'; 2563 2564 h = make_dataset_handle(hdl, target); 2565 if (h) { 2566 /* it already exists, nothing to do here */ 2567 zfs_close(h); 2568 continue; 2569 } 2570 2571 logstr = hdl->libzfs_log_str; 2572 hdl->libzfs_log_str = NULL; 2573 if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, 2574 NULL) != 0) { 2575 hdl->libzfs_log_str = logstr; 2576 opname = dgettext(TEXT_DOMAIN, "create"); 2577 goto ancestorerr; 2578 } 2579 2580 hdl->libzfs_log_str = logstr; 2581 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 2582 if (h == NULL) { 2583 opname = dgettext(TEXT_DOMAIN, "open"); 2584 goto ancestorerr; 2585 } 2586 2587 if (zfs_mount(h, NULL, 0) != 0) { 2588 opname = dgettext(TEXT_DOMAIN, "mount"); 2589 goto ancestorerr; 2590 } 2591 2592 if (zfs_share(h) != 0) { 2593 opname = dgettext(TEXT_DOMAIN, "share"); 2594 goto ancestorerr; 2595 } 2596 2597 zfs_close(h); 2598 } 2599 2600 return (0); 2601 2602 ancestorerr: 2603 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2604 "failed to %s ancestor '%s'"), opname, target); 2605 return (-1); 2606 } 2607 2608 /* 2609 * Creates non-existing ancestors of the given path. 2610 */ 2611 int 2612 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path) 2613 { 2614 int prefix; 2615 uint64_t zoned; 2616 char *path_copy; 2617 int rc; 2618 2619 if (check_parents(hdl, path, &zoned, B_TRUE, &prefix) != 0) 2620 return (-1); 2621 2622 if ((path_copy = strdup(path)) != NULL) { 2623 rc = create_parents(hdl, path_copy, prefix); 2624 free(path_copy); 2625 } 2626 if (path_copy == NULL || rc != 0) 2627 return (-1); 2628 2629 return (0); 2630 } 2631 2632 /* 2633 * Create a new filesystem or volume. 2634 */ 2635 int 2636 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, 2637 nvlist_t *props) 2638 { 2639 zfs_cmd_t zc = { 0 }; 2640 int ret; 2641 uint64_t size = 0; 2642 uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 2643 char errbuf[1024]; 2644 uint64_t zoned; 2645 2646 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2647 "cannot create '%s'"), path); 2648 2649 /* validate the path, taking care to note the extended error message */ 2650 if (!zfs_validate_name(hdl, path, type, B_TRUE)) 2651 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2652 2653 /* validate parents exist */ 2654 if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0) 2655 return (-1); 2656 2657 /* 2658 * The failure modes when creating a dataset of a different type over 2659 * one that already exists is a little strange. In particular, if you 2660 * try to create a dataset on top of an existing dataset, the ioctl() 2661 * will return ENOENT, not EEXIST. To prevent this from happening, we 2662 * first try to see if the dataset exists. 2663 */ 2664 (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 2665 if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) { 2666 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2667 "dataset already exists")); 2668 return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2669 } 2670 2671 if (type == ZFS_TYPE_VOLUME) 2672 zc.zc_objset_type = DMU_OST_ZVOL; 2673 else 2674 zc.zc_objset_type = DMU_OST_ZFS; 2675 2676 if (props && (props = zfs_validate_properties(hdl, type, props, 2677 zoned, NULL, errbuf)) == 0) 2678 return (-1); 2679 2680 if (type == ZFS_TYPE_VOLUME) { 2681 /* 2682 * If we are creating a volume, the size and block size must 2683 * satisfy a few restraints. First, the blocksize must be a 2684 * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 2685 * volsize must be a multiple of the block size, and cannot be 2686 * zero. 2687 */ 2688 if (props == NULL || nvlist_lookup_uint64(props, 2689 zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) { 2690 nvlist_free(props); 2691 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2692 "missing volume size")); 2693 return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2694 } 2695 2696 if ((ret = nvlist_lookup_uint64(props, 2697 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 2698 &blocksize)) != 0) { 2699 if (ret == ENOENT) { 2700 blocksize = zfs_prop_default_numeric( 2701 ZFS_PROP_VOLBLOCKSIZE); 2702 } else { 2703 nvlist_free(props); 2704 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2705 "missing volume block size")); 2706 return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2707 } 2708 } 2709 2710 if (size == 0) { 2711 nvlist_free(props); 2712 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2713 "volume size cannot be zero")); 2714 return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2715 } 2716 2717 if (size % blocksize != 0) { 2718 nvlist_free(props); 2719 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2720 "volume size must be a multiple of volume block " 2721 "size")); 2722 return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2723 } 2724 } 2725 2726 if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0) 2727 return (-1); 2728 nvlist_free(props); 2729 2730 /* create the dataset */ 2731 ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc); 2732 2733 if (ret == 0 && type == ZFS_TYPE_VOLUME) { 2734 ret = zvol_create_link(hdl, path); 2735 if (ret) { 2736 (void) zfs_standard_error(hdl, errno, 2737 dgettext(TEXT_DOMAIN, 2738 "Volume successfully created, but device links " 2739 "were not created")); 2740 zcmd_free_nvlists(&zc); 2741 return (-1); 2742 } 2743 } 2744 2745 zcmd_free_nvlists(&zc); 2746 2747 /* check for failure */ 2748 if (ret != 0) { 2749 char parent[ZFS_MAXNAMELEN]; 2750 (void) parent_name(path, parent, sizeof (parent)); 2751 2752 switch (errno) { 2753 case ENOENT: 2754 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2755 "no such parent '%s'"), parent); 2756 return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2757 2758 case EINVAL: 2759 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2760 "parent '%s' is not a filesystem"), parent); 2761 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 2762 2763 case EDOM: 2764 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2765 "volume block size must be power of 2 from " 2766 "%u to %uk"), 2767 (uint_t)SPA_MINBLOCKSIZE, 2768 (uint_t)SPA_MAXBLOCKSIZE >> 10); 2769 2770 return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2771 2772 case ENOTSUP: 2773 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2774 "pool must be upgraded to set this " 2775 "property or value")); 2776 return (zfs_error(hdl, EZFS_BADVERSION, errbuf)); 2777 2778 #ifdef _ILP32 2779 case EOVERFLOW: 2780 /* 2781 * This platform can't address a volume this big. 2782 */ 2783 if (type == ZFS_TYPE_VOLUME) 2784 return (zfs_error(hdl, EZFS_VOLTOOBIG, 2785 errbuf)); 2786 #endif 2787 /* FALLTHROUGH */ 2788 default: 2789 return (zfs_standard_error(hdl, errno, errbuf)); 2790 } 2791 } 2792 2793 return (0); 2794 } 2795 2796 /* 2797 * Destroys the given dataset. The caller must make sure that the filesystem 2798 * isn't mounted, and that there are no active dependents. 2799 */ 2800 int 2801 zfs_destroy(zfs_handle_t *zhp) 2802 { 2803 zfs_cmd_t zc = { 0 }; 2804 2805 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2806 2807 if (ZFS_IS_VOLUME(zhp)) { 2808 /* 2809 * If user doesn't have permissions to unshare volume, then 2810 * abort the request. This would only happen for a 2811 * non-privileged user. 2812 */ 2813 if (zfs_unshare_iscsi(zhp) != 0) { 2814 return (-1); 2815 } 2816 2817 if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 2818 return (-1); 2819 2820 zc.zc_objset_type = DMU_OST_ZVOL; 2821 } else { 2822 zc.zc_objset_type = DMU_OST_ZFS; 2823 } 2824 2825 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) { 2826 return (zfs_standard_error_fmt(zhp->zfs_hdl, errno, 2827 dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), 2828 zhp->zfs_name)); 2829 } 2830 2831 remove_mountpoint(zhp); 2832 2833 return (0); 2834 } 2835 2836 struct destroydata { 2837 char *snapname; 2838 boolean_t gotone; 2839 boolean_t closezhp; 2840 }; 2841 2842 static int 2843 zfs_remove_link_cb(zfs_handle_t *zhp, void *arg) 2844 { 2845 struct destroydata *dd = arg; 2846 zfs_handle_t *szhp; 2847 char name[ZFS_MAXNAMELEN]; 2848 boolean_t closezhp = dd->closezhp; 2849 int rv; 2850 2851 (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 2852 (void) strlcat(name, "@", sizeof (name)); 2853 (void) strlcat(name, dd->snapname, sizeof (name)); 2854 2855 szhp = make_dataset_handle(zhp->zfs_hdl, name); 2856 if (szhp) { 2857 dd->gotone = B_TRUE; 2858 zfs_close(szhp); 2859 } 2860 2861 if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 2862 (void) zvol_remove_link(zhp->zfs_hdl, name); 2863 /* 2864 * NB: this is simply a best-effort. We don't want to 2865 * return an error, because then we wouldn't visit all 2866 * the volumes. 2867 */ 2868 } 2869 2870 dd->closezhp = B_TRUE; 2871 rv = zfs_iter_filesystems(zhp, zfs_remove_link_cb, arg); 2872 if (closezhp) 2873 zfs_close(zhp); 2874 return (rv); 2875 } 2876 2877 /* 2878 * Destroys all snapshots with the given name in zhp & descendants. 2879 */ 2880 int 2881 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname) 2882 { 2883 zfs_cmd_t zc = { 0 }; 2884 int ret; 2885 struct destroydata dd = { 0 }; 2886 2887 dd.snapname = snapname; 2888 (void) zfs_remove_link_cb(zhp, &dd); 2889 2890 if (!dd.gotone) { 2891 return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, 2892 dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), 2893 zhp->zfs_name, snapname)); 2894 } 2895 2896 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2897 (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); 2898 2899 ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS, &zc); 2900 if (ret != 0) { 2901 char errbuf[1024]; 2902 2903 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2904 "cannot destroy '%s@%s'"), zc.zc_name, snapname); 2905 2906 switch (errno) { 2907 case EEXIST: 2908 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 2909 "snapshot is cloned")); 2910 return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf)); 2911 2912 default: 2913 return (zfs_standard_error(zhp->zfs_hdl, errno, 2914 errbuf)); 2915 } 2916 } 2917 2918 return (0); 2919 } 2920 2921 /* 2922 * Clones the given dataset. The target must be of the same type as the source. 2923 */ 2924 int 2925 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) 2926 { 2927 zfs_cmd_t zc = { 0 }; 2928 char parent[ZFS_MAXNAMELEN]; 2929 int ret; 2930 char errbuf[1024]; 2931 libzfs_handle_t *hdl = zhp->zfs_hdl; 2932 zfs_type_t type; 2933 uint64_t zoned; 2934 2935 assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 2936 2937 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2938 "cannot create '%s'"), target); 2939 2940 /* validate the target name */ 2941 if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE)) 2942 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2943 2944 /* validate parents exist */ 2945 if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0) 2946 return (-1); 2947 2948 (void) parent_name(target, parent, sizeof (parent)); 2949 2950 /* do the clone */ 2951 if (ZFS_IS_VOLUME(zhp)) { 2952 zc.zc_objset_type = DMU_OST_ZVOL; 2953 type = ZFS_TYPE_VOLUME; 2954 } else { 2955 zc.zc_objset_type = DMU_OST_ZFS; 2956 type = ZFS_TYPE_FILESYSTEM; 2957 } 2958 2959 if (props) { 2960 if ((props = zfs_validate_properties(hdl, type, props, 2961 zoned, zhp, errbuf)) == NULL) 2962 return (-1); 2963 2964 if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) { 2965 nvlist_free(props); 2966 return (-1); 2967 } 2968 2969 nvlist_free(props); 2970 } 2971 2972 (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); 2973 (void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value)); 2974 ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_CREATE, &zc); 2975 2976 zcmd_free_nvlists(&zc); 2977 2978 if (ret != 0) { 2979 switch (errno) { 2980 2981 case ENOENT: 2982 /* 2983 * The parent doesn't exist. We should have caught this 2984 * above, but there may a race condition that has since 2985 * destroyed the parent. 2986 * 2987 * At this point, we don't know whether it's the source 2988 * that doesn't exist anymore, or whether the target 2989 * dataset doesn't exist. 2990 */ 2991 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 2992 "no such parent '%s'"), parent); 2993 return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); 2994 2995 case EXDEV: 2996 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 2997 "source and target pools differ")); 2998 return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET, 2999 errbuf)); 3000 3001 default: 3002 return (zfs_standard_error(zhp->zfs_hdl, errno, 3003 errbuf)); 3004 } 3005 } else if (ZFS_IS_VOLUME(zhp)) { 3006 ret = zvol_create_link(zhp->zfs_hdl, target); 3007 } 3008 3009 return (ret); 3010 } 3011 3012 typedef struct promote_data { 3013 char cb_mountpoint[MAXPATHLEN]; 3014 const char *cb_target; 3015 const char *cb_errbuf; 3016 uint64_t cb_pivot_txg; 3017 } promote_data_t; 3018 3019 static int 3020 promote_snap_cb(zfs_handle_t *zhp, void *data) 3021 { 3022 promote_data_t *pd = data; 3023 zfs_handle_t *szhp; 3024 char snapname[MAXPATHLEN]; 3025 int rv = 0; 3026 3027 /* We don't care about snapshots after the pivot point */ 3028 if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg) { 3029 zfs_close(zhp); 3030 return (0); 3031 } 3032 3033 /* Remove the device link if it's a zvol. */ 3034 if (ZFS_IS_VOLUME(zhp)) 3035 (void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); 3036 3037 /* Check for conflicting names */ 3038 (void) strlcpy(snapname, pd->cb_target, sizeof (snapname)); 3039 (void) strlcat(snapname, strchr(zhp->zfs_name, '@'), sizeof (snapname)); 3040 szhp = make_dataset_handle(zhp->zfs_hdl, snapname); 3041 if (szhp != NULL) { 3042 zfs_close(szhp); 3043 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 3044 "snapshot name '%s' from origin \n" 3045 "conflicts with '%s' from target"), 3046 zhp->zfs_name, snapname); 3047 rv = zfs_error(zhp->zfs_hdl, EZFS_EXISTS, pd->cb_errbuf); 3048 } 3049 zfs_close(zhp); 3050 return (rv); 3051 } 3052 3053 static int 3054 promote_snap_done_cb(zfs_handle_t *zhp, void *data) 3055 { 3056 promote_data_t *pd = data; 3057 3058 /* We don't care about snapshots after the pivot point */ 3059 if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) <= pd->cb_pivot_txg) { 3060 /* Create the device link if it's a zvol. */ 3061 if (ZFS_IS_VOLUME(zhp)) 3062 (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 3063 } 3064 3065 zfs_close(zhp); 3066 return (0); 3067 } 3068 3069 /* 3070 * Promotes the given clone fs to be the clone parent. 3071 */ 3072 int 3073 zfs_promote(zfs_handle_t *zhp) 3074 { 3075 libzfs_handle_t *hdl = zhp->zfs_hdl; 3076 zfs_cmd_t zc = { 0 }; 3077 char parent[MAXPATHLEN]; 3078 char *cp; 3079 int ret; 3080 zfs_handle_t *pzhp; 3081 promote_data_t pd; 3082 char errbuf[1024]; 3083 3084 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 3085 "cannot promote '%s'"), zhp->zfs_name); 3086 3087 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 3088 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3089 "snapshots can not be promoted")); 3090 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 3091 } 3092 3093 (void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent)); 3094 if (parent[0] == '\0') { 3095 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3096 "not a cloned filesystem")); 3097 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 3098 } 3099 cp = strchr(parent, '@'); 3100 *cp = '\0'; 3101 3102 /* Walk the snapshots we will be moving */ 3103 pzhp = zfs_open(hdl, zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT); 3104 if (pzhp == NULL) 3105 return (-1); 3106 pd.cb_pivot_txg = zfs_prop_get_int(pzhp, ZFS_PROP_CREATETXG); 3107 zfs_close(pzhp); 3108 pd.cb_target = zhp->zfs_name; 3109 pd.cb_errbuf = errbuf; 3110 pzhp = zfs_open(hdl, parent, ZFS_TYPE_DATASET); 3111 if (pzhp == NULL) 3112 return (-1); 3113 (void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint, 3114 sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE); 3115 ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd); 3116 if (ret != 0) { 3117 zfs_close(pzhp); 3118 return (-1); 3119 } 3120 3121 /* issue the ioctl */ 3122 (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin, 3123 sizeof (zc.zc_value)); 3124 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3125 ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc); 3126 3127 if (ret != 0) { 3128 int save_errno = errno; 3129 3130 (void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd); 3131 zfs_close(pzhp); 3132 3133 switch (save_errno) { 3134 case EEXIST: 3135 /* 3136 * There is a conflicting snapshot name. We 3137 * should have caught this above, but they could 3138 * have renamed something in the mean time. 3139 */ 3140 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3141 "conflicting snapshot name from parent '%s'"), 3142 parent); 3143 return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 3144 3145 default: 3146 return (zfs_standard_error(hdl, save_errno, errbuf)); 3147 } 3148 } else { 3149 (void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd); 3150 } 3151 3152 zfs_close(pzhp); 3153 return (ret); 3154 } 3155 3156 struct createdata { 3157 const char *cd_snapname; 3158 int cd_ifexists; 3159 }; 3160 3161 static int 3162 zfs_create_link_cb(zfs_handle_t *zhp, void *arg) 3163 { 3164 struct createdata *cd = arg; 3165 int ret; 3166 3167 if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 3168 char name[MAXPATHLEN]; 3169 3170 (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 3171 (void) strlcat(name, "@", sizeof (name)); 3172 (void) strlcat(name, cd->cd_snapname, sizeof (name)); 3173 (void) zvol_create_link_common(zhp->zfs_hdl, name, 3174 cd->cd_ifexists); 3175 /* 3176 * NB: this is simply a best-effort. We don't want to 3177 * return an error, because then we wouldn't visit all 3178 * the volumes. 3179 */ 3180 } 3181 3182 ret = zfs_iter_filesystems(zhp, zfs_create_link_cb, cd); 3183 3184 zfs_close(zhp); 3185 3186 return (ret); 3187 } 3188 3189 /* 3190 * Takes a snapshot of the given dataset. 3191 */ 3192 int 3193 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive) 3194 { 3195 const char *delim; 3196 char *parent; 3197 zfs_handle_t *zhp; 3198 zfs_cmd_t zc = { 0 }; 3199 int ret; 3200 char errbuf[1024]; 3201 3202 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 3203 "cannot snapshot '%s'"), path); 3204 3205 /* validate the target name */ 3206 if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE)) 3207 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3208 3209 /* make sure the parent exists and is of the appropriate type */ 3210 delim = strchr(path, '@'); 3211 if ((parent = zfs_alloc(hdl, delim - path + 1)) == NULL) 3212 return (-1); 3213 (void) strncpy(parent, path, delim - path); 3214 parent[delim - path] = '\0'; 3215 3216 if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM | 3217 ZFS_TYPE_VOLUME)) == NULL) { 3218 free(parent); 3219 return (-1); 3220 } 3221 3222 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3223 (void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value)); 3224 if (ZFS_IS_VOLUME(zhp)) 3225 zc.zc_objset_type = DMU_OST_ZVOL; 3226 else 3227 zc.zc_objset_type = DMU_OST_ZFS; 3228 zc.zc_cookie = recursive; 3229 ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SNAPSHOT, &zc); 3230 3231 /* 3232 * if it was recursive, the one that actually failed will be in 3233 * zc.zc_name. 3234 */ 3235 if (ret != 0) 3236 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 3237 "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value); 3238 3239 if (ret == 0 && recursive) { 3240 struct createdata cd; 3241 3242 cd.cd_snapname = delim + 1; 3243 cd.cd_ifexists = B_FALSE; 3244 (void) zfs_iter_filesystems(zhp, zfs_create_link_cb, &cd); 3245 } 3246 if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) { 3247 ret = zvol_create_link(zhp->zfs_hdl, path); 3248 if (ret != 0) { 3249 (void) zfs_standard_error(hdl, errno, 3250 dgettext(TEXT_DOMAIN, 3251 "Volume successfully snapshotted, but device links " 3252 "were not created")); 3253 free(parent); 3254 zfs_close(zhp); 3255 return (-1); 3256 } 3257 } 3258 3259 if (ret != 0) 3260 (void) zfs_standard_error(hdl, errno, errbuf); 3261 3262 free(parent); 3263 zfs_close(zhp); 3264 3265 return (ret); 3266 } 3267 3268 /* 3269 * Destroy any more recent snapshots. We invoke this callback on any dependents 3270 * of the snapshot first. If the 'cb_dependent' member is non-zero, then this 3271 * is a dependent and we should just destroy it without checking the transaction 3272 * group. 3273 */ 3274 typedef struct rollback_data { 3275 const char *cb_target; /* the snapshot */ 3276 uint64_t cb_create; /* creation time reference */ 3277 prop_changelist_t *cb_clp; /* changelist pointer */ 3278 int cb_error; 3279 boolean_t cb_dependent; 3280 } rollback_data_t; 3281 3282 static int 3283 rollback_destroy(zfs_handle_t *zhp, void *data) 3284 { 3285 rollback_data_t *cbp = data; 3286 3287 if (!cbp->cb_dependent) { 3288 if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 && 3289 zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 3290 zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 3291 cbp->cb_create) { 3292 char *logstr; 3293 3294 cbp->cb_dependent = B_TRUE; 3295 if (zfs_iter_dependents(zhp, B_FALSE, rollback_destroy, 3296 cbp) != 0) 3297 cbp->cb_error = 1; 3298 cbp->cb_dependent = B_FALSE; 3299 3300 logstr = zhp->zfs_hdl->libzfs_log_str; 3301 zhp->zfs_hdl->libzfs_log_str = NULL; 3302 if (zfs_destroy(zhp) != 0) 3303 cbp->cb_error = 1; 3304 else 3305 changelist_remove(cbp->cb_clp, zhp->zfs_name); 3306 zhp->zfs_hdl->libzfs_log_str = logstr; 3307 } 3308 } else { 3309 if (zfs_destroy(zhp) != 0) 3310 cbp->cb_error = 1; 3311 else 3312 changelist_remove(cbp->cb_clp, zhp->zfs_name); 3313 } 3314 3315 zfs_close(zhp); 3316 return (0); 3317 } 3318 3319 /* 3320 * Rollback the dataset to its latest snapshot. 3321 */ 3322 static int 3323 do_rollback(zfs_handle_t *zhp) 3324 { 3325 int ret; 3326 zfs_cmd_t zc = { 0 }; 3327 3328 assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM || 3329 zhp->zfs_type == ZFS_TYPE_VOLUME); 3330 3331 if (zhp->zfs_type == ZFS_TYPE_VOLUME && 3332 zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) 3333 return (-1); 3334 3335 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3336 3337 if (ZFS_IS_VOLUME(zhp)) 3338 zc.zc_objset_type = DMU_OST_ZVOL; 3339 else 3340 zc.zc_objset_type = DMU_OST_ZFS; 3341 3342 /* 3343 * We rely on the consumer to verify that there are no newer snapshots 3344 * for the given dataset. Given these constraints, we can simply pass 3345 * the name on to the ioctl() call. There is still an unlikely race 3346 * condition where the user has taken a snapshot since we verified that 3347 * this was the most recent. 3348 */ 3349 if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) { 3350 (void) zfs_standard_error_fmt(zhp->zfs_hdl, errno, 3351 dgettext(TEXT_DOMAIN, "cannot rollback '%s'"), 3352 zhp->zfs_name); 3353 } else if (zhp->zfs_type == ZFS_TYPE_VOLUME) { 3354 ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); 3355 } 3356 3357 return (ret); 3358 } 3359 3360 /* 3361 * Given a dataset, rollback to a specific snapshot, discarding any 3362 * data changes since then and making it the active dataset. 3363 * 3364 * Any snapshots more recent than the target are destroyed, along with 3365 * their dependents. 3366 */ 3367 int 3368 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag) 3369 { 3370 int ret; 3371 rollback_data_t cb = { 0 }; 3372 prop_changelist_t *clp; 3373 3374 /* 3375 * Unmount all dependendents of the dataset and the dataset itself. 3376 * The list we need to gather is the same as for doing rename 3377 */ 3378 clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0); 3379 if (clp == NULL) 3380 return (-1); 3381 3382 if ((ret = changelist_prefix(clp)) != 0) 3383 goto out; 3384 3385 /* 3386 * Destroy all recent snapshots and its dependends. 3387 */ 3388 cb.cb_target = snap->zfs_name; 3389 cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 3390 cb.cb_clp = clp; 3391 (void) zfs_iter_children(zhp, rollback_destroy, &cb); 3392 3393 if ((ret = cb.cb_error) != 0) { 3394 (void) changelist_postfix(clp); 3395 goto out; 3396 } 3397 3398 /* 3399 * Now that we have verified that the snapshot is the latest, 3400 * rollback to the given snapshot. 3401 */ 3402 ret = do_rollback(zhp); 3403 3404 if (ret != 0) { 3405 (void) changelist_postfix(clp); 3406 goto out; 3407 } 3408 3409 /* 3410 * We only want to re-mount the filesystem if it was mounted in the 3411 * first place. 3412 */ 3413 ret = changelist_postfix(clp); 3414 3415 out: 3416 changelist_free(clp); 3417 return (ret); 3418 } 3419 3420 /* 3421 * Iterate over all dependents for a given dataset. This includes both 3422 * hierarchical dependents (children) and data dependents (snapshots and 3423 * clones). The bulk of the processing occurs in get_dependents() in 3424 * libzfs_graph.c. 3425 */ 3426 int 3427 zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion, 3428 zfs_iter_f func, void *data) 3429 { 3430 char **dependents; 3431 size_t count; 3432 int i; 3433 zfs_handle_t *child; 3434 int ret = 0; 3435 3436 if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name, 3437 &dependents, &count) != 0) 3438 return (-1); 3439 3440 for (i = 0; i < count; i++) { 3441 if ((child = make_dataset_handle(zhp->zfs_hdl, 3442 dependents[i])) == NULL) 3443 continue; 3444 3445 if ((ret = func(child, data)) != 0) 3446 break; 3447 } 3448 3449 for (i = 0; i < count; i++) 3450 free(dependents[i]); 3451 free(dependents); 3452 3453 return (ret); 3454 } 3455 3456 /* 3457 * Renames the given dataset. 3458 */ 3459 int 3460 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive) 3461 { 3462 int ret; 3463 zfs_cmd_t zc = { 0 }; 3464 char *delim; 3465 prop_changelist_t *cl = NULL; 3466 zfs_handle_t *zhrp = NULL; 3467 char *parentname = NULL; 3468 char parent[ZFS_MAXNAMELEN]; 3469 libzfs_handle_t *hdl = zhp->zfs_hdl; 3470 char errbuf[1024]; 3471 3472 /* if we have the same exact name, just return success */ 3473 if (strcmp(zhp->zfs_name, target) == 0) 3474 return (0); 3475 3476 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 3477 "cannot rename to '%s'"), target); 3478 3479 /* 3480 * Make sure the target name is valid 3481 */ 3482 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) { 3483 if ((strchr(target, '@') == NULL) || 3484 *target == '@') { 3485 /* 3486 * Snapshot target name is abbreviated, 3487 * reconstruct full dataset name 3488 */ 3489 (void) strlcpy(parent, zhp->zfs_name, 3490 sizeof (parent)); 3491 delim = strchr(parent, '@'); 3492 if (strchr(target, '@') == NULL) 3493 *(++delim) = '\0'; 3494 else 3495 *delim = '\0'; 3496 (void) strlcat(parent, target, sizeof (parent)); 3497 target = parent; 3498 } else { 3499 /* 3500 * Make sure we're renaming within the same dataset. 3501 */ 3502 delim = strchr(target, '@'); 3503 if (strncmp(zhp->zfs_name, target, delim - target) 3504 != 0 || zhp->zfs_name[delim - target] != '@') { 3505 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3506 "snapshots must be part of same " 3507 "dataset")); 3508 return (zfs_error(hdl, EZFS_CROSSTARGET, 3509 errbuf)); 3510 } 3511 } 3512 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE)) 3513 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3514 } else { 3515 if (recursive) { 3516 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3517 "recursive rename must be a snapshot")); 3518 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 3519 } 3520 3521 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE)) 3522 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3523 uint64_t unused; 3524 3525 /* validate parents */ 3526 if (check_parents(hdl, target, &unused, B_FALSE, NULL) != 0) 3527 return (-1); 3528 3529 (void) parent_name(target, parent, sizeof (parent)); 3530 3531 /* make sure we're in the same pool */ 3532 verify((delim = strchr(target, '/')) != NULL); 3533 if (strncmp(zhp->zfs_name, target, delim - target) != 0 || 3534 zhp->zfs_name[delim - target] != '/') { 3535 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3536 "datasets must be within same pool")); 3537 return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 3538 } 3539 3540 /* new name cannot be a child of the current dataset name */ 3541 if (strncmp(parent, zhp->zfs_name, 3542 strlen(zhp->zfs_name)) == 0) { 3543 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3544 "New dataset name cannot be a descendent of " 3545 "current dataset name")); 3546 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 3547 } 3548 } 3549 3550 (void) snprintf(errbuf, sizeof (errbuf), 3551 dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name); 3552 3553 if (getzoneid() == GLOBAL_ZONEID && 3554 zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 3555 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3556 "dataset is used in a non-global zone")); 3557 return (zfs_error(hdl, EZFS_ZONED, errbuf)); 3558 } 3559 3560 if (recursive) { 3561 struct destroydata dd; 3562 3563 parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name); 3564 if (parentname == NULL) { 3565 ret = -1; 3566 goto error; 3567 } 3568 delim = strchr(parentname, '@'); 3569 *delim = '\0'; 3570 zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET); 3571 if (zhrp == NULL) { 3572 ret = -1; 3573 goto error; 3574 } 3575 3576 dd.snapname = delim + 1; 3577 dd.gotone = B_FALSE; 3578 dd.closezhp = B_TRUE; 3579 3580 /* We remove any zvol links prior to renaming them */ 3581 ret = zfs_iter_filesystems(zhrp, zfs_remove_link_cb, &dd); 3582 if (ret) { 3583 goto error; 3584 } 3585 } else { 3586 if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL) 3587 return (-1); 3588 3589 if (changelist_haszonedchild(cl)) { 3590 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3591 "child dataset with inherited mountpoint is used " 3592 "in a non-global zone")); 3593 (void) zfs_error(hdl, EZFS_ZONED, errbuf); 3594 goto error; 3595 } 3596 3597 if ((ret = changelist_prefix(cl)) != 0) 3598 goto error; 3599 } 3600 3601 if (ZFS_IS_VOLUME(zhp)) 3602 zc.zc_objset_type = DMU_OST_ZVOL; 3603 else 3604 zc.zc_objset_type = DMU_OST_ZFS; 3605 3606 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 3607 (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value)); 3608 3609 zc.zc_cookie = recursive; 3610 3611 if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) { 3612 /* 3613 * if it was recursive, the one that actually failed will 3614 * be in zc.zc_name 3615 */ 3616 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 3617 "cannot rename '%s'"), zc.zc_name); 3618 3619 if (recursive && errno == EEXIST) { 3620 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3621 "a child dataset already has a snapshot " 3622 "with the new name")); 3623 (void) zfs_error(hdl, EZFS_EXISTS, errbuf); 3624 } else { 3625 (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf); 3626 } 3627 3628 /* 3629 * On failure, we still want to remount any filesystems that 3630 * were previously mounted, so we don't alter the system state. 3631 */ 3632 if (recursive) { 3633 struct createdata cd; 3634 3635 /* only create links for datasets that had existed */ 3636 cd.cd_snapname = delim + 1; 3637 cd.cd_ifexists = B_TRUE; 3638 (void) zfs_iter_filesystems(zhrp, zfs_create_link_cb, 3639 &cd); 3640 } else { 3641 (void) changelist_postfix(cl); 3642 } 3643 } else { 3644 if (recursive) { 3645 struct createdata cd; 3646 3647 /* only create links for datasets that had existed */ 3648 cd.cd_snapname = strchr(target, '@') + 1; 3649 cd.cd_ifexists = B_TRUE; 3650 ret = zfs_iter_filesystems(zhrp, zfs_create_link_cb, 3651 &cd); 3652 } else { 3653 changelist_rename(cl, zfs_get_name(zhp), target); 3654 ret = changelist_postfix(cl); 3655 } 3656 } 3657 3658 error: 3659 if (parentname) { 3660 free(parentname); 3661 } 3662 if (zhrp) { 3663 zfs_close(zhrp); 3664 } 3665 if (cl) { 3666 changelist_free(cl); 3667 } 3668 return (ret); 3669 } 3670 3671 /* 3672 * Given a zvol dataset, issue the ioctl to create the appropriate minor node, 3673 * poke devfsadm to create the /dev link, and then wait for the link to appear. 3674 */ 3675 int 3676 zvol_create_link(libzfs_handle_t *hdl, const char *dataset) 3677 { 3678 return (zvol_create_link_common(hdl, dataset, B_FALSE)); 3679 } 3680 3681 static int 3682 zvol_create_link_common(libzfs_handle_t *hdl, const char *dataset, int ifexists) 3683 { 3684 zfs_cmd_t zc = { 0 }; 3685 di_devlink_handle_t dhdl; 3686 priv_set_t *priv_effective; 3687 int privileged; 3688 3689 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3690 3691 /* 3692 * Issue the appropriate ioctl. 3693 */ 3694 if (ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) { 3695 switch (errno) { 3696 case EEXIST: 3697 /* 3698 * Silently ignore the case where the link already 3699 * exists. This allows 'zfs volinit' to be run multiple 3700 * times without errors. 3701 */ 3702 return (0); 3703 3704 case ENOENT: 3705 /* 3706 * Dataset does not exist in the kernel. If we 3707 * don't care (see zfs_rename), then ignore the 3708 * error quietly. 3709 */ 3710 if (ifexists) { 3711 return (0); 3712 } 3713 3714 /* FALLTHROUGH */ 3715 3716 default: 3717 return (zfs_standard_error_fmt(hdl, errno, 3718 dgettext(TEXT_DOMAIN, "cannot create device links " 3719 "for '%s'"), dataset)); 3720 } 3721 } 3722 3723 /* 3724 * If privileged call devfsadm and wait for the links to 3725 * magically appear. 3726 * Otherwise, print out an informational message. 3727 */ 3728 3729 priv_effective = priv_allocset(); 3730 (void) getppriv(PRIV_EFFECTIVE, priv_effective); 3731 privileged = (priv_isfullset(priv_effective) == B_TRUE); 3732 priv_freeset(priv_effective); 3733 3734 if (privileged) { 3735 if ((dhdl = di_devlink_init(ZFS_DRIVER, 3736 DI_MAKE_LINK)) == NULL) { 3737 zfs_error_aux(hdl, strerror(errno)); 3738 (void) zfs_standard_error_fmt(hdl, EZFS_DEVLINKS, 3739 dgettext(TEXT_DOMAIN, "cannot create device links " 3740 "for '%s'"), dataset); 3741 (void) ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); 3742 return (-1); 3743 } else { 3744 (void) di_devlink_fini(&dhdl); 3745 } 3746 } else { 3747 char pathname[MAXPATHLEN]; 3748 struct stat64 statbuf; 3749 int i; 3750 3751 #define MAX_WAIT 10 3752 3753 /* 3754 * This is the poor mans way of waiting for the link 3755 * to show up. If after 10 seconds we still don't 3756 * have it, then print out a message. 3757 */ 3758 (void) snprintf(pathname, sizeof (pathname), "/dev/zvol/dsk/%s", 3759 dataset); 3760 3761 for (i = 0; i != MAX_WAIT; i++) { 3762 if (stat64(pathname, &statbuf) == 0) 3763 break; 3764 (void) sleep(1); 3765 } 3766 if (i == MAX_WAIT) 3767 (void) printf(gettext("%s may not be immediately " 3768 "available\n"), pathname); 3769 } 3770 3771 return (0); 3772 } 3773 3774 /* 3775 * Remove a minor node for the given zvol and the associated /dev links. 3776 */ 3777 int 3778 zvol_remove_link(libzfs_handle_t *hdl, const char *dataset) 3779 { 3780 zfs_cmd_t zc = { 0 }; 3781 3782 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3783 3784 if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { 3785 switch (errno) { 3786 case ENXIO: 3787 /* 3788 * Silently ignore the case where the link no longer 3789 * exists, so that 'zfs volfini' can be run multiple 3790 * times without errors. 3791 */ 3792 return (0); 3793 3794 default: 3795 return (zfs_standard_error_fmt(hdl, errno, 3796 dgettext(TEXT_DOMAIN, "cannot remove device " 3797 "links for '%s'"), dataset)); 3798 } 3799 } 3800 3801 return (0); 3802 } 3803 3804 nvlist_t * 3805 zfs_get_user_props(zfs_handle_t *zhp) 3806 { 3807 return (zhp->zfs_user_props); 3808 } 3809 3810 /* 3811 * This function is used by 'zfs list' to determine the exact set of columns to 3812 * display, and their maximum widths. This does two main things: 3813 * 3814 * - If this is a list of all properties, then expand the list to include 3815 * all native properties, and set a flag so that for each dataset we look 3816 * for new unique user properties and add them to the list. 3817 * 3818 * - For non fixed-width properties, keep track of the maximum width seen 3819 * so that we can size the column appropriately. 3820 */ 3821 int 3822 zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp) 3823 { 3824 libzfs_handle_t *hdl = zhp->zfs_hdl; 3825 zprop_list_t *entry; 3826 zprop_list_t **last, **start; 3827 nvlist_t *userprops, *propval; 3828 nvpair_t *elem; 3829 char *strval; 3830 char buf[ZFS_MAXPROPLEN]; 3831 3832 if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0) 3833 return (-1); 3834 3835 userprops = zfs_get_user_props(zhp); 3836 3837 entry = *plp; 3838 if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) { 3839 /* 3840 * Go through and add any user properties as necessary. We 3841 * start by incrementing our list pointer to the first 3842 * non-native property. 3843 */ 3844 start = plp; 3845 while (*start != NULL) { 3846 if ((*start)->pl_prop == ZPROP_INVAL) 3847 break; 3848 start = &(*start)->pl_next; 3849 } 3850 3851 elem = NULL; 3852 while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) { 3853 /* 3854 * See if we've already found this property in our list. 3855 */ 3856 for (last = start; *last != NULL; 3857 last = &(*last)->pl_next) { 3858 if (strcmp((*last)->pl_user_prop, 3859 nvpair_name(elem)) == 0) 3860 break; 3861 } 3862 3863 if (*last == NULL) { 3864 if ((entry = zfs_alloc(hdl, 3865 sizeof (zprop_list_t))) == NULL || 3866 ((entry->pl_user_prop = zfs_strdup(hdl, 3867 nvpair_name(elem)))) == NULL) { 3868 free(entry); 3869 return (-1); 3870 } 3871 3872 entry->pl_prop = ZPROP_INVAL; 3873 entry->pl_width = strlen(nvpair_name(elem)); 3874 entry->pl_all = B_TRUE; 3875 *last = entry; 3876 } 3877 } 3878 } 3879 3880 /* 3881 * Now go through and check the width of any non-fixed columns 3882 */ 3883 for (entry = *plp; entry != NULL; entry = entry->pl_next) { 3884 if (entry->pl_fixed) 3885 continue; 3886 3887 if (entry->pl_prop != ZPROP_INVAL) { 3888 if (zfs_prop_get(zhp, entry->pl_prop, 3889 buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) { 3890 if (strlen(buf) > entry->pl_width) 3891 entry->pl_width = strlen(buf); 3892 } 3893 } else if (nvlist_lookup_nvlist(userprops, 3894 entry->pl_user_prop, &propval) == 0) { 3895 verify(nvlist_lookup_string(propval, 3896 ZPROP_VALUE, &strval) == 0); 3897 if (strlen(strval) > entry->pl_width) 3898 entry->pl_width = strlen(strval); 3899 } 3900 } 3901 3902 return (0); 3903 } 3904 3905 int 3906 zfs_iscsi_perm_check(libzfs_handle_t *hdl, char *dataset, ucred_t *cred) 3907 { 3908 zfs_cmd_t zc = { 0 }; 3909 nvlist_t *nvp; 3910 gid_t gid; 3911 uid_t uid; 3912 const gid_t *groups; 3913 int group_cnt; 3914 int error; 3915 3916 if (nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0) != 0) 3917 return (no_memory(hdl)); 3918 3919 uid = ucred_geteuid(cred); 3920 gid = ucred_getegid(cred); 3921 group_cnt = ucred_getgroups(cred, &groups); 3922 3923 if (uid == (uid_t)-1 || gid == (uid_t)-1 || group_cnt == (uid_t)-1) 3924 return (1); 3925 3926 if (nvlist_add_uint32(nvp, ZFS_DELEG_PERM_UID, uid) != 0) { 3927 nvlist_free(nvp); 3928 return (1); 3929 } 3930 3931 if (nvlist_add_uint32(nvp, ZFS_DELEG_PERM_GID, gid) != 0) { 3932 nvlist_free(nvp); 3933 return (1); 3934 } 3935 3936 if (nvlist_add_uint32_array(nvp, 3937 ZFS_DELEG_PERM_GROUPS, (uint32_t *)groups, group_cnt) != 0) { 3938 nvlist_free(nvp); 3939 return (1); 3940 } 3941 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3942 3943 if (zcmd_write_src_nvlist(hdl, &zc, nvp)) 3944 return (-1); 3945 3946 error = ioctl(hdl->libzfs_fd, ZFS_IOC_ISCSI_PERM_CHECK, &zc); 3947 nvlist_free(nvp); 3948 return (error); 3949 } 3950 3951 int 3952 zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path, 3953 void *export, void *sharetab, int sharemax, zfs_share_op_t operation) 3954 { 3955 zfs_cmd_t zc = { 0 }; 3956 int error; 3957 3958 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 3959 (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value)); 3960 zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab; 3961 zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export; 3962 zc.zc_share.z_sharetype = operation; 3963 zc.zc_share.z_sharemax = sharemax; 3964 3965 error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc); 3966 return (error); 3967 } 3968