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