xref: /freebsd-src/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py (revision 6cec9cad762b6476313fb1f8e931a1647822db6b)
110b9d77bSPawel Jakub Dawidek#! /usr/bin/python2.6
28fc25799SMartin Matuska#
38fc25799SMartin Matuska# CDDL HEADER START
48fc25799SMartin Matuska#
58fc25799SMartin Matuska# The contents of this file are subject to the terms of the
68fc25799SMartin Matuska# Common Development and Distribution License (the "License").
78fc25799SMartin Matuska# You may not use this file except in compliance with the License.
88fc25799SMartin Matuska#
98fc25799SMartin Matuska# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
108fc25799SMartin Matuska# or http://www.opensolaris.org/os/licensing.
118fc25799SMartin Matuska# See the License for the specific language governing permissions
128fc25799SMartin Matuska# and limitations under the License.
138fc25799SMartin Matuska#
148fc25799SMartin Matuska# When distributing Covered Code, include this CDDL HEADER in each
158fc25799SMartin Matuska# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
168fc25799SMartin Matuska# If applicable, add the following below this CDDL HEADER, with the
178fc25799SMartin Matuska# fields enclosed by brackets "[]" replaced with your own identifying
188fc25799SMartin Matuska# information: Portions Copyright [yyyy] [name of copyright owner]
198fc25799SMartin Matuska#
208fc25799SMartin Matuska# CDDL HEADER END
218fc25799SMartin Matuska#
2210b9d77bSPawel Jakub Dawidek# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23*ab0b9f6bSXin LI# Copyright (c) 2013 by Delphix. All rights reserved.
248fc25799SMartin Matuska#
258fc25799SMartin Matuska
268fc25799SMartin Matuska"""This module implements the "zfs allow" and "zfs unallow" subcommands.
278fc25799SMartin MatuskaThe only public interface is the zfs.allow.do_allow() function."""
288fc25799SMartin Matuska
298fc25799SMartin Matuskaimport zfs.util
308fc25799SMartin Matuskaimport zfs.dataset
318fc25799SMartin Matuskaimport optparse
328fc25799SMartin Matuskaimport sys
338fc25799SMartin Matuskaimport pwd
348fc25799SMartin Matuskaimport grp
358fc25799SMartin Matuskaimport errno
368fc25799SMartin Matuska
378fc25799SMartin Matuska_ = zfs.util._
388fc25799SMartin Matuska
398fc25799SMartin Matuskaclass FSPerms(object):
408fc25799SMartin Matuska	"""This class represents all the permissions that are set on a
418fc25799SMartin Matuska	particular filesystem (not including those inherited)."""
428fc25799SMartin Matuska
438fc25799SMartin Matuska	__slots__ = "create", "sets", "local", "descend", "ld"
448fc25799SMartin Matuska	__repr__ = zfs.util.default_repr
458fc25799SMartin Matuska
468fc25799SMartin Matuska	def __init__(self, raw):
478fc25799SMartin Matuska		"""Create a FSPerms based on the dict of raw permissions
488fc25799SMartin Matuska		from zfs.ioctl.get_fsacl()."""
498fc25799SMartin Matuska		# set of perms
508fc25799SMartin Matuska		self.create = set()
518fc25799SMartin Matuska
528fc25799SMartin Matuska		# below are { "Ntype name": set(perms) }
538fc25799SMartin Matuska		# where N is a number that we just use for sorting,
548fc25799SMartin Matuska		# type is "user", "group", "everyone", or "" (for sets)
558fc25799SMartin Matuska		# name is a user, group, or set name, or "" (for everyone)
568fc25799SMartin Matuska		self.sets = dict()
578fc25799SMartin Matuska		self.local = dict()
588fc25799SMartin Matuska		self.descend = dict()
598fc25799SMartin Matuska		self.ld = dict()
608fc25799SMartin Matuska
618fc25799SMartin Matuska		# see the comment in dsl_deleg.c for the definition of whokey
628fc25799SMartin Matuska		for whokey in raw.keys():
638fc25799SMartin Matuska			perms = raw[whokey].keys()
648fc25799SMartin Matuska			whotypechr = whokey[0].lower()
658fc25799SMartin Matuska			ws = whokey[3:]
668fc25799SMartin Matuska			if whotypechr == "c":
678fc25799SMartin Matuska				self.create.update(perms)
688fc25799SMartin Matuska			elif whotypechr == "s":
698fc25799SMartin Matuska				nwho = "1" + ws
708fc25799SMartin Matuska				self.sets.setdefault(nwho, set()).update(perms)
718fc25799SMartin Matuska			else:
728fc25799SMartin Matuska				if whotypechr == "u":
738fc25799SMartin Matuska					try:
748fc25799SMartin Matuska						name = pwd.getpwuid(int(ws)).pw_name
758fc25799SMartin Matuska					except KeyError:
768fc25799SMartin Matuska						name = ws
778fc25799SMartin Matuska					nwho = "1user " + name
788fc25799SMartin Matuska				elif whotypechr == "g":
798fc25799SMartin Matuska					try:
808fc25799SMartin Matuska						name = grp.getgrgid(int(ws)).gr_name
818fc25799SMartin Matuska					except KeyError:
828fc25799SMartin Matuska						name = ws
838fc25799SMartin Matuska					nwho = "2group " + name
848fc25799SMartin Matuska				elif whotypechr == "e":
858fc25799SMartin Matuska					nwho = "3everyone"
868fc25799SMartin Matuska				else:
878fc25799SMartin Matuska					raise ValueError(whotypechr)
888fc25799SMartin Matuska
898fc25799SMartin Matuska				if whokey[1] == "l":
908fc25799SMartin Matuska					d = self.local
918fc25799SMartin Matuska				elif whokey[1] == "d":
928fc25799SMartin Matuska					d = self.descend
938fc25799SMartin Matuska				else:
948fc25799SMartin Matuska					raise ValueError(whokey[1])
958fc25799SMartin Matuska
968fc25799SMartin Matuska				d.setdefault(nwho, set()).update(perms)
978fc25799SMartin Matuska
988fc25799SMartin Matuska		# Find perms that are in both local and descend, and
998fc25799SMartin Matuska		# move them to ld.
1008fc25799SMartin Matuska		for nwho in self.local:
1018fc25799SMartin Matuska			if nwho not in self.descend:
1028fc25799SMartin Matuska				continue
1038fc25799SMartin Matuska			# note: these are set operations
1048fc25799SMartin Matuska			self.ld[nwho] = self.local[nwho] & self.descend[nwho]
1058fc25799SMartin Matuska			self.local[nwho] -= self.ld[nwho]
1068fc25799SMartin Matuska			self.descend[nwho] -= self.ld[nwho]
1078fc25799SMartin Matuska
1088fc25799SMartin Matuska	@staticmethod
1098fc25799SMartin Matuska	def __ldstr(d, header):
1108fc25799SMartin Matuska		s = ""
1118fc25799SMartin Matuska		for (nwho, perms) in sorted(d.items()):
1128fc25799SMartin Matuska			# local and descend may have entries where perms
1138fc25799SMartin Matuska			# is an empty set, due to consolidating all
1148fc25799SMartin Matuska			# permissions into ld
1158fc25799SMartin Matuska			if perms:
1168fc25799SMartin Matuska				s += "\t%s %s\n" % \
1178fc25799SMartin Matuska				    (nwho[1:], ",".join(sorted(perms)))
1188fc25799SMartin Matuska		if s:
1198fc25799SMartin Matuska			s = header + s
1208fc25799SMartin Matuska		return s
1218fc25799SMartin Matuska
1228fc25799SMartin Matuska	def __str__(self):
1238fc25799SMartin Matuska		s = self.__ldstr(self.sets, _("Permission sets:\n"))
1248fc25799SMartin Matuska
1258fc25799SMartin Matuska		if self.create:
1268fc25799SMartin Matuska			s += _("Create time permissions:\n")
1278fc25799SMartin Matuska			s += "\t%s\n" % ",".join(sorted(self.create))
1288fc25799SMartin Matuska
1298fc25799SMartin Matuska		s += self.__ldstr(self.local, _("Local permissions:\n"))
1308fc25799SMartin Matuska		s += self.__ldstr(self.descend, _("Descendent permissions:\n"))
1318fc25799SMartin Matuska		s += self.__ldstr(self.ld, _("Local+Descendent permissions:\n"))
1328fc25799SMartin Matuska		return s.rstrip()
1338fc25799SMartin Matuska
1348fc25799SMartin Matuskadef args_to_perms(parser, options, who, perms):
1358fc25799SMartin Matuska	"""Return a dict of raw perms {"whostr" -> {"perm" -> None}}
1368fc25799SMartin Matuska	based on the command-line input."""
1378fc25799SMartin Matuska
1388fc25799SMartin Matuska	# perms is not set if we are doing a "zfs unallow <who> <fs>" to
1398fc25799SMartin Matuska	# remove all of someone's permissions
1408fc25799SMartin Matuska	if perms:
1418fc25799SMartin Matuska		setperms = dict(((p, None) for p in perms if p[0] == "@"))
1428fc25799SMartin Matuska		baseperms = dict(((canonicalized_perm(p), None)
1438fc25799SMartin Matuska		    for p in perms if p[0] != "@"))
1448fc25799SMartin Matuska	else:
1458fc25799SMartin Matuska		setperms = None
1468fc25799SMartin Matuska		baseperms = None
1478fc25799SMartin Matuska
1488fc25799SMartin Matuska	d = dict()
1498fc25799SMartin Matuska
1508fc25799SMartin Matuska	def storeperm(typechr, inheritchr, arg):
1518fc25799SMartin Matuska		assert typechr in "ugecs"
1528fc25799SMartin Matuska		assert inheritchr in "ld-"
1538fc25799SMartin Matuska
1548fc25799SMartin Matuska		def mkwhokey(t):
1558fc25799SMartin Matuska			return "%c%c$%s" % (t, inheritchr, arg)
1568fc25799SMartin Matuska
1578fc25799SMartin Matuska		if baseperms or not perms:
1588fc25799SMartin Matuska			d[mkwhokey(typechr)] = baseperms
1598fc25799SMartin Matuska		if setperms or not perms:
1608fc25799SMartin Matuska			d[mkwhokey(typechr.upper())] = setperms
1618fc25799SMartin Matuska
1628fc25799SMartin Matuska	def decodeid(w, toidfunc, fmt):
1638fc25799SMartin Matuska		try:
1648fc25799SMartin Matuska			return int(w)
1658fc25799SMartin Matuska		except ValueError:
1668fc25799SMartin Matuska			try:
1678fc25799SMartin Matuska				return toidfunc(w)[2]
1688fc25799SMartin Matuska			except KeyError:
1698fc25799SMartin Matuska				parser.error(fmt % w)
1708fc25799SMartin Matuska
1718fc25799SMartin Matuska	if options.set:
1728fc25799SMartin Matuska		storeperm("s", "-", who)
1738fc25799SMartin Matuska	elif options.create:
1748fc25799SMartin Matuska		storeperm("c", "-", "")
1758fc25799SMartin Matuska	else:
1768fc25799SMartin Matuska		for w in who:
1778fc25799SMartin Matuska			if options.user:
1788fc25799SMartin Matuska				id = decodeid(w, pwd.getpwnam,
1798fc25799SMartin Matuska				    _("invalid user %s"))
1808fc25799SMartin Matuska				typechr = "u"
1818fc25799SMartin Matuska			elif options.group:
1828fc25799SMartin Matuska				id = decodeid(w, grp.getgrnam,
1838fc25799SMartin Matuska				    _("invalid group %s"))
1848fc25799SMartin Matuska				typechr = "g"
1858fc25799SMartin Matuska			elif w == "everyone":
1868fc25799SMartin Matuska				id = ""
1878fc25799SMartin Matuska				typechr = "e"
1888fc25799SMartin Matuska			else:
1898fc25799SMartin Matuska				try:
1908fc25799SMartin Matuska					id = pwd.getpwnam(w)[2]
1918fc25799SMartin Matuska					typechr = "u"
1928fc25799SMartin Matuska				except KeyError:
1938fc25799SMartin Matuska					try:
1948fc25799SMartin Matuska						id = grp.getgrnam(w)[2]
1958fc25799SMartin Matuska						typechr = "g"
1968fc25799SMartin Matuska					except KeyError:
1978fc25799SMartin Matuska						parser.error(_("invalid user/group %s") % w)
1988fc25799SMartin Matuska			if options.local:
1998fc25799SMartin Matuska				storeperm(typechr, "l", id)
2008fc25799SMartin Matuska			if options.descend:
2018fc25799SMartin Matuska				storeperm(typechr, "d", id)
2028fc25799SMartin Matuska	return d
2038fc25799SMartin Matuska
2048fc25799SMartin Matuskaperms_subcmd = dict(
2058fc25799SMartin Matuska    create=_("Must also have the 'mount' ability"),
2068fc25799SMartin Matuska    destroy=_("Must also have the 'mount' ability"),
20710b9d77bSPawel Jakub Dawidek    snapshot="",
20810b9d77bSPawel Jakub Dawidek    rollback="",
2098fc25799SMartin Matuska    clone=_("""Must also have the 'create' ability and 'mount'
2108fc25799SMartin Matuska\t\t\t\tability in the origin file system"""),
2118fc25799SMartin Matuska    promote=_("""Must also have the 'mount'
2128fc25799SMartin Matuska\t\t\t\tand 'promote' ability in the origin file system"""),
2138fc25799SMartin Matuska    rename=_("""Must also have the 'mount' and 'create'
2148fc25799SMartin Matuska\t\t\t\tability in the new parent"""),
2158fc25799SMartin Matuska    receive=_("Must also have the 'mount' and 'create' ability"),
2168fc25799SMartin Matuska    allow=_("Must also have the permission that is being\n\t\t\t\tallowed"),
2178fc25799SMartin Matuska    mount=_("Allows mount/umount of ZFS datasets"),
2188fc25799SMartin Matuska    share=_("Allows sharing file systems over NFS or SMB\n\t\t\t\tprotocols"),
2198fc25799SMartin Matuska    send="",
22010b9d77bSPawel Jakub Dawidek    hold=_("Allows adding a user hold to a snapshot"),
22110b9d77bSPawel Jakub Dawidek    release=_("Allows releasing a user hold which\n\t\t\t\tmight destroy the snapshot"),
22210b9d77bSPawel Jakub Dawidek    diff=_("Allows lookup of paths within a dataset,\n\t\t\t\tgiven an object number. Ordinary users need this\n\t\t\t\tin order to use zfs diff"),
223*ab0b9f6bSXin LI    bookmark="",
2248fc25799SMartin Matuska)
2258fc25799SMartin Matuska
2268fc25799SMartin Matuskaperms_other = dict(
2278fc25799SMartin Matuska    userprop=_("Allows changing any user property"),
2288fc25799SMartin Matuska    userquota=_("Allows accessing any userquota@... property"),
2298fc25799SMartin Matuska    groupquota=_("Allows accessing any groupquota@... property"),
2308fc25799SMartin Matuska    userused=_("Allows reading any userused@... property"),
2318fc25799SMartin Matuska    groupused=_("Allows reading any groupused@... property"),
2328fc25799SMartin Matuska)
2338fc25799SMartin Matuska
2348fc25799SMartin Matuskadef hasset(ds, setname):
2358fc25799SMartin Matuska	"""Return True if the given setname (string) is defined for this
2368fc25799SMartin Matuska	ds (Dataset)."""
2378fc25799SMartin Matuska	# It would be nice to cache the result of get_fsacl().
2388fc25799SMartin Matuska	for raw in ds.get_fsacl().values():
2398fc25799SMartin Matuska		for whokey in raw.keys():
2408fc25799SMartin Matuska			if whokey[0].lower() == "s" and whokey[3:] == setname:
2418fc25799SMartin Matuska				return True
2428fc25799SMartin Matuska	return False
2438fc25799SMartin Matuska
2448fc25799SMartin Matuskadef canonicalized_perm(permname):
2458fc25799SMartin Matuska	"""Return the canonical name (string) for this permission (string).
2468fc25799SMartin Matuska	Raises ZFSError if it is not a valid permission."""
2478fc25799SMartin Matuska	if permname in perms_subcmd.keys() or permname in perms_other.keys():
2488fc25799SMartin Matuska		return permname
2498fc25799SMartin Matuska	try:
2508fc25799SMartin Matuska		return zfs.dataset.getpropobj(permname).name
2518fc25799SMartin Matuska	except KeyError:
2528fc25799SMartin Matuska		raise zfs.util.ZFSError(errno.EINVAL, permname,
2538fc25799SMartin Matuska		    _("invalid permission"))
2548fc25799SMartin Matuska
2558fc25799SMartin Matuskadef print_perms():
2568fc25799SMartin Matuska	"""Print the set of supported permissions."""
2578fc25799SMartin Matuska	print(_("\nThe following permissions are supported:\n"))
2588fc25799SMartin Matuska	fmt = "%-16s %-14s\t%s"
2598fc25799SMartin Matuska	print(fmt % (_("NAME"), _("TYPE"), _("NOTES")))
2608fc25799SMartin Matuska
2618fc25799SMartin Matuska	for (name, note) in sorted(perms_subcmd.iteritems()):
2628fc25799SMartin Matuska		print(fmt % (name, _("subcommand"), note))
2638fc25799SMartin Matuska
2648fc25799SMartin Matuska	for (name, note) in sorted(perms_other.iteritems()):
2658fc25799SMartin Matuska		print(fmt % (name, _("other"), note))
2668fc25799SMartin Matuska
2678fc25799SMartin Matuska	for (name, prop) in sorted(zfs.dataset.proptable.iteritems()):
2688fc25799SMartin Matuska		if prop.visible and prop.delegatable():
2698fc25799SMartin Matuska			print(fmt % (name, _("property"), ""))
2708fc25799SMartin Matuska
2718fc25799SMartin Matuskadef do_allow():
27210b9d77bSPawel Jakub Dawidek	"""Implements the "zfs allow" and "zfs unallow" subcommands."""
2738fc25799SMartin Matuska	un = (sys.argv[1] == "unallow")
2748fc25799SMartin Matuska
2758fc25799SMartin Matuska	def usage(msg=None):
2768fc25799SMartin Matuska		parser.print_help()
2778fc25799SMartin Matuska		print_perms()
2788fc25799SMartin Matuska		if msg:
2798fc25799SMartin Matuska			print
2808fc25799SMartin Matuska			parser.exit("zfs: error: " + msg)
2818fc25799SMartin Matuska		else:
2828fc25799SMartin Matuska			parser.exit()
2838fc25799SMartin Matuska
2848fc25799SMartin Matuska	if un:
2858fc25799SMartin Matuska		u = _("""unallow [-rldug] <"everyone"|user|group>[,...]
2868fc25799SMartin Matuska	    [<perm|@setname>[,...]] <filesystem|volume>
2878fc25799SMartin Matuska	unallow [-rld] -e [<perm|@setname>[,...]] <filesystem|volume>
2888fc25799SMartin Matuska	unallow [-r] -c [<perm|@setname>[,...]] <filesystem|volume>
2898fc25799SMartin Matuska	unallow [-r] -s @setname [<perm|@setname>[,...]] <filesystem|volume>""")
2908fc25799SMartin Matuska		verb = _("remove")
2918fc25799SMartin Matuska		sstr = _("undefine permission set")
2928fc25799SMartin Matuska	else:
2938fc25799SMartin Matuska		u = _("""allow <filesystem|volume>
2948fc25799SMartin Matuska	allow [-ldug] <"everyone"|user|group>[,...] <perm|@setname>[,...]
2958fc25799SMartin Matuska	    <filesystem|volume>
2968fc25799SMartin Matuska	allow [-ld] -e <perm|@setname>[,...] <filesystem|volume>
2978fc25799SMartin Matuska	allow -c <perm|@setname>[,...] <filesystem|volume>
2988fc25799SMartin Matuska	allow -s @setname <perm|@setname>[,...] <filesystem|volume>""")
2998fc25799SMartin Matuska		verb = _("set")
3008fc25799SMartin Matuska		sstr = _("define permission set")
3018fc25799SMartin Matuska
3028fc25799SMartin Matuska	parser = optparse.OptionParser(usage=u, prog="zfs")
3038fc25799SMartin Matuska
3048fc25799SMartin Matuska	parser.add_option("-l", action="store_true", dest="local",
3058fc25799SMartin Matuska	    help=_("%s permission locally") % verb)
3068fc25799SMartin Matuska	parser.add_option("-d", action="store_true", dest="descend",
3078fc25799SMartin Matuska	    help=_("%s permission for descendents") % verb)
3088fc25799SMartin Matuska	parser.add_option("-u", action="store_true", dest="user",
3098fc25799SMartin Matuska	    help=_("%s permission for user") % verb)
3108fc25799SMartin Matuska	parser.add_option("-g", action="store_true", dest="group",
3118fc25799SMartin Matuska	    help=_("%s permission for group") % verb)
3128fc25799SMartin Matuska	parser.add_option("-e", action="store_true", dest="everyone",
3138fc25799SMartin Matuska	    help=_("%s permission for everyone") % verb)
3148fc25799SMartin Matuska	parser.add_option("-c", action="store_true", dest="create",
3158fc25799SMartin Matuska	    help=_("%s create time permissions") % verb)
3168fc25799SMartin Matuska	parser.add_option("-s", action="store_true", dest="set", help=sstr)
3178fc25799SMartin Matuska	if un:
3188fc25799SMartin Matuska		parser.add_option("-r", action="store_true", dest="recursive",
3198fc25799SMartin Matuska		    help=_("remove permissions recursively"))
3208fc25799SMartin Matuska
3218fc25799SMartin Matuska	if len(sys.argv) == 3 and not un:
3228fc25799SMartin Matuska		# just print the permissions on this fs
3238fc25799SMartin Matuska
3248fc25799SMartin Matuska		if sys.argv[2] == "-h":
3258fc25799SMartin Matuska			# hack to make "zfs allow -h" work
3268fc25799SMartin Matuska			usage()
32710b9d77bSPawel Jakub Dawidek		ds = zfs.dataset.Dataset(sys.argv[2], snaps=False)
3288fc25799SMartin Matuska
3298fc25799SMartin Matuska		p = dict()
3308fc25799SMartin Matuska		for (fs, raw) in ds.get_fsacl().items():
3318fc25799SMartin Matuska			p[fs] = FSPerms(raw)
3328fc25799SMartin Matuska
3338fc25799SMartin Matuska		for fs in sorted(p.keys(), reverse=True):
3348fc25799SMartin Matuska			s = _("---- Permissions on %s ") % fs
3358fc25799SMartin Matuska			print(s + "-" * (70-len(s)))
3368fc25799SMartin Matuska			print(p[fs])
3378fc25799SMartin Matuska		return
3388fc25799SMartin Matuska
3398fc25799SMartin Matuska
3408fc25799SMartin Matuska	(options, args) = parser.parse_args(sys.argv[2:])
3418fc25799SMartin Matuska
3428fc25799SMartin Matuska	if sum((bool(options.everyone), bool(options.user),
3438fc25799SMartin Matuska	    bool(options.group))) > 1:
3448fc25799SMartin Matuska		parser.error(_("-u, -g, and -e are mutually exclusive"))
3458fc25799SMartin Matuska
3468fc25799SMartin Matuska	def mungeargs(expected_len):
3478fc25799SMartin Matuska		if un and len(args) == expected_len-1:
3488fc25799SMartin Matuska			return (None, args[expected_len-2])
3498fc25799SMartin Matuska		elif len(args) == expected_len:
3508fc25799SMartin Matuska			return (args[expected_len-2].split(","),
3518fc25799SMartin Matuska			    args[expected_len-1])
3528fc25799SMartin Matuska		else:
3538fc25799SMartin Matuska			usage(_("wrong number of parameters"))
3548fc25799SMartin Matuska
3558fc25799SMartin Matuska	if options.set:
3568fc25799SMartin Matuska		if options.local or options.descend or options.user or \
3578fc25799SMartin Matuska		    options.group or options.everyone or options.create:
3588fc25799SMartin Matuska			parser.error(_("invalid option combined with -s"))
3598fc25799SMartin Matuska		if args[0][0] != "@":
3608fc25799SMartin Matuska			parser.error(_("invalid set name: missing '@' prefix"))
3618fc25799SMartin Matuska
3628fc25799SMartin Matuska		(perms, fsname) = mungeargs(3)
3638fc25799SMartin Matuska		who = args[0]
3648fc25799SMartin Matuska	elif options.create:
3658fc25799SMartin Matuska		if options.local or options.descend or options.user or \
3668fc25799SMartin Matuska		    options.group or options.everyone or options.set:
3678fc25799SMartin Matuska			parser.error(_("invalid option combined with -c"))
3688fc25799SMartin Matuska
3698fc25799SMartin Matuska		(perms, fsname) = mungeargs(2)
3708fc25799SMartin Matuska		who = None
3718fc25799SMartin Matuska	elif options.everyone:
3728fc25799SMartin Matuska		if options.user or options.group or \
3738fc25799SMartin Matuska		    options.create or options.set:
3748fc25799SMartin Matuska			parser.error(_("invalid option combined with -e"))
3758fc25799SMartin Matuska
3768fc25799SMartin Matuska		(perms, fsname) = mungeargs(2)
3778fc25799SMartin Matuska		who = ["everyone"]
3788fc25799SMartin Matuska	else:
3798fc25799SMartin Matuska		(perms, fsname) = mungeargs(3)
3808fc25799SMartin Matuska		who = args[0].split(",")
3818fc25799SMartin Matuska
3828fc25799SMartin Matuska	if not options.local and not options.descend:
3838fc25799SMartin Matuska		options.local = True
3848fc25799SMartin Matuska		options.descend = True
3858fc25799SMartin Matuska
3868fc25799SMartin Matuska	d = args_to_perms(parser, options, who, perms)
3878fc25799SMartin Matuska
3888fc25799SMartin Matuska	ds = zfs.dataset.Dataset(fsname, snaps=False)
3898fc25799SMartin Matuska
3908fc25799SMartin Matuska	if not un and perms:
3918fc25799SMartin Matuska		for p in perms:
3928fc25799SMartin Matuska			if p[0] == "@" and not hasset(ds, p):
3938fc25799SMartin Matuska				parser.error(_("set %s is not defined") % p)
3948fc25799SMartin Matuska
3958fc25799SMartin Matuska	ds.set_fsacl(un, d)
3968fc25799SMartin Matuska	if un and options.recursive:
3978fc25799SMartin Matuska		for child in ds.descendents():
3988fc25799SMartin Matuska			child.set_fsacl(un, d)
399