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