Skip to content

Commit d0f3188

Browse files
committed
HADOOP-7110. Implement chmod with JNI. Contributed by Todd Lipcon
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1063090 13f79535-47bb-0310-9956-ffa450edef68
1 parent 93dc83f commit d0f3188

File tree

6 files changed

+69
-2
lines changed

6 files changed

+69
-2
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ Release 0.22.0 - Unreleased
266266
HADOOP-6056. Use java.net.preferIPv4Stack to force IPv4.
267267
(Michele Catasta via shv)
268268

269+
HADOOP-7110. Implement chmod with JNI. (todd)
270+
269271
OPTIMIZATIONS
270272

271273
HADOOP-6884. Add LOG.isDebugEnabled() guard for each LOG.debug(..).

src/java/org/apache/hadoop/fs/RawLocalFileSystem.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.hadoop.classification.InterfaceStability;
3737
import org.apache.hadoop.conf.Configuration;
3838
import org.apache.hadoop.fs.permission.FsPermission;
39+
import org.apache.hadoop.io.nativeio.NativeIO;
3940
import org.apache.hadoop.util.Progressable;
4041
import org.apache.hadoop.util.Shell;
4142
import org.apache.hadoop.util.StringUtils;
@@ -554,8 +555,13 @@ public void setOwner(Path p, String username, String groupname)
554555
@Override
555556
public void setPermission(Path p, FsPermission permission)
556557
throws IOException {
557-
execCommand(pathToFile(p), Shell.SET_PERMISSION_COMMAND,
558-
String.format("%05o", permission.toShort()));
558+
if (NativeIO.isAvailable()) {
559+
NativeIO.chmod(pathToFile(p).getCanonicalPath(),
560+
permission.toShort());
561+
} else {
562+
execCommand(pathToFile(p), Shell.SET_PERMISSION_COMMAND,
563+
String.format("%05o", permission.toShort()));
564+
}
559565
}
560566

561567
private static String execCommand(File f, String... cmd) throws IOException {

src/java/org/apache/hadoop/io/nativeio/NativeIO.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ public static boolean isAvailable() {
7474
public static native FileDescriptor open(String path, int flags, int mode) throws IOException;
7575
/** Wrapper around fstat(2) */
7676
public static native Stat fstat(FileDescriptor fd) throws IOException;
77+
/** Wrapper around chmod(2) */
78+
public static native void chmod(String path, int mode) throws IOException;
79+
7780
/** Initialize the JNI method ID and class ID cache */
7881
private static native void initNative();
7982

src/native/config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282
/* Define to the one symbol short name of this package. */
8383
#undef PACKAGE_TARNAME
8484

85+
/* Define to the home page for this package. */
86+
#undef PACKAGE_URL
87+
8588
/* Define to the version of this package. */
8689
#undef PACKAGE_VERSION
8790

src/native/src/org/apache/hadoop/io/nativeio/NativeIO.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,25 @@ Java_org_apache_hadoop_io_nativeio_NativeIO_open(
221221
return ret;
222222
}
223223

224+
/**
225+
* public static native void chmod(String path, int mode) throws IOException;
226+
*/
227+
JNIEXPORT void JNICALL
228+
Java_org_apache_hadoop_io_nativeio_NativeIO_chmod(
229+
JNIEnv *env, jclass clazz, jstring j_path,
230+
jint mode)
231+
{
232+
const char *path = (*env)->GetStringUTFChars(env, j_path, NULL);
233+
if (path == NULL) return; // JVM throws Exception for us
234+
235+
if (chmod(path, mode) != 0) {
236+
throw_ioe(env, errno);
237+
}
238+
239+
(*env)->ReleaseStringUTFChars(env, j_path, path);
240+
}
241+
242+
224243
/*
225244
* Throw a java.IO.IOException, generating the message from errno.
226245
*/

src/test/core/org/apache/hadoop/io/nativeio/TestNativeIO.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828

2929
import org.apache.commons.logging.Log;
3030
import org.apache.commons.logging.LogFactory;
31+
import org.apache.hadoop.conf.Configuration;
3132
import org.apache.hadoop.fs.FileUtil;
33+
import org.apache.hadoop.fs.FileSystem;
34+
import org.apache.hadoop.fs.Path;
35+
import org.apache.hadoop.fs.permission.FsPermission;
3236
import org.apache.hadoop.util.NativeCodeLoader;
3337

3438
public class TestNativeIO {
@@ -134,4 +138,34 @@ public void testFDDoesntLeak() throws IOException {
134138
}
135139
}
136140

141+
/**
142+
* Test basic chmod operation
143+
*/
144+
@Test
145+
public void testChmod() throws Exception {
146+
try {
147+
NativeIO.chmod("/this/file/doesnt/exist", 777);
148+
fail("Chmod of non-existent file didn't fail");
149+
} catch (NativeIOException nioe) {
150+
assertEquals(Errno.ENOENT, nioe.getErrno());
151+
}
152+
153+
File toChmod = new File(TEST_DIR, "testChmod");
154+
assertTrue("Create test subject",
155+
toChmod.exists() || toChmod.mkdir());
156+
NativeIO.chmod(toChmod.getAbsolutePath(), 0777);
157+
assertPermissions(toChmod, 0777);
158+
NativeIO.chmod(toChmod.getAbsolutePath(), 0000);
159+
assertPermissions(toChmod, 0000);
160+
NativeIO.chmod(toChmod.getAbsolutePath(), 0644);
161+
assertPermissions(toChmod, 0644);
162+
}
163+
164+
private void assertPermissions(File f, int expected) throws IOException {
165+
FileSystem localfs = FileSystem.getLocal(new Configuration());
166+
FsPermission perms = localfs.getFileStatus(
167+
new Path(f.getAbsolutePath())).getPermission();
168+
assertEquals(expected, perms.toShort());
169+
}
170+
137171
}

0 commit comments

Comments
 (0)