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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Internal utility routines for the ZFS library. 28 */ 29 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <libintl.h> 33 #include <stdarg.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <strings.h> 37 #include <unistd.h> 38 #include <ctype.h> 39 #include <math.h> 40 #include <sys/mnttab.h> 41 #include <sys/mntent.h> 42 #include <sys/types.h> 43 44 #include <libzfs.h> 45 46 #include "libzfs_impl.h" 47 #include "zfs_prop.h" 48 49 int 50 libzfs_errno(libzfs_handle_t *hdl) 51 { 52 return (hdl->libzfs_error); 53 } 54 55 const char * 56 libzfs_error_action(libzfs_handle_t *hdl) 57 { 58 return (hdl->libzfs_action); 59 } 60 61 const char * 62 libzfs_error_description(libzfs_handle_t *hdl) 63 { 64 if (hdl->libzfs_desc[0] != '\0') 65 return (hdl->libzfs_desc); 66 67 switch (hdl->libzfs_error) { 68 case EZFS_NOMEM: 69 return (dgettext(TEXT_DOMAIN, "out of memory")); 70 case EZFS_BADPROP: 71 return (dgettext(TEXT_DOMAIN, "invalid property value")); 72 case EZFS_PROPREADONLY: 73 return (dgettext(TEXT_DOMAIN, "read only property")); 74 case EZFS_PROPTYPE: 75 return (dgettext(TEXT_DOMAIN, "property doesn't apply to " 76 "datasets of this type")); 77 case EZFS_PROPNONINHERIT: 78 return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); 79 case EZFS_PROPSPACE: 80 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); 81 case EZFS_BADTYPE: 82 return (dgettext(TEXT_DOMAIN, "operation not applicable to " 83 "datasets of this type")); 84 case EZFS_BUSY: 85 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy")); 86 case EZFS_EXISTS: 87 return (dgettext(TEXT_DOMAIN, "pool or dataset exists")); 88 case EZFS_NOENT: 89 return (dgettext(TEXT_DOMAIN, "no such pool or dataset")); 90 case EZFS_BADSTREAM: 91 return (dgettext(TEXT_DOMAIN, "invalid backup stream")); 92 case EZFS_DSREADONLY: 93 return (dgettext(TEXT_DOMAIN, "dataset is read only")); 94 case EZFS_VOLTOOBIG: 95 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for " 96 "this system")); 97 case EZFS_INVALIDNAME: 98 return (dgettext(TEXT_DOMAIN, "invalid name")); 99 case EZFS_BADRESTORE: 100 return (dgettext(TEXT_DOMAIN, "unable to restore to " 101 "destination")); 102 case EZFS_BADBACKUP: 103 return (dgettext(TEXT_DOMAIN, "backup failed")); 104 case EZFS_BADTARGET: 105 return (dgettext(TEXT_DOMAIN, "invalid target vdev")); 106 case EZFS_NODEVICE: 107 return (dgettext(TEXT_DOMAIN, "no such device in pool")); 108 case EZFS_BADDEV: 109 return (dgettext(TEXT_DOMAIN, "invalid device")); 110 case EZFS_NOREPLICAS: 111 return (dgettext(TEXT_DOMAIN, "no valid replicas")); 112 case EZFS_RESILVERING: 113 return (dgettext(TEXT_DOMAIN, "currently resilvering")); 114 case EZFS_BADVERSION: 115 return (dgettext(TEXT_DOMAIN, "unsupported version")); 116 case EZFS_POOLUNAVAIL: 117 return (dgettext(TEXT_DOMAIN, "pool is unavailable")); 118 case EZFS_DEVOVERFLOW: 119 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev")); 120 case EZFS_BADPATH: 121 return (dgettext(TEXT_DOMAIN, "must be an absolute path")); 122 case EZFS_CROSSTARGET: 123 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or " 124 "pools")); 125 case EZFS_ZONED: 126 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone")); 127 case EZFS_MOUNTFAILED: 128 return (dgettext(TEXT_DOMAIN, "mount failed")); 129 case EZFS_UMOUNTFAILED: 130 return (dgettext(TEXT_DOMAIN, "umount failed")); 131 case EZFS_UNSHARENFSFAILED: 132 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed")); 133 case EZFS_SHARENFSFAILED: 134 return (dgettext(TEXT_DOMAIN, "share(1M) failed")); 135 case EZFS_UNSHARESMBFAILED: 136 return (dgettext(TEXT_DOMAIN, "smb remove share failed")); 137 case EZFS_SHARESMBFAILED: 138 return (dgettext(TEXT_DOMAIN, "smb add share failed")); 139 case EZFS_ISCSISVCUNAVAIL: 140 return (dgettext(TEXT_DOMAIN, 141 "iscsitgt service need to be enabled by " 142 "a privileged user")); 143 case EZFS_PERM: 144 return (dgettext(TEXT_DOMAIN, "permission denied")); 145 case EZFS_NOSPC: 146 return (dgettext(TEXT_DOMAIN, "out of space")); 147 case EZFS_IO: 148 return (dgettext(TEXT_DOMAIN, "I/O error")); 149 case EZFS_INTR: 150 return (dgettext(TEXT_DOMAIN, "signal received")); 151 case EZFS_ISSPARE: 152 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " 153 "spare")); 154 case EZFS_INVALCONFIG: 155 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration")); 156 case EZFS_RECURSIVE: 157 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); 158 case EZFS_NOHISTORY: 159 return (dgettext(TEXT_DOMAIN, "no history available")); 160 case EZFS_UNSHAREISCSIFAILED: 161 return (dgettext(TEXT_DOMAIN, 162 "iscsitgtd failed request to unshare")); 163 case EZFS_SHAREISCSIFAILED: 164 return (dgettext(TEXT_DOMAIN, 165 "iscsitgtd failed request to share")); 166 case EZFS_POOLPROPS: 167 return (dgettext(TEXT_DOMAIN, "failed to retrieve " 168 "pool properties")); 169 case EZFS_POOL_NOTSUP: 170 return (dgettext(TEXT_DOMAIN, "operation not supported " 171 "on this type of pool")); 172 case EZFS_POOL_INVALARG: 173 return (dgettext(TEXT_DOMAIN, "invalid argument for " 174 "this pool operation")); 175 case EZFS_NAMETOOLONG: 176 return (dgettext(TEXT_DOMAIN, "dataset name is too long")); 177 case EZFS_OPENFAILED: 178 return (dgettext(TEXT_DOMAIN, "open failed")); 179 case EZFS_NOCAP: 180 return (dgettext(TEXT_DOMAIN, 181 "disk capacity information could not be retrieved")); 182 case EZFS_LABELFAILED: 183 return (dgettext(TEXT_DOMAIN, "write of label failed")); 184 case EZFS_BADWHO: 185 return (dgettext(TEXT_DOMAIN, "invalid user/group")); 186 case EZFS_BADPERM: 187 return (dgettext(TEXT_DOMAIN, "invalid permission")); 188 case EZFS_BADPERMSET: 189 return (dgettext(TEXT_DOMAIN, "invalid permission set name")); 190 case EZFS_NODELEGATION: 191 return (dgettext(TEXT_DOMAIN, "delegated administration is " 192 "disabled on pool")); 193 case EZFS_PERMRDONLY: 194 return (dgettext(TEXT_DOMAIN, "snapshot permissions cannot be" 195 " modified")); 196 case EZFS_BADCACHE: 197 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); 198 case EZFS_ISL2CACHE: 199 return (dgettext(TEXT_DOMAIN, "device is in use as a cache")); 200 case EZFS_VDEVNOTSUP: 201 return (dgettext(TEXT_DOMAIN, "vdev specification is not " 202 "supported")); 203 case EZFS_NOTSUP: 204 return (dgettext(TEXT_DOMAIN, "operation not supported " 205 "on this dataset")); 206 case EZFS_ACTIVE_SPARE: 207 return (dgettext(TEXT_DOMAIN, "pool has active shared spare " 208 "device")); 209 case EZFS_UNPLAYED_LOGS: 210 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent " 211 "logs")); 212 case EZFS_REFTAG_RELE: 213 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset")); 214 case EZFS_REFTAG_HOLD: 215 return (dgettext(TEXT_DOMAIN, "tag already exists on this " 216 "dataset")); 217 case EZFS_TAGTOOLONG: 218 return (dgettext(TEXT_DOMAIN, "tag too long")); 219 case EZFS_PIPEFAILED: 220 return (dgettext(TEXT_DOMAIN, "pipe create failed")); 221 case EZFS_THREADCREATEFAILED: 222 return (dgettext(TEXT_DOMAIN, "thread create failed")); 223 case EZFS_POSTSPLIT_ONLINE: 224 return (dgettext(TEXT_DOMAIN, "disk was split from this pool " 225 "into a new one")); 226 case EZFS_UNKNOWN: 227 return (dgettext(TEXT_DOMAIN, "unknown error")); 228 default: 229 assert(hdl->libzfs_error == 0); 230 return (dgettext(TEXT_DOMAIN, "no error")); 231 } 232 } 233 234 /*PRINTFLIKE2*/ 235 void 236 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...) 237 { 238 va_list ap; 239 240 va_start(ap, fmt); 241 242 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc), 243 fmt, ap); 244 hdl->libzfs_desc_active = 1; 245 246 va_end(ap); 247 } 248 249 static void 250 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap) 251 { 252 (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action), 253 fmt, ap); 254 hdl->libzfs_error = error; 255 256 if (hdl->libzfs_desc_active) 257 hdl->libzfs_desc_active = 0; 258 else 259 hdl->libzfs_desc[0] = '\0'; 260 261 if (hdl->libzfs_printerr) { 262 if (error == EZFS_UNKNOWN) { 263 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal " 264 "error: %s\n"), libzfs_error_description(hdl)); 265 abort(); 266 } 267 268 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action, 269 libzfs_error_description(hdl)); 270 if (error == EZFS_NOMEM) 271 exit(1); 272 } 273 } 274 275 int 276 zfs_error(libzfs_handle_t *hdl, int error, const char *msg) 277 { 278 return (zfs_error_fmt(hdl, error, "%s", msg)); 279 } 280 281 /*PRINTFLIKE3*/ 282 int 283 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 284 { 285 va_list ap; 286 287 va_start(ap, fmt); 288 289 zfs_verror(hdl, error, fmt, ap); 290 291 va_end(ap); 292 293 return (-1); 294 } 295 296 static int 297 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, 298 va_list ap) 299 { 300 switch (error) { 301 case EPERM: 302 case EACCES: 303 zfs_verror(hdl, EZFS_PERM, fmt, ap); 304 return (-1); 305 306 case ECANCELED: 307 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap); 308 return (-1); 309 310 case EIO: 311 zfs_verror(hdl, EZFS_IO, fmt, ap); 312 return (-1); 313 314 case EINTR: 315 zfs_verror(hdl, EZFS_INTR, fmt, ap); 316 return (-1); 317 } 318 319 return (0); 320 } 321 322 int 323 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 324 { 325 return (zfs_standard_error_fmt(hdl, error, "%s", msg)); 326 } 327 328 /*PRINTFLIKE3*/ 329 int 330 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 331 { 332 va_list ap; 333 334 va_start(ap, fmt); 335 336 if (zfs_common_error(hdl, error, fmt, ap) != 0) { 337 va_end(ap); 338 return (-1); 339 } 340 341 switch (error) { 342 case ENXIO: 343 case ENODEV: 344 zfs_verror(hdl, EZFS_IO, fmt, ap); 345 break; 346 347 case ENOENT: 348 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 349 "dataset does not exist")); 350 zfs_verror(hdl, EZFS_NOENT, fmt, ap); 351 break; 352 353 case ENOSPC: 354 case EDQUOT: 355 zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 356 return (-1); 357 358 case EEXIST: 359 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 360 "dataset already exists")); 361 zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 362 break; 363 364 case EBUSY: 365 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 366 "dataset is busy")); 367 zfs_verror(hdl, EZFS_BUSY, fmt, ap); 368 break; 369 case EROFS: 370 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 371 "snapshot permissions cannot be modified")); 372 zfs_verror(hdl, EZFS_PERMRDONLY, fmt, ap); 373 break; 374 case ENAMETOOLONG: 375 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); 376 break; 377 case ENOTSUP: 378 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); 379 break; 380 case EAGAIN: 381 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 382 "pool I/O is currently suspended")); 383 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 384 break; 385 default: 386 zfs_error_aux(hdl, strerror(error)); 387 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 388 break; 389 } 390 391 va_end(ap); 392 return (-1); 393 } 394 395 int 396 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 397 { 398 return (zpool_standard_error_fmt(hdl, error, "%s", msg)); 399 } 400 401 /*PRINTFLIKE3*/ 402 int 403 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 404 { 405 va_list ap; 406 407 va_start(ap, fmt); 408 409 if (zfs_common_error(hdl, error, fmt, ap) != 0) { 410 va_end(ap); 411 return (-1); 412 } 413 414 switch (error) { 415 case ENODEV: 416 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); 417 break; 418 419 case ENOENT: 420 zfs_error_aux(hdl, 421 dgettext(TEXT_DOMAIN, "no such pool or dataset")); 422 zfs_verror(hdl, EZFS_NOENT, fmt, ap); 423 break; 424 425 case EEXIST: 426 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 427 "pool already exists")); 428 zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 429 break; 430 431 case EBUSY: 432 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); 433 zfs_verror(hdl, EZFS_BUSY, fmt, ap); 434 break; 435 436 case ENXIO: 437 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 438 "one or more devices is currently unavailable")); 439 zfs_verror(hdl, EZFS_BADDEV, fmt, ap); 440 break; 441 442 case ENAMETOOLONG: 443 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); 444 break; 445 446 case ENOTSUP: 447 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); 448 break; 449 450 case EINVAL: 451 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); 452 break; 453 454 case ENOSPC: 455 case EDQUOT: 456 zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 457 return (-1); 458 case EAGAIN: 459 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 460 "pool I/O is currently suspended")); 461 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 462 break; 463 464 default: 465 zfs_error_aux(hdl, strerror(error)); 466 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 467 } 468 469 va_end(ap); 470 return (-1); 471 } 472 473 /* 474 * Display an out of memory error message and abort the current program. 475 */ 476 int 477 no_memory(libzfs_handle_t *hdl) 478 { 479 return (zfs_error(hdl, EZFS_NOMEM, "internal error")); 480 } 481 482 /* 483 * A safe form of malloc() which will die if the allocation fails. 484 */ 485 void * 486 zfs_alloc(libzfs_handle_t *hdl, size_t size) 487 { 488 void *data; 489 490 if ((data = calloc(1, size)) == NULL) 491 (void) no_memory(hdl); 492 493 return (data); 494 } 495 496 /* 497 * A safe form of realloc(), which also zeroes newly allocated space. 498 */ 499 void * 500 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) 501 { 502 void *ret; 503 504 if ((ret = realloc(ptr, newsize)) == NULL) { 505 (void) no_memory(hdl); 506 return (NULL); 507 } 508 509 bzero((char *)ret + oldsize, (newsize - oldsize)); 510 return (ret); 511 } 512 513 /* 514 * A safe form of strdup() which will die if the allocation fails. 515 */ 516 char * 517 zfs_strdup(libzfs_handle_t *hdl, const char *str) 518 { 519 char *ret; 520 521 if ((ret = strdup(str)) == NULL) 522 (void) no_memory(hdl); 523 524 return (ret); 525 } 526 527 /* 528 * Convert a number to an appropriately human-readable output. 529 */ 530 void 531 zfs_nicenum(uint64_t num, char *buf, size_t buflen) 532 { 533 uint64_t n = num; 534 int index = 0; 535 char u; 536 537 while (n >= 1024) { 538 n /= 1024; 539 index++; 540 } 541 542 u = " KMGTPE"[index]; 543 544 if (index == 0) { 545 (void) snprintf(buf, buflen, "%llu", n); 546 } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { 547 /* 548 * If this is an even multiple of the base, always display 549 * without any decimal precision. 550 */ 551 (void) snprintf(buf, buflen, "%llu%c", n, u); 552 } else { 553 /* 554 * We want to choose a precision that reflects the best choice 555 * for fitting in 5 characters. This can get rather tricky when 556 * we have numbers that are very close to an order of magnitude. 557 * For example, when displaying 10239 (which is really 9.999K), 558 * we want only a single place of precision for 10.0K. We could 559 * develop some complex heuristics for this, but it's much 560 * easier just to try each combination in turn. 561 */ 562 int i; 563 for (i = 2; i >= 0; i--) { 564 if (snprintf(buf, buflen, "%.*f%c", i, 565 (double)num / (1ULL << 10 * index), u) <= 5) 566 break; 567 } 568 } 569 } 570 571 void 572 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) 573 { 574 hdl->libzfs_printerr = printerr; 575 } 576 577 libzfs_handle_t * 578 libzfs_init(void) 579 { 580 libzfs_handle_t *hdl; 581 582 if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) { 583 return (NULL); 584 } 585 586 if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { 587 free(hdl); 588 return (NULL); 589 } 590 591 if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { 592 (void) close(hdl->libzfs_fd); 593 free(hdl); 594 return (NULL); 595 } 596 597 hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); 598 599 zfs_prop_init(); 600 zpool_prop_init(); 601 libzfs_mnttab_init(hdl); 602 603 return (hdl); 604 } 605 606 void 607 libzfs_fini(libzfs_handle_t *hdl) 608 { 609 (void) close(hdl->libzfs_fd); 610 if (hdl->libzfs_mnttab) 611 (void) fclose(hdl->libzfs_mnttab); 612 if (hdl->libzfs_sharetab) 613 (void) fclose(hdl->libzfs_sharetab); 614 zfs_uninit_libshare(hdl); 615 if (hdl->libzfs_log_str) 616 (void) free(hdl->libzfs_log_str); 617 zpool_free_handles(hdl); 618 libzfs_fru_clear(hdl, B_TRUE); 619 namespace_clear(hdl); 620 libzfs_mnttab_fini(hdl); 621 free(hdl); 622 } 623 624 libzfs_handle_t * 625 zpool_get_handle(zpool_handle_t *zhp) 626 { 627 return (zhp->zpool_hdl); 628 } 629 630 libzfs_handle_t * 631 zfs_get_handle(zfs_handle_t *zhp) 632 { 633 return (zhp->zfs_hdl); 634 } 635 636 zpool_handle_t * 637 zfs_get_pool_handle(const zfs_handle_t *zhp) 638 { 639 return (zhp->zpool_hdl); 640 } 641 642 /* 643 * Given a name, determine whether or not it's a valid path 644 * (starts with '/' or "./"). If so, walk the mnttab trying 645 * to match the device number. If not, treat the path as an 646 * fs/vol/snap name. 647 */ 648 zfs_handle_t * 649 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype) 650 { 651 struct stat64 statbuf; 652 struct extmnttab entry; 653 int ret; 654 655 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { 656 /* 657 * It's not a valid path, assume it's a name of type 'argtype'. 658 */ 659 return (zfs_open(hdl, path, argtype)); 660 } 661 662 if (stat64(path, &statbuf) != 0) { 663 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno)); 664 return (NULL); 665 } 666 667 rewind(hdl->libzfs_mnttab); 668 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) { 669 if (makedevice(entry.mnt_major, entry.mnt_minor) == 670 statbuf.st_dev) { 671 break; 672 } 673 } 674 if (ret != 0) { 675 return (NULL); 676 } 677 678 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { 679 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), 680 path); 681 return (NULL); 682 } 683 684 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); 685 } 686 687 /* 688 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from 689 * an ioctl(). 690 */ 691 int 692 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) 693 { 694 if (len == 0) 695 len = 4*1024; 696 zc->zc_nvlist_dst_size = len; 697 if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 698 zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL) 699 return (-1); 700 701 return (0); 702 } 703 704 /* 705 * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will 706 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was 707 * filled in by the kernel to indicate the actual required size. 708 */ 709 int 710 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) 711 { 712 free((void *)(uintptr_t)zc->zc_nvlist_dst); 713 if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 714 zfs_alloc(hdl, zc->zc_nvlist_dst_size)) 715 == NULL) 716 return (-1); 717 718 return (0); 719 } 720 721 /* 722 * Called to free the src and dst nvlists stored in the command structure. 723 */ 724 void 725 zcmd_free_nvlists(zfs_cmd_t *zc) 726 { 727 free((void *)(uintptr_t)zc->zc_nvlist_conf); 728 free((void *)(uintptr_t)zc->zc_nvlist_src); 729 free((void *)(uintptr_t)zc->zc_nvlist_dst); 730 } 731 732 static int 733 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, 734 nvlist_t *nvl) 735 { 736 char *packed; 737 size_t len; 738 739 verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0); 740 741 if ((packed = zfs_alloc(hdl, len)) == NULL) 742 return (-1); 743 744 verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 745 746 *outnv = (uint64_t)(uintptr_t)packed; 747 *outlen = len; 748 749 return (0); 750 } 751 752 int 753 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 754 { 755 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, 756 &zc->zc_nvlist_conf_size, nvl)); 757 } 758 759 int 760 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 761 { 762 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, 763 &zc->zc_nvlist_src_size, nvl)); 764 } 765 766 /* 767 * Unpacks an nvlist from the ZFS ioctl command structure. 768 */ 769 int 770 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) 771 { 772 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, 773 zc->zc_nvlist_dst_size, nvlp, 0) != 0) 774 return (no_memory(hdl)); 775 776 return (0); 777 } 778 779 int 780 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) 781 { 782 int error; 783 784 zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str; 785 error = ioctl(hdl->libzfs_fd, request, zc); 786 if (hdl->libzfs_log_str) { 787 free(hdl->libzfs_log_str); 788 hdl->libzfs_log_str = NULL; 789 } 790 zc->zc_history = 0; 791 792 return (error); 793 } 794 795 /* 796 * ================================================================ 797 * API shared by zfs and zpool property management 798 * ================================================================ 799 */ 800 801 static void 802 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) 803 { 804 zprop_list_t *pl = cbp->cb_proplist; 805 int i; 806 char *title; 807 size_t len; 808 809 cbp->cb_first = B_FALSE; 810 if (cbp->cb_scripted) 811 return; 812 813 /* 814 * Start with the length of the column headers. 815 */ 816 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); 817 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, 818 "PROPERTY")); 819 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, 820 "VALUE")); 821 cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN, 822 "RECEIVED")); 823 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, 824 "SOURCE")); 825 826 /* first property is always NAME */ 827 assert(cbp->cb_proplist->pl_prop == 828 ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME)); 829 830 /* 831 * Go through and calculate the widths for each column. For the 832 * 'source' column, we kludge it up by taking the worst-case scenario of 833 * inheriting from the longest name. This is acceptable because in the 834 * majority of cases 'SOURCE' is the last column displayed, and we don't 835 * use the width anyway. Note that the 'VALUE' column can be oversized, 836 * if the name of the property is much longer than any values we find. 837 */ 838 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 839 /* 840 * 'PROPERTY' column 841 */ 842 if (pl->pl_prop != ZPROP_INVAL) { 843 const char *propname = (type == ZFS_TYPE_POOL) ? 844 zpool_prop_to_name(pl->pl_prop) : 845 zfs_prop_to_name(pl->pl_prop); 846 847 len = strlen(propname); 848 if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 849 cbp->cb_colwidths[GET_COL_PROPERTY] = len; 850 } else { 851 len = strlen(pl->pl_user_prop); 852 if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 853 cbp->cb_colwidths[GET_COL_PROPERTY] = len; 854 } 855 856 /* 857 * 'VALUE' column. The first property is always the 'name' 858 * property that was tacked on either by /sbin/zfs's 859 * zfs_do_get() or when calling zprop_expand_list(), so we 860 * ignore its width. If the user specified the name property 861 * to display, then it will be later in the list in any case. 862 */ 863 if (pl != cbp->cb_proplist && 864 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) 865 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; 866 867 /* 'RECEIVED' column. */ 868 if (pl != cbp->cb_proplist && 869 pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD]) 870 cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width; 871 872 /* 873 * 'NAME' and 'SOURCE' columns 874 */ 875 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME : 876 ZFS_PROP_NAME) && 877 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { 878 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; 879 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + 880 strlen(dgettext(TEXT_DOMAIN, "inherited from")); 881 } 882 } 883 884 /* 885 * Now go through and print the headers. 886 */ 887 for (i = 0; i < ZFS_GET_NCOLS; i++) { 888 switch (cbp->cb_columns[i]) { 889 case GET_COL_NAME: 890 title = dgettext(TEXT_DOMAIN, "NAME"); 891 break; 892 case GET_COL_PROPERTY: 893 title = dgettext(TEXT_DOMAIN, "PROPERTY"); 894 break; 895 case GET_COL_VALUE: 896 title = dgettext(TEXT_DOMAIN, "VALUE"); 897 break; 898 case GET_COL_RECVD: 899 title = dgettext(TEXT_DOMAIN, "RECEIVED"); 900 break; 901 case GET_COL_SOURCE: 902 title = dgettext(TEXT_DOMAIN, "SOURCE"); 903 break; 904 default: 905 title = NULL; 906 } 907 908 if (title != NULL) { 909 if (i == (ZFS_GET_NCOLS - 1) || 910 cbp->cb_columns[i + 1] == GET_COL_NONE) 911 (void) printf("%s", title); 912 else 913 (void) printf("%-*s ", 914 cbp->cb_colwidths[cbp->cb_columns[i]], 915 title); 916 } 917 } 918 (void) printf("\n"); 919 } 920 921 /* 922 * Display a single line of output, according to the settings in the callback 923 * structure. 924 */ 925 void 926 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, 927 const char *propname, const char *value, zprop_source_t sourcetype, 928 const char *source, const char *recvd_value) 929 { 930 int i; 931 const char *str; 932 char buf[128]; 933 934 /* 935 * Ignore those source types that the user has chosen to ignore. 936 */ 937 if ((sourcetype & cbp->cb_sources) == 0) 938 return; 939 940 if (cbp->cb_first) 941 zprop_print_headers(cbp, cbp->cb_type); 942 943 for (i = 0; i < ZFS_GET_NCOLS; i++) { 944 switch (cbp->cb_columns[i]) { 945 case GET_COL_NAME: 946 str = name; 947 break; 948 949 case GET_COL_PROPERTY: 950 str = propname; 951 break; 952 953 case GET_COL_VALUE: 954 str = value; 955 break; 956 957 case GET_COL_SOURCE: 958 switch (sourcetype) { 959 case ZPROP_SRC_NONE: 960 str = "-"; 961 break; 962 963 case ZPROP_SRC_DEFAULT: 964 str = "default"; 965 break; 966 967 case ZPROP_SRC_LOCAL: 968 str = "local"; 969 break; 970 971 case ZPROP_SRC_TEMPORARY: 972 str = "temporary"; 973 break; 974 975 case ZPROP_SRC_INHERITED: 976 (void) snprintf(buf, sizeof (buf), 977 "inherited from %s", source); 978 str = buf; 979 break; 980 case ZPROP_SRC_RECEIVED: 981 str = "received"; 982 break; 983 } 984 break; 985 986 case GET_COL_RECVD: 987 str = (recvd_value == NULL ? "-" : recvd_value); 988 break; 989 990 default: 991 continue; 992 } 993 994 if (cbp->cb_columns[i + 1] == GET_COL_NONE) 995 (void) printf("%s", str); 996 else if (cbp->cb_scripted) 997 (void) printf("%s\t", str); 998 else 999 (void) printf("%-*s ", 1000 cbp->cb_colwidths[cbp->cb_columns[i]], 1001 str); 1002 } 1003 1004 (void) printf("\n"); 1005 } 1006 1007 /* 1008 * Given a numeric suffix, convert the value into a number of bits that the 1009 * resulting value must be shifted. 1010 */ 1011 static int 1012 str2shift(libzfs_handle_t *hdl, const char *buf) 1013 { 1014 const char *ends = "BKMGTPEZ"; 1015 int i; 1016 1017 if (buf[0] == '\0') 1018 return (0); 1019 for (i = 0; i < strlen(ends); i++) { 1020 if (toupper(buf[0]) == ends[i]) 1021 break; 1022 } 1023 if (i == strlen(ends)) { 1024 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1025 "invalid numeric suffix '%s'"), buf); 1026 return (-1); 1027 } 1028 1029 /* 1030 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 1031 * allow 'BB' - that's just weird. 1032 */ 1033 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 1034 toupper(buf[0]) != 'B')) 1035 return (10*i); 1036 1037 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1038 "invalid numeric suffix '%s'"), buf); 1039 return (-1); 1040 } 1041 1042 /* 1043 * Convert a string of the form '100G' into a real number. Used when setting 1044 * properties or creating a volume. 'buf' is used to place an extended error 1045 * message for the caller to use. 1046 */ 1047 int 1048 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 1049 { 1050 char *end; 1051 int shift; 1052 1053 *num = 0; 1054 1055 /* Check to see if this looks like a number. */ 1056 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 1057 if (hdl) 1058 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1059 "bad numeric value '%s'"), value); 1060 return (-1); 1061 } 1062 1063 /* Rely on strtoull() to process the numeric portion. */ 1064 errno = 0; 1065 *num = strtoull(value, &end, 10); 1066 1067 /* 1068 * Check for ERANGE, which indicates that the value is too large to fit 1069 * in a 64-bit value. 1070 */ 1071 if (errno == ERANGE) { 1072 if (hdl) 1073 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1074 "numeric value is too large")); 1075 return (-1); 1076 } 1077 1078 /* 1079 * If we have a decimal value, then do the computation with floating 1080 * point arithmetic. Otherwise, use standard arithmetic. 1081 */ 1082 if (*end == '.') { 1083 double fval = strtod(value, &end); 1084 1085 if ((shift = str2shift(hdl, end)) == -1) 1086 return (-1); 1087 1088 fval *= pow(2, shift); 1089 1090 if (fval > UINT64_MAX) { 1091 if (hdl) 1092 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1093 "numeric value is too large")); 1094 return (-1); 1095 } 1096 1097 *num = (uint64_t)fval; 1098 } else { 1099 if ((shift = str2shift(hdl, end)) == -1) 1100 return (-1); 1101 1102 /* Check for overflow */ 1103 if (shift >= 64 || (*num << shift) >> shift != *num) { 1104 if (hdl) 1105 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1106 "numeric value is too large")); 1107 return (-1); 1108 } 1109 1110 *num <<= shift; 1111 } 1112 1113 return (0); 1114 } 1115 1116 /* 1117 * Given a propname=value nvpair to set, parse any numeric properties 1118 * (index, boolean, etc) if they are specified as strings and add the 1119 * resulting nvpair to the returned nvlist. 1120 * 1121 * At the DSL layer, all properties are either 64-bit numbers or strings. 1122 * We want the user to be able to ignore this fact and specify properties 1123 * as native values (numbers, for example) or as strings (to simplify 1124 * command line utilities). This also handles converting index types 1125 * (compression, checksum, etc) from strings to their on-disk index. 1126 */ 1127 int 1128 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, 1129 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp, 1130 const char *errbuf) 1131 { 1132 data_type_t datatype = nvpair_type(elem); 1133 zprop_type_t proptype; 1134 const char *propname; 1135 char *value; 1136 boolean_t isnone = B_FALSE; 1137 1138 if (type == ZFS_TYPE_POOL) { 1139 proptype = zpool_prop_get_type(prop); 1140 propname = zpool_prop_to_name(prop); 1141 } else { 1142 proptype = zfs_prop_get_type(prop); 1143 propname = zfs_prop_to_name(prop); 1144 } 1145 1146 /* 1147 * Convert any properties to the internal DSL value types. 1148 */ 1149 *svalp = NULL; 1150 *ivalp = 0; 1151 1152 switch (proptype) { 1153 case PROP_TYPE_STRING: 1154 if (datatype != DATA_TYPE_STRING) { 1155 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1156 "'%s' must be a string"), nvpair_name(elem)); 1157 goto error; 1158 } 1159 (void) nvpair_value_string(elem, svalp); 1160 if (strlen(*svalp) >= ZFS_MAXPROPLEN) { 1161 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1162 "'%s' is too long"), nvpair_name(elem)); 1163 goto error; 1164 } 1165 break; 1166 1167 case PROP_TYPE_NUMBER: 1168 if (datatype == DATA_TYPE_STRING) { 1169 (void) nvpair_value_string(elem, &value); 1170 if (strcmp(value, "none") == 0) { 1171 isnone = B_TRUE; 1172 } else if (zfs_nicestrtonum(hdl, value, ivalp) 1173 != 0) { 1174 goto error; 1175 } 1176 } else if (datatype == DATA_TYPE_UINT64) { 1177 (void) nvpair_value_uint64(elem, ivalp); 1178 } else { 1179 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1180 "'%s' must be a number"), nvpair_name(elem)); 1181 goto error; 1182 } 1183 1184 /* 1185 * Quota special: force 'none' and don't allow 0. 1186 */ 1187 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && 1188 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { 1189 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1190 "use 'none' to disable quota/refquota")); 1191 goto error; 1192 } 1193 break; 1194 1195 case PROP_TYPE_INDEX: 1196 if (datatype != DATA_TYPE_STRING) { 1197 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1198 "'%s' must be a string"), nvpair_name(elem)); 1199 goto error; 1200 } 1201 1202 (void) nvpair_value_string(elem, &value); 1203 1204 if (zprop_string_to_index(prop, value, ivalp, type) != 0) { 1205 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1206 "'%s' must be one of '%s'"), propname, 1207 zprop_values(prop, type)); 1208 goto error; 1209 } 1210 break; 1211 1212 default: 1213 abort(); 1214 } 1215 1216 /* 1217 * Add the result to our return set of properties. 1218 */ 1219 if (*svalp != NULL) { 1220 if (nvlist_add_string(ret, propname, *svalp) != 0) { 1221 (void) no_memory(hdl); 1222 return (-1); 1223 } 1224 } else { 1225 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { 1226 (void) no_memory(hdl); 1227 return (-1); 1228 } 1229 } 1230 1231 return (0); 1232 error: 1233 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1234 return (-1); 1235 } 1236 1237 static int 1238 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp, 1239 zfs_type_t type) 1240 { 1241 int prop; 1242 zprop_list_t *entry; 1243 1244 prop = zprop_name_to_prop(propname, type); 1245 1246 if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type)) 1247 prop = ZPROP_INVAL; 1248 1249 /* 1250 * When no property table entry can be found, return failure if 1251 * this is a pool property or if this isn't a user-defined 1252 * dataset property, 1253 */ 1254 if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL || 1255 (!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) { 1256 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1257 "invalid property '%s'"), propname); 1258 return (zfs_error(hdl, EZFS_BADPROP, 1259 dgettext(TEXT_DOMAIN, "bad property list"))); 1260 } 1261 1262 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 1263 return (-1); 1264 1265 entry->pl_prop = prop; 1266 if (prop == ZPROP_INVAL) { 1267 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) { 1268 free(entry); 1269 return (-1); 1270 } 1271 entry->pl_width = strlen(propname); 1272 } else { 1273 entry->pl_width = zprop_width(prop, &entry->pl_fixed, 1274 type); 1275 } 1276 1277 *listp = entry; 1278 1279 return (0); 1280 } 1281 1282 /* 1283 * Given a comma-separated list of properties, construct a property list 1284 * containing both user-defined and native properties. This function will 1285 * return a NULL list if 'all' is specified, which can later be expanded 1286 * by zprop_expand_list(). 1287 */ 1288 int 1289 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, 1290 zfs_type_t type) 1291 { 1292 *listp = NULL; 1293 1294 /* 1295 * If 'all' is specified, return a NULL list. 1296 */ 1297 if (strcmp(props, "all") == 0) 1298 return (0); 1299 1300 /* 1301 * If no props were specified, return an error. 1302 */ 1303 if (props[0] == '\0') { 1304 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1305 "no properties specified")); 1306 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 1307 "bad property list"))); 1308 } 1309 1310 /* 1311 * It would be nice to use getsubopt() here, but the inclusion of column 1312 * aliases makes this more effort than it's worth. 1313 */ 1314 while (*props != '\0') { 1315 size_t len; 1316 char *p; 1317 char c; 1318 1319 if ((p = strchr(props, ',')) == NULL) { 1320 len = strlen(props); 1321 p = props + len; 1322 } else { 1323 len = p - props; 1324 } 1325 1326 /* 1327 * Check for empty options. 1328 */ 1329 if (len == 0) { 1330 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1331 "empty property name")); 1332 return (zfs_error(hdl, EZFS_BADPROP, 1333 dgettext(TEXT_DOMAIN, "bad property list"))); 1334 } 1335 1336 /* 1337 * Check all regular property names. 1338 */ 1339 c = props[len]; 1340 props[len] = '\0'; 1341 1342 if (strcmp(props, "space") == 0) { 1343 static char *spaceprops[] = { 1344 "name", "avail", "used", "usedbysnapshots", 1345 "usedbydataset", "usedbyrefreservation", 1346 "usedbychildren", NULL 1347 }; 1348 int i; 1349 1350 for (i = 0; spaceprops[i]; i++) { 1351 if (addlist(hdl, spaceprops[i], listp, type)) 1352 return (-1); 1353 listp = &(*listp)->pl_next; 1354 } 1355 } else { 1356 if (addlist(hdl, props, listp, type)) 1357 return (-1); 1358 listp = &(*listp)->pl_next; 1359 } 1360 1361 props = p; 1362 if (c == ',') 1363 props++; 1364 } 1365 1366 return (0); 1367 } 1368 1369 void 1370 zprop_free_list(zprop_list_t *pl) 1371 { 1372 zprop_list_t *next; 1373 1374 while (pl != NULL) { 1375 next = pl->pl_next; 1376 free(pl->pl_user_prop); 1377 free(pl); 1378 pl = next; 1379 } 1380 } 1381 1382 typedef struct expand_data { 1383 zprop_list_t **last; 1384 libzfs_handle_t *hdl; 1385 zfs_type_t type; 1386 } expand_data_t; 1387 1388 int 1389 zprop_expand_list_cb(int prop, void *cb) 1390 { 1391 zprop_list_t *entry; 1392 expand_data_t *edp = cb; 1393 1394 if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL) 1395 return (ZPROP_INVAL); 1396 1397 entry->pl_prop = prop; 1398 entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); 1399 entry->pl_all = B_TRUE; 1400 1401 *(edp->last) = entry; 1402 edp->last = &entry->pl_next; 1403 1404 return (ZPROP_CONT); 1405 } 1406 1407 int 1408 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) 1409 { 1410 zprop_list_t *entry; 1411 zprop_list_t **last; 1412 expand_data_t exp; 1413 1414 if (*plp == NULL) { 1415 /* 1416 * If this is the very first time we've been called for an 'all' 1417 * specification, expand the list to include all native 1418 * properties. 1419 */ 1420 last = plp; 1421 1422 exp.last = last; 1423 exp.hdl = hdl; 1424 exp.type = type; 1425 1426 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, 1427 B_FALSE, type) == ZPROP_INVAL) 1428 return (-1); 1429 1430 /* 1431 * Add 'name' to the beginning of the list, which is handled 1432 * specially. 1433 */ 1434 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 1435 return (-1); 1436 1437 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : 1438 ZFS_PROP_NAME; 1439 entry->pl_width = zprop_width(entry->pl_prop, 1440 &entry->pl_fixed, type); 1441 entry->pl_all = B_TRUE; 1442 entry->pl_next = *plp; 1443 *plp = entry; 1444 } 1445 return (0); 1446 } 1447 1448 int 1449 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, 1450 zfs_type_t type) 1451 { 1452 return (zprop_iter_common(func, cb, show_all, ordered, type)); 1453 } 1454