xref: /illumos-gate/usr/src/lib/libzfs/common/libzfs_util.c (revision 46b592853d0f4f11781b6b0a7533f267c6aee132)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Internal utility routines for the ZFS library.
28  */
29 
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <libintl.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <strings.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #include <math.h>
40 #include <sys/mnttab.h>
41 #include <sys/mntent.h>
42 #include <sys/types.h>
43 
44 #include <libzfs.h>
45 
46 #include "libzfs_impl.h"
47 #include "zfs_prop.h"
48 
49 int
50 libzfs_errno(libzfs_handle_t *hdl)
51 {
52 	return (hdl->libzfs_error);
53 }
54 
55 const char *
56 libzfs_error_action(libzfs_handle_t *hdl)
57 {
58 	return (hdl->libzfs_action);
59 }
60 
61 const char *
62 libzfs_error_description(libzfs_handle_t *hdl)
63 {
64 	if (hdl->libzfs_desc[0] != '\0')
65 		return (hdl->libzfs_desc);
66 
67 	switch (hdl->libzfs_error) {
68 	case EZFS_NOMEM:
69 		return (dgettext(TEXT_DOMAIN, "out of memory"));
70 	case EZFS_BADPROP:
71 		return (dgettext(TEXT_DOMAIN, "invalid property value"));
72 	case EZFS_PROPREADONLY:
73 		return (dgettext(TEXT_DOMAIN, "read only property"));
74 	case EZFS_PROPTYPE:
75 		return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
76 		    "datasets of this type"));
77 	case EZFS_PROPNONINHERIT:
78 		return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
79 	case EZFS_PROPSPACE:
80 		return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
81 	case EZFS_BADTYPE:
82 		return (dgettext(TEXT_DOMAIN, "operation not applicable to "
83 		    "datasets of this type"));
84 	case EZFS_BUSY:
85 		return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
86 	case EZFS_EXISTS:
87 		return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
88 	case EZFS_NOENT:
89 		return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
90 	case EZFS_BADSTREAM:
91 		return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
92 	case EZFS_DSREADONLY:
93 		return (dgettext(TEXT_DOMAIN, "dataset is read only"));
94 	case EZFS_VOLTOOBIG:
95 		return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
96 		    "this system"));
97 	case EZFS_INVALIDNAME:
98 		return (dgettext(TEXT_DOMAIN, "invalid name"));
99 	case EZFS_BADRESTORE:
100 		return (dgettext(TEXT_DOMAIN, "unable to restore to "
101 		    "destination"));
102 	case EZFS_BADBACKUP:
103 		return (dgettext(TEXT_DOMAIN, "backup failed"));
104 	case EZFS_BADTARGET:
105 		return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
106 	case EZFS_NODEVICE:
107 		return (dgettext(TEXT_DOMAIN, "no such device in pool"));
108 	case EZFS_BADDEV:
109 		return (dgettext(TEXT_DOMAIN, "invalid device"));
110 	case EZFS_NOREPLICAS:
111 		return (dgettext(TEXT_DOMAIN, "no valid replicas"));
112 	case EZFS_RESILVERING:
113 		return (dgettext(TEXT_DOMAIN, "currently resilvering"));
114 	case EZFS_BADVERSION:
115 		return (dgettext(TEXT_DOMAIN, "unsupported version"));
116 	case EZFS_POOLUNAVAIL:
117 		return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
118 	case EZFS_DEVOVERFLOW:
119 		return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
120 	case EZFS_BADPATH:
121 		return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
122 	case EZFS_CROSSTARGET:
123 		return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
124 		    "pools"));
125 	case EZFS_ZONED:
126 		return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
127 	case EZFS_MOUNTFAILED:
128 		return (dgettext(TEXT_DOMAIN, "mount failed"));
129 	case EZFS_UMOUNTFAILED:
130 		return (dgettext(TEXT_DOMAIN, "umount failed"));
131 	case EZFS_UNSHARENFSFAILED:
132 		return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
133 	case EZFS_SHARENFSFAILED:
134 		return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
135 	case EZFS_UNSHARESMBFAILED:
136 		return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
137 	case EZFS_SHARESMBFAILED:
138 		return (dgettext(TEXT_DOMAIN, "smb add share failed"));
139 	case EZFS_ISCSISVCUNAVAIL:
140 		return (dgettext(TEXT_DOMAIN,
141 		    "iscsitgt service need to be enabled by "
142 		    "a privileged user"));
143 	case EZFS_PERM:
144 		return (dgettext(TEXT_DOMAIN, "permission denied"));
145 	case EZFS_NOSPC:
146 		return (dgettext(TEXT_DOMAIN, "out of space"));
147 	case EZFS_IO:
148 		return (dgettext(TEXT_DOMAIN, "I/O error"));
149 	case EZFS_INTR:
150 		return (dgettext(TEXT_DOMAIN, "signal received"));
151 	case EZFS_ISSPARE:
152 		return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
153 		    "spare"));
154 	case EZFS_INVALCONFIG:
155 		return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
156 	case EZFS_RECURSIVE:
157 		return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
158 	case EZFS_NOHISTORY:
159 		return (dgettext(TEXT_DOMAIN, "no history available"));
160 	case EZFS_UNSHAREISCSIFAILED:
161 		return (dgettext(TEXT_DOMAIN,
162 		    "iscsitgtd failed request to unshare"));
163 	case EZFS_SHAREISCSIFAILED:
164 		return (dgettext(TEXT_DOMAIN,
165 		    "iscsitgtd failed request to share"));
166 	case EZFS_POOLPROPS:
167 		return (dgettext(TEXT_DOMAIN, "failed to retrieve "
168 		    "pool properties"));
169 	case EZFS_POOL_NOTSUP:
170 		return (dgettext(TEXT_DOMAIN, "operation not supported "
171 		    "on this type of pool"));
172 	case EZFS_POOL_INVALARG:
173 		return (dgettext(TEXT_DOMAIN, "invalid argument for "
174 		    "this pool operation"));
175 	case EZFS_NAMETOOLONG:
176 		return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
177 	case EZFS_OPENFAILED:
178 		return (dgettext(TEXT_DOMAIN, "open failed"));
179 	case EZFS_NOCAP:
180 		return (dgettext(TEXT_DOMAIN,
181 		    "disk capacity information could not be retrieved"));
182 	case EZFS_LABELFAILED:
183 		return (dgettext(TEXT_DOMAIN, "write of label failed"));
184 	case EZFS_BADWHO:
185 		return (dgettext(TEXT_DOMAIN, "invalid user/group"));
186 	case EZFS_BADPERM:
187 		return (dgettext(TEXT_DOMAIN, "invalid permission"));
188 	case EZFS_BADPERMSET:
189 		return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
190 	case EZFS_NODELEGATION:
191 		return (dgettext(TEXT_DOMAIN, "delegated administration is "
192 		    "disabled on pool"));
193 	case EZFS_PERMRDONLY:
194 		return (dgettext(TEXT_DOMAIN, "snapshot permissions cannot be"
195 		    " modified"));
196 	case EZFS_BADCACHE:
197 		return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
198 	case EZFS_ISL2CACHE:
199 		return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
200 	case EZFS_VDEVNOTSUP:
201 		return (dgettext(TEXT_DOMAIN, "vdev specification is not "
202 		    "supported"));
203 	case EZFS_NOTSUP:
204 		return (dgettext(TEXT_DOMAIN, "operation not supported "
205 		    "on this dataset"));
206 	case EZFS_ACTIVE_SPARE:
207 		return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
208 		    "device"));
209 	case EZFS_UNPLAYED_LOGS:
210 		return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
211 		    "logs"));
212 	case EZFS_REFTAG_RELE:
213 		return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
214 	case EZFS_REFTAG_HOLD:
215 		return (dgettext(TEXT_DOMAIN, "tag already exists on this "
216 		    "dataset"));
217 	case EZFS_TAGTOOLONG:
218 		return (dgettext(TEXT_DOMAIN, "tag too long"));
219 	case EZFS_UNKNOWN:
220 		return (dgettext(TEXT_DOMAIN, "unknown error"));
221 	default:
222 		assert(hdl->libzfs_error == 0);
223 		return (dgettext(TEXT_DOMAIN, "no error"));
224 	}
225 }
226 
227 /*PRINTFLIKE2*/
228 void
229 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
230 {
231 	va_list ap;
232 
233 	va_start(ap, fmt);
234 
235 	(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
236 	    fmt, ap);
237 	hdl->libzfs_desc_active = 1;
238 
239 	va_end(ap);
240 }
241 
242 static void
243 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
244 {
245 	(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
246 	    fmt, ap);
247 	hdl->libzfs_error = error;
248 
249 	if (hdl->libzfs_desc_active)
250 		hdl->libzfs_desc_active = 0;
251 	else
252 		hdl->libzfs_desc[0] = '\0';
253 
254 	if (hdl->libzfs_printerr) {
255 		if (error == EZFS_UNKNOWN) {
256 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
257 			    "error: %s\n"), libzfs_error_description(hdl));
258 			abort();
259 		}
260 
261 		(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
262 		    libzfs_error_description(hdl));
263 		if (error == EZFS_NOMEM)
264 			exit(1);
265 	}
266 }
267 
268 int
269 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
270 {
271 	return (zfs_error_fmt(hdl, error, "%s", msg));
272 }
273 
274 /*PRINTFLIKE3*/
275 int
276 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
277 {
278 	va_list ap;
279 
280 	va_start(ap, fmt);
281 
282 	zfs_verror(hdl, error, fmt, ap);
283 
284 	va_end(ap);
285 
286 	return (-1);
287 }
288 
289 static int
290 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
291     va_list ap)
292 {
293 	switch (error) {
294 	case EPERM:
295 	case EACCES:
296 		zfs_verror(hdl, EZFS_PERM, fmt, ap);
297 		return (-1);
298 
299 	case ECANCELED:
300 		zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
301 		return (-1);
302 
303 	case EIO:
304 		zfs_verror(hdl, EZFS_IO, fmt, ap);
305 		return (-1);
306 
307 	case EINTR:
308 		zfs_verror(hdl, EZFS_INTR, fmt, ap);
309 		return (-1);
310 	}
311 
312 	return (0);
313 }
314 
315 int
316 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
317 {
318 	return (zfs_standard_error_fmt(hdl, error, "%s", msg));
319 }
320 
321 /*PRINTFLIKE3*/
322 int
323 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
324 {
325 	va_list ap;
326 
327 	va_start(ap, fmt);
328 
329 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
330 		va_end(ap);
331 		return (-1);
332 	}
333 
334 	switch (error) {
335 	case ENXIO:
336 	case ENODEV:
337 		zfs_verror(hdl, EZFS_IO, fmt, ap);
338 		break;
339 
340 	case ENOENT:
341 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
342 		    "dataset does not exist"));
343 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
344 		break;
345 
346 	case ENOSPC:
347 	case EDQUOT:
348 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
349 		return (-1);
350 
351 	case EEXIST:
352 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
353 		    "dataset already exists"));
354 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
355 		break;
356 
357 	case EBUSY:
358 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
359 		    "dataset is busy"));
360 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
361 		break;
362 	case EROFS:
363 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
364 		    "snapshot permissions cannot be modified"));
365 		zfs_verror(hdl, EZFS_PERMRDONLY, fmt, ap);
366 		break;
367 	case ENAMETOOLONG:
368 		zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
369 		break;
370 	case ENOTSUP:
371 		zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
372 		break;
373 	case EAGAIN:
374 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
375 		    "pool I/O is currently suspended"));
376 		zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
377 		break;
378 	default:
379 		zfs_error_aux(hdl, strerror(errno));
380 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
381 		break;
382 	}
383 
384 	va_end(ap);
385 	return (-1);
386 }
387 
388 int
389 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
390 {
391 	return (zpool_standard_error_fmt(hdl, error, "%s", msg));
392 }
393 
394 /*PRINTFLIKE3*/
395 int
396 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
397 {
398 	va_list ap;
399 
400 	va_start(ap, fmt);
401 
402 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
403 		va_end(ap);
404 		return (-1);
405 	}
406 
407 	switch (error) {
408 	case ENODEV:
409 		zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
410 		break;
411 
412 	case ENOENT:
413 		zfs_error_aux(hdl,
414 		    dgettext(TEXT_DOMAIN, "no such pool or dataset"));
415 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
416 		break;
417 
418 	case EEXIST:
419 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
420 		    "pool already exists"));
421 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
422 		break;
423 
424 	case EBUSY:
425 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
426 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
427 		break;
428 
429 	case ENXIO:
430 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
431 		    "one or more devices is currently unavailable"));
432 		zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
433 		break;
434 
435 	case ENAMETOOLONG:
436 		zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
437 		break;
438 
439 	case ENOTSUP:
440 		zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
441 		break;
442 
443 	case EINVAL:
444 		zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
445 		break;
446 
447 	case ENOSPC:
448 	case EDQUOT:
449 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
450 		return (-1);
451 	case EAGAIN:
452 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
453 		    "pool I/O is currently suspended"));
454 		zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
455 		break;
456 
457 	default:
458 		zfs_error_aux(hdl, strerror(error));
459 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
460 	}
461 
462 	va_end(ap);
463 	return (-1);
464 }
465 
466 /*
467  * Display an out of memory error message and abort the current program.
468  */
469 int
470 no_memory(libzfs_handle_t *hdl)
471 {
472 	return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
473 }
474 
475 /*
476  * A safe form of malloc() which will die if the allocation fails.
477  */
478 void *
479 zfs_alloc(libzfs_handle_t *hdl, size_t size)
480 {
481 	void *data;
482 
483 	if ((data = calloc(1, size)) == NULL)
484 		(void) no_memory(hdl);
485 
486 	return (data);
487 }
488 
489 /*
490  * A safe form of realloc(), which also zeroes newly allocated space.
491  */
492 void *
493 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
494 {
495 	void *ret;
496 
497 	if ((ret = realloc(ptr, newsize)) == NULL) {
498 		(void) no_memory(hdl);
499 		return (NULL);
500 	}
501 
502 	bzero((char *)ret + oldsize, (newsize - oldsize));
503 	return (ret);
504 }
505 
506 /*
507  * A safe form of strdup() which will die if the allocation fails.
508  */
509 char *
510 zfs_strdup(libzfs_handle_t *hdl, const char *str)
511 {
512 	char *ret;
513 
514 	if ((ret = strdup(str)) == NULL)
515 		(void) no_memory(hdl);
516 
517 	return (ret);
518 }
519 
520 /*
521  * Convert a number to an appropriately human-readable output.
522  */
523 void
524 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
525 {
526 	uint64_t n = num;
527 	int index = 0;
528 	char u;
529 
530 	while (n >= 1024) {
531 		n /= 1024;
532 		index++;
533 	}
534 
535 	u = " KMGTPE"[index];
536 
537 	if (index == 0) {
538 		(void) snprintf(buf, buflen, "%llu", n);
539 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
540 		/*
541 		 * If this is an even multiple of the base, always display
542 		 * without any decimal precision.
543 		 */
544 		(void) snprintf(buf, buflen, "%llu%c", n, u);
545 	} else {
546 		/*
547 		 * We want to choose a precision that reflects the best choice
548 		 * for fitting in 5 characters.  This can get rather tricky when
549 		 * we have numbers that are very close to an order of magnitude.
550 		 * For example, when displaying 10239 (which is really 9.999K),
551 		 * we want only a single place of precision for 10.0K.  We could
552 		 * develop some complex heuristics for this, but it's much
553 		 * easier just to try each combination in turn.
554 		 */
555 		int i;
556 		for (i = 2; i >= 0; i--) {
557 			if (snprintf(buf, buflen, "%.*f%c", i,
558 			    (double)num / (1ULL << 10 * index), u) <= 5)
559 				break;
560 		}
561 	}
562 }
563 
564 void
565 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
566 {
567 	hdl->libzfs_printerr = printerr;
568 }
569 
570 libzfs_handle_t *
571 libzfs_init(void)
572 {
573 	libzfs_handle_t *hdl;
574 
575 	if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
576 		return (NULL);
577 	}
578 
579 	if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
580 		free(hdl);
581 		return (NULL);
582 	}
583 
584 	if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
585 		(void) close(hdl->libzfs_fd);
586 		free(hdl);
587 		return (NULL);
588 	}
589 
590 	hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
591 
592 	zfs_prop_init();
593 	zpool_prop_init();
594 	libzfs_mnttab_init(hdl);
595 
596 	return (hdl);
597 }
598 
599 void
600 libzfs_fini(libzfs_handle_t *hdl)
601 {
602 	(void) close(hdl->libzfs_fd);
603 	if (hdl->libzfs_mnttab)
604 		(void) fclose(hdl->libzfs_mnttab);
605 	if (hdl->libzfs_sharetab)
606 		(void) fclose(hdl->libzfs_sharetab);
607 	zfs_uninit_libshare(hdl);
608 	if (hdl->libzfs_log_str)
609 		(void) free(hdl->libzfs_log_str);
610 	zpool_free_handles(hdl);
611 	libzfs_fru_clear(hdl, B_TRUE);
612 	namespace_clear(hdl);
613 	libzfs_mnttab_fini(hdl);
614 	free(hdl);
615 }
616 
617 libzfs_handle_t *
618 zpool_get_handle(zpool_handle_t *zhp)
619 {
620 	return (zhp->zpool_hdl);
621 }
622 
623 libzfs_handle_t *
624 zfs_get_handle(zfs_handle_t *zhp)
625 {
626 	return (zhp->zfs_hdl);
627 }
628 
629 zpool_handle_t *
630 zfs_get_pool_handle(const zfs_handle_t *zhp)
631 {
632 	return (zhp->zpool_hdl);
633 }
634 
635 /*
636  * Given a name, determine whether or not it's a valid path
637  * (starts with '/' or "./").  If so, walk the mnttab trying
638  * to match the device number.  If not, treat the path as an
639  * fs/vol/snap name.
640  */
641 zfs_handle_t *
642 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
643 {
644 	struct stat64 statbuf;
645 	struct extmnttab entry;
646 	int ret;
647 
648 	if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
649 		/*
650 		 * It's not a valid path, assume it's a name of type 'argtype'.
651 		 */
652 		return (zfs_open(hdl, path, argtype));
653 	}
654 
655 	if (stat64(path, &statbuf) != 0) {
656 		(void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
657 		return (NULL);
658 	}
659 
660 	rewind(hdl->libzfs_mnttab);
661 	while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
662 		if (makedevice(entry.mnt_major, entry.mnt_minor) ==
663 		    statbuf.st_dev) {
664 			break;
665 		}
666 	}
667 	if (ret != 0) {
668 		return (NULL);
669 	}
670 
671 	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
672 		(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
673 		    path);
674 		return (NULL);
675 	}
676 
677 	return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
678 }
679 
680 /*
681  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
682  * an ioctl().
683  */
684 int
685 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
686 {
687 	if (len == 0)
688 		len = 4*1024;
689 	zc->zc_nvlist_dst_size = len;
690 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
691 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
692 		return (-1);
693 
694 	return (0);
695 }
696 
697 /*
698  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
699  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
700  * filled in by the kernel to indicate the actual required size.
701  */
702 int
703 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
704 {
705 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
706 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
707 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size))
708 	    == NULL)
709 		return (-1);
710 
711 	return (0);
712 }
713 
714 /*
715  * Called to free the src and dst nvlists stored in the command structure.
716  */
717 void
718 zcmd_free_nvlists(zfs_cmd_t *zc)
719 {
720 	free((void *)(uintptr_t)zc->zc_nvlist_conf);
721 	free((void *)(uintptr_t)zc->zc_nvlist_src);
722 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
723 }
724 
725 static int
726 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
727     nvlist_t *nvl)
728 {
729 	char *packed;
730 	size_t len;
731 
732 	verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
733 
734 	if ((packed = zfs_alloc(hdl, len)) == NULL)
735 		return (-1);
736 
737 	verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
738 
739 	*outnv = (uint64_t)(uintptr_t)packed;
740 	*outlen = len;
741 
742 	return (0);
743 }
744 
745 int
746 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
747 {
748 	return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
749 	    &zc->zc_nvlist_conf_size, nvl));
750 }
751 
752 int
753 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
754 {
755 	return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
756 	    &zc->zc_nvlist_src_size, nvl));
757 }
758 
759 /*
760  * Unpacks an nvlist from the ZFS ioctl command structure.
761  */
762 int
763 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
764 {
765 	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
766 	    zc->zc_nvlist_dst_size, nvlp, 0) != 0)
767 		return (no_memory(hdl));
768 
769 	return (0);
770 }
771 
772 int
773 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
774 {
775 	int error;
776 
777 	zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str;
778 	error = ioctl(hdl->libzfs_fd, request, zc);
779 	if (hdl->libzfs_log_str) {
780 		free(hdl->libzfs_log_str);
781 		hdl->libzfs_log_str = NULL;
782 	}
783 	zc->zc_history = 0;
784 
785 	return (error);
786 }
787 
788 /*
789  * ================================================================
790  * API shared by zfs and zpool property management
791  * ================================================================
792  */
793 
794 static void
795 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
796 {
797 	zprop_list_t *pl = cbp->cb_proplist;
798 	int i;
799 	char *title;
800 	size_t len;
801 
802 	cbp->cb_first = B_FALSE;
803 	if (cbp->cb_scripted)
804 		return;
805 
806 	/*
807 	 * Start with the length of the column headers.
808 	 */
809 	cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
810 	cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
811 	    "PROPERTY"));
812 	cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
813 	    "VALUE"));
814 	cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
815 	    "SOURCE"));
816 
817 	/* first property is always NAME */
818 	assert(cbp->cb_proplist->pl_prop ==
819 	    ((type == ZFS_TYPE_POOL) ?  ZPOOL_PROP_NAME : ZFS_PROP_NAME));
820 
821 	/*
822 	 * Go through and calculate the widths for each column.  For the
823 	 * 'source' column, we kludge it up by taking the worst-case scenario of
824 	 * inheriting from the longest name.  This is acceptable because in the
825 	 * majority of cases 'SOURCE' is the last column displayed, and we don't
826 	 * use the width anyway.  Note that the 'VALUE' column can be oversized,
827 	 * if the name of the property is much longer the any values we find.
828 	 */
829 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
830 		/*
831 		 * 'PROPERTY' column
832 		 */
833 		if (pl->pl_prop != ZPROP_INVAL) {
834 			const char *propname = (type == ZFS_TYPE_POOL) ?
835 			    zpool_prop_to_name(pl->pl_prop) :
836 			    zfs_prop_to_name(pl->pl_prop);
837 
838 			len = strlen(propname);
839 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
840 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
841 		} else {
842 			len = strlen(pl->pl_user_prop);
843 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
844 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
845 		}
846 
847 		/*
848 		 * 'VALUE' column.  The first property is always the 'name'
849 		 * property that was tacked on either by /sbin/zfs's
850 		 * zfs_do_get() or when calling zprop_expand_list(), so we
851 		 * ignore its width.  If the user specified the name property
852 		 * to display, then it will be later in the list in any case.
853 		 */
854 		if (pl != cbp->cb_proplist &&
855 		    pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
856 			cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
857 
858 		/*
859 		 * 'NAME' and 'SOURCE' columns
860 		 */
861 		if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
862 		    ZFS_PROP_NAME) &&
863 		    pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
864 			cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
865 			cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
866 			    strlen(dgettext(TEXT_DOMAIN, "inherited from"));
867 		}
868 	}
869 
870 	/*
871 	 * Now go through and print the headers.
872 	 */
873 	for (i = 0; i < 4; i++) {
874 		switch (cbp->cb_columns[i]) {
875 		case GET_COL_NAME:
876 			title = dgettext(TEXT_DOMAIN, "NAME");
877 			break;
878 		case GET_COL_PROPERTY:
879 			title = dgettext(TEXT_DOMAIN, "PROPERTY");
880 			break;
881 		case GET_COL_VALUE:
882 			title = dgettext(TEXT_DOMAIN, "VALUE");
883 			break;
884 		case GET_COL_SOURCE:
885 			title = dgettext(TEXT_DOMAIN, "SOURCE");
886 			break;
887 		default:
888 			title = NULL;
889 		}
890 
891 		if (title != NULL) {
892 			if (i == 3 || cbp->cb_columns[i + 1] == 0)
893 				(void) printf("%s", title);
894 			else
895 				(void) printf("%-*s  ",
896 				    cbp->cb_colwidths[cbp->cb_columns[i]],
897 				    title);
898 		}
899 	}
900 	(void) printf("\n");
901 }
902 
903 /*
904  * Display a single line of output, according to the settings in the callback
905  * structure.
906  */
907 void
908 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
909     const char *propname, const char *value, zprop_source_t sourcetype,
910     const char *source)
911 {
912 	int i;
913 	const char *str;
914 	char buf[128];
915 
916 	/*
917 	 * Ignore those source types that the user has chosen to ignore.
918 	 */
919 	if ((sourcetype & cbp->cb_sources) == 0)
920 		return;
921 
922 	if (cbp->cb_first)
923 		zprop_print_headers(cbp, cbp->cb_type);
924 
925 	for (i = 0; i < 4; i++) {
926 		switch (cbp->cb_columns[i]) {
927 		case GET_COL_NAME:
928 			str = name;
929 			break;
930 
931 		case GET_COL_PROPERTY:
932 			str = propname;
933 			break;
934 
935 		case GET_COL_VALUE:
936 			str = value;
937 			break;
938 
939 		case GET_COL_SOURCE:
940 			switch (sourcetype) {
941 			case ZPROP_SRC_NONE:
942 				str = "-";
943 				break;
944 
945 			case ZPROP_SRC_DEFAULT:
946 				str = "default";
947 				break;
948 
949 			case ZPROP_SRC_LOCAL:
950 				str = "local";
951 				break;
952 
953 			case ZPROP_SRC_TEMPORARY:
954 				str = "temporary";
955 				break;
956 
957 			case ZPROP_SRC_INHERITED:
958 				(void) snprintf(buf, sizeof (buf),
959 				    "inherited from %s", source);
960 				str = buf;
961 				break;
962 			}
963 			break;
964 
965 		default:
966 			continue;
967 		}
968 
969 		if (cbp->cb_columns[i + 1] == 0)
970 			(void) printf("%s", str);
971 		else if (cbp->cb_scripted)
972 			(void) printf("%s\t", str);
973 		else
974 			(void) printf("%-*s  ",
975 			    cbp->cb_colwidths[cbp->cb_columns[i]],
976 			    str);
977 
978 	}
979 
980 	(void) printf("\n");
981 }
982 
983 /*
984  * Given a numeric suffix, convert the value into a number of bits that the
985  * resulting value must be shifted.
986  */
987 static int
988 str2shift(libzfs_handle_t *hdl, const char *buf)
989 {
990 	const char *ends = "BKMGTPEZ";
991 	int i;
992 
993 	if (buf[0] == '\0')
994 		return (0);
995 	for (i = 0; i < strlen(ends); i++) {
996 		if (toupper(buf[0]) == ends[i])
997 			break;
998 	}
999 	if (i == strlen(ends)) {
1000 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1001 		    "invalid numeric suffix '%s'"), buf);
1002 		return (-1);
1003 	}
1004 
1005 	/*
1006 	 * We want to allow trailing 'b' characters for 'GB' or 'Mb'.  But don't
1007 	 * allow 'BB' - that's just weird.
1008 	 */
1009 	if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1010 	    toupper(buf[0]) != 'B'))
1011 		return (10*i);
1012 
1013 	zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1014 	    "invalid numeric suffix '%s'"), buf);
1015 	return (-1);
1016 }
1017 
1018 /*
1019  * Convert a string of the form '100G' into a real number.  Used when setting
1020  * properties or creating a volume.  'buf' is used to place an extended error
1021  * message for the caller to use.
1022  */
1023 int
1024 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1025 {
1026 	char *end;
1027 	int shift;
1028 
1029 	*num = 0;
1030 
1031 	/* Check to see if this looks like a number.  */
1032 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1033 		if (hdl)
1034 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1035 			    "bad numeric value '%s'"), value);
1036 		return (-1);
1037 	}
1038 
1039 	/* Rely on strtoull() to process the numeric portion.  */
1040 	errno = 0;
1041 	*num = strtoull(value, &end, 10);
1042 
1043 	/*
1044 	 * Check for ERANGE, which indicates that the value is too large to fit
1045 	 * in a 64-bit value.
1046 	 */
1047 	if (errno == ERANGE) {
1048 		if (hdl)
1049 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1050 			    "numeric value is too large"));
1051 		return (-1);
1052 	}
1053 
1054 	/*
1055 	 * If we have a decimal value, then do the computation with floating
1056 	 * point arithmetic.  Otherwise, use standard arithmetic.
1057 	 */
1058 	if (*end == '.') {
1059 		double fval = strtod(value, &end);
1060 
1061 		if ((shift = str2shift(hdl, end)) == -1)
1062 			return (-1);
1063 
1064 		fval *= pow(2, shift);
1065 
1066 		if (fval > UINT64_MAX) {
1067 			if (hdl)
1068 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1069 				    "numeric value is too large"));
1070 			return (-1);
1071 		}
1072 
1073 		*num = (uint64_t)fval;
1074 	} else {
1075 		if ((shift = str2shift(hdl, end)) == -1)
1076 			return (-1);
1077 
1078 		/* Check for overflow */
1079 		if (shift >= 64 || (*num << shift) >> shift != *num) {
1080 			if (hdl)
1081 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1082 				    "numeric value is too large"));
1083 			return (-1);
1084 		}
1085 
1086 		*num <<= shift;
1087 	}
1088 
1089 	return (0);
1090 }
1091 
1092 /*
1093  * Given a propname=value nvpair to set, parse any numeric properties
1094  * (index, boolean, etc) if they are specified as strings and add the
1095  * resulting nvpair to the returned nvlist.
1096  *
1097  * At the DSL layer, all properties are either 64-bit numbers or strings.
1098  * We want the user to be able to ignore this fact and specify properties
1099  * as native values (numbers, for example) or as strings (to simplify
1100  * command line utilities).  This also handles converting index types
1101  * (compression, checksum, etc) from strings to their on-disk index.
1102  */
1103 int
1104 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1105     zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1106     const char *errbuf)
1107 {
1108 	data_type_t datatype = nvpair_type(elem);
1109 	zprop_type_t proptype;
1110 	const char *propname;
1111 	char *value;
1112 	boolean_t isnone = B_FALSE;
1113 
1114 	if (type == ZFS_TYPE_POOL) {
1115 		proptype = zpool_prop_get_type(prop);
1116 		propname = zpool_prop_to_name(prop);
1117 	} else {
1118 		proptype = zfs_prop_get_type(prop);
1119 		propname = zfs_prop_to_name(prop);
1120 	}
1121 
1122 	/*
1123 	 * Convert any properties to the internal DSL value types.
1124 	 */
1125 	*svalp = NULL;
1126 	*ivalp = 0;
1127 
1128 	switch (proptype) {
1129 	case PROP_TYPE_STRING:
1130 		if (datatype != DATA_TYPE_STRING) {
1131 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1132 			    "'%s' must be a string"), nvpair_name(elem));
1133 			goto error;
1134 		}
1135 		(void) nvpair_value_string(elem, svalp);
1136 		if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1137 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1138 			    "'%s' is too long"), nvpair_name(elem));
1139 			goto error;
1140 		}
1141 		break;
1142 
1143 	case PROP_TYPE_NUMBER:
1144 		if (datatype == DATA_TYPE_STRING) {
1145 			(void) nvpair_value_string(elem, &value);
1146 			if (strcmp(value, "none") == 0) {
1147 				isnone = B_TRUE;
1148 			} else if (zfs_nicestrtonum(hdl, value, ivalp)
1149 			    != 0) {
1150 				goto error;
1151 			}
1152 		} else if (datatype == DATA_TYPE_UINT64) {
1153 			(void) nvpair_value_uint64(elem, ivalp);
1154 		} else {
1155 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1156 			    "'%s' must be a number"), nvpair_name(elem));
1157 			goto error;
1158 		}
1159 
1160 		/*
1161 		 * Quota special: force 'none' and don't allow 0.
1162 		 */
1163 		if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1164 		    (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1165 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1166 			    "use 'none' to disable quota/refquota"));
1167 			goto error;
1168 		}
1169 		break;
1170 
1171 	case PROP_TYPE_INDEX:
1172 		if (datatype != DATA_TYPE_STRING) {
1173 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1174 			    "'%s' must be a string"), nvpair_name(elem));
1175 			goto error;
1176 		}
1177 
1178 		(void) nvpair_value_string(elem, &value);
1179 
1180 		if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1181 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1182 			    "'%s' must be one of '%s'"), propname,
1183 			    zprop_values(prop, type));
1184 			goto error;
1185 		}
1186 		break;
1187 
1188 	default:
1189 		abort();
1190 	}
1191 
1192 	/*
1193 	 * Add the result to our return set of properties.
1194 	 */
1195 	if (*svalp != NULL) {
1196 		if (nvlist_add_string(ret, propname, *svalp) != 0) {
1197 			(void) no_memory(hdl);
1198 			return (-1);
1199 		}
1200 	} else {
1201 		if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1202 			(void) no_memory(hdl);
1203 			return (-1);
1204 		}
1205 	}
1206 
1207 	return (0);
1208 error:
1209 	(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1210 	return (-1);
1211 }
1212 
1213 static int
1214 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1215     zfs_type_t type)
1216 {
1217 	int prop;
1218 	zprop_list_t *entry;
1219 
1220 	prop = zprop_name_to_prop(propname, type);
1221 
1222 	if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1223 		prop = ZPROP_INVAL;
1224 
1225 	/*
1226 	 * When no property table entry can be found, return failure if
1227 	 * this is a pool property or if this isn't a user-defined
1228 	 * dataset property,
1229 	 */
1230 	if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
1231 	    (!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) {
1232 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1233 		    "invalid property '%s'"), propname);
1234 		return (zfs_error(hdl, EZFS_BADPROP,
1235 		    dgettext(TEXT_DOMAIN, "bad property list")));
1236 	}
1237 
1238 	if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1239 		return (-1);
1240 
1241 	entry->pl_prop = prop;
1242 	if (prop == ZPROP_INVAL) {
1243 		if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) {
1244 			free(entry);
1245 			return (-1);
1246 		}
1247 		entry->pl_width = strlen(propname);
1248 	} else {
1249 		entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1250 		    type);
1251 	}
1252 
1253 	*listp = entry;
1254 
1255 	return (0);
1256 }
1257 
1258 /*
1259  * Given a comma-separated list of properties, construct a property list
1260  * containing both user-defined and native properties.  This function will
1261  * return a NULL list if 'all' is specified, which can later be expanded
1262  * by zprop_expand_list().
1263  */
1264 int
1265 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1266     zfs_type_t type)
1267 {
1268 	*listp = NULL;
1269 
1270 	/*
1271 	 * If 'all' is specified, return a NULL list.
1272 	 */
1273 	if (strcmp(props, "all") == 0)
1274 		return (0);
1275 
1276 	/*
1277 	 * If no props were specified, return an error.
1278 	 */
1279 	if (props[0] == '\0') {
1280 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1281 		    "no properties specified"));
1282 		return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1283 		    "bad property list")));
1284 	}
1285 
1286 	/*
1287 	 * It would be nice to use getsubopt() here, but the inclusion of column
1288 	 * aliases makes this more effort than it's worth.
1289 	 */
1290 	while (*props != '\0') {
1291 		size_t len;
1292 		char *p;
1293 		char c;
1294 
1295 		if ((p = strchr(props, ',')) == NULL) {
1296 			len = strlen(props);
1297 			p = props + len;
1298 		} else {
1299 			len = p - props;
1300 		}
1301 
1302 		/*
1303 		 * Check for empty options.
1304 		 */
1305 		if (len == 0) {
1306 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1307 			    "empty property name"));
1308 			return (zfs_error(hdl, EZFS_BADPROP,
1309 			    dgettext(TEXT_DOMAIN, "bad property list")));
1310 		}
1311 
1312 		/*
1313 		 * Check all regular property names.
1314 		 */
1315 		c = props[len];
1316 		props[len] = '\0';
1317 
1318 		if (strcmp(props, "space") == 0) {
1319 			static char *spaceprops[] = {
1320 				"name", "avail", "used", "usedbysnapshots",
1321 				"usedbydataset", "usedbyrefreservation",
1322 				"usedbychildren", NULL
1323 			};
1324 			int i;
1325 
1326 			for (i = 0; spaceprops[i]; i++) {
1327 				if (addlist(hdl, spaceprops[i], listp, type))
1328 					return (-1);
1329 				listp = &(*listp)->pl_next;
1330 			}
1331 		} else {
1332 			if (addlist(hdl, props, listp, type))
1333 				return (-1);
1334 			listp = &(*listp)->pl_next;
1335 		}
1336 
1337 		props = p;
1338 		if (c == ',')
1339 			props++;
1340 	}
1341 
1342 	return (0);
1343 }
1344 
1345 void
1346 zprop_free_list(zprop_list_t *pl)
1347 {
1348 	zprop_list_t *next;
1349 
1350 	while (pl != NULL) {
1351 		next = pl->pl_next;
1352 		free(pl->pl_user_prop);
1353 		free(pl);
1354 		pl = next;
1355 	}
1356 }
1357 
1358 typedef struct expand_data {
1359 	zprop_list_t	**last;
1360 	libzfs_handle_t	*hdl;
1361 	zfs_type_t type;
1362 } expand_data_t;
1363 
1364 int
1365 zprop_expand_list_cb(int prop, void *cb)
1366 {
1367 	zprop_list_t *entry;
1368 	expand_data_t *edp = cb;
1369 
1370 	if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1371 		return (ZPROP_INVAL);
1372 
1373 	entry->pl_prop = prop;
1374 	entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1375 	entry->pl_all = B_TRUE;
1376 
1377 	*(edp->last) = entry;
1378 	edp->last = &entry->pl_next;
1379 
1380 	return (ZPROP_CONT);
1381 }
1382 
1383 int
1384 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1385 {
1386 	zprop_list_t *entry;
1387 	zprop_list_t **last;
1388 	expand_data_t exp;
1389 
1390 	if (*plp == NULL) {
1391 		/*
1392 		 * If this is the very first time we've been called for an 'all'
1393 		 * specification, expand the list to include all native
1394 		 * properties.
1395 		 */
1396 		last = plp;
1397 
1398 		exp.last = last;
1399 		exp.hdl = hdl;
1400 		exp.type = type;
1401 
1402 		if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1403 		    B_FALSE, type) == ZPROP_INVAL)
1404 			return (-1);
1405 
1406 		/*
1407 		 * Add 'name' to the beginning of the list, which is handled
1408 		 * specially.
1409 		 */
1410 		if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1411 			return (-1);
1412 
1413 		entry->pl_prop = (type == ZFS_TYPE_POOL) ?  ZPOOL_PROP_NAME :
1414 		    ZFS_PROP_NAME;
1415 		entry->pl_width = zprop_width(entry->pl_prop,
1416 		    &entry->pl_fixed, type);
1417 		entry->pl_all = B_TRUE;
1418 		entry->pl_next = *plp;
1419 		*plp = entry;
1420 	}
1421 	return (0);
1422 }
1423 
1424 int
1425 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1426     zfs_type_t type)
1427 {
1428 	return (zprop_iter_common(func, cb, show_all, ordered, type));
1429 }
1430