124bb1048SAlexander Pyhalov#!@PYTHON@ 214843421SMatthew Ahrens# 314843421SMatthew Ahrens# CDDL HEADER START 414843421SMatthew Ahrens# 514843421SMatthew Ahrens# The contents of this file are subject to the terms of the 614843421SMatthew Ahrens# Common Development and Distribution License (the "License"). 714843421SMatthew Ahrens# You may not use this file except in compliance with the License. 814843421SMatthew Ahrens# 914843421SMatthew Ahrens# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1014843421SMatthew Ahrens# or http://www.opensolaris.org/os/licensing. 1114843421SMatthew Ahrens# See the License for the specific language governing permissions 1214843421SMatthew Ahrens# and limitations under the License. 1314843421SMatthew Ahrens# 1414843421SMatthew Ahrens# When distributing Covered Code, include this CDDL HEADER in each 1514843421SMatthew Ahrens# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1614843421SMatthew Ahrens# If applicable, add the following below this CDDL HEADER, with the 1714843421SMatthew Ahrens# fields enclosed by brackets "[]" replaced with your own identifying 1814843421SMatthew Ahrens# information: Portions Copyright [yyyy] [name of copyright owner] 1914843421SMatthew Ahrens# 2014843421SMatthew Ahrens# CDDL HEADER END 2114843421SMatthew Ahrens# 226d52f363SLori Alt# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2378f17100SMatthew Ahrens# Copyright (c) 2013 by Delphix. All rights reserved. 24*8cfa78e6SAndy Fiddaman# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 2514843421SMatthew Ahrens# 2614843421SMatthew Ahrens 2714843421SMatthew Ahrens"""This module implements the "zfs allow" and "zfs unallow" subcommands. 2814843421SMatthew AhrensThe only public interface is the zfs.allow.do_allow() function.""" 2914843421SMatthew Ahrens 3014843421SMatthew Ahrensimport zfs.util 3114843421SMatthew Ahrensimport zfs.dataset 3214843421SMatthew Ahrensimport optparse 3314843421SMatthew Ahrensimport sys 3414843421SMatthew Ahrensimport pwd 3514843421SMatthew Ahrensimport grp 3614843421SMatthew Ahrensimport errno 3714843421SMatthew Ahrens 3814843421SMatthew Ahrens_ = zfs.util._ 3914843421SMatthew Ahrens 4014843421SMatthew Ahrensclass FSPerms(object): 4114843421SMatthew Ahrens """This class represents all the permissions that are set on a 4214843421SMatthew Ahrens particular filesystem (not including those inherited).""" 4314843421SMatthew Ahrens 4414843421SMatthew Ahrens __slots__ = "create", "sets", "local", "descend", "ld" 4514843421SMatthew Ahrens __repr__ = zfs.util.default_repr 4614843421SMatthew Ahrens 4714843421SMatthew Ahrens def __init__(self, raw): 4814843421SMatthew Ahrens """Create a FSPerms based on the dict of raw permissions 4914843421SMatthew Ahrens from zfs.ioctl.get_fsacl().""" 5014843421SMatthew Ahrens # set of perms 5114843421SMatthew Ahrens self.create = set() 5214843421SMatthew Ahrens 5314843421SMatthew Ahrens # below are { "Ntype name": set(perms) } 5414843421SMatthew Ahrens # where N is a number that we just use for sorting, 5514843421SMatthew Ahrens # type is "user", "group", "everyone", or "" (for sets) 5614843421SMatthew Ahrens # name is a user, group, or set name, or "" (for everyone) 5714843421SMatthew Ahrens self.sets = dict() 5814843421SMatthew Ahrens self.local = dict() 5914843421SMatthew Ahrens self.descend = dict() 6014843421SMatthew Ahrens self.ld = dict() 6114843421SMatthew Ahrens 6214843421SMatthew Ahrens # see the comment in dsl_deleg.c for the definition of whokey 6314843421SMatthew Ahrens for whokey in raw.keys(): 6414843421SMatthew Ahrens perms = raw[whokey].keys() 6514843421SMatthew Ahrens whotypechr = whokey[0].lower() 6614843421SMatthew Ahrens ws = whokey[3:] 6714843421SMatthew Ahrens if whotypechr == "c": 6814843421SMatthew Ahrens self.create.update(perms) 6914843421SMatthew Ahrens elif whotypechr == "s": 7014843421SMatthew Ahrens nwho = "1" + ws 7114843421SMatthew Ahrens self.sets.setdefault(nwho, set()).update(perms) 7214843421SMatthew Ahrens else: 7314843421SMatthew Ahrens if whotypechr == "u": 7414843421SMatthew Ahrens try: 7514843421SMatthew Ahrens name = pwd.getpwuid(int(ws)).pw_name 7614843421SMatthew Ahrens except KeyError: 7714843421SMatthew Ahrens name = ws 7814843421SMatthew Ahrens nwho = "1user " + name 7914843421SMatthew Ahrens elif whotypechr == "g": 8014843421SMatthew Ahrens try: 8114843421SMatthew Ahrens name = grp.getgrgid(int(ws)).gr_name 8214843421SMatthew Ahrens except KeyError: 8314843421SMatthew Ahrens name = ws 8414843421SMatthew Ahrens nwho = "2group " + name 8514843421SMatthew Ahrens elif whotypechr == "e": 8614843421SMatthew Ahrens nwho = "3everyone" 8714843421SMatthew Ahrens else: 8814843421SMatthew Ahrens raise ValueError(whotypechr) 8914843421SMatthew Ahrens 9014843421SMatthew Ahrens if whokey[1] == "l": 9114843421SMatthew Ahrens d = self.local 9214843421SMatthew Ahrens elif whokey[1] == "d": 9314843421SMatthew Ahrens d = self.descend 9414843421SMatthew Ahrens else: 9514843421SMatthew Ahrens raise ValueError(whokey[1]) 9614843421SMatthew Ahrens 9714843421SMatthew Ahrens d.setdefault(nwho, set()).update(perms) 9814843421SMatthew Ahrens 9914843421SMatthew Ahrens # Find perms that are in both local and descend, and 10014843421SMatthew Ahrens # move them to ld. 10114843421SMatthew Ahrens for nwho in self.local: 10214843421SMatthew Ahrens if nwho not in self.descend: 10314843421SMatthew Ahrens continue 10414843421SMatthew Ahrens # note: these are set operations 10514843421SMatthew Ahrens self.ld[nwho] = self.local[nwho] & self.descend[nwho] 10614843421SMatthew Ahrens self.local[nwho] -= self.ld[nwho] 10714843421SMatthew Ahrens self.descend[nwho] -= self.ld[nwho] 10814843421SMatthew Ahrens 10914843421SMatthew Ahrens @staticmethod 11014843421SMatthew Ahrens def __ldstr(d, header): 11114843421SMatthew Ahrens s = "" 11214843421SMatthew Ahrens for (nwho, perms) in sorted(d.items()): 11314843421SMatthew Ahrens # local and descend may have entries where perms 11414843421SMatthew Ahrens # is an empty set, due to consolidating all 11514843421SMatthew Ahrens # permissions into ld 11614843421SMatthew Ahrens if perms: 11714843421SMatthew Ahrens s += "\t%s %s\n" % \ 11814843421SMatthew Ahrens (nwho[1:], ",".join(sorted(perms))) 11914843421SMatthew Ahrens if s: 12014843421SMatthew Ahrens s = header + s 12114843421SMatthew Ahrens return s 12214843421SMatthew Ahrens 12314843421SMatthew Ahrens def __str__(self): 12414843421SMatthew Ahrens s = self.__ldstr(self.sets, _("Permission sets:\n")) 12514843421SMatthew Ahrens 12614843421SMatthew Ahrens if self.create: 12714843421SMatthew Ahrens s += _("Create time permissions:\n") 12814843421SMatthew Ahrens s += "\t%s\n" % ",".join(sorted(self.create)) 12914843421SMatthew Ahrens 13014843421SMatthew Ahrens s += self.__ldstr(self.local, _("Local permissions:\n")) 13114843421SMatthew Ahrens s += self.__ldstr(self.descend, _("Descendent permissions:\n")) 13214843421SMatthew Ahrens s += self.__ldstr(self.ld, _("Local+Descendent permissions:\n")) 13314843421SMatthew Ahrens return s.rstrip() 13414843421SMatthew Ahrens 13514843421SMatthew Ahrensdef args_to_perms(parser, options, who, perms): 13614843421SMatthew Ahrens """Return a dict of raw perms {"whostr" -> {"perm" -> None}} 13714843421SMatthew Ahrens based on the command-line input.""" 13814843421SMatthew Ahrens 13914843421SMatthew Ahrens # perms is not set if we are doing a "zfs unallow <who> <fs>" to 14014843421SMatthew Ahrens # remove all of someone's permissions 14114843421SMatthew Ahrens if perms: 14214843421SMatthew Ahrens setperms = dict(((p, None) for p in perms if p[0] == "@")) 14314843421SMatthew Ahrens baseperms = dict(((canonicalized_perm(p), None) 14414843421SMatthew Ahrens for p in perms if p[0] != "@")) 14514843421SMatthew Ahrens else: 14614843421SMatthew Ahrens setperms = None 14714843421SMatthew Ahrens baseperms = None 14814843421SMatthew Ahrens 14914843421SMatthew Ahrens d = dict() 15014843421SMatthew Ahrens 15114843421SMatthew Ahrens def storeperm(typechr, inheritchr, arg): 15214843421SMatthew Ahrens assert typechr in "ugecs" 15314843421SMatthew Ahrens assert inheritchr in "ld-" 15414843421SMatthew Ahrens 15514843421SMatthew Ahrens def mkwhokey(t): 15614843421SMatthew Ahrens return "%c%c$%s" % (t, inheritchr, arg) 15714843421SMatthew Ahrens 15814843421SMatthew Ahrens if baseperms or not perms: 15914843421SMatthew Ahrens d[mkwhokey(typechr)] = baseperms 16014843421SMatthew Ahrens if setperms or not perms: 16114843421SMatthew Ahrens d[mkwhokey(typechr.upper())] = setperms 16214843421SMatthew Ahrens 16314843421SMatthew Ahrens def decodeid(w, toidfunc, fmt): 16414843421SMatthew Ahrens try: 16514843421SMatthew Ahrens return int(w) 16614843421SMatthew Ahrens except ValueError: 16714843421SMatthew Ahrens try: 16814843421SMatthew Ahrens return toidfunc(w)[2] 16914843421SMatthew Ahrens except KeyError: 17014843421SMatthew Ahrens parser.error(fmt % w) 17114843421SMatthew Ahrens 17214843421SMatthew Ahrens if options.set: 17314843421SMatthew Ahrens storeperm("s", "-", who) 17414843421SMatthew Ahrens elif options.create: 17514843421SMatthew Ahrens storeperm("c", "-", "") 17614843421SMatthew Ahrens else: 17714843421SMatthew Ahrens for w in who: 17814843421SMatthew Ahrens if options.user: 17914843421SMatthew Ahrens id = decodeid(w, pwd.getpwnam, 18014843421SMatthew Ahrens _("invalid user %s")) 18114843421SMatthew Ahrens typechr = "u" 18214843421SMatthew Ahrens elif options.group: 18314843421SMatthew Ahrens id = decodeid(w, grp.getgrnam, 18414843421SMatthew Ahrens _("invalid group %s")) 18514843421SMatthew Ahrens typechr = "g" 18614843421SMatthew Ahrens elif w == "everyone": 18714843421SMatthew Ahrens id = "" 18814843421SMatthew Ahrens typechr = "e" 18914843421SMatthew Ahrens else: 19014843421SMatthew Ahrens try: 19114843421SMatthew Ahrens id = pwd.getpwnam(w)[2] 19214843421SMatthew Ahrens typechr = "u" 19314843421SMatthew Ahrens except KeyError: 19414843421SMatthew Ahrens try: 19514843421SMatthew Ahrens id = grp.getgrnam(w)[2] 19614843421SMatthew Ahrens typechr = "g" 19714843421SMatthew Ahrens except KeyError: 19814843421SMatthew Ahrens parser.error(_("invalid user/group %s") % w) 19914843421SMatthew Ahrens if options.local: 20014843421SMatthew Ahrens storeperm(typechr, "l", id) 20114843421SMatthew Ahrens if options.descend: 20214843421SMatthew Ahrens storeperm(typechr, "d", id) 20314843421SMatthew Ahrens return d 20414843421SMatthew Ahrens 20514843421SMatthew Ahrensperms_subcmd = dict( 20614843421SMatthew Ahrens create=_("Must also have the 'mount' ability"), 20714843421SMatthew Ahrens destroy=_("Must also have the 'mount' ability"), 208681d9761SEric Taylor snapshot="", 209681d9761SEric Taylor rollback="", 21014843421SMatthew Ahrens clone=_("""Must also have the 'create' ability and 'mount' 21114843421SMatthew Ahrens\t\t\t\tability in the origin file system"""), 21214843421SMatthew Ahrens promote=_("""Must also have the 'mount' 21314843421SMatthew Ahrens\t\t\t\tand 'promote' ability in the origin file system"""), 21414843421SMatthew Ahrens rename=_("""Must also have the 'mount' and 'create' 21514843421SMatthew Ahrens\t\t\t\tability in the new parent"""), 21614843421SMatthew Ahrens receive=_("Must also have the 'mount' and 'create' ability"), 21714843421SMatthew Ahrens allow=_("Must also have the permission that is being\n\t\t\t\tallowed"), 21814843421SMatthew Ahrens mount=_("Allows mount/umount of ZFS datasets"), 21914843421SMatthew Ahrens share=_("Allows sharing file systems over NFS or SMB\n\t\t\t\tprotocols"), 22014843421SMatthew Ahrens send="", 221842727c2SChris Kirby hold=_("Allows adding a user hold to a snapshot"), 222842727c2SChris Kirby release=_("Allows releasing a user hold which\n\t\t\t\tmight destroy the snapshot"), 22399d5e173STim Haley 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"), 22478f17100SMatthew Ahrens bookmark="", 22514843421SMatthew Ahrens) 22614843421SMatthew Ahrens 22714843421SMatthew Ahrensperms_other = dict( 22814843421SMatthew Ahrens userprop=_("Allows changing any user property"), 22914843421SMatthew Ahrens userquota=_("Allows accessing any userquota@... property"), 23014843421SMatthew Ahrens groupquota=_("Allows accessing any groupquota@... property"), 23114843421SMatthew Ahrens userused=_("Allows reading any userused@... property"), 23214843421SMatthew Ahrens groupused=_("Allows reading any groupused@... property"), 23314843421SMatthew Ahrens) 23414843421SMatthew Ahrens 23514843421SMatthew Ahrensdef hasset(ds, setname): 23614843421SMatthew Ahrens """Return True if the given setname (string) is defined for this 23714843421SMatthew Ahrens ds (Dataset).""" 23814843421SMatthew Ahrens # It would be nice to cache the result of get_fsacl(). 23914843421SMatthew Ahrens for raw in ds.get_fsacl().values(): 24014843421SMatthew Ahrens for whokey in raw.keys(): 24114843421SMatthew Ahrens if whokey[0].lower() == "s" and whokey[3:] == setname: 24214843421SMatthew Ahrens return True 24314843421SMatthew Ahrens return False 24414843421SMatthew Ahrens 24514843421SMatthew Ahrensdef canonicalized_perm(permname): 24614843421SMatthew Ahrens """Return the canonical name (string) for this permission (string). 24714843421SMatthew Ahrens Raises ZFSError if it is not a valid permission.""" 24814843421SMatthew Ahrens if permname in perms_subcmd.keys() or permname in perms_other.keys(): 24914843421SMatthew Ahrens return permname 25014843421SMatthew Ahrens try: 25114843421SMatthew Ahrens return zfs.dataset.getpropobj(permname).name 25214843421SMatthew Ahrens except KeyError: 25314843421SMatthew Ahrens raise zfs.util.ZFSError(errno.EINVAL, permname, 25414843421SMatthew Ahrens _("invalid permission")) 25514843421SMatthew Ahrens 25614843421SMatthew Ahrensdef print_perms(): 25714843421SMatthew Ahrens """Print the set of supported permissions.""" 25814843421SMatthew Ahrens print(_("\nThe following permissions are supported:\n")) 25914843421SMatthew Ahrens fmt = "%-16s %-14s\t%s" 26014843421SMatthew Ahrens print(fmt % (_("NAME"), _("TYPE"), _("NOTES"))) 26114843421SMatthew Ahrens 262*8cfa78e6SAndy Fiddaman for (name, note) in sorted(perms_subcmd.items()): 26314843421SMatthew Ahrens print(fmt % (name, _("subcommand"), note)) 26414843421SMatthew Ahrens 265*8cfa78e6SAndy Fiddaman for (name, note) in sorted(perms_other.items()): 26614843421SMatthew Ahrens print(fmt % (name, _("other"), note)) 26714843421SMatthew Ahrens 268*8cfa78e6SAndy Fiddaman for (name, prop) in sorted(zfs.dataset.proptable.items()): 26914843421SMatthew Ahrens if prop.visible and prop.delegatable(): 27014843421SMatthew Ahrens print(fmt % (name, _("property"), "")) 27114843421SMatthew Ahrens 27214843421SMatthew Ahrensdef do_allow(): 273842727c2SChris Kirby """Implements the "zfs allow" and "zfs unallow" subcommands.""" 27414843421SMatthew Ahrens un = (sys.argv[1] == "unallow") 27514843421SMatthew Ahrens 27614843421SMatthew Ahrens def usage(msg=None): 27714843421SMatthew Ahrens parser.print_help() 27814843421SMatthew Ahrens print_perms() 27914843421SMatthew Ahrens if msg: 28014843421SMatthew Ahrens print 28114843421SMatthew Ahrens parser.exit("zfs: error: " + msg) 28214843421SMatthew Ahrens else: 28314843421SMatthew Ahrens parser.exit() 28414843421SMatthew Ahrens 28514843421SMatthew Ahrens if un: 28614843421SMatthew Ahrens u = _("""unallow [-rldug] <"everyone"|user|group>[,...] 28714843421SMatthew Ahrens [<perm|@setname>[,...]] <filesystem|volume> 28814843421SMatthew Ahrens unallow [-rld] -e [<perm|@setname>[,...]] <filesystem|volume> 28914843421SMatthew Ahrens unallow [-r] -c [<perm|@setname>[,...]] <filesystem|volume> 29014843421SMatthew Ahrens unallow [-r] -s @setname [<perm|@setname>[,...]] <filesystem|volume>""") 29114843421SMatthew Ahrens verb = _("remove") 29214843421SMatthew Ahrens sstr = _("undefine permission set") 29314843421SMatthew Ahrens else: 29414843421SMatthew Ahrens u = _("""allow <filesystem|volume> 29514843421SMatthew Ahrens allow [-ldug] <"everyone"|user|group>[,...] <perm|@setname>[,...] 29614843421SMatthew Ahrens <filesystem|volume> 29714843421SMatthew Ahrens allow [-ld] -e <perm|@setname>[,...] <filesystem|volume> 29814843421SMatthew Ahrens allow -c <perm|@setname>[,...] <filesystem|volume> 29914843421SMatthew Ahrens allow -s @setname <perm|@setname>[,...] <filesystem|volume>""") 30014843421SMatthew Ahrens verb = _("set") 30114843421SMatthew Ahrens sstr = _("define permission set") 30214843421SMatthew Ahrens 30314843421SMatthew Ahrens parser = optparse.OptionParser(usage=u, prog="zfs") 30414843421SMatthew Ahrens 30514843421SMatthew Ahrens parser.add_option("-l", action="store_true", dest="local", 30614843421SMatthew Ahrens help=_("%s permission locally") % verb) 30714843421SMatthew Ahrens parser.add_option("-d", action="store_true", dest="descend", 30814843421SMatthew Ahrens help=_("%s permission for descendents") % verb) 30914843421SMatthew Ahrens parser.add_option("-u", action="store_true", dest="user", 31014843421SMatthew Ahrens help=_("%s permission for user") % verb) 31114843421SMatthew Ahrens parser.add_option("-g", action="store_true", dest="group", 31214843421SMatthew Ahrens help=_("%s permission for group") % verb) 31314843421SMatthew Ahrens parser.add_option("-e", action="store_true", dest="everyone", 31414843421SMatthew Ahrens help=_("%s permission for everyone") % verb) 31514843421SMatthew Ahrens parser.add_option("-c", action="store_true", dest="create", 31614843421SMatthew Ahrens help=_("%s create time permissions") % verb) 31714843421SMatthew Ahrens parser.add_option("-s", action="store_true", dest="set", help=sstr) 31814843421SMatthew Ahrens if un: 31914843421SMatthew Ahrens parser.add_option("-r", action="store_true", dest="recursive", 32014843421SMatthew Ahrens help=_("remove permissions recursively")) 32114843421SMatthew Ahrens 32214843421SMatthew Ahrens if len(sys.argv) == 3 and not un: 32314843421SMatthew Ahrens # just print the permissions on this fs 32414843421SMatthew Ahrens 32514843421SMatthew Ahrens if sys.argv[2] == "-h": 32614843421SMatthew Ahrens # hack to make "zfs allow -h" work 32714843421SMatthew Ahrens usage() 3289d48f5d3SWilliam Gorrell ds = zfs.dataset.Dataset(sys.argv[2], snaps=False) 32914843421SMatthew Ahrens 33014843421SMatthew Ahrens p = dict() 33114843421SMatthew Ahrens for (fs, raw) in ds.get_fsacl().items(): 33214843421SMatthew Ahrens p[fs] = FSPerms(raw) 33314843421SMatthew Ahrens 33414843421SMatthew Ahrens for fs in sorted(p.keys(), reverse=True): 33514843421SMatthew Ahrens s = _("---- Permissions on %s ") % fs 33614843421SMatthew Ahrens print(s + "-" * (70-len(s))) 33714843421SMatthew Ahrens print(p[fs]) 33814843421SMatthew Ahrens return 33914843421SMatthew Ahrens 34014843421SMatthew Ahrens (options, args) = parser.parse_args(sys.argv[2:]) 34114843421SMatthew Ahrens 34214843421SMatthew Ahrens if sum((bool(options.everyone), bool(options.user), 34314843421SMatthew Ahrens bool(options.group))) > 1: 34414843421SMatthew Ahrens parser.error(_("-u, -g, and -e are mutually exclusive")) 34514843421SMatthew Ahrens 34614843421SMatthew Ahrens def mungeargs(expected_len): 34714843421SMatthew Ahrens if un and len(args) == expected_len-1: 34814843421SMatthew Ahrens return (None, args[expected_len-2]) 34914843421SMatthew Ahrens elif len(args) == expected_len: 35014843421SMatthew Ahrens return (args[expected_len-2].split(","), 35114843421SMatthew Ahrens args[expected_len-1]) 35214843421SMatthew Ahrens else: 35314843421SMatthew Ahrens usage(_("wrong number of parameters")) 35414843421SMatthew Ahrens 35514843421SMatthew Ahrens if options.set: 35614843421SMatthew Ahrens if options.local or options.descend or options.user or \ 35714843421SMatthew Ahrens options.group or options.everyone or options.create: 35814843421SMatthew Ahrens parser.error(_("invalid option combined with -s")) 35914843421SMatthew Ahrens if args[0][0] != "@": 36014843421SMatthew Ahrens parser.error(_("invalid set name: missing '@' prefix")) 36114843421SMatthew Ahrens 36214843421SMatthew Ahrens (perms, fsname) = mungeargs(3) 36314843421SMatthew Ahrens who = args[0] 36414843421SMatthew Ahrens elif options.create: 36514843421SMatthew Ahrens if options.local or options.descend or options.user or \ 36614843421SMatthew Ahrens options.group or options.everyone or options.set: 36714843421SMatthew Ahrens parser.error(_("invalid option combined with -c")) 36814843421SMatthew Ahrens 36914843421SMatthew Ahrens (perms, fsname) = mungeargs(2) 37014843421SMatthew Ahrens who = None 37114843421SMatthew Ahrens elif options.everyone: 37214843421SMatthew Ahrens if options.user or options.group or \ 37314843421SMatthew Ahrens options.create or options.set: 37414843421SMatthew Ahrens parser.error(_("invalid option combined with -e")) 37514843421SMatthew Ahrens 37614843421SMatthew Ahrens (perms, fsname) = mungeargs(2) 37714843421SMatthew Ahrens who = ["everyone"] 37814843421SMatthew Ahrens else: 37914843421SMatthew Ahrens (perms, fsname) = mungeargs(3) 38014843421SMatthew Ahrens who = args[0].split(",") 38114843421SMatthew Ahrens 38214843421SMatthew Ahrens if not options.local and not options.descend: 38314843421SMatthew Ahrens options.local = True 38414843421SMatthew Ahrens options.descend = True 38514843421SMatthew Ahrens 38614843421SMatthew Ahrens d = args_to_perms(parser, options, who, perms) 38714843421SMatthew Ahrens 38814843421SMatthew Ahrens ds = zfs.dataset.Dataset(fsname, snaps=False) 38914843421SMatthew Ahrens 39014843421SMatthew Ahrens if not un and perms: 39114843421SMatthew Ahrens for p in perms: 39214843421SMatthew Ahrens if p[0] == "@" and not hasset(ds, p): 39314843421SMatthew Ahrens parser.error(_("set %s is not defined") % p) 39414843421SMatthew Ahrens 39514843421SMatthew Ahrens ds.set_fsacl(un, d) 39614843421SMatthew Ahrens if un and options.recursive: 39714843421SMatthew Ahrens for child in ds.descendents(): 39814843421SMatthew Ahrens child.set_fsacl(un, d) 399