Browse Source

HADOOP-7432. Back-port HADOOP-7110 to 0.20-security: Implement chmod in NativeIO library. Contributed by Sherry Chen.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20-security@1148579 13f79535-47bb-0310-9956-ffa450edef68
Matthew Foley 14 years ago
parent
commit
4eacf16ae3

+ 3 - 0
CHANGES.txt

@@ -20,6 +20,9 @@ Release 0.20.205.0 - unreleased
     HDFS-1836. Thousand of CLOSE_WAIT socket. Contributed by Todd Lipcon,
     ported to security branch by Bharath Mundlapudi. (via mattf)
 
+    HADOOP-7432. Back-port HADOOP-7110 to 0.20-security: Implement chmod
+    in NativeIO library. (Sherry Chen via mattf)
+
 Release 0.20.204.0 - unreleased
 
   NEW FEATURES

+ 8 - 2
src/core/org/apache/hadoop/fs/RawLocalFileSystem.java

@@ -26,6 +26,7 @@ import java.util.*;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.permission.*;
+import org.apache.hadoop.io.nativeio.NativeIO;
 import org.apache.hadoop.util.Progressable;
 import org.apache.hadoop.util.StringUtils;
 import org.apache.hadoop.util.Shell;
@@ -529,8 +530,13 @@ public class RawLocalFileSystem extends FileSystem {
   
   private void execSetPermission(File f, FsPermission permission) 
   throws IOException {
-    execCommand(f, Shell.SET_PERMISSION_COMMAND,
-        String.format("%04o", permission.toShort()));
+    if (NativeIO.isAvailable()) {
+      NativeIO.chmod(f.getCanonicalPath(),
+      permission.toShort());
+    } else {
+      execCommand(f, Shell.SET_PERMISSION_COMMAND,
+          String.format("%04o", permission.toShort()));
+    }
   }
   
   private static String execCommand(File f, String... cmd) throws IOException {

+ 3 - 1
src/core/org/apache/hadoop/io/nativeio/NativeIO.java

@@ -79,11 +79,13 @@ public class NativeIO {
   //TODO: fstat is an old implementation. Doesn't use the cache. This should be 
   //changed to use the cache.
   public static native Stat fstat(FileDescriptor fd) throws IOException;
+
   private static native long getUIDforFDOwnerforOwner(FileDescriptor fd) throws IOException;
   private static native String getUserName(long uid) throws IOException;
   /** Initialize the JNI method ID and class ID cache */
   private static native void initNative();
-  
+  /** Wrapper around chmod(2) */
+  public static native void chmod(String path, int mode) throws IOException;
   private static class CachedUid {
     final long timestamp;
     final String username;

+ 3 - 0
src/native/config.h.in

@@ -82,6 +82,9 @@
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
 
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 

+ 18 - 0
src/native/src/org/apache/hadoop/io/nativeio/NativeIO.c

@@ -266,6 +266,24 @@ cleanup:
   return jstr_username;
 }
 
+/**
+ * public static native void chmod(String path, int mode) throws IOException;
+ */
+JNIEXPORT void JNICALL
+Java_org_apache_hadoop_io_nativeio_NativeIO_chmod(
+  JNIEnv *env, jclass clazz, jstring j_path,
+  jint mode)
+{
+  const char *path = (*env)->GetStringUTFChars(env, j_path, NULL);
+  if (path == NULL) return; // JVM throws Exception for us
+
+  if (chmod(path, mode) != 0) {
+    throw_ioe(env, errno);
+  }
+
+  (*env)->ReleaseStringUTFChars(env, j_path, path);
+}
+
 /*
  * Throw a java.IO.IOException, generating the message from errno.
  */

+ 34 - 0
src/test/org/apache/hadoop/io/nativeio/TestNativeIO.java

@@ -28,7 +28,11 @@ import static org.junit.Assert.*;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.util.NativeCodeLoader;
 
 public class TestNativeIO {
@@ -136,4 +140,34 @@ public class TestNativeIO {
     }
   }
 
+  /**
+   * Test basic chmod operation
+   */
+  @Test
+  public void testChmod() throws Exception {
+    try {
+      NativeIO.chmod("/this/file/doesnt/exist", 777);
+      fail("Chmod of non-existent file didn't fail");
+    } catch (NativeIOException nioe) {
+      assertEquals(Errno.ENOENT, nioe.getErrno());
+    }
+
+    File toChmod = new File(TEST_DIR, "testChmod");
+    assertTrue("Create test subject",
+               toChmod.exists() || toChmod.mkdir());
+    NativeIO.chmod(toChmod.getAbsolutePath(), 0777);
+    assertPermissions(toChmod, 0777);
+    NativeIO.chmod(toChmod.getAbsolutePath(), 0000);
+    assertPermissions(toChmod, 0000);
+    NativeIO.chmod(toChmod.getAbsolutePath(), 0644);
+    assertPermissions(toChmod, 0644);
+  }
+
+  private void assertPermissions(File f, int expected) throws IOException {
+    FileSystem localfs = FileSystem.getLocal(new Configuration());
+    FsPermission perms = localfs.getFileStatus(
+      new Path(f.getAbsolutePath())).getPermission();
+    assertEquals(expected, perms.toShort());
+  }
+
 }