Author: cnauroth Date: Thu May 15 16:45:36 2014 New Revision: 1594975 URL: http://svn.apache.org/r1594975 Log: HDFS-6326. WebHdfs ACL compatibility is broken. Contributed by Chris Nauroth.
Modified: hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/permission/FsPermission.java hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/AclCommands.java hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java Modified: hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/permission/FsPermission.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/permission/FsPermission.java?rev=1594975&r1=1594974&r2=1594975&view=diff ============================================================================== --- hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/permission/FsPermission.java (original) +++ hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/permission/FsPermission.java Thu May 15 16:45:36 2014 @@ -158,6 +158,17 @@ public class FsPermission implements Wri return (short)s; } + /** + * Encodes the object to a short. Unlike {@link #toShort()}, this method may + * return values outside the fixed range 00000 - 01777 if extended features + * are encoded into this permission, such as the ACL bit. + * + * @return short extended short representation of this permission + */ + public short toExtendedShort() { + return toShort(); + } + @Override public boolean equals(Object obj) { if (obj instanceof FsPermission) { @@ -273,6 +284,16 @@ public class FsPermission implements Wri return stickyBit; } + /** + * Returns true if there is also an ACL (access control list). + * + * @return boolean true if there is also an ACL (access control list). + */ + public boolean getAclBit() { + // File system subclasses that support the ACL bit would override this. + return false; + } + /** Set the user file creation mask (umask) */ public static void setUMask(Configuration conf, FsPermission umask) { conf.set(UMASK_LABEL, String.format("%1$03o", umask.toShort())); Modified: hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/AclCommands.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/AclCommands.java?rev=1594975&r1=1594974&r2=1594975&view=diff ============================================================================== --- hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/AclCommands.java (original) +++ hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/AclCommands.java Thu May 15 16:45:36 2014 @@ -75,29 +75,21 @@ class AclCommands extends FsCommand { @Override protected void processPath(PathData item) throws IOException { - AclStatus aclStatus = item.fs.getAclStatus(item.path); out.println("# file: " + item); - out.println("# owner: " + aclStatus.getOwner()); - out.println("# group: " + aclStatus.getGroup()); - List<AclEntry> entries = aclStatus.getEntries(); - if (aclStatus.isStickyBit()) { - String stickyFlag = "T"; - for (AclEntry aclEntry : entries) { - if (aclEntry.getType() == AclEntryType.OTHER - && aclEntry.getScope() == AclEntryScope.ACCESS - && aclEntry.getPermission().implies(FsAction.EXECUTE)) { - stickyFlag = "t"; - break; - } - } - out.println("# flags: --" + stickyFlag); + out.println("# owner: " + item.stat.getOwner()); + out.println("# group: " + item.stat.getGroup()); + FsPermission perm = item.stat.getPermission(); + if (perm.getStickyBit()) { + out.println("# flags: --" + + (perm.getOtherAction().implies(FsAction.EXECUTE) ? "t" : "T")); } - FsPermission perm = item.stat.getPermission(); - if (entries.isEmpty()) { - printMinimalAcl(perm); - } else { + if (perm.getAclBit()) { + AclStatus aclStatus = item.fs.getAclStatus(item.path); + List<AclEntry> entries = aclStatus.getEntries(); printExtendedAcl(perm, entries); + } else { + printMinimalAcl(perm); } out.println(); Modified: hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java?rev=1594975&r1=1594974&r2=1594975&view=diff ============================================================================== --- hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java (original) +++ hadoop/common/branches/branch-2.4/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java Thu May 15 16:45:36 2014 @@ -31,8 +31,6 @@ import org.apache.hadoop.classification. import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; -import org.apache.hadoop.ipc.RemoteException; -import org.apache.hadoop.ipc.RpcNoSuchMethodException; import com.google.common.collect.Sets; @@ -116,7 +114,7 @@ class Ls extends FsCommand { FileStatus stat = item.stat; String line = String.format(lineFormat, (stat.isDirectory() ? "d" : "-"), - stat.getPermission() + (hasAcl(item) ? "+" : " "), + stat.getPermission() + (stat.getPermission().getAclBit() ? "+" : " "), (stat.isFile() ? stat.getReplication() : "-"), stat.getOwner(), stat.getGroup(), @@ -153,49 +151,6 @@ class Ls extends FsCommand { lineFormat = fmt.toString(); } - /** - * Calls getAclStatus to determine if the given item has an ACL. For - * compatibility, this method traps errors caused by the RPC method missing - * from the server side. This would happen if the client was connected to an - * old NameNode that didn't have the ACL APIs. This method also traps the - * case of the client-side FileSystem not implementing the ACL APIs. - * FileSystem instances that do not support ACLs are remembered. This - * prevents the client from sending multiple failing RPC calls during a - * recursive ls. - * - * @param item PathData item to check - * @return boolean true if item has an ACL - * @throws IOException if there is a failure - */ - private boolean hasAcl(PathData item) throws IOException { - FileSystem fs = item.fs; - if (aclNotSupportedFsSet.contains(fs.getUri())) { - // This FileSystem failed to run the ACL API in an earlier iteration. - return false; - } - try { - return !fs.getAclStatus(item.path).getEntries().isEmpty(); - } catch (RemoteException e) { - // If this is a RpcNoSuchMethodException, then the client is connected to - // an older NameNode that doesn't support ACLs. Keep going. - IOException e2 = e.unwrapRemoteException(RpcNoSuchMethodException.class); - if (!(e2 instanceof RpcNoSuchMethodException)) { - throw e; - } - } catch (IOException e) { - // The NameNode supports ACLs, but they are not enabled. Keep going. - String message = e.getMessage(); - if (message != null && !message.contains("ACLs has been disabled")) { - throw e; - } - } catch (UnsupportedOperationException e) { - // The underlying FileSystem doesn't implement ACLs. Keep going. - } - // Remember that this FileSystem cannot support ACLs. - aclNotSupportedFsSet.add(fs.getUri()); - return false; - } - private int maxLength(int n, Object value) { return Math.max(n, (value != null) ? String.valueOf(value).length() : 0); }