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