Print this page
FAR: generating send-streams in portable format
This commit adds a switch '-F' to  zfs send. This set, zfs send generates
a stream in FAR-format instead of the traditional zfs stream format. The
generated send stream is compatible with the stream generated from 'btrfs send'
and can in principle easily be received to any filesystem.


 235                     "[-o property[,...]] [-t type[,...]] [-s property] ...\n"
 236                     "\t    [-S property] ... "
 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>[,...] "


3504         usage(B_FALSE);
3505         return (-1);
3506 }
3507 
3508 /*
3509  * Send a backup stream to stdout.
3510  */
3511 static int
3512 zfs_do_send(int argc, char **argv)
3513 {
3514         char *fromname = NULL;
3515         char *toname = NULL;
3516         char *cp;
3517         zfs_handle_t *zhp;
3518         sendflags_t flags = { 0 };
3519         int c, err;
3520         nvlist_t *dbgnv = NULL;
3521         boolean_t extraverbose = B_FALSE;
3522 
3523         /* check options */
3524         while ((c = getopt(argc, argv, ":i:I:RDpvnP")) != -1) {
3525                 switch (c) {
3526                 case 'i':
3527                         if (fromname)
3528                                 usage(B_FALSE);
3529                         fromname = optarg;
3530                         break;
3531                 case 'I':
3532                         if (fromname)
3533                                 usage(B_FALSE);
3534                         fromname = optarg;
3535                         flags.doall = B_TRUE;
3536                         break;
3537                 case 'R':
3538                         flags.replicate = B_TRUE;
3539                         break;
3540                 case 'p':
3541                         flags.props = B_TRUE;
3542                         break;
3543                 case 'P':
3544                         flags.parsable = B_TRUE;
3545                         flags.verbose = B_TRUE;
3546                         break;
3547                 case 'v':
3548                         if (flags.verbose)
3549                                 extraverbose = B_TRUE;
3550                         flags.verbose = B_TRUE;
3551                         flags.progress = B_TRUE;
3552                         break;
3553                 case 'D':
3554                         flags.dedup = B_TRUE;
3555                         break;
3556                 case 'n':
3557                         flags.dryrun = B_TRUE;
3558                         break;



3559                 case ':':
3560                         (void) fprintf(stderr, gettext("missing argument for "
3561                             "'%c' option\n"), optopt);
3562                         usage(B_FALSE);
3563                         break;
3564                 case '?':
3565                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3566                             optopt);
3567                         usage(B_FALSE);
3568                 }
3569         }
3570 
3571         argc -= optind;
3572         argv += optind;
3573 
3574         /* check number of arguments */
3575         if (argc < 1) {
3576                 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
3577                 usage(B_FALSE);
3578         }
3579         if (argc > 1) {
3580                 (void) fprintf(stderr, gettext("too many arguments\n"));
3581                 usage(B_FALSE);
3582         }
3583 





3584         if (!flags.dryrun && isatty(STDOUT_FILENO)) {
3585                 (void) fprintf(stderr,
3586                     gettext("Error: Stream can not be written to a terminal.\n"
3587                     "You must redirect standard output.\n"));
3588                 return (1);
3589         }
3590 
3591         cp = strchr(argv[0], '@');
3592         if (cp == NULL) {
3593                 (void) fprintf(stderr,
3594                     gettext("argument must be a snapshot\n"));
3595                 usage(B_FALSE);
3596         }
3597         *cp = '\0';
3598         toname = cp + 1;
3599         zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
3600         if (zhp == NULL)
3601                 return (1);
3602 
3603         /*




 235                     "[-o property[,...]] [-t type[,...]] [-s property] ...\n"
 236                     "\t    [-S property] ... "
 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] <snapshot>\n"
 256                     "\tsend -F [-nPRv] [-[iI] snapshot] <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>[,...] "


3504         usage(B_FALSE);
3505         return (-1);
3506 }
3507 
3508 /*
3509  * Send a backup stream to stdout.
3510  */
3511 static int
3512 zfs_do_send(int argc, char **argv)
3513 {
3514         char *fromname = NULL;
3515         char *toname = NULL;
3516         char *cp;
3517         zfs_handle_t *zhp;
3518         sendflags_t flags = { 0 };
3519         int c, err;
3520         nvlist_t *dbgnv = NULL;
3521         boolean_t extraverbose = B_FALSE;
3522 
3523         /* check options */
3524         while ((c = getopt(argc, argv, ":i:I:RDpvnPF")) != -1) {
3525                 switch (c) {
3526                 case 'i':
3527                         if (fromname)
3528                                 usage(B_FALSE);
3529                         fromname = optarg;
3530                         break;
3531                 case 'I':
3532                         if (fromname)
3533                                 usage(B_FALSE);
3534                         fromname = optarg;
3535                         flags.doall = B_TRUE;
3536                         break;
3537                 case 'R':
3538                         flags.replicate = B_TRUE;
3539                         break;
3540                 case 'p':
3541                         flags.props = B_TRUE;
3542                         break;
3543                 case 'P':
3544                         flags.parsable = B_TRUE;
3545                         flags.verbose = B_TRUE;
3546                         break;
3547                 case 'v':
3548                         if (flags.verbose)
3549                                 extraverbose = B_TRUE;
3550                         flags.verbose = B_TRUE;
3551                         flags.progress = B_TRUE;
3552                         break;
3553                 case 'D':
3554                         flags.dedup = B_TRUE;
3555                         break;
3556                 case 'n':
3557                         flags.dryrun = B_TRUE;
3558                         break;
3559                 case 'F':
3560                         flags.far = B_TRUE;
3561                         break;
3562                 case ':':
3563                         (void) fprintf(stderr, gettext("missing argument for "
3564                             "'%c' option\n"), optopt);
3565                         usage(B_FALSE);
3566                         break;
3567                 case '?':
3568                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3569                             optopt);
3570                         usage(B_FALSE);
3571                 }
3572         }
3573 
3574         argc -= optind;
3575         argv += optind;
3576 
3577         /* check number of arguments */
3578         if (argc < 1) {
3579                 (void) fprintf(stderr, gettext("missing snapshot argument\n"));
3580                 usage(B_FALSE);
3581         }
3582         if (argc > 1) {
3583                 (void) fprintf(stderr, gettext("too many arguments\n"));
3584                 usage(B_FALSE);
3585         }
3586 
3587         if (flags.far && (flags.dedup || flags.props)) {
3588                 (void) fprintf(stderr, gettext("options -D and -p are not "
3589                     "allowed with -F\n"));
3590                 usage(B_FALSE);
3591         }
3592         if (!flags.dryrun && isatty(STDOUT_FILENO)) {
3593                 (void) fprintf(stderr,
3594                     gettext("Error: Stream can not be written to a terminal.\n"
3595                     "You must redirect standard output.\n"));
3596                 return (1);
3597         }
3598 
3599         cp = strchr(argv[0], '@');
3600         if (cp == NULL) {
3601                 (void) fprintf(stderr,
3602                     gettext("argument must be a snapshot\n"));
3603                 usage(B_FALSE);
3604         }
3605         *cp = '\0';
3606         toname = cp + 1;
3607         zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
3608         if (zhp == NULL)
3609                 return (1);
3610 
3611         /*