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:
parent
67406460f0
commit
a3d0cba810
|
@ -55,7 +55,7 @@ class PermissionParser {
|
||||||
if ((matcher = symbolic.matcher(modeStr)).find()) {
|
if ((matcher = symbolic.matcher(modeStr)).find()) {
|
||||||
applyNormalPattern(modeStr, matcher);
|
applyNormalPattern(modeStr, matcher);
|
||||||
} else if ((matcher = octal.matcher(modeStr)).matches()) {
|
} else if ((matcher = octal.matcher(modeStr)).matches()) {
|
||||||
applyOctalPattern(modeStr, matcher);
|
applyOctalPattern(matcher);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(modeStr);
|
throw new IllegalArgumentException(modeStr);
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,10 @@ class PermissionParser {
|
||||||
|
|
||||||
private void applyNormalPattern(String modeStr, Matcher matcher) {
|
private void applyNormalPattern(String modeStr, Matcher matcher) {
|
||||||
// Are there multiple permissions stored in one chmod?
|
// 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++) {
|
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);
|
throw new IllegalArgumentException(modeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,19 +144,26 @@ class PermissionParser {
|
||||||
stickyBitType = type;
|
stickyBitType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
commaSeperated = matcher.group(4).contains(",");
|
commaSeparated = matcher.group(4).contains(",");
|
||||||
}
|
}
|
||||||
symbolic = true;
|
symbolic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyOctalPattern(String modeStr, Matcher matcher) {
|
private void applyOctalPattern(final Matcher matcher) {
|
||||||
userType = groupType = othersType = '=';
|
// 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);
|
String sb = matcher.group(1);
|
||||||
if (!sb.isEmpty()) {
|
if (!sb.isEmpty()) {
|
||||||
stickyMode = Short.valueOf(sb.substring(0, 1));
|
stickyMode = Short.valueOf(sb.substring(0, 1));
|
||||||
stickyBitType = '=';
|
} else {
|
||||||
|
stickyMode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String str = matcher.group(2);
|
String str = matcher.group(2);
|
||||||
|
|
|
@ -17,10 +17,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.fs.permission;
|
package org.apache.hadoop.fs.permission;
|
||||||
|
|
||||||
import static org.apache.hadoop.fs.permission.AclEntryScope.*;
|
import static org.apache.hadoop.fs.permission.AclEntryScope.ACCESS;
|
||||||
import static org.apache.hadoop.fs.permission.AclEntryType.*;
|
import static org.apache.hadoop.fs.permission.AclEntryScope.DEFAULT;
|
||||||
import static org.apache.hadoop.fs.permission.FsAction.*;
|
import static org.apache.hadoop.fs.permission.AclEntryType.USER;
|
||||||
import static org.apache.hadoop.hdfs.server.namenode.AclTestHelpers.*;
|
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.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
@ -46,6 +47,8 @@ import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class TestStickyBit {
|
public class TestStickyBit {
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ public class TestStickyBit {
|
||||||
UserGroupInformation.createUserForTesting("theDoctor", new String[] {"tardis"});
|
UserGroupInformation.createUserForTesting("theDoctor", new String[] {"tardis"});
|
||||||
static final UserGroupInformation user2 =
|
static final UserGroupInformation user2 =
|
||||||
UserGroupInformation.createUserForTesting("rose", new String[] {"powellestates"});
|
UserGroupInformation.createUserForTesting("rose", new String[] {"powellestates"});
|
||||||
|
static final Logger LOG = LoggerFactory.getLogger(TestStickyBit.class);
|
||||||
|
|
||||||
private static MiniDFSCluster cluster;
|
private static MiniDFSCluster cluster;
|
||||||
private static Configuration conf;
|
private static Configuration conf;
|
||||||
|
@ -344,6 +348,52 @@ public class TestStickyBit {
|
||||||
assertFalse(hdfs.getFileStatus(sbSetOff).getPermission().getStickyBit());
|
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
|
@Test
|
||||||
public void testAclStickyBitPersistence() throws Exception {
|
public void testAclStickyBitPersistence() throws Exception {
|
||||||
// A tale of three directories...
|
// A tale of three directories...
|
||||||
|
|
|
@ -1059,19 +1059,23 @@ public class TestDFSShell {
|
||||||
fs.getFileStatus(dir2).getPermission());
|
fs.getFileStatus(dir2).getPermission());
|
||||||
|
|
||||||
confirmPermissionChange("u=rwx,g=rx,o=rx", "rwxr-xr-x", fs, shell, dir2);
|
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);
|
confirmPermissionChange("+t", "rwxr-xr-t", fs, shell, dir2);
|
||||||
|
// sticky bit explicit reset
|
||||||
confirmPermissionChange("-t", "rwxr-xr-x", fs, shell, dir2);
|
confirmPermissionChange("-t", "rwxr-xr-x", fs, shell, dir2);
|
||||||
|
|
||||||
confirmPermissionChange("=t", "--------T", fs, shell, dir2);
|
confirmPermissionChange("=t", "--------T", fs, shell, dir2);
|
||||||
|
// reset all permissions
|
||||||
confirmPermissionChange("0000", "---------", fs, shell, dir2);
|
confirmPermissionChange("0000", "---------", fs, shell, dir2);
|
||||||
|
// turn on rw permissions for all
|
||||||
confirmPermissionChange("1666", "rw-rw-rwT", fs, shell, dir2);
|
confirmPermissionChange("1666", "rw-rw-rwT", fs, shell, dir2);
|
||||||
|
// sticky bit explicit set along with x permission
|
||||||
confirmPermissionChange("777", "rwxrwxrwt", fs, shell, dir2);
|
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);
|
fs.delete(dir2, true);
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Skipped sticky bit tests on Windows");
|
LOG.info("Skipped sticky bit tests on Windows");
|
||||||
|
|
Loading…
Reference in New Issue