1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21236884Smm 22168404Spjd/* 23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24265744Sdelphij * Copyright (c) 2013, Joyent, Inc. All rights reserved. 25236884Smm * Copyright (c) 2012 by Delphix. All rights reserved. 26168404Spjd */ 27168404Spjd 28168404Spjd/* 29168404Spjd * Internal utility routines for the ZFS library. 30168404Spjd */ 31168404Spjd 32219089Spjd#include <sys/param.h> 33219089Spjd#include <sys/linker.h> 34219089Spjd#include <sys/module.h> 35219089Spjd#include <sys/stat.h> 36219089Spjd 37168404Spjd#include <errno.h> 38168404Spjd#include <fcntl.h> 39168404Spjd#include <libintl.h> 40168404Spjd#include <stdarg.h> 41168404Spjd#include <stdio.h> 42168404Spjd#include <stdlib.h> 43168404Spjd#include <strings.h> 44168404Spjd#include <unistd.h> 45185029Spjd#include <ctype.h> 46185029Spjd#include <math.h> 47168404Spjd#include <sys/mnttab.h> 48168404Spjd#include <sys/mntent.h> 49168404Spjd#include <sys/types.h> 50168404Spjd 51168404Spjd#include <libzfs.h> 52248571Smm#include <libzfs_core.h> 53168404Spjd 54168404Spjd#include "libzfs_impl.h" 55185029Spjd#include "zfs_prop.h" 56236884Smm#include "zfeature_common.h" 57168404Spjd 58219089Spjdint aok; 59219089Spjd 60168404Spjdint 61168404Spjdlibzfs_errno(libzfs_handle_t *hdl) 62168404Spjd{ 63168404Spjd return (hdl->libzfs_error); 64168404Spjd} 65168404Spjd 66168404Spjdconst char * 67168404Spjdlibzfs_error_action(libzfs_handle_t *hdl) 68168404Spjd{ 69168404Spjd return (hdl->libzfs_action); 70168404Spjd} 71168404Spjd 72168404Spjdconst char * 73168404Spjdlibzfs_error_description(libzfs_handle_t *hdl) 74168404Spjd{ 75168404Spjd if (hdl->libzfs_desc[0] != '\0') 76168404Spjd return (hdl->libzfs_desc); 77168404Spjd 78168404Spjd switch (hdl->libzfs_error) { 79168404Spjd case EZFS_NOMEM: 80168404Spjd return (dgettext(TEXT_DOMAIN, "out of memory")); 81168404Spjd case EZFS_BADPROP: 82168404Spjd return (dgettext(TEXT_DOMAIN, "invalid property value")); 83168404Spjd case EZFS_PROPREADONLY: 84219089Spjd return (dgettext(TEXT_DOMAIN, "read-only property")); 85168404Spjd case EZFS_PROPTYPE: 86168404Spjd return (dgettext(TEXT_DOMAIN, "property doesn't apply to " 87168404Spjd "datasets of this type")); 88168404Spjd case EZFS_PROPNONINHERIT: 89168404Spjd return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); 90168404Spjd case EZFS_PROPSPACE: 91168404Spjd return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); 92168404Spjd case EZFS_BADTYPE: 93168404Spjd return (dgettext(TEXT_DOMAIN, "operation not applicable to " 94168404Spjd "datasets of this type")); 95168404Spjd case EZFS_BUSY: 96168404Spjd return (dgettext(TEXT_DOMAIN, "pool or dataset is busy")); 97168404Spjd case EZFS_EXISTS: 98168404Spjd return (dgettext(TEXT_DOMAIN, "pool or dataset exists")); 99168404Spjd case EZFS_NOENT: 100168404Spjd return (dgettext(TEXT_DOMAIN, "no such pool or dataset")); 101168404Spjd case EZFS_BADSTREAM: 102168404Spjd return (dgettext(TEXT_DOMAIN, "invalid backup stream")); 103168404Spjd case EZFS_DSREADONLY: 104219089Spjd return (dgettext(TEXT_DOMAIN, "dataset is read-only")); 105168404Spjd case EZFS_VOLTOOBIG: 106168404Spjd return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for " 107168404Spjd "this system")); 108168404Spjd case EZFS_INVALIDNAME: 109168404Spjd return (dgettext(TEXT_DOMAIN, "invalid name")); 110168404Spjd case EZFS_BADRESTORE: 111168404Spjd return (dgettext(TEXT_DOMAIN, "unable to restore to " 112168404Spjd "destination")); 113168404Spjd case EZFS_BADBACKUP: 114168404Spjd return (dgettext(TEXT_DOMAIN, "backup failed")); 115168404Spjd case EZFS_BADTARGET: 116168404Spjd return (dgettext(TEXT_DOMAIN, "invalid target vdev")); 117168404Spjd case EZFS_NODEVICE: 118168404Spjd return (dgettext(TEXT_DOMAIN, "no such device in pool")); 119168404Spjd case EZFS_BADDEV: 120168404Spjd return (dgettext(TEXT_DOMAIN, "invalid device")); 121168404Spjd case EZFS_NOREPLICAS: 122168404Spjd return (dgettext(TEXT_DOMAIN, "no valid replicas")); 123168404Spjd case EZFS_RESILVERING: 124168404Spjd return (dgettext(TEXT_DOMAIN, "currently resilvering")); 125168404Spjd case EZFS_BADVERSION: 126236884Smm return (dgettext(TEXT_DOMAIN, "unsupported version or " 127236884Smm "feature")); 128168404Spjd case EZFS_POOLUNAVAIL: 129168404Spjd return (dgettext(TEXT_DOMAIN, "pool is unavailable")); 130168404Spjd case EZFS_DEVOVERFLOW: 131168404Spjd return (dgettext(TEXT_DOMAIN, "too many devices in one vdev")); 132168404Spjd case EZFS_BADPATH: 133168404Spjd return (dgettext(TEXT_DOMAIN, "must be an absolute path")); 134168404Spjd case EZFS_CROSSTARGET: 135168404Spjd return (dgettext(TEXT_DOMAIN, "operation crosses datasets or " 136168404Spjd "pools")); 137168404Spjd case EZFS_ZONED: 138168404Spjd return (dgettext(TEXT_DOMAIN, "dataset in use by local zone")); 139168404Spjd case EZFS_MOUNTFAILED: 140168404Spjd return (dgettext(TEXT_DOMAIN, "mount failed")); 141168404Spjd case EZFS_UMOUNTFAILED: 142168404Spjd return (dgettext(TEXT_DOMAIN, "umount failed")); 143168404Spjd case EZFS_UNSHARENFSFAILED: 144168404Spjd return (dgettext(TEXT_DOMAIN, "unshare(1M) failed")); 145168404Spjd case EZFS_SHARENFSFAILED: 146168404Spjd return (dgettext(TEXT_DOMAIN, "share(1M) failed")); 147185029Spjd case EZFS_UNSHARESMBFAILED: 148185029Spjd return (dgettext(TEXT_DOMAIN, "smb remove share failed")); 149185029Spjd case EZFS_SHARESMBFAILED: 150185029Spjd return (dgettext(TEXT_DOMAIN, "smb add share failed")); 151168404Spjd case EZFS_PERM: 152168404Spjd return (dgettext(TEXT_DOMAIN, "permission denied")); 153168404Spjd case EZFS_NOSPC: 154168404Spjd return (dgettext(TEXT_DOMAIN, "out of space")); 155219089Spjd case EZFS_FAULT: 156219089Spjd return (dgettext(TEXT_DOMAIN, "bad address")); 157168404Spjd case EZFS_IO: 158168404Spjd return (dgettext(TEXT_DOMAIN, "I/O error")); 159168404Spjd case EZFS_INTR: 160168404Spjd return (dgettext(TEXT_DOMAIN, "signal received")); 161168404Spjd case EZFS_ISSPARE: 162168404Spjd return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " 163168404Spjd "spare")); 164168404Spjd case EZFS_INVALCONFIG: 165168404Spjd return (dgettext(TEXT_DOMAIN, "invalid vdev configuration")); 166168404Spjd case EZFS_RECURSIVE: 167168404Spjd return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); 168168404Spjd case EZFS_NOHISTORY: 169168404Spjd return (dgettext(TEXT_DOMAIN, "no history available")); 170168404Spjd case EZFS_POOLPROPS: 171168404Spjd return (dgettext(TEXT_DOMAIN, "failed to retrieve " 172168404Spjd "pool properties")); 173168404Spjd case EZFS_POOL_NOTSUP: 174168404Spjd return (dgettext(TEXT_DOMAIN, "operation not supported " 175168404Spjd "on this type of pool")); 176168404Spjd case EZFS_POOL_INVALARG: 177168404Spjd return (dgettext(TEXT_DOMAIN, "invalid argument for " 178168404Spjd "this pool operation")); 179168498Spjd case EZFS_NAMETOOLONG: 180168498Spjd return (dgettext(TEXT_DOMAIN, "dataset name is too long")); 181185029Spjd case EZFS_OPENFAILED: 182185029Spjd return (dgettext(TEXT_DOMAIN, "open failed")); 183185029Spjd case EZFS_NOCAP: 184185029Spjd return (dgettext(TEXT_DOMAIN, 185185029Spjd "disk capacity information could not be retrieved")); 186185029Spjd case EZFS_LABELFAILED: 187185029Spjd return (dgettext(TEXT_DOMAIN, "write of label failed")); 188185029Spjd case EZFS_BADWHO: 189185029Spjd return (dgettext(TEXT_DOMAIN, "invalid user/group")); 190185029Spjd case EZFS_BADPERM: 191185029Spjd return (dgettext(TEXT_DOMAIN, "invalid permission")); 192185029Spjd case EZFS_BADPERMSET: 193185029Spjd return (dgettext(TEXT_DOMAIN, "invalid permission set name")); 194185029Spjd case EZFS_NODELEGATION: 195185029Spjd return (dgettext(TEXT_DOMAIN, "delegated administration is " 196185029Spjd "disabled on pool")); 197185029Spjd case EZFS_BADCACHE: 198185029Spjd return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); 199185029Spjd case EZFS_ISL2CACHE: 200185029Spjd return (dgettext(TEXT_DOMAIN, "device is in use as a cache")); 201185029Spjd case EZFS_VDEVNOTSUP: 202185029Spjd return (dgettext(TEXT_DOMAIN, "vdev specification is not " 203185029Spjd "supported")); 204185029Spjd case EZFS_NOTSUP: 205185029Spjd return (dgettext(TEXT_DOMAIN, "operation not supported " 206185029Spjd "on this dataset")); 207185029Spjd case EZFS_ACTIVE_SPARE: 208185029Spjd return (dgettext(TEXT_DOMAIN, "pool has active shared spare " 209185029Spjd "device")); 210213197Smm case EZFS_UNPLAYED_LOGS: 211213197Smm return (dgettext(TEXT_DOMAIN, "log device has unplayed intent " 212213197Smm "logs")); 213219089Spjd case EZFS_REFTAG_RELE: 214219089Spjd return (dgettext(TEXT_DOMAIN, "no such tag on this dataset")); 215219089Spjd case EZFS_REFTAG_HOLD: 216219089Spjd return (dgettext(TEXT_DOMAIN, "tag already exists on this " 217219089Spjd "dataset")); 218219089Spjd case EZFS_TAGTOOLONG: 219219089Spjd return (dgettext(TEXT_DOMAIN, "tag too long")); 220219089Spjd case EZFS_PIPEFAILED: 221219089Spjd return (dgettext(TEXT_DOMAIN, "pipe create failed")); 222219089Spjd case EZFS_THREADCREATEFAILED: 223219089Spjd return (dgettext(TEXT_DOMAIN, "thread create failed")); 224219089Spjd case EZFS_POSTSPLIT_ONLINE: 225219089Spjd return (dgettext(TEXT_DOMAIN, "disk was split from this pool " 226219089Spjd "into a new one")); 227219089Spjd case EZFS_SCRUBBING: 228219089Spjd return (dgettext(TEXT_DOMAIN, "currently scrubbing; " 229219089Spjd "use 'zpool scrub -s' to cancel current scrub")); 230219089Spjd case EZFS_NO_SCRUB: 231219089Spjd return (dgettext(TEXT_DOMAIN, "there is no active scrub")); 232219089Spjd case EZFS_DIFF: 233219089Spjd return (dgettext(TEXT_DOMAIN, "unable to generate diffs")); 234219089Spjd case EZFS_DIFFDATA: 235219089Spjd return (dgettext(TEXT_DOMAIN, "invalid diff data")); 236219089Spjd case EZFS_POOLREADONLY: 237219089Spjd return (dgettext(TEXT_DOMAIN, "pool is read-only")); 238168404Spjd case EZFS_UNKNOWN: 239168404Spjd return (dgettext(TEXT_DOMAIN, "unknown error")); 240168404Spjd default: 241168404Spjd assert(hdl->libzfs_error == 0); 242168404Spjd return (dgettext(TEXT_DOMAIN, "no error")); 243168404Spjd } 244168404Spjd} 245168404Spjd 246168404Spjd/*PRINTFLIKE2*/ 247168404Spjdvoid 248168404Spjdzfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...) 249168404Spjd{ 250168404Spjd va_list ap; 251168404Spjd 252168404Spjd va_start(ap, fmt); 253168404Spjd 254168404Spjd (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc), 255168404Spjd fmt, ap); 256168404Spjd hdl->libzfs_desc_active = 1; 257168404Spjd 258168404Spjd va_end(ap); 259168404Spjd} 260168404Spjd 261168404Spjdstatic void 262168404Spjdzfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap) 263168404Spjd{ 264168404Spjd (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action), 265168404Spjd fmt, ap); 266168404Spjd hdl->libzfs_error = error; 267168404Spjd 268168404Spjd if (hdl->libzfs_desc_active) 269168404Spjd hdl->libzfs_desc_active = 0; 270168404Spjd else 271168404Spjd hdl->libzfs_desc[0] = '\0'; 272168404Spjd 273168404Spjd if (hdl->libzfs_printerr) { 274168404Spjd if (error == EZFS_UNKNOWN) { 275168404Spjd (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal " 276168404Spjd "error: %s\n"), libzfs_error_description(hdl)); 277168404Spjd abort(); 278168404Spjd } 279168404Spjd 280168404Spjd (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action, 281168404Spjd libzfs_error_description(hdl)); 282168404Spjd if (error == EZFS_NOMEM) 283168404Spjd exit(1); 284168404Spjd } 285168404Spjd} 286168404Spjd 287168404Spjdint 288168404Spjdzfs_error(libzfs_handle_t *hdl, int error, const char *msg) 289168404Spjd{ 290168404Spjd return (zfs_error_fmt(hdl, error, "%s", msg)); 291168404Spjd} 292168404Spjd 293168404Spjd/*PRINTFLIKE3*/ 294168404Spjdint 295168404Spjdzfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 296168404Spjd{ 297168404Spjd va_list ap; 298168404Spjd 299168404Spjd va_start(ap, fmt); 300168404Spjd 301168404Spjd zfs_verror(hdl, error, fmt, ap); 302168404Spjd 303168404Spjd va_end(ap); 304168404Spjd 305168404Spjd return (-1); 306168404Spjd} 307168404Spjd 308168404Spjdstatic int 309168404Spjdzfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, 310168404Spjd va_list ap) 311168404Spjd{ 312168404Spjd switch (error) { 313168404Spjd case EPERM: 314168404Spjd case EACCES: 315168404Spjd zfs_verror(hdl, EZFS_PERM, fmt, ap); 316168404Spjd return (-1); 317168404Spjd 318185029Spjd case ECANCELED: 319185029Spjd zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap); 320185029Spjd return (-1); 321185029Spjd 322168404Spjd case EIO: 323168404Spjd zfs_verror(hdl, EZFS_IO, fmt, ap); 324168404Spjd return (-1); 325168404Spjd 326219089Spjd case EFAULT: 327219089Spjd zfs_verror(hdl, EZFS_FAULT, fmt, ap); 328219089Spjd return (-1); 329219089Spjd 330168404Spjd case EINTR: 331168404Spjd zfs_verror(hdl, EZFS_INTR, fmt, ap); 332168404Spjd return (-1); 333168404Spjd } 334168404Spjd 335168404Spjd return (0); 336168404Spjd} 337168404Spjd 338168404Spjdint 339168404Spjdzfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 340168404Spjd{ 341168404Spjd return (zfs_standard_error_fmt(hdl, error, "%s", msg)); 342168404Spjd} 343168404Spjd 344168404Spjd/*PRINTFLIKE3*/ 345168404Spjdint 346168404Spjdzfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 347168404Spjd{ 348168404Spjd va_list ap; 349168404Spjd 350168404Spjd va_start(ap, fmt); 351168404Spjd 352168404Spjd if (zfs_common_error(hdl, error, fmt, ap) != 0) { 353168404Spjd va_end(ap); 354168404Spjd return (-1); 355168404Spjd } 356168404Spjd 357168404Spjd switch (error) { 358168404Spjd case ENXIO: 359185029Spjd case ENODEV: 360228103Smm case EPIPE: 361168404Spjd zfs_verror(hdl, EZFS_IO, fmt, ap); 362168404Spjd break; 363168404Spjd 364168404Spjd case ENOENT: 365168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 366168404Spjd "dataset does not exist")); 367168404Spjd zfs_verror(hdl, EZFS_NOENT, fmt, ap); 368168404Spjd break; 369168404Spjd 370168404Spjd case ENOSPC: 371168404Spjd case EDQUOT: 372168404Spjd zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 373241021Skevlo va_end(ap); 374168404Spjd return (-1); 375168404Spjd 376168404Spjd case EEXIST: 377168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 378168404Spjd "dataset already exists")); 379168404Spjd zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 380168404Spjd break; 381168404Spjd 382168404Spjd case EBUSY: 383168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 384168404Spjd "dataset is busy")); 385168404Spjd zfs_verror(hdl, EZFS_BUSY, fmt, ap); 386168404Spjd break; 387185029Spjd case EROFS: 388219089Spjd zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); 389185029Spjd break; 390168498Spjd case ENAMETOOLONG: 391168498Spjd zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); 392168498Spjd break; 393185029Spjd case ENOTSUP: 394185029Spjd zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); 395185029Spjd break; 396209962Smm case EAGAIN: 397209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 398209962Smm "pool I/O is currently suspended")); 399209962Smm zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 400209962Smm break; 401168404Spjd default: 402219089Spjd zfs_error_aux(hdl, strerror(error)); 403168404Spjd zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 404168404Spjd break; 405168404Spjd } 406168404Spjd 407168404Spjd va_end(ap); 408168404Spjd return (-1); 409168404Spjd} 410168404Spjd 411168404Spjdint 412168404Spjdzpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 413168404Spjd{ 414168404Spjd return (zpool_standard_error_fmt(hdl, error, "%s", msg)); 415168404Spjd} 416168404Spjd 417168404Spjd/*PRINTFLIKE3*/ 418168404Spjdint 419168404Spjdzpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 420168404Spjd{ 421168404Spjd va_list ap; 422168404Spjd 423168404Spjd va_start(ap, fmt); 424168404Spjd 425168404Spjd if (zfs_common_error(hdl, error, fmt, ap) != 0) { 426168404Spjd va_end(ap); 427168404Spjd return (-1); 428168404Spjd } 429168404Spjd 430168404Spjd switch (error) { 431168404Spjd case ENODEV: 432168404Spjd zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); 433168404Spjd break; 434168404Spjd 435168404Spjd case ENOENT: 436168404Spjd zfs_error_aux(hdl, 437168404Spjd dgettext(TEXT_DOMAIN, "no such pool or dataset")); 438168404Spjd zfs_verror(hdl, EZFS_NOENT, fmt, ap); 439168404Spjd break; 440168404Spjd 441168404Spjd case EEXIST: 442168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 443168404Spjd "pool already exists")); 444168404Spjd zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 445168404Spjd break; 446168404Spjd 447168404Spjd case EBUSY: 448168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); 449185029Spjd zfs_verror(hdl, EZFS_BUSY, fmt, ap); 450168404Spjd break; 451168404Spjd 452168404Spjd case ENXIO: 453168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 454168404Spjd "one or more devices is currently unavailable")); 455168404Spjd zfs_verror(hdl, EZFS_BADDEV, fmt, ap); 456168404Spjd break; 457168404Spjd 458168404Spjd case ENAMETOOLONG: 459168404Spjd zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); 460168404Spjd break; 461168404Spjd 462168404Spjd case ENOTSUP: 463168404Spjd zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); 464168404Spjd break; 465168404Spjd 466168404Spjd case EINVAL: 467168404Spjd zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); 468168404Spjd break; 469168404Spjd 470185029Spjd case ENOSPC: 471185029Spjd case EDQUOT: 472185029Spjd zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 473241021Skevlo va_end(ap); 474185029Spjd return (-1); 475219089Spjd 476209962Smm case EAGAIN: 477209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 478209962Smm "pool I/O is currently suspended")); 479209962Smm zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 480209962Smm break; 481185029Spjd 482219089Spjd case EROFS: 483219089Spjd zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); 484219089Spjd break; 485219089Spjd 486168404Spjd default: 487168404Spjd zfs_error_aux(hdl, strerror(error)); 488168404Spjd zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 489168404Spjd } 490168404Spjd 491168404Spjd va_end(ap); 492168404Spjd return (-1); 493168404Spjd} 494168404Spjd 495168404Spjd/* 496168404Spjd * Display an out of memory error message and abort the current program. 497168404Spjd */ 498168404Spjdint 499168404Spjdno_memory(libzfs_handle_t *hdl) 500168404Spjd{ 501168404Spjd return (zfs_error(hdl, EZFS_NOMEM, "internal error")); 502168404Spjd} 503168404Spjd 504168404Spjd/* 505168404Spjd * A safe form of malloc() which will die if the allocation fails. 506168404Spjd */ 507168404Spjdvoid * 508168404Spjdzfs_alloc(libzfs_handle_t *hdl, size_t size) 509168404Spjd{ 510168404Spjd void *data; 511168404Spjd 512168404Spjd if ((data = calloc(1, size)) == NULL) 513168404Spjd (void) no_memory(hdl); 514168404Spjd 515168404Spjd return (data); 516168404Spjd} 517168404Spjd 518168404Spjd/* 519219089Spjd * A safe form of asprintf() which will die if the allocation fails. 520219089Spjd */ 521219089Spjd/*PRINTFLIKE2*/ 522219089Spjdchar * 523219089Spjdzfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...) 524219089Spjd{ 525219089Spjd va_list ap; 526219089Spjd char *ret; 527219089Spjd int err; 528219089Spjd 529219089Spjd va_start(ap, fmt); 530219089Spjd 531219089Spjd err = vasprintf(&ret, fmt, ap); 532219089Spjd 533219089Spjd va_end(ap); 534219089Spjd 535219089Spjd if (err < 0) 536219089Spjd (void) no_memory(hdl); 537219089Spjd 538219089Spjd return (ret); 539219089Spjd} 540219089Spjd 541219089Spjd/* 542168404Spjd * A safe form of realloc(), which also zeroes newly allocated space. 543168404Spjd */ 544168404Spjdvoid * 545168404Spjdzfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) 546168404Spjd{ 547168404Spjd void *ret; 548168404Spjd 549168404Spjd if ((ret = realloc(ptr, newsize)) == NULL) { 550168404Spjd (void) no_memory(hdl); 551168404Spjd return (NULL); 552168404Spjd } 553168404Spjd 554168404Spjd bzero((char *)ret + oldsize, (newsize - oldsize)); 555168404Spjd return (ret); 556168404Spjd} 557168404Spjd 558168404Spjd/* 559168404Spjd * A safe form of strdup() which will die if the allocation fails. 560168404Spjd */ 561168404Spjdchar * 562168404Spjdzfs_strdup(libzfs_handle_t *hdl, const char *str) 563168404Spjd{ 564168404Spjd char *ret; 565168404Spjd 566168404Spjd if ((ret = strdup(str)) == NULL) 567168404Spjd (void) no_memory(hdl); 568168404Spjd 569168404Spjd return (ret); 570168404Spjd} 571168404Spjd 572168404Spjd/* 573168404Spjd * Convert a number to an appropriately human-readable output. 574168404Spjd */ 575168404Spjdvoid 576168404Spjdzfs_nicenum(uint64_t num, char *buf, size_t buflen) 577168404Spjd{ 578168404Spjd uint64_t n = num; 579168404Spjd int index = 0; 580168404Spjd char u; 581168404Spjd 582168404Spjd while (n >= 1024) { 583168404Spjd n /= 1024; 584168404Spjd index++; 585168404Spjd } 586168404Spjd 587168404Spjd u = " KMGTPE"[index]; 588168404Spjd 589168404Spjd if (index == 0) { 590168404Spjd (void) snprintf(buf, buflen, "%llu", n); 591168404Spjd } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { 592168404Spjd /* 593168404Spjd * If this is an even multiple of the base, always display 594168404Spjd * without any decimal precision. 595168404Spjd */ 596168404Spjd (void) snprintf(buf, buflen, "%llu%c", n, u); 597168404Spjd } else { 598168404Spjd /* 599168404Spjd * We want to choose a precision that reflects the best choice 600168404Spjd * for fitting in 5 characters. This can get rather tricky when 601168404Spjd * we have numbers that are very close to an order of magnitude. 602168404Spjd * For example, when displaying 10239 (which is really 9.999K), 603168404Spjd * we want only a single place of precision for 10.0K. We could 604168404Spjd * develop some complex heuristics for this, but it's much 605168404Spjd * easier just to try each combination in turn. 606168404Spjd */ 607168404Spjd int i; 608168404Spjd for (i = 2; i >= 0; i--) { 609185029Spjd if (snprintf(buf, buflen, "%.*f%c", i, 610185029Spjd (double)num / (1ULL << 10 * index), u) <= 5) 611168404Spjd break; 612168404Spjd } 613168404Spjd } 614168404Spjd} 615168404Spjd 616168404Spjdvoid 617168404Spjdlibzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) 618168404Spjd{ 619168404Spjd hdl->libzfs_printerr = printerr; 620168404Spjd} 621168404Spjd 622168484Spjdstatic int 623168484Spjdlibzfs_load(void) 624168484Spjd{ 625168484Spjd int error; 626168484Spjd 627168484Spjd if (modfind("zfs") < 0) { 628168484Spjd /* Not present in kernel, try loading it. */ 629168484Spjd if (kldload("zfs") < 0 || modfind("zfs") < 0) { 630168484Spjd if (errno != EEXIST) 631219089Spjd return (-1); 632168484Spjd } 633168484Spjd } 634168484Spjd return (0); 635168484Spjd} 636168484Spjd 637168404Spjdlibzfs_handle_t * 638168404Spjdlibzfs_init(void) 639168404Spjd{ 640168404Spjd libzfs_handle_t *hdl; 641168404Spjd 642219089Spjd if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) { 643168404Spjd return (NULL); 644168404Spjd } 645168404Spjd 646219089Spjd if (libzfs_load() < 0) { 647219089Spjd free(hdl); 648219089Spjd return (NULL); 649219089Spjd } 650219089Spjd 651168404Spjd if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { 652219089Spjd free(hdl); 653219089Spjd return (NULL); 654168404Spjd } 655168404Spjd 656168404Spjd if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { 657168404Spjd (void) close(hdl->libzfs_fd); 658168404Spjd free(hdl); 659168404Spjd return (NULL); 660168404Spjd } 661168404Spjd 662168404Spjd hdl->libzfs_sharetab = fopen(ZFS_EXPORTS_PATH, "r"); 663168404Spjd 664248571Smm if (libzfs_core_init() != 0) { 665248571Smm (void) close(hdl->libzfs_fd); 666248571Smm (void) fclose(hdl->libzfs_mnttab); 667248571Smm (void) fclose(hdl->libzfs_sharetab); 668248571Smm free(hdl); 669248571Smm return (NULL); 670248571Smm } 671248571Smm 672185029Spjd zfs_prop_init(); 673185029Spjd zpool_prop_init(); 674236884Smm zpool_feature_init(); 675209962Smm libzfs_mnttab_init(hdl); 676185029Spjd 677168404Spjd return (hdl); 678168404Spjd} 679168404Spjd 680168404Spjdvoid 681168404Spjdlibzfs_fini(libzfs_handle_t *hdl) 682168404Spjd{ 683168404Spjd (void) close(hdl->libzfs_fd); 684168404Spjd if (hdl->libzfs_mnttab) 685168404Spjd (void) fclose(hdl->libzfs_mnttab); 686168404Spjd if (hdl->libzfs_sharetab) 687168404Spjd (void) fclose(hdl->libzfs_sharetab); 688185029Spjd zfs_uninit_libshare(hdl); 689185029Spjd zpool_free_handles(hdl); 690219089Spjd#ifdef sun 691219089Spjd libzfs_fru_clear(hdl, B_TRUE); 692219089Spjd#endif 693168404Spjd namespace_clear(hdl); 694209962Smm libzfs_mnttab_fini(hdl); 695248571Smm libzfs_core_fini(); 696168404Spjd free(hdl); 697168404Spjd} 698168404Spjd 699168404Spjdlibzfs_handle_t * 700168404Spjdzpool_get_handle(zpool_handle_t *zhp) 701168404Spjd{ 702168404Spjd return (zhp->zpool_hdl); 703168404Spjd} 704168404Spjd 705168404Spjdlibzfs_handle_t * 706168404Spjdzfs_get_handle(zfs_handle_t *zhp) 707168404Spjd{ 708168404Spjd return (zhp->zfs_hdl); 709168404Spjd} 710168404Spjd 711185029Spjdzpool_handle_t * 712185029Spjdzfs_get_pool_handle(const zfs_handle_t *zhp) 713185029Spjd{ 714185029Spjd return (zhp->zpool_hdl); 715185029Spjd} 716185029Spjd 717168404Spjd/* 718168404Spjd * Given a name, determine whether or not it's a valid path 719168404Spjd * (starts with '/' or "./"). If so, walk the mnttab trying 720168404Spjd * to match the device number. If not, treat the path as an 721168404Spjd * fs/vol/snap name. 722168404Spjd */ 723168404Spjdzfs_handle_t * 724168404Spjdzfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype) 725168404Spjd{ 726219089Spjd struct stat64 statbuf; 727219089Spjd struct extmnttab entry; 728219089Spjd int ret; 729168404Spjd 730168404Spjd if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { 731168404Spjd /* 732168404Spjd * It's not a valid path, assume it's a name of type 'argtype'. 733168404Spjd */ 734168404Spjd return (zfs_open(hdl, path, argtype)); 735168404Spjd } 736168404Spjd 737219089Spjd if (stat64(path, &statbuf) != 0) { 738168404Spjd (void) fprintf(stderr, "%s: %s\n", path, strerror(errno)); 739168404Spjd return (NULL); 740168404Spjd } 741168404Spjd 742219089Spjd#ifdef sun 743219089Spjd rewind(hdl->libzfs_mnttab); 744219089Spjd while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) { 745219089Spjd if (makedevice(entry.mnt_major, entry.mnt_minor) == 746219089Spjd statbuf.st_dev) { 747219089Spjd break; 748219089Spjd } 749219089Spjd } 750219089Spjd#else 751219089Spjd { 752219089Spjd struct statfs sfs; 753219089Spjd 754220575Spjd ret = statfs(path, &sfs); 755220575Spjd if (ret == 0) 756220575Spjd statfs2mnttab(&sfs, &entry); 757220575Spjd else { 758219089Spjd (void) fprintf(stderr, "%s: %s\n", path, 759219089Spjd strerror(errno)); 760219089Spjd } 761219089Spjd } 762219089Spjd#endif /* sun */ 763219089Spjd if (ret != 0) { 764219089Spjd return (NULL); 765219089Spjd } 766219089Spjd 767219089Spjd if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { 768168404Spjd (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), 769168404Spjd path); 770168404Spjd return (NULL); 771168404Spjd } 772168404Spjd 773219089Spjd return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); 774168404Spjd} 775168404Spjd 776168404Spjd/* 777168404Spjd * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from 778168404Spjd * an ioctl(). 779168404Spjd */ 780168404Spjdint 781168404Spjdzcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) 782168404Spjd{ 783168404Spjd if (len == 0) 784219089Spjd len = 16 * 1024; 785168404Spjd zc->zc_nvlist_dst_size = len; 786168404Spjd if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 787168404Spjd zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0) 788168404Spjd return (-1); 789168404Spjd 790168404Spjd return (0); 791168404Spjd} 792168404Spjd 793168404Spjd/* 794168404Spjd * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will 795168404Spjd * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was 796168404Spjd * filled in by the kernel to indicate the actual required size. 797168404Spjd */ 798168404Spjdint 799168404Spjdzcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) 800168404Spjd{ 801168404Spjd free((void *)(uintptr_t)zc->zc_nvlist_dst); 802168404Spjd if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 803168404Spjd zfs_alloc(hdl, zc->zc_nvlist_dst_size)) 804168404Spjd == 0) 805168404Spjd return (-1); 806168404Spjd 807168404Spjd return (0); 808168404Spjd} 809168404Spjd 810168404Spjd/* 811168404Spjd * Called to free the src and dst nvlists stored in the command structure. 812168404Spjd */ 813168404Spjdvoid 814168404Spjdzcmd_free_nvlists(zfs_cmd_t *zc) 815168404Spjd{ 816185029Spjd free((void *)(uintptr_t)zc->zc_nvlist_conf); 817168404Spjd free((void *)(uintptr_t)zc->zc_nvlist_src); 818168404Spjd free((void *)(uintptr_t)zc->zc_nvlist_dst); 819168404Spjd} 820168404Spjd 821185029Spjdstatic int 822185029Spjdzcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, 823185029Spjd nvlist_t *nvl) 824168404Spjd{ 825168404Spjd char *packed; 826168404Spjd size_t len; 827168404Spjd 828168404Spjd verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0); 829168404Spjd 830168404Spjd if ((packed = zfs_alloc(hdl, len)) == NULL) 831168404Spjd return (-1); 832168404Spjd 833168404Spjd verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 834168404Spjd 835185029Spjd *outnv = (uint64_t)(uintptr_t)packed; 836185029Spjd *outlen = len; 837168404Spjd 838168404Spjd return (0); 839168404Spjd} 840168404Spjd 841185029Spjdint 842185029Spjdzcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 843185029Spjd{ 844185029Spjd return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, 845185029Spjd &zc->zc_nvlist_conf_size, nvl)); 846185029Spjd} 847185029Spjd 848185029Spjdint 849185029Spjdzcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 850185029Spjd{ 851185029Spjd return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, 852185029Spjd &zc->zc_nvlist_src_size, nvl)); 853185029Spjd} 854185029Spjd 855168404Spjd/* 856168404Spjd * Unpacks an nvlist from the ZFS ioctl command structure. 857168404Spjd */ 858168404Spjdint 859168404Spjdzcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) 860168404Spjd{ 861168404Spjd if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, 862168404Spjd zc->zc_nvlist_dst_size, nvlp, 0) != 0) 863168404Spjd return (no_memory(hdl)); 864168404Spjd 865168404Spjd return (0); 866168404Spjd} 867168404Spjd 868185029Spjdint 869248571Smmzfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) 870185029Spjd{ 871248571Smm return (ioctl(hdl->libzfs_fd, request, zc)); 872185029Spjd} 873185029Spjd 874185029Spjd/* 875185029Spjd * ================================================================ 876185029Spjd * API shared by zfs and zpool property management 877185029Spjd * ================================================================ 878185029Spjd */ 879185029Spjd 880168404Spjdstatic void 881185029Spjdzprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) 882168404Spjd{ 883185029Spjd zprop_list_t *pl = cbp->cb_proplist; 884168404Spjd int i; 885168404Spjd char *title; 886168404Spjd size_t len; 887168404Spjd 888168404Spjd cbp->cb_first = B_FALSE; 889168404Spjd if (cbp->cb_scripted) 890168404Spjd return; 891168404Spjd 892168404Spjd /* 893168404Spjd * Start with the length of the column headers. 894168404Spjd */ 895168404Spjd cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); 896168404Spjd cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, 897168404Spjd "PROPERTY")); 898168404Spjd cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, 899168404Spjd "VALUE")); 900219089Spjd cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN, 901219089Spjd "RECEIVED")); 902168404Spjd cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, 903168404Spjd "SOURCE")); 904168404Spjd 905209962Smm /* first property is always NAME */ 906209962Smm assert(cbp->cb_proplist->pl_prop == 907209962Smm ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME)); 908209962Smm 909168404Spjd /* 910168404Spjd * Go through and calculate the widths for each column. For the 911168404Spjd * 'source' column, we kludge it up by taking the worst-case scenario of 912168404Spjd * inheriting from the longest name. This is acceptable because in the 913168404Spjd * majority of cases 'SOURCE' is the last column displayed, and we don't 914168404Spjd * use the width anyway. Note that the 'VALUE' column can be oversized, 915219089Spjd * if the name of the property is much longer than any values we find. 916168404Spjd */ 917168404Spjd for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 918168404Spjd /* 919168404Spjd * 'PROPERTY' column 920168404Spjd */ 921185029Spjd if (pl->pl_prop != ZPROP_INVAL) { 922185029Spjd const char *propname = (type == ZFS_TYPE_POOL) ? 923185029Spjd zpool_prop_to_name(pl->pl_prop) : 924185029Spjd zfs_prop_to_name(pl->pl_prop); 925185029Spjd 926185029Spjd len = strlen(propname); 927168404Spjd if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 928168404Spjd cbp->cb_colwidths[GET_COL_PROPERTY] = len; 929168404Spjd } else { 930168404Spjd len = strlen(pl->pl_user_prop); 931168404Spjd if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 932168404Spjd cbp->cb_colwidths[GET_COL_PROPERTY] = len; 933168404Spjd } 934168404Spjd 935168404Spjd /* 936209962Smm * 'VALUE' column. The first property is always the 'name' 937209962Smm * property that was tacked on either by /sbin/zfs's 938209962Smm * zfs_do_get() or when calling zprop_expand_list(), so we 939209962Smm * ignore its width. If the user specified the name property 940209962Smm * to display, then it will be later in the list in any case. 941168404Spjd */ 942209962Smm if (pl != cbp->cb_proplist && 943168404Spjd pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) 944168404Spjd cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; 945168404Spjd 946219089Spjd /* 'RECEIVED' column. */ 947219089Spjd if (pl != cbp->cb_proplist && 948219089Spjd pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD]) 949219089Spjd cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width; 950219089Spjd 951168404Spjd /* 952168404Spjd * 'NAME' and 'SOURCE' columns 953168404Spjd */ 954185029Spjd if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME : 955185029Spjd ZFS_PROP_NAME) && 956168404Spjd pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { 957168404Spjd cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; 958168404Spjd cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + 959168404Spjd strlen(dgettext(TEXT_DOMAIN, "inherited from")); 960168404Spjd } 961168404Spjd } 962168404Spjd 963168404Spjd /* 964168404Spjd * Now go through and print the headers. 965168404Spjd */ 966219089Spjd for (i = 0; i < ZFS_GET_NCOLS; i++) { 967168404Spjd switch (cbp->cb_columns[i]) { 968168404Spjd case GET_COL_NAME: 969168404Spjd title = dgettext(TEXT_DOMAIN, "NAME"); 970168404Spjd break; 971168404Spjd case GET_COL_PROPERTY: 972168404Spjd title = dgettext(TEXT_DOMAIN, "PROPERTY"); 973168404Spjd break; 974168404Spjd case GET_COL_VALUE: 975168404Spjd title = dgettext(TEXT_DOMAIN, "VALUE"); 976168404Spjd break; 977219089Spjd case GET_COL_RECVD: 978219089Spjd title = dgettext(TEXT_DOMAIN, "RECEIVED"); 979219089Spjd break; 980168404Spjd case GET_COL_SOURCE: 981168404Spjd title = dgettext(TEXT_DOMAIN, "SOURCE"); 982168404Spjd break; 983168404Spjd default: 984168404Spjd title = NULL; 985168404Spjd } 986168404Spjd 987168404Spjd if (title != NULL) { 988219089Spjd if (i == (ZFS_GET_NCOLS - 1) || 989219089Spjd cbp->cb_columns[i + 1] == GET_COL_NONE) 990168404Spjd (void) printf("%s", title); 991168404Spjd else 992168404Spjd (void) printf("%-*s ", 993168404Spjd cbp->cb_colwidths[cbp->cb_columns[i]], 994168404Spjd title); 995168404Spjd } 996168404Spjd } 997168404Spjd (void) printf("\n"); 998168404Spjd} 999168404Spjd 1000168404Spjd/* 1001168404Spjd * Display a single line of output, according to the settings in the callback 1002168404Spjd * structure. 1003168404Spjd */ 1004168404Spjdvoid 1005185029Spjdzprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, 1006185029Spjd const char *propname, const char *value, zprop_source_t sourcetype, 1007219089Spjd const char *source, const char *recvd_value) 1008168404Spjd{ 1009168404Spjd int i; 1010168404Spjd const char *str; 1011168404Spjd char buf[128]; 1012168404Spjd 1013168404Spjd /* 1014168404Spjd * Ignore those source types that the user has chosen to ignore. 1015168404Spjd */ 1016168404Spjd if ((sourcetype & cbp->cb_sources) == 0) 1017168404Spjd return; 1018168404Spjd 1019168404Spjd if (cbp->cb_first) 1020185029Spjd zprop_print_headers(cbp, cbp->cb_type); 1021168404Spjd 1022219089Spjd for (i = 0; i < ZFS_GET_NCOLS; i++) { 1023168404Spjd switch (cbp->cb_columns[i]) { 1024168404Spjd case GET_COL_NAME: 1025168404Spjd str = name; 1026168404Spjd break; 1027168404Spjd 1028168404Spjd case GET_COL_PROPERTY: 1029168404Spjd str = propname; 1030168404Spjd break; 1031168404Spjd 1032168404Spjd case GET_COL_VALUE: 1033168404Spjd str = value; 1034168404Spjd break; 1035168404Spjd 1036168404Spjd case GET_COL_SOURCE: 1037168404Spjd switch (sourcetype) { 1038185029Spjd case ZPROP_SRC_NONE: 1039168404Spjd str = "-"; 1040168404Spjd break; 1041168404Spjd 1042185029Spjd case ZPROP_SRC_DEFAULT: 1043168404Spjd str = "default"; 1044168404Spjd break; 1045168404Spjd 1046185029Spjd case ZPROP_SRC_LOCAL: 1047168404Spjd str = "local"; 1048168404Spjd break; 1049168404Spjd 1050185029Spjd case ZPROP_SRC_TEMPORARY: 1051168404Spjd str = "temporary"; 1052168404Spjd break; 1053168404Spjd 1054185029Spjd case ZPROP_SRC_INHERITED: 1055168404Spjd (void) snprintf(buf, sizeof (buf), 1056168404Spjd "inherited from %s", source); 1057168404Spjd str = buf; 1058168404Spjd break; 1059219089Spjd case ZPROP_SRC_RECEIVED: 1060219089Spjd str = "received"; 1061219089Spjd break; 1062168404Spjd } 1063168404Spjd break; 1064168404Spjd 1065219089Spjd case GET_COL_RECVD: 1066219089Spjd str = (recvd_value == NULL ? "-" : recvd_value); 1067219089Spjd break; 1068219089Spjd 1069168404Spjd default: 1070168404Spjd continue; 1071168404Spjd } 1072168404Spjd 1073219089Spjd if (cbp->cb_columns[i + 1] == GET_COL_NONE) 1074168404Spjd (void) printf("%s", str); 1075168404Spjd else if (cbp->cb_scripted) 1076168404Spjd (void) printf("%s\t", str); 1077168404Spjd else 1078168404Spjd (void) printf("%-*s ", 1079168404Spjd cbp->cb_colwidths[cbp->cb_columns[i]], 1080168404Spjd str); 1081168404Spjd } 1082168404Spjd 1083168404Spjd (void) printf("\n"); 1084168404Spjd} 1085185029Spjd 1086185029Spjd/* 1087185029Spjd * Given a numeric suffix, convert the value into a number of bits that the 1088185029Spjd * resulting value must be shifted. 1089185029Spjd */ 1090185029Spjdstatic int 1091185029Spjdstr2shift(libzfs_handle_t *hdl, const char *buf) 1092185029Spjd{ 1093185029Spjd const char *ends = "BKMGTPEZ"; 1094185029Spjd int i; 1095185029Spjd 1096185029Spjd if (buf[0] == '\0') 1097185029Spjd return (0); 1098185029Spjd for (i = 0; i < strlen(ends); i++) { 1099185029Spjd if (toupper(buf[0]) == ends[i]) 1100185029Spjd break; 1101185029Spjd } 1102185029Spjd if (i == strlen(ends)) { 1103185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1104185029Spjd "invalid numeric suffix '%s'"), buf); 1105185029Spjd return (-1); 1106185029Spjd } 1107185029Spjd 1108185029Spjd /* 1109185029Spjd * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 1110185029Spjd * allow 'BB' - that's just weird. 1111185029Spjd */ 1112185029Spjd if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 1113185029Spjd toupper(buf[0]) != 'B')) 1114185029Spjd return (10*i); 1115185029Spjd 1116185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1117185029Spjd "invalid numeric suffix '%s'"), buf); 1118185029Spjd return (-1); 1119185029Spjd} 1120185029Spjd 1121185029Spjd/* 1122185029Spjd * Convert a string of the form '100G' into a real number. Used when setting 1123185029Spjd * properties or creating a volume. 'buf' is used to place an extended error 1124185029Spjd * message for the caller to use. 1125185029Spjd */ 1126185029Spjdint 1127185029Spjdzfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 1128185029Spjd{ 1129185029Spjd char *end; 1130185029Spjd int shift; 1131185029Spjd 1132185029Spjd *num = 0; 1133185029Spjd 1134185029Spjd /* Check to see if this looks like a number. */ 1135185029Spjd if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 1136185029Spjd if (hdl) 1137185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1138185029Spjd "bad numeric value '%s'"), value); 1139185029Spjd return (-1); 1140185029Spjd } 1141185029Spjd 1142219089Spjd /* Rely on strtoull() to process the numeric portion. */ 1143185029Spjd errno = 0; 1144209962Smm *num = strtoull(value, &end, 10); 1145185029Spjd 1146185029Spjd /* 1147185029Spjd * Check for ERANGE, which indicates that the value is too large to fit 1148185029Spjd * in a 64-bit value. 1149185029Spjd */ 1150185029Spjd if (errno == ERANGE) { 1151185029Spjd if (hdl) 1152185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1153185029Spjd "numeric value is too large")); 1154185029Spjd return (-1); 1155185029Spjd } 1156185029Spjd 1157185029Spjd /* 1158185029Spjd * If we have a decimal value, then do the computation with floating 1159185029Spjd * point arithmetic. Otherwise, use standard arithmetic. 1160185029Spjd */ 1161185029Spjd if (*end == '.') { 1162185029Spjd double fval = strtod(value, &end); 1163185029Spjd 1164185029Spjd if ((shift = str2shift(hdl, end)) == -1) 1165185029Spjd return (-1); 1166185029Spjd 1167185029Spjd fval *= pow(2, shift); 1168185029Spjd 1169185029Spjd if (fval > UINT64_MAX) { 1170185029Spjd if (hdl) 1171185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1172185029Spjd "numeric value is too large")); 1173185029Spjd return (-1); 1174185029Spjd } 1175185029Spjd 1176185029Spjd *num = (uint64_t)fval; 1177185029Spjd } else { 1178185029Spjd if ((shift = str2shift(hdl, end)) == -1) 1179185029Spjd return (-1); 1180185029Spjd 1181185029Spjd /* Check for overflow */ 1182185029Spjd if (shift >= 64 || (*num << shift) >> shift != *num) { 1183185029Spjd if (hdl) 1184185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1185185029Spjd "numeric value is too large")); 1186185029Spjd return (-1); 1187185029Spjd } 1188185029Spjd 1189185029Spjd *num <<= shift; 1190185029Spjd } 1191185029Spjd 1192185029Spjd return (0); 1193185029Spjd} 1194185029Spjd 1195185029Spjd/* 1196185029Spjd * Given a propname=value nvpair to set, parse any numeric properties 1197185029Spjd * (index, boolean, etc) if they are specified as strings and add the 1198185029Spjd * resulting nvpair to the returned nvlist. 1199185029Spjd * 1200185029Spjd * At the DSL layer, all properties are either 64-bit numbers or strings. 1201185029Spjd * We want the user to be able to ignore this fact and specify properties 1202185029Spjd * as native values (numbers, for example) or as strings (to simplify 1203185029Spjd * command line utilities). This also handles converting index types 1204185029Spjd * (compression, checksum, etc) from strings to their on-disk index. 1205185029Spjd */ 1206185029Spjdint 1207185029Spjdzprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, 1208185029Spjd zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp, 1209185029Spjd const char *errbuf) 1210185029Spjd{ 1211185029Spjd data_type_t datatype = nvpair_type(elem); 1212185029Spjd zprop_type_t proptype; 1213185029Spjd const char *propname; 1214185029Spjd char *value; 1215185029Spjd boolean_t isnone = B_FALSE; 1216185029Spjd 1217185029Spjd if (type == ZFS_TYPE_POOL) { 1218185029Spjd proptype = zpool_prop_get_type(prop); 1219185029Spjd propname = zpool_prop_to_name(prop); 1220185029Spjd } else { 1221185029Spjd proptype = zfs_prop_get_type(prop); 1222185029Spjd propname = zfs_prop_to_name(prop); 1223185029Spjd } 1224185029Spjd 1225185029Spjd /* 1226185029Spjd * Convert any properties to the internal DSL value types. 1227185029Spjd */ 1228185029Spjd *svalp = NULL; 1229185029Spjd *ivalp = 0; 1230185029Spjd 1231185029Spjd switch (proptype) { 1232185029Spjd case PROP_TYPE_STRING: 1233185029Spjd if (datatype != DATA_TYPE_STRING) { 1234185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1235185029Spjd "'%s' must be a string"), nvpair_name(elem)); 1236185029Spjd goto error; 1237185029Spjd } 1238185029Spjd (void) nvpair_value_string(elem, svalp); 1239185029Spjd if (strlen(*svalp) >= ZFS_MAXPROPLEN) { 1240185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1241185029Spjd "'%s' is too long"), nvpair_name(elem)); 1242185029Spjd goto error; 1243185029Spjd } 1244185029Spjd break; 1245185029Spjd 1246185029Spjd case PROP_TYPE_NUMBER: 1247185029Spjd if (datatype == DATA_TYPE_STRING) { 1248185029Spjd (void) nvpair_value_string(elem, &value); 1249185029Spjd if (strcmp(value, "none") == 0) { 1250185029Spjd isnone = B_TRUE; 1251185029Spjd } else if (zfs_nicestrtonum(hdl, value, ivalp) 1252185029Spjd != 0) { 1253185029Spjd goto error; 1254185029Spjd } 1255185029Spjd } else if (datatype == DATA_TYPE_UINT64) { 1256185029Spjd (void) nvpair_value_uint64(elem, ivalp); 1257185029Spjd } else { 1258185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1259185029Spjd "'%s' must be a number"), nvpair_name(elem)); 1260185029Spjd goto error; 1261185029Spjd } 1262185029Spjd 1263185029Spjd /* 1264185029Spjd * Quota special: force 'none' and don't allow 0. 1265185029Spjd */ 1266185029Spjd if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && 1267185029Spjd (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { 1268185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1269185029Spjd "use 'none' to disable quota/refquota")); 1270185029Spjd goto error; 1271185029Spjd } 1272265744Sdelphij 1273265744Sdelphij /* 1274265744Sdelphij * Special handling for "*_limit=none". In this case it's not 1275265744Sdelphij * 0 but UINT64_MAX. 1276265744Sdelphij */ 1277265744Sdelphij if ((type & ZFS_TYPE_DATASET) && isnone && 1278265744Sdelphij (prop == ZFS_PROP_FILESYSTEM_LIMIT || 1279265744Sdelphij prop == ZFS_PROP_SNAPSHOT_LIMIT)) { 1280265744Sdelphij *ivalp = UINT64_MAX; 1281265744Sdelphij } 1282185029Spjd break; 1283185029Spjd 1284185029Spjd case PROP_TYPE_INDEX: 1285185029Spjd if (datatype != DATA_TYPE_STRING) { 1286185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1287185029Spjd "'%s' must be a string"), nvpair_name(elem)); 1288185029Spjd goto error; 1289185029Spjd } 1290185029Spjd 1291185029Spjd (void) nvpair_value_string(elem, &value); 1292185029Spjd 1293185029Spjd if (zprop_string_to_index(prop, value, ivalp, type) != 0) { 1294185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1295185029Spjd "'%s' must be one of '%s'"), propname, 1296185029Spjd zprop_values(prop, type)); 1297185029Spjd goto error; 1298185029Spjd } 1299185029Spjd break; 1300185029Spjd 1301185029Spjd default: 1302185029Spjd abort(); 1303185029Spjd } 1304185029Spjd 1305185029Spjd /* 1306185029Spjd * Add the result to our return set of properties. 1307185029Spjd */ 1308185029Spjd if (*svalp != NULL) { 1309185029Spjd if (nvlist_add_string(ret, propname, *svalp) != 0) { 1310185029Spjd (void) no_memory(hdl); 1311185029Spjd return (-1); 1312185029Spjd } 1313185029Spjd } else { 1314185029Spjd if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { 1315185029Spjd (void) no_memory(hdl); 1316185029Spjd return (-1); 1317185029Spjd } 1318185029Spjd } 1319185029Spjd 1320185029Spjd return (0); 1321185029Spjderror: 1322185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1323185029Spjd return (-1); 1324185029Spjd} 1325185029Spjd 1326185029Spjdstatic int 1327185029Spjdaddlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp, 1328185029Spjd zfs_type_t type) 1329185029Spjd{ 1330185029Spjd int prop; 1331185029Spjd zprop_list_t *entry; 1332185029Spjd 1333185029Spjd prop = zprop_name_to_prop(propname, type); 1334185029Spjd 1335185029Spjd if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type)) 1336185029Spjd prop = ZPROP_INVAL; 1337185029Spjd 1338185029Spjd /* 1339185029Spjd * When no property table entry can be found, return failure if 1340185029Spjd * this is a pool property or if this isn't a user-defined 1341185029Spjd * dataset property, 1342185029Spjd */ 1343236884Smm if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL && 1344236884Smm !zpool_prop_feature(propname) && 1345236884Smm !zpool_prop_unsupported(propname)) || 1346236884Smm (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) && 1347236884Smm !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) { 1348185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1349185029Spjd "invalid property '%s'"), propname); 1350185029Spjd return (zfs_error(hdl, EZFS_BADPROP, 1351185029Spjd dgettext(TEXT_DOMAIN, "bad property list"))); 1352185029Spjd } 1353185029Spjd 1354185029Spjd if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 1355185029Spjd return (-1); 1356185029Spjd 1357185029Spjd entry->pl_prop = prop; 1358185029Spjd if (prop == ZPROP_INVAL) { 1359236884Smm if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == 1360236884Smm NULL) { 1361185029Spjd free(entry); 1362185029Spjd return (-1); 1363185029Spjd } 1364185029Spjd entry->pl_width = strlen(propname); 1365185029Spjd } else { 1366185029Spjd entry->pl_width = zprop_width(prop, &entry->pl_fixed, 1367185029Spjd type); 1368185029Spjd } 1369185029Spjd 1370185029Spjd *listp = entry; 1371185029Spjd 1372185029Spjd return (0); 1373185029Spjd} 1374185029Spjd 1375185029Spjd/* 1376185029Spjd * Given a comma-separated list of properties, construct a property list 1377185029Spjd * containing both user-defined and native properties. This function will 1378185029Spjd * return a NULL list if 'all' is specified, which can later be expanded 1379185029Spjd * by zprop_expand_list(). 1380185029Spjd */ 1381185029Spjdint 1382185029Spjdzprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, 1383185029Spjd zfs_type_t type) 1384185029Spjd{ 1385185029Spjd *listp = NULL; 1386185029Spjd 1387185029Spjd /* 1388185029Spjd * If 'all' is specified, return a NULL list. 1389185029Spjd */ 1390185029Spjd if (strcmp(props, "all") == 0) 1391185029Spjd return (0); 1392185029Spjd 1393185029Spjd /* 1394185029Spjd * If no props were specified, return an error. 1395185029Spjd */ 1396185029Spjd if (props[0] == '\0') { 1397185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1398185029Spjd "no properties specified")); 1399185029Spjd return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 1400185029Spjd "bad property list"))); 1401185029Spjd } 1402185029Spjd 1403185029Spjd /* 1404185029Spjd * It would be nice to use getsubopt() here, but the inclusion of column 1405185029Spjd * aliases makes this more effort than it's worth. 1406185029Spjd */ 1407185029Spjd while (*props != '\0') { 1408185029Spjd size_t len; 1409185029Spjd char *p; 1410185029Spjd char c; 1411185029Spjd 1412185029Spjd if ((p = strchr(props, ',')) == NULL) { 1413185029Spjd len = strlen(props); 1414185029Spjd p = props + len; 1415185029Spjd } else { 1416185029Spjd len = p - props; 1417185029Spjd } 1418185029Spjd 1419185029Spjd /* 1420185029Spjd * Check for empty options. 1421185029Spjd */ 1422185029Spjd if (len == 0) { 1423185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1424185029Spjd "empty property name")); 1425185029Spjd return (zfs_error(hdl, EZFS_BADPROP, 1426185029Spjd dgettext(TEXT_DOMAIN, "bad property list"))); 1427185029Spjd } 1428185029Spjd 1429185029Spjd /* 1430185029Spjd * Check all regular property names. 1431185029Spjd */ 1432185029Spjd c = props[len]; 1433185029Spjd props[len] = '\0'; 1434185029Spjd 1435185029Spjd if (strcmp(props, "space") == 0) { 1436185029Spjd static char *spaceprops[] = { 1437185029Spjd "name", "avail", "used", "usedbysnapshots", 1438185029Spjd "usedbydataset", "usedbyrefreservation", 1439185029Spjd "usedbychildren", NULL 1440185029Spjd }; 1441185029Spjd int i; 1442185029Spjd 1443185029Spjd for (i = 0; spaceprops[i]; i++) { 1444185029Spjd if (addlist(hdl, spaceprops[i], listp, type)) 1445185029Spjd return (-1); 1446185029Spjd listp = &(*listp)->pl_next; 1447185029Spjd } 1448185029Spjd } else { 1449185029Spjd if (addlist(hdl, props, listp, type)) 1450185029Spjd return (-1); 1451185029Spjd listp = &(*listp)->pl_next; 1452185029Spjd } 1453185029Spjd 1454185029Spjd props = p; 1455185029Spjd if (c == ',') 1456185029Spjd props++; 1457185029Spjd } 1458185029Spjd 1459185029Spjd return (0); 1460185029Spjd} 1461185029Spjd 1462185029Spjdvoid 1463185029Spjdzprop_free_list(zprop_list_t *pl) 1464185029Spjd{ 1465185029Spjd zprop_list_t *next; 1466185029Spjd 1467185029Spjd while (pl != NULL) { 1468185029Spjd next = pl->pl_next; 1469185029Spjd free(pl->pl_user_prop); 1470185029Spjd free(pl); 1471185029Spjd pl = next; 1472185029Spjd } 1473185029Spjd} 1474185029Spjd 1475185029Spjdtypedef struct expand_data { 1476185029Spjd zprop_list_t **last; 1477185029Spjd libzfs_handle_t *hdl; 1478185029Spjd zfs_type_t type; 1479185029Spjd} expand_data_t; 1480185029Spjd 1481185029Spjdint 1482185029Spjdzprop_expand_list_cb(int prop, void *cb) 1483185029Spjd{ 1484185029Spjd zprop_list_t *entry; 1485185029Spjd expand_data_t *edp = cb; 1486185029Spjd 1487185029Spjd if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL) 1488185029Spjd return (ZPROP_INVAL); 1489185029Spjd 1490185029Spjd entry->pl_prop = prop; 1491185029Spjd entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); 1492185029Spjd entry->pl_all = B_TRUE; 1493185029Spjd 1494185029Spjd *(edp->last) = entry; 1495185029Spjd edp->last = &entry->pl_next; 1496185029Spjd 1497185029Spjd return (ZPROP_CONT); 1498185029Spjd} 1499185029Spjd 1500185029Spjdint 1501185029Spjdzprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) 1502185029Spjd{ 1503185029Spjd zprop_list_t *entry; 1504185029Spjd zprop_list_t **last; 1505185029Spjd expand_data_t exp; 1506185029Spjd 1507185029Spjd if (*plp == NULL) { 1508185029Spjd /* 1509185029Spjd * If this is the very first time we've been called for an 'all' 1510185029Spjd * specification, expand the list to include all native 1511185029Spjd * properties. 1512185029Spjd */ 1513185029Spjd last = plp; 1514185029Spjd 1515185029Spjd exp.last = last; 1516185029Spjd exp.hdl = hdl; 1517185029Spjd exp.type = type; 1518185029Spjd 1519185029Spjd if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, 1520185029Spjd B_FALSE, type) == ZPROP_INVAL) 1521185029Spjd return (-1); 1522185029Spjd 1523185029Spjd /* 1524185029Spjd * Add 'name' to the beginning of the list, which is handled 1525185029Spjd * specially. 1526185029Spjd */ 1527185029Spjd if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 1528185029Spjd return (-1); 1529185029Spjd 1530185029Spjd entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : 1531185029Spjd ZFS_PROP_NAME; 1532185029Spjd entry->pl_width = zprop_width(entry->pl_prop, 1533185029Spjd &entry->pl_fixed, type); 1534185029Spjd entry->pl_all = B_TRUE; 1535185029Spjd entry->pl_next = *plp; 1536185029Spjd *plp = entry; 1537185029Spjd } 1538185029Spjd return (0); 1539185029Spjd} 1540185029Spjd 1541185029Spjdint 1542185029Spjdzprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, 1543185029Spjd zfs_type_t type) 1544185029Spjd{ 1545185029Spjd return (zprop_iter_common(func, cb, show_all, ordered, type)); 1546185029Spjd} 1547