Print this page
NEX-16219 pool import performance regression due to repeated libshare initialization
Reviewd by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15937 zpool import performance degradation in filesystem sharing
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-15937 zpool import performance degradation in filesystem sharing
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5728 Autosync Destination retention policy not being honoured
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
5984 zfs clone should not mount the clone if canmount == noauto
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Justin Gibbs <gibbs@scsiguy.com>
Reviewed by: Richard Elling <Richard.Elling@richardelling.com>
Approved by: Matthew Ahrens <mahrens@delphix.com>
6298 zfs_create_008_neg and zpool_create_023_neg need to be updated for large block support
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
2605 want to resume interrupted zfs send
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Xin Li <delphij@freebsd.org>
Reviewed by: Arne Jansen <sensille@gmx.net>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-4582 update wrc test cases for allow to use write back cache per tree of datasets
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
5960 zfs recv should prefetch indirect blocks
5925 zfs receive -o origin=
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
5745 zfs set allows only one dataset property to be set at a time
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com>
Reviewed by: Richard PALO <richard@NetBSD.org>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Rich Lowe <richlowe@richlowe.net>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-3669 Faults for fans that don't exist
Reviewed by: Jeffry Molanus <jeffry.molanus@nexenta.com>
NEX-3891 Hide the snapshots that belong to in-kernel autosnap-service
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3558 KRRP Integration
NEX-1456 Part 2, port FreeBSD patch - new zfs recv options support
4206 history_003_pos relies on exact size of history log and entries
4207 history_008_pos depends on obsolete internal history log message
4208 Typo in zfs_main.c: "posxiuser"
4209 Populate zfstest with the remainder of the STF tests
Reviewed by: Sonu Pillai <sonu.pillai@delphix.com>
Reviewed by: Will Guyette <will.guyette@delphix.com>
Reviewed by: Eric Diven <eric.diven@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
SUP-642 Regression leading to AD usernames not being displayed... (fix lint)
SUP-642 Regression leading to AD usernames not being displayed by zfs userspace command.
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
Bug 10481 - cstyle/lint cleanup
Bug 10481 - Dry run option in 'zfs send' isn't the same as in NexentaStor 3.1


  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                 /*