1*14843421SMatthew Ahrens#! /usr/bin/python2.4 2*14843421SMatthew Ahrens# 3*14843421SMatthew Ahrens# CDDL HEADER START 4*14843421SMatthew Ahrens# 5*14843421SMatthew Ahrens# The contents of this file are subject to the terms of the 6*14843421SMatthew Ahrens# Common Development and Distribution License (the "License"). 7*14843421SMatthew Ahrens# You may not use this file except in compliance with the License. 8*14843421SMatthew Ahrens# 9*14843421SMatthew Ahrens# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*14843421SMatthew Ahrens# or http://www.opensolaris.org/os/licensing. 11*14843421SMatthew Ahrens# See the License for the specific language governing permissions 12*14843421SMatthew Ahrens# and limitations under the License. 13*14843421SMatthew Ahrens# 14*14843421SMatthew Ahrens# When distributing Covered Code, include this CDDL HEADER in each 15*14843421SMatthew Ahrens# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*14843421SMatthew Ahrens# If applicable, add the following below this CDDL HEADER, with the 17*14843421SMatthew Ahrens# fields enclosed by brackets "[]" replaced with your own identifying 18*14843421SMatthew Ahrens# information: Portions Copyright [yyyy] [name of copyright owner] 19*14843421SMatthew Ahrens# 20*14843421SMatthew Ahrens# CDDL HEADER END 21*14843421SMatthew Ahrens# 22*14843421SMatthew Ahrens# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*14843421SMatthew Ahrens# Use is subject to license terms. 24*14843421SMatthew Ahrens# 25*14843421SMatthew Ahrens 26*14843421SMatthew Ahrens"""This module implements the "zfs allow" and "zfs unallow" subcommands. 27*14843421SMatthew AhrensThe only public interface is the zfs.allow.do_allow() function.""" 28*14843421SMatthew Ahrens 29*14843421SMatthew Ahrensimport zfs.util 30*14843421SMatthew Ahrensimport zfs.dataset 31*14843421SMatthew Ahrensimport optparse 32*14843421SMatthew Ahrensimport sys 33*14843421SMatthew Ahrensimport pwd 34*14843421SMatthew Ahrensimport grp 35*14843421SMatthew Ahrensimport errno 36*14843421SMatthew Ahrens 37*14843421SMatthew Ahrens_ = zfs.util._ 38*14843421SMatthew Ahrens 39*14843421SMatthew Ahrensclass FSPerms(object): 40*14843421SMatthew Ahrens """This class represents all the permissions that are set on a 41*14843421SMatthew Ahrens particular filesystem (not including those inherited).""" 42*14843421SMatthew Ahrens 43*14843421SMatthew Ahrens __slots__ = "create", "sets", "local", "descend", "ld" 44*14843421SMatthew Ahrens __repr__ = zfs.util.default_repr 45*14843421SMatthew Ahrens 46*14843421SMatthew Ahrens def __init__(self, raw): 47*14843421SMatthew Ahrens """Create a FSPerms based on the dict of raw permissions 48*14843421SMatthew Ahrens from zfs.ioctl.get_fsacl().""" 49*14843421SMatthew Ahrens # set of perms 50*14843421SMatthew Ahrens self.create = set() 51*14843421SMatthew Ahrens 52*14843421SMatthew Ahrens # below are { "Ntype name": set(perms) } 53*14843421SMatthew Ahrens # where N is a number that we just use for sorting, 54*14843421SMatthew Ahrens # type is "user", "group", "everyone", or "" (for sets) 55*14843421SMatthew Ahrens # name is a user, group, or set name, or "" (for everyone) 56*14843421SMatthew Ahrens self.sets = dict() 57*14843421SMatthew Ahrens self.local = dict() 58*14843421SMatthew Ahrens self.descend = dict() 59*14843421SMatthew Ahrens self.ld = dict() 60*14843421SMatthew Ahrens 61*14843421SMatthew Ahrens # see the comment in dsl_deleg.c for the definition of whokey 62*14843421SMatthew Ahrens for whokey in raw.keys(): 63*14843421SMatthew Ahrens perms = raw[whokey].keys() 64*14843421SMatthew Ahrens whotypechr = whokey[0].lower() 65*14843421SMatthew Ahrens ws = whokey[3:] 66*14843421SMatthew Ahrens if whotypechr == "c": 67*14843421SMatthew Ahrens self.create.update(perms) 68*14843421SMatthew Ahrens elif whotypechr == "s": 69*14843421SMatthew Ahrens nwho = "1" + ws 70*14843421SMatthew Ahrens self.sets.setdefault(nwho, set()).update(perms) 71*14843421SMatthew Ahrens else: 72*14843421SMatthew Ahrens if whotypechr == "u": 73*14843421SMatthew Ahrens try: 74*14843421SMatthew Ahrens name = pwd.getpwuid(int(ws)).pw_name 75*14843421SMatthew Ahrens except KeyError: 76*14843421SMatthew Ahrens name = ws 77*14843421SMatthew Ahrens nwho = "1user " + name 78*14843421SMatthew Ahrens elif whotypechr == "g": 79*14843421SMatthew Ahrens try: 80*14843421SMatthew Ahrens name = grp.getgrgid(int(ws)).gr_name 81*14843421SMatthew Ahrens except KeyError: 82*14843421SMatthew Ahrens name = ws 83*14843421SMatthew Ahrens nwho = "2group " + name 84*14843421SMatthew Ahrens elif whotypechr == "e": 85*14843421SMatthew Ahrens nwho = "3everyone" 86*14843421SMatthew Ahrens else: 87*14843421SMatthew Ahrens raise ValueError(whotypechr) 88*14843421SMatthew Ahrens 89*14843421SMatthew Ahrens if whokey[1] == "l": 90*14843421SMatthew Ahrens d = self.local 91*14843421SMatthew Ahrens elif whokey[1] == "d": 92*14843421SMatthew Ahrens d = self.descend 93*14843421SMatthew Ahrens else: 94*14843421SMatthew Ahrens raise ValueError(whokey[1]) 95*14843421SMatthew Ahrens 96*14843421SMatthew Ahrens d.setdefault(nwho, set()).update(perms) 97*14843421SMatthew Ahrens 98*14843421SMatthew Ahrens # Find perms that are in both local and descend, and 99*14843421SMatthew Ahrens # move them to ld. 100*14843421SMatthew Ahrens for nwho in self.local: 101*14843421SMatthew Ahrens if nwho not in self.descend: 102*14843421SMatthew Ahrens continue 103*14843421SMatthew Ahrens # note: these are set operations 104*14843421SMatthew Ahrens self.ld[nwho] = self.local[nwho] & self.descend[nwho] 105*14843421SMatthew Ahrens self.local[nwho] -= self.ld[nwho] 106*14843421SMatthew Ahrens self.descend[nwho] -= self.ld[nwho] 107*14843421SMatthew Ahrens 108*14843421SMatthew Ahrens @staticmethod 109*14843421SMatthew Ahrens def __ldstr(d, header): 110*14843421SMatthew Ahrens s = "" 111*14843421SMatthew Ahrens for (nwho, perms) in sorted(d.items()): 112*14843421SMatthew Ahrens # local and descend may have entries where perms 113*14843421SMatthew Ahrens # is an empty set, due to consolidating all 114*14843421SMatthew Ahrens # permissions into ld 115*14843421SMatthew Ahrens if perms: 116*14843421SMatthew Ahrens s += "\t%s %s\n" % \ 117*14843421SMatthew Ahrens (nwho[1:], ",".join(sorted(perms))) 118*14843421SMatthew Ahrens if s: 119*14843421SMatthew Ahrens s = header + s 120*14843421SMatthew Ahrens return s 121*14843421SMatthew Ahrens 122*14843421SMatthew Ahrens def __str__(self): 123*14843421SMatthew Ahrens s = self.__ldstr(self.sets, _("Permission sets:\n")) 124*14843421SMatthew Ahrens 125*14843421SMatthew Ahrens if self.create: 126*14843421SMatthew Ahrens s += _("Create time permissions:\n") 127*14843421SMatthew Ahrens s += "\t%s\n" % ",".join(sorted(self.create)) 128*14843421SMatthew Ahrens 129*14843421SMatthew Ahrens s += self.__ldstr(self.local, _("Local permissions:\n")) 130*14843421SMatthew Ahrens s += self.__ldstr(self.descend, _("Descendent permissions:\n")) 131*14843421SMatthew Ahrens s += self.__ldstr(self.ld, _("Local+Descendent permissions:\n")) 132*14843421SMatthew Ahrens return s.rstrip() 133*14843421SMatthew Ahrens 134*14843421SMatthew Ahrensdef args_to_perms(parser, options, who, perms): 135*14843421SMatthew Ahrens """Return a dict of raw perms {"whostr" -> {"perm" -> None}} 136*14843421SMatthew Ahrens based on the command-line input.""" 137*14843421SMatthew Ahrens 138*14843421SMatthew Ahrens # perms is not set if we are doing a "zfs unallow <who> <fs>" to 139*14843421SMatthew Ahrens # remove all of someone's permissions 140*14843421SMatthew Ahrens if perms: 141*14843421SMatthew Ahrens setperms = dict(((p, None) for p in perms if p[0] == "@")) 142*14843421SMatthew Ahrens baseperms = dict(((canonicalized_perm(p), None) 143*14843421SMatthew Ahrens for p in perms if p[0] != "@")) 144*14843421SMatthew Ahrens else: 145*14843421SMatthew Ahrens setperms = None 146*14843421SMatthew Ahrens baseperms = None 147*14843421SMatthew Ahrens 148*14843421SMatthew Ahrens d = dict() 149*14843421SMatthew Ahrens 150*14843421SMatthew Ahrens def storeperm(typechr, inheritchr, arg): 151*14843421SMatthew Ahrens assert typechr in "ugecs" 152*14843421SMatthew Ahrens assert inheritchr in "ld-" 153*14843421SMatthew Ahrens 154*14843421SMatthew Ahrens def mkwhokey(t): 155*14843421SMatthew Ahrens return "%c%c$%s" % (t, inheritchr, arg) 156*14843421SMatthew Ahrens 157*14843421SMatthew Ahrens if baseperms or not perms: 158*14843421SMatthew Ahrens d[mkwhokey(typechr)] = baseperms 159*14843421SMatthew Ahrens if setperms or not perms: 160*14843421SMatthew Ahrens d[mkwhokey(typechr.upper())] = setperms 161*14843421SMatthew Ahrens 162*14843421SMatthew Ahrens def decodeid(w, toidfunc, fmt): 163*14843421SMatthew Ahrens try: 164*14843421SMatthew Ahrens return int(w) 165*14843421SMatthew Ahrens except ValueError: 166*14843421SMatthew Ahrens try: 167*14843421SMatthew Ahrens return toidfunc(w)[2] 168*14843421SMatthew Ahrens except KeyError: 169*14843421SMatthew Ahrens parser.error(fmt % w) 170*14843421SMatthew Ahrens 171*14843421SMatthew Ahrens if options.set: 172*14843421SMatthew Ahrens storeperm("s", "-", who) 173*14843421SMatthew Ahrens elif options.create: 174*14843421SMatthew Ahrens storeperm("c", "-", "") 175*14843421SMatthew Ahrens else: 176*14843421SMatthew Ahrens for w in who: 177*14843421SMatthew Ahrens if options.user: 178*14843421SMatthew Ahrens id = decodeid(w, pwd.getpwnam, 179*14843421SMatthew Ahrens _("invalid user %s")) 180*14843421SMatthew Ahrens typechr = "u" 181*14843421SMatthew Ahrens elif options.group: 182*14843421SMatthew Ahrens id = decodeid(w, grp.getgrnam, 183*14843421SMatthew Ahrens _("invalid group %s")) 184*14843421SMatthew Ahrens typechr = "g" 185*14843421SMatthew Ahrens elif w == "everyone": 186*14843421SMatthew Ahrens id = "" 187*14843421SMatthew Ahrens typechr = "e" 188*14843421SMatthew Ahrens else: 189*14843421SMatthew Ahrens try: 190*14843421SMatthew Ahrens id = pwd.getpwnam(w)[2] 191*14843421SMatthew Ahrens typechr = "u" 192*14843421SMatthew Ahrens except KeyError: 193*14843421SMatthew Ahrens try: 194*14843421SMatthew Ahrens id = grp.getgrnam(w)[2] 195*14843421SMatthew Ahrens typechr = "g" 196*14843421SMatthew Ahrens except KeyError: 197*14843421SMatthew Ahrens parser.error(_("invalid user/group %s") % w) 198*14843421SMatthew Ahrens if options.local: 199*14843421SMatthew Ahrens storeperm(typechr, "l", id) 200*14843421SMatthew Ahrens if options.descend: 201*14843421SMatthew Ahrens storeperm(typechr, "d", id) 202*14843421SMatthew Ahrens return d 203*14843421SMatthew Ahrens 204*14843421SMatthew Ahrensperms_subcmd = dict( 205*14843421SMatthew Ahrens create=_("Must also have the 'mount' ability"), 206*14843421SMatthew Ahrens destroy=_("Must also have the 'mount' ability"), 207*14843421SMatthew Ahrens snapshot=_("Must also have the 'mount' ability"), 208*14843421SMatthew Ahrens rollback=_("Must also have the 'mount' ability"), 209*14843421SMatthew Ahrens clone=_("""Must also have the 'create' ability and 'mount' 210*14843421SMatthew Ahrens\t\t\t\tability in the origin file system"""), 211*14843421SMatthew Ahrens promote=_("""Must also have the 'mount' 212*14843421SMatthew Ahrens\t\t\t\tand 'promote' ability in the origin file system"""), 213*14843421SMatthew Ahrens rename=_("""Must also have the 'mount' and 'create' 214*14843421SMatthew Ahrens\t\t\t\tability in the new parent"""), 215*14843421SMatthew Ahrens receive=_("Must also have the 'mount' and 'create' ability"), 216*14843421SMatthew Ahrens allow=_("Must also have the permission that is being\n\t\t\t\tallowed"), 217*14843421SMatthew Ahrens mount=_("Allows mount/umount of ZFS datasets"), 218*14843421SMatthew Ahrens share=_("Allows sharing file systems over NFS or SMB\n\t\t\t\tprotocols"), 219*14843421SMatthew Ahrens send="", 220*14843421SMatthew Ahrens) 221*14843421SMatthew Ahrens 222*14843421SMatthew Ahrensperms_other = dict( 223*14843421SMatthew Ahrens userprop=_("Allows changing any user property"), 224*14843421SMatthew Ahrens userquota=_("Allows accessing any userquota@... property"), 225*14843421SMatthew Ahrens groupquota=_("Allows accessing any groupquota@... property"), 226*14843421SMatthew Ahrens userused=_("Allows reading any userused@... property"), 227*14843421SMatthew Ahrens groupused=_("Allows reading any groupused@... property"), 228*14843421SMatthew Ahrens) 229*14843421SMatthew Ahrens 230*14843421SMatthew Ahrensdef hasset(ds, setname): 231*14843421SMatthew Ahrens """Return True if the given setname (string) is defined for this 232*14843421SMatthew Ahrens ds (Dataset).""" 233*14843421SMatthew Ahrens # It would be nice to cache the result of get_fsacl(). 234*14843421SMatthew Ahrens for raw in ds.get_fsacl().values(): 235*14843421SMatthew Ahrens for whokey in raw.keys(): 236*14843421SMatthew Ahrens if whokey[0].lower() == "s" and whokey[3:] == setname: 237*14843421SMatthew Ahrens return True 238*14843421SMatthew Ahrens return False 239*14843421SMatthew Ahrens 240*14843421SMatthew Ahrensdef canonicalized_perm(permname): 241*14843421SMatthew Ahrens """Return the canonical name (string) for this permission (string). 242*14843421SMatthew Ahrens Raises ZFSError if it is not a valid permission.""" 243*14843421SMatthew Ahrens if permname in perms_subcmd.keys() or permname in perms_other.keys(): 244*14843421SMatthew Ahrens return permname 245*14843421SMatthew Ahrens try: 246*14843421SMatthew Ahrens return zfs.dataset.getpropobj(permname).name 247*14843421SMatthew Ahrens except KeyError: 248*14843421SMatthew Ahrens raise zfs.util.ZFSError(errno.EINVAL, permname, 249*14843421SMatthew Ahrens _("invalid permission")) 250*14843421SMatthew Ahrens 251*14843421SMatthew Ahrensdef print_perms(): 252*14843421SMatthew Ahrens """Print the set of supported permissions.""" 253*14843421SMatthew Ahrens print(_("\nThe following permissions are supported:\n")) 254*14843421SMatthew Ahrens fmt = "%-16s %-14s\t%s" 255*14843421SMatthew Ahrens print(fmt % (_("NAME"), _("TYPE"), _("NOTES"))) 256*14843421SMatthew Ahrens 257*14843421SMatthew Ahrens for (name, note) in sorted(perms_subcmd.iteritems()): 258*14843421SMatthew Ahrens print(fmt % (name, _("subcommand"), note)) 259*14843421SMatthew Ahrens 260*14843421SMatthew Ahrens for (name, note) in sorted(perms_other.iteritems()): 261*14843421SMatthew Ahrens print(fmt % (name, _("other"), note)) 262*14843421SMatthew Ahrens 263*14843421SMatthew Ahrens for (name, prop) in sorted(zfs.dataset.proptable.iteritems()): 264*14843421SMatthew Ahrens if prop.visible and prop.delegatable(): 265*14843421SMatthew Ahrens print(fmt % (name, _("property"), "")) 266*14843421SMatthew Ahrens 267*14843421SMatthew Ahrensdef do_allow(): 268*14843421SMatthew Ahrens """Implementes the "zfs allow" and "zfs unallow" subcommands.""" 269*14843421SMatthew Ahrens un = (sys.argv[1] == "unallow") 270*14843421SMatthew Ahrens 271*14843421SMatthew Ahrens def usage(msg=None): 272*14843421SMatthew Ahrens parser.print_help() 273*14843421SMatthew Ahrens print_perms() 274*14843421SMatthew Ahrens if msg: 275*14843421SMatthew Ahrens print 276*14843421SMatthew Ahrens parser.exit("zfs: error: " + msg) 277*14843421SMatthew Ahrens else: 278*14843421SMatthew Ahrens parser.exit() 279*14843421SMatthew Ahrens 280*14843421SMatthew Ahrens if un: 281*14843421SMatthew Ahrens u = _("""unallow [-rldug] <"everyone"|user|group>[,...] 282*14843421SMatthew Ahrens [<perm|@setname>[,...]] <filesystem|volume> 283*14843421SMatthew Ahrens unallow [-rld] -e [<perm|@setname>[,...]] <filesystem|volume> 284*14843421SMatthew Ahrens unallow [-r] -c [<perm|@setname>[,...]] <filesystem|volume> 285*14843421SMatthew Ahrens unallow [-r] -s @setname [<perm|@setname>[,...]] <filesystem|volume>""") 286*14843421SMatthew Ahrens verb = _("remove") 287*14843421SMatthew Ahrens sstr = _("undefine permission set") 288*14843421SMatthew Ahrens else: 289*14843421SMatthew Ahrens u = _("""allow <filesystem|volume> 290*14843421SMatthew Ahrens allow [-ldug] <"everyone"|user|group>[,...] <perm|@setname>[,...] 291*14843421SMatthew Ahrens <filesystem|volume> 292*14843421SMatthew Ahrens allow [-ld] -e <perm|@setname>[,...] <filesystem|volume> 293*14843421SMatthew Ahrens allow -c <perm|@setname>[,...] <filesystem|volume> 294*14843421SMatthew Ahrens allow -s @setname <perm|@setname>[,...] <filesystem|volume>""") 295*14843421SMatthew Ahrens verb = _("set") 296*14843421SMatthew Ahrens sstr = _("define permission set") 297*14843421SMatthew Ahrens 298*14843421SMatthew Ahrens parser = optparse.OptionParser(usage=u, prog="zfs") 299*14843421SMatthew Ahrens 300*14843421SMatthew Ahrens parser.add_option("-l", action="store_true", dest="local", 301*14843421SMatthew Ahrens help=_("%s permission locally") % verb) 302*14843421SMatthew Ahrens parser.add_option("-d", action="store_true", dest="descend", 303*14843421SMatthew Ahrens help=_("%s permission for descendents") % verb) 304*14843421SMatthew Ahrens parser.add_option("-u", action="store_true", dest="user", 305*14843421SMatthew Ahrens help=_("%s permission for user") % verb) 306*14843421SMatthew Ahrens parser.add_option("-g", action="store_true", dest="group", 307*14843421SMatthew Ahrens help=_("%s permission for group") % verb) 308*14843421SMatthew Ahrens parser.add_option("-e", action="store_true", dest="everyone", 309*14843421SMatthew Ahrens help=_("%s permission for everyone") % verb) 310*14843421SMatthew Ahrens parser.add_option("-c", action="store_true", dest="create", 311*14843421SMatthew Ahrens help=_("%s create time permissions") % verb) 312*14843421SMatthew Ahrens parser.add_option("-s", action="store_true", dest="set", help=sstr) 313*14843421SMatthew Ahrens if un: 314*14843421SMatthew Ahrens parser.add_option("-r", action="store_true", dest="recursive", 315*14843421SMatthew Ahrens help=_("remove permissions recursively")) 316*14843421SMatthew Ahrens 317*14843421SMatthew Ahrens if len(sys.argv) == 3 and not un: 318*14843421SMatthew Ahrens # just print the permissions on this fs 319*14843421SMatthew Ahrens 320*14843421SMatthew Ahrens if sys.argv[2] == "-h": 321*14843421SMatthew Ahrens # hack to make "zfs allow -h" work 322*14843421SMatthew Ahrens usage() 323*14843421SMatthew Ahrens ds = zfs.dataset.Dataset(sys.argv[2]) 324*14843421SMatthew Ahrens 325*14843421SMatthew Ahrens p = dict() 326*14843421SMatthew Ahrens for (fs, raw) in ds.get_fsacl().items(): 327*14843421SMatthew Ahrens p[fs] = FSPerms(raw) 328*14843421SMatthew Ahrens 329*14843421SMatthew Ahrens for fs in sorted(p.keys(), reverse=True): 330*14843421SMatthew Ahrens s = _("---- Permissions on %s ") % fs 331*14843421SMatthew Ahrens print(s + "-" * (70-len(s))) 332*14843421SMatthew Ahrens print(p[fs]) 333*14843421SMatthew Ahrens return 334*14843421SMatthew Ahrens 335*14843421SMatthew Ahrens 336*14843421SMatthew Ahrens (options, args) = parser.parse_args(sys.argv[2:]) 337*14843421SMatthew Ahrens 338*14843421SMatthew Ahrens if sum((bool(options.everyone), bool(options.user), 339*14843421SMatthew Ahrens bool(options.group))) > 1: 340*14843421SMatthew Ahrens parser.error(_("-u, -g, and -e are mutually exclusive")) 341*14843421SMatthew Ahrens 342*14843421SMatthew Ahrens def mungeargs(expected_len): 343*14843421SMatthew Ahrens if un and len(args) == expected_len-1: 344*14843421SMatthew Ahrens return (None, args[expected_len-2]) 345*14843421SMatthew Ahrens elif len(args) == expected_len: 346*14843421SMatthew Ahrens return (args[expected_len-2].split(","), 347*14843421SMatthew Ahrens args[expected_len-1]) 348*14843421SMatthew Ahrens else: 349*14843421SMatthew Ahrens usage(_("wrong number of parameters")) 350*14843421SMatthew Ahrens 351*14843421SMatthew Ahrens if options.set: 352*14843421SMatthew Ahrens if options.local or options.descend or options.user or \ 353*14843421SMatthew Ahrens options.group or options.everyone or options.create: 354*14843421SMatthew Ahrens parser.error(_("invalid option combined with -s")) 355*14843421SMatthew Ahrens if args[0][0] != "@": 356*14843421SMatthew Ahrens parser.error(_("invalid set name: missing '@' prefix")) 357*14843421SMatthew Ahrens 358*14843421SMatthew Ahrens (perms, fsname) = mungeargs(3) 359*14843421SMatthew Ahrens who = args[0] 360*14843421SMatthew Ahrens elif options.create: 361*14843421SMatthew Ahrens if options.local or options.descend or options.user or \ 362*14843421SMatthew Ahrens options.group or options.everyone or options.set: 363*14843421SMatthew Ahrens parser.error(_("invalid option combined with -c")) 364*14843421SMatthew Ahrens 365*14843421SMatthew Ahrens (perms, fsname) = mungeargs(2) 366*14843421SMatthew Ahrens who = None 367*14843421SMatthew Ahrens elif options.everyone: 368*14843421SMatthew Ahrens if options.user or options.group or \ 369*14843421SMatthew Ahrens options.create or options.set: 370*14843421SMatthew Ahrens parser.error(_("invalid option combined with -e")) 371*14843421SMatthew Ahrens 372*14843421SMatthew Ahrens (perms, fsname) = mungeargs(2) 373*14843421SMatthew Ahrens who = ["everyone"] 374*14843421SMatthew Ahrens else: 375*14843421SMatthew Ahrens (perms, fsname) = mungeargs(3) 376*14843421SMatthew Ahrens who = args[0].split(",") 377*14843421SMatthew Ahrens 378*14843421SMatthew Ahrens if not options.local and not options.descend: 379*14843421SMatthew Ahrens options.local = True 380*14843421SMatthew Ahrens options.descend = True 381*14843421SMatthew Ahrens 382*14843421SMatthew Ahrens d = args_to_perms(parser, options, who, perms) 383*14843421SMatthew Ahrens 384*14843421SMatthew Ahrens ds = zfs.dataset.Dataset(fsname, snaps=False) 385*14843421SMatthew Ahrens 386*14843421SMatthew Ahrens if not un and perms: 387*14843421SMatthew Ahrens for p in perms: 388*14843421SMatthew Ahrens if p[0] == "@" and not hasset(ds, p): 389*14843421SMatthew Ahrens parser.error(_("set %s is not defined") % p) 390*14843421SMatthew Ahrens 391*14843421SMatthew Ahrens ds.set_fsacl(un, d) 392*14843421SMatthew Ahrens if un and options.recursive: 393*14843421SMatthew Ahrens for child in ds.descendents(): 394*14843421SMatthew Ahrens child.set_fsacl(un, d) 395