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