HDFS-10689. Hdfs dfs chmod should reset sticky bit permission when the bit is omitted in the octal mode. (Manoj Govindassamy via Lei Xu)

This commit is contained in:
Lei Xu 2016-07-28 13:52:14 -07:00
parent 67406460f0
commit a3d0cba810
3 changed files with 81 additions and 20 deletions

View File

@ -55,7 +55,7 @@ class PermissionParser {
if ((matcher = symbolic.matcher(modeStr)).find()) {
applyNormalPattern(modeStr, matcher);
} else if ((matcher = octal.matcher(modeStr)).matches()) {
applyOctalPattern(modeStr, matcher);
applyOctalPattern(matcher);
} else {
throw new IllegalArgumentException(modeStr);
}
@ -63,10 +63,10 @@ class PermissionParser {
private void applyNormalPattern(String modeStr, Matcher matcher) {
// Are there multiple permissions stored in one chmod?
boolean commaSeperated = false;
boolean commaSeparated = false;
for (int i = 0; i < 1 || matcher.end() < modeStr.length(); i++) {
if (i > 0 && (!commaSeperated || !matcher.find())) {
if (i > 0 && (!commaSeparated || !matcher.find())) {
throw new IllegalArgumentException(modeStr);
}
@ -144,19 +144,26 @@ class PermissionParser {
stickyBitType = type;
}
commaSeperated = matcher.group(4).contains(",");
commaSeparated = matcher.group(4).contains(",");
}
symbolic = true;
}
private void applyOctalPattern(String modeStr, Matcher matcher) {
userType = groupType = othersType = '=';
private void applyOctalPattern(final Matcher matcher) {
// Matcher groups: 1: [01] 2: [0-7]{3}
final char typeApply = '=';
stickyBitType = typeApply;
userType = typeApply;
groupType = typeApply;
othersType = typeApply;
// Check if sticky bit is specified
// If sticky bit is specified get the bit, else
// default to reset for apply condition
String sb = matcher.group(1);
if (!sb.isEmpty()) {
stickyMode = Short.valueOf(sb.substring(0, 1));
stickyBitType = '=';
} else {
stickyMode = 0;
}
String str = matcher.group(2);

View File

@ -17,10 +17,11 @@
*/
package org.apache.hadoop.fs.permission;
import static org.apache.hadoop.fs.permission.AclEntryScope.*;
import static org.apache.hadoop.fs.permission.AclEntryType.*;
import static org.apache.hadoop.fs.permission.FsAction.*;
import static org.apache.hadoop.hdfs.server.namenode.AclTestHelpers.*;
import static org.apache.hadoop.fs.permission.AclEntryScope.ACCESS;
import static org.apache.hadoop.fs.permission.AclEntryScope.DEFAULT;
import static org.apache.hadoop.fs.permission.AclEntryType.USER;
import static org.apache.hadoop.fs.permission.FsAction.ALL;
import static org.apache.hadoop.hdfs.server.namenode.AclTestHelpers.aclEntry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@ -46,6 +47,8 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestStickyBit {
@ -53,6 +56,7 @@ public class TestStickyBit {
UserGroupInformation.createUserForTesting("theDoctor", new String[] {"tardis"});
static final UserGroupInformation user2 =
UserGroupInformation.createUserForTesting("rose", new String[] {"powellestates"});
static final Logger LOG = LoggerFactory.getLogger(TestStickyBit.class);
private static MiniDFSCluster cluster;
private static Configuration conf;
@ -344,6 +348,52 @@ public class TestStickyBit {
assertFalse(hdfs.getFileStatus(sbSetOff).getPermission().getStickyBit());
}
/**
* Sticky bit set on a directory can be reset either explicitly (like 0777)
* or by omitting the bit (like 777) in the permission. Ensure that the
* directory gets its sticky bit reset whenever it is omitted in permission.
*/
@Test
public void testStickyBitReset() throws Exception {
Path sbExplicitTestDir = new Path("/DirToTestExplicitStickyBit");
Path sbOmittedTestDir = new Path("/DirToTestOmittedStickyBit");
// Creation of directories and verification of their existence
hdfs.mkdirs(sbExplicitTestDir);
hdfs.mkdirs(sbOmittedTestDir);
assertTrue(hdfs.exists(sbExplicitTestDir));
assertTrue(hdfs.exists(sbOmittedTestDir));
// Setting sticky bit explicitly on sbExplicitTestDir and verification
hdfs.setPermission(sbExplicitTestDir, new FsPermission((short) 01777));
LOG.info("Dir: {}, permission: {}", sbExplicitTestDir.getName(),
hdfs.getFileStatus(sbExplicitTestDir).getPermission());
assertTrue(hdfs.getFileStatus(sbExplicitTestDir).
getPermission().getStickyBit());
// Sticky bit omitted on sbOmittedTestDir should behave like reset
hdfs.setPermission(sbOmittedTestDir, new FsPermission((short) 0777));
LOG.info("Dir: {}, permission: {}", sbOmittedTestDir.getName(),
hdfs.getFileStatus(sbOmittedTestDir).getPermission());
assertFalse(
hdfs.getFileStatus(sbOmittedTestDir).getPermission().getStickyBit());
// Resetting sticky bit explicitly on sbExplicitTestDir and verification
hdfs.setPermission(sbExplicitTestDir, new FsPermission((short) 00777));
LOG.info("Dir: {}, permission: {}", sbExplicitTestDir.getName(),
hdfs.getFileStatus(sbExplicitTestDir).getPermission());
assertFalse(
hdfs.getFileStatus(sbExplicitTestDir).getPermission().getStickyBit());
// Set the sticky bit and reset again by omitting in the permission
hdfs.setPermission(sbOmittedTestDir, new FsPermission((short) 01777));
hdfs.setPermission(sbOmittedTestDir, new FsPermission((short) 0777));
LOG.info("Dir: {}, permission: {}", sbOmittedTestDir.getName(),
hdfs.getFileStatus(sbOmittedTestDir).getPermission());
assertFalse(
hdfs.getFileStatus(sbOmittedTestDir).getPermission().getStickyBit());
}
@Test
public void testAclStickyBitPersistence() throws Exception {
// A tale of three directories...

View File

@ -1059,19 +1059,23 @@ public class TestDFSShell {
fs.getFileStatus(dir2).getPermission());
confirmPermissionChange("u=rwx,g=rx,o=rx", "rwxr-xr-x", fs, shell, dir2);
// sticky bit explicit set
confirmPermissionChange("+t", "rwxr-xr-t", fs, shell, dir2);
// sticky bit explicit reset
confirmPermissionChange("-t", "rwxr-xr-x", fs, shell, dir2);
confirmPermissionChange("=t", "--------T", fs, shell, dir2);
// reset all permissions
confirmPermissionChange("0000", "---------", fs, shell, dir2);
// turn on rw permissions for all
confirmPermissionChange("1666", "rw-rw-rwT", fs, shell, dir2);
confirmPermissionChange("777", "rwxrwxrwt", fs, shell, dir2);
// sticky bit explicit set along with x permission
confirmPermissionChange("1777", "rwxrwxrwt", fs, shell, dir2);
// sticky bit explicit reset
confirmPermissionChange("0777", "rwxrwxrwx", fs, shell, dir2);
// sticky bit explicit set
confirmPermissionChange("1777", "rwxrwxrwt", fs, shell, dir2);
// sticky bit implicit reset
confirmPermissionChange("777", "rwxrwxrwx", fs, shell, dir2);
fs.delete(dir2, true);
} else {
LOG.info("Skipped sticky bit tests on Windows");