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