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