FreeBSD/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
/*
 * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol>
 *
 * Given an existing dataset, create a writable copy whose initial contents
 * are the same as the source.  The newly created dataset maintains a
 * dependency on the original; the original cannot be destroyed so long as
 * the clone exists.
 *
 * The '-p' flag creates all the non-existing ancestors of the target first.
 */
zfs clone [-p] [-o prop=value] ...  
Given an existing dataset, create a writable copy whose initial contents
are the same as the source.  The newly created dataset maintains a
dependency on the original; the original cannot be destroyed so long as
the clone exists.

The '-p' flag creates all the non-existing ancestors of the target first.
zfs clone [ - p ] [ - o prop = value ] ... Given an existing dataset create a writable copy whose initial contents are the same as the source . The newly created dataset maintains a dependency on the original ; the original cannot be destroyed so long as the clone exists . The ' - p ' flag creates all the non - existing ancestors of the target first .
static int
zfs_do_clone(int argc, char **argv)
{
	zfs_handle_t *zhp = NULL;
	boolean_t parents = B_FALSE;
	nvlist_t *props;
	int ret = 0;
	int c;
	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
		nomem();
	while ((c = getopt(argc, argv, "o:p")) != -1) {
		switch (c) {
		case 'o':
			if (parseprop(props, optarg) != 0)
				return (1);
			break;
		case 'p':
			parents = B_TRUE;
			break;
		case '?':
			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
			    optopt);
			goto usage;
		}
	}
	argc -= optind;
	argv += optind;
	if (argc < 1) {
		(void) fprintf(stderr, gettext("missing source dataset "
		    "argument\n"));
		goto usage;
	}
	if (argc < 2) {
		(void) fprintf(stderr, gettext("missing target dataset "
		    "argument\n"));
		goto usage;
	}
	if (argc > 2) {
		(void) fprintf(stderr, gettext("too many arguments\n"));
		goto usage;
	}
	if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
		return (1);
	if (parents && zfs_name_valid(argv[1], ZFS_TYPE_FILESYSTEM |
	    ZFS_TYPE_VOLUME)) {
		if (zfs_dataset_exists(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM |
		    ZFS_TYPE_VOLUME))
			return (0);
		if (zfs_create_ancestors(g_zfs, argv[1]) != 0)
			return (1);
	}
	ret = zfs_clone(zhp, argv[1], props);
	if (ret == 0) {
		zfs_handle_t *clone;
		clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET);
		if (clone != NULL) {
			if (should_auto_mount(clone)) {
				if ((ret = zfs_mount(clone, NULL, 0)) != 0) {
					(void) fprintf(stderr, gettext("clone "
					    "successfully created, "
					    "but not mounted\n"));
				} else if ((ret = zfs_share(clone)) != 0) {
					(void) fprintf(stderr, gettext("clone "
					    "successfully created, "
					    "but not shared\n"));
				}
			}
			zfs_close(clone);
		}
	}
	zfs_close(zhp);
	nvlist_free(props);
	return (!!ret);
usage:
	if (zhp)
		zfs_close(zhp);
	nvlist_free(props);
	usage(B_FALSE);
	return (-1);
}
static int zfs_do_clone ( int argc , char * * argv ) { zfs_handle_t * zhp = NULL ; boolean_t parents = B_FALSE ; nvlist_t * props ; int ret = 0 ; int c ; if ( nvlist_alloc ( & props , NV_UNIQUE_NAME , 0 ) != 0 ) nomem ( ) ; while ( ( c = getopt ( argc , argv , " " ) ) != -1 ) { switch ( c ) { case ' ' : if ( parseprop ( props , optarg ) != 0 ) return ( 1 ) ; break ; case ' ' : parents = B_TRUE ; break ; case ' ' : ( void ) fprintf ( stderr , gettext ( " \n " ) , optopt ) ; goto usage ; } } argc -= optind ; argv += optind ; if ( argc < 1 ) { ( void ) fprintf ( stderr , gettext ( " " " \n " ) ) ; goto usage ; } if ( argc < 2 ) { ( void ) fprintf ( stderr , gettext ( " " " \n " ) ) ; goto usage ; } if ( argc > 2 ) { ( void ) fprintf ( stderr , gettext ( " \n " ) ) ; goto usage ; } if ( ( zhp = zfs_open ( g_zfs , argv [ 0 ] , ZFS_TYPE_SNAPSHOT ) ) == NULL ) return ( 1 ) ; if ( parents && zfs_name_valid ( argv [ 1 ] , ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME ) ) { if ( zfs_dataset_exists ( g_zfs , argv [ 1 ] , ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME ) ) return ( 0 ) ; if ( zfs_create_ancestors ( g_zfs , argv [ 1 ] ) != 0 ) return ( 1 ) ; } ret = zfs_clone ( zhp , argv [ 1 ] , props ) ; if ( ret == 0 ) { zfs_handle_t * clone ; clone = zfs_open ( g_zfs , argv [ 1 ] , ZFS_TYPE_DATASET ) ; if ( clone != NULL ) { if ( should_auto_mount ( clone ) ) { if ( ( ret = zfs_mount ( clone , NULL , 0 ) ) != 0 ) { ( void ) fprintf ( stderr , gettext ( " " " " " \n " ) ) ; } else if ( ( ret = zfs_share ( clone ) ) != 0 ) { ( void ) fprintf ( stderr , gettext ( " " " " " \n " ) ) ; } } zfs_close ( clone ) ; } } zfs_close ( zhp ) ; nvlist_free ( props ) ; return ( ! ! ret ) ; usage : if ( zhp ) zfs_close ( zhp ) ; nvlist_free ( props ) ; usage ( B_FALSE ) ; return ( -1 ) ; }
zfs clone [-p] [-o prop=value] ... <snap> <fs | vol>
 Given an existing dataset, create a writable copy whose initial contents
 are the same as the source.
zfs clone [ - p ] [ - o prop = value ] ... <snap > <fs | vol > Given an existing dataset create a writable copy whose initial contents are the same as the source .
/* check options */ /* check number of arguments */ /* open the source dataset */ /*
		 * Now create the ancestors of the target dataset.  If the
		 * target already exists and '-p' option was used we should not
		 * complain.
		 */ /* pass to libzfs */ /* create the mountpoint if necessary */ /*
			 * If the user doesn't want the dataset
			 * automatically mounted, then skip the mount/share
			 * step.
			 */