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