FreeBSD/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
/*
 * Sort datasets by specified columns.
 *
 * o  Numeric types sort in ascending order.
 * o  String types sort in alphabetical order.
 * o  Types inappropriate for a row sort that row to the literal
 *    bottom, regardless of the specified ordering.
 *
 * If no sort columns are specified, or two datasets compare equally
 * across all specified columns, they are sorted alphabetically by name
 * with snapshots grouped under their parents.
 */
Sort datasets by specified columns.
o  Numeric types sort in ascending order.
o  String types sort in alphabetical order.
o  Types inappropriate for a row sort that row to the literal
bottom, regardless of the specified ordering.

If no sort columns are specified, or two datasets compare equally
across all specified columns, they are sorted alphabetically by name
with snapshots grouped under their parents.
Sort datasets by specified columns . o Numeric types sort in ascending order . o String types sort in alphabetical order . o Types inappropriate for a row sort that row to the literal bottom regardless of the specified ordering . If no sort columns are specified or two datasets compare equally across all specified columns they are sorted alphabetically by name with snapshots grouped under their parents .
static int
zfs_sort(const void *larg, const void *rarg, void *data)
{
	zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
	zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
	zfs_sort_column_t *sc = (zfs_sort_column_t *)data;
	zfs_sort_column_t *psc;
	for (psc = sc; psc != NULL; psc = psc->sc_next) {
		char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
		char *lstr, *rstr;
		uint64_t lnum, rnum;
		boolean_t lvalid, rvalid;
		int ret = 0;
		lstr = rstr = NULL;
		if (psc->sc_prop == ZPROP_INVAL) {
			nvlist_t *luser, *ruser;
			nvlist_t *lval, *rval;
			luser = zfs_get_user_props(l);
			ruser = zfs_get_user_props(r);
			lvalid = (nvlist_lookup_nvlist(luser,
			    psc->sc_user_prop, &lval) == 0);
			rvalid = (nvlist_lookup_nvlist(ruser,
			    psc->sc_user_prop, &rval) == 0);
			if (lvalid)
				verify(nvlist_lookup_string(lval,
				    ZPROP_VALUE, &lstr) == 0);
			if (rvalid)
				verify(nvlist_lookup_string(rval,
				    ZPROP_VALUE, &rstr) == 0);
		} else if (psc->sc_prop == ZFS_PROP_NAME) {
			lvalid = rvalid = B_TRUE;
			(void) strlcpy(lbuf, zfs_get_name(l), sizeof(lbuf));
			(void) strlcpy(rbuf, zfs_get_name(r), sizeof(rbuf));
			lstr = lbuf;
			rstr = rbuf;
		} else if (zfs_prop_is_string(psc->sc_prop)) {
			lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
			    sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0);
			rvalid = (zfs_prop_get(r, psc->sc_prop, rbuf,
			    sizeof (rbuf), NULL, NULL, 0, B_TRUE) == 0);
			lstr = lbuf;
			rstr = rbuf;
		} else {
			lvalid = zfs_prop_valid_for_type(psc->sc_prop,
			    zfs_get_type(l));
			rvalid = zfs_prop_valid_for_type(psc->sc_prop,
			    zfs_get_type(r));
			if (lvalid)
				(void) zfs_prop_get_numeric(l, psc->sc_prop,
				    &lnum, NULL, NULL, 0);
			if (rvalid)
				(void) zfs_prop_get_numeric(r, psc->sc_prop,
				    &rnum, NULL, NULL, 0);
		}
		if (!lvalid && !rvalid)
			continue;
		else if (!lvalid)
			return (1);
		else if (!rvalid)
			return (-1);
		if (lstr)
			ret = strcmp(lstr, rstr);
		else if (lnum < rnum)
			ret = -1;
		else if (lnum > rnum)
			ret = 1;
		if (ret != 0) {
			if (psc->sc_reverse == B_TRUE)
				ret = (ret < 0) ? 1 : -1;
			return (ret);
		}
	}
	return (zfs_compare(larg, rarg, NULL));
}
static int zfs_sort ( const void * larg , const void * rarg , void * data ) { zfs_handle_t * l = ( ( zfs_node_t * ) larg ) -> zn_handle ; zfs_handle_t * r = ( ( zfs_node_t * ) rarg ) -> zn_handle ; zfs_sort_column_t * sc = ( zfs_sort_column_t * ) data ; zfs_sort_column_t * psc ; for ( psc = sc ; psc != NULL ; psc = psc -> sc_next ) { char lbuf [ ZFS_MAXPROPLEN ] , rbuf [ ZFS_MAXPROPLEN ] ; char * lstr , * rstr ; uint64_t lnum , rnum ; boolean_t lvalid , rvalid ; int ret = 0 ; lstr = rstr = NULL ; if ( psc -> sc_prop == ZPROP_INVAL ) { nvlist_t * luser , * ruser ; nvlist_t * lval , * rval ; luser = zfs_get_user_props ( l ) ; ruser = zfs_get_user_props ( r ) ; lvalid = ( nvlist_lookup_nvlist ( luser , psc -> sc_user_prop , & lval ) == 0 ) ; rvalid = ( nvlist_lookup_nvlist ( ruser , psc -> sc_user_prop , & rval ) == 0 ) ; if ( lvalid ) verify ( nvlist_lookup_string ( lval , ZPROP_VALUE , & lstr ) == 0 ) ; if ( rvalid ) verify ( nvlist_lookup_string ( rval , ZPROP_VALUE , & rstr ) == 0 ) ; } else if ( psc -> sc_prop == ZFS_PROP_NAME ) { lvalid = rvalid = B_TRUE ; ( void ) strlcpy ( lbuf , zfs_get_name ( l ) , sizeof ( lbuf ) ) ; ( void ) strlcpy ( rbuf , zfs_get_name ( r ) , sizeof ( rbuf ) ) ; lstr = lbuf ; rstr = rbuf ; } else if ( zfs_prop_is_string ( psc -> sc_prop ) ) { lvalid = ( zfs_prop_get ( l , psc -> sc_prop , lbuf , sizeof ( lbuf ) , NULL , NULL , 0 , B_TRUE ) == 0 ) ; rvalid = ( zfs_prop_get ( r , psc -> sc_prop , rbuf , sizeof ( rbuf ) , NULL , NULL , 0 , B_TRUE ) == 0 ) ; lstr = lbuf ; rstr = rbuf ; } else { lvalid = zfs_prop_valid_for_type ( psc -> sc_prop , zfs_get_type ( l ) ) ; rvalid = zfs_prop_valid_for_type ( psc -> sc_prop , zfs_get_type ( r ) ) ; if ( lvalid ) ( void ) zfs_prop_get_numeric ( l , psc -> sc_prop , & lnum , NULL , NULL , 0 ) ; if ( rvalid ) ( void ) zfs_prop_get_numeric ( r , psc -> sc_prop , & rnum , NULL , NULL , 0 ) ; } if ( ! lvalid && ! rvalid ) continue ; else if ( ! lvalid ) return ( 1 ) ; else if ( ! rvalid ) return ( -1 ) ; if ( lstr ) ret = strcmp ( lstr , rstr ) ; else if ( lnum < rnum ) ret = -1 ; else if ( lnum > rnum ) ret = 1 ; if ( ret != 0 ) { if ( psc -> sc_reverse == B_TRUE ) ret = ( ret < 0 ) ? 1 : -1 ; return ( ret ) ; } } return ( zfs_compare ( larg , rarg , NULL ) ) ; }
Sort datasets by specified columns.
Sort datasets by specified columns .
/*
		 * We group the checks below the generic code.  If 'lstr' and
		 * 'rstr' are non-NULL, then we do a string based comparison.
		 * Otherwise, we compare 'lnum' and 'rnum'.
		 */