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