Print this page
FITS: generating send-streams in portable format
This commit adds the command 'zfs fits-send', analogous to zfs send. The
generated send stream is compatible with the stream generated with that
from 'btrfs send' and can in principle easily be received to any filesystem.


  72 static FILE *mnttab_file;
  73 static char history_str[HIS_MAX_RECORD_LEN];
  74 static boolean_t log_history = B_TRUE;
  75 
  76 static int zfs_do_clone(int argc, char **argv);
  77 static int zfs_do_create(int argc, char **argv);
  78 static int zfs_do_destroy(int argc, char **argv);
  79 static int zfs_do_get(int argc, char **argv);
  80 static int zfs_do_inherit(int argc, char **argv);
  81 static int zfs_do_list(int argc, char **argv);
  82 static int zfs_do_mount(int argc, char **argv);
  83 static int zfs_do_rename(int argc, char **argv);
  84 static int zfs_do_rollback(int argc, char **argv);
  85 static int zfs_do_set(int argc, char **argv);
  86 static int zfs_do_upgrade(int argc, char **argv);
  87 static int zfs_do_snapshot(int argc, char **argv);
  88 static int zfs_do_unmount(int argc, char **argv);
  89 static int zfs_do_share(int argc, char **argv);
  90 static int zfs_do_unshare(int argc, char **argv);
  91 static int zfs_do_send(int argc, char **argv);

  92 static int zfs_do_receive(int argc, char **argv);
  93 static int zfs_do_promote(int argc, char **argv);
  94 static int zfs_do_userspace(int argc, char **argv);
  95 static int zfs_do_allow(int argc, char **argv);
  96 static int zfs_do_unallow(int argc, char **argv);
  97 static int zfs_do_hold(int argc, char **argv);
  98 static int zfs_do_holds(int argc, char **argv);
  99 static int zfs_do_release(int argc, char **argv);
 100 static int zfs_do_diff(int argc, char **argv);
 101 
 102 /*
 103  * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
 104  */
 105 
 106 #ifdef DEBUG
 107 const char *
 108 _umem_debug_init(void)
 109 {
 110         return ("default,verbose"); /* $UMEM_DEBUG setting */
 111 }


 114 _umem_logging_init(void)
 115 {
 116         return ("fail,contents"); /* $UMEM_LOGGING setting */
 117 }
 118 #endif
 119 
 120 typedef enum {
 121         HELP_CLONE,
 122         HELP_CREATE,
 123         HELP_DESTROY,
 124         HELP_GET,
 125         HELP_INHERIT,
 126         HELP_UPGRADE,
 127         HELP_LIST,
 128         HELP_MOUNT,
 129         HELP_PROMOTE,
 130         HELP_RECEIVE,
 131         HELP_RENAME,
 132         HELP_ROLLBACK,
 133         HELP_SEND,

 134         HELP_SET,
 135         HELP_SHARE,
 136         HELP_SNAPSHOT,
 137         HELP_UNMOUNT,
 138         HELP_UNSHARE,
 139         HELP_ALLOW,
 140         HELP_UNALLOW,
 141         HELP_USERSPACE,
 142         HELP_GROUPSPACE,
 143         HELP_HOLD,
 144         HELP_HOLDS,
 145         HELP_RELEASE,
 146         HELP_DIFF,
 147 } zfs_help_t;
 148 
 149 typedef struct zfs_command {
 150         const char      *name;
 151         int             (*func)(int argc, char **argv);
 152         zfs_help_t      usage;
 153 } zfs_command_t;


 171         { "promote",    zfs_do_promote,         HELP_PROMOTE            },
 172         { "rename",     zfs_do_rename,          HELP_RENAME             },
 173         { NULL },
 174         { "list",       zfs_do_list,            HELP_LIST               },
 175         { NULL },
 176         { "set",        zfs_do_set,             HELP_SET                },
 177         { "get",        zfs_do_get,             HELP_GET                },
 178         { "inherit",    zfs_do_inherit,         HELP_INHERIT            },
 179         { "upgrade",    zfs_do_upgrade,         HELP_UPGRADE            },
 180         { "userspace",  zfs_do_userspace,       HELP_USERSPACE          },
 181         { "groupspace", zfs_do_userspace,       HELP_GROUPSPACE         },
 182         { NULL },
 183         { "mount",      zfs_do_mount,           HELP_MOUNT              },
 184         { "unmount",    zfs_do_unmount,         HELP_UNMOUNT            },
 185         { "share",      zfs_do_share,           HELP_SHARE              },
 186         { "unshare",    zfs_do_unshare,         HELP_UNSHARE            },
 187         { NULL },
 188         { "send",       zfs_do_send,            HELP_SEND               },
 189         { "receive",    zfs_do_receive,         HELP_RECEIVE            },
 190         { NULL },


 191         { "allow",      zfs_do_allow,           HELP_ALLOW              },
 192         { NULL },
 193         { "unallow",    zfs_do_unallow,         HELP_UNALLOW            },
 194         { NULL },
 195         { "hold",       zfs_do_hold,            HELP_HOLD               },
 196         { "holds",      zfs_do_holds,           HELP_HOLDS              },
 197         { "release",    zfs_do_release,         HELP_RELEASE            },
 198         { "diff",       zfs_do_diff,            HELP_DIFF               },
 199 };
 200 
 201 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 202 
 203 zfs_command_t *current_command;
 204 
 205 static const char *
 206 get_usage(zfs_help_t idx)
 207 {
 208         switch (idx) {
 209         case HELP_CLONE:
 210                 return (gettext("\tclone [-p] [-o property=value] ... "


 237                     "[filesystem|volume|snapshot] ...\n"));
 238         case HELP_MOUNT:
 239                 return (gettext("\tmount\n"
 240                     "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
 241         case HELP_PROMOTE:
 242                 return (gettext("\tpromote <clone-filesystem>\n"));
 243         case HELP_RECEIVE:
 244                 return (gettext("\treceive [-vnFu] <filesystem|volume|"
 245                 "snapshot>\n"
 246                 "\treceive [-vnFu] [-d | -e] <filesystem>\n"));
 247         case HELP_RENAME:
 248                 return (gettext("\trename [-f] <filesystem|volume|snapshot> "
 249                     "<filesystem|volume|snapshot>\n"
 250                     "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
 251                     "\trename -r <snapshot> <snapshot>"));
 252         case HELP_ROLLBACK:
 253                 return (gettext("\trollback [-rRf] <snapshot>\n"));
 254         case HELP_SEND:
 255                 return (gettext("\tsend [-DnPpRv] [-[iI] snapshot] "
 256                     "<snapshot>\n"));



 257         case HELP_SET:
 258                 return (gettext("\tset <property=value> "
 259                     "<filesystem|volume|snapshot> ...\n"));
 260         case HELP_SHARE:
 261                 return (gettext("\tshare <-a | filesystem>\n"));
 262         case HELP_SNAPSHOT:
 263                 return (gettext("\tsnapshot [-r] [-o property=value] ... "
 264                     "<filesystem@snapname|volume@snapname> ...\n"));
 265         case HELP_UNMOUNT:
 266                 return (gettext("\tunmount [-f] "
 267                     "<-a | filesystem|mountpoint>\n"));
 268         case HELP_UNSHARE:
 269                 return (gettext("\tunshare "
 270                     "<-a | filesystem|mountpoint>\n"));
 271         case HELP_ALLOW:
 272                 return (gettext("\tallow <filesystem|volume>\n"
 273                     "\tallow [-ldug] "
 274                     "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n"
 275                     "\t    <filesystem|volume>\n"
 276                     "\tallow [-ld] -e <perm|@setname>[,...] "


3708         }
3709         if (argc > 1) {
3710                 (void) fprintf(stderr, gettext("too many arguments\n"));
3711                 usage(B_FALSE);
3712         }
3713 
3714         if (isatty(STDIN_FILENO)) {
3715                 (void) fprintf(stderr,
3716                     gettext("Error: Backup stream can not be read "
3717                     "from a terminal.\n"
3718                     "You must redirect standard input.\n"));
3719                 return (1);
3720         }
3721 
3722         err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, NULL);
3723 
3724         return (err != 0);
3725 }
3726 
3727 /*












































































































3728  * allow/unallow stuff
3729  */
3730 /* copied from zfs/sys/dsl_deleg.h */
3731 #define ZFS_DELEG_PERM_CREATE           "create"
3732 #define ZFS_DELEG_PERM_DESTROY          "destroy"
3733 #define ZFS_DELEG_PERM_SNAPSHOT         "snapshot"
3734 #define ZFS_DELEG_PERM_ROLLBACK         "rollback"
3735 #define ZFS_DELEG_PERM_CLONE            "clone"
3736 #define ZFS_DELEG_PERM_PROMOTE          "promote"
3737 #define ZFS_DELEG_PERM_RENAME           "rename"
3738 #define ZFS_DELEG_PERM_MOUNT            "mount"
3739 #define ZFS_DELEG_PERM_SHARE            "share"
3740 #define ZFS_DELEG_PERM_SEND             "send"
3741 #define ZFS_DELEG_PERM_RECEIVE          "receive"
3742 #define ZFS_DELEG_PERM_ALLOW            "allow"
3743 #define ZFS_DELEG_PERM_USERPROP         "userprop"
3744 #define ZFS_DELEG_PERM_VSCAN            "vscan" /* ??? */
3745 #define ZFS_DELEG_PERM_USERQUOTA        "userquota"
3746 #define ZFS_DELEG_PERM_GROUPQUOTA       "groupquota"
3747 #define ZFS_DELEG_PERM_USERUSED         "userused"




  72 static FILE *mnttab_file;
  73 static char history_str[HIS_MAX_RECORD_LEN];
  74 static boolean_t log_history = B_TRUE;
  75 
  76 static int zfs_do_clone(int argc, char **argv);
  77 static int zfs_do_create(int argc, char **argv);
  78 static int zfs_do_destroy(int argc, char **argv);
  79 static int zfs_do_get(int argc, char **argv);
  80 static int zfs_do_inherit(int argc, char **argv);
  81 static int zfs_do_list(int argc, char **argv);
  82 static int zfs_do_mount(int argc, char **argv);
  83 static int zfs_do_rename(int argc, char **argv);
  84 static int zfs_do_rollback(int argc, char **argv);
  85 static int zfs_do_set(int argc, char **argv);
  86 static int zfs_do_upgrade(int argc, char **argv);
  87 static int zfs_do_snapshot(int argc, char **argv);
  88 static int zfs_do_unmount(int argc, char **argv);
  89 static int zfs_do_share(int argc, char **argv);
  90 static int zfs_do_unshare(int argc, char **argv);
  91 static int zfs_do_send(int argc, char **argv);
  92 static int zfs_do_fits_send(int argc, char **argv);
  93 static int zfs_do_receive(int argc, char **argv);
  94 static int zfs_do_promote(int argc, char **argv);
  95 static int zfs_do_userspace(int argc, char **argv);
  96 static int zfs_do_allow(int argc, char **argv);
  97 static int zfs_do_unallow(int argc, char **argv);
  98 static int zfs_do_hold(int argc, char **argv);
  99 static int zfs_do_holds(int argc, char **argv);
 100 static int zfs_do_release(int argc, char **argv);
 101 static int zfs_do_diff(int argc, char **argv);
 102 
 103 /*
 104  * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
 105  */
 106 
 107 #ifdef DEBUG
 108 const char *
 109 _umem_debug_init(void)
 110 {
 111         return ("default,verbose"); /* $UMEM_DEBUG setting */
 112 }


 115 _umem_logging_init(void)
 116 {
 117         return ("fail,contents"); /* $UMEM_LOGGING setting */
 118 }
 119 #endif
 120 
 121 typedef enum {
 122         HELP_CLONE,
 123         HELP_CREATE,
 124         HELP_DESTROY,
 125         HELP_GET,
 126         HELP_INHERIT,
 127         HELP_UPGRADE,
 128         HELP_LIST,
 129         HELP_MOUNT,
 130         HELP_PROMOTE,
 131         HELP_RECEIVE,
 132         HELP_RENAME,
 133         HELP_ROLLBACK,
 134         HELP_SEND,
 135         HELP_FITS_SEND,
 136         HELP_SET,
 137         HELP_SHARE,
 138         HELP_SNAPSHOT,
 139         HELP_UNMOUNT,
 140         HELP_UNSHARE,
 141         HELP_ALLOW,
 142         HELP_UNALLOW,
 143         HELP_USERSPACE,
 144         HELP_GROUPSPACE,
 145         HELP_HOLD,
 146         HELP_HOLDS,
 147         HELP_RELEASE,
 148         HELP_DIFF,
 149 } zfs_help_t;
 150 
 151 typedef struct zfs_command {
 152         const char      *name;
 153         int             (*func)(int argc, char **argv);
 154         zfs_help_t      usage;
 155 } zfs_command_t;


 173         { "promote",    zfs_do_promote,         HELP_PROMOTE            },
 174         { "rename",     zfs_do_rename,          HELP_RENAME             },
 175         { NULL },
 176         { "list",       zfs_do_list,            HELP_LIST               },
 177         { NULL },
 178         { "set",        zfs_do_set,             HELP_SET                },
 179         { "get",        zfs_do_get,             HELP_GET                },
 180         { "inherit",    zfs_do_inherit,         HELP_INHERIT            },
 181         { "upgrade",    zfs_do_upgrade,         HELP_UPGRADE            },
 182         { "userspace",  zfs_do_userspace,       HELP_USERSPACE          },
 183         { "groupspace", zfs_do_userspace,       HELP_GROUPSPACE         },
 184         { NULL },
 185         { "mount",      zfs_do_mount,           HELP_MOUNT              },
 186         { "unmount",    zfs_do_unmount,         HELP_UNMOUNT            },
 187         { "share",      zfs_do_share,           HELP_SHARE              },
 188         { "unshare",    zfs_do_unshare,         HELP_UNSHARE            },
 189         { NULL },
 190         { "send",       zfs_do_send,            HELP_SEND               },
 191         { "receive",    zfs_do_receive,         HELP_RECEIVE            },
 192         { NULL },
 193         { "fits-send",  zfs_do_fits_send,       HELP_FITS_SEND          },
 194         { NULL },
 195         { "allow",      zfs_do_allow,           HELP_ALLOW              },
 196         { NULL },
 197         { "unallow",    zfs_do_unallow,         HELP_UNALLOW            },
 198         { NULL },
 199         { "hold",       zfs_do_hold,            HELP_HOLD               },
 200         { "holds",      zfs_do_holds,           HELP_HOLDS              },
 201         { "release",    zfs_do_release,         HELP_RELEASE            },
 202         { "diff",       zfs_do_diff,            HELP_DIFF               },
 203 };
 204 
 205 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 206 
 207 zfs_command_t *current_command;
 208 
 209 static const char *
 210 get_usage(zfs_help_t idx)
 211 {
 212         switch (idx) {
 213         case HELP_CLONE:
 214                 return (gettext("\tclone [-p] [-o property=value] ... "


 241                     "[filesystem|volume|snapshot] ...\n"));
 242         case HELP_MOUNT:
 243                 return (gettext("\tmount\n"
 244                     "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
 245         case HELP_PROMOTE:
 246                 return (gettext("\tpromote <clone-filesystem>\n"));
 247         case HELP_RECEIVE:
 248                 return (gettext("\treceive [-vnFu] <filesystem|volume|"
 249                 "snapshot>\n"
 250                 "\treceive [-vnFu] [-d | -e] <filesystem>\n"));
 251         case HELP_RENAME:
 252                 return (gettext("\trename [-f] <filesystem|volume|snapshot> "
 253                     "<filesystem|volume|snapshot>\n"
 254                     "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
 255                     "\trename -r <snapshot> <snapshot>"));
 256         case HELP_ROLLBACK:
 257                 return (gettext("\trollback [-rRf] <snapshot>\n"));
 258         case HELP_SEND:
 259                 return (gettext("\tsend [-DnPpRv] [-[iI] snapshot] "
 260                     "<snapshot>\n"));
 261         case HELP_FITS_SEND:
 262                 return (gettext("\tfits-send [-v] [-i snapshot] "
 263                     "<snapshot>\n"));
 264         case HELP_SET:
 265                 return (gettext("\tset <property=value> "
 266                     "<filesystem|volume|snapshot> ...\n"));
 267         case HELP_SHARE:
 268                 return (gettext("\tshare <-a | filesystem>\n"));
 269         case HELP_SNAPSHOT:
 270                 return (gettext("\tsnapshot [-r] [-o property=value] ... "
 271                     "<filesystem@snapname|volume@snapname> ...\n"));
 272         case HELP_UNMOUNT:
 273                 return (gettext("\tunmount [-f] "
 274                     "<-a | filesystem|mountpoint>\n"));
 275         case HELP_UNSHARE:
 276                 return (gettext("\tunshare "
 277                     "<-a | filesystem|mountpoint>\n"));
 278         case HELP_ALLOW:
 279                 return (gettext("\tallow <filesystem|volume>\n"
 280                     "\tallow [-ldug] "
 281                     "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n"
 282                     "\t    <filesystem|volume>\n"
 283                     "\tallow [-ld] -e <perm|@setname>[,...] "


3715         }
3716         if (argc > 1) {
3717                 (void) fprintf(stderr, gettext("too many arguments\n"));
3718                 usage(B_FALSE);
3719         }
3720 
3721         if (isatty(STDIN_FILENO)) {
3722                 (void) fprintf(stderr,
3723                     gettext("Error: Backup stream can not be read "
3724                     "from a terminal.\n"
3725                     "You must redirect standard input.\n"));
3726                 return (1);
3727         }
3728 
3729         err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, NULL);
3730 
3731         return (err != 0);
3732 }
3733 
3734 /*
3735  * Send a backup stream to stdout in fits format.
3736  */
3737 static int
3738 zfs_do_fits_send(int argc, char **argv)
3739 {
3740         char *fromname = NULL;
3741         char *toname = NULL;
3742         char *cp;
3743         zfs_handle_t *zhp;
3744         sendflags_t flags = { 0 };
3745         int c, err;
3746 
3747         /* check options */
3748         while ((c = getopt(argc, argv, ":i:v")) != -1) {
3749                 switch (c) {
3750                 case 'i':
3751                         if (fromname)
3752                                 usage(B_FALSE);
3753                         fromname = optarg;
3754                         break;
3755                 case 'v':
3756                         flags.verbose = B_TRUE;
3757                         break;
3758                 case ':':
3759                         (void) fprintf(stderr, gettext("missing argument for "
3760                             "'%c' option\n"), optopt);
3761                         usage(B_FALSE);
3762                         break;
3763                 case '?':
3764                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3765                             optopt);
3766                         usage(B_FALSE);
3767                 }
3768         }
3769 
3770         argc -= optind;
3771         argv += optind;
3772 
3773         /* check number of arguments */
3774         if (argc < 1) {
3775                 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
3776                 usage(B_FALSE);
3777         }
3778         if (argc > 1) {
3779                 (void) fprintf(stderr, gettext("too many arguments\n"));
3780                 usage(B_FALSE);
3781         }
3782 
3783         if (isatty(STDOUT_FILENO)) {
3784                 (void) fprintf(stderr,
3785                     gettext("Error: Stream can not be written to a terminal.\n"
3786                     "You must redirect standard output.\n"));
3787                 return (1);
3788         }
3789 
3790         cp = strchr(argv[0], '@');
3791         if (cp == NULL) {
3792                 (void) fprintf(stderr,
3793                     gettext("argument must be a snapshot\n"));
3794                 usage(B_FALSE);
3795         }
3796         *cp = '\0';
3797         toname = cp + 1;
3798         zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM);
3799         if (zhp == NULL)
3800                 return (1);
3801 
3802         /*
3803          * If they specified the full path to the snapshot, chop off
3804          * everything except the short name of the snapshot, but special
3805          * case if they specify the origin.
3806          */
3807         if (fromname && (cp = strchr(fromname, '@')) != NULL) {
3808                 char origin[ZFS_MAXNAMELEN];
3809                 zprop_source_t src;
3810 
3811                 (void) zfs_prop_get(zhp, ZFS_PROP_ORIGIN,
3812                     origin, sizeof (origin), &src, NULL, 0, B_FALSE);
3813 
3814                 if (strcmp(origin, fromname) == 0) {
3815                         fromname = NULL;
3816                         flags.fromorigin = B_TRUE;
3817                 } else {
3818                         *cp = '\0';
3819                         if (cp != fromname && strcmp(argv[0], fromname)) {
3820                                 (void) fprintf(stderr,
3821                                     gettext("incremental source must be "
3822                                     "in same filesystem\n"));
3823                                 usage(B_FALSE);
3824                         }
3825                         fromname = cp + 1;
3826                         if (strchr(fromname, '@') || strchr(fromname, '/')) {
3827                                 (void) fprintf(stderr,
3828                                     gettext("invalid incremental source\n"));
3829                                 usage(B_FALSE);
3830                         }
3831                 }
3832         }
3833 
3834         err = zfs_fits_send(zhp, fromname, toname, &flags, STDOUT_FILENO,
3835             NULL, 0);
3836 
3837         zfs_close(zhp);
3838 
3839         return (err != 0);
3840 }
3841 
3842 /*
3843  * allow/unallow stuff
3844  */
3845 /* copied from zfs/sys/dsl_deleg.h */
3846 #define ZFS_DELEG_PERM_CREATE           "create"
3847 #define ZFS_DELEG_PERM_DESTROY          "destroy"
3848 #define ZFS_DELEG_PERM_SNAPSHOT         "snapshot"
3849 #define ZFS_DELEG_PERM_ROLLBACK         "rollback"
3850 #define ZFS_DELEG_PERM_CLONE            "clone"
3851 #define ZFS_DELEG_PERM_PROMOTE          "promote"
3852 #define ZFS_DELEG_PERM_RENAME           "rename"
3853 #define ZFS_DELEG_PERM_MOUNT            "mount"
3854 #define ZFS_DELEG_PERM_SHARE            "share"
3855 #define ZFS_DELEG_PERM_SEND             "send"
3856 #define ZFS_DELEG_PERM_RECEIVE          "receive"
3857 #define ZFS_DELEG_PERM_ALLOW            "allow"
3858 #define ZFS_DELEG_PERM_USERPROP         "userprop"
3859 #define ZFS_DELEG_PERM_VSCAN            "vscan" /* ??? */
3860 #define ZFS_DELEG_PERM_USERQUOTA        "userquota"
3861 #define ZFS_DELEG_PERM_GROUPQUOTA       "groupquota"
3862 #define ZFS_DELEG_PERM_USERUSED         "userused"