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 */ 21243674Smm 22168404Spjd/* 23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24265754Sdelphij * Copyright (c) 2013, Joyent, Inc. All rights reserved. 25243674Smm * 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> 52249643Smm#include <libzfs_core.h> 53168404Spjd 54168404Spjd#include "libzfs_impl.h" 55185029Spjd#include "zfs_prop.h" 56243674Smm#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: 126243674Smm return (dgettext(TEXT_DOMAIN, "unsupported version or " 127243674Smm "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: 360229578Smm 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); 373168404Spjd return (-1); 374168404Spjd 375168404Spjd case EEXIST: 376168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 377168404Spjd "dataset already exists")); 378168404Spjd zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 379168404Spjd break; 380168404Spjd 381168404Spjd case EBUSY: 382168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 383168404Spjd "dataset is busy")); 384168404Spjd zfs_verror(hdl, EZFS_BUSY, fmt, ap); 385168404Spjd break; 386185029Spjd case EROFS: 387219089Spjd zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); 388185029Spjd break; 389168498Spjd case ENAMETOOLONG: 390168498Spjd zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); 391168498Spjd break; 392185029Spjd case ENOTSUP: 393185029Spjd zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); 394185029Spjd break; 395209962Smm case EAGAIN: 396209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 397209962Smm "pool I/O is currently suspended")); 398209962Smm zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 399209962Smm break; 400168404Spjd default: 401219089Spjd zfs_error_aux(hdl, strerror(error)); 402168404Spjd zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 403168404Spjd break; 404168404Spjd } 405168404Spjd 406168404Spjd va_end(ap); 407168404Spjd return (-1); 408168404Spjd} 409168404Spjd 410168404Spjdint 411168404Spjdzpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 412168404Spjd{ 413168404Spjd return (zpool_standard_error_fmt(hdl, error, "%s", msg)); 414168404Spjd} 415168404Spjd 416168404Spjd/*PRINTFLIKE3*/ 417168404Spjdint 418168404Spjdzpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 419168404Spjd{ 420168404Spjd va_list ap; 421168404Spjd 422168404Spjd va_start(ap, fmt); 423168404Spjd 424168404Spjd if (zfs_common_error(hdl, error, fmt, ap) != 0) { 425168404Spjd va_end(ap); 426168404Spjd return (-1); 427168404Spjd } 428168404Spjd 429168404Spjd switch (error) { 430168404Spjd case ENODEV: 431168404Spjd zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); 432168404Spjd break; 433168404Spjd 434168404Spjd case ENOENT: 435168404Spjd zfs_error_aux(hdl, 436168404Spjd dgettext(TEXT_DOMAIN, "no such pool or dataset")); 437168404Spjd zfs_verror(hdl, EZFS_NOENT, fmt, ap); 438168404Spjd break; 439168404Spjd 440168404Spjd case EEXIST: 441168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 442168404Spjd "pool already exists")); 443168404Spjd zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 444168404Spjd break; 445168404Spjd 446168404Spjd case EBUSY: 447168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); 448185029Spjd zfs_verror(hdl, EZFS_BUSY, fmt, ap); 449168404Spjd break; 450168404Spjd 451168404Spjd case ENXIO: 452168404Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 453168404Spjd "one or more devices is currently unavailable")); 454168404Spjd zfs_verror(hdl, EZFS_BADDEV, fmt, ap); 455168404Spjd break; 456168404Spjd 457168404Spjd case ENAMETOOLONG: 458168404Spjd zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); 459168404Spjd break; 460168404Spjd 461168404Spjd case ENOTSUP: 462168404Spjd zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); 463168404Spjd break; 464168404Spjd 465168404Spjd case EINVAL: 466168404Spjd zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); 467168404Spjd break; 468168404Spjd 469185029Spjd case ENOSPC: 470185029Spjd case EDQUOT: 471185029Spjd zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 472185029Spjd return (-1); 473219089Spjd 474209962Smm case EAGAIN: 475209962Smm zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 476209962Smm "pool I/O is currently suspended")); 477209962Smm zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 478209962Smm break; 479185029Spjd 480219089Spjd case EROFS: 481219089Spjd zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); 482219089Spjd break; 483219089Spjd 484168404Spjd default: 485168404Spjd zfs_error_aux(hdl, strerror(error)); 486168404Spjd zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 487168404Spjd } 488168404Spjd 489168404Spjd va_end(ap); 490168404Spjd return (-1); 491168404Spjd} 492168404Spjd 493168404Spjd/* 494168404Spjd * Display an out of memory error message and abort the current program. 495168404Spjd */ 496168404Spjdint 497168404Spjdno_memory(libzfs_handle_t *hdl) 498168404Spjd{ 499168404Spjd return (zfs_error(hdl, EZFS_NOMEM, "internal error")); 500168404Spjd} 501168404Spjd 502168404Spjd/* 503168404Spjd * A safe form of malloc() which will die if the allocation fails. 504168404Spjd */ 505168404Spjdvoid * 506168404Spjdzfs_alloc(libzfs_handle_t *hdl, size_t size) 507168404Spjd{ 508168404Spjd void *data; 509168404Spjd 510168404Spjd if ((data = calloc(1, size)) == NULL) 511168404Spjd (void) no_memory(hdl); 512168404Spjd 513168404Spjd return (data); 514168404Spjd} 515168404Spjd 516168404Spjd/* 517219089Spjd * A safe form of asprintf() which will die if the allocation fails. 518219089Spjd */ 519219089Spjd/*PRINTFLIKE2*/ 520219089Spjdchar * 521219089Spjdzfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...) 522219089Spjd{ 523219089Spjd va_list ap; 524219089Spjd char *ret; 525219089Spjd int err; 526219089Spjd 527219089Spjd va_start(ap, fmt); 528219089Spjd 529219089Spjd err = vasprintf(&ret, fmt, ap); 530219089Spjd 531219089Spjd va_end(ap); 532219089Spjd 533219089Spjd if (err < 0) 534219089Spjd (void) no_memory(hdl); 535219089Spjd 536219089Spjd return (ret); 537219089Spjd} 538219089Spjd 539219089Spjd/* 540168404Spjd * A safe form of realloc(), which also zeroes newly allocated space. 541168404Spjd */ 542168404Spjdvoid * 543168404Spjdzfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) 544168404Spjd{ 545168404Spjd void *ret; 546168404Spjd 547168404Spjd if ((ret = realloc(ptr, newsize)) == NULL) { 548168404Spjd (void) no_memory(hdl); 549168404Spjd return (NULL); 550168404Spjd } 551168404Spjd 552168404Spjd bzero((char *)ret + oldsize, (newsize - oldsize)); 553168404Spjd return (ret); 554168404Spjd} 555168404Spjd 556168404Spjd/* 557168404Spjd * A safe form of strdup() which will die if the allocation fails. 558168404Spjd */ 559168404Spjdchar * 560168404Spjdzfs_strdup(libzfs_handle_t *hdl, const char *str) 561168404Spjd{ 562168404Spjd char *ret; 563168404Spjd 564168404Spjd if ((ret = strdup(str)) == NULL) 565168404Spjd (void) no_memory(hdl); 566168404Spjd 567168404Spjd return (ret); 568168404Spjd} 569168404Spjd 570168404Spjd/* 571168404Spjd * Convert a number to an appropriately human-readable output. 572168404Spjd */ 573168404Spjdvoid 574168404Spjdzfs_nicenum(uint64_t num, char *buf, size_t buflen) 575168404Spjd{ 576168404Spjd uint64_t n = num; 577168404Spjd int index = 0; 578168404Spjd char u; 579168404Spjd 580168404Spjd while (n >= 1024) { 581168404Spjd n /= 1024; 582168404Spjd index++; 583168404Spjd } 584168404Spjd 585168404Spjd u = " KMGTPE"[index]; 586168404Spjd 587168404Spjd if (index == 0) { 588168404Spjd (void) snprintf(buf, buflen, "%llu", n); 589168404Spjd } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { 590168404Spjd /* 591168404Spjd * If this is an even multiple of the base, always display 592168404Spjd * without any decimal precision. 593168404Spjd */ 594168404Spjd (void) snprintf(buf, buflen, "%llu%c", n, u); 595168404Spjd } else { 596168404Spjd /* 597168404Spjd * We want to choose a precision that reflects the best choice 598168404Spjd * for fitting in 5 characters. This can get rather tricky when 599168404Spjd * we have numbers that are very close to an order of magnitude. 600168404Spjd * For example, when displaying 10239 (which is really 9.999K), 601168404Spjd * we want only a single place of precision for 10.0K. We could 602168404Spjd * develop some complex heuristics for this, but it's much 603168404Spjd * easier just to try each combination in turn. 604168404Spjd */ 605168404Spjd int i; 606168404Spjd for (i = 2; i >= 0; i--) { 607185029Spjd if (snprintf(buf, buflen, "%.*f%c", i, 608185029Spjd (double)num / (1ULL << 10 * index), u) <= 5) 609168404Spjd break; 610168404Spjd } 611168404Spjd } 612168404Spjd} 613168404Spjd 614168404Spjdvoid 615168404Spjdlibzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) 616168404Spjd{ 617168404Spjd hdl->libzfs_printerr = printerr; 618168404Spjd} 619168404Spjd 620168484Spjdstatic int 621168484Spjdlibzfs_load(void) 622168484Spjd{ 623168484Spjd int error; 624168484Spjd 625168484Spjd if (modfind("zfs") < 0) { 626168484Spjd /* Not present in kernel, try loading it. */ 627168484Spjd if (kldload("zfs") < 0 || modfind("zfs") < 0) { 628168484Spjd if (errno != EEXIST) 629219089Spjd return (-1); 630168484Spjd } 631168484Spjd } 632168484Spjd return (0); 633168484Spjd} 634168484Spjd 635168404Spjdlibzfs_handle_t * 636168404Spjdlibzfs_init(void) 637168404Spjd{ 638168404Spjd libzfs_handle_t *hdl; 639168404Spjd 640219089Spjd if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) { 641168404Spjd return (NULL); 642168404Spjd } 643168404Spjd 644219089Spjd if (libzfs_load() < 0) { 645219089Spjd free(hdl); 646219089Spjd return (NULL); 647219089Spjd } 648219089Spjd 649168404Spjd if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { 650219089Spjd free(hdl); 651219089Spjd return (NULL); 652168404Spjd } 653168404Spjd 654168404Spjd if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { 655168404Spjd (void) close(hdl->libzfs_fd); 656168404Spjd free(hdl); 657168404Spjd return (NULL); 658168404Spjd } 659168404Spjd 660168404Spjd hdl->libzfs_sharetab = fopen(ZFS_EXPORTS_PATH, "r"); 661168404Spjd 662249643Smm if (libzfs_core_init() != 0) { 663249643Smm (void) close(hdl->libzfs_fd); 664249643Smm (void) fclose(hdl->libzfs_mnttab); 665249643Smm (void) fclose(hdl->libzfs_sharetab); 666249643Smm free(hdl); 667249643Smm return (NULL); 668249643Smm } 669249643Smm 670185029Spjd zfs_prop_init(); 671185029Spjd zpool_prop_init(); 672243674Smm zpool_feature_init(); 673209962Smm libzfs_mnttab_init(hdl); 674185029Spjd 675168404Spjd return (hdl); 676168404Spjd} 677168404Spjd 678168404Spjdvoid 679168404Spjdlibzfs_fini(libzfs_handle_t *hdl) 680168404Spjd{ 681168404Spjd (void) close(hdl->libzfs_fd); 682168404Spjd if (hdl->libzfs_mnttab) 683168404Spjd (void) fclose(hdl->libzfs_mnttab); 684168404Spjd if (hdl->libzfs_sharetab) 685168404Spjd (void) fclose(hdl->libzfs_sharetab); 686185029Spjd zfs_uninit_libshare(hdl); 687185029Spjd zpool_free_handles(hdl); 688219089Spjd#ifdef sun 689219089Spjd libzfs_fru_clear(hdl, B_TRUE); 690219089Spjd#endif 691168404Spjd namespace_clear(hdl); 692209962Smm libzfs_mnttab_fini(hdl); 693249643Smm libzfs_core_fini(); 694168404Spjd free(hdl); 695168404Spjd} 696168404Spjd 697168404Spjdlibzfs_handle_t * 698168404Spjdzpool_get_handle(zpool_handle_t *zhp) 699168404Spjd{ 700168404Spjd return (zhp->zpool_hdl); 701168404Spjd} 702168404Spjd 703168404Spjdlibzfs_handle_t * 704168404Spjdzfs_get_handle(zfs_handle_t *zhp) 705168404Spjd{ 706168404Spjd return (zhp->zfs_hdl); 707168404Spjd} 708168404Spjd 709185029Spjdzpool_handle_t * 710185029Spjdzfs_get_pool_handle(const zfs_handle_t *zhp) 711185029Spjd{ 712185029Spjd return (zhp->zpool_hdl); 713185029Spjd} 714185029Spjd 715168404Spjd/* 716168404Spjd * Given a name, determine whether or not it's a valid path 717168404Spjd * (starts with '/' or "./"). If so, walk the mnttab trying 718168404Spjd * to match the device number. If not, treat the path as an 719168404Spjd * fs/vol/snap name. 720168404Spjd */ 721168404Spjdzfs_handle_t * 722168404Spjdzfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype) 723168404Spjd{ 724219089Spjd struct stat64 statbuf; 725219089Spjd struct extmnttab entry; 726219089Spjd int ret; 727168404Spjd 728168404Spjd if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { 729168404Spjd /* 730168404Spjd * It's not a valid path, assume it's a name of type 'argtype'. 731168404Spjd */ 732168404Spjd return (zfs_open(hdl, path, argtype)); 733168404Spjd } 734168404Spjd 735219089Spjd if (stat64(path, &statbuf) != 0) { 736168404Spjd (void) fprintf(stderr, "%s: %s\n", path, strerror(errno)); 737168404Spjd return (NULL); 738168404Spjd } 739168404Spjd 740219089Spjd#ifdef sun 741219089Spjd rewind(hdl->libzfs_mnttab); 742219089Spjd while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) { 743219089Spjd if (makedevice(entry.mnt_major, entry.mnt_minor) == 744219089Spjd statbuf.st_dev) { 745219089Spjd break; 746219089Spjd } 747219089Spjd } 748219089Spjd#else 749219089Spjd { 750219089Spjd struct statfs sfs; 751219089Spjd 752220575Spjd ret = statfs(path, &sfs); 753220575Spjd if (ret == 0) 754220575Spjd statfs2mnttab(&sfs, &entry); 755220575Spjd else { 756219089Spjd (void) fprintf(stderr, "%s: %s\n", path, 757219089Spjd strerror(errno)); 758219089Spjd } 759219089Spjd } 760219089Spjd#endif /* sun */ 761219089Spjd if (ret != 0) { 762219089Spjd return (NULL); 763219089Spjd } 764219089Spjd 765219089Spjd if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { 766168404Spjd (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), 767168404Spjd path); 768168404Spjd return (NULL); 769168404Spjd } 770168404Spjd 771219089Spjd return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); 772168404Spjd} 773168404Spjd 774168404Spjd/* 775168404Spjd * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from 776168404Spjd * an ioctl(). 777168404Spjd */ 778168404Spjdint 779168404Spjdzcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) 780168404Spjd{ 781168404Spjd if (len == 0) 782219089Spjd len = 16 * 1024; 783168404Spjd zc->zc_nvlist_dst_size = len; 784168404Spjd if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 785168404Spjd zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0) 786168404Spjd return (-1); 787168404Spjd 788168404Spjd return (0); 789168404Spjd} 790168404Spjd 791168404Spjd/* 792168404Spjd * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will 793168404Spjd * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was 794168404Spjd * filled in by the kernel to indicate the actual required size. 795168404Spjd */ 796168404Spjdint 797168404Spjdzcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) 798168404Spjd{ 799168404Spjd free((void *)(uintptr_t)zc->zc_nvlist_dst); 800168404Spjd if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 801168404Spjd zfs_alloc(hdl, zc->zc_nvlist_dst_size)) 802168404Spjd == 0) 803168404Spjd return (-1); 804168404Spjd 805168404Spjd return (0); 806168404Spjd} 807168404Spjd 808168404Spjd/* 809168404Spjd * Called to free the src and dst nvlists stored in the command structure. 810168404Spjd */ 811168404Spjdvoid 812168404Spjdzcmd_free_nvlists(zfs_cmd_t *zc) 813168404Spjd{ 814185029Spjd free((void *)(uintptr_t)zc->zc_nvlist_conf); 815168404Spjd free((void *)(uintptr_t)zc->zc_nvlist_src); 816168404Spjd free((void *)(uintptr_t)zc->zc_nvlist_dst); 817168404Spjd} 818168404Spjd 819185029Spjdstatic int 820185029Spjdzcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, 821185029Spjd nvlist_t *nvl) 822168404Spjd{ 823168404Spjd char *packed; 824168404Spjd size_t len; 825168404Spjd 826168404Spjd verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0); 827168404Spjd 828168404Spjd if ((packed = zfs_alloc(hdl, len)) == NULL) 829168404Spjd return (-1); 830168404Spjd 831168404Spjd verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 832168404Spjd 833185029Spjd *outnv = (uint64_t)(uintptr_t)packed; 834185029Spjd *outlen = len; 835168404Spjd 836168404Spjd return (0); 837168404Spjd} 838168404Spjd 839185029Spjdint 840185029Spjdzcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 841185029Spjd{ 842185029Spjd return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, 843185029Spjd &zc->zc_nvlist_conf_size, nvl)); 844185029Spjd} 845185029Spjd 846185029Spjdint 847185029Spjdzcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 848185029Spjd{ 849185029Spjd return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, 850185029Spjd &zc->zc_nvlist_src_size, nvl)); 851185029Spjd} 852185029Spjd 853168404Spjd/* 854168404Spjd * Unpacks an nvlist from the ZFS ioctl command structure. 855168404Spjd */ 856168404Spjdint 857168404Spjdzcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) 858168404Spjd{ 859168404Spjd if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, 860168404Spjd zc->zc_nvlist_dst_size, nvlp, 0) != 0) 861168404Spjd return (no_memory(hdl)); 862168404Spjd 863168404Spjd return (0); 864168404Spjd} 865168404Spjd 866185029Spjdint 867249643Smmzfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) 868185029Spjd{ 869249643Smm return (ioctl(hdl->libzfs_fd, request, zc)); 870185029Spjd} 871185029Spjd 872185029Spjd/* 873185029Spjd * ================================================================ 874185029Spjd * API shared by zfs and zpool property management 875185029Spjd * ================================================================ 876185029Spjd */ 877185029Spjd 878168404Spjdstatic void 879185029Spjdzprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) 880168404Spjd{ 881185029Spjd zprop_list_t *pl = cbp->cb_proplist; 882168404Spjd int i; 883168404Spjd char *title; 884168404Spjd size_t len; 885168404Spjd 886168404Spjd cbp->cb_first = B_FALSE; 887168404Spjd if (cbp->cb_scripted) 888168404Spjd return; 889168404Spjd 890168404Spjd /* 891168404Spjd * Start with the length of the column headers. 892168404Spjd */ 893168404Spjd cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); 894168404Spjd cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, 895168404Spjd "PROPERTY")); 896168404Spjd cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, 897168404Spjd "VALUE")); 898219089Spjd cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN, 899219089Spjd "RECEIVED")); 900168404Spjd cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, 901168404Spjd "SOURCE")); 902168404Spjd 903209962Smm /* first property is always NAME */ 904209962Smm assert(cbp->cb_proplist->pl_prop == 905209962Smm ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME)); 906209962Smm 907168404Spjd /* 908168404Spjd * Go through and calculate the widths for each column. For the 909168404Spjd * 'source' column, we kludge it up by taking the worst-case scenario of 910168404Spjd * inheriting from the longest name. This is acceptable because in the 911168404Spjd * majority of cases 'SOURCE' is the last column displayed, and we don't 912168404Spjd * use the width anyway. Note that the 'VALUE' column can be oversized, 913219089Spjd * if the name of the property is much longer than any values we find. 914168404Spjd */ 915168404Spjd for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 916168404Spjd /* 917168404Spjd * 'PROPERTY' column 918168404Spjd */ 919185029Spjd if (pl->pl_prop != ZPROP_INVAL) { 920185029Spjd const char *propname = (type == ZFS_TYPE_POOL) ? 921185029Spjd zpool_prop_to_name(pl->pl_prop) : 922185029Spjd zfs_prop_to_name(pl->pl_prop); 923185029Spjd 924185029Spjd len = strlen(propname); 925168404Spjd if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 926168404Spjd cbp->cb_colwidths[GET_COL_PROPERTY] = len; 927168404Spjd } else { 928168404Spjd len = strlen(pl->pl_user_prop); 929168404Spjd if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 930168404Spjd cbp->cb_colwidths[GET_COL_PROPERTY] = len; 931168404Spjd } 932168404Spjd 933168404Spjd /* 934209962Smm * 'VALUE' column. The first property is always the 'name' 935209962Smm * property that was tacked on either by /sbin/zfs's 936209962Smm * zfs_do_get() or when calling zprop_expand_list(), so we 937209962Smm * ignore its width. If the user specified the name property 938209962Smm * to display, then it will be later in the list in any case. 939168404Spjd */ 940209962Smm if (pl != cbp->cb_proplist && 941168404Spjd pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) 942168404Spjd cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; 943168404Spjd 944219089Spjd /* 'RECEIVED' column. */ 945219089Spjd if (pl != cbp->cb_proplist && 946219089Spjd pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD]) 947219089Spjd cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width; 948219089Spjd 949168404Spjd /* 950168404Spjd * 'NAME' and 'SOURCE' columns 951168404Spjd */ 952185029Spjd if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME : 953185029Spjd ZFS_PROP_NAME) && 954168404Spjd pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { 955168404Spjd cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; 956168404Spjd cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + 957168404Spjd strlen(dgettext(TEXT_DOMAIN, "inherited from")); 958168404Spjd } 959168404Spjd } 960168404Spjd 961168404Spjd /* 962168404Spjd * Now go through and print the headers. 963168404Spjd */ 964219089Spjd for (i = 0; i < ZFS_GET_NCOLS; i++) { 965168404Spjd switch (cbp->cb_columns[i]) { 966168404Spjd case GET_COL_NAME: 967168404Spjd title = dgettext(TEXT_DOMAIN, "NAME"); 968168404Spjd break; 969168404Spjd case GET_COL_PROPERTY: 970168404Spjd title = dgettext(TEXT_DOMAIN, "PROPERTY"); 971168404Spjd break; 972168404Spjd case GET_COL_VALUE: 973168404Spjd title = dgettext(TEXT_DOMAIN, "VALUE"); 974168404Spjd break; 975219089Spjd case GET_COL_RECVD: 976219089Spjd title = dgettext(TEXT_DOMAIN, "RECEIVED"); 977219089Spjd break; 978168404Spjd case GET_COL_SOURCE: 979168404Spjd title = dgettext(TEXT_DOMAIN, "SOURCE"); 980168404Spjd break; 981168404Spjd default: 982168404Spjd title = NULL; 983168404Spjd } 984168404Spjd 985168404Spjd if (title != NULL) { 986219089Spjd if (i == (ZFS_GET_NCOLS - 1) || 987219089Spjd cbp->cb_columns[i + 1] == GET_COL_NONE) 988168404Spjd (void) printf("%s", title); 989168404Spjd else 990168404Spjd (void) printf("%-*s ", 991168404Spjd cbp->cb_colwidths[cbp->cb_columns[i]], 992168404Spjd title); 993168404Spjd } 994168404Spjd } 995168404Spjd (void) printf("\n"); 996168404Spjd} 997168404Spjd 998168404Spjd/* 999168404Spjd * Display a single line of output, according to the settings in the callback 1000168404Spjd * structure. 1001168404Spjd */ 1002168404Spjdvoid 1003185029Spjdzprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, 1004185029Spjd const char *propname, const char *value, zprop_source_t sourcetype, 1005219089Spjd const char *source, const char *recvd_value) 1006168404Spjd{ 1007168404Spjd int i; 1008168404Spjd const char *str; 1009168404Spjd char buf[128]; 1010168404Spjd 1011168404Spjd /* 1012168404Spjd * Ignore those source types that the user has chosen to ignore. 1013168404Spjd */ 1014168404Spjd if ((sourcetype & cbp->cb_sources) == 0) 1015168404Spjd return; 1016168404Spjd 1017168404Spjd if (cbp->cb_first) 1018185029Spjd zprop_print_headers(cbp, cbp->cb_type); 1019168404Spjd 1020219089Spjd for (i = 0; i < ZFS_GET_NCOLS; i++) { 1021168404Spjd switch (cbp->cb_columns[i]) { 1022168404Spjd case GET_COL_NAME: 1023168404Spjd str = name; 1024168404Spjd break; 1025168404Spjd 1026168404Spjd case GET_COL_PROPERTY: 1027168404Spjd str = propname; 1028168404Spjd break; 1029168404Spjd 1030168404Spjd case GET_COL_VALUE: 1031168404Spjd str = value; 1032168404Spjd break; 1033168404Spjd 1034168404Spjd case GET_COL_SOURCE: 1035168404Spjd switch (sourcetype) { 1036185029Spjd case ZPROP_SRC_NONE: 1037168404Spjd str = "-"; 1038168404Spjd break; 1039168404Spjd 1040185029Spjd case ZPROP_SRC_DEFAULT: 1041168404Spjd str = "default"; 1042168404Spjd break; 1043168404Spjd 1044185029Spjd case ZPROP_SRC_LOCAL: 1045168404Spjd str = "local"; 1046168404Spjd break; 1047168404Spjd 1048185029Spjd case ZPROP_SRC_TEMPORARY: 1049168404Spjd str = "temporary"; 1050168404Spjd break; 1051168404Spjd 1052185029Spjd case ZPROP_SRC_INHERITED: 1053168404Spjd (void) snprintf(buf, sizeof (buf), 1054168404Spjd "inherited from %s", source); 1055168404Spjd str = buf; 1056168404Spjd break; 1057219089Spjd case ZPROP_SRC_RECEIVED: 1058219089Spjd str = "received"; 1059219089Spjd break; 1060168404Spjd } 1061168404Spjd break; 1062168404Spjd 1063219089Spjd case GET_COL_RECVD: 1064219089Spjd str = (recvd_value == NULL ? "-" : recvd_value); 1065219089Spjd break; 1066219089Spjd 1067168404Spjd default: 1068168404Spjd continue; 1069168404Spjd } 1070168404Spjd 1071219089Spjd if (cbp->cb_columns[i + 1] == GET_COL_NONE) 1072168404Spjd (void) printf("%s", str); 1073168404Spjd else if (cbp->cb_scripted) 1074168404Spjd (void) printf("%s\t", str); 1075168404Spjd else 1076168404Spjd (void) printf("%-*s ", 1077168404Spjd cbp->cb_colwidths[cbp->cb_columns[i]], 1078168404Spjd str); 1079168404Spjd } 1080168404Spjd 1081168404Spjd (void) printf("\n"); 1082168404Spjd} 1083185029Spjd 1084185029Spjd/* 1085185029Spjd * Given a numeric suffix, convert the value into a number of bits that the 1086185029Spjd * resulting value must be shifted. 1087185029Spjd */ 1088185029Spjdstatic int 1089185029Spjdstr2shift(libzfs_handle_t *hdl, const char *buf) 1090185029Spjd{ 1091185029Spjd const char *ends = "BKMGTPEZ"; 1092185029Spjd int i; 1093185029Spjd 1094185029Spjd if (buf[0] == '\0') 1095185029Spjd return (0); 1096185029Spjd for (i = 0; i < strlen(ends); i++) { 1097185029Spjd if (toupper(buf[0]) == ends[i]) 1098185029Spjd break; 1099185029Spjd } 1100185029Spjd if (i == strlen(ends)) { 1101185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1102185029Spjd "invalid numeric suffix '%s'"), buf); 1103185029Spjd return (-1); 1104185029Spjd } 1105185029Spjd 1106185029Spjd /* 1107185029Spjd * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 1108185029Spjd * allow 'BB' - that's just weird. 1109185029Spjd */ 1110185029Spjd if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 1111185029Spjd toupper(buf[0]) != 'B')) 1112185029Spjd return (10*i); 1113185029Spjd 1114185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1115185029Spjd "invalid numeric suffix '%s'"), buf); 1116185029Spjd return (-1); 1117185029Spjd} 1118185029Spjd 1119185029Spjd/* 1120185029Spjd * Convert a string of the form '100G' into a real number. Used when setting 1121185029Spjd * properties or creating a volume. 'buf' is used to place an extended error 1122185029Spjd * message for the caller to use. 1123185029Spjd */ 1124185029Spjdint 1125185029Spjdzfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 1126185029Spjd{ 1127185029Spjd char *end; 1128185029Spjd int shift; 1129185029Spjd 1130185029Spjd *num = 0; 1131185029Spjd 1132185029Spjd /* Check to see if this looks like a number. */ 1133185029Spjd if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 1134185029Spjd if (hdl) 1135185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1136185029Spjd "bad numeric value '%s'"), value); 1137185029Spjd return (-1); 1138185029Spjd } 1139185029Spjd 1140219089Spjd /* Rely on strtoull() to process the numeric portion. */ 1141185029Spjd errno = 0; 1142209962Smm *num = strtoull(value, &end, 10); 1143185029Spjd 1144185029Spjd /* 1145185029Spjd * Check for ERANGE, which indicates that the value is too large to fit 1146185029Spjd * in a 64-bit value. 1147185029Spjd */ 1148185029Spjd if (errno == ERANGE) { 1149185029Spjd if (hdl) 1150185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1151185029Spjd "numeric value is too large")); 1152185029Spjd return (-1); 1153185029Spjd } 1154185029Spjd 1155185029Spjd /* 1156185029Spjd * If we have a decimal value, then do the computation with floating 1157185029Spjd * point arithmetic. Otherwise, use standard arithmetic. 1158185029Spjd */ 1159185029Spjd if (*end == '.') { 1160185029Spjd double fval = strtod(value, &end); 1161185029Spjd 1162185029Spjd if ((shift = str2shift(hdl, end)) == -1) 1163185029Spjd return (-1); 1164185029Spjd 1165185029Spjd fval *= pow(2, shift); 1166185029Spjd 1167185029Spjd if (fval > UINT64_MAX) { 1168185029Spjd if (hdl) 1169185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1170185029Spjd "numeric value is too large")); 1171185029Spjd return (-1); 1172185029Spjd } 1173185029Spjd 1174185029Spjd *num = (uint64_t)fval; 1175185029Spjd } else { 1176185029Spjd if ((shift = str2shift(hdl, end)) == -1) 1177185029Spjd return (-1); 1178185029Spjd 1179185029Spjd /* Check for overflow */ 1180185029Spjd if (shift >= 64 || (*num << shift) >> shift != *num) { 1181185029Spjd if (hdl) 1182185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1183185029Spjd "numeric value is too large")); 1184185029Spjd return (-1); 1185185029Spjd } 1186185029Spjd 1187185029Spjd *num <<= shift; 1188185029Spjd } 1189185029Spjd 1190185029Spjd return (0); 1191185029Spjd} 1192185029Spjd 1193185029Spjd/* 1194185029Spjd * Given a propname=value nvpair to set, parse any numeric properties 1195185029Spjd * (index, boolean, etc) if they are specified as strings and add the 1196185029Spjd * resulting nvpair to the returned nvlist. 1197185029Spjd * 1198185029Spjd * At the DSL layer, all properties are either 64-bit numbers or strings. 1199185029Spjd * We want the user to be able to ignore this fact and specify properties 1200185029Spjd * as native values (numbers, for example) or as strings (to simplify 1201185029Spjd * command line utilities). This also handles converting index types 1202185029Spjd * (compression, checksum, etc) from strings to their on-disk index. 1203185029Spjd */ 1204185029Spjdint 1205185029Spjdzprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, 1206185029Spjd zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp, 1207185029Spjd const char *errbuf) 1208185029Spjd{ 1209185029Spjd data_type_t datatype = nvpair_type(elem); 1210185029Spjd zprop_type_t proptype; 1211185029Spjd const char *propname; 1212185029Spjd char *value; 1213185029Spjd boolean_t isnone = B_FALSE; 1214185029Spjd 1215185029Spjd if (type == ZFS_TYPE_POOL) { 1216185029Spjd proptype = zpool_prop_get_type(prop); 1217185029Spjd propname = zpool_prop_to_name(prop); 1218185029Spjd } else { 1219185029Spjd proptype = zfs_prop_get_type(prop); 1220185029Spjd propname = zfs_prop_to_name(prop); 1221185029Spjd } 1222185029Spjd 1223185029Spjd /* 1224185029Spjd * Convert any properties to the internal DSL value types. 1225185029Spjd */ 1226185029Spjd *svalp = NULL; 1227185029Spjd *ivalp = 0; 1228185029Spjd 1229185029Spjd switch (proptype) { 1230185029Spjd case PROP_TYPE_STRING: 1231185029Spjd if (datatype != DATA_TYPE_STRING) { 1232185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1233185029Spjd "'%s' must be a string"), nvpair_name(elem)); 1234185029Spjd goto error; 1235185029Spjd } 1236185029Spjd (void) nvpair_value_string(elem, svalp); 1237185029Spjd if (strlen(*svalp) >= ZFS_MAXPROPLEN) { 1238185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1239185029Spjd "'%s' is too long"), nvpair_name(elem)); 1240185029Spjd goto error; 1241185029Spjd } 1242185029Spjd break; 1243185029Spjd 1244185029Spjd case PROP_TYPE_NUMBER: 1245185029Spjd if (datatype == DATA_TYPE_STRING) { 1246185029Spjd (void) nvpair_value_string(elem, &value); 1247185029Spjd if (strcmp(value, "none") == 0) { 1248185029Spjd isnone = B_TRUE; 1249185029Spjd } else if (zfs_nicestrtonum(hdl, value, ivalp) 1250185029Spjd != 0) { 1251185029Spjd goto error; 1252185029Spjd } 1253185029Spjd } else if (datatype == DATA_TYPE_UINT64) { 1254185029Spjd (void) nvpair_value_uint64(elem, ivalp); 1255185029Spjd } else { 1256185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1257185029Spjd "'%s' must be a number"), nvpair_name(elem)); 1258185029Spjd goto error; 1259185029Spjd } 1260185029Spjd 1261185029Spjd /* 1262185029Spjd * Quota special: force 'none' and don't allow 0. 1263185029Spjd */ 1264185029Spjd if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && 1265185029Spjd (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { 1266185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1267185029Spjd "use 'none' to disable quota/refquota")); 1268185029Spjd goto error; 1269185029Spjd } 1270265754Sdelphij 1271265754Sdelphij /* 1272265754Sdelphij * Special handling for "*_limit=none". In this case it's not 1273265754Sdelphij * 0 but UINT64_MAX. 1274265754Sdelphij */ 1275265754Sdelphij if ((type & ZFS_TYPE_DATASET) && isnone && 1276265754Sdelphij (prop == ZFS_PROP_FILESYSTEM_LIMIT || 1277265754Sdelphij prop == ZFS_PROP_SNAPSHOT_LIMIT)) { 1278265754Sdelphij *ivalp = UINT64_MAX; 1279265754Sdelphij } 1280185029Spjd break; 1281185029Spjd 1282185029Spjd case PROP_TYPE_INDEX: 1283185029Spjd if (datatype != DATA_TYPE_STRING) { 1284185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1285185029Spjd "'%s' must be a string"), nvpair_name(elem)); 1286185029Spjd goto error; 1287185029Spjd } 1288185029Spjd 1289185029Spjd (void) nvpair_value_string(elem, &value); 1290185029Spjd 1291185029Spjd if (zprop_string_to_index(prop, value, ivalp, type) != 0) { 1292185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1293185029Spjd "'%s' must be one of '%s'"), propname, 1294185029Spjd zprop_values(prop, type)); 1295185029Spjd goto error; 1296185029Spjd } 1297185029Spjd break; 1298185029Spjd 1299185029Spjd default: 1300185029Spjd abort(); 1301185029Spjd } 1302185029Spjd 1303185029Spjd /* 1304185029Spjd * Add the result to our return set of properties. 1305185029Spjd */ 1306185029Spjd if (*svalp != NULL) { 1307185029Spjd if (nvlist_add_string(ret, propname, *svalp) != 0) { 1308185029Spjd (void) no_memory(hdl); 1309185029Spjd return (-1); 1310185029Spjd } 1311185029Spjd } else { 1312185029Spjd if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { 1313185029Spjd (void) no_memory(hdl); 1314185029Spjd return (-1); 1315185029Spjd } 1316185029Spjd } 1317185029Spjd 1318185029Spjd return (0); 1319185029Spjderror: 1320185029Spjd (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1321185029Spjd return (-1); 1322185029Spjd} 1323185029Spjd 1324185029Spjdstatic int 1325185029Spjdaddlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp, 1326185029Spjd zfs_type_t type) 1327185029Spjd{ 1328185029Spjd int prop; 1329185029Spjd zprop_list_t *entry; 1330185029Spjd 1331185029Spjd prop = zprop_name_to_prop(propname, type); 1332185029Spjd 1333185029Spjd if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type)) 1334185029Spjd prop = ZPROP_INVAL; 1335185029Spjd 1336185029Spjd /* 1337185029Spjd * When no property table entry can be found, return failure if 1338185029Spjd * this is a pool property or if this isn't a user-defined 1339185029Spjd * dataset property, 1340185029Spjd */ 1341243674Smm if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL && 1342243674Smm !zpool_prop_feature(propname) && 1343243674Smm !zpool_prop_unsupported(propname)) || 1344243674Smm (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) && 1345243674Smm !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) { 1346185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1347185029Spjd "invalid property '%s'"), propname); 1348185029Spjd return (zfs_error(hdl, EZFS_BADPROP, 1349185029Spjd dgettext(TEXT_DOMAIN, "bad property list"))); 1350185029Spjd } 1351185029Spjd 1352185029Spjd if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 1353185029Spjd return (-1); 1354185029Spjd 1355185029Spjd entry->pl_prop = prop; 1356185029Spjd if (prop == ZPROP_INVAL) { 1357243674Smm if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == 1358243674Smm NULL) { 1359185029Spjd free(entry); 1360185029Spjd return (-1); 1361185029Spjd } 1362185029Spjd entry->pl_width = strlen(propname); 1363185029Spjd } else { 1364185029Spjd entry->pl_width = zprop_width(prop, &entry->pl_fixed, 1365185029Spjd type); 1366185029Spjd } 1367185029Spjd 1368185029Spjd *listp = entry; 1369185029Spjd 1370185029Spjd return (0); 1371185029Spjd} 1372185029Spjd 1373185029Spjd/* 1374185029Spjd * Given a comma-separated list of properties, construct a property list 1375185029Spjd * containing both user-defined and native properties. This function will 1376185029Spjd * return a NULL list if 'all' is specified, which can later be expanded 1377185029Spjd * by zprop_expand_list(). 1378185029Spjd */ 1379185029Spjdint 1380185029Spjdzprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, 1381185029Spjd zfs_type_t type) 1382185029Spjd{ 1383185029Spjd *listp = NULL; 1384185029Spjd 1385185029Spjd /* 1386185029Spjd * If 'all' is specified, return a NULL list. 1387185029Spjd */ 1388185029Spjd if (strcmp(props, "all") == 0) 1389185029Spjd return (0); 1390185029Spjd 1391185029Spjd /* 1392185029Spjd * If no props were specified, return an error. 1393185029Spjd */ 1394185029Spjd if (props[0] == '\0') { 1395185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1396185029Spjd "no properties specified")); 1397185029Spjd return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 1398185029Spjd "bad property list"))); 1399185029Spjd } 1400185029Spjd 1401185029Spjd /* 1402185029Spjd * It would be nice to use getsubopt() here, but the inclusion of column 1403185029Spjd * aliases makes this more effort than it's worth. 1404185029Spjd */ 1405185029Spjd while (*props != '\0') { 1406185029Spjd size_t len; 1407185029Spjd char *p; 1408185029Spjd char c; 1409185029Spjd 1410185029Spjd if ((p = strchr(props, ',')) == NULL) { 1411185029Spjd len = strlen(props); 1412185029Spjd p = props + len; 1413185029Spjd } else { 1414185029Spjd len = p - props; 1415185029Spjd } 1416185029Spjd 1417185029Spjd /* 1418185029Spjd * Check for empty options. 1419185029Spjd */ 1420185029Spjd if (len == 0) { 1421185029Spjd zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1422185029Spjd "empty property name")); 1423185029Spjd return (zfs_error(hdl, EZFS_BADPROP, 1424185029Spjd dgettext(TEXT_DOMAIN, "bad property list"))); 1425185029Spjd } 1426185029Spjd 1427185029Spjd /* 1428185029Spjd * Check all regular property names. 1429185029Spjd */ 1430185029Spjd c = props[len]; 1431185029Spjd props[len] = '\0'; 1432185029Spjd 1433185029Spjd if (strcmp(props, "space") == 0) { 1434185029Spjd static char *spaceprops[] = { 1435185029Spjd "name", "avail", "used", "usedbysnapshots", 1436185029Spjd "usedbydataset", "usedbyrefreservation", 1437185029Spjd "usedbychildren", NULL 1438185029Spjd }; 1439185029Spjd int i; 1440185029Spjd 1441185029Spjd for (i = 0; spaceprops[i]; i++) { 1442185029Spjd if (addlist(hdl, spaceprops[i], listp, type)) 1443185029Spjd return (-1); 1444185029Spjd listp = &(*listp)->pl_next; 1445185029Spjd } 1446185029Spjd } else { 1447185029Spjd if (addlist(hdl, props, listp, type)) 1448185029Spjd return (-1); 1449185029Spjd listp = &(*listp)->pl_next; 1450185029Spjd } 1451185029Spjd 1452185029Spjd props = p; 1453185029Spjd if (c == ',') 1454185029Spjd props++; 1455185029Spjd } 1456185029Spjd 1457185029Spjd return (0); 1458185029Spjd} 1459185029Spjd 1460185029Spjdvoid 1461185029Spjdzprop_free_list(zprop_list_t *pl) 1462185029Spjd{ 1463185029Spjd zprop_list_t *next; 1464185029Spjd 1465185029Spjd while (pl != NULL) { 1466185029Spjd next = pl->pl_next; 1467185029Spjd free(pl->pl_user_prop); 1468185029Spjd free(pl); 1469185029Spjd pl = next; 1470185029Spjd } 1471185029Spjd} 1472185029Spjd 1473185029Spjdtypedef struct expand_data { 1474185029Spjd zprop_list_t **last; 1475185029Spjd libzfs_handle_t *hdl; 1476185029Spjd zfs_type_t type; 1477185029Spjd} expand_data_t; 1478185029Spjd 1479185029Spjdint 1480185029Spjdzprop_expand_list_cb(int prop, void *cb) 1481185029Spjd{ 1482185029Spjd zprop_list_t *entry; 1483185029Spjd expand_data_t *edp = cb; 1484185029Spjd 1485185029Spjd if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL) 1486185029Spjd return (ZPROP_INVAL); 1487185029Spjd 1488185029Spjd entry->pl_prop = prop; 1489185029Spjd entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); 1490185029Spjd entry->pl_all = B_TRUE; 1491185029Spjd 1492185029Spjd *(edp->last) = entry; 1493185029Spjd edp->last = &entry->pl_next; 1494185029Spjd 1495185029Spjd return (ZPROP_CONT); 1496185029Spjd} 1497185029Spjd 1498185029Spjdint 1499185029Spjdzprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) 1500185029Spjd{ 1501185029Spjd zprop_list_t *entry; 1502185029Spjd zprop_list_t **last; 1503185029Spjd expand_data_t exp; 1504185029Spjd 1505185029Spjd if (*plp == NULL) { 1506185029Spjd /* 1507185029Spjd * If this is the very first time we've been called for an 'all' 1508185029Spjd * specification, expand the list to include all native 1509185029Spjd * properties. 1510185029Spjd */ 1511185029Spjd last = plp; 1512185029Spjd 1513185029Spjd exp.last = last; 1514185029Spjd exp.hdl = hdl; 1515185029Spjd exp.type = type; 1516185029Spjd 1517185029Spjd if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, 1518185029Spjd B_FALSE, type) == ZPROP_INVAL) 1519185029Spjd return (-1); 1520185029Spjd 1521185029Spjd /* 1522185029Spjd * Add 'name' to the beginning of the list, which is handled 1523185029Spjd * specially. 1524185029Spjd */ 1525185029Spjd if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 1526185029Spjd return (-1); 1527185029Spjd 1528185029Spjd entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : 1529185029Spjd ZFS_PROP_NAME; 1530185029Spjd entry->pl_width = zprop_width(entry->pl_prop, 1531185029Spjd &entry->pl_fixed, type); 1532185029Spjd entry->pl_all = B_TRUE; 1533185029Spjd entry->pl_next = *plp; 1534185029Spjd *plp = entry; 1535185029Spjd } 1536185029Spjd return (0); 1537185029Spjd} 1538185029Spjd 1539185029Spjdint 1540185029Spjdzprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, 1541185029Spjd zfs_type_t type) 1542185029Spjd{ 1543185029Spjd return (zprop_iter_common(func, cb, show_all, ordered, type)); 1544185029Spjd} 1545