]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / cddl / contrib / opensolaris / lib / libzfs / common / libzfs_util.c
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 #pragma ident   "%Z%%M% %I%     %E% SMI"
27
28 /*
29  * Internal utility routines for the ZFS library.
30  */
31
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <libintl.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <strings.h>
39 #include <unistd.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
48 int
49 libzfs_errno(libzfs_handle_t *hdl)
50 {
51         return (hdl->libzfs_error);
52 }
53
54 const char *
55 libzfs_error_action(libzfs_handle_t *hdl)
56 {
57         return (hdl->libzfs_action);
58 }
59
60 const char *
61 libzfs_error_description(libzfs_handle_t *hdl)
62 {
63         if (hdl->libzfs_desc[0] != '\0')
64                 return (hdl->libzfs_desc);
65
66         switch (hdl->libzfs_error) {
67         case EZFS_NOMEM:
68                 return (dgettext(TEXT_DOMAIN, "out of memory"));
69         case EZFS_BADPROP:
70                 return (dgettext(TEXT_DOMAIN, "invalid property value"));
71         case EZFS_PROPREADONLY:
72                 return (dgettext(TEXT_DOMAIN, "read only property"));
73         case EZFS_PROPTYPE:
74                 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
75                     "datasets of this type"));
76         case EZFS_PROPNONINHERIT:
77                 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
78         case EZFS_PROPSPACE:
79                 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
80         case EZFS_BADTYPE:
81                 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
82                     "datasets of this type"));
83         case EZFS_BUSY:
84                 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
85         case EZFS_EXISTS:
86                 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
87         case EZFS_NOENT:
88                 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
89         case EZFS_BADSTREAM:
90                 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
91         case EZFS_DSREADONLY:
92                 return (dgettext(TEXT_DOMAIN, "dataset is read only"));
93         case EZFS_VOLTOOBIG:
94                 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
95                     "this system"));
96         case EZFS_VOLHASDATA:
97                 return (dgettext(TEXT_DOMAIN, "volume has data"));
98         case EZFS_INVALIDNAME:
99                 return (dgettext(TEXT_DOMAIN, "invalid name"));
100         case EZFS_BADRESTORE:
101                 return (dgettext(TEXT_DOMAIN, "unable to restore to "
102                     "destination"));
103         case EZFS_BADBACKUP:
104                 return (dgettext(TEXT_DOMAIN, "backup failed"));
105         case EZFS_BADTARGET:
106                 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
107         case EZFS_NODEVICE:
108                 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
109         case EZFS_BADDEV:
110                 return (dgettext(TEXT_DOMAIN, "invalid device"));
111         case EZFS_NOREPLICAS:
112                 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
113         case EZFS_RESILVERING:
114                 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
115         case EZFS_BADVERSION:
116                 return (dgettext(TEXT_DOMAIN, "unsupported version"));
117         case EZFS_POOLUNAVAIL:
118                 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
119         case EZFS_DEVOVERFLOW:
120                 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
121         case EZFS_BADPATH:
122                 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
123         case EZFS_CROSSTARGET:
124                 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
125                     "pools"));
126         case EZFS_ZONED:
127                 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
128         case EZFS_MOUNTFAILED:
129                 return (dgettext(TEXT_DOMAIN, "mount failed"));
130         case EZFS_UMOUNTFAILED:
131                 return (dgettext(TEXT_DOMAIN, "umount failed"));
132         case EZFS_UNSHARENFSFAILED:
133                 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
134         case EZFS_SHARENFSFAILED:
135                 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
136         case EZFS_DEVLINKS:
137                 return (dgettext(TEXT_DOMAIN, "failed to create /dev links"));
138         case EZFS_PERM:
139                 return (dgettext(TEXT_DOMAIN, "permission denied"));
140         case EZFS_NOSPC:
141                 return (dgettext(TEXT_DOMAIN, "out of space"));
142         case EZFS_IO:
143                 return (dgettext(TEXT_DOMAIN, "I/O error"));
144         case EZFS_INTR:
145                 return (dgettext(TEXT_DOMAIN, "signal received"));
146         case EZFS_ISSPARE:
147                 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
148                     "spare"));
149         case EZFS_INVALCONFIG:
150                 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
151         case EZFS_RECURSIVE:
152                 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
153         case EZFS_NOHISTORY:
154                 return (dgettext(TEXT_DOMAIN, "no history available"));
155         case EZFS_UNSHAREISCSIFAILED:
156                 return (dgettext(TEXT_DOMAIN,
157                     "iscsitgtd failed request to unshare"));
158         case EZFS_SHAREISCSIFAILED:
159                 return (dgettext(TEXT_DOMAIN,
160                     "iscsitgtd failed request to share"));
161         case EZFS_POOLPROPS:
162                 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
163                     "pool properties"));
164         case EZFS_POOL_NOTSUP:
165                 return (dgettext(TEXT_DOMAIN, "operation not supported "
166                     "on this type of pool"));
167         case EZFS_POOL_INVALARG:
168                 return (dgettext(TEXT_DOMAIN, "invalid argument for "
169                     "this pool operation"));
170         case EZFS_NAMETOOLONG:
171                 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
172         case EZFS_UNKNOWN:
173                 return (dgettext(TEXT_DOMAIN, "unknown error"));
174         default:
175                 assert(hdl->libzfs_error == 0);
176                 return (dgettext(TEXT_DOMAIN, "no error"));
177         }
178 }
179
180 /*PRINTFLIKE2*/
181 void
182 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
183 {
184         va_list ap;
185
186         va_start(ap, fmt);
187
188         (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
189             fmt, ap);
190         hdl->libzfs_desc_active = 1;
191
192         va_end(ap);
193 }
194
195 static void
196 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
197 {
198         (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
199             fmt, ap);
200         hdl->libzfs_error = error;
201
202         if (hdl->libzfs_desc_active)
203                 hdl->libzfs_desc_active = 0;
204         else
205                 hdl->libzfs_desc[0] = '\0';
206
207         if (hdl->libzfs_printerr) {
208                 if (error == EZFS_UNKNOWN) {
209                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
210                             "error: %s\n"), libzfs_error_description(hdl));
211                         abort();
212                 }
213
214                 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
215                     libzfs_error_description(hdl));
216                 if (error == EZFS_NOMEM)
217                         exit(1);
218         }
219 }
220
221 int
222 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
223 {
224         return (zfs_error_fmt(hdl, error, "%s", msg));
225 }
226
227 /*PRINTFLIKE3*/
228 int
229 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
230 {
231         va_list ap;
232
233         va_start(ap, fmt);
234
235         zfs_verror(hdl, error, fmt, ap);
236
237         va_end(ap);
238
239         return (-1);
240 }
241
242 static int
243 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
244     va_list ap)
245 {
246         switch (error) {
247         case EPERM:
248         case EACCES:
249                 zfs_verror(hdl, EZFS_PERM, fmt, ap);
250                 return (-1);
251
252         case EIO:
253                 zfs_verror(hdl, EZFS_IO, fmt, ap);
254                 return (-1);
255
256         case EINTR:
257                 zfs_verror(hdl, EZFS_INTR, fmt, ap);
258                 return (-1);
259         }
260
261         return (0);
262 }
263
264 int
265 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
266 {
267         return (zfs_standard_error_fmt(hdl, error, "%s", msg));
268 }
269
270 /*PRINTFLIKE3*/
271 int
272 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
273 {
274         va_list ap;
275
276         va_start(ap, fmt);
277
278         if (zfs_common_error(hdl, error, fmt, ap) != 0) {
279                 va_end(ap);
280                 return (-1);
281         }
282
283
284         switch (error) {
285         case ENXIO:
286                 zfs_verror(hdl, EZFS_IO, fmt, ap);
287                 break;
288
289         case ENOENT:
290                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
291                     "dataset does not exist"));
292                 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
293                 break;
294
295         case ENOSPC:
296         case EDQUOT:
297                 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
298                 return (-1);
299
300         case EEXIST:
301                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
302                     "dataset already exists"));
303                 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
304                 break;
305
306         case EBUSY:
307                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
308                     "dataset is busy"));
309                 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
310                 break;
311
312         case ENAMETOOLONG:
313                 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
314                 break;
315
316         default:
317                 zfs_error_aux(hdl, strerror(errno));
318                 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
319                 break;
320         }
321
322         va_end(ap);
323         return (-1);
324 }
325
326 int
327 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
328 {
329         return (zpool_standard_error_fmt(hdl, error, "%s", msg));
330 }
331
332 /*PRINTFLIKE3*/
333 int
334 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
335 {
336         va_list ap;
337
338         va_start(ap, fmt);
339
340         if (zfs_common_error(hdl, error, fmt, ap) != 0) {
341                 va_end(ap);
342                 return (-1);
343         }
344
345         switch (error) {
346         case ENODEV:
347                 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
348                 break;
349
350         case ENOENT:
351                 zfs_error_aux(hdl,
352                     dgettext(TEXT_DOMAIN, "no such pool or dataset"));
353                 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
354                 break;
355
356         case EEXIST:
357                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
358                     "pool already exists"));
359                 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
360                 break;
361
362         case EBUSY:
363                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
364                 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
365                 break;
366
367         case ENXIO:
368                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
369                     "one or more devices is currently unavailable"));
370                 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
371                 break;
372
373         case ENAMETOOLONG:
374                 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
375                 break;
376
377         case ENOTSUP:
378                 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
379                 break;
380
381         case EINVAL:
382                 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
383                 break;
384
385         default:
386                 zfs_error_aux(hdl, strerror(error));
387                 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
388         }
389
390         va_end(ap);
391         return (-1);
392 }
393
394 /*
395  * Display an out of memory error message and abort the current program.
396  */
397 int
398 no_memory(libzfs_handle_t *hdl)
399 {
400         return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
401 }
402
403 /*
404  * A safe form of malloc() which will die if the allocation fails.
405  */
406 void *
407 zfs_alloc(libzfs_handle_t *hdl, size_t size)
408 {
409         void *data;
410
411         if ((data = calloc(1, size)) == NULL)
412                 (void) no_memory(hdl);
413
414         return (data);
415 }
416
417 /*
418  * A safe form of realloc(), which also zeroes newly allocated space.
419  */
420 void *
421 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
422 {
423         void *ret;
424
425         if ((ret = realloc(ptr, newsize)) == NULL) {
426                 (void) no_memory(hdl);
427                 free(ptr);
428                 return (NULL);
429         }
430
431         bzero((char *)ret + oldsize, (newsize - oldsize));
432         return (ret);
433 }
434
435 /*
436  * A safe form of strdup() which will die if the allocation fails.
437  */
438 char *
439 zfs_strdup(libzfs_handle_t *hdl, const char *str)
440 {
441         char *ret;
442
443         if ((ret = strdup(str)) == NULL)
444                 (void) no_memory(hdl);
445
446         return (ret);
447 }
448
449 /*
450  * Convert a number to an appropriately human-readable output.
451  */
452 void
453 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
454 {
455         uint64_t n = num;
456         int index = 0;
457         char u;
458
459         while (n >= 1024) {
460                 n /= 1024;
461                 index++;
462         }
463
464         u = " KMGTPE"[index];
465
466         if (index == 0) {
467                 (void) snprintf(buf, buflen, "%llu", n);
468         } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
469                 /*
470                  * If this is an even multiple of the base, always display
471                  * without any decimal precision.
472                  */
473                 (void) snprintf(buf, buflen, "%llu%c", n, u);
474         } else {
475                 /*
476                  * We want to choose a precision that reflects the best choice
477                  * for fitting in 5 characters.  This can get rather tricky when
478                  * we have numbers that are very close to an order of magnitude.
479                  * For example, when displaying 10239 (which is really 9.999K),
480                  * we want only a single place of precision for 10.0K.  We could
481                  * develop some complex heuristics for this, but it's much
482                  * easier just to try each combination in turn.
483                  */
484                 int i;
485                 for (i = 2; i >= 0; i--) {
486                         (void) snprintf(buf, buflen, "%.*f%c", i,
487                             (double)num / (1ULL << 10 * index), u);
488                         if (strlen(buf) <= 5)
489                                 break;
490                 }
491         }
492 }
493
494 void
495 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
496 {
497         hdl->libzfs_printerr = printerr;
498 }
499
500 static int
501 libzfs_load(void)
502 {
503         int error;
504
505         if (modfind("zfs") < 0) {
506                 /* Not present in kernel, try loading it. */
507                 if (kldload("zfs") < 0 || modfind("zfs") < 0) {
508                         if (errno != EEXIST)
509                                 return (error);
510                 }
511         }
512         return (0);
513 }
514
515 libzfs_handle_t *
516 libzfs_init(void)
517 {
518         libzfs_handle_t *hdl;
519
520         if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
521                 return (NULL);
522         }
523
524         if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
525                 if (libzfs_load() == 0)
526                         hdl->libzfs_fd = open(ZFS_DEV, O_RDWR);
527                 if (hdl->libzfs_fd < 0) {
528                         free(hdl);
529                         return (NULL);
530                 }
531         }
532
533         if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
534                 (void) close(hdl->libzfs_fd);
535                 free(hdl);
536                 return (NULL);
537         }
538
539         hdl->libzfs_sharetab = fopen(ZFS_EXPORTS_PATH, "r");
540
541         return (hdl);
542 }
543
544 void
545 libzfs_fini(libzfs_handle_t *hdl)
546 {
547         (void) close(hdl->libzfs_fd);
548         if (hdl->libzfs_mnttab)
549                 (void) fclose(hdl->libzfs_mnttab);
550         if (hdl->libzfs_sharetab)
551                 (void) fclose(hdl->libzfs_sharetab);
552         namespace_clear(hdl);
553         free(hdl);
554 }
555
556 libzfs_handle_t *
557 zpool_get_handle(zpool_handle_t *zhp)
558 {
559         return (zhp->zpool_hdl);
560 }
561
562 libzfs_handle_t *
563 zfs_get_handle(zfs_handle_t *zhp)
564 {
565         return (zhp->zfs_hdl);
566 }
567
568 /*
569  * Given a name, determine whether or not it's a valid path
570  * (starts with '/' or "./").  If so, walk the mnttab trying
571  * to match the device number.  If not, treat the path as an
572  * fs/vol/snap name.
573  */
574 zfs_handle_t *
575 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
576 {
577         struct statfs statbuf;
578
579         if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
580                 /*
581                  * It's not a valid path, assume it's a name of type 'argtype'.
582                  */
583                 return (zfs_open(hdl, path, argtype));
584         }
585
586         if (statfs(path, &statbuf) != 0) {
587                 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
588                 return (NULL);
589         }
590
591         if (strcmp(statbuf.f_fstypename, MNTTYPE_ZFS) != 0) {
592                 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
593                     path);
594                 return (NULL);
595         }
596
597         return (zfs_open(hdl, statbuf.f_mntfromname, ZFS_TYPE_FILESYSTEM));
598 }
599
600 /*
601  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
602  * an ioctl().
603  */
604 int
605 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
606 {
607         if (len == 0)
608                 len = 2048;
609         zc->zc_nvlist_dst_size = len;
610         if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
611             zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0)
612                 return (-1);
613
614         return (0);
615 }
616
617 /*
618  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
619  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
620  * filled in by the kernel to indicate the actual required size.
621  */
622 int
623 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
624 {
625         free((void *)(uintptr_t)zc->zc_nvlist_dst);
626         if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
627             zfs_alloc(hdl, zc->zc_nvlist_dst_size))
628             == 0)
629                 return (-1);
630
631         return (0);
632 }
633
634 /*
635  * Called to free the src and dst nvlists stored in the command structure.
636  */
637 void
638 zcmd_free_nvlists(zfs_cmd_t *zc)
639 {
640         free((void *)(uintptr_t)zc->zc_nvlist_src);
641         free((void *)(uintptr_t)zc->zc_nvlist_dst);
642 }
643
644 int
645 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
646     size_t *size)
647 {
648         char *packed;
649         size_t len;
650
651         verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
652
653         if ((packed = zfs_alloc(hdl, len)) == NULL)
654                 return (-1);
655
656         verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
657
658         zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
659         zc->zc_nvlist_src_size = len;
660
661         if (size)
662                 *size = len;
663         return (0);
664 }
665
666 /*
667  * Unpacks an nvlist from the ZFS ioctl command structure.
668  */
669 int
670 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
671 {
672         if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
673             zc->zc_nvlist_dst_size, nvlp, 0) != 0)
674                 return (no_memory(hdl));
675
676         return (0);
677 }
678
679 static void
680 zfs_print_prop_headers(libzfs_get_cbdata_t *cbp)
681 {
682         zfs_proplist_t *pl = cbp->cb_proplist;
683         int i;
684         char *title;
685         size_t len;
686
687         cbp->cb_first = B_FALSE;
688         if (cbp->cb_scripted)
689                 return;
690
691         /*
692          * Start with the length of the column headers.
693          */
694         cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
695         cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
696             "PROPERTY"));
697         cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
698             "VALUE"));
699         cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
700             "SOURCE"));
701
702         /*
703          * Go through and calculate the widths for each column.  For the
704          * 'source' column, we kludge it up by taking the worst-case scenario of
705          * inheriting from the longest name.  This is acceptable because in the
706          * majority of cases 'SOURCE' is the last column displayed, and we don't
707          * use the width anyway.  Note that the 'VALUE' column can be oversized,
708          * if the name of the property is much longer the any values we find.
709          */
710         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
711                 /*
712                  * 'PROPERTY' column
713                  */
714                 if (pl->pl_prop != ZFS_PROP_INVAL) {
715                         len = strlen(zfs_prop_to_name(pl->pl_prop));
716                         if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
717                                 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
718                 } else {
719                         len = strlen(pl->pl_user_prop);
720                         if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
721                                 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
722                 }
723
724                 /*
725                  * 'VALUE' column
726                  */
727                 if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) &&
728                     pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
729                         cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
730
731                 /*
732                  * 'NAME' and 'SOURCE' columns
733                  */
734                 if (pl->pl_prop == ZFS_PROP_NAME &&
735                     pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
736                         cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
737                         cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
738                             strlen(dgettext(TEXT_DOMAIN, "inherited from"));
739                 }
740         }
741
742         /*
743          * Now go through and print the headers.
744          */
745         for (i = 0; i < 4; i++) {
746                 switch (cbp->cb_columns[i]) {
747                 case GET_COL_NAME:
748                         title = dgettext(TEXT_DOMAIN, "NAME");
749                         break;
750                 case GET_COL_PROPERTY:
751                         title = dgettext(TEXT_DOMAIN, "PROPERTY");
752                         break;
753                 case GET_COL_VALUE:
754                         title = dgettext(TEXT_DOMAIN, "VALUE");
755                         break;
756                 case GET_COL_SOURCE:
757                         title = dgettext(TEXT_DOMAIN, "SOURCE");
758                         break;
759                 default:
760                         title = NULL;
761                 }
762
763                 if (title != NULL) {
764                         if (i == 3 || cbp->cb_columns[i + 1] == 0)
765                                 (void) printf("%s", title);
766                         else
767                                 (void) printf("%-*s  ",
768                                     cbp->cb_colwidths[cbp->cb_columns[i]],
769                                     title);
770                 }
771         }
772         (void) printf("\n");
773 }
774
775 /*
776  * Display a single line of output, according to the settings in the callback
777  * structure.
778  */
779 void
780 libzfs_print_one_property(const char *name, libzfs_get_cbdata_t *cbp,
781     const char *propname, const char *value, zfs_source_t sourcetype,
782     const char *source)
783 {
784         int i;
785         const char *str;
786         char buf[128];
787
788         /*
789          * Ignore those source types that the user has chosen to ignore.
790          */
791         if ((sourcetype & cbp->cb_sources) == 0)
792                 return;
793
794         if (cbp->cb_first)
795                 zfs_print_prop_headers(cbp);
796
797         for (i = 0; i < 4; i++) {
798                 switch (cbp->cb_columns[i]) {
799                 case GET_COL_NAME:
800                         str = name;
801                         break;
802
803                 case GET_COL_PROPERTY:
804                         str = propname;
805                         break;
806
807                 case GET_COL_VALUE:
808                         str = value;
809                         break;
810
811                 case GET_COL_SOURCE:
812                         switch (sourcetype) {
813                         case ZFS_SRC_NONE:
814                                 str = "-";
815                                 break;
816
817                         case ZFS_SRC_DEFAULT:
818                                 str = "default";
819                                 break;
820
821                         case ZFS_SRC_LOCAL:
822                                 str = "local";
823                                 break;
824
825                         case ZFS_SRC_TEMPORARY:
826                                 str = "temporary";
827                                 break;
828
829                         case ZFS_SRC_INHERITED:
830                                 (void) snprintf(buf, sizeof (buf),
831                                     "inherited from %s", source);
832                                 str = buf;
833                                 break;
834                         }
835                         break;
836
837                 default:
838                         continue;
839                 }
840
841                 if (cbp->cb_columns[i + 1] == 0)
842                         (void) printf("%s", str);
843                 else if (cbp->cb_scripted)
844                         (void) printf("%s\t", str);
845                 else
846                         (void) printf("%-*s  ",
847                             cbp->cb_colwidths[cbp->cb_columns[i]],
848                             str);
849
850         }
851
852         (void) printf("\n");
853 }