1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 228811SEric.Taylor@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens /* 27789Sahrens * Internal utility routines for the ZFS library. 28789Sahrens */ 29789Sahrens 30789Sahrens #include <errno.h> 31789Sahrens #include <fcntl.h> 32789Sahrens #include <libintl.h> 33789Sahrens #include <stdarg.h> 34789Sahrens #include <stdio.h> 35789Sahrens #include <stdlib.h> 36789Sahrens #include <strings.h> 37789Sahrens #include <unistd.h> 385094Slling #include <ctype.h> 395094Slling #include <math.h> 40789Sahrens #include <sys/mnttab.h> 413635Sck153898 #include <sys/mntent.h> 423635Sck153898 #include <sys/types.h> 43789Sahrens 44789Sahrens #include <libzfs.h> 45789Sahrens 46789Sahrens #include "libzfs_impl.h" 474787Sahrens #include "zfs_prop.h" 48789Sahrens 492082Seschrock int 502082Seschrock libzfs_errno(libzfs_handle_t *hdl) 512082Seschrock { 522082Seschrock return (hdl->libzfs_error); 532082Seschrock } 54789Sahrens 552082Seschrock const char * 562082Seschrock libzfs_error_action(libzfs_handle_t *hdl) 572082Seschrock { 582082Seschrock return (hdl->libzfs_action); 592082Seschrock } 602082Seschrock 612082Seschrock const char * 622082Seschrock libzfs_error_description(libzfs_handle_t *hdl) 632082Seschrock { 642082Seschrock if (hdl->libzfs_desc[0] != '\0') 652082Seschrock return (hdl->libzfs_desc); 66789Sahrens 672082Seschrock switch (hdl->libzfs_error) { 682082Seschrock case EZFS_NOMEM: 692082Seschrock return (dgettext(TEXT_DOMAIN, "out of memory")); 702082Seschrock case EZFS_BADPROP: 712082Seschrock return (dgettext(TEXT_DOMAIN, "invalid property value")); 722082Seschrock case EZFS_PROPREADONLY: 732082Seschrock return (dgettext(TEXT_DOMAIN, "read only property")); 742082Seschrock case EZFS_PROPTYPE: 752082Seschrock return (dgettext(TEXT_DOMAIN, "property doesn't apply to " 762082Seschrock "datasets of this type")); 772082Seschrock case EZFS_PROPNONINHERIT: 782082Seschrock return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); 792082Seschrock case EZFS_PROPSPACE: 802082Seschrock return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); 812082Seschrock case EZFS_BADTYPE: 822082Seschrock return (dgettext(TEXT_DOMAIN, "operation not applicable to " 832082Seschrock "datasets of this type")); 842082Seschrock case EZFS_BUSY: 852082Seschrock return (dgettext(TEXT_DOMAIN, "pool or dataset is busy")); 862082Seschrock case EZFS_EXISTS: 872082Seschrock return (dgettext(TEXT_DOMAIN, "pool or dataset exists")); 882082Seschrock case EZFS_NOENT: 892082Seschrock return (dgettext(TEXT_DOMAIN, "no such pool or dataset")); 902082Seschrock case EZFS_BADSTREAM: 912082Seschrock return (dgettext(TEXT_DOMAIN, "invalid backup stream")); 922082Seschrock case EZFS_DSREADONLY: 932082Seschrock return (dgettext(TEXT_DOMAIN, "dataset is read only")); 942082Seschrock case EZFS_VOLTOOBIG: 952082Seschrock return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for " 962082Seschrock "this system")); 972082Seschrock case EZFS_VOLHASDATA: 982082Seschrock return (dgettext(TEXT_DOMAIN, "volume has data")); 992082Seschrock case EZFS_INVALIDNAME: 1002082Seschrock return (dgettext(TEXT_DOMAIN, "invalid name")); 1012082Seschrock case EZFS_BADRESTORE: 1022082Seschrock return (dgettext(TEXT_DOMAIN, "unable to restore to " 1032082Seschrock "destination")); 1042082Seschrock case EZFS_BADBACKUP: 1052082Seschrock return (dgettext(TEXT_DOMAIN, "backup failed")); 1062082Seschrock case EZFS_BADTARGET: 1072082Seschrock return (dgettext(TEXT_DOMAIN, "invalid target vdev")); 1082082Seschrock case EZFS_NODEVICE: 1092082Seschrock return (dgettext(TEXT_DOMAIN, "no such device in pool")); 1102082Seschrock case EZFS_BADDEV: 1112082Seschrock return (dgettext(TEXT_DOMAIN, "invalid device")); 1122082Seschrock case EZFS_NOREPLICAS: 1132082Seschrock return (dgettext(TEXT_DOMAIN, "no valid replicas")); 1142082Seschrock case EZFS_RESILVERING: 1152082Seschrock return (dgettext(TEXT_DOMAIN, "currently resilvering")); 1162082Seschrock case EZFS_BADVERSION: 1172082Seschrock return (dgettext(TEXT_DOMAIN, "unsupported version")); 1182082Seschrock case EZFS_POOLUNAVAIL: 1192082Seschrock return (dgettext(TEXT_DOMAIN, "pool is unavailable")); 1202082Seschrock case EZFS_DEVOVERFLOW: 1212082Seschrock return (dgettext(TEXT_DOMAIN, "too many devices in one vdev")); 1222082Seschrock case EZFS_BADPATH: 1232082Seschrock return (dgettext(TEXT_DOMAIN, "must be an absolute path")); 1242082Seschrock case EZFS_CROSSTARGET: 1252082Seschrock return (dgettext(TEXT_DOMAIN, "operation crosses datasets or " 1262082Seschrock "pools")); 1272082Seschrock case EZFS_ZONED: 1282082Seschrock return (dgettext(TEXT_DOMAIN, "dataset in use by local zone")); 1292082Seschrock case EZFS_MOUNTFAILED: 1302082Seschrock return (dgettext(TEXT_DOMAIN, "mount failed")); 1312082Seschrock case EZFS_UMOUNTFAILED: 1322082Seschrock return (dgettext(TEXT_DOMAIN, "umount failed")); 1333126Sahl case EZFS_UNSHARENFSFAILED: 1342082Seschrock return (dgettext(TEXT_DOMAIN, "unshare(1M) failed")); 1353126Sahl case EZFS_SHARENFSFAILED: 1362082Seschrock return (dgettext(TEXT_DOMAIN, "share(1M) failed")); 1375331Samw case EZFS_UNSHARESMBFAILED: 1385331Samw return (dgettext(TEXT_DOMAIN, "smb remove share failed")); 1395331Samw case EZFS_SHARESMBFAILED: 1405331Samw return (dgettext(TEXT_DOMAIN, "smb add share failed")); 1414543Smarks case EZFS_ISCSISVCUNAVAIL: 1424543Smarks return (dgettext(TEXT_DOMAIN, 1434543Smarks "iscsitgt service need to be enabled by " 1444543Smarks "a privileged user")); 1452082Seschrock case EZFS_DEVLINKS: 1462082Seschrock return (dgettext(TEXT_DOMAIN, "failed to create /dev links")); 1472082Seschrock case EZFS_PERM: 1482082Seschrock return (dgettext(TEXT_DOMAIN, "permission denied")); 1492082Seschrock case EZFS_NOSPC: 1502082Seschrock return (dgettext(TEXT_DOMAIN, "out of space")); 1512082Seschrock case EZFS_IO: 1522082Seschrock return (dgettext(TEXT_DOMAIN, "I/O error")); 1532082Seschrock case EZFS_INTR: 1542082Seschrock return (dgettext(TEXT_DOMAIN, "signal received")); 1552082Seschrock case EZFS_ISSPARE: 1562082Seschrock return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " 1572082Seschrock "spare")); 1582082Seschrock case EZFS_INVALCONFIG: 1592082Seschrock return (dgettext(TEXT_DOMAIN, "invalid vdev configuration")); 1602474Seschrock case EZFS_RECURSIVE: 1612474Seschrock return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); 1622926Sek110237 case EZFS_NOHISTORY: 1632926Sek110237 return (dgettext(TEXT_DOMAIN, "no history available")); 1643126Sahl case EZFS_UNSHAREISCSIFAILED: 1653126Sahl return (dgettext(TEXT_DOMAIN, 1663126Sahl "iscsitgtd failed request to unshare")); 1673126Sahl case EZFS_SHAREISCSIFAILED: 1683126Sahl return (dgettext(TEXT_DOMAIN, 1693126Sahl "iscsitgtd failed request to share")); 1703912Slling case EZFS_POOLPROPS: 1713912Slling return (dgettext(TEXT_DOMAIN, "failed to retrieve " 1723912Slling "pool properties")); 1733912Slling case EZFS_POOL_NOTSUP: 1743912Slling return (dgettext(TEXT_DOMAIN, "operation not supported " 1753912Slling "on this type of pool")); 1763912Slling case EZFS_POOL_INVALARG: 1773912Slling return (dgettext(TEXT_DOMAIN, "invalid argument for " 1783912Slling "this pool operation")); 1793978Smmusante case EZFS_NAMETOOLONG: 1803978Smmusante return (dgettext(TEXT_DOMAIN, "dataset name is too long")); 1814276Staylor case EZFS_OPENFAILED: 1824276Staylor return (dgettext(TEXT_DOMAIN, "open failed")); 1834276Staylor case EZFS_NOCAP: 1844276Staylor return (dgettext(TEXT_DOMAIN, 1854276Staylor "disk capacity information could not be retrieved")); 1864276Staylor case EZFS_LABELFAILED: 1874276Staylor return (dgettext(TEXT_DOMAIN, "write of label failed")); 1884543Smarks case EZFS_BADWHO: 1894543Smarks return (dgettext(TEXT_DOMAIN, "invalid user/group")); 1904543Smarks case EZFS_BADPERM: 1914543Smarks return (dgettext(TEXT_DOMAIN, "invalid permission")); 1924543Smarks case EZFS_BADPERMSET: 1934543Smarks return (dgettext(TEXT_DOMAIN, "invalid permission set name")); 1944543Smarks case EZFS_NODELEGATION: 1954543Smarks return (dgettext(TEXT_DOMAIN, "delegated administration is " 1964543Smarks "disabled on pool")); 1974543Smarks case EZFS_PERMRDONLY: 1984543Smarks return (dgettext(TEXT_DOMAIN, "snapshot permissions cannot be" 1994543Smarks " modified")); 2005363Seschrock case EZFS_BADCACHE: 2015363Seschrock return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); 2025450Sbrendan case EZFS_ISL2CACHE: 2035450Sbrendan return (dgettext(TEXT_DOMAIN, "device is in use as a cache")); 2046423Sgw25295 case EZFS_VDEVNOTSUP: 2056423Sgw25295 return (dgettext(TEXT_DOMAIN, "vdev specification is not " 2066423Sgw25295 "supported")); 2077042Sgw25295 case EZFS_NOTSUP: 2087042Sgw25295 return (dgettext(TEXT_DOMAIN, "operation not supported " 2097042Sgw25295 "on this dataset")); 2107214Slling case EZFS_ACTIVE_SPARE: 2117214Slling return (dgettext(TEXT_DOMAIN, "pool has active shared spare " 2127214Slling "device")); 213*9701SGeorge.Wilson@Sun.COM case EZFS_UNPLAYED_LOGS: 214*9701SGeorge.Wilson@Sun.COM return (dgettext(TEXT_DOMAIN, "log device has unplayed intent " 215*9701SGeorge.Wilson@Sun.COM "logs")); 2162082Seschrock case EZFS_UNKNOWN: 2172082Seschrock return (dgettext(TEXT_DOMAIN, "unknown error")); 2182082Seschrock default: 2192500Seschrock assert(hdl->libzfs_error == 0); 2202500Seschrock return (dgettext(TEXT_DOMAIN, "no error")); 2212082Seschrock } 2222082Seschrock } 2232082Seschrock 2242082Seschrock /*PRINTFLIKE2*/ 225789Sahrens void 2262082Seschrock zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...) 227789Sahrens { 228789Sahrens va_list ap; 229789Sahrens 230789Sahrens va_start(ap, fmt); 231789Sahrens 2322082Seschrock (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc), 2332082Seschrock fmt, ap); 2342082Seschrock hdl->libzfs_desc_active = 1; 235789Sahrens 236789Sahrens va_end(ap); 237789Sahrens } 238789Sahrens 2392082Seschrock static void 2402082Seschrock zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap) 2412082Seschrock { 2422082Seschrock (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action), 2432082Seschrock fmt, ap); 2442082Seschrock hdl->libzfs_error = error; 2452082Seschrock 2462082Seschrock if (hdl->libzfs_desc_active) 2472082Seschrock hdl->libzfs_desc_active = 0; 2482082Seschrock else 2492082Seschrock hdl->libzfs_desc[0] = '\0'; 2502082Seschrock 2512082Seschrock if (hdl->libzfs_printerr) { 2522082Seschrock if (error == EZFS_UNKNOWN) { 2532082Seschrock (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal " 2542082Seschrock "error: %s\n"), libzfs_error_description(hdl)); 2552082Seschrock abort(); 2562082Seschrock } 2572082Seschrock 2582082Seschrock (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action, 2593912Slling libzfs_error_description(hdl)); 2602082Seschrock if (error == EZFS_NOMEM) 2612082Seschrock exit(1); 2622082Seschrock } 2632082Seschrock } 2642082Seschrock 2653237Slling int 2663237Slling zfs_error(libzfs_handle_t *hdl, int error, const char *msg) 2673237Slling { 2683237Slling return (zfs_error_fmt(hdl, error, "%s", msg)); 2693237Slling } 2703237Slling 2712082Seschrock /*PRINTFLIKE3*/ 2722082Seschrock int 2733237Slling zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 2742082Seschrock { 2752082Seschrock va_list ap; 2762082Seschrock 2772082Seschrock va_start(ap, fmt); 2782082Seschrock 2792082Seschrock zfs_verror(hdl, error, fmt, ap); 2802082Seschrock 2812082Seschrock va_end(ap); 2822082Seschrock 2832082Seschrock return (-1); 2842082Seschrock } 2852082Seschrock 2862082Seschrock static int 2872082Seschrock zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, 2882082Seschrock va_list ap) 2892082Seschrock { 2902082Seschrock switch (error) { 2912082Seschrock case EPERM: 2922082Seschrock case EACCES: 2932082Seschrock zfs_verror(hdl, EZFS_PERM, fmt, ap); 2942082Seschrock return (-1); 2952082Seschrock 2964543Smarks case ECANCELED: 2974543Smarks zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap); 2984543Smarks return (-1); 2994543Smarks 3002082Seschrock case EIO: 3012082Seschrock zfs_verror(hdl, EZFS_IO, fmt, ap); 3022082Seschrock return (-1); 3032082Seschrock 3042082Seschrock case EINTR: 3052082Seschrock zfs_verror(hdl, EZFS_INTR, fmt, ap); 3062082Seschrock return (-1); 3072082Seschrock } 3082082Seschrock 3092082Seschrock return (0); 3102082Seschrock } 3112082Seschrock 3123237Slling int 3133237Slling zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 3143237Slling { 3153237Slling return (zfs_standard_error_fmt(hdl, error, "%s", msg)); 3163237Slling } 3173237Slling 3182082Seschrock /*PRINTFLIKE3*/ 3192082Seschrock int 3203237Slling zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 321789Sahrens { 322789Sahrens va_list ap; 323789Sahrens 324789Sahrens va_start(ap, fmt); 325789Sahrens 3262082Seschrock if (zfs_common_error(hdl, error, fmt, ap) != 0) { 3272082Seschrock va_end(ap); 3282082Seschrock return (-1); 3292082Seschrock } 3302082Seschrock 3312082Seschrock switch (error) { 3322082Seschrock case ENXIO: 3335807Sck153898 case ENODEV: 3342082Seschrock zfs_verror(hdl, EZFS_IO, fmt, ap); 3352082Seschrock break; 3362082Seschrock 3372082Seschrock case ENOENT: 3382082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3392082Seschrock "dataset does not exist")); 3402082Seschrock zfs_verror(hdl, EZFS_NOENT, fmt, ap); 3412082Seschrock break; 3422082Seschrock 3432082Seschrock case ENOSPC: 3442082Seschrock case EDQUOT: 3452082Seschrock zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 3462082Seschrock return (-1); 3472082Seschrock 3482082Seschrock case EEXIST: 3492082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3502082Seschrock "dataset already exists")); 3512082Seschrock zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 3522082Seschrock break; 3532082Seschrock 3542082Seschrock case EBUSY: 3552082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3562082Seschrock "dataset is busy")); 3572082Seschrock zfs_verror(hdl, EZFS_BUSY, fmt, ap); 3582082Seschrock break; 3594543Smarks case EROFS: 3604543Smarks zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3614543Smarks "snapshot permissions cannot be modified")); 3624543Smarks zfs_verror(hdl, EZFS_PERMRDONLY, fmt, ap); 3634543Smarks break; 3643978Smmusante case ENAMETOOLONG: 3653978Smmusante zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); 3663978Smmusante break; 3675860Sck153898 case ENOTSUP: 3685860Sck153898 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); 3695860Sck153898 break; 3709234SGeorge.Wilson@Sun.COM case EAGAIN: 3719234SGeorge.Wilson@Sun.COM zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 3729234SGeorge.Wilson@Sun.COM "pool I/O is currently suspended")); 3739234SGeorge.Wilson@Sun.COM zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 3749234SGeorge.Wilson@Sun.COM break; 3752082Seschrock default: 3762082Seschrock zfs_error_aux(hdl, strerror(errno)); 3772082Seschrock zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 3782082Seschrock break; 379789Sahrens } 380789Sahrens 381789Sahrens va_end(ap); 3822082Seschrock return (-1); 383789Sahrens } 384789Sahrens 3853237Slling int 3863237Slling zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) 3873237Slling { 3883237Slling return (zpool_standard_error_fmt(hdl, error, "%s", msg)); 3893237Slling } 3903237Slling 3912082Seschrock /*PRINTFLIKE3*/ 3922082Seschrock int 3933237Slling zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) 394789Sahrens { 3952082Seschrock va_list ap; 3962082Seschrock 3972082Seschrock va_start(ap, fmt); 3982082Seschrock 3992082Seschrock if (zfs_common_error(hdl, error, fmt, ap) != 0) { 4002082Seschrock va_end(ap); 4012082Seschrock return (-1); 4022082Seschrock } 4032082Seschrock 4042082Seschrock switch (error) { 4052082Seschrock case ENODEV: 4062082Seschrock zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); 4072082Seschrock break; 4082082Seschrock 4092082Seschrock case ENOENT: 4103912Slling zfs_error_aux(hdl, 4113912Slling dgettext(TEXT_DOMAIN, "no such pool or dataset")); 4122082Seschrock zfs_verror(hdl, EZFS_NOENT, fmt, ap); 4132082Seschrock break; 4142082Seschrock 4152082Seschrock case EEXIST: 4162082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4172082Seschrock "pool already exists")); 4182082Seschrock zfs_verror(hdl, EZFS_EXISTS, fmt, ap); 4192082Seschrock break; 4202082Seschrock 4212082Seschrock case EBUSY: 4222082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); 4237341SEric.Schrock@Sun.COM zfs_verror(hdl, EZFS_BUSY, fmt, ap); 4242082Seschrock break; 4252082Seschrock 4262082Seschrock case ENXIO: 4272082Seschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4282082Seschrock "one or more devices is currently unavailable")); 4292082Seschrock zfs_verror(hdl, EZFS_BADDEV, fmt, ap); 4302082Seschrock break; 4312082Seschrock 4322082Seschrock case ENAMETOOLONG: 4332082Seschrock zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); 4342082Seschrock break; 4352082Seschrock 4363912Slling case ENOTSUP: 4373912Slling zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); 4383912Slling break; 4393912Slling 4403912Slling case EINVAL: 4413912Slling zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); 4423912Slling break; 4433912Slling 4444543Smarks case ENOSPC: 4454543Smarks case EDQUOT: 4464543Smarks zfs_verror(hdl, EZFS_NOSPC, fmt, ap); 4474543Smarks return (-1); 4489234SGeorge.Wilson@Sun.COM case EAGAIN: 4499234SGeorge.Wilson@Sun.COM zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 4509234SGeorge.Wilson@Sun.COM "pool I/O is currently suspended")); 4519234SGeorge.Wilson@Sun.COM zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); 4529234SGeorge.Wilson@Sun.COM break; 4534543Smarks 4542082Seschrock default: 4552082Seschrock zfs_error_aux(hdl, strerror(error)); 4562082Seschrock zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); 4572082Seschrock } 4582082Seschrock 4592082Seschrock va_end(ap); 4602082Seschrock return (-1); 461789Sahrens } 462789Sahrens 463789Sahrens /* 464789Sahrens * Display an out of memory error message and abort the current program. 465789Sahrens */ 4662082Seschrock int 4672082Seschrock no_memory(libzfs_handle_t *hdl) 468789Sahrens { 4692082Seschrock return (zfs_error(hdl, EZFS_NOMEM, "internal error")); 470789Sahrens } 471789Sahrens 472789Sahrens /* 473789Sahrens * A safe form of malloc() which will die if the allocation fails. 474789Sahrens */ 475789Sahrens void * 4762082Seschrock zfs_alloc(libzfs_handle_t *hdl, size_t size) 477789Sahrens { 478789Sahrens void *data; 479789Sahrens 480789Sahrens if ((data = calloc(1, size)) == NULL) 4812082Seschrock (void) no_memory(hdl); 482789Sahrens 483789Sahrens return (data); 484789Sahrens } 485789Sahrens 486789Sahrens /* 4872676Seschrock * A safe form of realloc(), which also zeroes newly allocated space. 4882676Seschrock */ 4892676Seschrock void * 4902676Seschrock zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) 4912676Seschrock { 4922676Seschrock void *ret; 4932676Seschrock 4942676Seschrock if ((ret = realloc(ptr, newsize)) == NULL) { 4952676Seschrock (void) no_memory(hdl); 4962676Seschrock return (NULL); 4972676Seschrock } 4982676Seschrock 4992676Seschrock bzero((char *)ret + oldsize, (newsize - oldsize)); 5002676Seschrock return (ret); 5012676Seschrock } 5022676Seschrock 5032676Seschrock /* 504789Sahrens * A safe form of strdup() which will die if the allocation fails. 505789Sahrens */ 506789Sahrens char * 5072082Seschrock zfs_strdup(libzfs_handle_t *hdl, const char *str) 508789Sahrens { 509789Sahrens char *ret; 510789Sahrens 511789Sahrens if ((ret = strdup(str)) == NULL) 5122082Seschrock (void) no_memory(hdl); 513789Sahrens 514789Sahrens return (ret); 515789Sahrens } 516789Sahrens 517789Sahrens /* 518789Sahrens * Convert a number to an appropriately human-readable output. 519789Sahrens */ 520789Sahrens void 521789Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen) 522789Sahrens { 523789Sahrens uint64_t n = num; 524789Sahrens int index = 0; 525789Sahrens char u; 526789Sahrens 527789Sahrens while (n >= 1024) { 5281162Seschrock n /= 1024; 529789Sahrens index++; 530789Sahrens } 531789Sahrens 532789Sahrens u = " KMGTPE"[index]; 533789Sahrens 5341162Seschrock if (index == 0) { 535789Sahrens (void) snprintf(buf, buflen, "%llu", n); 5361162Seschrock } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { 5371162Seschrock /* 5381162Seschrock * If this is an even multiple of the base, always display 5391162Seschrock * without any decimal precision. 5401162Seschrock */ 541789Sahrens (void) snprintf(buf, buflen, "%llu%c", n, u); 5421162Seschrock } else { 5431162Seschrock /* 5441162Seschrock * We want to choose a precision that reflects the best choice 5451162Seschrock * for fitting in 5 characters. This can get rather tricky when 5461162Seschrock * we have numbers that are very close to an order of magnitude. 5471162Seschrock * For example, when displaying 10239 (which is really 9.999K), 5481162Seschrock * we want only a single place of precision for 10.0K. We could 5491162Seschrock * develop some complex heuristics for this, but it's much 5501162Seschrock * easier just to try each combination in turn. 5511162Seschrock */ 5521162Seschrock int i; 5531162Seschrock for (i = 2; i >= 0; i--) { 5544451Seschrock if (snprintf(buf, buflen, "%.*f%c", i, 5554451Seschrock (double)num / (1ULL << 10 * index), u) <= 5) 5561162Seschrock break; 5571162Seschrock } 5581162Seschrock } 559789Sahrens } 5602082Seschrock 5612082Seschrock void 5622082Seschrock libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) 5632082Seschrock { 5642082Seschrock hdl->libzfs_printerr = printerr; 5652082Seschrock } 5662082Seschrock 5672082Seschrock libzfs_handle_t * 5682082Seschrock libzfs_init(void) 5692082Seschrock { 5702082Seschrock libzfs_handle_t *hdl; 5712082Seschrock 5722082Seschrock if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) { 5732082Seschrock return (NULL); 5742082Seschrock } 5752082Seschrock 5762500Seschrock if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { 5772082Seschrock free(hdl); 5782082Seschrock return (NULL); 5792082Seschrock } 5802082Seschrock 5812082Seschrock if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { 5822082Seschrock (void) close(hdl->libzfs_fd); 5832082Seschrock free(hdl); 5842082Seschrock return (NULL); 5852082Seschrock } 5862082Seschrock 5872082Seschrock hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); 5882082Seschrock 5894787Sahrens zfs_prop_init(); 5905094Slling zpool_prop_init(); 5918811SEric.Taylor@Sun.COM libzfs_mnttab_init(hdl); 5924787Sahrens 5932082Seschrock return (hdl); 5942082Seschrock } 5952082Seschrock 5962082Seschrock void 5972082Seschrock libzfs_fini(libzfs_handle_t *hdl) 5982082Seschrock { 5992082Seschrock (void) close(hdl->libzfs_fd); 6002082Seschrock if (hdl->libzfs_mnttab) 6012082Seschrock (void) fclose(hdl->libzfs_mnttab); 6022082Seschrock if (hdl->libzfs_sharetab) 6032082Seschrock (void) fclose(hdl->libzfs_sharetab); 6044180Sdougm zfs_uninit_libshare(hdl); 6054543Smarks if (hdl->libzfs_log_str) 6064543Smarks (void) free(hdl->libzfs_log_str); 6076865Srm160521 zpool_free_handles(hdl); 6082082Seschrock namespace_clear(hdl); 6098811SEric.Taylor@Sun.COM libzfs_mnttab_fini(hdl); 6102082Seschrock free(hdl); 6112082Seschrock } 6122082Seschrock 6132082Seschrock libzfs_handle_t * 6142082Seschrock zpool_get_handle(zpool_handle_t *zhp) 6152082Seschrock { 6162082Seschrock return (zhp->zpool_hdl); 6172082Seschrock } 6182082Seschrock 6192082Seschrock libzfs_handle_t * 6202082Seschrock zfs_get_handle(zfs_handle_t *zhp) 6212082Seschrock { 6222082Seschrock return (zhp->zfs_hdl); 6232082Seschrock } 6242676Seschrock 6257538SRichard.Morris@Sun.COM zpool_handle_t * 6267538SRichard.Morris@Sun.COM zfs_get_pool_handle(const zfs_handle_t *zhp) 6277538SRichard.Morris@Sun.COM { 6287538SRichard.Morris@Sun.COM return (zhp->zpool_hdl); 6297538SRichard.Morris@Sun.COM } 6307538SRichard.Morris@Sun.COM 6312676Seschrock /* 6323635Sck153898 * Given a name, determine whether or not it's a valid path 6333635Sck153898 * (starts with '/' or "./"). If so, walk the mnttab trying 6343635Sck153898 * to match the device number. If not, treat the path as an 6353635Sck153898 * fs/vol/snap name. 6363635Sck153898 */ 6373635Sck153898 zfs_handle_t * 6383635Sck153898 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype) 6393635Sck153898 { 6403635Sck153898 struct stat64 statbuf; 6413635Sck153898 struct extmnttab entry; 6423635Sck153898 int ret; 6433635Sck153898 6443635Sck153898 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { 6453635Sck153898 /* 6463635Sck153898 * It's not a valid path, assume it's a name of type 'argtype'. 6473635Sck153898 */ 6483635Sck153898 return (zfs_open(hdl, path, argtype)); 6493635Sck153898 } 6503635Sck153898 6513635Sck153898 if (stat64(path, &statbuf) != 0) { 6523635Sck153898 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno)); 6533635Sck153898 return (NULL); 6543635Sck153898 } 6553635Sck153898 6563635Sck153898 rewind(hdl->libzfs_mnttab); 6573635Sck153898 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) { 6583635Sck153898 if (makedevice(entry.mnt_major, entry.mnt_minor) == 6593635Sck153898 statbuf.st_dev) { 6603635Sck153898 break; 6613635Sck153898 } 6623635Sck153898 } 6633635Sck153898 if (ret != 0) { 6643635Sck153898 return (NULL); 6653635Sck153898 } 6663635Sck153898 6673635Sck153898 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { 6683635Sck153898 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), 6693635Sck153898 path); 6703635Sck153898 return (NULL); 6713635Sck153898 } 6723635Sck153898 6733635Sck153898 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); 6743635Sck153898 } 6753635Sck153898 6763635Sck153898 /* 6772676Seschrock * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from 6782676Seschrock * an ioctl(). 6792676Seschrock */ 6802676Seschrock int 6812676Seschrock zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) 6822676Seschrock { 6832676Seschrock if (len == 0) 6842885Sahrens len = 2048; 6852676Seschrock zc->zc_nvlist_dst_size = len; 6862676Seschrock if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 6872676Seschrock zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL) 6882676Seschrock return (-1); 6892676Seschrock 6902676Seschrock return (0); 6912676Seschrock } 6922676Seschrock 6932676Seschrock /* 6942676Seschrock * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will 6952676Seschrock * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was 6962676Seschrock * filled in by the kernel to indicate the actual required size. 6972676Seschrock */ 6982676Seschrock int 6992676Seschrock zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) 7002676Seschrock { 7012676Seschrock free((void *)(uintptr_t)zc->zc_nvlist_dst); 7022676Seschrock if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) 7032676Seschrock zfs_alloc(hdl, zc->zc_nvlist_dst_size)) 7042676Seschrock == NULL) 7052676Seschrock return (-1); 7062676Seschrock 7072676Seschrock return (0); 7082676Seschrock } 7092676Seschrock 7102676Seschrock /* 7112885Sahrens * Called to free the src and dst nvlists stored in the command structure. 7122676Seschrock */ 7132676Seschrock void 7142676Seschrock zcmd_free_nvlists(zfs_cmd_t *zc) 7152676Seschrock { 7165094Slling free((void *)(uintptr_t)zc->zc_nvlist_conf); 7172676Seschrock free((void *)(uintptr_t)zc->zc_nvlist_src); 7182676Seschrock free((void *)(uintptr_t)zc->zc_nvlist_dst); 7192676Seschrock } 7202676Seschrock 7215094Slling static int 7225094Slling zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, 7235094Slling nvlist_t *nvl) 7242676Seschrock { 7252676Seschrock char *packed; 7262676Seschrock size_t len; 7272676Seschrock 7282676Seschrock verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0); 7292676Seschrock 7302676Seschrock if ((packed = zfs_alloc(hdl, len)) == NULL) 7312676Seschrock return (-1); 7322676Seschrock 7332676Seschrock verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); 7342676Seschrock 7355094Slling *outnv = (uint64_t)(uintptr_t)packed; 7365094Slling *outlen = len; 7375094Slling 7385094Slling return (0); 7395094Slling } 7402676Seschrock 7415094Slling int 7425094Slling zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 7435094Slling { 7445094Slling return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, 7455094Slling &zc->zc_nvlist_conf_size, nvl)); 7465094Slling } 7475094Slling 7485094Slling int 7495094Slling zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) 7505094Slling { 7515094Slling return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, 7525094Slling &zc->zc_nvlist_src_size, nvl)); 7532676Seschrock } 7542676Seschrock 7552676Seschrock /* 7562676Seschrock * Unpacks an nvlist from the ZFS ioctl command structure. 7572676Seschrock */ 7582676Seschrock int 7592676Seschrock zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) 7602676Seschrock { 7612676Seschrock if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, 7622676Seschrock zc->zc_nvlist_dst_size, nvlp, 0) != 0) 7632676Seschrock return (no_memory(hdl)); 7642676Seschrock 7652676Seschrock return (0); 7662676Seschrock } 7673912Slling 7685094Slling int 7695094Slling zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) 7705094Slling { 7715094Slling int error; 7725094Slling 7735094Slling zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str; 7745094Slling error = ioctl(hdl->libzfs_fd, request, zc); 7755094Slling if (hdl->libzfs_log_str) { 7765094Slling free(hdl->libzfs_log_str); 7775094Slling hdl->libzfs_log_str = NULL; 7785094Slling } 7795094Slling zc->zc_history = 0; 7805094Slling 7815094Slling return (error); 7825094Slling } 7835094Slling 7845094Slling /* 7855094Slling * ================================================================ 7865094Slling * API shared by zfs and zpool property management 7875094Slling * ================================================================ 7885094Slling */ 7895094Slling 7903912Slling static void 7915094Slling zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) 7923912Slling { 7935094Slling zprop_list_t *pl = cbp->cb_proplist; 7943912Slling int i; 7953912Slling char *title; 7963912Slling size_t len; 7973912Slling 7983912Slling cbp->cb_first = B_FALSE; 7993912Slling if (cbp->cb_scripted) 8003912Slling return; 8013912Slling 8023912Slling /* 8033912Slling * Start with the length of the column headers. 8043912Slling */ 8053912Slling cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); 8063912Slling cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, 8073912Slling "PROPERTY")); 8083912Slling cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, 8093912Slling "VALUE")); 8103912Slling cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, 8113912Slling "SOURCE")); 8123912Slling 8138269SMark.Musante@Sun.COM /* first property is always NAME */ 8148269SMark.Musante@Sun.COM assert(cbp->cb_proplist->pl_prop == 8158269SMark.Musante@Sun.COM ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME)); 8168269SMark.Musante@Sun.COM 8173912Slling /* 8183912Slling * Go through and calculate the widths for each column. For the 8193912Slling * 'source' column, we kludge it up by taking the worst-case scenario of 8203912Slling * inheriting from the longest name. This is acceptable because in the 8213912Slling * majority of cases 'SOURCE' is the last column displayed, and we don't 8223912Slling * use the width anyway. Note that the 'VALUE' column can be oversized, 8233912Slling * if the name of the property is much longer the any values we find. 8243912Slling */ 8253912Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 8263912Slling /* 8273912Slling * 'PROPERTY' column 8283912Slling */ 8295094Slling if (pl->pl_prop != ZPROP_INVAL) { 8305094Slling const char *propname = (type == ZFS_TYPE_POOL) ? 8315094Slling zpool_prop_to_name(pl->pl_prop) : 8325094Slling zfs_prop_to_name(pl->pl_prop); 8335094Slling 8345094Slling len = strlen(propname); 8353912Slling if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 8363912Slling cbp->cb_colwidths[GET_COL_PROPERTY] = len; 8373912Slling } else { 8383912Slling len = strlen(pl->pl_user_prop); 8393912Slling if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 8403912Slling cbp->cb_colwidths[GET_COL_PROPERTY] = len; 8413912Slling } 8423912Slling 8433912Slling /* 8448269SMark.Musante@Sun.COM * 'VALUE' column. The first property is always the 'name' 8458269SMark.Musante@Sun.COM * property that was tacked on either by /sbin/zfs's 8468269SMark.Musante@Sun.COM * zfs_do_get() or when calling zprop_expand_list(), so we 8478269SMark.Musante@Sun.COM * ignore its width. If the user specified the name property 8488269SMark.Musante@Sun.COM * to display, then it will be later in the list in any case. 8493912Slling */ 8508269SMark.Musante@Sun.COM if (pl != cbp->cb_proplist && 8513912Slling pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) 8523912Slling cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; 8533912Slling 8543912Slling /* 8553912Slling * 'NAME' and 'SOURCE' columns 8563912Slling */ 8575094Slling if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME : 8585094Slling ZFS_PROP_NAME) && 8593912Slling pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { 8603912Slling cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; 8613912Slling cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + 8623912Slling strlen(dgettext(TEXT_DOMAIN, "inherited from")); 8633912Slling } 8643912Slling } 8653912Slling 8663912Slling /* 8673912Slling * Now go through and print the headers. 8683912Slling */ 8693912Slling for (i = 0; i < 4; i++) { 8703912Slling switch (cbp->cb_columns[i]) { 8713912Slling case GET_COL_NAME: 8723912Slling title = dgettext(TEXT_DOMAIN, "NAME"); 8733912Slling break; 8743912Slling case GET_COL_PROPERTY: 8753912Slling title = dgettext(TEXT_DOMAIN, "PROPERTY"); 8763912Slling break; 8773912Slling case GET_COL_VALUE: 8783912Slling title = dgettext(TEXT_DOMAIN, "VALUE"); 8793912Slling break; 8803912Slling case GET_COL_SOURCE: 8813912Slling title = dgettext(TEXT_DOMAIN, "SOURCE"); 8823912Slling break; 8833912Slling default: 8843912Slling title = NULL; 8853912Slling } 8863912Slling 8873912Slling if (title != NULL) { 8883912Slling if (i == 3 || cbp->cb_columns[i + 1] == 0) 8893912Slling (void) printf("%s", title); 8903912Slling else 8913912Slling (void) printf("%-*s ", 8923912Slling cbp->cb_colwidths[cbp->cb_columns[i]], 8933912Slling title); 8943912Slling } 8953912Slling } 8963912Slling (void) printf("\n"); 8973912Slling } 8983912Slling 8993912Slling /* 9003912Slling * Display a single line of output, according to the settings in the callback 9013912Slling * structure. 9023912Slling */ 9033912Slling void 9045094Slling zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, 9055094Slling const char *propname, const char *value, zprop_source_t sourcetype, 9063912Slling const char *source) 9073912Slling { 9083912Slling int i; 9093912Slling const char *str; 9103912Slling char buf[128]; 9113912Slling 9123912Slling /* 9133912Slling * Ignore those source types that the user has chosen to ignore. 9143912Slling */ 9153912Slling if ((sourcetype & cbp->cb_sources) == 0) 9163912Slling return; 9173912Slling 9183912Slling if (cbp->cb_first) 9195094Slling zprop_print_headers(cbp, cbp->cb_type); 9203912Slling 9213912Slling for (i = 0; i < 4; i++) { 9223912Slling switch (cbp->cb_columns[i]) { 9233912Slling case GET_COL_NAME: 9243912Slling str = name; 9253912Slling break; 9263912Slling 9273912Slling case GET_COL_PROPERTY: 9283912Slling str = propname; 9293912Slling break; 9303912Slling 9313912Slling case GET_COL_VALUE: 9323912Slling str = value; 9333912Slling break; 9343912Slling 9353912Slling case GET_COL_SOURCE: 9363912Slling switch (sourcetype) { 9375094Slling case ZPROP_SRC_NONE: 9383912Slling str = "-"; 9393912Slling break; 9403912Slling 9415094Slling case ZPROP_SRC_DEFAULT: 9423912Slling str = "default"; 9433912Slling break; 9443912Slling 9455094Slling case ZPROP_SRC_LOCAL: 9463912Slling str = "local"; 9473912Slling break; 9483912Slling 9495094Slling case ZPROP_SRC_TEMPORARY: 9503912Slling str = "temporary"; 9513912Slling break; 9523912Slling 9535094Slling case ZPROP_SRC_INHERITED: 9543912Slling (void) snprintf(buf, sizeof (buf), 9553912Slling "inherited from %s", source); 9563912Slling str = buf; 9573912Slling break; 9583912Slling } 9593912Slling break; 9603912Slling 9613912Slling default: 9623912Slling continue; 9633912Slling } 9643912Slling 9653912Slling if (cbp->cb_columns[i + 1] == 0) 9663912Slling (void) printf("%s", str); 9673912Slling else if (cbp->cb_scripted) 9683912Slling (void) printf("%s\t", str); 9693912Slling else 9703912Slling (void) printf("%-*s ", 9713912Slling cbp->cb_colwidths[cbp->cb_columns[i]], 9723912Slling str); 9733912Slling 9743912Slling } 9753912Slling 9763912Slling (void) printf("\n"); 9773912Slling } 9784543Smarks 9795094Slling /* 9805094Slling * Given a numeric suffix, convert the value into a number of bits that the 9815094Slling * resulting value must be shifted. 9825094Slling */ 9835094Slling static int 9845094Slling str2shift(libzfs_handle_t *hdl, const char *buf) 9855094Slling { 9865094Slling const char *ends = "BKMGTPEZ"; 9875094Slling int i; 9885094Slling 9895094Slling if (buf[0] == '\0') 9905094Slling return (0); 9915094Slling for (i = 0; i < strlen(ends); i++) { 9925094Slling if (toupper(buf[0]) == ends[i]) 9935094Slling break; 9945094Slling } 9955094Slling if (i == strlen(ends)) { 9965094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 9975094Slling "invalid numeric suffix '%s'"), buf); 9985094Slling return (-1); 9995094Slling } 10005094Slling 10015094Slling /* 10025094Slling * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't 10035094Slling * allow 'BB' - that's just weird. 10045094Slling */ 10055094Slling if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && 10065094Slling toupper(buf[0]) != 'B')) 10075094Slling return (10*i); 10085094Slling 10095094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10105094Slling "invalid numeric suffix '%s'"), buf); 10115094Slling return (-1); 10125094Slling } 10135094Slling 10145094Slling /* 10155094Slling * Convert a string of the form '100G' into a real number. Used when setting 10165094Slling * properties or creating a volume. 'buf' is used to place an extended error 10175094Slling * message for the caller to use. 10185094Slling */ 10194543Smarks int 10205094Slling zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) 10215094Slling { 10225094Slling char *end; 10235094Slling int shift; 10245094Slling 10255094Slling *num = 0; 10265094Slling 10275094Slling /* Check to see if this looks like a number. */ 10285094Slling if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 10295094Slling if (hdl) 10305094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10315094Slling "bad numeric value '%s'"), value); 10325094Slling return (-1); 10335094Slling } 10345094Slling 10358343SEric.Schrock@Sun.COM /* Rely on stroull() to process the numeric portion. */ 10365094Slling errno = 0; 10378343SEric.Schrock@Sun.COM *num = strtoull(value, &end, 10); 10385094Slling 10395094Slling /* 10405094Slling * Check for ERANGE, which indicates that the value is too large to fit 10415094Slling * in a 64-bit value. 10425094Slling */ 10435094Slling if (errno == ERANGE) { 10445094Slling if (hdl) 10455094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10465094Slling "numeric value is too large")); 10475094Slling return (-1); 10485094Slling } 10495094Slling 10505094Slling /* 10515094Slling * If we have a decimal value, then do the computation with floating 10525094Slling * point arithmetic. Otherwise, use standard arithmetic. 10535094Slling */ 10545094Slling if (*end == '.') { 10555094Slling double fval = strtod(value, &end); 10565094Slling 10575094Slling if ((shift = str2shift(hdl, end)) == -1) 10585094Slling return (-1); 10595094Slling 10605094Slling fval *= pow(2, shift); 10615094Slling 10625094Slling if (fval > UINT64_MAX) { 10635094Slling if (hdl) 10645094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10655094Slling "numeric value is too large")); 10665094Slling return (-1); 10675094Slling } 10685094Slling 10695094Slling *num = (uint64_t)fval; 10705094Slling } else { 10715094Slling if ((shift = str2shift(hdl, end)) == -1) 10725094Slling return (-1); 10735094Slling 10745094Slling /* Check for overflow */ 10755094Slling if (shift >= 64 || (*num << shift) >> shift != *num) { 10765094Slling if (hdl) 10775094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 10785094Slling "numeric value is too large")); 10795094Slling return (-1); 10805094Slling } 10815094Slling 10825094Slling *num <<= shift; 10835094Slling } 10845094Slling 10855094Slling return (0); 10865094Slling } 10875094Slling 10885094Slling /* 10895094Slling * Given a propname=value nvpair to set, parse any numeric properties 10905094Slling * (index, boolean, etc) if they are specified as strings and add the 10915094Slling * resulting nvpair to the returned nvlist. 10925094Slling * 10935094Slling * At the DSL layer, all properties are either 64-bit numbers or strings. 10945094Slling * We want the user to be able to ignore this fact and specify properties 10955094Slling * as native values (numbers, for example) or as strings (to simplify 10965094Slling * command line utilities). This also handles converting index types 10975094Slling * (compression, checksum, etc) from strings to their on-disk index. 10985094Slling */ 10995094Slling int 11005094Slling zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, 11015094Slling zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp, 11025094Slling const char *errbuf) 11034543Smarks { 11045094Slling data_type_t datatype = nvpair_type(elem); 11055094Slling zprop_type_t proptype; 11065094Slling const char *propname; 11075094Slling char *value; 11085094Slling boolean_t isnone = B_FALSE; 11095094Slling 11105094Slling if (type == ZFS_TYPE_POOL) { 11115094Slling proptype = zpool_prop_get_type(prop); 11125094Slling propname = zpool_prop_to_name(prop); 11135094Slling } else { 11145094Slling proptype = zfs_prop_get_type(prop); 11155094Slling propname = zfs_prop_to_name(prop); 11165094Slling } 11175094Slling 11185094Slling /* 11195094Slling * Convert any properties to the internal DSL value types. 11205094Slling */ 11215094Slling *svalp = NULL; 11225094Slling *ivalp = 0; 11235094Slling 11245094Slling switch (proptype) { 11255094Slling case PROP_TYPE_STRING: 11265094Slling if (datatype != DATA_TYPE_STRING) { 11275094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11285094Slling "'%s' must be a string"), nvpair_name(elem)); 11295094Slling goto error; 11305094Slling } 11315094Slling (void) nvpair_value_string(elem, svalp); 11325094Slling if (strlen(*svalp) >= ZFS_MAXPROPLEN) { 11335094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11345094Slling "'%s' is too long"), nvpair_name(elem)); 11355094Slling goto error; 11365094Slling } 11375094Slling break; 11385094Slling 11395094Slling case PROP_TYPE_NUMBER: 11405094Slling if (datatype == DATA_TYPE_STRING) { 11415094Slling (void) nvpair_value_string(elem, &value); 11425094Slling if (strcmp(value, "none") == 0) { 11435094Slling isnone = B_TRUE; 11445094Slling } else if (zfs_nicestrtonum(hdl, value, ivalp) 11455094Slling != 0) { 11465094Slling goto error; 11475094Slling } 11485094Slling } else if (datatype == DATA_TYPE_UINT64) { 11495094Slling (void) nvpair_value_uint64(elem, ivalp); 11505094Slling } else { 11515094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11525094Slling "'%s' must be a number"), nvpair_name(elem)); 11535094Slling goto error; 11545094Slling } 11555094Slling 11565094Slling /* 11575094Slling * Quota special: force 'none' and don't allow 0. 11585094Slling */ 11595378Sck153898 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && 11605378Sck153898 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { 11615094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11625378Sck153898 "use 'none' to disable quota/refquota")); 11635094Slling goto error; 11645094Slling } 11655094Slling break; 11665094Slling 11675094Slling case PROP_TYPE_INDEX: 11685378Sck153898 if (datatype != DATA_TYPE_STRING) { 11695094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11705094Slling "'%s' must be a string"), nvpair_name(elem)); 11715094Slling goto error; 11725094Slling } 11735094Slling 11745378Sck153898 (void) nvpair_value_string(elem, &value); 11755378Sck153898 11765094Slling if (zprop_string_to_index(prop, value, ivalp, type) != 0) { 11775094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 11785094Slling "'%s' must be one of '%s'"), propname, 11795094Slling zprop_values(prop, type)); 11805094Slling goto error; 11815094Slling } 11825094Slling break; 11835094Slling 11845094Slling default: 11855094Slling abort(); 11865094Slling } 11874543Smarks 11885094Slling /* 11895094Slling * Add the result to our return set of properties. 11905094Slling */ 11915094Slling if (*svalp != NULL) { 11925094Slling if (nvlist_add_string(ret, propname, *svalp) != 0) { 11935094Slling (void) no_memory(hdl); 11945094Slling return (-1); 11955094Slling } 11965094Slling } else { 11975094Slling if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { 11985094Slling (void) no_memory(hdl); 11995094Slling return (-1); 12005094Slling } 12015094Slling } 12025094Slling 12035094Slling return (0); 12045094Slling error: 12055094Slling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 12065094Slling return (-1); 12075094Slling } 12085094Slling 12097390SMatthew.Ahrens@Sun.COM static int 12107390SMatthew.Ahrens@Sun.COM addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp, 12117390SMatthew.Ahrens@Sun.COM zfs_type_t type) 12127390SMatthew.Ahrens@Sun.COM { 12137390SMatthew.Ahrens@Sun.COM int prop; 12147390SMatthew.Ahrens@Sun.COM zprop_list_t *entry; 12157390SMatthew.Ahrens@Sun.COM 12167390SMatthew.Ahrens@Sun.COM prop = zprop_name_to_prop(propname, type); 12177390SMatthew.Ahrens@Sun.COM 12187390SMatthew.Ahrens@Sun.COM if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type)) 12197390SMatthew.Ahrens@Sun.COM prop = ZPROP_INVAL; 12207390SMatthew.Ahrens@Sun.COM 12217390SMatthew.Ahrens@Sun.COM /* 12227390SMatthew.Ahrens@Sun.COM * When no property table entry can be found, return failure if 12237390SMatthew.Ahrens@Sun.COM * this is a pool property or if this isn't a user-defined 12247390SMatthew.Ahrens@Sun.COM * dataset property, 12257390SMatthew.Ahrens@Sun.COM */ 12267390SMatthew.Ahrens@Sun.COM if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL || 12279396SMatthew.Ahrens@Sun.COM (!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) { 12287390SMatthew.Ahrens@Sun.COM zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12297390SMatthew.Ahrens@Sun.COM "invalid property '%s'"), propname); 12307390SMatthew.Ahrens@Sun.COM return (zfs_error(hdl, EZFS_BADPROP, 12317390SMatthew.Ahrens@Sun.COM dgettext(TEXT_DOMAIN, "bad property list"))); 12327390SMatthew.Ahrens@Sun.COM } 12337390SMatthew.Ahrens@Sun.COM 12347390SMatthew.Ahrens@Sun.COM if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 12357390SMatthew.Ahrens@Sun.COM return (-1); 12367390SMatthew.Ahrens@Sun.COM 12377390SMatthew.Ahrens@Sun.COM entry->pl_prop = prop; 12387390SMatthew.Ahrens@Sun.COM if (prop == ZPROP_INVAL) { 12397390SMatthew.Ahrens@Sun.COM if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) { 12407390SMatthew.Ahrens@Sun.COM free(entry); 12417390SMatthew.Ahrens@Sun.COM return (-1); 12427390SMatthew.Ahrens@Sun.COM } 12437390SMatthew.Ahrens@Sun.COM entry->pl_width = strlen(propname); 12447390SMatthew.Ahrens@Sun.COM } else { 12457390SMatthew.Ahrens@Sun.COM entry->pl_width = zprop_width(prop, &entry->pl_fixed, 12467390SMatthew.Ahrens@Sun.COM type); 12477390SMatthew.Ahrens@Sun.COM } 12487390SMatthew.Ahrens@Sun.COM 12497390SMatthew.Ahrens@Sun.COM *listp = entry; 12507390SMatthew.Ahrens@Sun.COM 12517390SMatthew.Ahrens@Sun.COM return (0); 12527390SMatthew.Ahrens@Sun.COM } 12537390SMatthew.Ahrens@Sun.COM 12545094Slling /* 12555094Slling * Given a comma-separated list of properties, construct a property list 12565094Slling * containing both user-defined and native properties. This function will 12575094Slling * return a NULL list if 'all' is specified, which can later be expanded 12585094Slling * by zprop_expand_list(). 12595094Slling */ 12605094Slling int 12615094Slling zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, 12625094Slling zfs_type_t type) 12635094Slling { 12645094Slling *listp = NULL; 12655094Slling 12665094Slling /* 12675094Slling * If 'all' is specified, return a NULL list. 12685094Slling */ 12695094Slling if (strcmp(props, "all") == 0) 12705094Slling return (0); 12715094Slling 12725094Slling /* 12735094Slling * If no props were specified, return an error. 12745094Slling */ 12755094Slling if (props[0] == '\0') { 12765094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 12775094Slling "no properties specified")); 12785094Slling return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, 12795094Slling "bad property list"))); 12804543Smarks } 12815094Slling 12825094Slling /* 12835094Slling * It would be nice to use getsubopt() here, but the inclusion of column 12845094Slling * aliases makes this more effort than it's worth. 12855094Slling */ 12867390SMatthew.Ahrens@Sun.COM while (*props != '\0') { 12877390SMatthew.Ahrens@Sun.COM size_t len; 12887390SMatthew.Ahrens@Sun.COM char *p; 12897390SMatthew.Ahrens@Sun.COM char c; 12907390SMatthew.Ahrens@Sun.COM 12917390SMatthew.Ahrens@Sun.COM if ((p = strchr(props, ',')) == NULL) { 12927390SMatthew.Ahrens@Sun.COM len = strlen(props); 12937390SMatthew.Ahrens@Sun.COM p = props + len; 12945094Slling } else { 12957390SMatthew.Ahrens@Sun.COM len = p - props; 12965094Slling } 12975094Slling 12985094Slling /* 12995094Slling * Check for empty options. 13005094Slling */ 13015094Slling if (len == 0) { 13025094Slling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 13035094Slling "empty property name")); 13045094Slling return (zfs_error(hdl, EZFS_BADPROP, 13055094Slling dgettext(TEXT_DOMAIN, "bad property list"))); 13065094Slling } 13075094Slling 13085094Slling /* 13095094Slling * Check all regular property names. 13105094Slling */ 13117390SMatthew.Ahrens@Sun.COM c = props[len]; 13127390SMatthew.Ahrens@Sun.COM props[len] = '\0'; 13135094Slling 13147390SMatthew.Ahrens@Sun.COM if (strcmp(props, "space") == 0) { 13157390SMatthew.Ahrens@Sun.COM static char *spaceprops[] = { 13167390SMatthew.Ahrens@Sun.COM "name", "avail", "used", "usedbysnapshots", 13177390SMatthew.Ahrens@Sun.COM "usedbydataset", "usedbyrefreservation", 13187390SMatthew.Ahrens@Sun.COM "usedbychildren", NULL 13197390SMatthew.Ahrens@Sun.COM }; 13207390SMatthew.Ahrens@Sun.COM int i; 13217390SMatthew.Ahrens@Sun.COM 13227390SMatthew.Ahrens@Sun.COM for (i = 0; spaceprops[i]; i++) { 13237390SMatthew.Ahrens@Sun.COM if (addlist(hdl, spaceprops[i], listp, type)) 13247390SMatthew.Ahrens@Sun.COM return (-1); 13257390SMatthew.Ahrens@Sun.COM listp = &(*listp)->pl_next; 13267390SMatthew.Ahrens@Sun.COM } 13277390SMatthew.Ahrens@Sun.COM } else { 13287390SMatthew.Ahrens@Sun.COM if (addlist(hdl, props, listp, type)) 13297390SMatthew.Ahrens@Sun.COM return (-1); 13307390SMatthew.Ahrens@Sun.COM listp = &(*listp)->pl_next; 13315094Slling } 13325094Slling 13337390SMatthew.Ahrens@Sun.COM props = p; 13345094Slling if (c == ',') 13357390SMatthew.Ahrens@Sun.COM props++; 13365094Slling } 13375094Slling 13385094Slling return (0); 13395094Slling } 13405094Slling 13415094Slling void 13425094Slling zprop_free_list(zprop_list_t *pl) 13435094Slling { 13445094Slling zprop_list_t *next; 13454543Smarks 13465094Slling while (pl != NULL) { 13475094Slling next = pl->pl_next; 13485094Slling free(pl->pl_user_prop); 13495094Slling free(pl); 13505094Slling pl = next; 13515094Slling } 13525094Slling } 13535094Slling 13545094Slling typedef struct expand_data { 13555094Slling zprop_list_t **last; 13565094Slling libzfs_handle_t *hdl; 13575094Slling zfs_type_t type; 13585094Slling } expand_data_t; 13595094Slling 13605094Slling int 13615094Slling zprop_expand_list_cb(int prop, void *cb) 13625094Slling { 13635094Slling zprop_list_t *entry; 13645094Slling expand_data_t *edp = cb; 13655094Slling 13665094Slling if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL) 13675094Slling return (ZPROP_INVAL); 13685094Slling 13695094Slling entry->pl_prop = prop; 13705094Slling entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); 13715094Slling entry->pl_all = B_TRUE; 13725094Slling 13735094Slling *(edp->last) = entry; 13745094Slling edp->last = &entry->pl_next; 13755094Slling 13765094Slling return (ZPROP_CONT); 13774543Smarks } 13785094Slling 13795094Slling int 13805094Slling zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) 13815094Slling { 13825094Slling zprop_list_t *entry; 13835094Slling zprop_list_t **last; 13845094Slling expand_data_t exp; 13855094Slling 13865094Slling if (*plp == NULL) { 13875094Slling /* 13885094Slling * If this is the very first time we've been called for an 'all' 13895094Slling * specification, expand the list to include all native 13905094Slling * properties. 13915094Slling */ 13925094Slling last = plp; 13935094Slling 13945094Slling exp.last = last; 13955094Slling exp.hdl = hdl; 13965094Slling exp.type = type; 13975094Slling 13985094Slling if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, 13995094Slling B_FALSE, type) == ZPROP_INVAL) 14005094Slling return (-1); 14015094Slling 14025094Slling /* 14035094Slling * Add 'name' to the beginning of the list, which is handled 14045094Slling * specially. 14055094Slling */ 14065094Slling if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) 14075094Slling return (-1); 14085094Slling 14095094Slling entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : 14105094Slling ZFS_PROP_NAME; 14115094Slling entry->pl_width = zprop_width(entry->pl_prop, 14125094Slling &entry->pl_fixed, type); 14135094Slling entry->pl_all = B_TRUE; 14145094Slling entry->pl_next = *plp; 14155094Slling *plp = entry; 14165094Slling } 14175094Slling return (0); 14185094Slling } 14195094Slling 14205094Slling int 14215094Slling zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, 14225094Slling zfs_type_t type) 14235094Slling { 14245094Slling return (zprop_iter_common(func, cb, show_all, ordered, type)); 14255094Slling } 1426