11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
25 * Copyright 2012 Milan Jurik. All rights reserved.
26 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
29 * Copyright (c) 2014 Integros [integros.com]
30 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
31 * Copyright 2016 Nexenta Systems, Inc.
32 */
33
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <getopt.h>
38 #include <libgen.h>
39 #include <libintl.h>
40 #include <libuutil.h>
41 #include <libnvpair.h>
42 #include <locale.h>
43 #include <stddef.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <strings.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <zone.h>
50 #include <grp.h>
51 #include <pwd.h>
90 static int zfs_do_mount(int argc, char **argv);
91 static int zfs_do_rename(int argc, char **argv);
92 static int zfs_do_rollback(int argc, char **argv);
93 static int zfs_do_set(int argc, char **argv);
94 static int zfs_do_upgrade(int argc, char **argv);
95 static int zfs_do_snapshot(int argc, char **argv);
96 static int zfs_do_unmount(int argc, char **argv);
97 static int zfs_do_share(int argc, char **argv);
98 static int zfs_do_unshare(int argc, char **argv);
99 static int zfs_do_send(int argc, char **argv);
100 static int zfs_do_receive(int argc, char **argv);
101 static int zfs_do_promote(int argc, char **argv);
102 static int zfs_do_userspace(int argc, char **argv);
103 static int zfs_do_allow(int argc, char **argv);
104 static int zfs_do_unallow(int argc, char **argv);
105 static int zfs_do_hold(int argc, char **argv);
106 static int zfs_do_holds(int argc, char **argv);
107 static int zfs_do_release(int argc, char **argv);
108 static int zfs_do_diff(int argc, char **argv);
109 static int zfs_do_bookmark(int argc, char **argv);
110 static int zfs_do_remap(int argc, char **argv);
111 static int zfs_do_channel_program(int argc, char **argv);
112
113 /*
114 * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
115 */
116
117 #ifdef DEBUG
118 const char *
119 _umem_debug_init(void)
120 {
121 return ("default,verbose"); /* $UMEM_DEBUG setting */
122 }
123
124 const char *
125 _umem_logging_init(void)
126 {
127 return ("fail,contents"); /* $UMEM_LOGGING setting */
128 }
129 #endif
130
138 HELP_LIST,
139 HELP_MOUNT,
140 HELP_PROMOTE,
141 HELP_RECEIVE,
142 HELP_RENAME,
143 HELP_ROLLBACK,
144 HELP_SEND,
145 HELP_SET,
146 HELP_SHARE,
147 HELP_SNAPSHOT,
148 HELP_UNMOUNT,
149 HELP_UNSHARE,
150 HELP_ALLOW,
151 HELP_UNALLOW,
152 HELP_USERSPACE,
153 HELP_GROUPSPACE,
154 HELP_HOLD,
155 HELP_HOLDS,
156 HELP_RELEASE,
157 HELP_DIFF,
158 HELP_REMAP,
159 HELP_BOOKMARK,
160 HELP_CHANNEL_PROGRAM,
161 } zfs_help_t;
162
163 typedef struct zfs_command {
164 const char *name;
165 int (*func)(int argc, char **argv);
166 zfs_help_t usage;
167 } zfs_command_t;
168
169 /*
170 * Master command table. Each ZFS command has a name, associated function, and
171 * usage message. The usage messages need to be internationalized, so we have
172 * to have a function to return the usage message based on a command index.
173 *
174 * These commands are organized according to how they are displayed in the usage
175 * message. An empty command (one with a NULL name) indicates an empty line in
176 * the generic usage message.
177 */
178 static zfs_command_t command_table[] = {
195 { "upgrade", zfs_do_upgrade, HELP_UPGRADE },
196 { "userspace", zfs_do_userspace, HELP_USERSPACE },
197 { "groupspace", zfs_do_userspace, HELP_GROUPSPACE },
198 { NULL },
199 { "mount", zfs_do_mount, HELP_MOUNT },
200 { "unmount", zfs_do_unmount, HELP_UNMOUNT },
201 { "share", zfs_do_share, HELP_SHARE },
202 { "unshare", zfs_do_unshare, HELP_UNSHARE },
203 { NULL },
204 { "send", zfs_do_send, HELP_SEND },
205 { "receive", zfs_do_receive, HELP_RECEIVE },
206 { NULL },
207 { "allow", zfs_do_allow, HELP_ALLOW },
208 { NULL },
209 { "unallow", zfs_do_unallow, HELP_UNALLOW },
210 { NULL },
211 { "hold", zfs_do_hold, HELP_HOLD },
212 { "holds", zfs_do_holds, HELP_HOLDS },
213 { "release", zfs_do_release, HELP_RELEASE },
214 { "diff", zfs_do_diff, HELP_DIFF },
215 { "remap", zfs_do_remap, HELP_REMAP },
216 };
217
218 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
219
220 zfs_command_t *current_command;
221
222 static const char *
223 get_usage(zfs_help_t idx)
224 {
225 switch (idx) {
226 case HELP_CLONE:
227 return (gettext("\tclone [-p] [-o property=value] ... "
228 "<snapshot> <filesystem|volume>\n"));
229 case HELP_CREATE:
230 return (gettext("\tcreate [-p] [-o property=value] ... "
231 "<filesystem>\n"
232 "\tcreate [-ps] [-b blocksize] [-o property=value] ... "
233 "-V <size> <volume>\n"));
234 case HELP_DESTROY:
235 return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
236 "\tdestroy [-dnpRrv] "
237 "<filesystem|volume>@<snap>[%<snap>][,...]\n"
238 "\tdestroy <filesystem|volume>#<bookmark>\n"));
239 case HELP_GET:
240 return (gettext("\tget [-rHp] [-d max] "
241 "[-o \"all\" | field[,...]]\n"
242 "\t [-t type[,...]] [-s source[,...]]\n"
243 "\t <\"all\" | property[,...]> "
244 "[filesystem|volume|snapshot|bookmark] ...\n"));
245 case HELP_INHERIT:
246 return (gettext("\tinherit [-rS] <property> "
247 "<filesystem|volume|snapshot> ...\n"));
248 case HELP_UPGRADE:
249 return (gettext("\tupgrade [-v]\n"
250 "\tupgrade [-r] [-V version] <-a | filesystem ...>\n"));
251 case HELP_LIST:
252 return (gettext("\tlist [-Hp] [-r|-d max] [-o property[,...]] "
253 "[-s property]...\n\t [-S property]... [-t type[,...]] "
254 "[filesystem|volume|snapshot] ...\n"));
255 case HELP_MOUNT:
256 return (gettext("\tmount\n"
257 "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
258 case HELP_PROMOTE:
259 return (gettext("\tpromote <clone-filesystem>\n"));
260 case HELP_RECEIVE:
261 return (gettext("\treceive [-vnsFu] <filesystem|volume|"
262 "snapshot>\n"
263 "\treceive [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
264 "<filesystem>\n"
265 "\treceive -A <filesystem|volume>\n"));
266 case HELP_RENAME:
267 return (gettext("\trename [-f] <filesystem|volume|snapshot> "
268 "<filesystem|volume|snapshot>\n"
269 "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
270 "\trename -r <snapshot> <snapshot>\n"));
271 case HELP_ROLLBACK:
272 return (gettext("\trollback [-rRf] <snapshot>\n"));
273 case HELP_SEND:
274 return (gettext("\tsend [-DnPpRvLec] [-[iI] snapshot] "
275 "<snapshot>\n"
276 "\tsend [-Le] [-i snapshot|bookmark] "
277 "<filesystem|volume|snapshot>\n"
278 "\tsend [-nvPe] -t <receive_resume_token>\n"));
279 case HELP_SET:
280 return (gettext("\tset <property=value> ... "
281 "<filesystem|volume|snapshot> ...\n"));
282 case HELP_SHARE:
283 return (gettext("\tshare <-a | filesystem>\n"));
284 case HELP_SNAPSHOT:
285 return (gettext("\tsnapshot [-r] [-o property=value] ... "
286 "<filesystem|volume>@<snap> ...\n"));
287 case HELP_UNMOUNT:
288 return (gettext("\tunmount [-f] "
289 "<-a | filesystem|mountpoint>\n"));
290 case HELP_UNSHARE:
291 return (gettext("\tunshare "
292 "<-a | filesystem|mountpoint>\n"));
293 case HELP_ALLOW:
294 return (gettext("\tallow <filesystem|volume>\n"
312 "<filesystem|volume>\n"));
313 case HELP_USERSPACE:
314 return (gettext("\tuserspace [-Hinp] [-o field[,...]] "
315 "[-s field] ...\n"
316 "\t [-S field] ... [-t type[,...]] "
317 "<filesystem|snapshot>\n"));
318 case HELP_GROUPSPACE:
319 return (gettext("\tgroupspace [-Hinp] [-o field[,...]] "
320 "[-s field] ...\n"
321 "\t [-S field] ... [-t type[,...]] "
322 "<filesystem|snapshot>\n"));
323 case HELP_HOLD:
324 return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
325 case HELP_HOLDS:
326 return (gettext("\tholds [-r] <snapshot> ...\n"));
327 case HELP_RELEASE:
328 return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
329 case HELP_DIFF:
330 return (gettext("\tdiff [-FHt] <snapshot> "
331 "[snapshot|filesystem]\n"));
332 case HELP_REMAP:
333 return (gettext("\tremap <filesystem | volume>\n"));
334 case HELP_BOOKMARK:
335 return (gettext("\tbookmark <snapshot> <bookmark>\n"));
336 case HELP_CHANNEL_PROGRAM:
337 return (gettext("\tprogram [-n] [-t <instruction limit>] "
338 "[-m <memory limit (b)>] <pool> <program file> "
339 "[lua args...]\n"));
340 }
341
342 abort();
343 /* NOTREACHED */
344 }
345
346 void
347 nomem(void)
348 {
349 (void) fprintf(stderr, gettext("internal error: out of memory\n"));
350 exit(1);
351 }
352
353 /*
494 (void) fprintf(fp,
495 gettext("\nFor the property list, run: %s\n"),
496 "zfs set|get");
497 (void) fprintf(fp,
498 gettext("\nFor the delegated permission list, run: %s\n"),
499 "zfs allow|unallow");
500 }
501
502 /*
503 * See comments at end of main().
504 */
505 if (getenv("ZFS_ABORT") != NULL) {
506 (void) printf("dumping core by request\n");
507 abort();
508 }
509
510 exit(requested ? 0 : 2);
511 }
512
513 /*
514 * Take a property=value argument string and add it to the given nvlist.
515 * Modifies the argument inplace.
516 */
517 static int
518 parseprop(nvlist_t *props, char *propname)
519 {
520 char *propval, *strval;
521
522 if ((propval = strchr(propname, '=')) == NULL) {
523 (void) fprintf(stderr, gettext("missing "
524 "'=' for property=value argument\n"));
525 return (-1);
526 }
527 *propval = '\0';
528 propval++;
529 if (nvlist_lookup_string(props, propname, &strval) == 0) {
530 (void) fprintf(stderr, gettext("property '%s' "
531 "specified multiple times\n"), propname);
532 return (-1);
533 }
534 if (nvlist_add_string(props, propname, propval) != 0)
535 nomem();
536 return (0);
537 }
538
539 static int
540 parse_depth(char *opt, int *flags)
541 {
542 char *tmp;
543 int depth;
544
545 depth = (int)strtol(opt, &tmp, 0);
546 if (*tmp) {
547 (void) fprintf(stderr,
548 gettext("%s is not an integer\n"), optarg);
549 usage(B_FALSE);
550 }
551 if (depth < 0) {
552 (void) fprintf(stderr,
553 gettext("Depth can not be negative.\n"));
554 usage(B_FALSE);
555 }
556 *flags |= (ZFS_ITER_DEPTH_LIMIT|ZFS_ITER_RECURSE);
557 return (depth);
558 }
559
560 #define PROGRESS_DELAY 2 /* seconds */
561
562 static char *pt_reverse = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
563 static time_t pt_begin;
564 static char *pt_header = NULL;
565 static boolean_t pt_shown;
566
567 static void
568 start_progress_timer(void)
1059 /*
1060 * Ignore pools (which we've already flagged as an error before getting
1061 * here).
1062 */
1063 if (strchr(zfs_get_name(zhp), '/') == NULL &&
1064 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
1065 zfs_close(zhp);
1066 return (0);
1067 }
1068 if (cb->cb_dryrun) {
1069 zfs_close(zhp);
1070 return (0);
1071 }
1072
1073 /*
1074 * We batch up all contiguous snapshots (even of different
1075 * filesystems) and destroy them with one ioctl. We can't
1076 * simply do all snap deletions and then all fs deletions,
1077 * because we must delete a clone before its origin.
1078 */
1079 if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
1080 fnvlist_add_boolean(cb->cb_batchedsnaps, name);
1081 } else {
1082 int error = zfs_destroy_snaps_nvl(g_zfs,
1083 cb->cb_batchedsnaps, B_FALSE);
1084 fnvlist_free(cb->cb_batchedsnaps);
1085 cb->cb_batchedsnaps = fnvlist_alloc();
1086
1087 if (error != 0 ||
1088 zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
1089 zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
1090 zfs_close(zhp);
1091 return (-1);
1092 }
1093 }
1094
1095 zfs_close(zhp);
1096 return (0);
1097 }
1098
1099 static int
1221 boolean_t defer = cb->cb_defer_destroy;
1222 int err = 0;
1223
1224 /*
1225 * We can't defer destroy non-snapshots, so set it to
1226 * false while destroying the clones.
1227 */
1228 cb->cb_defer_destroy = B_FALSE;
1229 err = zfs_iter_dependents(zhp, B_FALSE,
1230 destroy_callback, cb);
1231 cb->cb_defer_destroy = defer;
1232 zfs_close(zhp);
1233 if (err != 0)
1234 return (err);
1235 }
1236 }
1237 return (0);
1238 }
1239
1240 static int
1241 zfs_do_destroy(int argc, char **argv)
1242 {
1243 destroy_cbdata_t cb = { 0 };
1244 int rv = 0;
1245 int err = 0;
1246 int c;
1247 zfs_handle_t *zhp = NULL;
1248 char *at, *pound;
1249 zfs_type_t type = ZFS_TYPE_DATASET;
1250
1251 /* check options */
1252 while ((c = getopt(argc, argv, "vpndfrR")) != -1) {
1253 switch (c) {
1254 case 'v':
1255 cb.cb_verbose = B_TRUE;
1256 break;
1257 case 'p':
1258 cb.cb_verbose = B_TRUE;
1259 cb.cb_parsable = B_TRUE;
1260 break;
1389
1390 nvl = fnvlist_alloc();
1391 fnvlist_add_boolean(nvl, argv[0]);
1392
1393 err = lzc_destroy_bookmarks(nvl, NULL);
1394 if (err != 0) {
1395 (void) zfs_standard_error(g_zfs, err,
1396 "cannot destroy bookmark");
1397 }
1398
1399 nvlist_free(cb.cb_nvl);
1400
1401 return (err);
1402 } else {
1403 /* Open the given dataset */
1404 if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
1405 return (1);
1406
1407 cb.cb_target = zhp;
1408
1409 /*
1410 * Perform an explicit check for pools before going any further.
1411 */
1412 if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
1413 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
1414 (void) fprintf(stderr, gettext("cannot destroy '%s': "
1415 "operation does not apply to pools\n"),
1416 zfs_get_name(zhp));
1417 (void) fprintf(stderr, gettext("use 'zfs destroy -r "
1418 "%s' to destroy all datasets in the pool\n"),
1419 zfs_get_name(zhp));
1420 (void) fprintf(stderr, gettext("use 'zpool destroy %s' "
1421 "to destroy the pool itself\n"), zfs_get_name(zhp));
1422 rv = 1;
1423 goto out;
1424 }
1425
1426 /*
1427 * Check for any dependents and/or clones.
1428 */
1429 cb.cb_first = B_TRUE;
2062 "upgraded; the pool version needs to first "
2063 "be upgraded\nto version %d\n\n"),
2064 zfs_get_name(zhp), needed_spa_version);
2065 cb->cb_numfailed++;
2066 return (0);
2067 }
2068
2069 /* upgrade */
2070 if (version < cb->cb_version) {
2071 char verstr[16];
2072 (void) snprintf(verstr, sizeof (verstr),
2073 "%llu", cb->cb_version);
2074 if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
2075 /*
2076 * If they did "zfs upgrade -a", then we could
2077 * be doing ioctls to different pools. We need
2078 * to log this history once to each pool, and bypass
2079 * the normal history logging that happens in main().
2080 */
2081 (void) zpool_log_history(g_zfs, history_str);
2082 log_history = B_FALSE;
2083 }
2084 if (zfs_prop_set(zhp, "version", verstr) == 0)
2085 cb->cb_numupgraded++;
2086 else
2087 cb->cb_numfailed++;
2088 (void) strcpy(cb->cb_lastfs, zfs_get_name(zhp));
2089 } else if (version > cb->cb_version) {
2090 /* can't downgrade */
2091 (void) printf(gettext("%s: can not be downgraded; "
2092 "it is already at version %u\n"),
2093 zfs_get_name(zhp), version);
2094 cb->cb_numfailed++;
2095 } else {
2096 cb->cb_numsamegraded++;
2097 }
2098 return (0);
2099 }
2100
2101 /*
3109 (void) fprintf(stderr,
3110 gettext("invalid property '%s'\n"), optarg);
3111 usage(B_FALSE);
3112 }
3113 break;
3114 case 'S':
3115 if (zfs_add_sort_column(&sortcol, optarg,
3116 B_TRUE) != 0) {
3117 (void) fprintf(stderr,
3118 gettext("invalid property '%s'\n"), optarg);
3119 usage(B_FALSE);
3120 }
3121 break;
3122 case 't':
3123 types = 0;
3124 types_specified = B_TRUE;
3125 flags &= ~ZFS_ITER_PROP_LISTSNAPS;
3126 while (*optarg != '\0') {
3127 static char *type_subopts[] = { "filesystem",
3128 "volume", "snapshot", "snap", "bookmark",
3129 "all", NULL };
3130
3131 switch (getsubopt(&optarg, type_subopts,
3132 &value)) {
3133 case 0:
3134 types |= ZFS_TYPE_FILESYSTEM;
3135 break;
3136 case 1:
3137 types |= ZFS_TYPE_VOLUME;
3138 break;
3139 case 2:
3140 case 3:
3141 types |= ZFS_TYPE_SNAPSHOT;
3142 break;
3143 case 4:
3144 types |= ZFS_TYPE_BOOKMARK;
3145 break;
3146 case 5:
3147 types = ZFS_TYPE_DATASET |
3148 ZFS_TYPE_BOOKMARK;
3149 break;
3150 default:
3151 (void) fprintf(stderr,
3152 gettext("invalid type '%s'\n"),
3153 value);
3154 usage(B_FALSE);
3155 }
3156 }
3157 break;
3158 case ':':
3159 (void) fprintf(stderr, gettext("missing argument for "
3160 "'%c' option\n"), optopt);
3161 usage(B_FALSE);
3162 break;
3163 case '?':
3164 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3165 optopt);
3166 usage(B_FALSE);
3167 }
3168 }
3169
3729 sendflags_t flags = { 0 };
3730 int c, err;
3731 nvlist_t *dbgnv = NULL;
3732 boolean_t extraverbose = B_FALSE;
3733
3734 struct option long_options[] = {
3735 {"replicate", no_argument, NULL, 'R'},
3736 {"props", no_argument, NULL, 'p'},
3737 {"parsable", no_argument, NULL, 'P'},
3738 {"dedup", no_argument, NULL, 'D'},
3739 {"verbose", no_argument, NULL, 'v'},
3740 {"dryrun", no_argument, NULL, 'n'},
3741 {"large-block", no_argument, NULL, 'L'},
3742 {"embed", no_argument, NULL, 'e'},
3743 {"resume", required_argument, NULL, 't'},
3744 {"compressed", no_argument, NULL, 'c'},
3745 {0, 0, 0, 0}
3746 };
3747
3748 /* check options */
3749 while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:c", long_options,
3750 NULL)) != -1) {
3751 switch (c) {
3752 case 'i':
3753 if (fromname)
3754 usage(B_FALSE);
3755 fromname = optarg;
3756 break;
3757 case 'I':
3758 if (fromname)
3759 usage(B_FALSE);
3760 fromname = optarg;
3761 flags.doall = B_TRUE;
3762 break;
3763 case 'R':
3764 flags.replicate = B_TRUE;
3765 break;
3766 case 'p':
3767 flags.props = B_TRUE;
3768 break;
3769 case 'P':
3771 flags.verbose = B_TRUE;
3772 break;
3773 case 'v':
3774 if (flags.verbose)
3775 extraverbose = B_TRUE;
3776 flags.verbose = B_TRUE;
3777 flags.progress = B_TRUE;
3778 break;
3779 case 'D':
3780 flags.dedup = B_TRUE;
3781 break;
3782 case 'n':
3783 flags.dryrun = B_TRUE;
3784 break;
3785 case 'L':
3786 flags.largeblock = B_TRUE;
3787 break;
3788 case 'e':
3789 flags.embed_data = B_TRUE;
3790 break;
3791 case 't':
3792 resume_token = optarg;
3793 break;
3794 case 'c':
3795 flags.compress = B_TRUE;
3796 break;
3797 case ':':
3798 /*
3799 * If a parameter was not passed, optopt contains the
3800 * value that would normally lead us into the
3801 * appropriate case statement. If it's > 256, then this
3802 * must be a longopt and we should look at argv to get
3803 * the string. Otherwise it's just the character, so we
3804 * should use it directly.
3805 */
3806 if (optopt <= UINT8_MAX) {
3807 (void) fprintf(stderr,
3808 gettext("missing argument for '%c' "
3809 "option\n"), optopt);
3810 } else {
3845 gettext("invalid flags combined with -t\n"));
3846 usage(B_FALSE);
3847 }
3848 if (argc != 0) {
3849 (void) fprintf(stderr, gettext("no additional "
3850 "arguments are permitted with -t\n"));
3851 usage(B_FALSE);
3852 }
3853 } else {
3854 if (argc < 1) {
3855 (void) fprintf(stderr,
3856 gettext("missing snapshot argument\n"));
3857 usage(B_FALSE);
3858 }
3859 if (argc > 1) {
3860 (void) fprintf(stderr, gettext("too many arguments\n"));
3861 usage(B_FALSE);
3862 }
3863 }
3864
3865 if (!flags.dryrun && isatty(STDOUT_FILENO)) {
3866 (void) fprintf(stderr,
3867 gettext("Error: Stream can not be written to a terminal.\n"
3868 "You must redirect standard output.\n"));
3869 return (1);
3870 }
3871
3872 if (resume_token != NULL) {
3873 return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
3874 resume_token));
3875 }
3876
3877 /*
3878 * Special case sending a filesystem, or from a bookmark.
3879 */
3880 if (strchr(argv[0], '@') == NULL ||
3881 (fromname && strchr(fromname, '#') != NULL)) {
3882 char frombuf[ZFS_MAX_DATASET_NAME_LEN];
3883 enum lzc_send_flags lzc_flags = 0;
3884
3885 if (flags.replicate || flags.doall || flags.props ||
3970 * dump_nvlist prints to stdout, but that's been
3971 * redirected to a file. Make it print to stderr
3972 * instead.
3973 */
3974 (void) dup2(STDERR_FILENO, STDOUT_FILENO);
3975 dump_nvlist(dbgnv, 0);
3976 nvlist_free(dbgnv);
3977 }
3978 zfs_close(zhp);
3979
3980 return (err != 0);
3981 }
3982
3983 /*
3984 * Restore a backup stream from stdin.
3985 */
3986 static int
3987 zfs_do_receive(int argc, char **argv)
3988 {
3989 int c, err = 0;
3990 recvflags_t flags = { 0 };
3991 boolean_t abort_resumable = B_FALSE;
3992
3993 nvlist_t *props;
3994 nvpair_t *nvp = NULL;
3995
3996 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
3997 nomem();
3998
3999 /* check options */
4000 while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) {
4001 switch (c) {
4002 case 'o':
4003 if (parseprop(props, optarg) != 0)
4004 return (1);
4005 break;
4006 case 'd':
4007 flags.isprefix = B_TRUE;
4008 break;
4009 case 'e':
4010 flags.isprefix = B_TRUE;
4011 flags.istail = B_TRUE;
4012 break;
4013 case 'n':
4014 flags.dryrun = B_TRUE;
4015 break;
4016 case 'u':
4017 flags.nomount = B_TRUE;
4018 break;
4019 case 'v':
4020 flags.verbose = B_TRUE;
4021 break;
4022 case 's':
4023 flags.resumable = B_TRUE;
4024 break;
4025 case 'F':
4026 flags.force = B_TRUE;
4027 break;
4028 case 'A':
4029 abort_resumable = B_TRUE;
4030 break;
4031 case ':':
4032 (void) fprintf(stderr, gettext("missing argument for "
4033 "'%c' option\n"), optopt);
4034 usage(B_FALSE);
4035 break;
4036 case '?':
4037 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4038 optopt);
4039 usage(B_FALSE);
4040 }
4041 }
4042
4043 argc -= optind;
4044 argv += optind;
4045
4046 /* check number of arguments */
4047 if (argc < 1) {
4048 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
4049 usage(B_FALSE);
4050 }
4051 if (argc > 1) {
4052 (void) fprintf(stderr, gettext("too many arguments\n"));
4053 usage(B_FALSE);
4054 }
4055
4056 while ((nvp = nvlist_next_nvpair(props, nvp))) {
4057 if (strcmp(nvpair_name(nvp), "origin") != 0) {
4058 (void) fprintf(stderr, gettext("invalid option"));
4059 usage(B_FALSE);
4060 }
4061 }
4062
4063 if (abort_resumable) {
4064 if (flags.isprefix || flags.istail || flags.dryrun ||
4065 flags.resumable || flags.nomount) {
4066 (void) fprintf(stderr, gettext("invalid option"));
4067 usage(B_FALSE);
4068 }
4069
4070 char namebuf[ZFS_MAX_DATASET_NAME_LEN];
4071 (void) snprintf(namebuf, sizeof (namebuf),
4072 "%s/%%recv", argv[0]);
4073
4074 if (zfs_dataset_exists(g_zfs, namebuf,
4075 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) {
4076 zfs_handle_t *zhp = zfs_open(g_zfs,
4077 namebuf, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
4078 if (zhp == NULL)
4079 return (1);
4080 err = zfs_destroy(zhp, B_FALSE);
4081 } else {
4082 zfs_handle_t *zhp = zfs_open(g_zfs,
4088 NULL, 0, NULL, NULL, 0, B_TRUE) == -1) {
4089 (void) fprintf(stderr,
4090 gettext("'%s' does not have any "
4091 "resumable receive state to abort\n"),
4092 argv[0]);
4093 return (1);
4094 }
4095 err = zfs_destroy(zhp, B_FALSE);
4096 }
4097
4098 return (err != 0);
4099 }
4100
4101 if (isatty(STDIN_FILENO)) {
4102 (void) fprintf(stderr,
4103 gettext("Error: Backup stream can not be read "
4104 "from a terminal.\n"
4105 "You must redirect standard input.\n"));
4106 return (1);
4107 }
4108 err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL);
4109
4110 return (err != 0);
4111 }
4112
4113 /*
4114 * allow/unallow stuff
4115 */
4116 /* copied from zfs/sys/dsl_deleg.h */
4117 #define ZFS_DELEG_PERM_CREATE "create"
4118 #define ZFS_DELEG_PERM_DESTROY "destroy"
4119 #define ZFS_DELEG_PERM_SNAPSHOT "snapshot"
4120 #define ZFS_DELEG_PERM_ROLLBACK "rollback"
4121 #define ZFS_DELEG_PERM_CLONE "clone"
4122 #define ZFS_DELEG_PERM_PROMOTE "promote"
4123 #define ZFS_DELEG_PERM_RENAME "rename"
4124 #define ZFS_DELEG_PERM_MOUNT "mount"
4125 #define ZFS_DELEG_PERM_SHARE "share"
4126 #define ZFS_DELEG_PERM_SEND "send"
4127 #define ZFS_DELEG_PERM_RECEIVE "receive"
4128 #define ZFS_DELEG_PERM_ALLOW "allow"
4129 #define ZFS_DELEG_PERM_USERPROP "userprop"
4130 #define ZFS_DELEG_PERM_VSCAN "vscan" /* ??? */
4131 #define ZFS_DELEG_PERM_USERQUOTA "userquota"
4132 #define ZFS_DELEG_PERM_GROUPQUOTA "groupquota"
4133 #define ZFS_DELEG_PERM_USERUSED "userused"
4134 #define ZFS_DELEG_PERM_GROUPUSED "groupused"
4135 #define ZFS_DELEG_PERM_HOLD "hold"
4136 #define ZFS_DELEG_PERM_RELEASE "release"
4137 #define ZFS_DELEG_PERM_DIFF "diff"
4138 #define ZFS_DELEG_PERM_BOOKMARK "bookmark"
4139 #define ZFS_DELEG_PERM_REMAP "remap"
4140
4141 #define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
4142
4143 static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
4144 { ZFS_DELEG_PERM_ALLOW, ZFS_DELEG_NOTE_ALLOW },
4145 { ZFS_DELEG_PERM_CLONE, ZFS_DELEG_NOTE_CLONE },
4146 { ZFS_DELEG_PERM_CREATE, ZFS_DELEG_NOTE_CREATE },
4147 { ZFS_DELEG_PERM_DESTROY, ZFS_DELEG_NOTE_DESTROY },
4148 { ZFS_DELEG_PERM_DIFF, ZFS_DELEG_NOTE_DIFF},
4149 { ZFS_DELEG_PERM_HOLD, ZFS_DELEG_NOTE_HOLD },
4150 { ZFS_DELEG_PERM_MOUNT, ZFS_DELEG_NOTE_MOUNT },
4151 { ZFS_DELEG_PERM_PROMOTE, ZFS_DELEG_NOTE_PROMOTE },
4152 { ZFS_DELEG_PERM_RECEIVE, ZFS_DELEG_NOTE_RECEIVE },
4153 { ZFS_DELEG_PERM_RELEASE, ZFS_DELEG_NOTE_RELEASE },
4154 { ZFS_DELEG_PERM_RENAME, ZFS_DELEG_NOTE_RENAME },
4155 { ZFS_DELEG_PERM_ROLLBACK, ZFS_DELEG_NOTE_ROLLBACK },
4156 { ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_SEND },
4157 { ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
4158 { ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
4159 { ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
4160 { ZFS_DELEG_PERM_REMAP, ZFS_DELEG_NOTE_REMAP },
4161
4162 { ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
4163 { ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
4164 { ZFS_DELEG_PERM_USERPROP, ZFS_DELEG_NOTE_USERPROP },
4165 { ZFS_DELEG_PERM_USERQUOTA, ZFS_DELEG_NOTE_USERQUOTA },
4166 { ZFS_DELEG_PERM_USERUSED, ZFS_DELEG_NOTE_USERUSED },
4167 { NULL, ZFS_DELEG_NOTE_NONE }
4168 };
4169
4170 /* permission structure */
4171 typedef struct deleg_perm {
4172 zfs_deleg_who_type_t dp_who_type;
4173 const char *dp_name;
4174 boolean_t dp_local;
4175 boolean_t dp_descend;
4176 } deleg_perm_t;
4177
4178 /* */
4179 typedef struct deleg_perm_node {
4180 deleg_perm_t dpn_perm;
5586 col = gettext(hdr_cols[i]);
5587 if (i < 2)
5588 (void) printf("%-*s ", i ? tagwidth : nwidth,
5589 col);
5590 else
5591 (void) printf("%s\n", col);
5592 }
5593 }
5594
5595 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
5596 char *zname = nvpair_name(nvp);
5597 nvlist_t *nvl2;
5598 nvpair_t *nvp2 = NULL;
5599 (void) nvpair_value_nvlist(nvp, &nvl2);
5600 while ((nvp2 = nvlist_next_nvpair(nvl2, nvp2)) != NULL) {
5601 char tsbuf[DATETIME_BUF_LEN];
5602 char *tagname = nvpair_name(nvp2);
5603 uint64_t val = 0;
5604 time_t time;
5605 struct tm t;
5606
5607 (void) nvpair_value_uint64(nvp2, &val);
5608 time = (time_t)val;
5609 (void) localtime_r(&time, &t);
5610 (void) strftime(tsbuf, DATETIME_BUF_LEN,
5611 gettext(STRFTIME_FMT_STR), &t);
5612
5613 if (scripted) {
5614 (void) printf("%s\t%s\t%s\n", zname,
5615 tagname, tsbuf);
5616 } else {
5617 (void) printf("%-*s %-*s %s\n", nwidth,
5618 zname, tagwidth, tagname, tsbuf);
5619 }
5620 }
5621 }
5622 }
5623
5624 /*
5625 * Generic callback function to list a dataset or snapshot.
5626 */
5627 static int
5628 holds_callback(zfs_handle_t *zhp, void *data)
5629 {
5630 holds_cbdata_t *cbp = data;
5631 nvlist_t *top_nvl = *cbp->cb_nvlp;
5632 nvlist_t *nvl = NULL;
5633 nvpair_t *nvp = NULL;
5634 const char *zname = zfs_get_name(zhp);
5635 size_t znamelen = strlen(zname);
5636
5637 if (cbp->cb_recursive) {
5638 const char *snapname;
5639 char *delim = strchr(zname, '@');
5640 if (delim == NULL)
5641 return (0);
6517 default:
6518 break;
6519 }
6520
6521 node = safe_malloc(sizeof (unshare_unmount_node_t));
6522 node->un_zhp = zhp;
6523 node->un_mountp = safe_strdup(entry.mnt_mountp);
6524
6525 uu_avl_node_init(node, &node->un_avlnode, pool);
6526
6527 if (uu_avl_find(tree, node, NULL, &idx) == NULL) {
6528 uu_avl_insert(tree, node, idx);
6529 } else {
6530 zfs_close(node->un_zhp);
6531 free(node->un_mountp);
6532 free(node);
6533 }
6534 }
6535
6536 /*
6537 * Walk the AVL tree in reverse, unmounting each filesystem and
6538 * removing it from the AVL tree in the process.
6539 */
6540 if ((walk = uu_avl_walk_start(tree,
6541 UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL)
6542 nomem();
6543
6544 while ((node = uu_avl_walk_next(walk)) != NULL) {
6545 uu_avl_remove(tree, node);
6546
6547 switch (op) {
6548 case OP_SHARE:
6549 if (zfs_unshareall_bypath(node->un_zhp,
6550 node->un_mountp) != 0)
6551 ret = 1;
6552 break;
6553
6554 case OP_MOUNT:
6555 if (zfs_unmount(node->un_zhp,
6556 node->un_mountp, flags) != 0)
6887 *atp = '\0';
6888
6889 if ((zhp = zfs_open(g_zfs, copy, ZFS_TYPE_FILESYSTEM)) == NULL)
6890 return (1);
6891
6892 free(copy);
6893
6894 /*
6895 * Ignore SIGPIPE so that the library can give us
6896 * information on any failure
6897 */
6898 (void) sigignore(SIGPIPE);
6899
6900 err = zfs_show_diffs(zhp, STDOUT_FILENO, fromsnap, tosnap, flags);
6901
6902 zfs_close(zhp);
6903
6904 return (err != 0);
6905 }
6906
6907 static int
6908 zfs_do_remap(int argc, char **argv)
6909 {
6910 const char *fsname;
6911 int err = 0;
6912 if (argc != 2) {
6913 (void) fprintf(stderr, gettext("wrong number of arguments\n"));
6914 usage(B_FALSE);
6915 }
6916
6917 fsname = argv[1];
6918 err = zfs_remap_indirects(g_zfs, fsname);
6919
6920 return (err);
6921 }
6922
6923 /*
6924 * zfs bookmark <fs@snap> <fs#bmark>
6925 *
6926 * Creates a bookmark with the given name from the given snapshot.
6927 */
6928 static int
6929 zfs_do_bookmark(int argc, char **argv)
6930 {
6931 char snapname[ZFS_MAX_DATASET_NAME_LEN];
6932 zfs_handle_t *zhp;
6933 nvlist_t *nvl;
6934 int ret = 0;
6935 int c;
6936
6937 /* check options */
6938 while ((c = getopt(argc, argv, "")) != -1) {
6939 switch (c) {
6940 case '?':
6941 (void) fprintf(stderr,
6942 gettext("invalid option '%c'\n"), optopt);
7222 int
7223 main(int argc, char **argv)
7224 {
7225 int ret = 0;
7226 int i;
7227 char *progname;
7228 char *cmdname;
7229
7230 (void) setlocale(LC_ALL, "");
7231 (void) textdomain(TEXT_DOMAIN);
7232
7233 opterr = 0;
7234
7235 if ((g_zfs = libzfs_init()) == NULL) {
7236 (void) fprintf(stderr, gettext("internal error: failed to "
7237 "initialize ZFS library\n"));
7238 return (1);
7239 }
7240
7241 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
7242
7243 libzfs_print_on_error(g_zfs, B_TRUE);
7244
7245 if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
7246 (void) fprintf(stderr, gettext("internal error: unable to "
7247 "open %s\n"), MNTTAB);
7248 return (1);
7249 }
7250
7251 /*
7252 * This command also doubles as the /etc/fs mount and unmount program.
7253 * Determine if we should take this behavior based on argv[0].
7254 */
7255 progname = basename(argv[0]);
7256 if (strcmp(progname, "mount") == 0) {
7257 ret = manual_mount(argc, argv);
7258 } else if (strcmp(progname, "umount") == 0) {
7259 ret = manual_unmount(argc, argv);
7260 } else {
7261 /*
|
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
25 * Copyright 2012 Milan Jurik. All rights reserved.
26 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
29 * Copyright (c) 2014 Integros [integros.com]
30 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
31 * Copyright 2018 Nexenta Systems, Inc.
32 */
33
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <getopt.h>
38 #include <libgen.h>
39 #include <libintl.h>
40 #include <libuutil.h>
41 #include <libnvpair.h>
42 #include <locale.h>
43 #include <stddef.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <strings.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <zone.h>
50 #include <grp.h>
51 #include <pwd.h>
90 static int zfs_do_mount(int argc, char **argv);
91 static int zfs_do_rename(int argc, char **argv);
92 static int zfs_do_rollback(int argc, char **argv);
93 static int zfs_do_set(int argc, char **argv);
94 static int zfs_do_upgrade(int argc, char **argv);
95 static int zfs_do_snapshot(int argc, char **argv);
96 static int zfs_do_unmount(int argc, char **argv);
97 static int zfs_do_share(int argc, char **argv);
98 static int zfs_do_unshare(int argc, char **argv);
99 static int zfs_do_send(int argc, char **argv);
100 static int zfs_do_receive(int argc, char **argv);
101 static int zfs_do_promote(int argc, char **argv);
102 static int zfs_do_userspace(int argc, char **argv);
103 static int zfs_do_allow(int argc, char **argv);
104 static int zfs_do_unallow(int argc, char **argv);
105 static int zfs_do_hold(int argc, char **argv);
106 static int zfs_do_holds(int argc, char **argv);
107 static int zfs_do_release(int argc, char **argv);
108 static int zfs_do_diff(int argc, char **argv);
109 static int zfs_do_bookmark(int argc, char **argv);
110 static int zfs_do_channel_program(int argc, char **argv);
111
112 /*
113 * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
114 */
115
116 #ifdef DEBUG
117 const char *
118 _umem_debug_init(void)
119 {
120 return ("default,verbose"); /* $UMEM_DEBUG setting */
121 }
122
123 const char *
124 _umem_logging_init(void)
125 {
126 return ("fail,contents"); /* $UMEM_LOGGING setting */
127 }
128 #endif
129
137 HELP_LIST,
138 HELP_MOUNT,
139 HELP_PROMOTE,
140 HELP_RECEIVE,
141 HELP_RENAME,
142 HELP_ROLLBACK,
143 HELP_SEND,
144 HELP_SET,
145 HELP_SHARE,
146 HELP_SNAPSHOT,
147 HELP_UNMOUNT,
148 HELP_UNSHARE,
149 HELP_ALLOW,
150 HELP_UNALLOW,
151 HELP_USERSPACE,
152 HELP_GROUPSPACE,
153 HELP_HOLD,
154 HELP_HOLDS,
155 HELP_RELEASE,
156 HELP_DIFF,
157 HELP_BOOKMARK,
158 HELP_CHANNEL_PROGRAM,
159 } zfs_help_t;
160
161 typedef struct zfs_command {
162 const char *name;
163 int (*func)(int argc, char **argv);
164 zfs_help_t usage;
165 } zfs_command_t;
166
167 /*
168 * Master command table. Each ZFS command has a name, associated function, and
169 * usage message. The usage messages need to be internationalized, so we have
170 * to have a function to return the usage message based on a command index.
171 *
172 * These commands are organized according to how they are displayed in the usage
173 * message. An empty command (one with a NULL name) indicates an empty line in
174 * the generic usage message.
175 */
176 static zfs_command_t command_table[] = {
193 { "upgrade", zfs_do_upgrade, HELP_UPGRADE },
194 { "userspace", zfs_do_userspace, HELP_USERSPACE },
195 { "groupspace", zfs_do_userspace, HELP_GROUPSPACE },
196 { NULL },
197 { "mount", zfs_do_mount, HELP_MOUNT },
198 { "unmount", zfs_do_unmount, HELP_UNMOUNT },
199 { "share", zfs_do_share, HELP_SHARE },
200 { "unshare", zfs_do_unshare, HELP_UNSHARE },
201 { NULL },
202 { "send", zfs_do_send, HELP_SEND },
203 { "receive", zfs_do_receive, HELP_RECEIVE },
204 { NULL },
205 { "allow", zfs_do_allow, HELP_ALLOW },
206 { NULL },
207 { "unallow", zfs_do_unallow, HELP_UNALLOW },
208 { NULL },
209 { "hold", zfs_do_hold, HELP_HOLD },
210 { "holds", zfs_do_holds, HELP_HOLDS },
211 { "release", zfs_do_release, HELP_RELEASE },
212 { "diff", zfs_do_diff, HELP_DIFF },
213 };
214
215 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
216
217 zfs_command_t *current_command;
218
219 static const char *
220 get_usage(zfs_help_t idx)
221 {
222 switch (idx) {
223 case HELP_CLONE:
224 return (gettext("\tclone [-p] [-o property=value] ... "
225 "<snapshot> <filesystem|volume>\n"));
226 case HELP_CREATE:
227 return (gettext("\tcreate [-p] [-o property=value] ... "
228 "<filesystem>\n"
229 "\tcreate [-ps] [-b blocksize] [-o property=value] ... "
230 "-V <size> <volume>\n"));
231 case HELP_DESTROY:
232 return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
233 "\tdestroy [-dnpRrv] "
234 "<filesystem|volume>@<snap>[%<snap>][,...]\n"
235 "\tdestroy <filesystem|volume>#<bookmark>\n"));
236 case HELP_GET:
237 return (gettext("\tget [-rHp] [-d max] "
238 "[-o \"all\" | field[,...]]\n"
239 "\t [-t type[,...]] [-s source[,...]]\n"
240 "\t <\"all\" | property[,...]> "
241 "[filesystem|volume|snapshot|bookmark] ...\n"));
242 case HELP_INHERIT:
243 return (gettext("\tinherit [-rS] <property> "
244 "<filesystem|volume|snapshot> ...\n"));
245 case HELP_UPGRADE:
246 return (gettext("\tupgrade [-v]\n"
247 "\tupgrade [-r] [-V version] <-a | filesystem ...>\n"));
248 case HELP_LIST:
249 return (gettext("\tlist [-Hp] [-r|-d max] [-o property[,...]] "
250 "[-s property]...\n\t [-S property]... [-t type[,...]] "
251 "[filesystem|volume|snapshot|autosnapshot] ...\n"));
252 case HELP_MOUNT:
253 return (gettext("\tmount\n"
254 "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
255 case HELP_PROMOTE:
256 return (gettext("\tpromote <clone-filesystem>\n"));
257 case HELP_RECEIVE:
258 return (gettext("\treceive [-vnsFKu] <filesystem|volume|"
259 "snapshot>\n"
260 "\treceive [-vnsFKu] [-d |-e] [-o <property=value>]... "
261 "[-x <property>]... [-l <filesystem|volume>] ... "
262 "<filesystem|volume|snapshot>\n"
263 "\treceive -A <filesystem|volume>\n"));
264 case HELP_RENAME:
265 return (gettext("\trename [-f] <filesystem|volume|snapshot> "
266 "<filesystem|volume|snapshot>\n"
267 "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
268 "\trename -r <snapshot> <snapshot>\n"));
269 case HELP_ROLLBACK:
270 return (gettext("\trollback [-rRf] <snapshot>\n"));
271 case HELP_SEND:
272 return (gettext("\tsend [-DnPpRvLesc] [-[iI] snapshot] "
273 "<snapshot>\n"
274 "\tsend [-Le] [-i snapshot|bookmark] "
275 "<filesystem|volume|snapshot>\n"
276 "\tsend [-nvPe] -t <receive_resume_token>\n"));
277 case HELP_SET:
278 return (gettext("\tset <property=value> ... "
279 "<filesystem|volume|snapshot> ...\n"));
280 case HELP_SHARE:
281 return (gettext("\tshare <-a | filesystem>\n"));
282 case HELP_SNAPSHOT:
283 return (gettext("\tsnapshot [-r] [-o property=value] ... "
284 "<filesystem|volume>@<snap> ...\n"));
285 case HELP_UNMOUNT:
286 return (gettext("\tunmount [-f] "
287 "<-a | filesystem|mountpoint>\n"));
288 case HELP_UNSHARE:
289 return (gettext("\tunshare "
290 "<-a | filesystem|mountpoint>\n"));
291 case HELP_ALLOW:
292 return (gettext("\tallow <filesystem|volume>\n"
310 "<filesystem|volume>\n"));
311 case HELP_USERSPACE:
312 return (gettext("\tuserspace [-Hinp] [-o field[,...]] "
313 "[-s field] ...\n"
314 "\t [-S field] ... [-t type[,...]] "
315 "<filesystem|snapshot>\n"));
316 case HELP_GROUPSPACE:
317 return (gettext("\tgroupspace [-Hinp] [-o field[,...]] "
318 "[-s field] ...\n"
319 "\t [-S field] ... [-t type[,...]] "
320 "<filesystem|snapshot>\n"));
321 case HELP_HOLD:
322 return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
323 case HELP_HOLDS:
324 return (gettext("\tholds [-r] <snapshot> ...\n"));
325 case HELP_RELEASE:
326 return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
327 case HELP_DIFF:
328 return (gettext("\tdiff [-FHt] <snapshot> "
329 "[snapshot|filesystem]\n"));
330 case HELP_BOOKMARK:
331 return (gettext("\tbookmark <snapshot> <bookmark>\n"));
332 case HELP_CHANNEL_PROGRAM:
333 return (gettext("\tprogram [-n] [-t <instruction limit>] "
334 "[-m <memory limit (b)>] <pool> <program file> "
335 "[lua args...]\n"));
336 }
337
338 abort();
339 /* NOTREACHED */
340 }
341
342 void
343 nomem(void)
344 {
345 (void) fprintf(stderr, gettext("internal error: out of memory\n"));
346 exit(1);
347 }
348
349 /*
490 (void) fprintf(fp,
491 gettext("\nFor the property list, run: %s\n"),
492 "zfs set|get");
493 (void) fprintf(fp,
494 gettext("\nFor the delegated permission list, run: %s\n"),
495 "zfs allow|unallow");
496 }
497
498 /*
499 * See comments at end of main().
500 */
501 if (getenv("ZFS_ABORT") != NULL) {
502 (void) printf("dumping core by request\n");
503 abort();
504 }
505
506 exit(requested ? 0 : 2);
507 }
508
509 /*
510 * Add parameter to the list if it's not in there already
511 */
512 static void
513 add_unique_option(nvlist_t *props, char *propname)
514 {
515 if (nvlist_lookup_string(props, propname, NULL) != 0) {
516 if (nvlist_add_boolean(props, propname) != 0) {
517 nomem();
518 }
519 }
520 }
521
522 /*
523 * Take a property=value argument string and add it to the given nvlist.
524 * Modifies the argument inplace.
525 */
526 static int
527 parseprop(nvlist_t *props, char *propname)
528 {
529 char *propval, *strval;
530
531 if ((propval = strchr(propname, '=')) == NULL) {
532 (void) fprintf(stderr, gettext("missing "
533 "'=' for property=value argument\n"));
534 return (-1);
535 }
536 *propval = '\0';
537 propval++;
538 if (nvlist_lookup_string(props, propname, &strval) == 0) {
539 (void) fprintf(stderr, gettext("property '%s' "
540 "specified multiple times\n"), propname);
541 return (-1);
542 }
543 if (nvlist_add_string(props, propname, propval) != 0)
544 nomem();
545 return (0);
546 }
547
548 static int
549 parse_depth(char *opt, int *flags)
550 {
551 char *tmp;
552 int depth;
553
554 depth = (int)strtol(opt, &tmp, 0);
555 if (*tmp) {
556 (void) fprintf(stderr,
557 gettext("%s is not an integer\n"), opt);
558 usage(B_FALSE);
559 }
560 if (depth < 0) {
561 (void) fprintf(stderr,
562 gettext("Depth can not be negative.\n"));
563 usage(B_FALSE);
564 }
565 *flags |= (ZFS_ITER_DEPTH_LIMIT|ZFS_ITER_RECURSE);
566 return (depth);
567 }
568
569 #define PROGRESS_DELAY 2 /* seconds */
570
571 static char *pt_reverse = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
572 static time_t pt_begin;
573 static char *pt_header = NULL;
574 static boolean_t pt_shown;
575
576 static void
577 start_progress_timer(void)
1068 /*
1069 * Ignore pools (which we've already flagged as an error before getting
1070 * here).
1071 */
1072 if (strchr(zfs_get_name(zhp), '/') == NULL &&
1073 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
1074 zfs_close(zhp);
1075 return (0);
1076 }
1077 if (cb->cb_dryrun) {
1078 zfs_close(zhp);
1079 return (0);
1080 }
1081
1082 /*
1083 * We batch up all contiguous snapshots (even of different
1084 * filesystems) and destroy them with one ioctl. We can't
1085 * simply do all snap deletions and then all fs deletions,
1086 * because we must delete a clone before its origin.
1087 */
1088 if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT ||
1089 zfs_get_type(zhp) == ZFS_TYPE_AUTOSNAP) {
1090 fnvlist_add_boolean(cb->cb_batchedsnaps, name);
1091 } else {
1092 int error = zfs_destroy_snaps_nvl(g_zfs,
1093 cb->cb_batchedsnaps, B_FALSE);
1094 fnvlist_free(cb->cb_batchedsnaps);
1095 cb->cb_batchedsnaps = fnvlist_alloc();
1096
1097 if (error != 0 ||
1098 zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
1099 zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
1100 zfs_close(zhp);
1101 return (-1);
1102 }
1103 }
1104
1105 zfs_close(zhp);
1106 return (0);
1107 }
1108
1109 static int
1231 boolean_t defer = cb->cb_defer_destroy;
1232 int err = 0;
1233
1234 /*
1235 * We can't defer destroy non-snapshots, so set it to
1236 * false while destroying the clones.
1237 */
1238 cb->cb_defer_destroy = B_FALSE;
1239 err = zfs_iter_dependents(zhp, B_FALSE,
1240 destroy_callback, cb);
1241 cb->cb_defer_destroy = defer;
1242 zfs_close(zhp);
1243 if (err != 0)
1244 return (err);
1245 }
1246 }
1247 return (0);
1248 }
1249
1250 static int
1251 unmount_callback(zfs_handle_t *zhp, void *arg)
1252 {
1253 destroy_cbdata_t *cb = arg;
1254 int err = 0;
1255
1256 if (zfs_is_mounted(zhp, NULL))
1257 err = zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0);
1258
1259 zfs_close(zhp);
1260
1261 return (err);
1262 }
1263
1264 static int
1265 zfs_do_destroy(int argc, char **argv)
1266 {
1267 destroy_cbdata_t cb = { 0 };
1268 int rv = 0;
1269 int err = 0;
1270 int c;
1271 zfs_handle_t *zhp = NULL;
1272 char *at, *pound;
1273 zfs_type_t type = ZFS_TYPE_DATASET;
1274
1275 /* check options */
1276 while ((c = getopt(argc, argv, "vpndfrR")) != -1) {
1277 switch (c) {
1278 case 'v':
1279 cb.cb_verbose = B_TRUE;
1280 break;
1281 case 'p':
1282 cb.cb_verbose = B_TRUE;
1283 cb.cb_parsable = B_TRUE;
1284 break;
1413
1414 nvl = fnvlist_alloc();
1415 fnvlist_add_boolean(nvl, argv[0]);
1416
1417 err = lzc_destroy_bookmarks(nvl, NULL);
1418 if (err != 0) {
1419 (void) zfs_standard_error(g_zfs, err,
1420 "cannot destroy bookmark");
1421 }
1422
1423 nvlist_free(cb.cb_nvl);
1424
1425 return (err);
1426 } else {
1427 /* Open the given dataset */
1428 if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
1429 return (1);
1430
1431 cb.cb_target = zhp;
1432
1433 err = zfs_check_krrp(g_zfs, argv[0]);
1434
1435 /*
1436 * ENOTSUP means that autosnaper doesn't handle this dataset
1437 * and the basic detruction can be used.
1438 */
1439 if (err != ENOTSUP) {
1440 rv = 1;
1441 if (!cb.cb_recurse || !cb.cb_doclones) {
1442 (void) fprintf(stderr,
1443 gettext("cannot destroy '%s': "
1444 "dataset under autosnap can be destroyed "
1445 "with -R only\n"), zfs_get_name(zhp));
1446 } else if (err == ECHILD) {
1447 (void) fprintf(stderr,
1448 gettext("cannot destroy '%s': "
1449 "dataset has children under krrp\n"),
1450 zfs_get_name(zhp));
1451 } else if (err == EBUSY) {
1452 (void) fprintf(stderr,
1453 gettext("cannot destroy '%s': "
1454 "dataset is root of a krrp task\n"),
1455 zfs_get_name(zhp));
1456 } else if (err && err != EUSERS) {
1457 (void) fprintf(stderr,
1458 gettext("cannot destroy '%s': "
1459 "unexpected error : %d\n"),
1460 zfs_get_name(zhp), err);
1461 } else {
1462 /*
1463 * err == 0 || err == EUSERS means the ds can
1464 * be destroyed with atomical destroy
1465 */
1466 err = zfs_iter_dependents(zhp, B_FALSE,
1467 unmount_callback, &cb);
1468 if (!err) {
1469 err = unmount_callback(
1470 zfs_handle_dup(zhp), &cb);
1471 }
1472 if (!err) {
1473 err = zfs_destroy_atomically(
1474 zhp, B_TRUE);
1475 }
1476
1477 if (!err)
1478 rv = 0;
1479 }
1480 goto out;
1481 }
1482
1483 err = 0;
1484
1485 /*
1486 * Perform an explicit check for pools before going any further.
1487 */
1488 if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
1489 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
1490 (void) fprintf(stderr, gettext("cannot destroy '%s': "
1491 "operation does not apply to pools\n"),
1492 zfs_get_name(zhp));
1493 (void) fprintf(stderr, gettext("use 'zfs destroy -r "
1494 "%s' to destroy all datasets in the pool\n"),
1495 zfs_get_name(zhp));
1496 (void) fprintf(stderr, gettext("use 'zpool destroy %s' "
1497 "to destroy the pool itself\n"), zfs_get_name(zhp));
1498 rv = 1;
1499 goto out;
1500 }
1501
1502 /*
1503 * Check for any dependents and/or clones.
1504 */
1505 cb.cb_first = B_TRUE;
2138 "upgraded; the pool version needs to first "
2139 "be upgraded\nto version %d\n\n"),
2140 zfs_get_name(zhp), needed_spa_version);
2141 cb->cb_numfailed++;
2142 return (0);
2143 }
2144
2145 /* upgrade */
2146 if (version < cb->cb_version) {
2147 char verstr[16];
2148 (void) snprintf(verstr, sizeof (verstr),
2149 "%llu", cb->cb_version);
2150 if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
2151 /*
2152 * If they did "zfs upgrade -a", then we could
2153 * be doing ioctls to different pools. We need
2154 * to log this history once to each pool, and bypass
2155 * the normal history logging that happens in main().
2156 */
2157 (void) zpool_log_history(g_zfs, history_str);
2158 verify(zpool_stage_history(g_zfs, history_str) == 0);
2159 log_history = B_FALSE;
2160 }
2161 if (zfs_prop_set(zhp, "version", verstr) == 0)
2162 cb->cb_numupgraded++;
2163 else
2164 cb->cb_numfailed++;
2165 (void) strcpy(cb->cb_lastfs, zfs_get_name(zhp));
2166 } else if (version > cb->cb_version) {
2167 /* can't downgrade */
2168 (void) printf(gettext("%s: can not be downgraded; "
2169 "it is already at version %u\n"),
2170 zfs_get_name(zhp), version);
2171 cb->cb_numfailed++;
2172 } else {
2173 cb->cb_numsamegraded++;
2174 }
2175 return (0);
2176 }
2177
2178 /*
3186 (void) fprintf(stderr,
3187 gettext("invalid property '%s'\n"), optarg);
3188 usage(B_FALSE);
3189 }
3190 break;
3191 case 'S':
3192 if (zfs_add_sort_column(&sortcol, optarg,
3193 B_TRUE) != 0) {
3194 (void) fprintf(stderr,
3195 gettext("invalid property '%s'\n"), optarg);
3196 usage(B_FALSE);
3197 }
3198 break;
3199 case 't':
3200 types = 0;
3201 types_specified = B_TRUE;
3202 flags &= ~ZFS_ITER_PROP_LISTSNAPS;
3203 while (*optarg != '\0') {
3204 static char *type_subopts[] = { "filesystem",
3205 "volume", "snapshot", "snap", "bookmark",
3206 "all", "autosnapshot", NULL };
3207
3208 switch (getsubopt(&optarg, type_subopts,
3209 &value)) {
3210 case 0:
3211 types |= ZFS_TYPE_FILESYSTEM;
3212 break;
3213 case 1:
3214 types |= ZFS_TYPE_VOLUME;
3215 break;
3216 case 2:
3217 case 3:
3218 types |= ZFS_TYPE_SNAPSHOT;
3219 break;
3220 case 4:
3221 types |= ZFS_TYPE_BOOKMARK;
3222 break;
3223 case 5:
3224 types = ZFS_TYPE_DATASET |
3225 ZFS_TYPE_BOOKMARK |
3226 ZFS_TYPE_AUTOSNAP;
3227 break;
3228 case 6:
3229 types |= ZFS_TYPE_AUTOSNAP;
3230 break;
3231 default:
3232 (void) fprintf(stderr,
3233 gettext("invalid type '%s'\n"),
3234 value);
3235 usage(B_FALSE);
3236 }
3237 }
3238 break;
3239 case ':':
3240 (void) fprintf(stderr, gettext("missing argument for "
3241 "'%c' option\n"), optopt);
3242 usage(B_FALSE);
3243 break;
3244 case '?':
3245 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3246 optopt);
3247 usage(B_FALSE);
3248 }
3249 }
3250
3810 sendflags_t flags = { 0 };
3811 int c, err;
3812 nvlist_t *dbgnv = NULL;
3813 boolean_t extraverbose = B_FALSE;
3814
3815 struct option long_options[] = {
3816 {"replicate", no_argument, NULL, 'R'},
3817 {"props", no_argument, NULL, 'p'},
3818 {"parsable", no_argument, NULL, 'P'},
3819 {"dedup", no_argument, NULL, 'D'},
3820 {"verbose", no_argument, NULL, 'v'},
3821 {"dryrun", no_argument, NULL, 'n'},
3822 {"large-block", no_argument, NULL, 'L'},
3823 {"embed", no_argument, NULL, 'e'},
3824 {"resume", required_argument, NULL, 't'},
3825 {"compressed", no_argument, NULL, 'c'},
3826 {0, 0, 0, 0}
3827 };
3828
3829 /* check options */
3830 while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLest:c", long_options,
3831 NULL)) != -1) {
3832 switch (c) {
3833 case 'i':
3834 if (fromname)
3835 usage(B_FALSE);
3836 fromname = optarg;
3837 break;
3838 case 'I':
3839 if (fromname)
3840 usage(B_FALSE);
3841 fromname = optarg;
3842 flags.doall = B_TRUE;
3843 break;
3844 case 'R':
3845 flags.replicate = B_TRUE;
3846 break;
3847 case 'p':
3848 flags.props = B_TRUE;
3849 break;
3850 case 'P':
3852 flags.verbose = B_TRUE;
3853 break;
3854 case 'v':
3855 if (flags.verbose)
3856 extraverbose = B_TRUE;
3857 flags.verbose = B_TRUE;
3858 flags.progress = B_TRUE;
3859 break;
3860 case 'D':
3861 flags.dedup = B_TRUE;
3862 break;
3863 case 'n':
3864 flags.dryrun = B_TRUE;
3865 break;
3866 case 'L':
3867 flags.largeblock = B_TRUE;
3868 break;
3869 case 'e':
3870 flags.embed_data = B_TRUE;
3871 break;
3872 case 's':
3873 flags.sendsize = B_TRUE;
3874 break;
3875 case 't':
3876 resume_token = optarg;
3877 break;
3878 case 'c':
3879 flags.compress = B_TRUE;
3880 break;
3881 case ':':
3882 /*
3883 * If a parameter was not passed, optopt contains the
3884 * value that would normally lead us into the
3885 * appropriate case statement. If it's > 256, then this
3886 * must be a longopt and we should look at argv to get
3887 * the string. Otherwise it's just the character, so we
3888 * should use it directly.
3889 */
3890 if (optopt <= UINT8_MAX) {
3891 (void) fprintf(stderr,
3892 gettext("missing argument for '%c' "
3893 "option\n"), optopt);
3894 } else {
3929 gettext("invalid flags combined with -t\n"));
3930 usage(B_FALSE);
3931 }
3932 if (argc != 0) {
3933 (void) fprintf(stderr, gettext("no additional "
3934 "arguments are permitted with -t\n"));
3935 usage(B_FALSE);
3936 }
3937 } else {
3938 if (argc < 1) {
3939 (void) fprintf(stderr,
3940 gettext("missing snapshot argument\n"));
3941 usage(B_FALSE);
3942 }
3943 if (argc > 1) {
3944 (void) fprintf(stderr, gettext("too many arguments\n"));
3945 usage(B_FALSE);
3946 }
3947 }
3948
3949 if (flags.sendsize) {
3950 int fd = open("/dev/null", O_WRONLY|O_LARGEFILE);
3951 if (fd < 0) {
3952 perror("failed to open /dev/null");
3953 return (1);
3954 }
3955 if ((dup2(fd, STDOUT_FILENO)) < 0) {
3956 perror("failed to dup2(/dev/null,STDOUT_FILENO)");
3957 return (1);
3958 }
3959 } else if (!flags.dryrun && isatty(STDOUT_FILENO)) {
3960 (void) fprintf(stderr,
3961 gettext("Error: Stream can not be written to a terminal.\n"
3962 "You must redirect standard output.\n"));
3963 return (1);
3964 }
3965
3966 if (resume_token != NULL) {
3967 return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
3968 resume_token));
3969 }
3970
3971 /*
3972 * Special case sending a filesystem, or from a bookmark.
3973 */
3974 if (strchr(argv[0], '@') == NULL ||
3975 (fromname && strchr(fromname, '#') != NULL)) {
3976 char frombuf[ZFS_MAX_DATASET_NAME_LEN];
3977 enum lzc_send_flags lzc_flags = 0;
3978
3979 if (flags.replicate || flags.doall || flags.props ||
4064 * dump_nvlist prints to stdout, but that's been
4065 * redirected to a file. Make it print to stderr
4066 * instead.
4067 */
4068 (void) dup2(STDERR_FILENO, STDOUT_FILENO);
4069 dump_nvlist(dbgnv, 0);
4070 nvlist_free(dbgnv);
4071 }
4072 zfs_close(zhp);
4073
4074 return (err != 0);
4075 }
4076
4077 /*
4078 * Restore a backup stream from stdin.
4079 */
4080 static int
4081 zfs_do_receive(int argc, char **argv)
4082 {
4083 int c, err = 0;
4084 nvlist_t *exprops, *limitds;
4085 recvflags_t flags = { 0 };
4086 boolean_t abort_resumable = B_FALSE;
4087
4088 if (nvlist_alloc(&exprops, NV_UNIQUE_NAME, 0) != 0)
4089 nomem();
4090 if (nvlist_alloc(&limitds, NV_UNIQUE_NAME, 0) != 0)
4091 nomem();
4092
4093 /* check options */
4094 while ((c = getopt(argc, argv, ":del:no:uvx:FsAK")) != -1) {
4095 switch (c) {
4096 case 'o':
4097 if (parseprop(exprops, optarg) != 0) {
4098 err = 1;
4099 goto recverror;
4100 }
4101 break;
4102 case 'd':
4103 flags.isprefix = B_TRUE;
4104 break;
4105 case 'e':
4106 flags.isprefix = B_TRUE;
4107 flags.istail = B_TRUE;
4108 break;
4109 case 'l':
4110 add_unique_option(limitds, optarg);
4111 break;
4112 case 'n':
4113 flags.dryrun = B_TRUE;
4114 break;
4115 case 'u':
4116 flags.nomount = B_TRUE;
4117 break;
4118 case 'v':
4119 flags.verbose = B_TRUE;
4120 break;
4121 case 'x':
4122 add_unique_option(exprops, optarg);
4123 break;
4124 case 's':
4125 flags.resumable = B_TRUE;
4126 break;
4127 case 'F':
4128 flags.force = B_TRUE;
4129 break;
4130 case 'A':
4131 abort_resumable = B_TRUE;
4132 break;
4133 case 'K':
4134 flags.keepsnap = B_TRUE;
4135 break;
4136 case ':':
4137 (void) fprintf(stderr, gettext("missing argument for "
4138 "'%c' option\n"), optopt);
4139 usage(B_FALSE);
4140 break;
4141 case '?':
4142 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4143 optopt);
4144 usage(B_FALSE);
4145 }
4146 }
4147
4148 argc -= optind;
4149 argv += optind;
4150
4151 /* check number of arguments */
4152 if (argc < 1) {
4153 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
4154 usage(B_FALSE);
4155 }
4156 if (argc > 1) {
4157 (void) fprintf(stderr, gettext("too many arguments\n"));
4158 usage(B_FALSE);
4159 }
4160
4161 if (abort_resumable) {
4162 if (flags.isprefix || flags.istail || flags.dryrun ||
4163 flags.resumable || flags.nomount) {
4164 (void) fprintf(stderr, gettext("invalid option"));
4165 usage(B_FALSE);
4166 }
4167
4168 char namebuf[ZFS_MAX_DATASET_NAME_LEN];
4169 (void) snprintf(namebuf, sizeof (namebuf),
4170 "%s/%%recv", argv[0]);
4171
4172 if (zfs_dataset_exists(g_zfs, namebuf,
4173 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) {
4174 zfs_handle_t *zhp = zfs_open(g_zfs,
4175 namebuf, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
4176 if (zhp == NULL)
4177 return (1);
4178 err = zfs_destroy(zhp, B_FALSE);
4179 } else {
4180 zfs_handle_t *zhp = zfs_open(g_zfs,
4186 NULL, 0, NULL, NULL, 0, B_TRUE) == -1) {
4187 (void) fprintf(stderr,
4188 gettext("'%s' does not have any "
4189 "resumable receive state to abort\n"),
4190 argv[0]);
4191 return (1);
4192 }
4193 err = zfs_destroy(zhp, B_FALSE);
4194 }
4195
4196 return (err != 0);
4197 }
4198
4199 if (isatty(STDIN_FILENO)) {
4200 (void) fprintf(stderr,
4201 gettext("Error: Backup stream can not be read "
4202 "from a terminal.\n"
4203 "You must redirect standard input.\n"));
4204 return (1);
4205 }
4206
4207 err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, exprops,
4208 limitds, NULL);
4209
4210 recverror:
4211 nvlist_free(exprops);
4212 nvlist_free(limitds);
4213
4214 return (err != 0);
4215 }
4216
4217 /*
4218 * allow/unallow stuff
4219 */
4220 /* copied from zfs/sys/dsl_deleg.h */
4221 #define ZFS_DELEG_PERM_CREATE "create"
4222 #define ZFS_DELEG_PERM_DESTROY "destroy"
4223 #define ZFS_DELEG_PERM_SNAPSHOT "snapshot"
4224 #define ZFS_DELEG_PERM_ROLLBACK "rollback"
4225 #define ZFS_DELEG_PERM_CLONE "clone"
4226 #define ZFS_DELEG_PERM_PROMOTE "promote"
4227 #define ZFS_DELEG_PERM_RENAME "rename"
4228 #define ZFS_DELEG_PERM_MOUNT "mount"
4229 #define ZFS_DELEG_PERM_SHARE "share"
4230 #define ZFS_DELEG_PERM_SEND "send"
4231 #define ZFS_DELEG_PERM_RECEIVE "receive"
4232 #define ZFS_DELEG_PERM_ALLOW "allow"
4233 #define ZFS_DELEG_PERM_USERPROP "userprop"
4234 #define ZFS_DELEG_PERM_VSCAN "vscan" /* ??? */
4235 #define ZFS_DELEG_PERM_USERQUOTA "userquota"
4236 #define ZFS_DELEG_PERM_GROUPQUOTA "groupquota"
4237 #define ZFS_DELEG_PERM_USERUSED "userused"
4238 #define ZFS_DELEG_PERM_GROUPUSED "groupused"
4239 #define ZFS_DELEG_PERM_HOLD "hold"
4240 #define ZFS_DELEG_PERM_RELEASE "release"
4241 #define ZFS_DELEG_PERM_DIFF "diff"
4242 #define ZFS_DELEG_PERM_BOOKMARK "bookmark"
4243
4244 #define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
4245
4246 static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
4247 { ZFS_DELEG_PERM_ALLOW, ZFS_DELEG_NOTE_ALLOW },
4248 { ZFS_DELEG_PERM_CLONE, ZFS_DELEG_NOTE_CLONE },
4249 { ZFS_DELEG_PERM_CREATE, ZFS_DELEG_NOTE_CREATE },
4250 { ZFS_DELEG_PERM_DESTROY, ZFS_DELEG_NOTE_DESTROY },
4251 { ZFS_DELEG_PERM_DIFF, ZFS_DELEG_NOTE_DIFF},
4252 { ZFS_DELEG_PERM_HOLD, ZFS_DELEG_NOTE_HOLD },
4253 { ZFS_DELEG_PERM_MOUNT, ZFS_DELEG_NOTE_MOUNT },
4254 { ZFS_DELEG_PERM_PROMOTE, ZFS_DELEG_NOTE_PROMOTE },
4255 { ZFS_DELEG_PERM_RECEIVE, ZFS_DELEG_NOTE_RECEIVE },
4256 { ZFS_DELEG_PERM_RELEASE, ZFS_DELEG_NOTE_RELEASE },
4257 { ZFS_DELEG_PERM_RENAME, ZFS_DELEG_NOTE_RENAME },
4258 { ZFS_DELEG_PERM_ROLLBACK, ZFS_DELEG_NOTE_ROLLBACK },
4259 { ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_SEND },
4260 { ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
4261 { ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
4262 { ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
4263
4264 { ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
4265 { ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
4266 { ZFS_DELEG_PERM_USERPROP, ZFS_DELEG_NOTE_USERPROP },
4267 { ZFS_DELEG_PERM_USERQUOTA, ZFS_DELEG_NOTE_USERQUOTA },
4268 { ZFS_DELEG_PERM_USERUSED, ZFS_DELEG_NOTE_USERUSED },
4269 { NULL, ZFS_DELEG_NOTE_NONE }
4270 };
4271
4272 /* permission structure */
4273 typedef struct deleg_perm {
4274 zfs_deleg_who_type_t dp_who_type;
4275 const char *dp_name;
4276 boolean_t dp_local;
4277 boolean_t dp_descend;
4278 } deleg_perm_t;
4279
4280 /* */
4281 typedef struct deleg_perm_node {
4282 deleg_perm_t dpn_perm;
5688 col = gettext(hdr_cols[i]);
5689 if (i < 2)
5690 (void) printf("%-*s ", i ? tagwidth : nwidth,
5691 col);
5692 else
5693 (void) printf("%s\n", col);
5694 }
5695 }
5696
5697 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
5698 char *zname = nvpair_name(nvp);
5699 nvlist_t *nvl2;
5700 nvpair_t *nvp2 = NULL;
5701 (void) nvpair_value_nvlist(nvp, &nvl2);
5702 while ((nvp2 = nvlist_next_nvpair(nvl2, nvp2)) != NULL) {
5703 char tsbuf[DATETIME_BUF_LEN];
5704 char *tagname = nvpair_name(nvp2);
5705 uint64_t val = 0;
5706 time_t time;
5707 struct tm t;
5708 char sep = scripted ? '\t' : ' ';
5709 size_t sepnum = scripted ? 1 : 2;
5710
5711 (void) nvpair_value_uint64(nvp2, &val);
5712 time = (time_t)val;
5713 (void) localtime_r(&time, &t);
5714 (void) strftime(tsbuf, DATETIME_BUF_LEN,
5715 gettext(STRFTIME_FMT_STR), &t);
5716
5717 (void) printf("%-*s%*c%-*s%*c%s\n", nwidth, zname,
5718 sepnum, sep, tagwidth, tagname, sepnum, sep, tsbuf);
5719 }
5720 }
5721 }
5722
5723 /*
5724 * Generic callback function to list a dataset or snapshot.
5725 */
5726 static int
5727 holds_callback(zfs_handle_t *zhp, void *data)
5728 {
5729 holds_cbdata_t *cbp = data;
5730 nvlist_t *top_nvl = *cbp->cb_nvlp;
5731 nvlist_t *nvl = NULL;
5732 nvpair_t *nvp = NULL;
5733 const char *zname = zfs_get_name(zhp);
5734 size_t znamelen = strlen(zname);
5735
5736 if (cbp->cb_recursive) {
5737 const char *snapname;
5738 char *delim = strchr(zname, '@');
5739 if (delim == NULL)
5740 return (0);
6616 default:
6617 break;
6618 }
6619
6620 node = safe_malloc(sizeof (unshare_unmount_node_t));
6621 node->un_zhp = zhp;
6622 node->un_mountp = safe_strdup(entry.mnt_mountp);
6623
6624 uu_avl_node_init(node, &node->un_avlnode, pool);
6625
6626 if (uu_avl_find(tree, node, NULL, &idx) == NULL) {
6627 uu_avl_insert(tree, node, idx);
6628 } else {
6629 zfs_close(node->un_zhp);
6630 free(node->un_mountp);
6631 free(node);
6632 }
6633 }
6634
6635 /*
6636 * Initilialize libshare SA_INIT_SHARE_API_SELECTIVE here
6637 * to avoid unneccesary load/unload of the libshare API
6638 * per shared dataset downstream.
6639 */
6640 if (op == OP_SHARE) {
6641 zfs_handle_t **dslist = NULL;
6642 size_t count = 0;
6643 get_all_datasets(&dslist, &count, B_FALSE);
6644
6645 if (count > 0) {
6646 sa_init_selective_arg_t sharearg;
6647 sharearg.zhandle_arr = dslist;
6648 sharearg.zhandle_len = count;
6649 if ((ret = zfs_init_libshare_arg(
6650 zfs_get_handle(dslist[0]),
6651 SA_INIT_SHARE_API_SELECTIVE, &sharearg))
6652 != SA_OK) {
6653 (void) fprintf(stderr, gettext(
6654 "Could not initialize libshare,"
6655 "%d"), ret);
6656 return (1);
6657 }
6658 }
6659 }
6660
6661 /*
6662 * Walk the AVL tree in reverse, unmounting each filesystem and
6663 * removing it from the AVL tree in the process.
6664 */
6665 if ((walk = uu_avl_walk_start(tree,
6666 UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL)
6667 nomem();
6668
6669 while ((node = uu_avl_walk_next(walk)) != NULL) {
6670 uu_avl_remove(tree, node);
6671
6672 switch (op) {
6673 case OP_SHARE:
6674 if (zfs_unshareall_bypath(node->un_zhp,
6675 node->un_mountp) != 0)
6676 ret = 1;
6677 break;
6678
6679 case OP_MOUNT:
6680 if (zfs_unmount(node->un_zhp,
6681 node->un_mountp, flags) != 0)
7012 *atp = '\0';
7013
7014 if ((zhp = zfs_open(g_zfs, copy, ZFS_TYPE_FILESYSTEM)) == NULL)
7015 return (1);
7016
7017 free(copy);
7018
7019 /*
7020 * Ignore SIGPIPE so that the library can give us
7021 * information on any failure
7022 */
7023 (void) sigignore(SIGPIPE);
7024
7025 err = zfs_show_diffs(zhp, STDOUT_FILENO, fromsnap, tosnap, flags);
7026
7027 zfs_close(zhp);
7028
7029 return (err != 0);
7030 }
7031
7032 /*
7033 * zfs bookmark <fs@snap> <fs#bmark>
7034 *
7035 * Creates a bookmark with the given name from the given snapshot.
7036 */
7037 static int
7038 zfs_do_bookmark(int argc, char **argv)
7039 {
7040 char snapname[ZFS_MAX_DATASET_NAME_LEN];
7041 zfs_handle_t *zhp;
7042 nvlist_t *nvl;
7043 int ret = 0;
7044 int c;
7045
7046 /* check options */
7047 while ((c = getopt(argc, argv, "")) != -1) {
7048 switch (c) {
7049 case '?':
7050 (void) fprintf(stderr,
7051 gettext("invalid option '%c'\n"), optopt);
7331 int
7332 main(int argc, char **argv)
7333 {
7334 int ret = 0;
7335 int i;
7336 char *progname;
7337 char *cmdname;
7338
7339 (void) setlocale(LC_ALL, "");
7340 (void) textdomain(TEXT_DOMAIN);
7341
7342 opterr = 0;
7343
7344 if ((g_zfs = libzfs_init()) == NULL) {
7345 (void) fprintf(stderr, gettext("internal error: failed to "
7346 "initialize ZFS library\n"));
7347 return (1);
7348 }
7349
7350 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
7351 verify(zpool_stage_history(g_zfs, history_str) == 0);
7352
7353 libzfs_print_on_error(g_zfs, B_TRUE);
7354
7355 if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
7356 (void) fprintf(stderr, gettext("internal error: unable to "
7357 "open %s\n"), MNTTAB);
7358 return (1);
7359 }
7360
7361 /*
7362 * This command also doubles as the /etc/fs mount and unmount program.
7363 * Determine if we should take this behavior based on argv[0].
7364 */
7365 progname = basename(argv[0]);
7366 if (strcmp(progname, "mount") == 0) {
7367 ret = manual_mount(argc, argv);
7368 } else if (strcmp(progname, "umount") == 0) {
7369 ret = manual_unmount(argc, argv);
7370 } else {
7371 /*
|