FreeBSD/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
/*
 * Given a propname=value nvpair to set, parse any numeric properties
 * (index, boolean, etc) if they are specified as strings and add the
 * resulting nvpair to the returned nvlist.
 *
 * At the DSL layer, all properties are either 64-bit numbers or strings.
 * We want the user to be able to ignore this fact and specify properties
 * as native values (numbers, for example) or as strings (to simplify
 * command line utilities).  This also handles converting index types
 * (compression, checksum, etc) from strings to their on-disk index.
 */
Given a propname=value nvpair to set, parse any numeric properties
(index, boolean, etc) if they are specified as strings and add the
resulting nvpair to the returned nvlist.

At the DSL layer, all properties are either 64-bit numbers or strings.
We want the user to be able to ignore this fact and specify properties
as native values (numbers, for example) or as strings (to simplify
command line utilities).  This also handles converting index types
(compression, checksum, etc) from strings to their on-disk index.
Given a propname = value nvpair to set parse any numeric properties ( index boolean etc ) if they are specified as strings and add the resulting nvpair to the returned nvlist . At the DSL layer all properties are either 64 - bit numbers or strings . We want the user to be able to ignore this fact and specify properties as native values ( numbers for example ) or as strings ( to simplify command line utilities ) . This also handles converting index types ( compression checksum etc ) from strings to their on - disk index .
int
zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
    zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
    const char *errbuf)
{
	data_type_t datatype = nvpair_type(elem);
	zprop_type_t proptype;
	const char *propname;
	char *value;
	boolean_t isnone = B_FALSE;
	if (type == ZFS_TYPE_POOL) {
		proptype = zpool_prop_get_type(prop);
		propname = zpool_prop_to_name(prop);
	} else {
		proptype = zfs_prop_get_type(prop);
		propname = zfs_prop_to_name(prop);
	}
	*svalp = NULL;
	*ivalp = 0;
	switch (proptype) {
	case PROP_TYPE_STRING:
		if (datatype != DATA_TYPE_STRING) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "'%s' must be a string"), nvpair_name(elem));
			goto error;
		}
		(void) nvpair_value_string(elem, svalp);
		if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "'%s' is too long"), nvpair_name(elem));
			goto error;
		}
		break;
	case PROP_TYPE_NUMBER:
		if (datatype == DATA_TYPE_STRING) {
			(void) nvpair_value_string(elem, &value);
			if (strcmp(value, "none") == 0) {
				isnone = B_TRUE;
			} else if (zfs_nicestrtonum(hdl, value, ivalp)
			    != 0) {
				goto error;
			}
		} else if (datatype == DATA_TYPE_UINT64) {
			(void) nvpair_value_uint64(elem, ivalp);
		} else {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "'%s' must be a number"), nvpair_name(elem));
			goto error;
		}
		if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
		    (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "use 'none' to disable quota/refquota"));
			goto error;
		}
		if ((type & ZFS_TYPE_DATASET) && isnone &&
		    (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
		    prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
			*ivalp = UINT64_MAX;
		}
		break;
	case PROP_TYPE_INDEX:
		if (datatype != DATA_TYPE_STRING) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "'%s' must be a string"), nvpair_name(elem));
			goto error;
		}
		(void) nvpair_value_string(elem, &value);
		if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "'%s' must be one of '%s'"), propname,
			    zprop_values(prop, type));
			goto error;
		}
		break;
	default:
		abort();
	}
	if (*svalp != NULL) {
		if (nvlist_add_string(ret, propname, *svalp) != 0) {
			(void) no_memory(hdl);
			return (-1);
		}
	} else {
		if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
			(void) no_memory(hdl);
			return (-1);
		}
	}
	return (0);
error:
	(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
	return (-1);
}
int zprop_parse_value ( libzfs_handle_t * hdl , nvpair_t * elem , int prop , zfs_type_t type , nvlist_t * ret , char * * svalp , uint64_t * ivalp , const char * errbuf ) { data_type_t datatype = nvpair_type ( elem ) ; zprop_type_t proptype ; const char * propname ; char * value ; boolean_t isnone = B_FALSE ; if ( type == ZFS_TYPE_POOL ) { proptype = zpool_prop_get_type ( prop ) ; propname = zpool_prop_to_name ( prop ) ; } else { proptype = zfs_prop_get_type ( prop ) ; propname = zfs_prop_to_name ( prop ) ; } * svalp = NULL ; * ivalp = 0 ; switch ( proptype ) { case PROP_TYPE_STRING : if ( datatype != DATA_TYPE_STRING ) { zfs_error_aux ( hdl , dgettext ( TEXT_DOMAIN , " " ) , nvpair_name ( elem ) ) ; goto error ; } ( void ) nvpair_value_string ( elem , svalp ) ; if ( strlen ( * svalp ) >= ZFS_MAXPROPLEN ) { zfs_error_aux ( hdl , dgettext ( TEXT_DOMAIN , " " ) , nvpair_name ( elem ) ) ; goto error ; } break ; case PROP_TYPE_NUMBER : if ( datatype == DATA_TYPE_STRING ) { ( void ) nvpair_value_string ( elem , & value ) ; if ( strcmp ( value , " " ) == 0 ) { isnone = B_TRUE ; } else if ( zfs_nicestrtonum ( hdl , value , ivalp ) != 0 ) { goto error ; } } else if ( datatype == DATA_TYPE_UINT64 ) { ( void ) nvpair_value_uint64 ( elem , ivalp ) ; } else { zfs_error_aux ( hdl , dgettext ( TEXT_DOMAIN , " " ) , nvpair_name ( elem ) ) ; goto error ; } if ( ( type & ZFS_TYPE_DATASET ) && * ivalp == 0 && ! isnone && ( prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA ) ) { zfs_error_aux ( hdl , dgettext ( TEXT_DOMAIN , " " ) ) ; goto error ; } if ( ( type & ZFS_TYPE_DATASET ) && isnone && ( prop == ZFS_PROP_FILESYSTEM_LIMIT || prop == ZFS_PROP_SNAPSHOT_LIMIT ) ) { * ivalp = UINT64_MAX ; } break ; case PROP_TYPE_INDEX : if ( datatype != DATA_TYPE_STRING ) { zfs_error_aux ( hdl , dgettext ( TEXT_DOMAIN , " " ) , nvpair_name ( elem ) ) ; goto error ; } ( void ) nvpair_value_string ( elem , & value ) ; if ( zprop_string_to_index ( prop , value , ivalp , type ) != 0 ) { zfs_error_aux ( hdl , dgettext ( TEXT_DOMAIN , " " ) , propname , zprop_values ( prop , type ) ) ; goto error ; } break ; default : abort ( ) ; } if ( * svalp != NULL ) { if ( nvlist_add_string ( ret , propname , * svalp ) != 0 ) { ( void ) no_memory ( hdl ) ; return ( -1 ) ; } } else { if ( nvlist_add_uint64 ( ret , propname , * ivalp ) != 0 ) { ( void ) no_memory ( hdl ) ; return ( -1 ) ; } } return ( 0 ) ; error : ( void ) zfs_error ( hdl , EZFS_BADPROP , errbuf ) ; return ( -1 ) ; }
Given a propname=value nvpair to set, parse any numeric properties
 (index, boolean, etc) if they are specified as strings and add the
 resulting nvpair to the returned nvlist.
Given a propname = value nvpair to set parse any numeric properties ( index boolean etc ) if they are specified as strings and add the resulting nvpair to the returned nvlist .
/*
	 * Convert any properties to the internal DSL value types.
	 */ /*
		 * Quota special: force 'none' and don't allow 0.
		 */ /*
		 * Special handling for "*_limit=none". In this case it's not
		 * 0 but UINT64_MAX.
		 */ /*
	 * Add the result to our return set of properties.
	 */