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 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  25  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  26  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  27  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
  28  * Copyright (c) 2017 Datto Inc.
  29  */
  30 
  31 /*
  32  * Internal utility routines for the ZFS library.
  33  */
  34 
  35 #include <errno.h>
  36 #include <fcntl.h>
  37 #include <libintl.h>
  38 #include <stdarg.h>
  39 #include <stdio.h>
  40 #include <stdlib.h>
  41 #include <strings.h>
  42 #include <unistd.h>
  43 #include <ctype.h>
  44 #include <math.h>
  45 #include <sys/filio.h>
  46 #include <sys/mnttab.h>
  47 #include <sys/mntent.h>
  48 #include <sys/types.h>
  49 #include <libcmdutils.h>
  50 
  51 #include <libzfs.h>
  52 #include <libzfs_core.h>
  53 
  54 #include "libzfs_impl.h"
  55 #include "zfs_prop.h"
  56 #include "zfeature_common.h"
  57 
  58 int
  59 libzfs_errno(libzfs_handle_t *hdl)
  60 {
  61         return (hdl->libzfs_error);
  62 }
  63 
  64 const char *
  65 libzfs_error_action(libzfs_handle_t *hdl)
  66 {
  67         return (hdl->libzfs_action);
  68 }
  69 
  70 const char *
  71 libzfs_error_description(libzfs_handle_t *hdl)
  72 {
  73         if (hdl->libzfs_desc[0] != '\0')
  74                 return (hdl->libzfs_desc);
  75 
  76         switch (hdl->libzfs_error) {
  77         case EZFS_NOMEM:
  78                 return (dgettext(TEXT_DOMAIN, "out of memory"));
  79         case EZFS_BADPROP:
  80                 return (dgettext(TEXT_DOMAIN, "invalid property value"));
  81         case EZFS_PROPREADONLY:
  82                 return (dgettext(TEXT_DOMAIN, "read-only property"));
  83         case EZFS_PROPTYPE:
  84                 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
  85                     "datasets of this type"));
  86         case EZFS_PROPNONINHERIT:
  87                 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
  88         case EZFS_PROPSPACE:
  89                 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
  90         case EZFS_BADTYPE:
  91                 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
  92                     "datasets of this type"));
  93         case EZFS_BUSY:
  94                 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
  95         case EZFS_EXISTS:
  96                 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
  97         case EZFS_NOENT:
  98                 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
  99         case EZFS_BADSTREAM:
 100                 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
 101         case EZFS_DSREADONLY:
 102                 return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
 103         case EZFS_VOLTOOBIG:
 104                 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
 105                     "this system"));
 106         case EZFS_INVALIDNAME:
 107                 return (dgettext(TEXT_DOMAIN, "invalid name"));
 108         case EZFS_BADRESTORE:
 109                 return (dgettext(TEXT_DOMAIN, "unable to restore to "
 110                     "destination"));
 111         case EZFS_BADBACKUP:
 112                 return (dgettext(TEXT_DOMAIN, "backup failed"));
 113         case EZFS_BADTARGET:
 114                 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
 115         case EZFS_NODEVICE:
 116                 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
 117         case EZFS_BADDEV:
 118                 return (dgettext(TEXT_DOMAIN, "invalid device"));
 119         case EZFS_NOREPLICAS:
 120                 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
 121         case EZFS_RESILVERING:
 122                 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
 123         case EZFS_BADVERSION:
 124                 return (dgettext(TEXT_DOMAIN, "unsupported version or "
 125                     "feature"));
 126         case EZFS_POOLUNAVAIL:
 127                 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
 128         case EZFS_DEVOVERFLOW:
 129                 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
 130         case EZFS_BADPATH:
 131                 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
 132         case EZFS_CROSSTARGET:
 133                 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
 134                     "pools"));
 135         case EZFS_ZONED:
 136                 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
 137         case EZFS_MOUNTFAILED:
 138                 return (dgettext(TEXT_DOMAIN, "mount failed"));
 139         case EZFS_UMOUNTFAILED:
 140                 return (dgettext(TEXT_DOMAIN, "umount failed"));
 141         case EZFS_UNSHARENFSFAILED:
 142                 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
 143         case EZFS_SHARENFSFAILED:
 144                 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
 145         case EZFS_UNSHARESMBFAILED:
 146                 return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
 147         case EZFS_SHARESMBFAILED:
 148                 return (dgettext(TEXT_DOMAIN, "smb add share failed"));
 149         case EZFS_PERM:
 150                 return (dgettext(TEXT_DOMAIN, "permission denied"));
 151         case EZFS_NOSPC:
 152                 return (dgettext(TEXT_DOMAIN, "out of space"));
 153         case EZFS_FAULT:
 154                 return (dgettext(TEXT_DOMAIN, "bad address"));
 155         case EZFS_IO:
 156                 return (dgettext(TEXT_DOMAIN, "I/O error"));
 157         case EZFS_INTR:
 158                 return (dgettext(TEXT_DOMAIN, "signal received"));
 159         case EZFS_ISSPARE:
 160                 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
 161                     "spare"));
 162         case EZFS_INVALCONFIG:
 163                 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
 164         case EZFS_RECURSIVE:
 165                 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
 166         case EZFS_NOHISTORY:
 167                 return (dgettext(TEXT_DOMAIN, "no history available"));
 168         case EZFS_POOLPROPS:
 169                 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
 170                     "pool properties"));
 171         case EZFS_POOL_NOTSUP:
 172                 return (dgettext(TEXT_DOMAIN, "operation not supported "
 173                     "on this type of pool"));
 174         case EZFS_POOL_INVALARG:
 175                 return (dgettext(TEXT_DOMAIN, "invalid argument for "
 176                     "this pool operation"));
 177         case EZFS_NAMETOOLONG:
 178                 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
 179         case EZFS_OPENFAILED:
 180                 return (dgettext(TEXT_DOMAIN, "open failed"));
 181         case EZFS_NOCAP:
 182                 return (dgettext(TEXT_DOMAIN,
 183                     "disk capacity information could not be retrieved"));
 184         case EZFS_LABELFAILED:
 185                 return (dgettext(TEXT_DOMAIN, "write of label failed"));
 186         case EZFS_BADWHO:
 187                 return (dgettext(TEXT_DOMAIN, "invalid user/group"));
 188         case EZFS_BADPERM:
 189                 return (dgettext(TEXT_DOMAIN, "invalid permission"));
 190         case EZFS_BADPERMSET:
 191                 return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
 192         case EZFS_NODELEGATION:
 193                 return (dgettext(TEXT_DOMAIN, "delegated administration is "
 194                     "disabled on pool"));
 195         case EZFS_BADCACHE:
 196                 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
 197         case EZFS_ISL2CACHE:
 198                 return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
 199         case EZFS_VDEVNOTSUP:
 200                 return (dgettext(TEXT_DOMAIN, "vdev specification is not "
 201                     "supported"));
 202         case EZFS_NOTSUP:
 203                 return (dgettext(TEXT_DOMAIN, "operation not supported "
 204                     "on this dataset"));
 205         case EZFS_ACTIVE_SPARE:
 206                 return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
 207                     "device"));
 208         case EZFS_UNPLAYED_LOGS:
 209                 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
 210                     "logs"));
 211         case EZFS_REFTAG_RELE:
 212                 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
 213         case EZFS_REFTAG_HOLD:
 214                 return (dgettext(TEXT_DOMAIN, "tag already exists on this "
 215                     "dataset"));
 216         case EZFS_TAGTOOLONG:
 217                 return (dgettext(TEXT_DOMAIN, "tag too long"));
 218         case EZFS_PIPEFAILED:
 219                 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
 220         case EZFS_THREADCREATEFAILED:
 221                 return (dgettext(TEXT_DOMAIN, "thread create failed"));
 222         case EZFS_POSTSPLIT_ONLINE:
 223                 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
 224                     "into a new one"));
 225         case EZFS_SCRUB_PAUSED:
 226                 return (dgettext(TEXT_DOMAIN, "scrub is paused; "
 227                     "use 'zpool scrub' to resume"));
 228         case EZFS_SCRUBBING:
 229                 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
 230                     "use 'zpool scrub -s' to cancel current scrub"));
 231         case EZFS_NO_SCRUB:
 232                 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
 233         case EZFS_DIFF:
 234                 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
 235         case EZFS_DIFFDATA:
 236                 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
 237         case EZFS_POOLREADONLY:
 238                 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
 239         case EZFS_PROPNOTSUP:
 240                 return (dgettext(TEXT_DOMAIN, "property is not supported"));
 241         case EZFS_COSNOTFOUND:
 242                 return (dgettext(TEXT_DOMAIN, "CoS descriptor not found"));
 243         case EZFS_COSEXIST:
 244                 return (dgettext(TEXT_DOMAIN, "CoS descriptor already exists"));
 245         case EZFS_COSREF:
 246                 return (dgettext(TEXT_DOMAIN,
 247                         "CoS descriptor is still referenced"));
 248         case EZFS_UNKNOWN:
 249                 return (dgettext(TEXT_DOMAIN, "unknown error"));
 250         default:
 251                 assert(hdl->libzfs_error == 0);
 252                 return (dgettext(TEXT_DOMAIN, "no error"));
 253         }
 254 }
 255 
 256 /*PRINTFLIKE2*/
 257 void
 258 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
 259 {
 260         va_list ap;
 261 
 262         va_start(ap, fmt);
 263 
 264         (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
 265             fmt, ap);
 266         hdl->libzfs_desc_active = 1;
 267 
 268         va_end(ap);
 269 }
 270 
 271 static void
 272 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
 273 {
 274         (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
 275             fmt, ap);
 276         hdl->libzfs_error = error;
 277 
 278         if (hdl->libzfs_desc_active)
 279                 hdl->libzfs_desc_active = 0;
 280         else
 281                 hdl->libzfs_desc[0] = '\0';
 282 
 283         if (hdl->libzfs_printerr) {
 284                 if (error == EZFS_UNKNOWN) {
 285                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
 286                             "error: %s\n"), libzfs_error_description(hdl));
 287                         abort();
 288                 }
 289 
 290                 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
 291                     libzfs_error_description(hdl));
 292                 if (error == EZFS_NOMEM)
 293                         exit(1);
 294         }
 295 }
 296 
 297 int
 298 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
 299 {
 300         return (zfs_error_fmt(hdl, error, "%s", msg));
 301 }
 302 
 303 /*PRINTFLIKE3*/
 304 int
 305 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
 306 {
 307         va_list ap;
 308 
 309         va_start(ap, fmt);
 310 
 311         zfs_verror(hdl, error, fmt, ap);
 312 
 313         va_end(ap);
 314 
 315         return (-1);
 316 }
 317 
 318 static int
 319 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
 320     va_list ap)
 321 {
 322         switch (error) {
 323         case EPERM:
 324         case EACCES:
 325                 zfs_verror(hdl, EZFS_PERM, fmt, ap);
 326                 return (-1);
 327 
 328         case ECANCELED:
 329                 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
 330                 return (-1);
 331 
 332         case EIO:
 333                 zfs_verror(hdl, EZFS_IO, fmt, ap);
 334                 return (-1);
 335 
 336         case EFAULT:
 337                 zfs_verror(hdl, EZFS_FAULT, fmt, ap);
 338                 return (-1);
 339 
 340         case EINTR:
 341                 zfs_verror(hdl, EZFS_INTR, fmt, ap);
 342                 return (-1);
 343         }
 344 
 345         return (0);
 346 }
 347 
 348 int
 349 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
 350 {
 351         return (zfs_standard_error_fmt(hdl, error, "%s", msg));
 352 }
 353 
 354 /*PRINTFLIKE3*/
 355 int
 356 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
 357 {
 358         va_list ap;
 359 
 360         va_start(ap, fmt);
 361 
 362         if (zfs_common_error(hdl, error, fmt, ap) != 0) {
 363                 va_end(ap);
 364                 return (-1);
 365         }
 366 
 367         switch (error) {
 368         case ENXIO:
 369         case ENODEV:
 370         case EPIPE:
 371                 zfs_verror(hdl, EZFS_IO, fmt, ap);
 372                 break;
 373 
 374         case ENOENT:
 375                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 376                     "dataset does not exist"));
 377                 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
 378                 break;
 379 
 380         case ENOSPC:
 381         case EDQUOT:
 382                 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
 383                 return (-1);
 384 
 385         case EEXIST:
 386                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 387                     "dataset already exists"));
 388                 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
 389                 break;
 390 
 391         case EBUSY:
 392                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 393                     "dataset is busy"));
 394                 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
 395                 break;
 396         case EROFS:
 397                 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
 398                 break;
 399         case EINVAL:
 400                 zfs_verror(hdl, EZFS_INVALIDNAME, fmt, ap);
 401                 break;
 402         case ENAMETOOLONG:
 403                 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
 404                 break;
 405         case ENOTSUP:
 406                 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
 407                 break;
 408         case EAGAIN:
 409                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 410                     "pool I/O is currently suspended"));
 411                 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
 412                 break;
 413         default:
 414                 zfs_error_aux(hdl, strerror(error));
 415                 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
 416                 break;
 417         }
 418 
 419         va_end(ap);
 420         return (-1);
 421 }
 422 
 423 int
 424 zpool_vprop_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
 425 {
 426         return (zpool_vprop_standard_error_fmt(hdl, error, "%s", msg));
 427 }
 428 
 429 /*PRINTFLIKE3*/
 430 int
 431 zpool_vprop_standard_error_fmt(libzfs_handle_t *hdl, int error,
 432     const char *fmt, ...)
 433 {
 434         va_list ap;
 435 
 436         va_start(ap, fmt);
 437 
 438         if (zfs_common_error(hdl, error, fmt, ap) != 0) {
 439                 va_end(ap);
 440                 return (-1);
 441         }
 442 
 443         switch (error) {
 444         case ENOENT:
 445                 zfs_verror(hdl, EZFS_COSNOTFOUND, fmt, ap);
 446                 break;
 447         case ENOTSUP:
 448                 zfs_verror(hdl, EZFS_PROPNOTSUP, fmt, ap);
 449                 break;
 450 
 451         case EEXIST:
 452                 zfs_verror(hdl, EZFS_COSEXIST, fmt, ap);
 453                 break;
 454         case EBUSY:
 455                 zfs_verror(hdl, EZFS_COSREF, fmt, ap);
 456                 break;
 457         default:
 458                 zfs_error_aux(hdl, strerror(error));
 459                 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
 460                 break;
 461         }
 462 
 463         va_end(ap);
 464         return (-1);
 465 }
 466 
 467 int
 468 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
 469 {
 470         return (zpool_standard_error_fmt(hdl, error, "%s", msg));
 471 }
 472 
 473 /*PRINTFLIKE3*/
 474 int
 475 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
 476 {
 477         va_list ap;
 478 
 479         va_start(ap, fmt);
 480 
 481         if (zfs_common_error(hdl, error, fmt, ap) != 0) {
 482                 va_end(ap);
 483                 return (-1);
 484         }
 485 
 486         switch (error) {
 487         case ENODEV:
 488                 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
 489                 break;
 490 
 491         case ENOENT:
 492                 zfs_error_aux(hdl,
 493                     dgettext(TEXT_DOMAIN, "no such pool or dataset"));
 494                 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
 495                 break;
 496 
 497         case EEXIST:
 498                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 499                     "pool already exists"));
 500                 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
 501                 break;
 502 
 503         case EBUSY:
 504                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 505                     "pool or device is busy"));
 506                 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
 507                 break;
 508 
 509         case ENXIO:
 510                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 511                     "one or more devices is currently unavailable"));
 512                 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
 513                 break;
 514 
 515         case ENAMETOOLONG:
 516                 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
 517                 break;
 518 
 519         case ENOTSUP:
 520                 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
 521                 break;
 522 
 523         case EINVAL:
 524                 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
 525                 break;
 526 
 527         case ENOSPC:
 528         case EDQUOT:
 529                 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
 530                 return (-1);
 531 
 532         case EAGAIN:
 533                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 534                     "pool I/O is currently suspended"));
 535                 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
 536                 break;
 537 
 538         case EROFS:
 539                 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
 540                 break;
 541 
 542         default:
 543                 zfs_error_aux(hdl, strerror(error));
 544                 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
 545         }
 546 
 547         va_end(ap);
 548         return (-1);
 549 }
 550 
 551 /*
 552  * Display an out of memory error message and abort the current program.
 553  */
 554 int
 555 no_memory(libzfs_handle_t *hdl)
 556 {
 557         return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
 558 }
 559 
 560 /*
 561  * A safe form of malloc() which will die if the allocation fails.
 562  */
 563 void *
 564 zfs_alloc(libzfs_handle_t *hdl, size_t size)
 565 {
 566         void *data;
 567 
 568         if ((data = calloc(1, size)) == NULL)
 569                 (void) no_memory(hdl);
 570 
 571         return (data);
 572 }
 573 
 574 /*
 575  * A safe form of asprintf() which will die if the allocation fails.
 576  */
 577 /*PRINTFLIKE2*/
 578 char *
 579 zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
 580 {
 581         va_list ap;
 582         char *ret;
 583         int err;
 584 
 585         va_start(ap, fmt);
 586 
 587         err = vasprintf(&ret, fmt, ap);
 588 
 589         va_end(ap);
 590 
 591         if (err < 0)
 592                 (void) no_memory(hdl);
 593 
 594         return (ret);
 595 }
 596 
 597 /*
 598  * A safe form of realloc(), which also zeroes newly allocated space.
 599  */
 600 void *
 601 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
 602 {
 603         void *ret;
 604 
 605         if ((ret = realloc(ptr, newsize)) == NULL) {
 606                 (void) no_memory(hdl);
 607                 return (NULL);
 608         }
 609 
 610         bzero((char *)ret + oldsize, (newsize - oldsize));
 611         return (ret);
 612 }
 613 
 614 /*
 615  * A safe form of strdup() which will die if the allocation fails.
 616  */
 617 char *
 618 zfs_strdup(libzfs_handle_t *hdl, const char *str)
 619 {
 620         char *ret;
 621 
 622         if ((ret = strdup(str)) == NULL)
 623                 (void) no_memory(hdl);
 624 
 625         return (ret);
 626 }
 627 
 628 /*
 629  * Convert a number to an appropriately human-readable output.
 630  */
 631 void
 632 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
 633 {
 634         nicenum(num, buf, buflen);
 635 }
 636 
 637 void
 638 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
 639 {
 640         hdl->libzfs_printerr = printerr;
 641 }
 642 
 643 libzfs_handle_t *
 644 libzfs_init(void)
 645 {
 646         libzfs_handle_t *hdl;
 647 
 648         if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
 649                 return (NULL);
 650         }
 651 
 652         if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
 653                 free(hdl);
 654                 return (NULL);
 655         }
 656 
 657         if ((hdl->libzfs_mnttab = fopen(MNTTAB, "rF")) == NULL) {
 658                 (void) close(hdl->libzfs_fd);
 659                 free(hdl);
 660                 return (NULL);
 661         }
 662 
 663         hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "rF");
 664 
 665         if (libzfs_core_init() != 0) {
 666                 (void) close(hdl->libzfs_fd);
 667                 (void) fclose(hdl->libzfs_mnttab);
 668                 (void) fclose(hdl->libzfs_sharetab);
 669                 free(hdl);
 670                 return (NULL);
 671         }
 672 
 673         zfs_prop_init();
 674         zpool_prop_init();
 675         zpool_feature_init();
 676         vdev_prop_init();
 677         cos_prop_init();
 678         libzfs_mnttab_init(hdl);
 679 
 680         if (getenv("ZFS_PROP_DEBUG") != NULL) {
 681                 hdl->libzfs_prop_debug = B_TRUE;
 682         }
 683 
 684         return (hdl);
 685 }
 686 
 687 void
 688 libzfs_fini(libzfs_handle_t *hdl)
 689 {
 690         (void) close(hdl->libzfs_fd);
 691         if (hdl->libzfs_mnttab)
 692                 (void) fclose(hdl->libzfs_mnttab);
 693         if (hdl->libzfs_sharetab)
 694                 (void) fclose(hdl->libzfs_sharetab);
 695         if (hdl->libzfs_log_str)
 696                 free(hdl->libzfs_log_str);
 697         zfs_uninit_libshare(hdl);
 698         zpool_free_handles(hdl);
 699         libzfs_fru_clear(hdl, B_TRUE);
 700         namespace_clear(hdl);
 701         libzfs_mnttab_fini(hdl);
 702         libzfs_core_fini();
 703         free(hdl);
 704 }
 705 
 706 libzfs_handle_t *
 707 zpool_get_handle(zpool_handle_t *zhp)
 708 {
 709         return (zhp->zpool_hdl);
 710 }
 711 
 712 libzfs_handle_t *
 713 zfs_get_handle(zfs_handle_t *zhp)
 714 {
 715         return (zhp->zfs_hdl);
 716 }
 717 
 718 zpool_handle_t *
 719 zfs_get_pool_handle(const zfs_handle_t *zhp)
 720 {
 721         return (zhp->zpool_hdl);
 722 }
 723 
 724 /*
 725  * Given a name, determine whether or not it's a valid path
 726  * (starts with '/' or "./").  If so, walk the mnttab trying
 727  * to match the device number.  If not, treat the path as an
 728  * fs/vol/snap/bkmark name.
 729  */
 730 zfs_handle_t *
 731 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
 732 {
 733         struct stat64 statbuf;
 734         struct extmnttab entry;
 735         int ret;
 736 
 737         if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
 738                 /*
 739                  * It's not a valid path, assume it's a name of type 'argtype'.
 740                  */
 741                 return (zfs_open(hdl, path, argtype));
 742         }
 743 
 744         if (stat64(path, &statbuf) != 0) {
 745                 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
 746                 return (NULL);
 747         }
 748 
 749         rewind(hdl->libzfs_mnttab);
 750         while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
 751                 if (makedevice(entry.mnt_major, entry.mnt_minor) ==
 752                     statbuf.st_dev) {
 753                         break;
 754                 }
 755         }
 756         if (ret != 0) {
 757                 return (NULL);
 758         }
 759 
 760         if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
 761                 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
 762                     path);
 763                 return (NULL);
 764         }
 765 
 766         return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
 767 }
 768 
 769 /*
 770  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
 771  * an ioctl().
 772  */
 773 int
 774 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
 775 {
 776         if (len == 0)
 777                 len = 16 * 1024;
 778         zc->zc_nvlist_dst_size = len;
 779         zc->zc_nvlist_dst =
 780             (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
 781         if (zc->zc_nvlist_dst == 0)
 782                 return (-1);
 783 
 784         return (0);
 785 }
 786 
 787 /*
 788  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
 789  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
 790  * filled in by the kernel to indicate the actual required size.
 791  */
 792 int
 793 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
 794 {
 795         free((void *)(uintptr_t)zc->zc_nvlist_dst);
 796         zc->zc_nvlist_dst =
 797             (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
 798         if (zc->zc_nvlist_dst == 0)
 799                 return (-1);
 800 
 801         return (0);
 802 }
 803 
 804 /*
 805  * Called to free the src and dst nvlists stored in the command structure.
 806  */
 807 void
 808 zcmd_free_nvlists(zfs_cmd_t *zc)
 809 {
 810         free((void *)(uintptr_t)zc->zc_nvlist_conf);
 811         free((void *)(uintptr_t)zc->zc_nvlist_src);
 812         free((void *)(uintptr_t)zc->zc_nvlist_dst);
 813         zc->zc_nvlist_conf = NULL;
 814         zc->zc_nvlist_src = NULL;
 815         zc->zc_nvlist_dst = NULL;
 816 }
 817 
 818 static int
 819 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
 820     nvlist_t *nvl)
 821 {
 822         char *packed;
 823         size_t len;
 824 
 825         verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
 826 
 827         if ((packed = zfs_alloc(hdl, len)) == NULL)
 828                 return (-1);
 829 
 830         verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
 831 
 832         *outnv = (uint64_t)(uintptr_t)packed;
 833         *outlen = len;
 834 
 835         return (0);
 836 }
 837 
 838 int
 839 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
 840 {
 841         return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
 842             &zc->zc_nvlist_conf_size, nvl));
 843 }
 844 
 845 int
 846 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
 847 {
 848         return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
 849             &zc->zc_nvlist_src_size, nvl));
 850 }
 851 
 852 /*
 853  * Unpacks an nvlist from the ZFS ioctl command structure.
 854  */
 855 int
 856 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
 857 {
 858         if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
 859             zc->zc_nvlist_dst_size, nvlp, 0) != 0)
 860                 return (no_memory(hdl));
 861 
 862         return (0);
 863 }
 864 
 865 #pragma weak libzfs_log_event = libzfs_log_event_stub
 866 
 867 /* ARGSUSED hdl zc */
 868 void
 869 libzfs_log_event_stub(libzfs_handle_t *hdl, const char *zc)
 870 {
 871 }
 872 
 873 int
 874 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
 875 {
 876         int error;
 877 
 878         error = ioctl(hdl->libzfs_fd, request, zc);
 879         if (error == 0)
 880                 libzfs_log_event(hdl, zc->zc_name);
 881 
 882         return (error);
 883 }
 884 
 885 /*
 886  * ================================================================
 887  * API shared by zfs and zpool property management
 888  * ================================================================
 889  */
 890 
 891 static void
 892 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
 893 {
 894         zprop_list_t *pl = cbp->cb_proplist;
 895         int i;
 896         char *title;
 897         size_t len;
 898 
 899         cbp->cb_first = B_FALSE;
 900         if (cbp->cb_scripted)
 901                 return;
 902 
 903         /*
 904          * Start with the length of the column headers.
 905          */
 906         cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
 907         cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
 908             "PROPERTY"));
 909         cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
 910             "VALUE"));
 911         cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
 912             "RECEIVED"));
 913         cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
 914             "SOURCE"));
 915 
 916         /* first property is always NAME */
 917         assert(cbp->cb_proplist->pl_prop ==
 918             ((type == ZFS_TYPE_POOL) ?  ZPOOL_PROP_NAME : ZFS_PROP_NAME));
 919 
 920         /*
 921          * Go through and calculate the widths for each column.  For the
 922          * 'source' column, we kludge it up by taking the worst-case scenario of
 923          * inheriting from the longest name.  This is acceptable because in the
 924          * majority of cases 'SOURCE' is the last column displayed, and we don't
 925          * use the width anyway.  Note that the 'VALUE' column can be oversized,
 926          * if the name of the property is much longer than any values we find.
 927          */
 928         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
 929                 /*
 930                  * 'PROPERTY' column
 931                  */
 932                 if (pl->pl_prop != ZPROP_INVAL) {
 933                         const char *propname = (type == ZFS_TYPE_POOL) ?
 934                             zpool_prop_to_name(pl->pl_prop) :
 935                             zfs_prop_to_name(pl->pl_prop);
 936 
 937                         len = strlen(propname);
 938                         if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
 939                                 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
 940                 } else {
 941                         len = strlen(pl->pl_user_prop);
 942                         if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
 943                                 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
 944                 }
 945 
 946                 /*
 947                  * 'VALUE' column.  The first property is always the 'name'
 948                  * property that was tacked on either by /sbin/zfs's
 949                  * zfs_do_get() or when calling zprop_expand_list(), so we
 950                  * ignore its width.  If the user specified the name property
 951                  * to display, then it will be later in the list in any case.
 952                  */
 953                 if (pl != cbp->cb_proplist &&
 954                     pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
 955                         cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
 956 
 957                 /* 'RECEIVED' column. */
 958                 if (pl != cbp->cb_proplist &&
 959                     pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
 960                         cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
 961 
 962                 /*
 963                  * 'NAME' and 'SOURCE' columns
 964                  */
 965                 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
 966                     ZFS_PROP_NAME) &&
 967                     pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
 968                         cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
 969                         cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
 970                             strlen(dgettext(TEXT_DOMAIN, "inherited from"));
 971                 }
 972         }
 973 
 974         /*
 975          * Now go through and print the headers.
 976          */
 977         for (i = 0; i < ZFS_GET_NCOLS; i++) {
 978                 switch (cbp->cb_columns[i]) {
 979                 case GET_COL_NAME:
 980                         title = dgettext(TEXT_DOMAIN, "NAME");
 981                         break;
 982                 case GET_COL_PROPERTY:
 983                         title = dgettext(TEXT_DOMAIN, "PROPERTY");
 984                         break;
 985                 case GET_COL_VALUE:
 986                         title = dgettext(TEXT_DOMAIN, "VALUE");
 987                         break;
 988                 case GET_COL_RECVD:
 989                         title = dgettext(TEXT_DOMAIN, "RECEIVED");
 990                         break;
 991                 case GET_COL_SOURCE:
 992                         title = dgettext(TEXT_DOMAIN, "SOURCE");
 993                         break;
 994                 default:
 995                         title = NULL;
 996                 }
 997 
 998                 if (title != NULL) {
 999                         if (i == (ZFS_GET_NCOLS - 1) ||
1000                             cbp->cb_columns[i + 1] == GET_COL_NONE)
1001                                 (void) printf("%s", title);
1002                         else
1003                                 (void) printf("%-*s  ",
1004                                     cbp->cb_colwidths[cbp->cb_columns[i]],
1005                                     title);
1006                 }
1007         }
1008         (void) printf("\n");
1009 }
1010 
1011 /*
1012  * Display a single line of output, according to the settings in the callback
1013  * structure.
1014  */
1015 void
1016 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
1017     const char *propname, const char *value, zprop_source_t sourcetype,
1018     const char *source, const char *recvd_value)
1019 {
1020         int i;
1021         const char *str = NULL;
1022         char buf[128];
1023 
1024         /*
1025          * Ignore those source types that the user has chosen to ignore.
1026          */
1027         if ((sourcetype & cbp->cb_sources) == 0)
1028                 return;
1029 
1030         if (cbp->cb_first)
1031                 zprop_print_headers(cbp, cbp->cb_type);
1032 
1033         for (i = 0; i < ZFS_GET_NCOLS; i++) {
1034                 switch (cbp->cb_columns[i]) {
1035                 case GET_COL_NAME:
1036                         str = name;
1037                         break;
1038 
1039                 case GET_COL_PROPERTY:
1040                         str = propname;
1041                         break;
1042 
1043                 case GET_COL_VALUE:
1044                         str = value;
1045                         break;
1046 
1047                 case GET_COL_SOURCE:
1048                         switch (sourcetype) {
1049                         case ZPROP_SRC_NONE:
1050                                 str = "-";
1051                                 break;
1052 
1053                         case ZPROP_SRC_DEFAULT:
1054                                 str = "default";
1055                                 break;
1056 
1057                         case ZPROP_SRC_LOCAL:
1058                                 str = "local";
1059                                 break;
1060 
1061                         case ZPROP_SRC_TEMPORARY:
1062                                 str = "temporary";
1063                                 break;
1064 
1065                         case ZPROP_SRC_INHERITED:
1066                                 (void) snprintf(buf, sizeof (buf),
1067                                     "inherited from %s", source);
1068                                 str = buf;
1069                                 break;
1070                         case ZPROP_SRC_RECEIVED:
1071                                 str = "received";
1072                                 break;
1073 
1074                         default:
1075                                 str = NULL;
1076                                 assert(!"unhandled zprop_source_t");
1077                         }
1078                         break;
1079 
1080                 case GET_COL_RECVD:
1081                         str = (recvd_value == NULL ? "-" : recvd_value);
1082                         break;
1083 
1084                 default:
1085                         continue;
1086                 }
1087 
1088                 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1089                         (void) printf("%s", str);
1090                 else if (cbp->cb_scripted)
1091                         (void) printf("%s\t", str);
1092                 else
1093                         (void) printf("%-*s  ",
1094                             cbp->cb_colwidths[cbp->cb_columns[i]],
1095                             str);
1096         }
1097 
1098         (void) printf("\n");
1099 }
1100 
1101 /*
1102  * Given a numeric suffix, convert the value into a number of bits that the
1103  * resulting value must be shifted.
1104  */
1105 static int
1106 str2shift(libzfs_handle_t *hdl, const char *buf)
1107 {
1108         const char *ends = "BKMGTPEZ";
1109         int i;
1110 
1111         if (buf[0] == '\0')
1112                 return (0);
1113         for (i = 0; i < strlen(ends); i++) {
1114                 if (toupper(buf[0]) == ends[i])
1115                         break;
1116         }
1117         if (i == strlen(ends)) {
1118                 if (hdl)
1119                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1120                             "invalid numeric suffix '%s'"), buf);
1121                 return (-1);
1122         }
1123 
1124         /*
1125          * We want to allow trailing 'b' characters for 'GB' or 'Mb'.  But don't
1126          * allow 'BB' - that's just weird.
1127          */
1128         if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1129             toupper(buf[0]) != 'B'))
1130                 return (10*i);
1131 
1132         if (hdl)
1133                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1134                     "invalid numeric suffix '%s'"), buf);
1135         return (-1);
1136 }
1137 
1138 /*
1139  * Convert a string of the form '100G' into a real number.  Used when setting
1140  * properties or creating a volume.  'buf' is used to place an extended error
1141  * message for the caller to use.
1142  */
1143 int
1144 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1145 {
1146         char *end;
1147         int shift;
1148 
1149         *num = 0;
1150 
1151         /* Check to see if this looks like a number.  */
1152         if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1153                 if (hdl)
1154                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1155                             "bad numeric value '%s'"), value);
1156                 return (-1);
1157         }
1158 
1159         /* Rely on strtoull() to process the numeric portion.  */
1160         errno = 0;
1161         *num = strtoull(value, &end, 10);
1162 
1163         /*
1164          * Check for ERANGE, which indicates that the value is too large to fit
1165          * in a 64-bit value.
1166          */
1167         if (errno == ERANGE) {
1168                 if (hdl)
1169                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1170                             "numeric value is too large"));
1171                 return (-1);
1172         }
1173 
1174         /*
1175          * If we have a decimal value, then do the computation with floating
1176          * point arithmetic.  Otherwise, use standard arithmetic.
1177          */
1178         if (*end == '.') {
1179                 double fval = strtod(value, &end);
1180 
1181                 if ((shift = str2shift(hdl, end)) == -1)
1182                         return (-1);
1183 
1184                 fval *= pow(2, shift);
1185 
1186                 if (fval > UINT64_MAX) {
1187                         if (hdl)
1188                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1189                                     "numeric value is too large"));
1190                         return (-1);
1191                 }
1192 
1193                 *num = (uint64_t)fval;
1194         } else {
1195                 if ((shift = str2shift(hdl, end)) == -1)
1196                         return (-1);
1197 
1198                 /* Check for overflow */
1199                 if (shift >= 64 || (*num << shift) >> shift != *num) {
1200                         if (hdl)
1201                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1202                                     "numeric value is too large"));
1203                         return (-1);
1204                 }
1205 
1206                 *num <<= shift;
1207         }
1208 
1209         return (0);
1210 }
1211 
1212 /*
1213  * Given a propname=value nvpair to set, parse any numeric properties
1214  * (index, boolean, etc) if they are specified as strings and add the
1215  * resulting nvpair to the returned nvlist.
1216  *
1217  * At the DSL layer, all properties are either 64-bit numbers or strings.
1218  * We want the user to be able to ignore this fact and specify properties
1219  * as native values (numbers, for example) or as strings (to simplify
1220  * command line utilities).  This also handles converting index types
1221  * (compression, checksum, etc) from strings to their on-disk index.
1222  */
1223 int
1224 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1225     zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1226     const char *errbuf)
1227 {
1228         data_type_t datatype = nvpair_type(elem);
1229         zprop_type_t proptype;
1230         const char *propname;
1231         char *value;
1232         boolean_t isnone = B_FALSE;
1233 
1234         switch (type) {
1235         case ZFS_TYPE_POOL:
1236                 proptype = zpool_prop_get_type(prop);
1237                 propname = zpool_prop_to_name(prop);
1238                 break;
1239         case ZFS_TYPE_VDEV:
1240                 proptype = vdev_prop_get_type(prop);
1241                 propname = vdev_prop_to_name(prop);
1242                 break;
1243         case ZFS_TYPE_COS:
1244                 proptype = cos_prop_get_type(prop);
1245                 propname = cos_prop_to_name(prop);
1246                 break;
1247         default:
1248                 proptype = zfs_prop_get_type(prop);
1249                 propname = zfs_prop_to_name(prop);
1250         }
1251 
1252         /*
1253          * Convert any properties to the internal DSL value types.
1254          */
1255         *svalp = NULL;
1256         *ivalp = 0;
1257 
1258         switch (proptype) {
1259         case PROP_TYPE_STRING:
1260                 if (datatype != DATA_TYPE_STRING) {
1261                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1262                             "'%s' must be a string"), nvpair_name(elem));
1263                         goto error;
1264                 }
1265                 (void) nvpair_value_string(elem, svalp);
1266                 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1267                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1268                             "'%s' is too long"), nvpair_name(elem));
1269                         goto error;
1270                 }
1271                 break;
1272 
1273         case PROP_TYPE_NUMBER:
1274                 if (datatype == DATA_TYPE_STRING) {
1275                         (void) nvpair_value_string(elem, &value);
1276                         if (strcmp(value, "none") == 0) {
1277                                 isnone = B_TRUE;
1278                         } else if (zfs_nicestrtonum(hdl, value, ivalp)
1279                             != 0) {
1280                                 goto error;
1281                         }
1282                 } else if (datatype == DATA_TYPE_UINT64) {
1283                         (void) nvpair_value_uint64(elem, ivalp);
1284                 } else {
1285                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1286                             "'%s' must be a number"), nvpair_name(elem));
1287                         goto error;
1288                 }
1289 
1290                 /*
1291                  * Quota special: force 'none' and don't allow 0.
1292                  */
1293                 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1294                     (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1295                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1296                             "use 'none' to disable quota/refquota"));
1297                         goto error;
1298                 }
1299 
1300                 /*
1301                  * Special handling for "*_limit=none". In this case it's not
1302                  * 0 but UINT64_MAX.
1303                  */
1304                 if ((type & ZFS_TYPE_DATASET) && isnone &&
1305                     (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
1306                     prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
1307                         *ivalp = UINT64_MAX;
1308                 }
1309                 break;
1310 
1311         case PROP_TYPE_INDEX:
1312                 if (datatype != DATA_TYPE_STRING) {
1313                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1314                             "'%s' must be a string"), nvpair_name(elem));
1315                         goto error;
1316                 }
1317 
1318                 (void) nvpair_value_string(elem, &value);
1319 
1320                 if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1321                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1322                             "'%s' must be one of '%s'"), propname,
1323                             zprop_values(prop, type));
1324                         goto error;
1325                 }
1326                 break;
1327 
1328         default:
1329                 abort();
1330         }
1331 
1332         /*
1333          * Add the result to our return set of properties.
1334          */
1335         if (*svalp != NULL) {
1336                 if (nvlist_add_string(ret, propname, *svalp) != 0) {
1337                         (void) no_memory(hdl);
1338                         return (-1);
1339                 }
1340         } else {
1341                 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1342                         (void) no_memory(hdl);
1343                         return (-1);
1344                 }
1345         }
1346 
1347         return (0);
1348 error:
1349         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1350         return (-1);
1351 }
1352 
1353 static int
1354 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1355     zfs_type_t type)
1356 {
1357         int prop;
1358         zprop_list_t *entry;
1359 
1360         prop = zprop_name_to_prop(propname, type);
1361 
1362         if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1363                 prop = ZPROP_INVAL;
1364 
1365         /*
1366          * When no property table entry can be found, return failure if
1367          * this is a pool property or if this isn't a user-defined
1368          * dataset property,
1369          */
1370         if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1371             !zpool_prop_feature(propname) &&
1372             !zpool_prop_unsupported(propname)) ||
1373             (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
1374             !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1375                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1376                     "invalid property '%s'"), propname);
1377                 return (zfs_error(hdl, EZFS_BADPROP,
1378                     dgettext(TEXT_DOMAIN, "bad property list")));
1379         }
1380 
1381         if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1382                 return (-1);
1383 
1384         entry->pl_prop = prop;
1385         if (prop == ZPROP_INVAL) {
1386                 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
1387                     NULL) {
1388                         free(entry);
1389                         return (-1);
1390                 }
1391                 entry->pl_width = strlen(propname);
1392         } else {
1393                 entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1394                     type);
1395         }
1396 
1397         *listp = entry;
1398 
1399         return (0);
1400 }
1401 
1402 /*
1403  * Given a comma-separated list of properties, construct a property list
1404  * containing both user-defined and native properties.  This function will
1405  * return a NULL list if 'all' is specified, which can later be expanded
1406  * by zprop_expand_list().
1407  */
1408 int
1409 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1410     zfs_type_t type)
1411 {
1412         *listp = NULL;
1413 
1414         /*
1415          * If 'all' is specified, return a NULL list.
1416          */
1417         if (strcmp(props, "all") == 0)
1418                 return (0);
1419 
1420         /*
1421          * If no props were specified, return an error.
1422          */
1423         if (props[0] == '\0') {
1424                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1425                     "no properties specified"));
1426                 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1427                     "bad property list")));
1428         }
1429 
1430         /*
1431          * It would be nice to use getsubopt() here, but the inclusion of column
1432          * aliases makes this more effort than it's worth.
1433          */
1434         while (*props != '\0') {
1435                 size_t len;
1436                 char *p;
1437                 char c;
1438 
1439                 if ((p = strchr(props, ',')) == NULL) {
1440                         len = strlen(props);
1441                         p = props + len;
1442                 } else {
1443                         len = p - props;
1444                 }
1445 
1446                 /*
1447                  * Check for empty options.
1448                  */
1449                 if (len == 0) {
1450                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1451                             "empty property name"));
1452                         return (zfs_error(hdl, EZFS_BADPROP,
1453                             dgettext(TEXT_DOMAIN, "bad property list")));
1454                 }
1455 
1456                 /*
1457                  * Check all regular property names.
1458                  */
1459                 c = props[len];
1460                 props[len] = '\0';
1461 
1462                 if (strcmp(props, "space") == 0) {
1463                         static char *spaceprops[] = {
1464                                 "name", "avail", "used", "usedbysnapshots",
1465                                 "usedbydataset", "usedbyrefreservation",
1466                                 "usedbychildren", NULL
1467                         };
1468                         int i;
1469 
1470                         for (i = 0; spaceprops[i]; i++) {
1471                                 if (addlist(hdl, spaceprops[i], listp, type))
1472                                         return (-1);
1473                                 listp = &(*listp)->pl_next;
1474                         }
1475                 } else {
1476                         if (addlist(hdl, props, listp, type))
1477                                 return (-1);
1478                         listp = &(*listp)->pl_next;
1479                 }
1480 
1481                 props = p;
1482                 if (c == ',')
1483                         props++;
1484         }
1485 
1486         return (0);
1487 }
1488 
1489 void
1490 zprop_free_list(zprop_list_t *pl)
1491 {
1492         zprop_list_t *next;
1493 
1494         while (pl != NULL) {
1495                 next = pl->pl_next;
1496                 free(pl->pl_user_prop);
1497                 free(pl);
1498                 pl = next;
1499         }
1500 }
1501 
1502 typedef struct expand_data {
1503         zprop_list_t    **last;
1504         libzfs_handle_t *hdl;
1505         zfs_type_t type;
1506 } expand_data_t;
1507 
1508 int
1509 zprop_expand_list_cb(int prop, void *cb)
1510 {
1511         zprop_list_t *entry;
1512         expand_data_t *edp = cb;
1513 
1514         if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1515                 return (ZPROP_INVAL);
1516 
1517         entry->pl_prop = prop;
1518         entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1519         entry->pl_all = B_TRUE;
1520 
1521         *(edp->last) = entry;
1522         edp->last = &entry->pl_next;
1523 
1524         return (ZPROP_CONT);
1525 }
1526 
1527 int
1528 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1529 {
1530         zprop_list_t *entry;
1531         zprop_list_t **last;
1532         expand_data_t exp;
1533 
1534         if (*plp == NULL) {
1535                 /*
1536                  * If this is the very first time we've been called for an 'all'
1537                  * specification, expand the list to include all native
1538                  * properties.
1539                  */
1540                 last = plp;
1541 
1542                 exp.last = last;
1543                 exp.hdl = hdl;
1544                 exp.type = type;
1545 
1546                 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1547                     B_FALSE, type) == ZPROP_INVAL)
1548                         return (-1);
1549 
1550                 /*
1551                  * Add 'name' to the beginning of the list, which is handled
1552                  * specially.
1553                  */
1554                 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1555                         return (-1);
1556 
1557                 entry->pl_prop = (type == ZFS_TYPE_POOL) ?  ZPOOL_PROP_NAME :
1558                     ZFS_PROP_NAME;
1559                 entry->pl_width = zprop_width(entry->pl_prop,
1560                     &entry->pl_fixed, type);
1561                 entry->pl_all = B_TRUE;
1562                 entry->pl_next = *plp;
1563                 *plp = entry;
1564         }
1565         return (0);
1566 }
1567 
1568 int
1569 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1570     zfs_type_t type)
1571 {
1572         return (zprop_iter_common(func, cb, show_all, ordered, type));
1573 }
1574 
1575 int
1576 vdev_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp)
1577 {
1578         *listp = NULL;
1579 
1580         /*
1581          * If 'all' is specified, return a NULL list.
1582          */
1583         if (strcmp(props, "all") == 0) {
1584                 vdev_prop_t prop;
1585                 for (prop = VDEV_PROP_PATH; prop < VDEV_NUM_PROPS; prop++) {
1586                         const char *propname = vdev_prop_to_name(prop);
1587                         if (addlist(hdl, (char *)propname, listp,
1588                             ZFS_TYPE_VDEV))
1589                                 return (-1);
1590                         listp = &(*listp)->pl_next;
1591                 }
1592 
1593                 return (0);
1594         }
1595 
1596         /*
1597          * If no props were specified, return an error.
1598          */
1599         if (props[0] == '\0') {
1600                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1601                     "no properties specified"));
1602                 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1603                     "bad property list")));
1604         }
1605 
1606         /*
1607          * It would be nice to use getsubopt() here, but the inclusion of column
1608          * aliases makes this more effort than it's worth.
1609          */
1610         while (*props != '\0') {
1611                 size_t len;
1612                 char *p;
1613                 char c;
1614 
1615                 if ((p = strchr(props, ',')) == NULL) {
1616                         len = strlen(props);
1617                         p = props + len;
1618                 } else {
1619                         len = p - props;
1620                 }
1621 
1622                 /*
1623                  * Check for empty options.
1624                  */
1625                 if (len == 0) {
1626                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1627                             "empty property name"));
1628                         return (zfs_error(hdl, EZFS_BADPROP,
1629                             dgettext(TEXT_DOMAIN, "bad property list")));
1630                 }
1631 
1632                 /*
1633                  * Check all regular property names.
1634                  */
1635                 c = props[len];
1636                 props[len] = '\0';
1637 
1638                 /*
1639                  * Make sure we're looking at a valid prop.
1640                  */
1641                 if (vdev_name_to_prop(props) == ZPROP_INVAL) {
1642                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1643                             "invalid property '%s'"), props);
1644                         return (zfs_error(hdl, EZFS_BADPROP,
1645                             dgettext(TEXT_DOMAIN, "bad property list")));
1646                 }
1647 
1648                 if (addlist(hdl, props, listp, ZFS_TYPE_VDEV))
1649                         return (-1);
1650                 listp = &(*listp)->pl_next;
1651 
1652                 props = p;
1653                 if (c == ',')
1654                         props++;
1655         }
1656 
1657         return (0);
1658 }
1659 
1660 int
1661 cos_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp)
1662 {
1663         *listp = NULL;
1664 
1665         /*
1666          * If 'all' is specified, return a NULL list.
1667          */
1668         if (strcmp(props, "all") == 0) {
1669                 cos_prop_t prop;
1670                 for (prop = COS_PROP_GUID; prop < COS_NUM_PROPS; prop++) {
1671                         const char *propname = cos_prop_to_name(prop);
1672                         if (addlist(hdl, (char *)propname, listp,
1673                             ZFS_TYPE_COS))
1674                                 return (-1);
1675                         listp = &(*listp)->pl_next;
1676                 }
1677 
1678                 return (0);
1679         }
1680 
1681         /*
1682          * If no props were specified, return an error.
1683          */
1684         if (props[0] == '\0') {
1685                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1686                     "no properties specified"));
1687                 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1688                     "bad property list")));
1689         }
1690 
1691         /*
1692          * It would be nice to use getsubopt() here, but the inclusion of column
1693          * aliases makes this more effort than it's worth.
1694          */
1695         while (*props != '\0') {
1696                 size_t len;
1697                 char *p;
1698                 char c;
1699 
1700                 if ((p = strchr(props, ',')) == NULL) {
1701                         len = strlen(props);
1702                         p = props + len;
1703                 } else {
1704                         len = p - props;
1705                 }
1706 
1707                 /*
1708                  * Check for empty options.
1709                  */
1710                 if (len == 0) {
1711                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1712                             "empty property name"));
1713                         return (zfs_error(hdl, EZFS_BADPROP,
1714                             dgettext(TEXT_DOMAIN, "bad property list")));
1715                 }
1716 
1717                 /*
1718                  * Check all regular property names.
1719                  */
1720                 c = props[len];
1721                 props[len] = '\0';
1722 
1723                 if (addlist(hdl, props, listp, ZFS_TYPE_COS))
1724                         return (-1);
1725                 listp = &(*listp)->pl_next;
1726 
1727                 props = p;
1728                 if (c == ',')
1729                         props++;
1730         }
1731 
1732         return (0);
1733 }
1734 
1735 void
1736 vdev_print_headers(zprop_get_cbdata_t *cbp)
1737 {
1738         zprop_list_t *pl = cbp->cb_proplist;
1739         int i;
1740         char *title;
1741         size_t len;
1742 
1743         cbp->cb_first = B_FALSE;
1744         if (cbp->cb_scripted)
1745                 return;
1746 
1747         /*
1748          * Start with the length of the column headers.
1749          */
1750         cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN,
1751             "POOLNAME"));
1752         cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
1753             "c0t0d0s0"));
1754         cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
1755             "PROPERTY"));
1756         cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
1757             "VALUE"));
1758 
1759         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
1760                 /*
1761                  * 'PROPERTY' column
1762                  */
1763                 const char *propname = vdev_prop_to_name(pl->pl_prop);
1764 
1765                 len = strlen(propname);
1766                 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
1767                         cbp->cb_colwidths[GET_COL_PROPERTY] = len;
1768 
1769                 /*
1770                  * 'VALUE' column.
1771                  */
1772                 if (pl != cbp->cb_proplist &&
1773                     pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
1774                         cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
1775 
1776                 /*
1777                  * 'NAME'
1778                  */
1779                 if (pl->pl_prop == 0 &&
1780                     pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
1781                         cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
1782                 }
1783                 /*
1784                  * 'SOURCE'
1785                  */
1786                 if (pl->pl_prop == 0 &&
1787                     pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) {
1788                         cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width;
1789                 }
1790         }
1791 
1792         /*
1793          * Now go through and print the headers.
1794          */
1795         for (i = 0; i < ZFS_GET_NCOLS-1; i++) {
1796                 switch (cbp->cb_columns[i]) {
1797                 case GET_COL_NAME:
1798                         title = dgettext(TEXT_DOMAIN, "POOLNAME");
1799                         break;
1800                 case GET_COL_SOURCE:
1801                         title = dgettext(TEXT_DOMAIN, "VDEV");
1802                         break;
1803                 case GET_COL_PROPERTY:
1804                         title = dgettext(TEXT_DOMAIN, "PROPERTY");
1805                         break;
1806                 case GET_COL_VALUE:
1807                         title = dgettext(TEXT_DOMAIN, "VALUE");
1808                         break;
1809                 default:
1810                         title = NULL;
1811                 }
1812 
1813                 if (title != NULL) {
1814                         if (i == (ZFS_GET_NCOLS - 1) ||
1815                             cbp->cb_columns[i + 1] == GET_COL_NONE)
1816                                 (void) printf("%s", title);
1817                         else
1818                                 (void) printf("%-*s  ",
1819                                     cbp->cb_colwidths[cbp->cb_columns[i]],
1820                                     title);
1821                 }
1822         }
1823         (void) printf("\n");
1824 }
1825 
1826 void
1827 cos_print_headers(zprop_get_cbdata_t *cbp)
1828 {
1829         zprop_list_t *pl = cbp->cb_proplist;
1830         int i;
1831         char *title;
1832         size_t len;
1833 
1834         cbp->cb_first = B_FALSE;
1835         if (cbp->cb_scripted)
1836                 return;
1837 
1838         /*
1839          * Start with the length of the column headers.
1840          */
1841         cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN,
1842             "POOLNAME"));
1843         cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
1844             "c0t0d0s0"));
1845         cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
1846             "PROPERTY"));
1847         cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
1848             "VALUE"));
1849 
1850         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
1851                 /*
1852                  * 'PROPERTY' column
1853                  */
1854                 const char *propname = cos_prop_to_name(pl->pl_prop);
1855 
1856                 len = strlen(propname);
1857                 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
1858                         cbp->cb_colwidths[GET_COL_PROPERTY] = len;
1859 
1860                 /*
1861                  * 'VALUE' column.
1862                  */
1863                 if (pl != cbp->cb_proplist &&
1864                     pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
1865                         cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
1866 
1867                 /*
1868                  * 'NAME'
1869                  */
1870                 if (pl->pl_prop == 0 &&
1871                     pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
1872                         cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
1873                 }
1874                 /*
1875                  * 'SOURCE'
1876                  */
1877                 if (pl->pl_prop == 0 &&
1878                     pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) {
1879                         cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width;
1880                 }
1881         }
1882 
1883         /*
1884          * Now go through and print the headers.
1885          */
1886         for (i = 0; i < ZFS_GET_NCOLS-1; i++) {
1887                 switch (cbp->cb_columns[i]) {
1888                 case GET_COL_NAME:
1889                         title = dgettext(TEXT_DOMAIN, "POOLNAME");
1890                         break;
1891                 case GET_COL_SOURCE:
1892                         title = dgettext(TEXT_DOMAIN, "COS");
1893                         break;
1894                 case GET_COL_PROPERTY:
1895                         title = dgettext(TEXT_DOMAIN, "PROPERTY");
1896                         break;
1897                 case GET_COL_VALUE:
1898                         title = dgettext(TEXT_DOMAIN, "VALUE");
1899                         break;
1900                 default:
1901                         title = NULL;
1902                 }
1903 
1904                 if (title != NULL) {
1905                         if (i == (ZFS_GET_NCOLS - 1) ||
1906                             cbp->cb_columns[i + 1] == GET_COL_NONE)
1907                                 (void) printf("%s", title);
1908                         else
1909                                 (void) printf("%-*s  ",
1910                                     cbp->cb_colwidths[cbp->cb_columns[i]],
1911                                     title);
1912                 }
1913         }
1914         (void) printf("\n");
1915 }
1916 
1917 void
1918 vdev_print_one_property(const char *poolname, const char *vdevname,
1919     zprop_get_cbdata_t *cbp, const char *propname, const char *value)
1920 {
1921         int i;
1922         const char *str;
1923 
1924         if (cbp->cb_first)
1925                 vdev_print_headers(cbp);
1926 
1927         for (i = 0; i < ZFS_GET_NCOLS; i++) {
1928                 switch (cbp->cb_columns[i]) {
1929                 case GET_COL_NAME:
1930                         str = poolname;
1931                         break;
1932 
1933                 case GET_COL_SOURCE:
1934                         str = vdevname;
1935                         break;
1936 
1937                 case GET_COL_PROPERTY:
1938                         str = propname;
1939                         break;
1940 
1941                 case GET_COL_VALUE:
1942                         str = value;
1943                         break;
1944 
1945                 default:
1946                         continue;
1947                 }
1948 
1949                 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1950                         (void) printf("%s", str);
1951                 else if (cbp->cb_scripted)
1952                         (void) printf("%s\t", str);
1953                 else
1954                         (void) printf("%-*s  ",
1955                             cbp->cb_colwidths[cbp->cb_columns[i]],
1956                             str);
1957         }
1958 
1959         (void) printf("\n");
1960 }
1961 
1962 void
1963 cos_print_one_property(const char *poolname, const char *cosname,
1964     zprop_get_cbdata_t *cbp, const char *propname, const char *value)
1965 {
1966         int i;
1967         const char *str;
1968 
1969         if (cbp->cb_first)
1970                 cos_print_headers(cbp);
1971 
1972         for (i = 0; i < ZFS_GET_NCOLS; i++) {
1973                 switch (cbp->cb_columns[i]) {
1974                 case GET_COL_NAME:
1975                         str = poolname;
1976                         break;
1977 
1978                 case GET_COL_SOURCE:
1979                         str = cosname;
1980                         break;
1981 
1982                 case GET_COL_PROPERTY:
1983                         str = propname;
1984                         break;
1985 
1986                 case GET_COL_VALUE:
1987                         str = value;
1988                         break;
1989 
1990                 default:
1991                         continue;
1992                 }
1993 
1994                 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1995                         (void) printf("%s", str);
1996                 else if (cbp->cb_scripted)
1997                         (void) printf("%s\t", str);
1998                 else
1999                         (void) printf("%-*s  ",
2000                             cbp->cb_colwidths[cbp->cb_columns[i]],
2001                             str);
2002         }
2003 
2004         (void) printf("\n");
2005 }
2006 
2007 /*
2008  * zfs_get_hole_count retrieves the number of holes (blocks which are
2009  * zero-filled) in the specified file using the _FIO_COUNT_FILLED ioctl. It
2010  * also optionally fetches the block size when bs is non-NULL. With hole count
2011  * and block size the full space consumed by the holes of a file can be
2012  * calculated.
2013  *
2014  * On success, zero is returned, the count argument is set to the
2015  * number of holes, and the bs argument is set to the block size (if it is
2016  * not NULL). On error, a non-zero errno is returned and the values in count
2017  * and bs are undefined.
2018  */
2019 int
2020 zfs_get_hole_count(const char *path, uint64_t *count, uint64_t *bs)
2021 {
2022         int fd, err;
2023         struct stat64 ss;
2024         uint64_t fill;
2025 
2026         fd = open(path, O_RDONLY | O_LARGEFILE);
2027         if (fd == -1)
2028                 return (errno);
2029 
2030         if (ioctl(fd, _FIO_COUNT_FILLED, &fill) == -1) {
2031                 err = errno;
2032                 (void) close(fd);
2033                 return (err);
2034         }
2035 
2036         if (fstat64(fd, &ss) == -1) {
2037                 err = errno;
2038                 (void) close(fd);
2039                 return (err);
2040         }
2041 
2042         *count = (ss.st_size + ss.st_blksize - 1) / ss.st_blksize - fill;
2043         VERIFY3S(*count, >=, 0);
2044         if (bs != NULL) {
2045                 *bs = ss.st_blksize;
2046         }
2047 
2048         if (close(fd) == -1) {
2049                 return (errno);
2050         }
2051         return (0);
2052 }