usr/src/lib/libzfs/common/libzfs_dataset.c
changeset 9396 f41cf682d0d3
parent 8845 91af0d9c0790
child 9469 4f68f041ddcd
equal deleted inserted replaced
9395:2db090840cf7 9396:f41cf682d0d3
    43 #include <priv.h>
    43 #include <priv.h>
    44 #include <pwd.h>
    44 #include <pwd.h>
    45 #include <grp.h>
    45 #include <grp.h>
    46 #include <stddef.h>
    46 #include <stddef.h>
    47 #include <ucred.h>
    47 #include <ucred.h>
       
    48 #include <idmap.h>
       
    49 #include <aclutils.h>
    48 
    50 
    49 #include <sys/spa.h>
    51 #include <sys/spa.h>
    50 #include <sys/zap.h>
    52 #include <sys/zap.h>
    51 #include <libzfs.h>
    53 #include <libzfs.h>
    52 
    54 
    54 #include "zfs_prop.h"
    56 #include "zfs_prop.h"
    55 #include "libzfs_impl.h"
    57 #include "libzfs_impl.h"
    56 #include "zfs_deleg.h"
    58 #include "zfs_deleg.h"
    57 
    59 
    58 static int zvol_create_link_common(libzfs_handle_t *, const char *, int);
    60 static int zvol_create_link_common(libzfs_handle_t *, const char *, int);
       
    61 static int userquota_propname_decode(const char *propname, boolean_t zoned,
       
    62     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
    59 
    63 
    60 /*
    64 /*
    61  * Given a single type (not a mask of types), return the type in a human
    65  * Given a single type (not a mask of types), return the type in a human
    62  * readable form.
    66  * readable form.
    63  */
    67  */
   119 	return (dgettext(TEXT_DOMAIN, "volume"));
   123 	return (dgettext(TEXT_DOMAIN, "volume"));
   120 }
   124 }
   121 
   125 
   122 /*
   126 /*
   123  * Validate a ZFS path.  This is used even before trying to open the dataset, to
   127  * Validate a ZFS path.  This is used even before trying to open the dataset, to
   124  * provide a more meaningful error message.  We place a more useful message in
   128  * provide a more meaningful error message.  We call zfs_error_aux() to
   125  * 'buf' detailing exactly why the name was not valid.
   129  * explain exactly why the name was not valid.
   126  */
   130  */
   127 static int
   131 static int
   128 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
   132 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
   129     boolean_t modifying)
   133     boolean_t modifying)
   130 {
   134 {
   344 
   348 
   345 	if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
   349 	if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
   346 		return (-1);
   350 		return (-1);
   347 	}
   351 	}
   348 
   352 
       
   353 	/*
       
   354 	 * XXX Why do we store the user props separately, in addition to
       
   355 	 * storing them in zfs_props?
       
   356 	 */
   349 	if ((userprops = process_user_props(zhp, allprops)) == NULL) {
   357 	if ((userprops = process_user_props(zhp, allprops)) == NULL) {
   350 		nvlist_free(allprops);
   358 		nvlist_free(allprops);
   351 		return (-1);
   359 		return (-1);
   352 	}
   360 	}
   353 
   361 
   770 	if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
   778 	if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
   771 		(void) no_memory(hdl);
   779 		(void) no_memory(hdl);
   772 		return (NULL);
   780 		return (NULL);
   773 	}
   781 	}
   774 
   782 
       
   783 	/*
       
   784 	 * Make sure this property is valid and applies to this type.
       
   785 	 */
       
   786 
   775 	elem = NULL;
   787 	elem = NULL;
   776 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
   788 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
   777 		const char *propname = nvpair_name(elem);
   789 		const char *propname = nvpair_name(elem);
   778 
   790 
   779 		/*
   791 		prop = zfs_name_to_prop(propname);
   780 		 * Make sure this property is valid and applies to this type.
   792 		if (prop == ZPROP_INVAL && zfs_prop_user(propname)) {
   781 		 */
       
   782 		if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
       
   783 			if (!zfs_prop_user(propname)) {
       
   784 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
       
   785 				    "invalid property '%s'"), propname);
       
   786 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
       
   787 				goto error;
       
   788 			}
       
   789 
       
   790 			/*
   793 			/*
   791 			 * If this is a user property, make sure it's a
   794 			 * This is a user property: make sure it's a
   792 			 * string, and that it's less than ZAP_MAXNAMELEN.
   795 			 * string, and that it's less than ZAP_MAXNAMELEN.
   793 			 */
   796 			 */
   794 			if (nvpair_type(elem) != DATA_TYPE_STRING) {
   797 			if (nvpair_type(elem) != DATA_TYPE_STRING) {
   795 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
   798 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
   796 				    "'%s' must be a string"), propname);
   799 				    "'%s' must be a string"), propname);
   812 				goto error;
   815 				goto error;
   813 			}
   816 			}
   814 			continue;
   817 			continue;
   815 		}
   818 		}
   816 
   819 
       
   820 		/*
       
   821 		 * Currently, only user properties can be modified on
       
   822 		 * snapshots.
       
   823 		 */
   817 		if (type == ZFS_TYPE_SNAPSHOT) {
   824 		if (type == ZFS_TYPE_SNAPSHOT) {
   818 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
   825 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
   819 			    "this property can not be modified for snapshots"));
   826 			    "this property can not be modified for snapshots"));
   820 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
   827 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
       
   828 			goto error;
       
   829 		}
       
   830 
       
   831 		if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) {
       
   832 			zfs_userquota_prop_t uqtype;
       
   833 			char newpropname[128];
       
   834 			char domain[128];
       
   835 			uint64_t rid;
       
   836 			uint64_t valary[3];
       
   837 
       
   838 			if (userquota_propname_decode(propname, zoned,
       
   839 			    &uqtype, domain, sizeof (domain), &rid) != 0) {
       
   840 				zfs_error_aux(hdl,
       
   841 				    dgettext(TEXT_DOMAIN,
       
   842 				    "'%s' has an invalid user/group name"),
       
   843 				    propname);
       
   844 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
       
   845 				goto error;
       
   846 			}
       
   847 
       
   848 			if (uqtype != ZFS_PROP_USERQUOTA &&
       
   849 			    uqtype != ZFS_PROP_GROUPQUOTA) {
       
   850 				zfs_error_aux(hdl,
       
   851 				    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
       
   852 				    propname);
       
   853 				(void) zfs_error(hdl, EZFS_PROPREADONLY,
       
   854 				    errbuf);
       
   855 				goto error;
       
   856 			}
       
   857 
       
   858 			if (nvpair_type(elem) == DATA_TYPE_STRING) {
       
   859 				(void) nvpair_value_string(elem, &strval);
       
   860 				if (strcmp(strval, "none") == 0) {
       
   861 					intval = 0;
       
   862 				} else if (zfs_nicestrtonum(hdl,
       
   863 				    strval, &intval) != 0) {
       
   864 					(void) zfs_error(hdl,
       
   865 					    EZFS_BADPROP, errbuf);
       
   866 					goto error;
       
   867 				}
       
   868 			} else if (nvpair_type(elem) ==
       
   869 			    DATA_TYPE_UINT64) {
       
   870 				(void) nvpair_value_uint64(elem, &intval);
       
   871 				if (intval == 0) {
       
   872 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
       
   873 					    "use 'none' to disable "
       
   874 					    "userquota/groupquota"));
       
   875 					goto error;
       
   876 				}
       
   877 			} else {
       
   878 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
       
   879 				    "'%s' must be a number"), propname);
       
   880 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
       
   881 				goto error;
       
   882 			}
       
   883 
       
   884 			(void) snprintf(newpropname, sizeof (newpropname),
       
   885 			    "%s%s", zfs_userquota_prop_prefixes[uqtype],
       
   886 			    domain);
       
   887 			valary[0] = uqtype;
       
   888 			valary[1] = rid;
       
   889 			valary[2] = intval;
       
   890 			if (nvlist_add_uint64_array(ret, newpropname,
       
   891 			    valary, 3) != 0) {
       
   892 				(void) no_memory(hdl);
       
   893 				goto error;
       
   894 			}
       
   895 			continue;
       
   896 		}
       
   897 
       
   898 		if (prop == ZPROP_INVAL) {
       
   899 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
       
   900 			    "invalid property '%s'"), propname);
       
   901 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
   821 			goto error;
   902 			goto error;
   822 		}
   903 		}
   823 
   904 
   824 		if (!zfs_prop_valid_for_type(prop, type)) {
   905 		if (!zfs_prop_valid_for_type(prop, type)) {
   825 			zfs_error_aux(hdl,
   906 			zfs_error_aux(hdl,
   958 					goto error;
  1039 					goto error;
   959 				}
  1040 				}
   960 			} else if (getzoneid() != GLOBAL_ZONEID) {
  1041 			} else if (getzoneid() != GLOBAL_ZONEID) {
   961 				/*
  1042 				/*
   962 				 * If zoned property is 'off', this must be in
  1043 				 * If zoned property is 'off', this must be in
   963 				 * a globle zone. If not, something is wrong.
  1044 				 * a global zone. If not, something is wrong.
   964 				 */
  1045 				 */
   965 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  1046 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
   966 				    "'%s' cannot be set while dataset "
  1047 				    "'%s' cannot be set while dataset "
   967 				    "'zoned' property is set"), propname);
  1048 				    "'zoned' property is set"), propname);
   968 				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
  1049 				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
  1142 error:
  1223 error:
  1143 	nvlist_free(ret);
  1224 	nvlist_free(ret);
  1144 	return (NULL);
  1225 	return (NULL);
  1145 }
  1226 }
  1146 
  1227 
  1147 static int
       
  1148 zfs_get_perm_who(const char *who, zfs_deleg_who_type_t *who_type,
       
  1149     uint64_t *ret_who)
       
  1150 {
       
  1151 	struct passwd *pwd;
       
  1152 	struct group *grp;
       
  1153 	uid_t id;
       
  1154 
       
  1155 	if (*who_type == ZFS_DELEG_EVERYONE || *who_type == ZFS_DELEG_CREATE ||
       
  1156 	    *who_type == ZFS_DELEG_NAMED_SET) {
       
  1157 		*ret_who = -1;
       
  1158 		return (0);
       
  1159 	}
       
  1160 	if (who == NULL && !(*who_type == ZFS_DELEG_EVERYONE))
       
  1161 		return (EZFS_BADWHO);
       
  1162 
       
  1163 	if (*who_type == ZFS_DELEG_WHO_UNKNOWN &&
       
  1164 	    strcmp(who, "everyone") == 0) {
       
  1165 		*ret_who = -1;
       
  1166 		*who_type = ZFS_DELEG_EVERYONE;
       
  1167 		return (0);
       
  1168 	}
       
  1169 
       
  1170 	pwd = getpwnam(who);
       
  1171 	grp = getgrnam(who);
       
  1172 
       
  1173 	if ((*who_type == ZFS_DELEG_USER) && pwd) {
       
  1174 		*ret_who = pwd->pw_uid;
       
  1175 	} else if ((*who_type == ZFS_DELEG_GROUP) && grp) {
       
  1176 		*ret_who = grp->gr_gid;
       
  1177 	} else if (pwd) {
       
  1178 		*ret_who = pwd->pw_uid;
       
  1179 		*who_type = ZFS_DELEG_USER;
       
  1180 	} else if (grp) {
       
  1181 		*ret_who = grp->gr_gid;
       
  1182 		*who_type = ZFS_DELEG_GROUP;
       
  1183 	} else {
       
  1184 		char *end;
       
  1185 
       
  1186 		id = strtol(who, &end, 10);
       
  1187 		if (errno != 0 || *end != '\0') {
       
  1188 			return (EZFS_BADWHO);
       
  1189 		} else {
       
  1190 			*ret_who = id;
       
  1191 			if (*who_type == ZFS_DELEG_WHO_UNKNOWN)
       
  1192 				*who_type = ZFS_DELEG_USER;
       
  1193 		}
       
  1194 	}
       
  1195 
       
  1196 	return (0);
       
  1197 }
       
  1198 
       
  1199 static void
       
  1200 zfs_perms_add_to_nvlist(nvlist_t *who_nvp, char *name, nvlist_t *perms_nvp)
       
  1201 {
       
  1202 	if (perms_nvp != NULL) {
       
  1203 		verify(nvlist_add_nvlist(who_nvp,
       
  1204 		    name, perms_nvp) == 0);
       
  1205 	} else {
       
  1206 		verify(nvlist_add_boolean(who_nvp, name) == 0);
       
  1207 	}
       
  1208 }
       
  1209 
       
  1210 static void
       
  1211 helper(zfs_deleg_who_type_t who_type, uint64_t whoid, char *whostr,
       
  1212     zfs_deleg_inherit_t inherit, nvlist_t *who_nvp, nvlist_t *perms_nvp,
       
  1213     nvlist_t *sets_nvp)
       
  1214 {
       
  1215 	boolean_t do_perms, do_sets;
       
  1216 	char name[ZFS_MAX_DELEG_NAME];
       
  1217 
       
  1218 	do_perms = (nvlist_next_nvpair(perms_nvp, NULL) != NULL);
       
  1219 	do_sets = (nvlist_next_nvpair(sets_nvp, NULL) != NULL);
       
  1220 
       
  1221 	if (!do_perms && !do_sets)
       
  1222 		do_perms = do_sets = B_TRUE;
       
  1223 
       
  1224 	if (do_perms) {
       
  1225 		zfs_deleg_whokey(name, who_type, inherit,
       
  1226 		    (who_type == ZFS_DELEG_NAMED_SET) ?
       
  1227 		    whostr : (void *)&whoid);
       
  1228 		zfs_perms_add_to_nvlist(who_nvp, name, perms_nvp);
       
  1229 	}
       
  1230 	if (do_sets) {
       
  1231 		zfs_deleg_whokey(name, toupper(who_type), inherit,
       
  1232 		    (who_type == ZFS_DELEG_NAMED_SET) ?
       
  1233 		    whostr : (void *)&whoid);
       
  1234 		zfs_perms_add_to_nvlist(who_nvp, name, sets_nvp);
       
  1235 	}
       
  1236 }
       
  1237 
       
  1238 static void
       
  1239 zfs_perms_add_who_nvlist(nvlist_t *who_nvp, uint64_t whoid, void *whostr,
       
  1240     nvlist_t *perms_nvp, nvlist_t *sets_nvp,
       
  1241     zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit)
       
  1242 {
       
  1243 	if (who_type == ZFS_DELEG_NAMED_SET || who_type == ZFS_DELEG_CREATE) {
       
  1244 		helper(who_type, whoid, whostr, 0,
       
  1245 		    who_nvp, perms_nvp, sets_nvp);
       
  1246 	} else {
       
  1247 		if (inherit & ZFS_DELEG_PERM_LOCAL) {
       
  1248 			helper(who_type, whoid, whostr, ZFS_DELEG_LOCAL,
       
  1249 			    who_nvp, perms_nvp, sets_nvp);
       
  1250 		}
       
  1251 		if (inherit & ZFS_DELEG_PERM_DESCENDENT) {
       
  1252 			helper(who_type, whoid, whostr, ZFS_DELEG_DESCENDENT,
       
  1253 			    who_nvp, perms_nvp, sets_nvp);
       
  1254 		}
       
  1255 	}
       
  1256 }
       
  1257 
       
  1258 /*
       
  1259  * Construct nvlist to pass down to kernel for setting/removing permissions.
       
  1260  *
       
  1261  * The nvlist is constructed as a series of nvpairs with an optional embedded
       
  1262  * nvlist of permissions to remove or set.  The topmost nvpairs are the actual
       
  1263  * base attribute named stored in the dsl.
       
  1264  * Arguments:
       
  1265  *
       
  1266  * whostr:   is a comma separated list of users, groups, or a single set name.
       
  1267  *           whostr may be null for everyone or create perms.
       
  1268  * who_type: is the type of entry in whostr.  Typically this will be
       
  1269  *           ZFS_DELEG_WHO_UNKNOWN.
       
  1270  * perms:    common separated list of permissions.  May be null if user
       
  1271  *           is requested to remove permissions by who.
       
  1272  * inherit:  Specifies the inheritance of the permissions.  Will be either
       
  1273  *           ZFS_DELEG_PERM_LOCAL and/or  ZFS_DELEG_PERM_DESCENDENT.
       
  1274  * nvp       The constructed nvlist to pass to zfs_perm_set().
       
  1275  *           The output nvp will look something like this.
       
  1276  *              ul$1234 -> {create ; destroy }
       
  1277  *              Ul$1234 -> { @myset }
       
  1278  *              s-$@myset - { snapshot; checksum; compression }
       
  1279  */
       
  1280 int
       
  1281 zfs_build_perms(zfs_handle_t *zhp, char *whostr, char *perms,
       
  1282     zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit, nvlist_t **nvp)
       
  1283 {
       
  1284 	nvlist_t *who_nvp;
       
  1285 	nvlist_t *perms_nvp = NULL;
       
  1286 	nvlist_t *sets_nvp = NULL;
       
  1287 	char errbuf[1024];
       
  1288 	char *who_tok, *perm;
       
  1289 	int error;
       
  1290 
       
  1291 	*nvp = NULL;
       
  1292 
       
  1293 	if (perms) {
       
  1294 		if ((error = nvlist_alloc(&perms_nvp,
       
  1295 		    NV_UNIQUE_NAME, 0)) != 0) {
       
  1296 			return (1);
       
  1297 		}
       
  1298 		if ((error = nvlist_alloc(&sets_nvp,
       
  1299 		    NV_UNIQUE_NAME, 0)) != 0) {
       
  1300 			nvlist_free(perms_nvp);
       
  1301 			return (1);
       
  1302 		}
       
  1303 	}
       
  1304 
       
  1305 	if ((error = nvlist_alloc(&who_nvp, NV_UNIQUE_NAME, 0)) != 0) {
       
  1306 		if (perms_nvp)
       
  1307 			nvlist_free(perms_nvp);
       
  1308 		if (sets_nvp)
       
  1309 			nvlist_free(sets_nvp);
       
  1310 		return (1);
       
  1311 	}
       
  1312 
       
  1313 	if (who_type == ZFS_DELEG_NAMED_SET) {
       
  1314 		namecheck_err_t why;
       
  1315 		char what;
       
  1316 
       
  1317 		if ((error = permset_namecheck(whostr, &why, &what)) != 0) {
       
  1318 			nvlist_free(who_nvp);
       
  1319 			if (perms_nvp)
       
  1320 				nvlist_free(perms_nvp);
       
  1321 			if (sets_nvp)
       
  1322 				nvlist_free(sets_nvp);
       
  1323 
       
  1324 			switch (why) {
       
  1325 			case NAME_ERR_NO_AT:
       
  1326 				zfs_error_aux(zhp->zfs_hdl,
       
  1327 				    dgettext(TEXT_DOMAIN,
       
  1328 				    "set definition must begin with an '@' "
       
  1329 				    "character"));
       
  1330 			}
       
  1331 			return (zfs_error(zhp->zfs_hdl,
       
  1332 			    EZFS_BADPERMSET, whostr));
       
  1333 		}
       
  1334 	}
       
  1335 
       
  1336 	/*
       
  1337 	 * Build up nvlist(s) of permissions.  Two nvlists are maintained.
       
  1338 	 * The first nvlist perms_nvp will have normal permissions and the
       
  1339 	 * other sets_nvp will have only permssion set names in it.
       
  1340 	 */
       
  1341 	for (perm = strtok(perms, ","); perm; perm = strtok(NULL, ",")) {
       
  1342 		const char *perm_canonical = zfs_deleg_canonicalize_perm(perm);
       
  1343 
       
  1344 		if (perm_canonical) {
       
  1345 			verify(nvlist_add_boolean(perms_nvp,
       
  1346 			    perm_canonical) == 0);
       
  1347 		} else if (perm[0] == '@') {
       
  1348 			verify(nvlist_add_boolean(sets_nvp, perm) == 0);
       
  1349 		} else {
       
  1350 			nvlist_free(who_nvp);
       
  1351 			nvlist_free(perms_nvp);
       
  1352 			nvlist_free(sets_nvp);
       
  1353 			return (zfs_error(zhp->zfs_hdl, EZFS_BADPERM, perm));
       
  1354 		}
       
  1355 	}
       
  1356 
       
  1357 	if (whostr && who_type != ZFS_DELEG_CREATE) {
       
  1358 		who_tok = strtok(whostr, ",");
       
  1359 		if (who_tok == NULL) {
       
  1360 			nvlist_free(who_nvp);
       
  1361 			if (perms_nvp)
       
  1362 				nvlist_free(perms_nvp);
       
  1363 			if (sets_nvp)
       
  1364 				nvlist_free(sets_nvp);
       
  1365 			(void) snprintf(errbuf, sizeof (errbuf),
       
  1366 			    dgettext(TEXT_DOMAIN, "Who string is NULL"),
       
  1367 			    whostr);
       
  1368 			return (zfs_error(zhp->zfs_hdl, EZFS_BADWHO, errbuf));
       
  1369 		}
       
  1370 	}
       
  1371 
       
  1372 	/*
       
  1373 	 * Now create the nvlist(s)
       
  1374 	 */
       
  1375 	do {
       
  1376 		uint64_t who_id;
       
  1377 
       
  1378 		error = zfs_get_perm_who(who_tok, &who_type,
       
  1379 		    &who_id);
       
  1380 		if (error) {
       
  1381 			nvlist_free(who_nvp);
       
  1382 			if (perms_nvp)
       
  1383 				nvlist_free(perms_nvp);
       
  1384 			if (sets_nvp)
       
  1385 				nvlist_free(sets_nvp);
       
  1386 			(void) snprintf(errbuf, sizeof (errbuf),
       
  1387 			    dgettext(TEXT_DOMAIN,
       
  1388 			    "Unable to determine uid/gid for "
       
  1389 			    "%s "), who_tok);
       
  1390 			return (zfs_error(zhp->zfs_hdl, EZFS_BADWHO, errbuf));
       
  1391 		}
       
  1392 
       
  1393 		/*
       
  1394 		 * add entries for both local and descendent when required
       
  1395 		 */
       
  1396 		zfs_perms_add_who_nvlist(who_nvp, who_id, who_tok,
       
  1397 		    perms_nvp, sets_nvp, who_type, inherit);
       
  1398 
       
  1399 	} while (who_tok = strtok(NULL, ","));
       
  1400 	*nvp = who_nvp;
       
  1401 	return (0);
       
  1402 }
       
  1403 
       
  1404 static int
       
  1405 zfs_perm_set_common(zfs_handle_t *zhp, nvlist_t *nvp, boolean_t unset)
       
  1406 {
       
  1407 	zfs_cmd_t zc = { 0 };
       
  1408 	int error;
       
  1409 	char errbuf[1024];
       
  1410 
       
  1411 	(void) snprintf(errbuf, sizeof (errbuf),
       
  1412 	    dgettext(TEXT_DOMAIN, "Cannot update 'allows' for '%s'"),
       
  1413 	    zhp->zfs_name);
       
  1414 
       
  1415 	if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, nvp))
       
  1416 		return (-1);
       
  1417 
       
  1418 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
       
  1419 	zc.zc_perm_action = unset;
       
  1420 
       
  1421 	error = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SET_FSACL, &zc);
       
  1422 	if (error && errno == ENOTSUP) {
       
  1423 		(void) snprintf(errbuf, sizeof (errbuf),
       
  1424 		    gettext("Pool must be upgraded to use 'allow/unallow'"));
       
  1425 		zcmd_free_nvlists(&zc);
       
  1426 		return (zfs_error(zhp->zfs_hdl, EZFS_BADVERSION, errbuf));
       
  1427 	} else if (error) {
       
  1428 		return (zfs_standard_error(zhp->zfs_hdl, errno, errbuf));
       
  1429 	}
       
  1430 	zcmd_free_nvlists(&zc);
       
  1431 
       
  1432 	return (error);
       
  1433 }
       
  1434 
       
  1435 int
       
  1436 zfs_perm_set(zfs_handle_t *zhp, nvlist_t *nvp)
       
  1437 {
       
  1438 	return (zfs_perm_set_common(zhp, nvp, B_FALSE));
       
  1439 }
       
  1440 
       
  1441 int
       
  1442 zfs_perm_remove(zfs_handle_t *zhp, nvlist_t *perms)
       
  1443 {
       
  1444 	return (zfs_perm_set_common(zhp, perms, B_TRUE));
       
  1445 }
       
  1446 
       
  1447 static int
       
  1448 perm_compare(const void *arg1, const void *arg2)
       
  1449 {
       
  1450 	const zfs_perm_node_t *node1 = arg1;
       
  1451 	const zfs_perm_node_t *node2 = arg2;
       
  1452 	int ret;
       
  1453 
       
  1454 	ret = strcmp(node1->z_pname, node2->z_pname);
       
  1455 
       
  1456 	if (ret > 0)
       
  1457 		return (1);
       
  1458 	if (ret < 0)
       
  1459 		return (-1);
       
  1460 	else
       
  1461 		return (0);
       
  1462 }
       
  1463 
       
  1464 static void
       
  1465 zfs_destroy_perm_tree(avl_tree_t *tree)
       
  1466 {
       
  1467 	zfs_perm_node_t *permnode;
       
  1468 	void *cookie = NULL;
       
  1469 
       
  1470 	while ((permnode = avl_destroy_nodes(tree,  &cookie)) != NULL)
       
  1471 		free(permnode);
       
  1472 	avl_destroy(tree);
       
  1473 }
       
  1474 
       
  1475 static void
       
  1476 zfs_destroy_tree(avl_tree_t *tree)
       
  1477 {
       
  1478 	zfs_allow_node_t *allownode;
       
  1479 	void *cookie = NULL;
       
  1480 
       
  1481 	while ((allownode = avl_destroy_nodes(tree, &cookie)) != NULL) {
       
  1482 		zfs_destroy_perm_tree(&allownode->z_localdescend);
       
  1483 		zfs_destroy_perm_tree(&allownode->z_local);
       
  1484 		zfs_destroy_perm_tree(&allownode->z_descend);
       
  1485 		free(allownode);
       
  1486 	}
       
  1487 	avl_destroy(tree);
       
  1488 }
       
  1489 
       
  1490 void
       
  1491 zfs_free_allows(zfs_allow_t *allow)
       
  1492 {
       
  1493 	zfs_allow_t *allownext;
       
  1494 	zfs_allow_t *freeallow;
       
  1495 
       
  1496 	allownext = allow;
       
  1497 	while (allownext) {
       
  1498 		zfs_destroy_tree(&allownext->z_sets);
       
  1499 		zfs_destroy_tree(&allownext->z_crperms);
       
  1500 		zfs_destroy_tree(&allownext->z_user);
       
  1501 		zfs_destroy_tree(&allownext->z_group);
       
  1502 		zfs_destroy_tree(&allownext->z_everyone);
       
  1503 		freeallow = allownext;
       
  1504 		allownext = allownext->z_next;
       
  1505 		free(freeallow);
       
  1506 	}
       
  1507 }
       
  1508 
       
  1509 static zfs_allow_t *
       
  1510 zfs_alloc_perm_tree(zfs_handle_t *zhp, zfs_allow_t *prev, char *setpoint)
       
  1511 {
       
  1512 	zfs_allow_t *ptree;
       
  1513 
       
  1514 	if ((ptree = zfs_alloc(zhp->zfs_hdl,
       
  1515 	    sizeof (zfs_allow_t))) == NULL) {
       
  1516 		return (NULL);
       
  1517 	}
       
  1518 
       
  1519 	(void) strlcpy(ptree->z_setpoint, setpoint, sizeof (ptree->z_setpoint));
       
  1520 	avl_create(&ptree->z_sets,
       
  1521 	    perm_compare, sizeof (zfs_allow_node_t),
       
  1522 	    offsetof(zfs_allow_node_t, z_node));
       
  1523 	avl_create(&ptree->z_crperms,
       
  1524 	    perm_compare, sizeof (zfs_allow_node_t),
       
  1525 	    offsetof(zfs_allow_node_t, z_node));
       
  1526 	avl_create(&ptree->z_user,
       
  1527 	    perm_compare, sizeof (zfs_allow_node_t),
       
  1528 	    offsetof(zfs_allow_node_t, z_node));
       
  1529 	avl_create(&ptree->z_group,
       
  1530 	    perm_compare, sizeof (zfs_allow_node_t),
       
  1531 	    offsetof(zfs_allow_node_t, z_node));
       
  1532 	avl_create(&ptree->z_everyone,
       
  1533 	    perm_compare, sizeof (zfs_allow_node_t),
       
  1534 	    offsetof(zfs_allow_node_t, z_node));
       
  1535 
       
  1536 	if (prev)
       
  1537 		prev->z_next = ptree;
       
  1538 	ptree->z_next = NULL;
       
  1539 	return (ptree);
       
  1540 }
       
  1541 
       
  1542 /*
       
  1543  * Add permissions to the appropriate AVL permission tree.
       
  1544  * The appropriate tree may not be the requested tree.
       
  1545  * For example if ld indicates a local permission, but
       
  1546  * same permission also exists as a descendent permission
       
  1547  * then the permission will be removed from the descendent
       
  1548  * tree and add the the local+descendent tree.
       
  1549  */
       
  1550 static int
       
  1551 zfs_coalesce_perm(zfs_handle_t *zhp, zfs_allow_node_t *allownode,
       
  1552     char *perm, char ld)
       
  1553 {
       
  1554 	zfs_perm_node_t pnode, *permnode, *permnode2;
       
  1555 	zfs_perm_node_t *newnode;
       
  1556 	avl_index_t where, where2;
       
  1557 	avl_tree_t *tree, *altree;
       
  1558 
       
  1559 	(void) strlcpy(pnode.z_pname, perm, sizeof (pnode.z_pname));
       
  1560 
       
  1561 	if (ld == ZFS_DELEG_NA) {
       
  1562 		tree =  &allownode->z_localdescend;
       
  1563 		altree = &allownode->z_descend;
       
  1564 	} else if (ld == ZFS_DELEG_LOCAL) {
       
  1565 		tree = &allownode->z_local;
       
  1566 		altree = &allownode->z_descend;
       
  1567 	} else {
       
  1568 		tree = &allownode->z_descend;
       
  1569 		altree = &allownode->z_local;
       
  1570 	}
       
  1571 	permnode = avl_find(tree, &pnode, &where);
       
  1572 	permnode2 = avl_find(altree, &pnode, &where2);
       
  1573 
       
  1574 	if (permnode2) {
       
  1575 		avl_remove(altree, permnode2);
       
  1576 		free(permnode2);
       
  1577 		if (permnode == NULL) {
       
  1578 			tree =  &allownode->z_localdescend;
       
  1579 		}
       
  1580 	}
       
  1581 
       
  1582 	/*
       
  1583 	 * Now insert new permission in either requested location
       
  1584 	 * local/descendent or into ld when perm will exist in both.
       
  1585 	 */
       
  1586 	if (permnode == NULL) {
       
  1587 		if ((newnode = zfs_alloc(zhp->zfs_hdl,
       
  1588 		    sizeof (zfs_perm_node_t))) == NULL) {
       
  1589 			return (-1);
       
  1590 		}
       
  1591 		*newnode = pnode;
       
  1592 		avl_add(tree, newnode);
       
  1593 	}
       
  1594 	return (0);
       
  1595 }
       
  1596 
       
  1597 /*
       
  1598  * Uggh, this is going to be a bit complicated.
       
  1599  * we have an nvlist coming out of the kernel that
       
  1600  * will indicate where the permission is set and then
       
  1601  * it will contain allow of the various "who's", and what
       
  1602  * their permissions are.  To further complicate this
       
  1603  * we will then have to coalesce the local,descendent
       
  1604  * and local+descendent permissions where appropriate.
       
  1605  * The kernel only knows about a permission as being local
       
  1606  * or descendent, but not both.
       
  1607  *
       
  1608  * In order to make this easier for zfs_main to deal with
       
  1609  * a series of AVL trees will be used to maintain
       
  1610  * all of this, primarily for sorting purposes as well
       
  1611  * as the ability to quickly locate a specific entry.
       
  1612  *
       
  1613  * What we end up with are tree's for sets, create perms,
       
  1614  * user, groups and everyone.  With each of those trees
       
  1615  * we have subtrees for local, descendent and local+descendent
       
  1616  * permissions.
       
  1617  */
       
  1618 int
       
  1619 zfs_perm_get(zfs_handle_t *zhp, zfs_allow_t **zfs_perms)
       
  1620 {
       
  1621 	zfs_cmd_t zc = { 0 };
       
  1622 	int error;
       
  1623 	nvlist_t *nvlist;
       
  1624 	nvlist_t *permnv, *sourcenv;
       
  1625 	nvpair_t *who_pair, *source_pair;
       
  1626 	nvpair_t *perm_pair;
       
  1627 	char errbuf[1024];
       
  1628 	zfs_allow_t *zallowp, *newallowp;
       
  1629 	char  ld;
       
  1630 	char *nvpname;
       
  1631 	uid_t	uid;
       
  1632 	gid_t	gid;
       
  1633 	avl_tree_t *tree;
       
  1634 	avl_index_t where;
       
  1635 
       
  1636 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
       
  1637 
       
  1638 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
       
  1639 		return (-1);
       
  1640 
       
  1641 	while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
       
  1642 		if (errno == ENOMEM) {
       
  1643 			if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, &zc) != 0) {
       
  1644 				zcmd_free_nvlists(&zc);
       
  1645 				return (-1);
       
  1646 			}
       
  1647 		} else if (errno == ENOTSUP) {
       
  1648 			zcmd_free_nvlists(&zc);
       
  1649 			(void) snprintf(errbuf, sizeof (errbuf),
       
  1650 			    gettext("Pool must be upgraded to use 'allow'"));
       
  1651 			return (zfs_error(zhp->zfs_hdl,
       
  1652 			    EZFS_BADVERSION, errbuf));
       
  1653 		} else {
       
  1654 			zcmd_free_nvlists(&zc);
       
  1655 			return (-1);
       
  1656 		}
       
  1657 	}
       
  1658 
       
  1659 	if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &nvlist) != 0) {
       
  1660 		zcmd_free_nvlists(&zc);
       
  1661 		return (-1);
       
  1662 	}
       
  1663 
       
  1664 	zcmd_free_nvlists(&zc);
       
  1665 
       
  1666 	source_pair = nvlist_next_nvpair(nvlist, NULL);
       
  1667 
       
  1668 	if (source_pair == NULL) {
       
  1669 		*zfs_perms = NULL;
       
  1670 		return (0);
       
  1671 	}
       
  1672 
       
  1673 	*zfs_perms = zfs_alloc_perm_tree(zhp, NULL, nvpair_name(source_pair));
       
  1674 	if (*zfs_perms == NULL) {
       
  1675 		return (0);
       
  1676 	}
       
  1677 
       
  1678 	zallowp = *zfs_perms;
       
  1679 
       
  1680 	for (;;) {
       
  1681 		struct passwd *pwd;
       
  1682 		struct group *grp;
       
  1683 		zfs_allow_node_t *allownode;
       
  1684 		zfs_allow_node_t  findallownode;
       
  1685 		zfs_allow_node_t *newallownode;
       
  1686 
       
  1687 		(void) strlcpy(zallowp->z_setpoint,
       
  1688 		    nvpair_name(source_pair),
       
  1689 		    sizeof (zallowp->z_setpoint));
       
  1690 
       
  1691 		if ((error = nvpair_value_nvlist(source_pair, &sourcenv)) != 0)
       
  1692 			goto abort;
       
  1693 
       
  1694 		/*
       
  1695 		 * Make sure nvlist is composed correctly
       
  1696 		 */
       
  1697 		if (zfs_deleg_verify_nvlist(sourcenv)) {
       
  1698 			goto abort;
       
  1699 		}
       
  1700 
       
  1701 		who_pair = nvlist_next_nvpair(sourcenv, NULL);
       
  1702 		if (who_pair == NULL) {
       
  1703 			goto abort;
       
  1704 		}
       
  1705 
       
  1706 		do {
       
  1707 			error = nvpair_value_nvlist(who_pair, &permnv);
       
  1708 			if (error) {
       
  1709 				goto abort;
       
  1710 			}
       
  1711 
       
  1712 			/*
       
  1713 			 * First build up the key to use
       
  1714 			 * for looking up in the various
       
  1715 			 * who trees.
       
  1716 			 */
       
  1717 			ld = nvpair_name(who_pair)[1];
       
  1718 			nvpname = nvpair_name(who_pair);
       
  1719 			switch (nvpair_name(who_pair)[0]) {
       
  1720 			case ZFS_DELEG_USER:
       
  1721 			case ZFS_DELEG_USER_SETS:
       
  1722 				tree = &zallowp->z_user;
       
  1723 				uid = atol(&nvpname[3]);
       
  1724 				pwd = getpwuid(uid);
       
  1725 				(void) snprintf(findallownode.z_key,
       
  1726 				    sizeof (findallownode.z_key), "user %s",
       
  1727 				    (pwd) ? pwd->pw_name :
       
  1728 				    &nvpair_name(who_pair)[3]);
       
  1729 				break;
       
  1730 			case ZFS_DELEG_GROUP:
       
  1731 			case ZFS_DELEG_GROUP_SETS:
       
  1732 				tree = &zallowp->z_group;
       
  1733 				gid = atol(&nvpname[3]);
       
  1734 				grp = getgrgid(gid);
       
  1735 				(void) snprintf(findallownode.z_key,
       
  1736 				    sizeof (findallownode.z_key), "group %s",
       
  1737 				    (grp) ? grp->gr_name :
       
  1738 				    &nvpair_name(who_pair)[3]);
       
  1739 				break;
       
  1740 			case ZFS_DELEG_CREATE:
       
  1741 			case ZFS_DELEG_CREATE_SETS:
       
  1742 				tree = &zallowp->z_crperms;
       
  1743 				(void) strlcpy(findallownode.z_key, "",
       
  1744 				    sizeof (findallownode.z_key));
       
  1745 				break;
       
  1746 			case ZFS_DELEG_EVERYONE:
       
  1747 			case ZFS_DELEG_EVERYONE_SETS:
       
  1748 				(void) snprintf(findallownode.z_key,
       
  1749 				    sizeof (findallownode.z_key), "everyone");
       
  1750 				tree = &zallowp->z_everyone;
       
  1751 				break;
       
  1752 			case ZFS_DELEG_NAMED_SET:
       
  1753 			case ZFS_DELEG_NAMED_SET_SETS:
       
  1754 				(void) snprintf(findallownode.z_key,
       
  1755 				    sizeof (findallownode.z_key), "%s",
       
  1756 				    &nvpair_name(who_pair)[3]);
       
  1757 				tree = &zallowp->z_sets;
       
  1758 				break;
       
  1759 			}
       
  1760 
       
  1761 			/*
       
  1762 			 * Place who in tree
       
  1763 			 */
       
  1764 			allownode = avl_find(tree, &findallownode, &where);
       
  1765 			if (allownode == NULL) {
       
  1766 				if ((newallownode = zfs_alloc(zhp->zfs_hdl,
       
  1767 				    sizeof (zfs_allow_node_t))) == NULL) {
       
  1768 					goto abort;
       
  1769 				}
       
  1770 				avl_create(&newallownode->z_localdescend,
       
  1771 				    perm_compare,
       
  1772 				    sizeof (zfs_perm_node_t),
       
  1773 				    offsetof(zfs_perm_node_t, z_node));
       
  1774 				avl_create(&newallownode->z_local,
       
  1775 				    perm_compare,
       
  1776 				    sizeof (zfs_perm_node_t),
       
  1777 				    offsetof(zfs_perm_node_t, z_node));
       
  1778 				avl_create(&newallownode->z_descend,
       
  1779 				    perm_compare,
       
  1780 				    sizeof (zfs_perm_node_t),
       
  1781 				    offsetof(zfs_perm_node_t, z_node));
       
  1782 				(void) strlcpy(newallownode->z_key,
       
  1783 				    findallownode.z_key,
       
  1784 				    sizeof (findallownode.z_key));
       
  1785 				avl_insert(tree, newallownode, where);
       
  1786 				allownode = newallownode;
       
  1787 			}
       
  1788 
       
  1789 			/*
       
  1790 			 * Now iterate over the permissions and
       
  1791 			 * place them in the appropriate local,
       
  1792 			 * descendent or local+descendent tree.
       
  1793 			 *
       
  1794 			 * The permissions are added to the tree
       
  1795 			 * via zfs_coalesce_perm().
       
  1796 			 */
       
  1797 			perm_pair = nvlist_next_nvpair(permnv, NULL);
       
  1798 			if (perm_pair == NULL)
       
  1799 				goto abort;
       
  1800 			do {
       
  1801 				if (zfs_coalesce_perm(zhp, allownode,
       
  1802 				    nvpair_name(perm_pair), ld) != 0)
       
  1803 					goto abort;
       
  1804 			} while (perm_pair = nvlist_next_nvpair(permnv,
       
  1805 			    perm_pair));
       
  1806 		} while (who_pair = nvlist_next_nvpair(sourcenv, who_pair));
       
  1807 
       
  1808 		source_pair = nvlist_next_nvpair(nvlist, source_pair);
       
  1809 		if (source_pair == NULL)
       
  1810 			break;
       
  1811 
       
  1812 		/*
       
  1813 		 * allocate another node from the link list of
       
  1814 		 * zfs_allow_t structures
       
  1815 		 */
       
  1816 		newallowp = zfs_alloc_perm_tree(zhp, zallowp,
       
  1817 		    nvpair_name(source_pair));
       
  1818 		if (newallowp == NULL) {
       
  1819 			goto abort;
       
  1820 		}
       
  1821 		zallowp = newallowp;
       
  1822 	}
       
  1823 	nvlist_free(nvlist);
       
  1824 	return (0);
       
  1825 abort:
       
  1826 	zfs_free_allows(*zfs_perms);
       
  1827 	nvlist_free(nvlist);
       
  1828 	return (-1);
       
  1829 }
       
  1830 
       
  1831 static char *
       
  1832 zfs_deleg_perm_note(zfs_deleg_note_t note)
       
  1833 {
       
  1834 	/*
       
  1835 	 * Don't put newlines on end of lines
       
  1836 	 */
       
  1837 	switch (note) {
       
  1838 	case ZFS_DELEG_NOTE_CREATE:
       
  1839 		return (dgettext(TEXT_DOMAIN,
       
  1840 		    "Must also have the 'mount' ability"));
       
  1841 	case ZFS_DELEG_NOTE_DESTROY:
       
  1842 		return (dgettext(TEXT_DOMAIN,
       
  1843 		    "Must also have the 'mount' ability"));
       
  1844 	case ZFS_DELEG_NOTE_SNAPSHOT:
       
  1845 		return (dgettext(TEXT_DOMAIN,
       
  1846 		    "Must also have the 'mount' ability"));
       
  1847 	case ZFS_DELEG_NOTE_ROLLBACK:
       
  1848 		return (dgettext(TEXT_DOMAIN,
       
  1849 		    "Must also have the 'mount' ability"));
       
  1850 	case ZFS_DELEG_NOTE_CLONE:
       
  1851 		return (dgettext(TEXT_DOMAIN, "Must also have the 'create' "
       
  1852 		    "ability and 'mount'\n"
       
  1853 		    "\t\t\t\tability in the origin file system"));
       
  1854 	case ZFS_DELEG_NOTE_PROMOTE:
       
  1855 		return (dgettext(TEXT_DOMAIN, "Must also have the 'mount'\n"
       
  1856 		    "\t\t\t\tand 'promote' ability in the origin file system"));
       
  1857 	case ZFS_DELEG_NOTE_RENAME:
       
  1858 		return (dgettext(TEXT_DOMAIN, "Must also have the 'mount' "
       
  1859 		    "and 'create' \n\t\t\t\tability in the new parent"));
       
  1860 	case ZFS_DELEG_NOTE_RECEIVE:
       
  1861 		return (dgettext(TEXT_DOMAIN, "Must also have the 'mount'"
       
  1862 		    " and 'create' ability"));
       
  1863 	case ZFS_DELEG_NOTE_USERPROP:
       
  1864 		return (dgettext(TEXT_DOMAIN,
       
  1865 		    "Allows changing any user property"));
       
  1866 	case ZFS_DELEG_NOTE_ALLOW:
       
  1867 		return (dgettext(TEXT_DOMAIN,
       
  1868 		    "Must also have the permission that is being\n"
       
  1869 		    "\t\t\t\tallowed"));
       
  1870 	case ZFS_DELEG_NOTE_MOUNT:
       
  1871 		return (dgettext(TEXT_DOMAIN,
       
  1872 		    "Allows mount/umount of ZFS datasets"));
       
  1873 	case ZFS_DELEG_NOTE_SHARE:
       
  1874 		return (dgettext(TEXT_DOMAIN,
       
  1875 		    "Allows sharing file systems over NFS or SMB\n"
       
  1876 		    "\t\t\t\tprotocols"));
       
  1877 	case ZFS_DELEG_NOTE_NONE:
       
  1878 	default:
       
  1879 		return (dgettext(TEXT_DOMAIN, ""));
       
  1880 	}
       
  1881 }
       
  1882 
       
  1883 typedef enum {
       
  1884 	ZFS_DELEG_SUBCOMMAND,
       
  1885 	ZFS_DELEG_PROP,
       
  1886 	ZFS_DELEG_OTHER
       
  1887 } zfs_deleg_perm_type_t;
       
  1888 
       
  1889 /*
       
  1890  * is the permission a subcommand or other?
       
  1891  */
       
  1892 zfs_deleg_perm_type_t
       
  1893 zfs_deleg_perm_type(const char *perm)
       
  1894 {
       
  1895 	if (strcmp(perm, "userprop") == 0)
       
  1896 		return (ZFS_DELEG_OTHER);
       
  1897 	else
       
  1898 		return (ZFS_DELEG_SUBCOMMAND);
       
  1899 }
       
  1900 
       
  1901 static char *
       
  1902 zfs_deleg_perm_type_str(zfs_deleg_perm_type_t type)
       
  1903 {
       
  1904 	switch (type) {
       
  1905 	case ZFS_DELEG_SUBCOMMAND:
       
  1906 		return (dgettext(TEXT_DOMAIN, "subcommand"));
       
  1907 	case ZFS_DELEG_PROP:
       
  1908 		return (dgettext(TEXT_DOMAIN, "property"));
       
  1909 	case ZFS_DELEG_OTHER:
       
  1910 		return (dgettext(TEXT_DOMAIN, "other"));
       
  1911 	}
       
  1912 	return ("");
       
  1913 }
       
  1914 
       
  1915 /*ARGSUSED*/
       
  1916 static int
       
  1917 zfs_deleg_prop_cb(int prop, void *cb)
       
  1918 {
       
  1919 	if (zfs_prop_delegatable(prop))
       
  1920 		(void) fprintf(stderr, "%-15s %-15s\n", zfs_prop_to_name(prop),
       
  1921 		    zfs_deleg_perm_type_str(ZFS_DELEG_PROP));
       
  1922 
       
  1923 	return (ZPROP_CONT);
       
  1924 }
       
  1925 
       
  1926 void
       
  1927 zfs_deleg_permissions(void)
       
  1928 {
       
  1929 	int i;
       
  1930 
       
  1931 	(void) fprintf(stderr, "\n%-15s %-15s\t%s\n\n", "NAME",
       
  1932 	    "TYPE", "NOTES");
       
  1933 
       
  1934 	/*
       
  1935 	 * First print out the subcommands
       
  1936 	 */
       
  1937 	for (i = 0; zfs_deleg_perm_tab[i].z_perm != NULL; i++) {
       
  1938 		(void) fprintf(stderr, "%-15s %-15s\t%s\n",
       
  1939 		    zfs_deleg_perm_tab[i].z_perm,
       
  1940 		    zfs_deleg_perm_type_str(
       
  1941 		    zfs_deleg_perm_type(zfs_deleg_perm_tab[i].z_perm)),
       
  1942 		    zfs_deleg_perm_note(zfs_deleg_perm_tab[i].z_note));
       
  1943 	}
       
  1944 
       
  1945 	(void) zprop_iter(zfs_deleg_prop_cb, NULL, B_FALSE, B_TRUE,
       
  1946 	    ZFS_TYPE_DATASET|ZFS_TYPE_VOLUME);
       
  1947 }
       
  1948 
       
  1949 /*
  1228 /*
  1950  * Given a property name and value, set the property for the given dataset.
  1229  * Given a property name and value, set the property for the given dataset.
  1951  */
  1230  */
  1952 int
  1231 int
  1953 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
  1232 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
  2420 		switch (zfs_prop_get_type(prop)) {
  1699 		switch (zfs_prop_get_type(prop)) {
  2421 		case PROP_TYPE_NUMBER:
  1700 		case PROP_TYPE_NUMBER:
  2422 		case PROP_TYPE_INDEX:
  1701 		case PROP_TYPE_INDEX:
  2423 			*val = getprop_uint64(zhp, prop, source);
  1702 			*val = getprop_uint64(zhp, prop, source);
  2424 			/*
  1703 			/*
  2425 			 * If we tried to use a defalut value for a
  1704 			 * If we tried to use a default value for a
  2426 			 * readonly property, it means that it was not
  1705 			 * readonly property, it means that it was not
  2427 			 * present; return an error.
  1706 			 * present; return an error.
  2428 			 */
  1707 			 */
  2429 			if (zfs_prop_readonly(prop) &&
  1708 			if (zfs_prop_readonly(prop) &&
  2430 			    *source && (*source)[0] == '\0') {
  1709 			    *source && (*source)[0] == '\0') {
  2714 int
  1993 int
  2715 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
  1994 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
  2716 {
  1995 {
  2717 	char buf[64];
  1996 	char buf[64];
  2718 
  1997 
  2719 	zfs_nicenum(val, buf, sizeof (buf));
  1998 	(void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
  2720 	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
  1999 	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
  2721 }
  2000 }
  2722 
  2001 
  2723 /*
  2002 /*
  2724  * Similar to zfs_prop_get(), but returns the value as an integer.
  2003  * Similar to zfs_prop_get(), but returns the value as an integer.
  2744 	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
  2023 	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
  2745 		return (-1);
  2024 		return (-1);
  2746 
  2025 
  2747 	get_source(zhp, src, source, statbuf, statlen);
  2026 	get_source(zhp, src, source, statbuf, statlen);
  2748 
  2027 
       
  2028 	return (0);
       
  2029 }
       
  2030 
       
  2031 static int
       
  2032 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
       
  2033     char **domainp, idmap_rid_t *ridp)
       
  2034 {
       
  2035 	idmap_handle_t *idmap_hdl = NULL;
       
  2036 	idmap_get_handle_t *get_hdl = NULL;
       
  2037 	idmap_stat status;
       
  2038 	int err = EINVAL;
       
  2039 
       
  2040 	if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS)
       
  2041 		goto out;
       
  2042 	if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS)
       
  2043 		goto out;
       
  2044 
       
  2045 	if (isuser) {
       
  2046 		err = idmap_get_sidbyuid(get_hdl, id,
       
  2047 		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
       
  2048 	} else {
       
  2049 		err = idmap_get_sidbygid(get_hdl, id,
       
  2050 		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
       
  2051 	}
       
  2052 	if (err == IDMAP_SUCCESS &&
       
  2053 	    idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
       
  2054 	    status == IDMAP_SUCCESS)
       
  2055 		err = 0;
       
  2056 	else
       
  2057 		err = EINVAL;
       
  2058 out:
       
  2059 	if (get_hdl)
       
  2060 		idmap_get_destroy(get_hdl);
       
  2061 	if (idmap_hdl)
       
  2062 		(void) idmap_fini(idmap_hdl);
       
  2063 	return (err);
       
  2064 }
       
  2065 
       
  2066 /*
       
  2067  * convert the propname into parameters needed by kernel
       
  2068  * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
       
  2069  * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
       
  2070  */
       
  2071 static int
       
  2072 userquota_propname_decode(const char *propname, boolean_t zoned,
       
  2073     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
       
  2074 {
       
  2075 	zfs_userquota_prop_t type;
       
  2076 	char *cp, *end;
       
  2077 	boolean_t isuser;
       
  2078 
       
  2079 	domain[0] = '\0';
       
  2080 
       
  2081 	/* Figure out the property type ({user|group}{quota|space}) */
       
  2082 	for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
       
  2083 		if (strncmp(propname, zfs_userquota_prop_prefixes[type],
       
  2084 		    strlen(zfs_userquota_prop_prefixes[type])) == 0)
       
  2085 			break;
       
  2086 	}
       
  2087 	if (type == ZFS_NUM_USERQUOTA_PROPS)
       
  2088 		return (EINVAL);
       
  2089 	*typep = type;
       
  2090 
       
  2091 	isuser = (type == ZFS_PROP_USERQUOTA ||
       
  2092 	    type == ZFS_PROP_USERUSED);
       
  2093 
       
  2094 	cp = strchr(propname, '@') + 1;
       
  2095 
       
  2096 	if (strchr(cp, '@')) {
       
  2097 		/*
       
  2098 		 * It's a SID name (eg "user@domain") that needs to be
       
  2099 		 * turned into S-1-domainID-RID.  There should be a
       
  2100 		 * better way to do this, but for now just translate it
       
  2101 		 * to the (possibly ephemeral) uid and then back to the
       
  2102 		 * SID.  This is like getsidname(noresolve=TRUE).
       
  2103 		 */
       
  2104 		uid_t id;
       
  2105 		idmap_rid_t rid;
       
  2106 		char *mapdomain;
       
  2107 
       
  2108 		if (zoned && getzoneid() == GLOBAL_ZONEID)
       
  2109 			return (ENOENT);
       
  2110 		if (sid_to_id(cp, isuser, &id) != 0)
       
  2111 			return (ENOENT);
       
  2112 		if (idmap_id_to_numeric_domain_rid(id, isuser,
       
  2113 		    &mapdomain, &rid) != 0)
       
  2114 			return (ENOENT);
       
  2115 		(void) strlcpy(domain, mapdomain, domainlen);
       
  2116 		*ridp = rid;
       
  2117 	} else if (strncmp(cp, "S-1-", 4) == 0) {
       
  2118 		/* It's a numeric SID (eg "S-1-234-567-89") */
       
  2119 		(void) strcpy(domain, cp);
       
  2120 		cp = strrchr(domain, '-');
       
  2121 		*cp = '\0';
       
  2122 		cp++;
       
  2123 
       
  2124 		errno = 0;
       
  2125 		*ridp = strtoull(cp, &end, 10);
       
  2126 		if (errno == 0 || *end != '\0')
       
  2127 			return (EINVAL);
       
  2128 	} else if (!isdigit(*cp)) {
       
  2129 		/*
       
  2130 		 * It's a user/group name (eg "user") that needs to be
       
  2131 		 * turned into a uid/gid
       
  2132 		 */
       
  2133 		if (zoned && getzoneid() == GLOBAL_ZONEID)
       
  2134 			return (ENOENT);
       
  2135 		if (isuser) {
       
  2136 			struct passwd *pw;
       
  2137 			pw = getpwnam(cp);
       
  2138 			if (pw == NULL)
       
  2139 				return (ENOENT);
       
  2140 			*ridp = pw->pw_uid;
       
  2141 		} else {
       
  2142 			struct group *gr;
       
  2143 			gr = getgrnam(cp);
       
  2144 			if (gr == NULL)
       
  2145 				return (ENOENT);
       
  2146 			*ridp = gr->gr_gid;
       
  2147 		}
       
  2148 	} else {
       
  2149 		/* It's a user/group ID (eg "12345"). */
       
  2150 		uid_t id = strtoul(cp, &end, 10);
       
  2151 		idmap_rid_t rid;
       
  2152 		char *mapdomain;
       
  2153 
       
  2154 		if (*end != '\0')
       
  2155 			return (EINVAL);
       
  2156 		if (id > MAXUID) {
       
  2157 			/* It's an ephemeral ID. */
       
  2158 			if (idmap_id_to_numeric_domain_rid(id, isuser,
       
  2159 			    &mapdomain, &rid) != 0)
       
  2160 				return (ENOENT);
       
  2161 			(void) strcpy(domain, mapdomain);
       
  2162 			*ridp = rid;
       
  2163 		} else {
       
  2164 			*ridp = id;
       
  2165 		}
       
  2166 	}
       
  2167 
       
  2168 	return (0);
       
  2169 }
       
  2170 
       
  2171 int
       
  2172 zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
       
  2173     char *propbuf, int proplen, boolean_t literal)
       
  2174 {
       
  2175 	int err;
       
  2176 	zfs_cmd_t zc = { 0 };
       
  2177 	zfs_userquota_prop_t type;
       
  2178 
       
  2179 	(void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
       
  2180 
       
  2181 	err = userquota_propname_decode(propname,
       
  2182 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
       
  2183 	    &type, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
       
  2184 	zc.zc_objset_type = type;
       
  2185 	if (err)
       
  2186 		return (err);
       
  2187 
       
  2188 	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
       
  2189 	if (err)
       
  2190 		return (err);
       
  2191 
       
  2192 	if (literal) {
       
  2193 		(void) snprintf(propbuf, proplen, "%llu",
       
  2194 		    (u_longlong_t)zc.zc_cookie);
       
  2195 	} else if (zc.zc_cookie == 0 &&
       
  2196 	    (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
       
  2197 		(void) strlcpy(propbuf, "none", proplen);
       
  2198 	} else {
       
  2199 		zfs_nicenum(zc.zc_cookie, propbuf, proplen);
       
  2200 	}
  2749 	return (0);
  2201 	return (0);
  2750 }
  2202 }
  2751 
  2203 
  2752 /*
  2204 /*
  2753  * Returns the name of the given zfs handle.
  2205  * Returns the name of the given zfs handle.
  2823 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
  2275 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
  2824 		return (-1);
  2276 		return (-1);
  2825 
  2277 
  2826 	while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
  2278 	while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
  2827 	    &zc)) == 0) {
  2279 	    &zc)) == 0) {
  2828 		/*
       
  2829 		 * Ignore private dataset names.
       
  2830 		 */
       
  2831 		if (dataset_name_hidden(zc.zc_name))
       
  2832 			continue;
       
  2833 
       
  2834 		/*
  2280 		/*
  2835 		 * Silently ignore errors, as the only plausible explanation is
  2281 		 * Silently ignore errors, as the only plausible explanation is
  2836 		 * that the pool has since been removed.
  2282 		 * that the pool has since been removed.
  2837 		 */
  2283 		 */
  2838 		if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
  2284 		if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
  4486 
  3932 
  4487 	while (curr) {
  3933 	while (curr) {
  4488 		zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
  3934 		zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
  4489 		nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
  3935 		nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
  4490 
  3936 
  4491 		if (props[zfs_prop] == B_FALSE)
  3937 		/*
       
  3938 		 * We leave user:props in the nvlist, so there will be
       
  3939 		 * some ZPROP_INVAL.  To be extra safe, don't prune
       
  3940 		 * those.
       
  3941 		 */
       
  3942 		if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
  4492 			(void) nvlist_remove(zhp->zfs_props,
  3943 			(void) nvlist_remove(zhp->zfs_props,
  4493 			    nvpair_name(curr), nvpair_type(curr));
  3944 			    nvpair_name(curr), nvpair_type(curr));
  4494 		curr = next;
  3945 		curr = next;
  4495 	}
  3946 	}
  4496 }
  3947 }
  4574     char *oldname, char *newname)
  4025     char *oldname, char *newname)
  4575 {
  4026 {
  4576 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
  4027 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
  4577 	    oldname, newname));
  4028 	    oldname, newname));
  4578 }
  4029 }
       
  4030 
       
  4031 int
       
  4032 zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
       
  4033     zfs_userspace_cb_t func, void *arg)
       
  4034 {
       
  4035 	zfs_cmd_t zc = { 0 };
       
  4036 	int error;
       
  4037 	zfs_useracct_t buf[100];
       
  4038 
       
  4039 	(void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
       
  4040 
       
  4041 	zc.zc_objset_type = type;
       
  4042 	zc.zc_nvlist_dst = (uintptr_t)buf;
       
  4043 
       
  4044 	/* CONSTCOND */
       
  4045 	while (1) {
       
  4046 		zfs_useracct_t *zua = buf;
       
  4047 
       
  4048 		zc.zc_nvlist_dst_size = sizeof (buf);
       
  4049 		error = ioctl(zhp->zfs_hdl->libzfs_fd,
       
  4050 		    ZFS_IOC_USERSPACE_MANY, &zc);
       
  4051 		if (error || zc.zc_nvlist_dst_size == 0)
       
  4052 			break;
       
  4053 
       
  4054 		while (zc.zc_nvlist_dst_size > 0) {
       
  4055 			func(arg, zua->zu_domain, zua->zu_rid, zua->zu_space);
       
  4056 			zua++;
       
  4057 			zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
       
  4058 		}
       
  4059 	}
       
  4060 
       
  4061 	return (error);
       
  4062 }