Esempio n. 1
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);
        }