示例#1
0
        /// <summary>
        /// Adds unspecified default entries by copying permissions from the
        /// corresponding access entries.
        /// </summary>
        /// <param name="aclBuilder">ArrayList<AclEntry> containing entries to build</param>
        private static void CopyDefaultsIfNeeded(IList <AclEntry> aclBuilder)
        {
            aclBuilder.Sort(AclEntryComparator);
            ScopedAclEntries scopedEntries = new ScopedAclEntries(aclBuilder);

            if (!scopedEntries.GetDefaultEntries().IsEmpty())
            {
                IList <AclEntry> accessEntries  = scopedEntries.GetAccessEntries();
                IList <AclEntry> defaultEntries = scopedEntries.GetDefaultEntries();
                IList <AclEntry> copiedEntries  = Lists.NewArrayListWithCapacity(3);
                foreach (AclEntryType type in EnumSet.Of(AclEntryType.User, AclEntryType.Group, AclEntryType
                                                         .Other))
                {
                    AclEntry defaultEntryKey = new AclEntry.Builder().SetScope(AclEntryScope.Default)
                                               .SetType(type).Build();
                    int defaultEntryIndex = Sharpen.Collections.BinarySearch(defaultEntries, defaultEntryKey
                                                                             , AclEntryComparator);
                    if (defaultEntryIndex < 0)
                    {
                        AclEntry accessEntryKey = new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                                      (type).Build();
                        int accessEntryIndex = Sharpen.Collections.BinarySearch(accessEntries, accessEntryKey
                                                                                , AclEntryComparator);
                        if (accessEntryIndex >= 0)
                        {
                            copiedEntries.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Default).SetType
                                                      (type).SetPermission(accessEntries[accessEntryIndex].GetPermission()).Build());
                        }
                    }
                }
                // Add all copied entries when done to prevent potential issues with binary
                // search on a modified aclBulider during the main loop.
                Sharpen.Collections.AddAll(aclBuilder, copiedEntries);
            }
        }
示例#2
0
        /// <summary>
        /// Builds the final list of ACL entries to return by trimming, sorting and
        /// validating the ACL entries that have been added.
        /// </summary>
        /// <param name="aclBuilder">ArrayList<AclEntry> containing entries to build</param>
        /// <returns>List<AclEntry> unmodifiable, sorted list of ACL entries</returns>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.AclException">if validation fails
        ///     </exception>
        private static IList <AclEntry> BuildAndValidateAcl(AList <AclEntry> aclBuilder)
        {
            if (aclBuilder.Count > MaxEntries)
            {
                throw new AclException("Invalid ACL: ACL has " + aclBuilder.Count + " entries, which exceeds maximum of "
                                       + MaxEntries + ".");
            }
            aclBuilder.TrimToSize();
            aclBuilder.Sort(AclEntryComparator);
            // Full iteration to check for duplicates and invalid named entries.
            AclEntry prevEntry = null;

            foreach (AclEntry entry in aclBuilder)
            {
                if (prevEntry != null && AclEntryComparator.Compare(prevEntry, entry) == 0)
                {
                    throw new AclException("Invalid ACL: multiple entries with same scope, type and name."
                                           );
                }
                if (entry.GetName() != null && (entry.GetType() == AclEntryType.Mask || entry.GetType
                                                    () == AclEntryType.Other))
                {
                    throw new AclException("Invalid ACL: this entry type must not have a name: " + entry
                                           + ".");
                }
                prevEntry = entry;
            }
            // Search for the required base access entries.  If there is a default ACL,
            // then do the same check on the default entries.
            ScopedAclEntries scopedEntries = new ScopedAclEntries(aclBuilder);

            foreach (AclEntryType type in EnumSet.Of(AclEntryType.User, AclEntryType.Group, AclEntryType
                                                     .Other))
            {
                AclEntry accessEntryKey = new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                              (type).Build();
                if (Sharpen.Collections.BinarySearch(scopedEntries.GetAccessEntries(), accessEntryKey
                                                     , AclEntryComparator) < 0)
                {
                    throw new AclException("Invalid ACL: the user, group and other entries are required."
                                           );
                }
                if (!scopedEntries.GetDefaultEntries().IsEmpty())
                {
                    AclEntry defaultEntryKey = new AclEntry.Builder().SetScope(AclEntryScope.Default)
                                               .SetType(type).Build();
                    if (Sharpen.Collections.BinarySearch(scopedEntries.GetDefaultEntries(), defaultEntryKey
                                                         , AclEntryComparator) < 0)
                    {
                        throw new AclException("Invalid default ACL: the user, group and other entries are required."
                                               );
                    }
                }
            }
            return(Sharpen.Collections.UnmodifiableList(aclBuilder));
        }
示例#3
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);
        }
示例#4
0
            /// <exception cref="System.IO.IOException"/>
            protected internal override void ProcessPath(PathData item)
            {
                @out.WriteLine("# file: " + item);
                @out.WriteLine("# owner: " + item.stat.GetOwner());
                @out.WriteLine("# group: " + item.stat.GetGroup());
                FsPermission perm = item.stat.GetPermission();

                if (perm.GetStickyBit())
                {
                    @out.WriteLine("# flags: --" + (perm.GetOtherAction().Implies(FsAction.Execute) ?
                                                    "t" : "T"));
                }
                AclStatus        aclStatus = item.fs.GetAclStatus(item.path);
                IList <AclEntry> entries   = perm.GetAclBit() ? aclStatus.GetEntries() : Collections
                                             .EmptyList <AclEntry>();
                ScopedAclEntries scopedEntries = new ScopedAclEntries(AclUtil.GetAclFromPermAndEntries
                                                                          (perm, entries));

                PrintAclEntriesForSingleScope(aclStatus, perm, scopedEntries.GetAccessEntries());
                PrintAclEntriesForSingleScope(aclStatus, perm, scopedEntries.GetDefaultEntries());
                @out.WriteLine();
            }
示例#5
0
        /// <summary>Updates an inode with a new ACL.</summary>
        /// <remarks>
        /// Updates an inode with a new ACL.  This method takes a full logical ACL and
        /// stores the entries to the inode's
        /// <see cref="Org.Apache.Hadoop.FS.Permission.FsPermission"/>
        /// and
        /// <see cref="AclFeature"/>
        /// .
        /// </remarks>
        /// <param name="inode">INode to update</param>
        /// <param name="newAcl">List<AclEntry> containing new ACL entries</param>
        /// <param name="snapshotId">int latest snapshot ID of inode</param>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.AclException">if the ACL is invalid for the given inode
        ///     </exception>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.QuotaExceededException">if quota limit is exceeded
        ///     </exception>
        public static void UpdateINodeAcl(INode inode, IList <AclEntry> newAcl, int snapshotId
                                          )
        {
            System.Diagnostics.Debug.Assert(newAcl.Count >= 3);
            FsPermission perm = inode.GetFsPermission();
            FsPermission newPerm;

            if (!AclUtil.IsMinimalAcl(newAcl))
            {
                // This is an extended ACL.  Split entries into access vs. default.
                ScopedAclEntries scoped         = new ScopedAclEntries(newAcl);
                IList <AclEntry> accessEntries  = scoped.GetAccessEntries();
                IList <AclEntry> defaultEntries = scoped.GetDefaultEntries();
                // Only directories may have a default ACL.
                if (!defaultEntries.IsEmpty() && !inode.IsDirectory())
                {
                    throw new AclException("Invalid ACL: only directories may have a default ACL.");
                }
                // Attach entries to the feature.
                if (inode.GetAclFeature() != null)
                {
                    inode.RemoveAclFeature(snapshotId);
                }
                inode.AddAclFeature(CreateAclFeature(accessEntries, defaultEntries), snapshotId);
                newPerm = CreateFsPermissionForExtendedAcl(accessEntries, perm);
            }
            else
            {
                // This is a minimal ACL.  Remove the ACL feature if it previously had one.
                if (inode.GetAclFeature() != null)
                {
                    inode.RemoveAclFeature(snapshotId);
                }
                newPerm = CreateFsPermissionForMinimalAcl(newAcl, perm);
            }
            inode.SetPermission(newPerm, snapshotId);
        }
示例#6
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);
        }