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