FreeBSD/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
/*
 * spec is a string like "A,B%C,D"
 *
 * <snaps>, where <snaps> can be:
 *      <snap>          (single snapshot)
 *      <snap>%<snap>   (range of snapshots, inclusive)
 *      %<snap>         (range of snapshots, starting with earliest)
 *      <snap>%         (range of snapshots, ending with last)
 *      %               (all snapshots)
 *      <snaps>[,...]   (comma separated list of the above)
 *
 * If a snapshot can not be opened, continue trying to open the others, but
 * return ENOENT at the end.
 */


If a snapshot can not be opened, continue trying to open the others, but
return ENOENT at the end.
If a snapshot can not be opened continue trying to open the others but return ENOENT at the end .
int
zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
    zfs_iter_f func, void *arg)
{
	char *buf, *comma_separated, *cp;
	int err = 0;
	int ret = 0;
	buf = zfs_strdup(fs_zhp->zfs_hdl, spec_orig);
	cp = buf;
	while ((comma_separated = strsep(&cp, ",")) != NULL) {
		char *pct = strchr(comma_separated, '%');
		if (pct != NULL) {
			snapspec_arg_t ssa = { 0 };
			ssa.ssa_func = func;
			ssa.ssa_arg = arg;
			if (pct == comma_separated)
				ssa.ssa_seenfirst = B_TRUE;
			else
				ssa.ssa_first = comma_separated;
			*pct = '\0';
			ssa.ssa_last = pct + 1;
			if (ssa.ssa_last[0] != '\0') {
				char snapname[ZFS_MAXNAMELEN];
				(void) snprintf(snapname, sizeof (snapname),
				    "%s@%s", zfs_get_name(fs_zhp),
				    ssa.ssa_last);
				if (!zfs_dataset_exists(fs_zhp->zfs_hdl,
				    snapname, ZFS_TYPE_SNAPSHOT)) {
					ret = ENOENT;
					continue;
				}
			}
			err = zfs_iter_snapshots_sorted(fs_zhp,
			    snapspec_cb, &ssa);
			if (ret == 0)
				ret = err;
			if (ret == 0 && (!ssa.ssa_seenfirst ||
			    (ssa.ssa_last[0] != '\0' && !ssa.ssa_seenlast))) {
				ret = ENOENT;
			}
		} else {
			char snapname[ZFS_MAXNAMELEN];
			zfs_handle_t *snap_zhp;
			(void) snprintf(snapname, sizeof (snapname), "%s@%s",
			    zfs_get_name(fs_zhp), comma_separated);
			snap_zhp = make_dataset_handle(fs_zhp->zfs_hdl,
			    snapname);
			if (snap_zhp == NULL) {
				ret = ENOENT;
				continue;
			}
			err = func(snap_zhp, arg);
			if (ret == 0)
				ret = err;
		}
	}
	free(buf);
	return (ret);
}
int zfs_iter_snapspec ( zfs_handle_t * fs_zhp , const char * spec_orig , zfs_iter_f func , void * arg ) { char * buf , * comma_separated , * cp ; int err = 0 ; int ret = 0 ; buf = zfs_strdup ( fs_zhp -> zfs_hdl , spec_orig ) ; cp = buf ; while ( ( comma_separated = strsep ( & cp , " " ) ) != NULL ) { char * pct = strchr ( comma_separated , ' ' ) ; if ( pct != NULL ) { snapspec_arg_t ssa = { 0 } ; ssa . ssa_func = func ; ssa . ssa_arg = arg ; if ( pct == comma_separated ) ssa . ssa_seenfirst = B_TRUE ; else ssa . ssa_first = comma_separated ; * pct = ' \0 ' ; ssa . ssa_last = pct + 1 ; if ( ssa . ssa_last [ 0 ] != ' \0 ' ) { char snapname [ ZFS_MAXNAMELEN ] ; ( void ) snprintf ( snapname , sizeof ( snapname ) , " " , zfs_get_name ( fs_zhp ) , ssa . ssa_last ) ; if ( ! zfs_dataset_exists ( fs_zhp -> zfs_hdl , snapname , ZFS_TYPE_SNAPSHOT ) ) { ret = ENOENT ; continue ; } } err = zfs_iter_snapshots_sorted ( fs_zhp , snapspec_cb , & ssa ) ; if ( ret == 0 ) ret = err ; if ( ret == 0 && ( ! ssa . ssa_seenfirst || ( ssa . ssa_last [ 0 ] != ' \0 ' && ! ssa . ssa_seenlast ) ) ) { ret = ENOENT ; } } else { char snapname [ ZFS_MAXNAMELEN ] ; zfs_handle_t * snap_zhp ; ( void ) snprintf ( snapname , sizeof ( snapname ) , " " , zfs_get_name ( fs_zhp ) , comma_separated ) ; snap_zhp = make_dataset_handle ( fs_zhp -> zfs_hdl , snapname ) ; if ( snap_zhp == NULL ) { ret = ENOENT ; continue ; } err = func ( snap_zhp , arg ) ; if ( ret == 0 ) ret = err ; } } free ( buf ) ; return ( ret ) ; }
spec is a string like "A,B%C,D"
 <snaps>, where <snaps> can be:
      <snap>          (single snapshot)
      <snap>%<snap>   (range of snapshots, inclusive)
      %<snap>         (range of snapshots, starting with earliest)
      <snap>%         (range of snapshots, ending with last)
      %               (all snapshots)
      <snaps>[,...]   (comma separated list of the above)
spec is a string like " A B%C D " <snaps > where <snaps > can be : <snap > ( single snapshot ) <snap > %<snap > ( range of snapshots inclusive ) %<snap > ( range of snapshots starting with earliest ) <snap > % ( range of snapshots ending with last ) % ( all snapshots ) <snaps > [ ... ] ( comma separated list of the above )
/*
			 * If there is a lastname specified, make sure it
			 * exists.
			 */