Exemplo n.º 1
0
 internal Org.Apache.Hadoop.Hdfs.Server.Namenode.INode AddAclFeature(AclFeature aclFeature
                                                                     , int latestSnapshotId)
 {
     RecordModification(latestSnapshotId);
     AddAclFeature(aclFeature);
     return(this);
 }
Exemplo n.º 2
0
            private void LoadRootINode(FsImageProto.INodeSection.INode p)
            {
                INodeDirectory root    = LoadINodeDirectory(p, parent.GetLoaderContext());
                QuotaCounts    q       = root.GetQuotaCounts();
                long           nsQuota = q.GetNameSpace();
                long           dsQuota = q.GetStorageSpace();

                if (nsQuota != -1 || dsQuota != -1)
                {
                    dir.rootDir.GetDirectoryWithQuotaFeature().SetQuota(nsQuota, dsQuota);
                }
                EnumCounters <StorageType> typeQuotas = q.GetTypeSpaces();

                if (typeQuotas.AnyGreaterOrEqual(0))
                {
                    dir.rootDir.GetDirectoryWithQuotaFeature().SetQuota(typeQuotas);
                }
                dir.rootDir.CloneModificationTime(root);
                dir.rootDir.ClonePermissionStatus(root);
                AclFeature af = root.GetFeature(typeof(AclFeature));

                if (af != null)
                {
                    dir.rootDir.AddAclFeature(af);
                }
                // root dir supports having extended attributes according to POSIX
                XAttrFeature f = root.GetXAttrFeature();

                if (f != null)
                {
                    dir.rootDir.AddXAttrFeature(f);
                }
                dir.AddRootDirToEncryptionZone(f);
            }
Exemplo n.º 3
0
            public static FsImageProto.INodeSection.INodeDirectory.Builder BuildINodeDirectory
                (INodeDirectoryAttributes dir, FSImageFormatProtobuf.SaverContext state)
            {
                QuotaCounts quota = dir.GetQuotaCounts();

                FsImageProto.INodeSection.INodeDirectory.Builder b = FsImageProto.INodeSection.INodeDirectory
                                                                     .NewBuilder().SetModificationTime(dir.GetModificationTime()).SetNsQuota(quota.GetNameSpace
                                                                                                                                                 ()).SetDsQuota(quota.GetStorageSpace()).SetPermission(BuildPermissionStatus(dir,
                                                                                                                                                                                                                             state.GetStringMap()));
                if (quota.GetTypeSpaces().AnyGreaterOrEqual(0))
                {
                    b.SetTypeQuotas(BuildQuotaByStorageTypeEntries(quota));
                }
                AclFeature f = dir.GetAclFeature();

                if (f != null)
                {
                    b.SetAcl(BuildAclEntries(f, state.GetStringMap()));
                }
                XAttrFeature xAttrFeature = dir.GetXAttrFeature();

                if (xAttrFeature != null)
                {
                    b.SetXAttrs(BuildXAttrs(xAttrFeature, state.GetStringMap()));
                }
                return(b);
            }
Exemplo n.º 4
0
        /// <exception cref="System.IO.IOException"/>
        private static void UnprotectedRemoveAcl(FSDirectory fsd, INodesInPath iip)
        {
            System.Diagnostics.Debug.Assert(fsd.HasWriteLock());
            INode      inode      = FSDirectory.ResolveLastINode(iip);
            int        snapshotId = iip.GetLatestSnapshotId();
            AclFeature f          = inode.GetAclFeature();

            if (f == null)
            {
                return;
            }
            FsPermission     perm           = inode.GetFsPermission();
            IList <AclEntry> featureEntries = AclStorage.GetEntriesFromAclFeature(f);

            if (featureEntries[0].GetScope() == AclEntryScope.Access)
            {
                // Restore group permissions from the feature's entry to permission
                // bits, overwriting the mask, which is not part of a minimal ACL.
                AclEntry groupEntryKey = new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                             (AclEntryType.Group).Build();
                int groupEntryIndex = Sharpen.Collections.BinarySearch(featureEntries, groupEntryKey
                                                                       , AclTransformation.AclEntryComparator);
                System.Diagnostics.Debug.Assert(groupEntryIndex >= 0);
                FsAction     groupPerm = featureEntries[groupEntryIndex].GetPermission();
                FsPermission newPerm   = new FsPermission(perm.GetUserAction(), groupPerm, perm.GetOtherAction
                                                              (), perm.GetStickyBit());
                inode.SetPermission(newPerm, snapshotId);
            }
            inode.RemoveAclFeature(snapshotId);
        }
 public CopyWithQuota(byte[] name, PermissionStatus permissions, AclFeature aclFeature
                      , long modificationTime, long nsQuota, long dsQuota, EnumCounters <StorageType> typeQuotas
                      , XAttrFeature xAttrsFeature)
     : base(name, permissions, aclFeature, modificationTime, xAttrsFeature)
 {
     this.quota = new QuotaCounts.Builder().NameSpace(nsQuota).StorageSpace(dsQuota).TypeSpaces
                      (typeQuotas).Build();
 }
Exemplo n.º 6
0
        internal override void RemoveAclFeature()
        {
            AclFeature f = GetAclFeature();

            Preconditions.CheckNotNull(f);
            RemoveFeature(f);
            AclStorage.RemoveAclFeature(f);
        }
Exemplo n.º 7
0
 public SnapshotCopy(byte[] name, PermissionStatus permissions, AclFeature aclFeature
                     , long modificationTime, long accessTime, short replication, long preferredBlockSize
                     , byte storagePolicyID, XAttrFeature xAttrsFeature)
     : base(name, permissions, aclFeature, modificationTime, accessTime, xAttrsFeature
            )
 {
     header = INodeFile.HeaderFormat.ToLong(preferredBlockSize, replication, storagePolicyID
                                            );
 }
Exemplo n.º 8
0
        internal override void AddAclFeature(AclFeature f)
        {
            AclFeature f1 = GetAclFeature();

            if (f1 != null)
            {
                throw new InvalidOperationException("Duplicated ACLFeature");
            }
            AddFeature(AclStorage.AddAclFeature(f));
        }
Exemplo n.º 9
0
        /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/>
        private void Check(INodeAttributes inode, string path, FsAction access)
        {
            if (inode == null)
            {
                return;
            }
            FsPermission mode       = inode.GetFsPermission();
            AclFeature   aclFeature = inode.GetAclFeature();

            if (aclFeature != null)
            {
                // It's possible that the inode has a default ACL but no access ACL.
                int firstEntry = aclFeature.GetEntryAt(0);
                if (AclEntryStatusFormat.GetScope(firstEntry) == AclEntryScope.Access)
                {
                    CheckAccessAcl(inode, path, access, mode, aclFeature);
                    return;
                }
            }
            if (GetUser().Equals(inode.GetUserName()))
            {
                //user class
                if (mode.GetUserAction().Implies(access))
                {
                    return;
                }
            }
            else
            {
                if (GetGroups().Contains(inode.GetGroupName()))
                {
                    //group class
                    if (mode.GetGroupAction().Implies(access))
                    {
                        return;
                    }
                }
                else
                {
                    //other class
                    if (mode.GetOtherAction().Implies(access))
                    {
                        return;
                    }
                }
            }
            throw new AccessControlException(ToAccessControlString(inode, path, access, mode)
                                             );
        }
Exemplo n.º 10
0
 internal static ImmutableList <AclEntry> GetEntriesFromAclFeature(AclFeature aclFeature
                                                                   )
 {
     if (aclFeature == null)
     {
         return(ImmutableList.Of <AclEntry>());
     }
     ImmutableList.Builder <AclEntry> b = new ImmutableList.Builder <AclEntry>();
     for (int pos = 0; pos < aclFeature.GetEntriesSize(); pos++)
     {
         entry = aclFeature.GetEntryAt(pos);
         b.Add(AclEntryStatusFormat.ToAclEntry(entry));
     }
     return((ImmutableList <AclEntry>)b.Build());
 }
Exemplo n.º 11
0
 internal SnapshotCopy(byte[] name, PermissionStatus permissions, AclFeature aclFeature
                       , long modificationTime, long accessTime, XAttrFeature xAttrFeature)
 {
     this.name       = name;
     this.permission = INodeWithAdditionalFields.PermissionStatusFormat.ToLong(permissions
                                                                               );
     if (aclFeature != null)
     {
         aclFeature = AclStorage.AddAclFeature(aclFeature);
     }
     this.aclFeature       = aclFeature;
     this.modificationTime = modificationTime;
     this.accessTime       = accessTime;
     this.xAttrFeature     = xAttrFeature;
 }
Exemplo n.º 12
0
 internal SnapshotCopy(INode inode)
 {
     this.name       = inode.GetLocalNameBytes();
     this.permission = inode.GetPermissionLong();
     if (inode.GetAclFeature() != null)
     {
         aclFeature = AclStorage.AddAclFeature(inode.GetAclFeature());
     }
     else
     {
         aclFeature = null;
     }
     this.modificationTime = inode.GetModificationTime();
     this.accessTime       = inode.GetAccessTime();
     this.xAttrFeature     = inode.GetXAttrFeature();
 }
Exemplo n.º 13
0
 private static FsImageProto.INodeSection.AclFeatureProto.Builder BuildAclEntries(
     AclFeature f, FSImageFormatProtobuf.SaverContext.DeduplicationMap <string> map)
 {
     FsImageProto.INodeSection.AclFeatureProto.Builder b = FsImageProto.INodeSection.AclFeatureProto
                                                           .NewBuilder();
     for (int pos = 0; pos < f.GetEntriesSize(); pos++)
     {
         e = f.GetEntryAt(pos);
         int nameId = map.GetId(AclEntryStatusFormat.GetName(e));
         int v      = ((nameId & AclEntryNameMask) << AclEntryNameOffset) | ((int)(AclEntryStatusFormat
                                                                                   .GetType(e)) << AclEntryTypeOffset) | ((int)(AclEntryStatusFormat.GetScope(e)) <<
                                                                                                                     AclEntryScopeOffset) | ((int)(AclEntryStatusFormat.GetPermission(e)));
         b.AddEntries(v);
     }
     return(b);
 }
Exemplo n.º 14
0
                public override AclFeature GetAclFeature()
                {
                    AclFeature f;

                    if (useDefault)
                    {
                        f = inode.GetAclFeature();
                    }
                    else
                    {
                        AclEntry acl = new AclEntry.Builder().SetType(AclEntryType.Group).SetPermission(FsAction
                                                                                                        .All).SetName("xxx").Build();
                        f = new AclFeature(AclEntryStatusFormat.ToInt(Lists.NewArrayList(acl)));
                    }
                    return(f);
                }
Exemplo n.º 15
0
        /// <summary>Reads the existing ACL of an inode.</summary>
        /// <remarks>
        /// Reads the existing ACL of an inode.  This method always returns the full
        /// logical ACL of the inode after reading relevant data from the inode's
        /// <see cref="Org.Apache.Hadoop.FS.Permission.FsPermission"/>
        /// and
        /// <see cref="AclFeature"/>
        /// .  Note that every inode
        /// logically has an ACL, even if no ACL has been set explicitly.  If the inode
        /// does not have an extended ACL, then the result is a minimal ACL consising of
        /// exactly 3 entries that correspond to the owner, group and other permissions.
        /// This method always reads the inode's current state and does not support
        /// querying by snapshot ID.  This is because the method is intended to support
        /// ACL modification APIs, which always apply a delta on top of current state.
        /// </remarks>
        /// <param name="inode">INode to read</param>
        /// <returns>List<AclEntry> containing all logical inode ACL entries</returns>
        public static IList <AclEntry> ReadINodeLogicalAcl(INode inode)
        {
            FsPermission perm = inode.GetFsPermission();
            AclFeature   f    = inode.GetAclFeature();

            if (f == null)
            {
                return(AclUtil.GetMinimalAcl(perm));
            }
            IList <AclEntry> existingAcl;
            // Split ACL entries stored in the feature into access vs. default.
            IList <AclEntry> featureEntries = GetEntriesFromAclFeature(f);
            ScopedAclEntries scoped         = new ScopedAclEntries(featureEntries);
            IList <AclEntry> accessEntries  = scoped.GetAccessEntries();
            IList <AclEntry> defaultEntries = scoped.GetDefaultEntries();

            // Pre-allocate list size for the explicit entries stored in the feature
            // plus the 3 implicit entries (owner, group and other) from the permission
            // bits.
            existingAcl = Lists.NewArrayListWithCapacity(featureEntries.Count + 3);
            if (!accessEntries.IsEmpty())
            {
                // Add owner entry implied from user permission bits.
                existingAcl.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                        (AclEntryType.User).SetPermission(perm.GetUserAction()).Build());
                // Next add all named user and group entries taken from the feature.
                Sharpen.Collections.AddAll(existingAcl, accessEntries);
                // Add mask entry implied from group permission bits.
                existingAcl.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                        (AclEntryType.Mask).SetPermission(perm.GetGroupAction()).Build());
                // Add other entry implied from other permission bits.
                existingAcl.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                        (AclEntryType.Other).SetPermission(perm.GetOtherAction()).Build());
            }
            else
            {
                // It's possible that there is a default ACL but no access ACL. In this
                // case, add the minimal access ACL implied by the permission bits.
                Sharpen.Collections.AddAll(existingAcl, AclUtil.GetMinimalAcl(perm));
            }
            // Add all default entries after the access entries.
            Sharpen.Collections.AddAll(existingAcl, defaultEntries);
            // The above adds entries in the correct order, so no need to sort here.
            return(existingAcl);
        }
Exemplo n.º 16
0
        /// <summary>Copy constructor</summary>
        /// <param name="other">The INodeDirectory to be copied</param>
        /// <param name="adopt">
        /// Indicate whether or not need to set the parent field of child
        /// INodes to the new node
        /// </param>
        /// <param name="featuresToCopy">
        /// any number of features to copy to the new node.
        /// The method will do a reference copy, not a deep copy.
        /// </param>
        public INodeDirectory(Org.Apache.Hadoop.Hdfs.Server.Namenode.INodeDirectory other
                              , bool adopt, params INode.Feature[] featuresToCopy)
            : base(other)
        {
            this.children = other.children;
            if (adopt && this.children != null)
            {
                foreach (INode child in children)
                {
                    child.SetParent(this);
                }
            }
            this.features = featuresToCopy;
            AclFeature aclFeature = GetFeature(typeof(AclFeature));

            if (aclFeature != null)
            {
                // for the de-duplication of AclFeature
                RemoveFeature(aclFeature);
                AddFeature(AclStorage.AddAclFeature(aclFeature));
            }
        }
Exemplo n.º 17
0
            public static FsImageProto.INodeSection.INodeFile.Builder BuildINodeFile(INodeFileAttributes
                                                                                     file, FSImageFormatProtobuf.SaverContext state)
            {
                FsImageProto.INodeSection.INodeFile.Builder b = FsImageProto.INodeSection.INodeFile
                                                                .NewBuilder().SetAccessTime(file.GetAccessTime()).SetModificationTime(file.GetModificationTime
                                                                                                                                          ()).SetPermission(BuildPermissionStatus(file, state.GetStringMap())).SetPreferredBlockSize
                                                                    (file.GetPreferredBlockSize()).SetReplication(file.GetFileReplication()).SetStoragePolicyID
                                                                    (file.GetLocalStoragePolicyID());
                AclFeature f = file.GetAclFeature();

                if (f != null)
                {
                    b.SetAcl(BuildAclEntries(f, state.GetStringMap()));
                }
                XAttrFeature xAttrFeature = file.GetXAttrFeature();

                if (xAttrFeature != null)
                {
                    b.SetXAttrs(BuildXAttrs(xAttrFeature, state.GetStringMap()));
                }
                return(b);
            }
Exemplo n.º 18
0
 /// <summary>Remove reference to the AclFeature</summary>
 /// <param name="aclFeature"/>
 public static void RemoveAclFeature(AclFeature aclFeature)
 {
     UniqueAclFeatures.Remove(aclFeature);
 }
Exemplo n.º 19
0
        /// <summary>Checks requested access against an Access Control List.</summary>
        /// <remarks>
        /// Checks requested access against an Access Control List.  This method relies
        /// on finding the ACL data in the relevant portions of
        /// <see cref="Org.Apache.Hadoop.FS.Permission.FsPermission"/>
        /// and
        /// <see cref="AclFeature"/>
        /// as implemented in the logic of
        /// <see cref="AclStorage"/>
        /// .  This
        /// method also relies on receiving the ACL entries in sorted order.  This is
        /// assumed to be true, because the ACL modification methods in
        /// <see cref="AclTransformation"/>
        /// sort the resulting entries.
        /// More specifically, this method depends on these invariants in an ACL:
        /// - The list must be sorted.
        /// - Each entry in the list must be unique by scope + type + name.
        /// - There is exactly one each of the unnamed user/group/other entries.
        /// - The mask entry must not have a name.
        /// - The other entry must not have a name.
        /// - Default entries may be present, but they are ignored during enforcement.
        /// </remarks>
        /// <param name="inode">INodeAttributes accessed inode</param>
        /// <param name="snapshotId">int snapshot ID</param>
        /// <param name="access">FsAction requested permission</param>
        /// <param name="mode">FsPermission mode from inode</param>
        /// <param name="aclFeature">AclFeature of inode</param>
        /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException">if the ACL denies permission
        ///     </exception>
        private void CheckAccessAcl(INodeAttributes inode, string path, FsAction access,
                                    FsPermission mode, AclFeature aclFeature)
        {
            bool foundMatch = false;

            // Use owner entry from permission bits if user is owner.
            if (GetUser().Equals(inode.GetUserName()))
            {
                if (mode.GetUserAction().Implies(access))
                {
                    return;
                }
                foundMatch = true;
            }
            // Check named user and group entries if user was not denied by owner entry.
            if (!foundMatch)
            {
                for (int pos = 0; pos < aclFeature.GetEntriesSize(); pos++)
                {
                    entry = aclFeature.GetEntryAt(pos);
                    if (AclEntryStatusFormat.GetScope(entry) == AclEntryScope.Default)
                    {
                        break;
                    }
                    AclEntryType type = AclEntryStatusFormat.GetType(entry);
                    string       name = AclEntryStatusFormat.GetName(entry);
                    if (type == AclEntryType.User)
                    {
                        // Use named user entry with mask from permission bits applied if user
                        // matches name.
                        if (GetUser().Equals(name))
                        {
                            FsAction masked = AclEntryStatusFormat.GetPermission(entry).And(mode.GetGroupAction
                                                                                                ());
                            if (masked.Implies(access))
                            {
                                return;
                            }
                            foundMatch = true;
                            break;
                        }
                    }
                    else
                    {
                        if (type == AclEntryType.Group)
                        {
                            // Use group entry (unnamed or named) with mask from permission bits
                            // applied if user is a member and entry grants access.  If user is a
                            // member of multiple groups that have entries that grant access, then
                            // it doesn't matter which is chosen, so exit early after first match.
                            string group = name == null?inode.GetGroupName() : name;

                            if (GetGroups().Contains(group))
                            {
                                FsAction masked = AclEntryStatusFormat.GetPermission(entry).And(mode.GetGroupAction
                                                                                                    ());
                                if (masked.Implies(access))
                                {
                                    return;
                                }
                                foundMatch = true;
                            }
                        }
                    }
                }
            }
            // Use other entry if user was not denied by an earlier match.
            if (!foundMatch && mode.GetOtherAction().Implies(access))
            {
                return;
            }
            throw new AccessControlException(ToAccessControlString(inode, path, access, mode)
                                             );
        }
Exemplo n.º 20
0
 internal abstract void AddAclFeature(AclFeature aclFeature);
Exemplo n.º 21
0
 internal sealed override void AddAclFeature(AclFeature aclFeature)
 {
     referred.AddAclFeature(aclFeature);
 }
Exemplo n.º 22
0
 public SnapshotCopy(byte[] name, PermissionStatus permissions, AclFeature aclFeature
                     , long modificationTime, XAttrFeature xAttrsFeature)
     : base(name, permissions, aclFeature, modificationTime, 0L, xAttrsFeature)
 {
 }
Exemplo n.º 23
0
        /// <summary>Reads the existing extended ACL entries of an inode.</summary>
        /// <remarks>
        /// Reads the existing extended ACL entries of an inode.  This method returns
        /// only the extended ACL entries stored in the AclFeature.  If the inode does
        /// not have an ACL, then this method returns an empty list.  This method
        /// supports querying by snapshot ID.
        /// </remarks>
        /// <param name="inode">INode to read</param>
        /// <param name="snapshotId">int ID of snapshot to read</param>
        /// <returns>List<AclEntry> containing extended inode ACL entries</returns>
        public static IList <AclEntry> ReadINodeAcl(INode inode, int snapshotId)
        {
            AclFeature f = inode.GetAclFeature(snapshotId);

            return(GetEntriesFromAclFeature(f));
        }
Exemplo n.º 24
0
        /// <summary>Reads the existing extended ACL entries of an INodeAttribute object.</summary>
        /// <param name="inodeAttr">INode to read</param>
        /// <returns>List<AclEntry> containing extended inode ACL entries</returns>
        public static IList <AclEntry> ReadINodeAcl(INodeAttributes inodeAttr)
        {
            AclFeature f = inodeAttr.GetAclFeature();

            return(GetEntriesFromAclFeature(f));
        }
Exemplo n.º 25
0
 /// <summary>Add reference for the said AclFeature</summary>
 /// <param name="aclFeature"/>
 /// <returns>Referenced AclFeature</returns>
 public static AclFeature AddAclFeature(AclFeature aclFeature)
 {
     return(UniqueAclFeatures.Put(aclFeature));
 }
Exemplo n.º 26
0
 internal override void AddAclFeature(AclFeature f)
 {
     throw new NotSupportedException("ACLs are not supported on symlinks");
 }
Exemplo n.º 27
0
        /// <summary>
        /// If a default ACL is defined on a parent directory, then copies that default
        /// ACL to a newly created child file or directory.
        /// </summary>
        /// <param name="child">INode newly created child</param>
        public static void CopyINodeDefaultAcl(INode child)
        {
            INodeDirectory parent           = child.GetParent();
            AclFeature     parentAclFeature = parent.GetAclFeature();

            if (parentAclFeature == null || !(child.IsFile() || child.IsDirectory()))
            {
                return;
            }
            // Split parent's entries into access vs. default.
            IList <AclEntry> featureEntries       = GetEntriesFromAclFeature(parent.GetAclFeature());
            ScopedAclEntries scopedEntries        = new ScopedAclEntries(featureEntries);
            IList <AclEntry> parentDefaultEntries = scopedEntries.GetDefaultEntries();

            // The parent may have an access ACL but no default ACL.  If so, exit.
            if (parentDefaultEntries.IsEmpty())
            {
                return;
            }
            // Pre-allocate list size for access entries to copy from parent.
            IList <AclEntry> accessEntries = Lists.NewArrayListWithCapacity(parentDefaultEntries
                                                                            .Count);
            FsPermission childPerm = child.GetFsPermission();
            // Copy each default ACL entry from parent to new child's access ACL.
            bool parentDefaultIsMinimal = AclUtil.IsMinimalAcl(parentDefaultEntries);

            foreach (AclEntry entry in parentDefaultEntries)
            {
                AclEntryType     type    = entry.GetType();
                string           name    = entry.GetName();
                AclEntry.Builder builder = new AclEntry.Builder().SetScope(AclEntryScope.Access).
                                           SetType(type).SetName(name);
                // The child's initial permission bits are treated as the mode parameter,
                // which can filter copied permission values for owner, mask and other.
                FsAction permission;
                if (type == AclEntryType.User && name == null)
                {
                    permission = entry.GetPermission().And(childPerm.GetUserAction());
                }
                else
                {
                    if (type == AclEntryType.Group && parentDefaultIsMinimal)
                    {
                        // This only happens if the default ACL is a minimal ACL: exactly 3
                        // entries corresponding to owner, group and other.  In this case,
                        // filter the group permissions.
                        permission = entry.GetPermission().And(childPerm.GetGroupAction());
                    }
                    else
                    {
                        if (type == AclEntryType.Mask)
                        {
                            // Group bits from mode parameter filter permission of mask entry.
                            permission = entry.GetPermission().And(childPerm.GetGroupAction());
                        }
                        else
                        {
                            if (type == AclEntryType.Other)
                            {
                                permission = entry.GetPermission().And(childPerm.GetOtherAction());
                            }
                            else
                            {
                                permission = entry.GetPermission();
                            }
                        }
                    }
                }
                builder.SetPermission(permission);
                accessEntries.AddItem(builder.Build());
            }
            // A new directory also receives a copy of the parent's default ACL.
            IList <AclEntry> defaultEntries = child.IsDirectory() ? parentDefaultEntries : Sharpen.Collections
                                              .EmptyList <AclEntry>();
            FsPermission newPerm;

            if (!AclUtil.IsMinimalAcl(accessEntries) || !defaultEntries.IsEmpty())
            {
                // Save the new ACL to the child.
                child.AddAclFeature(CreateAclFeature(accessEntries, defaultEntries));
                newPerm = CreateFsPermissionForExtendedAcl(accessEntries, childPerm);
            }
            else
            {
                // The child is receiving a minimal ACL.
                newPerm = CreateFsPermissionForMinimalAcl(accessEntries, childPerm);
            }
            child.SetPermission(newPerm);
        }