]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / cddl / contrib / opensolaris / cmd / zfs / zfs_main.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 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26
27 #pragma ident   "%Z%%M% %I%     %E% SMI"
28
29 #include <assert.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <libgen.h>
33 #include <libintl.h>
34 #include <libuutil.h>
35 #include <locale.h>
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <zone.h>
43 #include <sys/mntent.h>
44 #include <sys/mnttab.h>
45 #include <sys/mount.h>
46 #include <sys/stat.h>
47
48 #include <libzfs.h>
49
50 #include "zfs_iter.h"
51 #include "zfs_util.h"
52
53 libzfs_handle_t *g_zfs;
54
55 static FILE *mnttab_file;
56
57 static int zfs_do_clone(int argc, char **argv);
58 static int zfs_do_create(int argc, char **argv);
59 static int zfs_do_destroy(int argc, char **argv);
60 static int zfs_do_get(int argc, char **argv);
61 static int zfs_do_inherit(int argc, char **argv);
62 static int zfs_do_list(int argc, char **argv);
63 static int zfs_do_mount(int argc, char **argv);
64 static int zfs_do_rename(int argc, char **argv);
65 static int zfs_do_rollback(int argc, char **argv);
66 static int zfs_do_set(int argc, char **argv);
67 static int zfs_do_snapshot(int argc, char **argv);
68 static int zfs_do_unmount(int argc, char **argv);
69 static int zfs_do_share(int argc, char **argv);
70 static int zfs_do_unshare(int argc, char **argv);
71 static int zfs_do_send(int argc, char **argv);
72 static int zfs_do_receive(int argc, char **argv);
73 static int zfs_do_promote(int argc, char **argv);
74 static int zfs_do_jail(int argc, char **argv);
75 static int zfs_do_unjail(int argc, char **argv);
76
77 /*
78  * These libumem hooks provide a reasonable set of defaults for the allocator's
79  * debugging facilities.
80  */
81 const char *
82 _umem_debug_init(void)
83 {
84         return ("default,verbose"); /* $UMEM_DEBUG setting */
85 }
86
87 const char *
88 _umem_logging_init(void)
89 {
90         return ("fail,contents"); /* $UMEM_LOGGING setting */
91 }
92
93 typedef enum {
94         HELP_CLONE,
95         HELP_CREATE,
96         HELP_DESTROY,
97         HELP_GET,
98         HELP_INHERIT,
99         HELP_JAIL,
100         HELP_UNJAIL,
101         HELP_LIST,
102         HELP_MOUNT,
103         HELP_PROMOTE,
104         HELP_RECEIVE,
105         HELP_RENAME,
106         HELP_ROLLBACK,
107         HELP_SEND,
108         HELP_SET,
109         HELP_SHARE,
110         HELP_SNAPSHOT,
111         HELP_UNMOUNT,
112         HELP_UNSHARE
113 } zfs_help_t;
114
115 typedef struct zfs_command {
116         const char      *name;
117         int             (*func)(int argc, char **argv);
118         zfs_help_t      usage;
119 } zfs_command_t;
120
121 /*
122  * Master command table.  Each ZFS command has a name, associated function, and
123  * usage message.  The usage messages need to be internationalized, so we have
124  * to have a function to return the usage message based on a command index.
125  *
126  * These commands are organized according to how they are displayed in the usage
127  * message.  An empty command (one with a NULL name) indicates an empty line in
128  * the generic usage message.
129  */
130 static zfs_command_t command_table[] = {
131         { "create",     zfs_do_create,          HELP_CREATE             },
132         { "destroy",    zfs_do_destroy,         HELP_DESTROY            },
133         { NULL },
134         { "snapshot",   zfs_do_snapshot,        HELP_SNAPSHOT           },
135         { "rollback",   zfs_do_rollback,        HELP_ROLLBACK           },
136         { "clone",      zfs_do_clone,           HELP_CLONE              },
137         { "promote",    zfs_do_promote,         HELP_PROMOTE            },
138         { "rename",     zfs_do_rename,          HELP_RENAME             },
139         { NULL },
140         { "list",       zfs_do_list,            HELP_LIST               },
141         { NULL },
142         { "set",        zfs_do_set,             HELP_SET                },
143         { "get",        zfs_do_get,             HELP_GET                },
144         { "inherit",    zfs_do_inherit,         HELP_INHERIT            },
145         { NULL },
146         { "mount",      zfs_do_mount,           HELP_MOUNT              },
147         { NULL },
148         { "unmount",    zfs_do_unmount,         HELP_UNMOUNT            },
149         { NULL },
150         { "share",      zfs_do_share,           HELP_SHARE              },
151         { NULL },
152         { "unshare",    zfs_do_unshare,         HELP_UNSHARE            },
153         { NULL },
154         { "send",       zfs_do_send,            HELP_SEND               },
155         { "receive",    zfs_do_receive,         HELP_RECEIVE            },
156         { NULL },
157         { "jail",       zfs_do_jail,            HELP_JAIL               },
158         { "unjail",     zfs_do_unjail,          HELP_UNJAIL             },
159 };
160
161 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
162
163 zfs_command_t *current_command;
164
165 static const char *
166 get_usage(zfs_help_t idx)
167 {
168         switch (idx) {
169         case HELP_CLONE:
170                 return (gettext("\tclone <snapshot> <filesystem|volume>\n"));
171         case HELP_CREATE:
172                 return (gettext("\tcreate [[-o property=value] ... ] "
173                     "<filesystem>\n"
174                     "\tcreate [-s] [-b blocksize] [[-o property=value] ...]\n"
175                     "\t    -V <size> <volume>\n"));
176         case HELP_DESTROY:
177                 return (gettext("\tdestroy [-rRf] "
178                     "<filesystem|volume|snapshot>\n"));
179         case HELP_GET:
180                 return (gettext("\tget [-rHp] [-o field[,field]...] "
181                     "[-s source[,source]...]\n"
182                     "\t    <all | property[,property]...> "
183                     "[filesystem|volume|snapshot] ...\n"));
184         case HELP_INHERIT:
185                 return (gettext("\tinherit [-r] <property> "
186                     "<filesystem|volume> ...\n"));
187         case HELP_JAIL:
188                 return (gettext("\tjail <jailid> <filesystem>\n"));
189         case HELP_UNJAIL:
190                 return (gettext("\tunjail <jailid> <filesystem>\n"));
191         case HELP_LIST:
192                 return (gettext("\tlist [-rH] [-o property[,property]...] "
193                     "[-t type[,type]...]\n"
194                     "\t    [-s property [-s property]...]"
195                     " [-S property [-S property]...]\n"
196                     "\t    [filesystem|volume|snapshot] ...\n"));
197         case HELP_MOUNT:
198                 return (gettext("\tmount\n"
199                     "\tmount [-o opts] [-O] -a\n"
200                     "\tmount [-o opts] [-O] <filesystem>\n"));
201         case HELP_PROMOTE:
202                 return (gettext("\tpromote <clone filesystem>\n"));
203         case HELP_RECEIVE:
204                 return (gettext("\treceive [-vnF] <filesystem|volume|"
205                 "snapshot>\n"
206                 "\treceive [-vnF] -d <filesystem>\n"));
207         case HELP_RENAME:
208                 return (gettext("\trename <filesystem|volume|snapshot> "
209                     "<filesystem|volume|snapshot>\n"
210                     "\trename -r <snapshot> <snapshot>"));
211         case HELP_ROLLBACK:
212                 return (gettext("\trollback [-rRf] <snapshot>\n"));
213         case HELP_SEND:
214                 return (gettext("\tsend [-i <snapshot>] <snapshot>\n"));
215         case HELP_SET:
216                 return (gettext("\tset <property=value> "
217                     "<filesystem|volume> ...\n"));
218         case HELP_SHARE:
219                 return (gettext("\tshare -a\n"
220                     "\tshare <filesystem>\n"));
221         case HELP_SNAPSHOT:
222                 return (gettext("\tsnapshot [-r] "
223                     "<filesystem@name|volume@name>\n"));
224         case HELP_UNMOUNT:
225                 return (gettext("\tunmount [-f] -a\n"
226                     "\tunmount [-f] <filesystem|mountpoint>\n"));
227         case HELP_UNSHARE:
228                 return (gettext("\tunshare [-f] -a\n"
229                     "\tunshare [-f] <filesystem|mountpoint>\n"));
230         }
231
232         abort();
233         /* NOTREACHED */
234 }
235
236 /*
237  * Utility function to guarantee malloc() success.
238  */
239 void *
240 safe_malloc(size_t size)
241 {
242         void *data;
243
244         if ((data = calloc(1, size)) == NULL) {
245                 (void) fprintf(stderr, "internal error: out of memory\n");
246                 exit(1);
247         }
248
249         return (data);
250 }
251
252 /*
253  * Callback routinue that will print out information for each of the
254  * the properties.
255  */
256 static zfs_prop_t
257 usage_prop_cb(zfs_prop_t prop, void *cb)
258 {
259         FILE *fp = cb;
260
261         (void) fprintf(fp, "\t%-13s  ", zfs_prop_to_name(prop));
262
263         if (zfs_prop_readonly(prop))
264                 (void) fprintf(fp, "  NO    ");
265         else
266                 (void) fprintf(fp, " YES    ");
267
268         if (zfs_prop_inheritable(prop))
269                 (void) fprintf(fp, "  YES   ");
270         else
271                 (void) fprintf(fp, "   NO   ");
272
273         if (zfs_prop_values(prop) == NULL)
274                 (void) fprintf(fp, "-\n");
275         else
276                 (void) fprintf(fp, "%s\n", zfs_prop_values(prop));
277
278         return (ZFS_PROP_CONT);
279 }
280
281 /*
282  * Display usage message.  If we're inside a command, display only the usage for
283  * that command.  Otherwise, iterate over the entire command table and display
284  * a complete usage message.
285  */
286 static void
287 usage(boolean_t requested)
288 {
289         int i;
290         boolean_t show_properties = B_FALSE;
291         FILE *fp = requested ? stdout : stderr;
292
293         if (current_command == NULL) {
294
295                 (void) fprintf(fp, gettext("usage: zfs command args ...\n"));
296                 (void) fprintf(fp,
297                     gettext("where 'command' is one of the following:\n\n"));
298
299                 for (i = 0; i < NCOMMAND; i++) {
300                         if (command_table[i].name == NULL)
301                                 (void) fprintf(fp, "\n");
302                         else
303                                 (void) fprintf(fp, "%s",
304                                     get_usage(command_table[i].usage));
305                 }
306
307                 (void) fprintf(fp, gettext("\nEach dataset is of the form: "
308                     "pool/[dataset/]*dataset[@name]\n"));
309         } else {
310                 (void) fprintf(fp, gettext("usage:\n"));
311                 (void) fprintf(fp, "%s", get_usage(current_command->usage));
312         }
313
314         if (current_command != NULL &&
315             (strcmp(current_command->name, "set") == 0 ||
316             strcmp(current_command->name, "get") == 0 ||
317             strcmp(current_command->name, "inherit") == 0 ||
318             strcmp(current_command->name, "list") == 0))
319                 show_properties = B_TRUE;
320
321         if (show_properties) {
322
323                 (void) fprintf(fp,
324                     gettext("\nThe following properties are supported:\n"));
325
326                 (void) fprintf(fp, "\n\t%-13s  %s  %s   %s\n\n",
327                     "PROPERTY", "EDIT", "INHERIT", "VALUES");
328
329                 /* Iterate over all properties */
330                 (void) zfs_prop_iter(usage_prop_cb, fp, B_FALSE);
331
332                 (void) fprintf(fp, gettext("\nSizes are specified in bytes "
333                     "with standard units such as K, M, G, etc.\n"));
334                 (void) fprintf(fp, gettext("\n\nUser-defined properties can "
335                     "be specified by using a name containing a colon (:).\n"));
336         } else {
337                 /*
338                  * TRANSLATION NOTE:
339                  * "zfs set|get" must not be localised this is the
340                  * command name and arguments.
341                  */
342                 (void) fprintf(fp,
343                     gettext("\nFor the property list, run: zfs set|get\n"));
344         }
345
346         /*
347          * See comments at end of main().
348          */
349         if (getenv("ZFS_ABORT") != NULL) {
350                 (void) printf("dumping core by request\n");
351                 abort();
352         }
353
354         exit(requested ? 0 : 2);
355 }
356
357 /*
358  * zfs clone <fs, snap, vol> fs
359  *
360  * Given an existing dataset, create a writable copy whose initial contents
361  * are the same as the source.  The newly created dataset maintains a
362  * dependency on the original; the original cannot be destroyed so long as
363  * the clone exists.
364  */
365 static int
366 zfs_do_clone(int argc, char **argv)
367 {
368         zfs_handle_t *zhp;
369         int ret;
370
371         /* check options */
372         if (argc > 1 && argv[1][0] == '-') {
373                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
374                     argv[1][1]);
375                 usage(B_FALSE);
376         }
377
378         /* check number of arguments */
379         if (argc < 2) {
380                 (void) fprintf(stderr, gettext("missing source dataset "
381                     "argument\n"));
382                 usage(B_FALSE);
383         }
384         if (argc < 3) {
385                 (void) fprintf(stderr, gettext("missing target dataset "
386                     "argument\n"));
387                 usage(B_FALSE);
388         }
389         if (argc > 3) {
390                 (void) fprintf(stderr, gettext("too many arguments\n"));
391                 usage(B_FALSE);
392         }
393
394         /* open the source dataset */
395         if ((zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_SNAPSHOT)) == NULL)
396                 return (1);
397
398         /* pass to libzfs */
399         ret = zfs_clone(zhp, argv[2], NULL);
400
401         /* create the mountpoint if necessary */
402         if (ret == 0) {
403                 zfs_handle_t *clone = zfs_open(g_zfs, argv[2], ZFS_TYPE_ANY);
404                 if (clone != NULL) {
405                         if ((ret = zfs_mount(clone, NULL, 0)) == 0)
406                                 ret = zfs_share(clone);
407                         zfs_close(clone);
408                 }
409                 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
410         }
411
412         zfs_close(zhp);
413
414         return (ret == 0 ? 0 : 1);
415 }
416
417 /*
418  * zfs create [-o prop=value] ... fs
419  * zfs create [-s] [-b blocksize] [-o prop=value] ... -V vol size
420  *
421  * Create a new dataset.  This command can be used to create filesystems
422  * and volumes.  Snapshot creation is handled by 'zfs snapshot'.
423  * For volumes, the user must specify a size to be used.
424  *
425  * The '-s' flag applies only to volumes, and indicates that we should not try
426  * to set the reservation for this volume.  By default we set a reservation
427  * equal to the size for any volume.
428  */
429 static int
430 zfs_do_create(int argc, char **argv)
431 {
432         zfs_type_t type = ZFS_TYPE_FILESYSTEM;
433         zfs_handle_t *zhp = NULL;
434         uint64_t volsize;
435         int c;
436         boolean_t noreserve = B_FALSE;
437         int ret = 1;
438         nvlist_t *props = NULL;
439         uint64_t intval;
440         char *propname;
441         char *propval = NULL;
442         char *strval;
443
444         if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
445                 (void) fprintf(stderr, gettext("internal error: "
446                     "out of memory\n"));
447                 return (1);
448         }
449
450         /* check options */
451         while ((c = getopt(argc, argv, ":V:b:so:")) != -1) {
452                 switch (c) {
453                 case 'V':
454                         type = ZFS_TYPE_VOLUME;
455                         if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) {
456                                 (void) fprintf(stderr, gettext("bad volume "
457                                     "size '%s': %s\n"), optarg,
458                                     libzfs_error_description(g_zfs));
459                                 goto error;
460                         }
461
462                         if (nvlist_add_uint64(props,
463                             zfs_prop_to_name(ZFS_PROP_VOLSIZE),
464                             intval) != 0) {
465                                 (void) fprintf(stderr, gettext("internal "
466                                     "error: out of memory\n"));
467                                 goto error;
468                         }
469                         volsize = intval;
470                         break;
471                 case 'b':
472                         if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) {
473                                 (void) fprintf(stderr, gettext("bad volume "
474                                     "block size '%s': %s\n"), optarg,
475                                     libzfs_error_description(g_zfs));
476                                 goto error;
477                         }
478
479                         if (nvlist_add_uint64(props,
480                             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
481                             intval) != 0) {
482                                 (void) fprintf(stderr, gettext("internal "
483                                     "error: out of memory\n"));
484                                 goto error;
485                         }
486                         break;
487                 case 'o':
488                         propname = optarg;
489                         if ((propval = strchr(propname, '=')) == NULL) {
490                                 (void) fprintf(stderr, gettext("missing "
491                                     "'=' for -o option\n"));
492                                 goto error;
493                         }
494                         *propval = '\0';
495                         propval++;
496                         if (nvlist_lookup_string(props, propname,
497                             &strval) == 0) {
498                                 (void) fprintf(stderr, gettext("property '%s' "
499                                     "specified multiple times\n"), propname);
500                                 goto error;
501                         }
502                         if (nvlist_add_string(props, propname, propval) != 0) {
503                                 (void) fprintf(stderr, gettext("internal "
504                                     "error: out of memory\n"));
505                                 goto error;
506                         }
507                         break;
508                 case 's':
509                         noreserve = B_TRUE;
510                         break;
511                 case ':':
512                         (void) fprintf(stderr, gettext("missing size "
513                             "argument\n"));
514                         goto badusage;
515                         break;
516                 case '?':
517                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
518                             optopt);
519                         goto badusage;
520                 }
521         }
522
523         if (noreserve && type != ZFS_TYPE_VOLUME) {
524                 (void) fprintf(stderr, gettext("'-s' can only be used when "
525                     "creating a volume\n"));
526                 goto badusage;
527         }
528
529         argc -= optind;
530         argv += optind;
531
532         /* check number of arguments */
533         if (argc == 0) {
534                 (void) fprintf(stderr, gettext("missing %s argument\n"),
535                     zfs_type_to_name(type));
536                 goto badusage;
537         }
538         if (argc > 1) {
539                 (void) fprintf(stderr, gettext("too many arguments\n"));
540                 goto badusage;
541         }
542
543         if (type == ZFS_TYPE_VOLUME && !noreserve &&
544             nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_RESERVATION),
545             &strval) != 0) {
546                 if (nvlist_add_uint64(props,
547                     zfs_prop_to_name(ZFS_PROP_RESERVATION),
548                     volsize) != 0) {
549                         (void) fprintf(stderr, gettext("internal "
550                             "error: out of memory\n"));
551                         nvlist_free(props);
552                         return (1);
553                 }
554         }
555
556         /* pass to libzfs */
557         if (zfs_create(g_zfs, argv[0], type, props) != 0)
558                 goto error;
559
560         if (propval != NULL)
561                 *(propval - 1) = '=';
562         zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
563             B_FALSE, B_FALSE);
564
565         if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
566                 goto error;
567
568         /*
569          * Mount and/or share the new filesystem as appropriate.  We provide a
570          * verbose error message to let the user know that their filesystem was
571          * in fact created, even if we failed to mount or share it.
572          */
573         if (zfs_mount(zhp, NULL, 0) != 0) {
574                 (void) fprintf(stderr, gettext("filesystem successfully "
575                     "created, but not mounted\n"));
576                 ret = 1;
577         } else if (zfs_share(zhp) != 0) {
578                 (void) fprintf(stderr, gettext("filesystem successfully "
579                     "created, but not shared\n"));
580                 ret = 1;
581         } else {
582                 ret = 0;
583         }
584
585 error:
586         if (zhp)
587                 zfs_close(zhp);
588         nvlist_free(props);
589         return (ret);
590 badusage:
591         nvlist_free(props);
592         usage(B_FALSE);
593         return (2);
594 }
595
596 /*
597  * zfs destroy [-rf] <fs, snap, vol>
598  *
599  *      -r      Recursively destroy all children
600  *      -R      Recursively destroy all dependents, including clones
601  *      -f      Force unmounting of any dependents
602  *
603  * Destroys the given dataset.  By default, it will unmount any filesystems,
604  * and refuse to destroy a dataset that has any dependents.  A dependent can
605  * either be a child, or a clone of a child.
606  */
607 typedef struct destroy_cbdata {
608         boolean_t       cb_first;
609         int             cb_force;
610         int             cb_recurse;
611         int             cb_error;
612         int             cb_needforce;
613         int             cb_doclones;
614         boolean_t       cb_closezhp;
615         zfs_handle_t    *cb_target;
616         char            *cb_snapname;
617 } destroy_cbdata_t;
618
619 /*
620  * Check for any dependents based on the '-r' or '-R' flags.
621  */
622 static int
623 destroy_check_dependent(zfs_handle_t *zhp, void *data)
624 {
625         destroy_cbdata_t *cbp = data;
626         const char *tname = zfs_get_name(cbp->cb_target);
627         const char *name = zfs_get_name(zhp);
628
629         if (strncmp(tname, name, strlen(tname)) == 0 &&
630             (name[strlen(tname)] == '/' || name[strlen(tname)] == '@')) {
631                 /*
632                  * This is a direct descendant, not a clone somewhere else in
633                  * the hierarchy.
634                  */
635                 if (cbp->cb_recurse)
636                         goto out;
637
638                 if (cbp->cb_first) {
639                         (void) fprintf(stderr, gettext("cannot destroy '%s': "
640                             "%s has children\n"),
641                             zfs_get_name(cbp->cb_target),
642                             zfs_type_to_name(zfs_get_type(cbp->cb_target)));
643                         (void) fprintf(stderr, gettext("use '-r' to destroy "
644                             "the following datasets:\n"));
645                         cbp->cb_first = B_FALSE;
646                         cbp->cb_error = 1;
647                 }
648
649                 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
650         } else {
651                 /*
652                  * This is a clone.  We only want to report this if the '-r'
653                  * wasn't specified, or the target is a snapshot.
654                  */
655                 if (!cbp->cb_recurse &&
656                     zfs_get_type(cbp->cb_target) != ZFS_TYPE_SNAPSHOT)
657                         goto out;
658
659                 if (cbp->cb_first) {
660                         (void) fprintf(stderr, gettext("cannot destroy '%s': "
661                             "%s has dependent clones\n"),
662                             zfs_get_name(cbp->cb_target),
663                             zfs_type_to_name(zfs_get_type(cbp->cb_target)));
664                         (void) fprintf(stderr, gettext("use '-R' to destroy "
665                             "the following datasets:\n"));
666                         cbp->cb_first = B_FALSE;
667                         cbp->cb_error = 1;
668                 }
669
670                 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
671         }
672
673 out:
674         zfs_close(zhp);
675         return (0);
676 }
677
678 static int
679 destroy_callback(zfs_handle_t *zhp, void *data)
680 {
681         destroy_cbdata_t *cbp = data;
682
683         /*
684          * Ignore pools (which we've already flagged as an error before getting
685          * here.
686          */
687         if (strchr(zfs_get_name(zhp), '/') == NULL &&
688             zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
689                 zfs_close(zhp);
690                 return (0);
691         }
692
693         /*
694          * Bail out on the first error.
695          */
696         if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 ||
697             zfs_destroy(zhp) != 0) {
698                 zfs_close(zhp);
699                 return (-1);
700         }
701
702         zfs_close(zhp);
703         return (0);
704 }
705
706 static int
707 destroy_snap_clones(zfs_handle_t *zhp, void *arg)
708 {
709         destroy_cbdata_t *cbp = arg;
710         char thissnap[MAXPATHLEN];
711         zfs_handle_t *szhp;
712         boolean_t closezhp = cbp->cb_closezhp;
713         int rv;
714
715         (void) snprintf(thissnap, sizeof (thissnap),
716             "%s@%s", zfs_get_name(zhp), cbp->cb_snapname);
717
718         libzfs_print_on_error(g_zfs, B_FALSE);
719         szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT);
720         libzfs_print_on_error(g_zfs, B_TRUE);
721         if (szhp) {
722                 /*
723                  * Destroy any clones of this snapshot
724                  */
725                 if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback,
726                     cbp) != 0) {
727                         zfs_close(szhp);
728                         if (closezhp)
729                                 zfs_close(zhp);
730                         return (-1);
731                 }
732                 zfs_close(szhp);
733         }
734
735         cbp->cb_closezhp = B_TRUE;
736         rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg);
737         if (closezhp)
738                 zfs_close(zhp);
739         return (rv);
740 }
741
742 static int
743 zfs_do_destroy(int argc, char **argv)
744 {
745         destroy_cbdata_t cb = { 0 };
746         int c;
747         zfs_handle_t *zhp;
748         char *cp;
749
750         /* check options */
751         while ((c = getopt(argc, argv, "frR")) != -1) {
752                 switch (c) {
753                 case 'f':
754                         cb.cb_force = 1;
755                         break;
756                 case 'r':
757                         cb.cb_recurse = 1;
758                         break;
759                 case 'R':
760                         cb.cb_recurse = 1;
761                         cb.cb_doclones = 1;
762                         break;
763                 case '?':
764                 default:
765                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
766                             optopt);
767                         usage(B_FALSE);
768                 }
769         }
770
771         argc -= optind;
772         argv += optind;
773
774         /* check number of arguments */
775         if (argc == 0) {
776                 (void) fprintf(stderr, gettext("missing path argument\n"));
777                 usage(B_FALSE);
778         }
779         if (argc > 1) {
780                 (void) fprintf(stderr, gettext("too many arguments\n"));
781                 usage(B_FALSE);
782         }
783
784         /*
785          * If we are doing recursive destroy of a snapshot, then the
786          * named snapshot may not exist.  Go straight to libzfs.
787          */
788         if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) {
789                 int ret;
790
791                 *cp = '\0';
792                 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
793                         return (1);
794                 *cp = '@';
795                 cp++;
796
797                 if (cb.cb_doclones) {
798                         cb.cb_snapname = cp;
799                         if (destroy_snap_clones(zhp, &cb) != 0) {
800                                 zfs_close(zhp);
801                                 return (1);
802                         }
803                 }
804
805                 ret = zfs_destroy_snaps(zhp, cp);
806                 zfs_close(zhp);
807                 if (ret) {
808                         (void) fprintf(stderr,
809                             gettext("no snapshots destroyed\n"));
810                 } else {
811                         zpool_log_history(g_zfs, argc + optind, argv - optind,
812                             argv[0], B_FALSE, B_FALSE);
813                 }
814                 return (ret != 0);
815         }
816
817
818         /* Open the given dataset */
819         if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
820                 return (1);
821
822         cb.cb_target = zhp;
823
824         /*
825          * Perform an explicit check for pools before going any further.
826          */
827         if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
828             zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
829                 (void) fprintf(stderr, gettext("cannot destroy '%s': "
830                     "operation does not apply to pools\n"),
831                     zfs_get_name(zhp));
832                 (void) fprintf(stderr, gettext("use 'zfs destroy -r "
833                     "%s' to destroy all datasets in the pool\n"),
834                     zfs_get_name(zhp));
835                 (void) fprintf(stderr, gettext("use 'zpool destroy %s' "
836                     "to destroy the pool itself\n"), zfs_get_name(zhp));
837                 zfs_close(zhp);
838                 return (1);
839         }
840
841         /*
842          * Check for any dependents and/or clones.
843          */
844         cb.cb_first = B_TRUE;
845         if (!cb.cb_doclones &&
846             zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
847             &cb) != 0) {
848                 zfs_close(zhp);
849                 return (1);
850         }
851
852
853         if (cb.cb_error ||
854             zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) {
855                 zfs_close(zhp);
856                 return (1);
857         }
858
859         /*
860          * Do the real thing.  The callback will close the handle regardless of
861          * whether it succeeds or not.
862          */
863         if (destroy_callback(zhp, &cb) != 0)
864                 return (1);
865
866         zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
867             B_FALSE, B_FALSE);
868
869         return (0);
870 }
871
872 /*
873  * zfs get [-rHp] [-o field[,field]...] [-s source[,source]...]
874  *      < all | property[,property]... > < fs | snap | vol > ...
875  *
876  *      -r      recurse over any child datasets
877  *      -H      scripted mode.  Headers are stripped, and fields are separated
878  *              by tabs instead of spaces.
879  *      -o      Set of fields to display.  One of "name,property,value,source".
880  *              Default is all four.
881  *      -s      Set of sources to allow.  One of
882  *              "local,default,inherited,temporary,none".  Default is all
883  *              five.
884  *      -p      Display values in parsable (literal) format.
885  *
886  *  Prints properties for the given datasets.  The user can control which
887  *  columns to display as well as which property types to allow.
888  */
889
890 /*
891  * Invoked to display the properties for a single dataset.
892  */
893 static int
894 get_callback(zfs_handle_t *zhp, void *data)
895 {
896         char buf[ZFS_MAXPROPLEN];
897         zfs_source_t sourcetype;
898         char source[ZFS_MAXNAMELEN];
899         libzfs_get_cbdata_t *cbp = data;
900         nvlist_t *userprop = zfs_get_user_props(zhp);
901         zfs_proplist_t *pl = cbp->cb_proplist;
902         nvlist_t *propval;
903         char *strval;
904         char *sourceval;
905
906         for (; pl != NULL; pl = pl->pl_next) {
907                 /*
908                  * Skip the special fake placeholder.  This will also skip over
909                  * the name property when 'all' is specified.
910                  */
911                 if (pl->pl_prop == ZFS_PROP_NAME &&
912                     pl == cbp->cb_proplist)
913                         continue;
914
915                 if (pl->pl_prop != ZFS_PROP_INVAL) {
916                         if (zfs_prop_get(zhp, pl->pl_prop, buf,
917                             sizeof (buf), &sourcetype, source,
918                             sizeof (source),
919                             cbp->cb_literal) != 0) {
920                                 if (pl->pl_all)
921                                         continue;
922                                 if (!zfs_prop_valid_for_type(pl->pl_prop,
923                                     ZFS_TYPE_ANY)) {
924                                         (void) fprintf(stderr,
925                                             gettext("No such property '%s'\n"),
926                                             zfs_prop_to_name(pl->pl_prop));
927                                         continue;
928                                 }
929                                 sourcetype = ZFS_SRC_NONE;
930                                 (void) strlcpy(buf, "-", sizeof (buf));
931                         }
932
933                         libzfs_print_one_property(zfs_get_name(zhp), cbp,
934                             zfs_prop_to_name(pl->pl_prop),
935                             buf, sourcetype, source);
936                 } else {
937                         if (nvlist_lookup_nvlist(userprop,
938                             pl->pl_user_prop, &propval) != 0) {
939                                 if (pl->pl_all)
940                                         continue;
941                                 sourcetype = ZFS_SRC_NONE;
942                                 strval = "-";
943                         } else {
944                                 verify(nvlist_lookup_string(propval,
945                                     ZFS_PROP_VALUE, &strval) == 0);
946                                 verify(nvlist_lookup_string(propval,
947                                     ZFS_PROP_SOURCE, &sourceval) == 0);
948
949                                 if (strcmp(sourceval,
950                                     zfs_get_name(zhp)) == 0) {
951                                         sourcetype = ZFS_SRC_LOCAL;
952                                 } else {
953                                         sourcetype = ZFS_SRC_INHERITED;
954                                         (void) strlcpy(source,
955                                             sourceval, sizeof (source));
956                                 }
957                         }
958
959                         libzfs_print_one_property(zfs_get_name(zhp), cbp,
960                             pl->pl_user_prop, strval, sourcetype,
961                             source);
962                 }
963         }
964
965         return (0);
966 }
967
968 static int
969 zfs_do_get(int argc, char **argv)
970 {
971         libzfs_get_cbdata_t cb = { 0 };
972         boolean_t recurse = B_FALSE;
973         int i, c;
974         char *value, *fields;
975         int ret;
976         zfs_proplist_t fake_name = { 0 };
977
978         /*
979          * Set up default columns and sources.
980          */
981         cb.cb_sources = ZFS_SRC_ALL;
982         cb.cb_columns[0] = GET_COL_NAME;
983         cb.cb_columns[1] = GET_COL_PROPERTY;
984         cb.cb_columns[2] = GET_COL_VALUE;
985         cb.cb_columns[3] = GET_COL_SOURCE;
986
987         /* check options */
988         while ((c = getopt(argc, argv, ":o:s:rHp")) != -1) {
989                 switch (c) {
990                 case 'p':
991                         cb.cb_literal = B_TRUE;
992                         break;
993                 case 'r':
994                         recurse = B_TRUE;
995                         break;
996                 case 'H':
997                         cb.cb_scripted = B_TRUE;
998                         break;
999                 case ':':
1000                         (void) fprintf(stderr, gettext("missing argument for "
1001                             "'%c' option\n"), optopt);
1002                         usage(B_FALSE);
1003                         break;
1004                 case 'o':
1005                         /*
1006                          * Process the set of columns to display.  We zero out
1007                          * the structure to give us a blank slate.
1008                          */
1009                         bzero(&cb.cb_columns, sizeof (cb.cb_columns));
1010                         i = 0;
1011                         while (*optarg != '\0') {
1012                                 static char *col_subopts[] =
1013                                     { "name", "property", "value", "source",
1014                                     NULL };
1015
1016                                 if (i == 4) {
1017                                         (void) fprintf(stderr, gettext("too "
1018                                             "many fields given to -o "
1019                                             "option\n"));
1020                                         usage(B_FALSE);
1021                                 }
1022
1023                                 switch (getsubopt(&optarg, col_subopts,
1024                                     &value)) {
1025                                 case 0:
1026                                         cb.cb_columns[i++] = GET_COL_NAME;
1027                                         break;
1028                                 case 1:
1029                                         cb.cb_columns[i++] = GET_COL_PROPERTY;
1030                                         break;
1031                                 case 2:
1032                                         cb.cb_columns[i++] = GET_COL_VALUE;
1033                                         break;
1034                                 case 3:
1035                                         cb.cb_columns[i++] = GET_COL_SOURCE;
1036                                         break;
1037                                 default:
1038                                         (void) fprintf(stderr,
1039                                             gettext("invalid column name "
1040                                             "'%s'\n"), value);
1041                                         usage(B_FALSE);
1042                                 }
1043                         }
1044                         break;
1045
1046                 case 's':
1047                         cb.cb_sources = 0;
1048                         while (*optarg != '\0') {
1049                                 static char *source_subopts[] = {
1050                                         "local", "default", "inherited",
1051                                         "temporary", "none", NULL };
1052
1053                                 switch (getsubopt(&optarg, source_subopts,
1054                                     &value)) {
1055                                 case 0:
1056                                         cb.cb_sources |= ZFS_SRC_LOCAL;
1057                                         break;
1058                                 case 1:
1059                                         cb.cb_sources |= ZFS_SRC_DEFAULT;
1060                                         break;
1061                                 case 2:
1062                                         cb.cb_sources |= ZFS_SRC_INHERITED;
1063                                         break;
1064                                 case 3:
1065                                         cb.cb_sources |= ZFS_SRC_TEMPORARY;
1066                                         break;
1067                                 case 4:
1068                                         cb.cb_sources |= ZFS_SRC_NONE;
1069                                         break;
1070                                 default:
1071                                         (void) fprintf(stderr,
1072                                             gettext("invalid source "
1073                                             "'%s'\n"), value);
1074                                         usage(B_FALSE);
1075                                 }
1076                         }
1077                         break;
1078
1079                 case '?':
1080                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1081                             optopt);
1082                         usage(B_FALSE);
1083                 }
1084         }
1085
1086         argc -= optind;
1087         argv += optind;
1088
1089         if (argc < 1) {
1090                 (void) fprintf(stderr, gettext("missing property "
1091                     "argument\n"));
1092                 usage(B_FALSE);
1093         }
1094
1095         fields = argv[0];
1096
1097         if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0)
1098                 usage(B_FALSE);
1099
1100         argc--;
1101         argv++;
1102
1103         /*
1104          * As part of zfs_expand_proplist(), we keep track of the maximum column
1105          * width for each property.  For the 'NAME' (and 'SOURCE') columns, we
1106          * need to know the maximum name length.  However, the user likely did
1107          * not specify 'name' as one of the properties to fetch, so we need to
1108          * make sure we always include at least this property for
1109          * print_get_headers() to work properly.
1110          */
1111         if (cb.cb_proplist != NULL) {
1112                 fake_name.pl_prop = ZFS_PROP_NAME;
1113                 fake_name.pl_width = strlen(gettext("NAME"));
1114                 fake_name.pl_next = cb.cb_proplist;
1115                 cb.cb_proplist = &fake_name;
1116         }
1117
1118         cb.cb_first = B_TRUE;
1119
1120         /* run for each object */
1121         ret = zfs_for_each(argc, argv, recurse, ZFS_TYPE_ANY, NULL,
1122             &cb.cb_proplist, get_callback, &cb, B_FALSE);
1123
1124         if (cb.cb_proplist == &fake_name)
1125                 zfs_free_proplist(fake_name.pl_next);
1126         else
1127                 zfs_free_proplist(cb.cb_proplist);
1128
1129         return (ret);
1130 }
1131
1132 /*
1133  * inherit [-r] <property> <fs|vol> ...
1134  *
1135  *      -r      Recurse over all children
1136  *
1137  * For each dataset specified on the command line, inherit the given property
1138  * from its parent.  Inheriting a property at the pool level will cause it to
1139  * use the default value.  The '-r' flag will recurse over all children, and is
1140  * useful for setting a property on a hierarchy-wide basis, regardless of any
1141  * local modifications for each dataset.
1142  */
1143 typedef struct inherit_cbdata {
1144         char            *cb_propname;
1145         boolean_t       cb_any_successful;
1146 } inherit_cbdata_t;
1147
1148 static int
1149 inherit_callback(zfs_handle_t *zhp, void *data)
1150 {
1151         inherit_cbdata_t *cbp = data;
1152         int ret;
1153
1154         ret = zfs_prop_inherit(zhp, cbp->cb_propname);
1155         if (ret == 0)
1156                 cbp->cb_any_successful = B_TRUE;
1157         return (ret != 0);
1158 }
1159
1160 static int
1161 zfs_do_inherit(int argc, char **argv)
1162 {
1163         boolean_t recurse = B_FALSE;
1164         int c;
1165         zfs_prop_t prop;
1166         inherit_cbdata_t cb;
1167         int ret;
1168
1169         /* check options */
1170         while ((c = getopt(argc, argv, "r")) != -1) {
1171                 switch (c) {
1172                 case 'r':
1173                         recurse = B_TRUE;
1174                         break;
1175                 case '?':
1176                 default:
1177                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1178                             optopt);
1179                         usage(B_FALSE);
1180                 }
1181         }
1182
1183         argc -= optind;
1184         argv += optind;
1185
1186         /* check number of arguments */
1187         if (argc < 1) {
1188                 (void) fprintf(stderr, gettext("missing property argument\n"));
1189                 usage(B_FALSE);
1190         }
1191         if (argc < 2) {
1192                 (void) fprintf(stderr, gettext("missing dataset argument\n"));
1193                 usage(B_FALSE);
1194         }
1195
1196         cb.cb_propname = argv[0];
1197         argc--;
1198         argv++;
1199
1200         if ((prop = zfs_name_to_prop(cb.cb_propname)) != ZFS_PROP_INVAL) {
1201                 if (zfs_prop_readonly(prop)) {
1202                         (void) fprintf(stderr, gettext(
1203                             "%s property is read-only\n"),
1204                             cb.cb_propname);
1205                         return (1);
1206                 }
1207                 if (!zfs_prop_inheritable(prop)) {
1208                         (void) fprintf(stderr, gettext("'%s' property cannot "
1209                             "be inherited\n"), cb.cb_propname);
1210                         if (prop == ZFS_PROP_QUOTA ||
1211                             prop == ZFS_PROP_RESERVATION)
1212                                 (void) fprintf(stderr, gettext("use 'zfs set "
1213                                     "%s=none' to clear\n"), cb.cb_propname);
1214                         return (1);
1215                 }
1216         } else if (!zfs_prop_user(cb.cb_propname)) {
1217                 (void) fprintf(stderr, gettext(
1218                     "invalid property '%s'\n"),
1219                     cb.cb_propname);
1220                 usage(B_FALSE);
1221         }
1222
1223         cb.cb_any_successful = B_FALSE;
1224
1225         ret = zfs_for_each(argc, argv, recurse,
1226             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL,
1227             inherit_callback, &cb, B_FALSE);
1228
1229         if (cb.cb_any_successful) {
1230                 zpool_log_history(g_zfs, argc + optind + 1, argv - optind - 1,
1231                     argv[0], B_FALSE, B_FALSE);
1232         }
1233
1234         return (ret);
1235 }
1236
1237 /*
1238  * list [-rH] [-o property[,property]...] [-t type[,type]...]
1239  *      [-s property [-s property]...] [-S property [-S property]...]
1240  *      <dataset> ...
1241  *
1242  *      -r      Recurse over all children
1243  *      -H      Scripted mode; elide headers and separate colums by tabs
1244  *      -o      Control which fields to display.
1245  *      -t      Control which object types to display.
1246  *      -s      Specify sort columns, descending order.
1247  *      -S      Specify sort columns, ascending order.
1248  *
1249  * When given no arguments, lists all filesystems in the system.
1250  * Otherwise, list the specified datasets, optionally recursing down them if
1251  * '-r' is specified.
1252  */
1253 typedef struct list_cbdata {
1254         boolean_t       cb_first;
1255         boolean_t       cb_scripted;
1256         zfs_proplist_t  *cb_proplist;
1257 } list_cbdata_t;
1258
1259 /*
1260  * Given a list of columns to display, output appropriate headers for each one.
1261  */
1262 static void
1263 print_header(zfs_proplist_t *pl)
1264 {
1265         char headerbuf[ZFS_MAXPROPLEN];
1266         const char *header;
1267         int i;
1268         boolean_t first = B_TRUE;
1269         boolean_t right_justify;
1270
1271         for (; pl != NULL; pl = pl->pl_next) {
1272                 if (!first) {
1273                         (void) printf("  ");
1274                 } else {
1275                         first = B_FALSE;
1276                 }
1277
1278                 right_justify = B_FALSE;
1279                 if (pl->pl_prop != ZFS_PROP_INVAL) {
1280                         header = zfs_prop_column_name(pl->pl_prop);
1281                         right_justify = zfs_prop_align_right(pl->pl_prop);
1282                 } else {
1283                         for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
1284                                 headerbuf[i] = toupper(pl->pl_user_prop[i]);
1285                         headerbuf[i] = '\0';
1286                         header = headerbuf;
1287                 }
1288
1289                 if (pl->pl_next == NULL && !right_justify)
1290                         (void) printf("%s", header);
1291                 else if (right_justify)
1292                         (void) printf("%*s", pl->pl_width, header);
1293                 else
1294                         (void) printf("%-*s", pl->pl_width, header);
1295         }
1296
1297         (void) printf("\n");
1298 }
1299
1300 /*
1301  * Given a dataset and a list of fields, print out all the properties according
1302  * to the described layout.
1303  */
1304 static void
1305 print_dataset(zfs_handle_t *zhp, zfs_proplist_t *pl, int scripted)
1306 {
1307         boolean_t first = B_TRUE;
1308         char property[ZFS_MAXPROPLEN];
1309         nvlist_t *userprops = zfs_get_user_props(zhp);
1310         nvlist_t *propval;
1311         char *propstr;
1312         boolean_t right_justify;
1313         int width;
1314
1315         for (; pl != NULL; pl = pl->pl_next) {
1316                 if (!first) {
1317                         if (scripted)
1318                                 (void) printf("\t");
1319                         else
1320                                 (void) printf("  ");
1321                 } else {
1322                         first = B_FALSE;
1323                 }
1324
1325                 right_justify = B_FALSE;
1326                 if (pl->pl_prop != ZFS_PROP_INVAL) {
1327                         if (zfs_prop_get(zhp, pl->pl_prop, property,
1328                             sizeof (property), NULL, NULL, 0, B_FALSE) != 0)
1329                                 propstr = "-";
1330                         else
1331                                 propstr = property;
1332
1333                         right_justify = zfs_prop_align_right(pl->pl_prop);
1334                 } else {
1335                         if (nvlist_lookup_nvlist(userprops,
1336                             pl->pl_user_prop, &propval) != 0)
1337                                 propstr = "-";
1338                         else
1339                                 verify(nvlist_lookup_string(propval,
1340                                     ZFS_PROP_VALUE, &propstr) == 0);
1341                 }
1342
1343                 width = pl->pl_width;
1344
1345                 /*
1346                  * If this is being called in scripted mode, or if this is the
1347                  * last column and it is left-justified, don't include a width
1348                  * format specifier.
1349                  */
1350                 if (scripted || (pl->pl_next == NULL && !right_justify))
1351                         (void) printf("%s", propstr);
1352                 else if (right_justify)
1353                         (void) printf("%*s", width, propstr);
1354                 else
1355                         (void) printf("%-*s", width, propstr);
1356         }
1357
1358         (void) printf("\n");
1359 }
1360
1361 /*
1362  * Generic callback function to list a dataset or snapshot.
1363  */
1364 static int
1365 list_callback(zfs_handle_t *zhp, void *data)
1366 {
1367         list_cbdata_t *cbp = data;
1368
1369         if (cbp->cb_first) {
1370                 if (!cbp->cb_scripted)
1371                         print_header(cbp->cb_proplist);
1372                 cbp->cb_first = B_FALSE;
1373         }
1374
1375         print_dataset(zhp, cbp->cb_proplist, cbp->cb_scripted);
1376
1377         return (0);
1378 }
1379
1380 static int
1381 zfs_do_list(int argc, char **argv)
1382 {
1383         int c;
1384         boolean_t recurse = B_FALSE;
1385         boolean_t scripted = B_FALSE;
1386         static char default_fields[] =
1387             "name,used,available,referenced,mountpoint";
1388         int types = ZFS_TYPE_ANY;
1389         char *fields = NULL;
1390         char *basic_fields = default_fields;
1391         list_cbdata_t cb = { 0 };
1392         char *value;
1393         int ret;
1394         char *type_subopts[] = { "filesystem", "volume", "snapshot", NULL };
1395         zfs_sort_column_t *sortcol = NULL;
1396
1397         /* check options */
1398         while ((c = getopt(argc, argv, ":o:rt:Hs:S:")) != -1) {
1399                 switch (c) {
1400                 case 'o':
1401                         fields = optarg;
1402                         break;
1403                 case 'r':
1404                         recurse = B_TRUE;
1405                         break;
1406                 case 'H':
1407                         scripted = B_TRUE;
1408                         break;
1409                 case 's':
1410                         if (zfs_add_sort_column(&sortcol, optarg,
1411                             B_FALSE) != 0) {
1412                                 (void) fprintf(stderr,
1413                                     gettext("invalid property '%s'\n"), optarg);
1414                                 usage(B_FALSE);
1415                         }
1416                         break;
1417                 case 'S':
1418                         if (zfs_add_sort_column(&sortcol, optarg,
1419                             B_TRUE) != 0) {
1420                                 (void) fprintf(stderr,
1421                                     gettext("invalid property '%s'\n"), optarg);
1422                                 usage(B_FALSE);
1423                         }
1424                         break;
1425                 case 't':
1426                         types = 0;
1427                         while (*optarg != '\0') {
1428                                 switch (getsubopt(&optarg, type_subopts,
1429                                     &value)) {
1430                                 case 0:
1431                                         types |= ZFS_TYPE_FILESYSTEM;
1432                                         break;
1433                                 case 1:
1434                                         types |= ZFS_TYPE_VOLUME;
1435                                         break;
1436                                 case 2:
1437                                         types |= ZFS_TYPE_SNAPSHOT;
1438                                         break;
1439                                 default:
1440                                         (void) fprintf(stderr,
1441                                             gettext("invalid type '%s'\n"),
1442                                             value);
1443                                         usage(B_FALSE);
1444                                 }
1445                         }
1446                         break;
1447                 case ':':
1448                         (void) fprintf(stderr, gettext("missing argument for "
1449                             "'%c' option\n"), optopt);
1450                         usage(B_FALSE);
1451                         break;
1452                 case '?':
1453                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1454                             optopt);
1455                         usage(B_FALSE);
1456                 }
1457         }
1458
1459         argc -= optind;
1460         argv += optind;
1461
1462         if (fields == NULL)
1463                 fields = basic_fields;
1464
1465         /*
1466          * If the user specifies '-o all', the zfs_get_proplist() doesn't
1467          * normally include the name of the dataset.  For 'zfs list', we always
1468          * want this property to be first.
1469          */
1470         if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0)
1471                 usage(B_FALSE);
1472
1473         cb.cb_scripted = scripted;
1474         cb.cb_first = B_TRUE;
1475
1476         ret = zfs_for_each(argc, argv, recurse, types, sortcol, &cb.cb_proplist,
1477             list_callback, &cb, B_TRUE);
1478
1479         zfs_free_proplist(cb.cb_proplist);
1480         zfs_free_sort_columns(sortcol);
1481
1482         if (ret == 0 && cb.cb_first)
1483                 (void) printf(gettext("no datasets available\n"));
1484
1485         return (ret);
1486 }
1487
1488 /*
1489  * zfs rename [-r] <fs | snap | vol> <fs | snap | vol>
1490  *
1491  * Renames the given dataset to another of the same type.
1492  */
1493 /* ARGSUSED */
1494 static int
1495 zfs_do_rename(int argc, char **argv)
1496 {
1497         zfs_handle_t *zhp;
1498         int c;
1499         int ret;
1500         int recurse = 0;
1501
1502         /* check options */
1503         while ((c = getopt(argc, argv, "r")) != -1) {
1504                 switch (c) {
1505                 case 'r':
1506                         recurse = 1;
1507                         break;
1508                 case '?':
1509                 default:
1510                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1511                             optopt);
1512                         usage(B_FALSE);
1513                 }
1514         }
1515
1516         argc -= optind;
1517         argv += optind;
1518
1519         /* check number of arguments */
1520         if (argc < 1) {
1521                 (void) fprintf(stderr, gettext("missing source dataset "
1522                     "argument\n"));
1523                 usage(B_FALSE);
1524         }
1525         if (argc < 2) {
1526                 (void) fprintf(stderr, gettext("missing target dataset "
1527                     "argument\n"));
1528                 usage(B_FALSE);
1529         }
1530         if (argc > 2) {
1531                 (void) fprintf(stderr, gettext("too many arguments\n"));
1532                 usage(B_FALSE);
1533         }
1534
1535         if (recurse && strchr(argv[0], '@') == 0) {
1536                 (void) fprintf(stderr, gettext("source dataset for recursive "
1537                     "rename must be a snapshot\n"));
1538                 usage(B_FALSE);
1539         }
1540
1541         if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
1542                 return (1);
1543
1544         ret = (zfs_rename(zhp, argv[1], recurse) != 0);
1545
1546         if (!ret)
1547                 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[1],
1548                     B_FALSE, B_FALSE);
1549
1550         zfs_close(zhp);
1551         return (ret);
1552 }
1553
1554 /*
1555  * zfs promote <fs>
1556  *
1557  * Promotes the given clone fs to be the parent
1558  */
1559 /* ARGSUSED */
1560 static int
1561 zfs_do_promote(int argc, char **argv)
1562 {
1563         zfs_handle_t *zhp;
1564         int ret;
1565
1566         /* check options */
1567         if (argc > 1 && argv[1][0] == '-') {
1568                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1569                     argv[1][1]);
1570                 usage(B_FALSE);
1571         }
1572
1573         /* check number of arguments */
1574         if (argc < 2) {
1575                 (void) fprintf(stderr, gettext("missing clone filesystem"
1576                     " argument\n"));
1577                 usage(B_FALSE);
1578         }
1579         if (argc > 2) {
1580                 (void) fprintf(stderr, gettext("too many arguments\n"));
1581                 usage(B_FALSE);
1582         }
1583
1584         zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
1585         if (zhp == NULL)
1586                 return (1);
1587
1588         ret = (zfs_promote(zhp) != 0);
1589
1590         if (!ret)
1591                 zpool_log_history(g_zfs, argc, argv, argv[1], B_FALSE, B_FALSE);
1592
1593         zfs_close(zhp);
1594         return (ret);
1595 }
1596
1597 /*
1598  * zfs rollback [-rfR] <snapshot>
1599  *
1600  *      -r      Delete any intervening snapshots before doing rollback
1601  *      -R      Delete any snapshots and their clones
1602  *      -f      Force unmount filesystems, even if they are in use.
1603  *
1604  * Given a filesystem, rollback to a specific snapshot, discarding any changes
1605  * since then and making it the active dataset.  If more recent snapshots exist,
1606  * the command will complain unless the '-r' flag is given.
1607  */
1608 typedef struct rollback_cbdata {
1609         uint64_t        cb_create;
1610         boolean_t       cb_first;
1611         int             cb_doclones;
1612         char            *cb_target;
1613         int             cb_error;
1614         boolean_t       cb_recurse;
1615         boolean_t       cb_dependent;
1616 } rollback_cbdata_t;
1617
1618 /*
1619  * Report any snapshots more recent than the one specified.  Used when '-r' is
1620  * not specified.  We reuse this same callback for the snapshot dependents - if
1621  * 'cb_dependent' is set, then this is a dependent and we should report it
1622  * without checking the transaction group.
1623  */
1624 static int
1625 rollback_check(zfs_handle_t *zhp, void *data)
1626 {
1627         rollback_cbdata_t *cbp = data;
1628
1629         if (cbp->cb_doclones) {
1630                 zfs_close(zhp);
1631                 return (0);
1632         }
1633
1634         if (!cbp->cb_dependent) {
1635                 if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 &&
1636                     zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
1637                     zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
1638                     cbp->cb_create) {
1639
1640                         if (cbp->cb_first && !cbp->cb_recurse) {
1641                                 (void) fprintf(stderr, gettext("cannot "
1642                                     "rollback to '%s': more recent snapshots "
1643                                     "exist\n"),
1644                                     cbp->cb_target);
1645                                 (void) fprintf(stderr, gettext("use '-r' to "
1646                                     "force deletion of the following "
1647                                     "snapshots:\n"));
1648                                 cbp->cb_first = 0;
1649                                 cbp->cb_error = 1;
1650                         }
1651
1652                         if (cbp->cb_recurse) {
1653                                 cbp->cb_dependent = B_TRUE;
1654                                 if (zfs_iter_dependents(zhp, B_TRUE,
1655                                     rollback_check, cbp) != 0) {
1656                                         zfs_close(zhp);
1657                                         return (-1);
1658                                 }
1659                                 cbp->cb_dependent = B_FALSE;
1660                         } else {
1661                                 (void) fprintf(stderr, "%s\n",
1662                                     zfs_get_name(zhp));
1663                         }
1664                 }
1665         } else {
1666                 if (cbp->cb_first && cbp->cb_recurse) {
1667                         (void) fprintf(stderr, gettext("cannot rollback to "
1668                             "'%s': clones of previous snapshots exist\n"),
1669                             cbp->cb_target);
1670                         (void) fprintf(stderr, gettext("use '-R' to "
1671                             "force deletion of the following clones and "
1672                             "dependents:\n"));
1673                         cbp->cb_first = 0;
1674                         cbp->cb_error = 1;
1675                 }
1676
1677                 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
1678         }
1679
1680         zfs_close(zhp);
1681         return (0);
1682 }
1683
1684 static int
1685 zfs_do_rollback(int argc, char **argv)
1686 {
1687         int ret;
1688         int c;
1689         rollback_cbdata_t cb = { 0 };
1690         zfs_handle_t *zhp, *snap;
1691         char parentname[ZFS_MAXNAMELEN];
1692         char *delim;
1693         int force = 0;
1694
1695         /* check options */
1696         while ((c = getopt(argc, argv, "rfR")) != -1) {
1697                 switch (c) {
1698                 case 'f':
1699                         force = 1;
1700                         break;
1701                 case 'r':
1702                         cb.cb_recurse = 1;
1703                         break;
1704                 case 'R':
1705                         cb.cb_recurse = 1;
1706                         cb.cb_doclones = 1;
1707                         break;
1708                 case '?':
1709                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1710                             optopt);
1711                         usage(B_FALSE);
1712                 }
1713         }
1714
1715         argc -= optind;
1716         argv += optind;
1717
1718         /* check number of arguments */
1719         if (argc < 1) {
1720                 (void) fprintf(stderr, gettext("missing dataset argument\n"));
1721                 usage(B_FALSE);
1722         }
1723         if (argc > 1) {
1724                 (void) fprintf(stderr, gettext("too many arguments\n"));
1725                 usage(B_FALSE);
1726         }
1727
1728         /* open the snapshot */
1729         if ((snap = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
1730                 return (1);
1731
1732         /* open the parent dataset */
1733         (void) strlcpy(parentname, argv[0], sizeof (parentname));
1734         verify((delim = strrchr(parentname, '@')) != NULL);
1735         *delim = '\0';
1736         if ((zhp = zfs_open(g_zfs, parentname, ZFS_TYPE_ANY)) == NULL) {
1737                 zfs_close(snap);
1738                 return (1);
1739         }
1740
1741         /*
1742          * Check for more recent snapshots and/or clones based on the presence
1743          * of '-r' and '-R'.
1744          */
1745         cb.cb_target = argv[0];
1746         cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
1747         cb.cb_first = B_TRUE;
1748         cb.cb_error = 0;
1749         if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0)
1750                 goto out;
1751
1752         if ((ret = cb.cb_error) != 0)
1753                 goto out;
1754
1755         /*
1756          * Rollback parent to the given snapshot.
1757          */
1758         ret = zfs_rollback(zhp, snap, force);
1759
1760         if (!ret) {
1761                 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
1762                     B_FALSE, B_FALSE);
1763         }
1764
1765 out:
1766         zfs_close(snap);
1767         zfs_close(zhp);
1768
1769         if (ret == 0)
1770                 return (0);
1771         else
1772                 return (1);
1773 }
1774
1775 /*
1776  * zfs set property=value { fs | snap | vol } ...
1777  *
1778  * Sets the given property for all datasets specified on the command line.
1779  */
1780 typedef struct set_cbdata {
1781         char            *cb_propname;
1782         char            *cb_value;
1783         boolean_t       cb_any_successful;
1784 } set_cbdata_t;
1785
1786 static int
1787 set_callback(zfs_handle_t *zhp, void *data)
1788 {
1789         set_cbdata_t *cbp = data;
1790
1791         if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) {
1792                 switch (libzfs_errno(g_zfs)) {
1793                 case EZFS_MOUNTFAILED:
1794                         (void) fprintf(stderr, gettext("property may be set "
1795                             "but unable to remount filesystem\n"));
1796                         break;
1797                 case EZFS_SHARENFSFAILED:
1798                         (void) fprintf(stderr, gettext("property may be set "
1799                             "but unable to reshare filesystem\n"));
1800                         break;
1801                 }
1802                 return (1);
1803         }
1804         cbp->cb_any_successful = B_TRUE;
1805         return (0);
1806 }
1807
1808 static int
1809 zfs_do_set(int argc, char **argv)
1810 {
1811         set_cbdata_t cb;
1812         int ret;
1813
1814         /* check for options */
1815         if (argc > 1 && argv[1][0] == '-') {
1816                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1817                     argv[1][1]);
1818                 usage(B_FALSE);
1819         }
1820
1821         /* check number of arguments */
1822         if (argc < 2) {
1823                 (void) fprintf(stderr, gettext("missing property=value "
1824                     "argument\n"));
1825                 usage(B_FALSE);
1826         }
1827         if (argc < 3) {
1828                 (void) fprintf(stderr, gettext("missing dataset name\n"));
1829                 usage(B_FALSE);
1830         }
1831
1832         /* validate property=value argument */
1833         cb.cb_propname = argv[1];
1834         if ((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) {
1835                 (void) fprintf(stderr, gettext("missing value in "
1836                     "property=value argument\n"));
1837                 usage(B_FALSE);
1838         }
1839
1840         *cb.cb_value = '\0';
1841         cb.cb_value++;
1842         cb.cb_any_successful = B_FALSE;
1843
1844         if (*cb.cb_propname == '\0') {
1845                 (void) fprintf(stderr,
1846                     gettext("missing property in property=value argument\n"));
1847                 usage(B_FALSE);
1848         }
1849
1850         ret = zfs_for_each(argc - 2, argv + 2, B_FALSE,
1851             ZFS_TYPE_ANY, NULL, NULL, set_callback, &cb, B_FALSE);
1852
1853         if (cb.cb_any_successful) {
1854                 *(cb.cb_value - 1) = '=';
1855                 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
1856         }
1857
1858         return (ret);
1859 }
1860
1861 /*
1862  * zfs snapshot [-r] <fs@snap>
1863  *
1864  * Creates a snapshot with the given name.  While functionally equivalent to
1865  * 'zfs create', it is a separate command to diffferentiate intent.
1866  */
1867 static int
1868 zfs_do_snapshot(int argc, char **argv)
1869 {
1870         int recursive = B_FALSE;
1871         int ret;
1872         char c;
1873
1874         /* check options */
1875         while ((c = getopt(argc, argv, ":r")) != -1) {
1876                 switch (c) {
1877                 case 'r':
1878                         recursive = B_TRUE;
1879                         break;
1880                 case '?':
1881                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1882                             optopt);
1883                         usage(B_FALSE);
1884                 }
1885         }
1886
1887         argc -= optind;
1888         argv += optind;
1889
1890         /* check number of arguments */
1891         if (argc < 1) {
1892                 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
1893                 usage(B_FALSE);
1894         }
1895         if (argc > 1) {
1896                 (void) fprintf(stderr, gettext("too many arguments\n"));
1897                 usage(B_FALSE);
1898         }
1899
1900         ret = zfs_snapshot(g_zfs, argv[0], recursive);
1901         if (ret && recursive)
1902                 (void) fprintf(stderr, gettext("no snapshots were created\n"));
1903         if (!ret) {
1904                 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
1905                     B_FALSE, B_FALSE);
1906         }
1907         return (ret != 0);
1908 }
1909
1910 /*
1911  * zfs send [-i <@snap>] <fs@snap>
1912  *
1913  * Send a backup stream to stdout.
1914  */
1915 static int
1916 zfs_do_send(int argc, char **argv)
1917 {
1918         char *fromname = NULL;
1919         char *cp;
1920         zfs_handle_t *zhp;
1921         int c, err;
1922
1923         /* check options */
1924         while ((c = getopt(argc, argv, ":i:")) != -1) {
1925                 switch (c) {
1926                 case 'i':
1927                         if (fromname)
1928                                 usage(B_FALSE);
1929                         fromname = optarg;
1930                         break;
1931                 case ':':
1932                         (void) fprintf(stderr, gettext("missing argument for "
1933                             "'%c' option\n"), optopt);
1934                         usage(B_FALSE);
1935                         break;
1936                 case '?':
1937                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1938                             optopt);
1939                         usage(B_FALSE);
1940                 }
1941         }
1942
1943         argc -= optind;
1944         argv += optind;
1945
1946         /* check number of arguments */
1947         if (argc < 1) {
1948                 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
1949                 usage(B_FALSE);
1950         }
1951         if (argc > 1) {
1952                 (void) fprintf(stderr, gettext("too many arguments\n"));
1953                 usage(B_FALSE);
1954         }
1955
1956         if (isatty(STDOUT_FILENO)) {
1957                 (void) fprintf(stderr,
1958                     gettext("Error: Stream can not be written to a terminal.\n"
1959                     "You must redirect standard output.\n"));
1960                 return (1);
1961         }
1962
1963         if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
1964                 return (1);
1965
1966         /*
1967          * If they specified the full path to the snapshot, chop off
1968          * everything except the short name of the snapshot.
1969          */
1970         if (fromname && (cp = strchr(fromname, '@')) != NULL) {
1971                 if (cp != fromname &&
1972                     strncmp(argv[0], fromname, cp - fromname + 1)) {
1973                         (void) fprintf(stderr,
1974                             gettext("incremental source must be "
1975                             "in same filesystem\n"));
1976                         usage(B_FALSE);
1977                 }
1978                 fromname = cp + 1;
1979                 if (strchr(fromname, '@') || strchr(fromname, '/')) {
1980                         (void) fprintf(stderr,
1981                             gettext("invalid incremental source\n"));
1982                         usage(B_FALSE);
1983                 }
1984         }
1985
1986         err = zfs_send(zhp, fromname, STDOUT_FILENO);
1987         zfs_close(zhp);
1988
1989         return (err != 0);
1990 }
1991
1992 /*
1993  * zfs receive <fs@snap>
1994  *
1995  * Restore a backup stream from stdin.
1996  */
1997 static int
1998 zfs_do_receive(int argc, char **argv)
1999 {
2000         int c, err;
2001         boolean_t isprefix = B_FALSE;
2002         boolean_t dryrun = B_FALSE;
2003         boolean_t verbose = B_FALSE;
2004         boolean_t force = B_FALSE;
2005
2006         /* check options */
2007         while ((c = getopt(argc, argv, ":dnvF")) != -1) {
2008                 switch (c) {
2009                 case 'd':
2010                         isprefix = B_TRUE;
2011                         break;
2012                 case 'n':
2013                         dryrun = B_TRUE;
2014                         break;
2015                 case 'v':
2016                         verbose = B_TRUE;
2017                         break;
2018                 case 'F':
2019                         force = B_TRUE;
2020                         break;
2021                 case ':':
2022                         (void) fprintf(stderr, gettext("missing argument for "
2023                             "'%c' option\n"), optopt);
2024                         usage(B_FALSE);
2025                         break;
2026                 case '?':
2027                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2028                             optopt);
2029                         usage(B_FALSE);
2030                 }
2031         }
2032
2033         argc -= optind;
2034         argv += optind;
2035
2036         /* check number of arguments */
2037         if (argc < 1) {
2038                 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
2039                 usage(B_FALSE);
2040         }
2041         if (argc > 1) {
2042                 (void) fprintf(stderr, gettext("too many arguments\n"));
2043                 usage(B_FALSE);
2044         }
2045
2046         if (isatty(STDIN_FILENO)) {
2047                 (void) fprintf(stderr,
2048                     gettext("Error: Backup stream can not be read "
2049                     "from a terminal.\n"
2050                     "You must redirect standard input.\n"));
2051                 return (1);
2052         }
2053
2054         err = zfs_receive(g_zfs, argv[0], isprefix, verbose, dryrun, force,
2055             STDIN_FILENO);
2056
2057         if (!err) {
2058                 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
2059                     B_FALSE, B_FALSE);
2060         }
2061
2062         return (err != 0);
2063 }
2064
2065 typedef struct get_all_cbdata {
2066         zfs_handle_t    **cb_handles;
2067         size_t          cb_alloc;
2068         size_t          cb_used;
2069         uint_t          cb_types;
2070 } get_all_cbdata_t;
2071
2072 static int
2073 get_one_dataset(zfs_handle_t *zhp, void *data)
2074 {
2075         get_all_cbdata_t *cbp = data;
2076         zfs_type_t type = zfs_get_type(zhp);
2077
2078         /*
2079          * Interate over any nested datasets.
2080          */
2081         if (type == ZFS_TYPE_FILESYSTEM &&
2082             zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) {
2083                 zfs_close(zhp);
2084                 return (1);
2085         }
2086
2087         /*
2088          * Skip any datasets whose type does not match.
2089          */
2090         if ((type & cbp->cb_types) == 0) {
2091                 zfs_close(zhp);
2092                 return (0);
2093         }
2094
2095         if (cbp->cb_alloc == cbp->cb_used) {
2096                 zfs_handle_t **handles;
2097
2098                 if (cbp->cb_alloc == 0)
2099                         cbp->cb_alloc = 64;
2100                 else
2101                         cbp->cb_alloc *= 2;
2102
2103                 handles = safe_malloc(cbp->cb_alloc * sizeof (void *));
2104
2105                 if (cbp->cb_handles) {
2106                         bcopy(cbp->cb_handles, handles,
2107                             cbp->cb_used * sizeof (void *));
2108                         free(cbp->cb_handles);
2109                 }
2110
2111                 cbp->cb_handles = handles;
2112         }
2113
2114         cbp->cb_handles[cbp->cb_used++] = zhp;
2115
2116         return (0);
2117 }
2118
2119 static void
2120 get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count)
2121 {
2122         get_all_cbdata_t cb = { 0 };
2123         cb.cb_types = types;
2124
2125         (void) zfs_iter_root(g_zfs, get_one_dataset, &cb);
2126
2127         *dslist = cb.cb_handles;
2128         *count = cb.cb_used;
2129 }
2130
2131 static int
2132 dataset_cmp(const void *a, const void *b)
2133 {
2134         zfs_handle_t **za = (zfs_handle_t **)a;
2135         zfs_handle_t **zb = (zfs_handle_t **)b;
2136         char mounta[MAXPATHLEN];
2137         char mountb[MAXPATHLEN];
2138         boolean_t gota, gotb;
2139
2140         if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0)
2141                 verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
2142                     sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
2143         if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0)
2144                 verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
2145                     sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
2146
2147         if (gota && gotb)
2148                 return (strcmp(mounta, mountb));
2149
2150         if (gota)
2151                 return (-1);
2152         if (gotb)
2153                 return (1);
2154
2155         return (strcmp(zfs_get_name(a), zfs_get_name(b)));
2156 }
2157
2158 /*
2159  * Generic callback for sharing or mounting filesystems.  Because the code is so
2160  * similar, we have a common function with an extra parameter to determine which
2161  * mode we are using.
2162  */
2163 #define OP_SHARE        0x1
2164 #define OP_MOUNT        0x2
2165
2166 /*
2167  * Share or mount a dataset.
2168  */
2169 static int
2170 share_mount_one(zfs_handle_t *zhp, int op, int flags, boolean_t explicit,
2171     const char *options)
2172 {
2173         char mountpoint[ZFS_MAXPROPLEN];
2174         char shareopts[ZFS_MAXPROPLEN];
2175         const char *cmdname = op == OP_SHARE ? "share" : "mount";
2176         struct mnttab mnt;
2177         uint64_t zoned, canmount;
2178         zfs_type_t type = zfs_get_type(zhp);
2179
2180         assert(type & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME));
2181
2182         if (type == ZFS_TYPE_FILESYSTEM) {
2183                 /*
2184                  * Check to make sure we can mount/share this dataset.  If we
2185                  * are in the global zone and the filesystem is exported to a
2186                  * local zone, or if we are in a local zone and the
2187                  * filesystem is not exported, then it is an error.
2188                  */
2189                 zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
2190
2191                 if (zoned && getzoneid() == GLOBAL_ZONEID) {
2192                         if (!explicit)
2193                                 return (0);
2194
2195                         (void) fprintf(stderr, gettext("cannot %s '%s': "
2196                             "dataset is exported to a local zone\n"), cmdname,
2197                             zfs_get_name(zhp));
2198                         return (1);
2199
2200                 } else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
2201                         if (!explicit)
2202                                 return (0);
2203
2204                         (void) fprintf(stderr, gettext("cannot %s '%s': "
2205                             "permission denied\n"), cmdname,
2206                             zfs_get_name(zhp));
2207                         return (1);
2208                 }
2209
2210                 /*
2211                  * Ignore any filesystems which don't apply to us. This
2212                  * includes those with a legacy mountpoint, or those with
2213                  * legacy share options.
2214                  */
2215                 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
2216                     sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
2217                 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
2218                     sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
2219                 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
2220
2221                 if (op == OP_SHARE && strcmp(shareopts, "off") == 0) {
2222                         if (!explicit)
2223                                 return (0);
2224
2225                         (void) fprintf(stderr, gettext("cannot share '%s': "
2226                             "legacy share\n"), zfs_get_name(zhp));
2227                         (void) fprintf(stderr, gettext("use share(1M) to "
2228                             "share this filesystem\n"));
2229                         return (1);
2230                 }
2231
2232                 /*
2233                  * We cannot share or mount legacy filesystems. If the
2234                  * shareopts is non-legacy but the mountpoint is legacy, we
2235                  * treat it as a legacy share.
2236                  */
2237                 if (strcmp(mountpoint, "legacy") == 0) {
2238                         if (!explicit)
2239                                 return (0);
2240
2241                         (void) fprintf(stderr, gettext("cannot %s '%s': "
2242                             "legacy mountpoint\n"), cmdname, zfs_get_name(zhp));
2243                         (void) fprintf(stderr, gettext("use %s to "
2244                             "%s this filesystem\n"), op == OP_SHARE ?
2245                             "share(1M)" : "mount(1M)", cmdname);
2246                         return (1);
2247                 }
2248
2249                 if (strcmp(mountpoint, "none") == 0) {
2250                         if (!explicit)
2251                                 return (0);
2252
2253                         (void) fprintf(stderr, gettext("cannot %s '%s': no "
2254                             "mountpoint set\n"), cmdname, zfs_get_name(zhp));
2255                         return (1);
2256                 }
2257
2258                 if (!canmount) {
2259                         if (!explicit)
2260                                 return (0);
2261
2262                         (void) fprintf(stderr, gettext("cannot %s '%s': "
2263                             "'canmount' property is set to 'off'\n"), cmdname,
2264                             zfs_get_name(zhp));
2265                         return (1);
2266                 }
2267
2268                 /*
2269                  * At this point, we have verified that the mountpoint and/or
2270                  * shareopts are appropriate for auto management. If the
2271                  * filesystem is already mounted or shared, return (failing
2272                  * for explicit requests); otherwise mount or share the
2273                  * filesystem.
2274                  */
2275                 switch (op) {
2276                 case OP_SHARE:
2277                         if (zfs_is_shared_nfs(zhp, NULL)) {
2278                                 if (!explicit)
2279                                         return (0);
2280
2281                                 (void) fprintf(stderr, gettext("cannot share "
2282                                     "'%s': filesystem already shared\n"),
2283                                     zfs_get_name(zhp));
2284                                 return (1);
2285                         }
2286
2287                         if (!zfs_is_mounted(zhp, NULL) &&
2288                             zfs_mount(zhp, NULL, 0) != 0)
2289                                 return (1);
2290
2291                         if (zfs_share_nfs(zhp) != 0)
2292                                 return (1);
2293                         break;
2294
2295                 case OP_MOUNT:
2296                         if (options == NULL)
2297                                 mnt.mnt_mntopts = "";
2298                         else
2299                                 mnt.mnt_mntopts = (char *)options;
2300
2301                         if (!hasmntopt(&mnt, MNTOPT_REMOUNT) &&
2302                             zfs_is_mounted(zhp, NULL)) {
2303                                 if (!explicit)
2304                                         return (0);
2305
2306                                 (void) fprintf(stderr, gettext("cannot mount "
2307                                     "'%s': filesystem already mounted\n"),
2308                                     zfs_get_name(zhp));
2309                                 return (1);
2310                         }
2311
2312                         if (zfs_mount(zhp, options, flags) != 0)
2313                                 return (1);
2314                         break;
2315                 }
2316         } else {
2317                 assert(op == OP_SHARE);
2318
2319                 /*
2320                  * Ignore any volumes that aren't shared.
2321                  */
2322                 verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts,
2323                     sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
2324
2325                 if (strcmp(shareopts, "off") == 0) {
2326                         if (!explicit)
2327                                 return (0);
2328
2329                         (void) fprintf(stderr, gettext("cannot share '%s': "
2330                             "'shareiscsi' property not set\n"),
2331                             zfs_get_name(zhp));
2332                         (void) fprintf(stderr, gettext("set 'shareiscsi' "
2333                             "property or use iscsitadm(1M) to share this "
2334                             "volume\n"));
2335                         return (1);
2336                 }
2337
2338                 if (zfs_is_shared_iscsi(zhp)) {
2339                         if (!explicit)
2340                                 return (0);
2341
2342                         (void) fprintf(stderr, gettext("cannot share "
2343                             "'%s': volume already shared\n"),
2344                             zfs_get_name(zhp));
2345                         return (1);
2346                 }
2347
2348                 if (zfs_share_iscsi(zhp) != 0)
2349                         return (1);
2350         }
2351
2352         return (0);
2353 }
2354
2355 static int
2356 share_mount(int op, int argc, char **argv)
2357 {
2358         int do_all = 0;
2359         int c, ret = 0;
2360         const char *options = NULL;
2361         int types, flags = 0;
2362
2363         /* check options */
2364         while ((c = getopt(argc, argv, op == OP_MOUNT ? ":ao:O" : "a"))
2365             != -1) {
2366                 switch (c) {
2367                 case 'a':
2368                         do_all = 1;
2369                         break;
2370                 case 'o':
2371                         options = optarg;
2372                         break;
2373                 case 'O':
2374                         warnx("no overlay mounts support on FreeBSD, ignoring");
2375                         break;
2376                 case ':':
2377                         (void) fprintf(stderr, gettext("missing argument for "
2378                             "'%c' option\n"), optopt);
2379                         usage(B_FALSE);
2380                         break;
2381                 case '?':
2382                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2383                             optopt);
2384                         usage(B_FALSE);
2385                 }
2386         }
2387
2388         argc -= optind;
2389         argv += optind;
2390
2391         /* check number of arguments */
2392         if (do_all) {
2393                 zfs_handle_t **dslist = NULL;
2394                 size_t i, count = 0;
2395
2396                 if (op == OP_MOUNT) {
2397                         types = ZFS_TYPE_FILESYSTEM;
2398                 } else if (argc > 0) {
2399                         if (strcmp(argv[0], "nfs") == 0) {
2400                                 types = ZFS_TYPE_FILESYSTEM;
2401                         } else if (strcmp(argv[0], "iscsi") == 0) {
2402                                 types = ZFS_TYPE_VOLUME;
2403                         } else {
2404                                 (void) fprintf(stderr, gettext("share type "
2405                                     "must be 'nfs' or 'iscsi'\n"));
2406                                 usage(B_FALSE);
2407                         }
2408
2409                         argc--;
2410                         argv++;
2411                 } else {
2412                         types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
2413                 }
2414
2415                 if (argc != 0) {
2416                         (void) fprintf(stderr, gettext("too many arguments\n"));
2417                         usage(B_FALSE);
2418                 }
2419
2420                 get_all_datasets(types, &dslist, &count);
2421
2422                 if (count == 0)
2423                         return (0);
2424
2425                 qsort(dslist, count, sizeof (void *), dataset_cmp);
2426
2427                 for (i = 0; i < count; i++) {
2428                         if (share_mount_one(dslist[i], op, flags, B_FALSE,
2429                             options) != 0)
2430                                 ret = 1;
2431                         zfs_close(dslist[i]);
2432                 }
2433
2434                 free(dslist);
2435         } else if (argc == 0) {
2436                 struct statfs *sfs;
2437                 int i, n;
2438
2439                 if (op == OP_SHARE) {
2440                         (void) fprintf(stderr, gettext("missing filesystem "
2441                             "argument\n"));
2442                         usage(B_FALSE);
2443                 }
2444
2445                 /*
2446                  * When mount is given no arguments, go through /etc/mnttab and
2447                  * display any active ZFS mounts.  We hide any snapshots, since
2448                  * they are controlled automatically.
2449                  */
2450                 if ((n = getmntinfo(&sfs, MNT_WAIT)) == 0) {
2451                         fprintf(stderr, "getmntinfo(): %s\n", strerror(errno));
2452                         return (0);
2453                 }
2454                 for (i = 0; i < n; i++) {
2455                         if (strcmp(sfs[i].f_fstypename, MNTTYPE_ZFS) != 0 ||
2456                             strchr(sfs[i].f_mntfromname, '@') != NULL)
2457                                 continue;
2458
2459                         (void) printf("%-30s  %s\n", sfs[i].f_mntfromname,
2460                             sfs[i].f_mntonname);
2461                 }
2462
2463         } else {
2464                 zfs_handle_t *zhp;
2465
2466                 types = ZFS_TYPE_FILESYSTEM;
2467                 if (op == OP_SHARE)
2468                         types |= ZFS_TYPE_VOLUME;
2469
2470                 if (argc > 1) {
2471                         (void) fprintf(stderr,
2472                             gettext("too many arguments\n"));
2473                         usage(B_FALSE);
2474                 }
2475
2476                 if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) {
2477                         ret = 1;
2478                 } else {
2479                         ret = share_mount_one(zhp, op, flags, B_TRUE,
2480                             options);
2481                         zfs_close(zhp);
2482                 }
2483         }
2484
2485         return (ret);
2486 }
2487
2488 /*
2489  * zfs mount -a [nfs | iscsi]
2490  * zfs mount filesystem
2491  *
2492  * Mount all filesystems, or mount the given filesystem.
2493  */
2494 static int
2495 zfs_do_mount(int argc, char **argv)
2496 {
2497         return (share_mount(OP_MOUNT, argc, argv));
2498 }
2499
2500 /*
2501  * zfs share -a [nfs | iscsi]
2502  * zfs share filesystem
2503  *
2504  * Share all filesystems, or share the given filesystem.
2505  */
2506 static int
2507 zfs_do_share(int argc, char **argv)
2508 {
2509         return (share_mount(OP_SHARE, argc, argv));
2510 }
2511
2512 typedef struct unshare_unmount_node {
2513         zfs_handle_t    *un_zhp;
2514         char            *un_mountp;
2515         uu_avl_node_t   un_avlnode;
2516 } unshare_unmount_node_t;
2517
2518 /* ARGSUSED */
2519 static int
2520 unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
2521 {
2522         const unshare_unmount_node_t *l = larg;
2523         const unshare_unmount_node_t *r = rarg;
2524
2525         return (strcmp(l->un_mountp, r->un_mountp));
2526 }
2527
2528 /*
2529  * Convenience routine used by zfs_do_umount() and manual_unmount().  Given an
2530  * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem,
2531  * and unmount it appropriately.
2532  */
2533 static int
2534 unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
2535 {
2536         zfs_handle_t *zhp;
2537         int ret;
2538         struct mnttab search = { 0 }, entry;
2539         const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount";
2540         char property[ZFS_MAXPROPLEN];
2541
2542         /*
2543          * Search for the given (major,minor) pair in the mount table.
2544          */
2545         search.mnt_mountp = path;
2546         rewind(mnttab_file);
2547         if (getmntany(mnttab_file, &entry, &search) != 0) {
2548                 (void) fprintf(stderr, gettext("cannot %s '%s': not "
2549                     "currently mounted\n"), cmdname, path);
2550                 return (1);
2551         }
2552
2553         if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
2554                 (void) fprintf(stderr, gettext("cannot %s '%s': not a ZFS "
2555                     "filesystem\n"), cmdname, path);
2556                 return (1);
2557         }
2558
2559         if ((zhp = zfs_open(g_zfs, entry.mnt_special,
2560             ZFS_TYPE_FILESYSTEM)) == NULL)
2561                 return (1);
2562
2563         verify(zfs_prop_get(zhp, op == OP_SHARE ?
2564             ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
2565             sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
2566
2567         if (op == OP_SHARE) {
2568                 if (strcmp(property, "off") == 0) {
2569                         (void) fprintf(stderr, gettext("cannot unshare "
2570                             "'%s': legacy share\n"), path);
2571                         (void) fprintf(stderr, gettext("use "
2572                             "unshare(1M) to unshare this filesystem\n"));
2573                         ret = 1;
2574                 } else if (!zfs_is_shared_nfs(zhp, NULL)) {
2575                         (void) fprintf(stderr, gettext("cannot unshare '%s': "
2576                             "not currently shared\n"), path);
2577                         ret = 1;
2578                 } else {
2579                         ret = zfs_unshareall_nfs(zhp);
2580                 }
2581         } else {
2582                 if (is_manual) {
2583                         ret = zfs_unmount(zhp, NULL, flags);
2584                 } else if (strcmp(property, "legacy") == 0) {
2585                         (void) fprintf(stderr, gettext("cannot unmount "
2586                             "'%s': legacy mountpoint\n"),
2587                             zfs_get_name(zhp));
2588                         (void) fprintf(stderr, gettext("use umount(1M) "
2589                             "to unmount this filesystem\n"));
2590                         ret = 1;
2591                 } else {
2592                         ret = zfs_unmountall(zhp, flags);
2593                 }
2594         }
2595
2596         zfs_close(zhp);
2597
2598         return (ret != 0);
2599 }
2600
2601 /*
2602  * Generic callback for unsharing or unmounting a filesystem.
2603  */
2604 static int
2605 unshare_unmount(int op, int argc, char **argv)
2606 {
2607         int do_all = 0;
2608         int flags = 0;
2609         int ret = 0;
2610         int types, c;
2611         zfs_handle_t *zhp;
2612         char property[ZFS_MAXPROPLEN];
2613
2614         /* check options */
2615         while ((c = getopt(argc, argv, op == OP_SHARE ? "a" : "af")) != -1) {
2616                 switch (c) {
2617                 case 'a':
2618                         do_all = 1;
2619                         break;
2620                 case 'f':
2621                         flags = MS_FORCE;
2622                         break;
2623                 case '?':
2624                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2625                             optopt);
2626                         usage(B_FALSE);
2627                 }
2628         }
2629
2630         argc -= optind;
2631         argv += optind;
2632
2633         if (do_all) {
2634                 /*
2635                  * We could make use of zfs_for_each() to walk all datasets in
2636                  * the system, but this would be very inefficient, especially
2637                  * since we would have to linearly search /etc/mnttab for each
2638                  * one.  Instead, do one pass through /etc/mnttab looking for
2639                  * zfs entries and call zfs_unmount() for each one.
2640                  *
2641                  * Things get a little tricky if the administrator has created
2642                  * mountpoints beneath other ZFS filesystems.  In this case, we
2643                  * have to unmount the deepest filesystems first.  To accomplish
2644                  * this, we place all the mountpoints in an AVL tree sorted by
2645                  * the special type (dataset name), and walk the result in
2646                  * reverse to make sure to get any snapshots first.
2647                  */
2648                 uu_avl_pool_t *pool;
2649                 uu_avl_t *tree;
2650                 unshare_unmount_node_t *node;
2651                 uu_avl_index_t idx;
2652                 uu_avl_walk_t *walk;
2653                 struct statfs *sfs;
2654                 int i, n;
2655
2656                 if (argc != 0) {
2657                         (void) fprintf(stderr, gettext("too many arguments\n"));
2658                         usage(B_FALSE);
2659                 }
2660
2661                 if ((pool = uu_avl_pool_create("unmount_pool",
2662                     sizeof (unshare_unmount_node_t),
2663                     offsetof(unshare_unmount_node_t, un_avlnode),
2664                     unshare_unmount_compare,
2665                     UU_DEFAULT)) == NULL) {
2666                         (void) fprintf(stderr, gettext("internal error: "
2667                             "out of memory\n"));
2668                         exit(1);
2669                 }
2670
2671                 if ((tree = uu_avl_create(pool, NULL, UU_DEFAULT)) == NULL) {
2672                         (void) fprintf(stderr, gettext("internal error: "
2673                             "out of memory\n"));
2674                         exit(1);
2675                 }
2676
2677                 if ((n = getmntinfo(&sfs, MNT_WAIT)) == 0) {
2678                         (void) fprintf(stderr, gettext("internal error: "
2679                             "getmntinfo() failed\n"));
2680                         exit(1);
2681                 }
2682                 for (i = 0; i < n; i++) {
2683
2684                         /* ignore non-ZFS entries */
2685                         if (strcmp(sfs[i].f_fstypename, MNTTYPE_ZFS) != 0)
2686                                 continue;
2687
2688                         /* ignore snapshots */
2689                         if (strchr(sfs[i].f_mntfromname, '@') != NULL)
2690                                 continue;
2691
2692                         if ((zhp = zfs_open(g_zfs, sfs[i].f_mntfromname,
2693                             ZFS_TYPE_FILESYSTEM)) == NULL) {
2694                                 ret = 1;
2695                                 continue;
2696                         }
2697
2698                         verify(zfs_prop_get(zhp, op == OP_SHARE ?
2699                             ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT,
2700                             property, sizeof (property), NULL, NULL,
2701                             0, B_FALSE) == 0);
2702
2703                         /* Ignore legacy mounts and shares */
2704                         if ((op == OP_SHARE &&
2705                             strcmp(property, "off") == 0) ||
2706                             (op == OP_MOUNT &&
2707                             strcmp(property, "legacy") == 0)) {
2708                                 zfs_close(zhp);
2709                                 continue;
2710                         }
2711
2712                         node = safe_malloc(sizeof (unshare_unmount_node_t));
2713                         node->un_zhp = zhp;
2714
2715                         if ((node->un_mountp = strdup(sfs[i].f_mntonname)) ==
2716                             NULL) {
2717                                 (void) fprintf(stderr, gettext("internal error:"
2718                                     " out of memory\n"));
2719                                 exit(1);
2720                         }
2721
2722                         uu_avl_node_init(node, &node->un_avlnode, pool);
2723
2724                         if (uu_avl_find(tree, node, NULL, &idx) == NULL) {
2725                                 uu_avl_insert(tree, node, idx);
2726                         } else {
2727                                 zfs_close(node->un_zhp);
2728                                 free(node->un_mountp);
2729                                 free(node);
2730                         }
2731                 }
2732
2733                 /*
2734                  * Walk the AVL tree in reverse, unmounting each filesystem and
2735                  * removing it from the AVL tree in the process.
2736                  */
2737                 if ((walk = uu_avl_walk_start(tree,
2738                     UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL) {
2739                         (void) fprintf(stderr,
2740                             gettext("internal error: out of memory"));
2741                         exit(1);
2742                 }
2743
2744                 while ((node = uu_avl_walk_next(walk)) != NULL) {
2745                         uu_avl_remove(tree, node);
2746
2747                         switch (op) {
2748                         case OP_SHARE:
2749                                 if (zfs_unshare_nfs(node->un_zhp,
2750                                     node->un_mountp) != 0)
2751                                         ret = 1;
2752                                 break;
2753
2754                         case OP_MOUNT:
2755                                 if (zfs_unmount(node->un_zhp,
2756                                     node->un_mountp, flags) != 0)
2757                                         ret = 1;
2758                                 break;
2759                         }
2760
2761                         zfs_close(node->un_zhp);
2762                         free(node->un_mountp);
2763                         free(node);
2764                 }
2765
2766                 uu_avl_walk_end(walk);
2767                 uu_avl_destroy(tree);
2768                 uu_avl_pool_destroy(pool);
2769
2770                 if (op == OP_SHARE) {
2771                         /*
2772                          * Finally, unshare any volumes shared via iSCSI.
2773                          */
2774                         zfs_handle_t **dslist = NULL;
2775                         size_t i, count = 0;
2776
2777                         get_all_datasets(ZFS_TYPE_VOLUME, &dslist, &count);
2778
2779                         if (count != 0) {
2780                                 qsort(dslist, count, sizeof (void *),
2781                                     dataset_cmp);
2782
2783                                 for (i = 0; i < count; i++) {
2784                                         if (zfs_unshare_iscsi(dslist[i]) != 0)
2785                                                 ret = 1;
2786                                         zfs_close(dslist[i]);
2787                                 }
2788
2789                                 free(dslist);
2790                         }
2791                 }
2792         } else {
2793                 if (argc != 1) {
2794                         if (argc == 0)
2795                                 (void) fprintf(stderr,
2796                                     gettext("missing filesystem argument\n"));
2797                         else
2798                                 (void) fprintf(stderr,
2799                                     gettext("too many arguments\n"));
2800                         usage(B_FALSE);
2801                 }
2802
2803                 /*
2804                  * We have an argument, but it may be a full path or a ZFS
2805                  * filesystem.  Pass full paths off to unmount_path() (shared by
2806                  * manual_unmount), otherwise open the filesystem and pass to
2807                  * zfs_unmount().
2808                  */
2809                 if (argv[0][0] == '/')
2810                         return (unshare_unmount_path(op, argv[0],
2811                             flags, B_FALSE));
2812
2813                 types = ZFS_TYPE_FILESYSTEM;
2814                 if (op == OP_SHARE)
2815                         types |= ZFS_TYPE_VOLUME;
2816
2817                 if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL)
2818                         return (1);
2819
2820                 if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
2821                         verify(zfs_prop_get(zhp, op == OP_SHARE ?
2822                             ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
2823                             sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
2824
2825                         switch (op) {
2826                         case OP_SHARE:
2827                                 if (strcmp(property, "off") == 0) {
2828                                         (void) fprintf(stderr, gettext("cannot "
2829                                             "unshare '%s': legacy share\n"),
2830                                             zfs_get_name(zhp));
2831                                         (void) fprintf(stderr, gettext("use "
2832                                             "unshare(1M) to unshare this "
2833                                             "filesystem\n"));
2834                                         ret = 1;
2835                                 } else if (!zfs_is_shared_nfs(zhp, NULL)) {
2836                                         (void) fprintf(stderr, gettext("cannot "
2837                                             "unshare '%s': not currently "
2838                                             "shared\n"), zfs_get_name(zhp));
2839                                         ret = 1;
2840                                 } else if (zfs_unshareall_nfs(zhp) != 0) {
2841                                         ret = 1;
2842                                 }
2843                                 break;
2844
2845                         case OP_MOUNT:
2846                                 if (strcmp(property, "legacy") == 0) {
2847                                         (void) fprintf(stderr, gettext("cannot "
2848                                             "unmount '%s': legacy "
2849                                             "mountpoint\n"), zfs_get_name(zhp));
2850                                         (void) fprintf(stderr, gettext("use "
2851                                             "umount(1M) to unmount this "
2852                                             "filesystem\n"));
2853                                         ret = 1;
2854                                 } else if (!zfs_is_mounted(zhp, NULL)) {
2855                                         (void) fprintf(stderr, gettext("cannot "
2856                                             "unmount '%s': not currently "
2857                                             "mounted\n"),
2858                                             zfs_get_name(zhp));
2859                                         ret = 1;
2860                                 } else if (zfs_unmountall(zhp, flags) != 0) {
2861                                         ret = 1;
2862                                 }
2863                                 break;
2864                         }
2865                 } else {
2866                         assert(op == OP_SHARE);
2867
2868                         verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, property,
2869                             sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
2870
2871                         if (strcmp(property, "off") == 0) {
2872                                 (void) fprintf(stderr, gettext("cannot unshare "
2873                                     "'%s': 'shareiscsi' property not set\n"),
2874                                     zfs_get_name(zhp));
2875                                 (void) fprintf(stderr, gettext("set "
2876                                     "'shareiscsi' property or use "
2877                                     "iscsitadm(1M) to share this volume\n"));
2878                                 ret = 1;
2879                         } else if (!zfs_is_shared_iscsi(zhp)) {
2880                                 (void) fprintf(stderr, gettext("cannot "
2881                                     "unshare '%s': not currently shared\n"),
2882                                     zfs_get_name(zhp));
2883                                 ret = 1;
2884                         } else if (zfs_unshare_iscsi(zhp) != 0) {
2885                                 ret = 1;
2886                         }
2887                 }
2888
2889                 zfs_close(zhp);
2890         }
2891
2892         return (ret);
2893 }
2894
2895 /*
2896  * zfs unmount -a
2897  * zfs unmount filesystem
2898  *
2899  * Unmount all filesystems, or a specific ZFS filesystem.
2900  */
2901 static int
2902 zfs_do_unmount(int argc, char **argv)
2903 {
2904         return (unshare_unmount(OP_MOUNT, argc, argv));
2905 }
2906
2907 /*
2908  * zfs unshare -a
2909  * zfs unshare filesystem
2910  *
2911  * Unshare all filesystems, or a specific ZFS filesystem.
2912  */
2913 static int
2914 zfs_do_unshare(int argc, char **argv)
2915 {
2916         return (unshare_unmount(OP_SHARE, argc, argv));
2917 }
2918
2919 /*
2920  * Attach/detach the given dataset to/from the given jail
2921  */
2922 /* ARGSUSED */
2923 static int
2924 do_jail(int argc, char **argv, int attach)
2925 {
2926         zfs_handle_t *zhp;
2927         int jailid, ret;
2928
2929         /* check number of arguments */
2930         if (argc < 3) {
2931                 (void) fprintf(stderr, gettext("missing argument(s)\n"));
2932                 usage(B_FALSE);
2933         }
2934         if (argc > 3) {
2935                 (void) fprintf(stderr, gettext("too many arguments\n"));
2936                 usage(B_FALSE);
2937         }
2938
2939         jailid = atoi(argv[1]);
2940         if (jailid == 0) {
2941                 (void) fprintf(stderr, gettext("invalid jailid\n"));
2942                 usage(B_FALSE);
2943         }
2944
2945         zhp = zfs_open(g_zfs, argv[2], ZFS_TYPE_FILESYSTEM);
2946         if (zhp == NULL)
2947                 return (1);
2948
2949         ret = (zfs_jail(zhp, jailid, attach) != 0);
2950
2951         if (!ret)
2952                 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
2953
2954         zfs_close(zhp);
2955         return (ret);
2956 }
2957
2958 /*
2959  * zfs jail jailid filesystem
2960  *
2961  * Attach the given dataset to the given jail
2962  */
2963 /* ARGSUSED */
2964 static int
2965 zfs_do_jail(int argc, char **argv)
2966 {
2967
2968         return (do_jail(argc, argv, 1));
2969 }
2970
2971 /*
2972  * zfs unjail jailid filesystem
2973  *
2974  * Detach the given dataset from the given jail
2975  */
2976 /* ARGSUSED */
2977 static int
2978 zfs_do_unjail(int argc, char **argv)
2979 {
2980
2981         return (do_jail(argc, argv, 0));
2982 }
2983
2984 /*
2985  * Called when invoked as /etc/fs/zfs/mount.  Do the mount if the mountpoint is
2986  * 'legacy'.  Otherwise, complain that use should be using 'zfs mount'.
2987  */
2988 static int
2989 manual_mount(int argc, char **argv)
2990 {
2991         zfs_handle_t *zhp;
2992         char mountpoint[ZFS_MAXPROPLEN];
2993         char mntopts[MNT_LINE_MAX] = { '\0' };
2994         int ret;
2995         int c;
2996         int flags = 0;
2997         char *dataset, *path;
2998
2999         /* check options */
3000         while ((c = getopt(argc, argv, ":mo:O")) != -1) {
3001                 switch (c) {
3002                 case 'o':
3003                         (void) strlcpy(mntopts, optarg, sizeof (mntopts));
3004                         break;
3005                 case 'O':
3006 #if 0   /* FreeBSD: No support for MS_OVERLAY. */
3007                         flags |= MS_OVERLAY;
3008 #endif
3009                         break;
3010                 case 'm':
3011 #if 0   /* FreeBSD: No support for MS_NOMNTTAB. */
3012                         flags |= MS_NOMNTTAB;
3013 #endif
3014                         break;
3015                 case ':':
3016                         (void) fprintf(stderr, gettext("missing argument for "
3017                             "'%c' option\n"), optopt);
3018                         usage(B_FALSE);
3019                         break;
3020                 case '?':
3021                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3022                             optopt);
3023                         (void) fprintf(stderr, gettext("usage: mount [-o opts] "
3024                             "<path>\n"));
3025                         return (2);
3026                 }
3027         }
3028
3029         argc -= optind;
3030         argv += optind;
3031
3032         /* check that we only have two arguments */
3033         if (argc != 2) {
3034                 if (argc == 0)
3035                         (void) fprintf(stderr, gettext("missing dataset "
3036                             "argument\n"));
3037                 else if (argc == 1)
3038                         (void) fprintf(stderr,
3039                             gettext("missing mountpoint argument\n"));
3040                 else
3041                         (void) fprintf(stderr, gettext("too many arguments\n"));
3042                 (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n");
3043                 return (2);
3044         }
3045
3046         dataset = argv[0];
3047         path = argv[1];
3048
3049         /* try to open the dataset */
3050         if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL)
3051                 return (1);
3052
3053         (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3054             sizeof (mountpoint), NULL, NULL, 0, B_FALSE);
3055
3056         /* check for legacy mountpoint and complain appropriately */
3057         ret = 0;
3058         if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
3059                 if (zmount(dataset, path, flags, MNTTYPE_ZFS,
3060                     NULL, 0, mntopts, sizeof (mntopts)) != 0) {
3061                         (void) fprintf(stderr, gettext("mount failed: %s\n"),
3062                             strerror(errno));
3063                         ret = 1;
3064                 }
3065         } else {
3066                 (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
3067                     "mounted using 'mount -F zfs'\n"), dataset);
3068                 (void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' "
3069                     "instead.\n"), path);
3070                 (void) fprintf(stderr, gettext("If you must use 'mount -F zfs' "
3071                     "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n"));
3072                 (void) fprintf(stderr, gettext("See zfs(1M) for more "
3073                     "information.\n"));
3074                 ret = 1;
3075         }
3076
3077         return (ret);
3078 }
3079
3080 /*
3081  * Called when invoked as /etc/fs/zfs/umount.  Unlike a manual mount, we allow
3082  * unmounts of non-legacy filesystems, as this is the dominant administrative
3083  * interface.
3084  */
3085 static int
3086 manual_unmount(int argc, char **argv)
3087 {
3088         int flags = 0;
3089         int c;
3090
3091         /* check options */
3092         while ((c = getopt(argc, argv, "f")) != -1) {
3093                 switch (c) {
3094                 case 'f':
3095                         flags = MS_FORCE;
3096                         break;
3097                 case '?':
3098                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3099                             optopt);
3100                         (void) fprintf(stderr, gettext("usage: unmount [-f] "
3101                             "<path>\n"));
3102                         return (2);
3103                 }
3104         }
3105
3106         argc -= optind;
3107         argv += optind;
3108
3109         /* check arguments */
3110         if (argc != 1) {
3111                 if (argc == 0)
3112                         (void) fprintf(stderr, gettext("missing path "
3113                             "argument\n"));
3114                 else
3115                         (void) fprintf(stderr, gettext("too many arguments\n"));
3116                 (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
3117                 return (2);
3118         }
3119
3120         return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
3121 }
3122
3123 static int
3124 volcheck(zpool_handle_t *zhp, void *data)
3125 {
3126         boolean_t isinit = *((boolean_t *)data);
3127
3128         if (isinit)
3129                 return (zpool_create_zvol_links(zhp));
3130         else
3131                 return (zpool_remove_zvol_links(zhp));
3132 }
3133
3134 /*
3135  * Iterate over all pools in the system and either create or destroy /dev/zvol
3136  * links, depending on the value of 'isinit'.
3137  */
3138 static int
3139 do_volcheck(boolean_t isinit)
3140 {
3141         return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0);
3142 }
3143
3144 int
3145 main(int argc, char **argv)
3146 {
3147         int ret;
3148         int i;
3149         char *progname;
3150         char *cmdname;
3151
3152         (void) setlocale(LC_ALL, "");
3153         (void) textdomain(TEXT_DOMAIN);
3154
3155         opterr = 0;
3156
3157         if ((g_zfs = libzfs_init()) == NULL) {
3158                 (void) fprintf(stderr, gettext("internal error: failed to "
3159                     "initialize ZFS library\n"));
3160                 return (1);
3161         }
3162
3163         libzfs_print_on_error(g_zfs, B_TRUE);
3164
3165         if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
3166                 (void) fprintf(stderr, gettext("internal error: unable to "
3167                     "open %s\n"), MNTTAB);
3168                 return (1);
3169         }
3170
3171         /*
3172          * This command also doubles as the /etc/fs mount and unmount program.
3173          * Determine if we should take this behavior based on argv[0].
3174          */
3175         progname = basename(argv[0]);
3176         if (strcmp(progname, "mount") == 0) {
3177                 ret = manual_mount(argc, argv);
3178         } else if (strcmp(progname, "umount") == 0) {
3179                 ret = manual_unmount(argc, argv);
3180         } else {
3181                 /*
3182                  * Make sure the user has specified some command.
3183                  */
3184                 if (argc < 2) {
3185                         (void) fprintf(stderr, gettext("missing command\n"));
3186                         usage(B_FALSE);
3187                 }
3188
3189                 cmdname = argv[1];
3190
3191                 /*
3192                  * The 'umount' command is an alias for 'unmount'
3193                  */
3194                 if (strcmp(cmdname, "umount") == 0)
3195                         cmdname = "unmount";
3196
3197                 /*
3198                  * The 'recv' command is an alias for 'receive'
3199                  */
3200                 if (strcmp(cmdname, "recv") == 0)
3201                         cmdname = "receive";
3202
3203                 /*
3204                  * Special case '-?'
3205                  */
3206                 if (strcmp(cmdname, "-?") == 0)
3207                         usage(B_TRUE);
3208
3209                 /*
3210                  * 'volinit' and 'volfini' do not appear in the usage message,
3211                  * so we have to special case them here.
3212                  */
3213                 if (strcmp(cmdname, "volinit") == 0)
3214                         return (do_volcheck(B_TRUE));
3215                 else if (strcmp(cmdname, "volfini") == 0)
3216                         return (do_volcheck(B_FALSE));
3217
3218                 /*
3219                  * Run the appropriate command.
3220                  */
3221                 for (i = 0; i < NCOMMAND; i++) {
3222                         if (command_table[i].name == NULL)
3223                                 continue;
3224
3225                         if (strcmp(cmdname, command_table[i].name) == 0) {
3226                                 current_command = &command_table[i];
3227                                 ret = command_table[i].func(argc - 1, argv + 1);
3228                                 break;
3229                         }
3230                 }
3231
3232                 if (i == NCOMMAND) {
3233                         (void) fprintf(stderr, gettext("unrecognized "
3234                             "command '%s'\n"), cmdname);
3235                         usage(B_FALSE);
3236                 }
3237         }
3238
3239         (void) fclose(mnttab_file);
3240
3241         libzfs_fini(g_zfs);
3242
3243         /*
3244          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3245          * for the purposes of running ::findleaks.
3246          */
3247         if (getenv("ZFS_ABORT") != NULL) {
3248                 (void) printf("dumping core by request\n");
3249                 abort();
3250         }
3251
3252         return (ret);
3253 }