diff options
-rw-r--r-- | luni/src/main/java/android/system/Os.java | 5 | ||||
-rw-r--r-- | luni/src/main/java/android/system/OsConstants.java | 1 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/ForwardingOs.java | 1 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Linux.java | 1 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Os.java | 1 | ||||
-rw-r--r-- | luni/src/main/native/android_system_OsConstants.cpp | 3 | ||||
-rw-r--r-- | luni/src/main/native/libcore_io_Linux.cpp | 16 | ||||
-rw-r--r-- | luni/src/test/java/libcore/android/system/OsTest.java | 68 | ||||
-rw-r--r-- | luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java | 1 |
9 files changed, 97 insertions, 0 deletions
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java index cc6b0a56d5..4c258c69e2 100644 --- a/luni/src/main/java/android/system/Os.java +++ b/luni/src/main/java/android/system/Os.java @@ -362,6 +362,11 @@ public final class Os { public static StructStat lstat(String path) throws ErrnoException { return Libcore.os.lstat(path); } /** + * See <a href="http://man7.org/linux/man-pages/man2/memfd_create.2.html">memfd_create(2)</a>. + */ + public static @NonNull FileDescriptor memfd_create(@NonNull String name, int flags) throws ErrnoException { return Libcore.os.memfd_create(name, flags); } + + /** * See <a href="http://man7.org/linux/man-pages/man2/mincore.2.html">mincore(2)</a>. */ public static void mincore(long address, long byteCount, byte[] vector) throws ErrnoException { Libcore.os.mincore(address, byteCount, vector); } diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java index 9daccc697d..d8745511c2 100644 --- a/luni/src/main/java/android/system/OsConstants.java +++ b/luni/src/main/java/android/system/OsConstants.java @@ -374,6 +374,7 @@ public final class OsConstants { public static final int MCAST_UNBLOCK_SOURCE = placeholder(); public static final int MCL_CURRENT = placeholder(); public static final int MCL_FUTURE = placeholder(); + public static final int MFD_CLOEXEC = placeholder(); public static final int MSG_CTRUNC = placeholder(); public static final int MSG_DONTROUTE = placeholder(); public static final int MSG_EOR = placeholder(); diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index c82cbe0fa3..c75f94e4ad 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -150,6 +150,7 @@ public class ForwardingOs implements Os { public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException { return os.lseek(fd, offset, whence); } @UnsupportedAppUsage public StructStat lstat(String path) throws ErrnoException { return os.lstat(path); } + public FileDescriptor memfd_create(String name, int flags) throws ErrnoException { return os.memfd_create(name, flags); } public void mincore(long address, long byteCount, byte[] vector) throws ErrnoException { os.mincore(address, byteCount, vector); } @UnsupportedAppUsage public void mkdir(String path, int mode) throws ErrnoException { os.mkdir(path, mode); } diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java index e2a4c548d4..74608d392a 100644 --- a/luni/src/main/java/libcore/io/Linux.java +++ b/luni/src/main/java/libcore/io/Linux.java @@ -121,6 +121,7 @@ public final class Linux implements Os { public native String[] listxattr(String path) throws ErrnoException; public native long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException; public native StructStat lstat(String path) throws ErrnoException; + public native FileDescriptor memfd_create(String name, int flags) throws ErrnoException; public native void mincore(long address, long byteCount, byte[] vector) throws ErrnoException; public native void mkdir(String path, int mode) throws ErrnoException; public native void mkfifo(String path, int mode) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index a7bae10450..048a973778 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -123,6 +123,7 @@ public interface Os { public String[] listxattr(String path) throws ErrnoException; public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException; public StructStat lstat(String path) throws ErrnoException; + public FileDescriptor memfd_create(String name, int flags) throws ErrnoException; public void mincore(long address, long byteCount, byte[] vector) throws ErrnoException; public void mkdir(String path, int mode) throws ErrnoException; public void mkfifo(String path, int mode) throws ErrnoException; diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp index 31ef37da3c..6cf2c8b30b 100644 --- a/luni/src/main/native/android_system_OsConstants.cpp +++ b/luni/src/main/native/android_system_OsConstants.cpp @@ -375,6 +375,9 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { #endif initConstant(env, c, "MCL_CURRENT", MCL_CURRENT); initConstant(env, c, "MCL_FUTURE", MCL_FUTURE); +#if defined(MFD_CLOEXEC) + initConstant(env, c, "MFD_CLOEXEC", MFD_CLOEXEC); +#endif initConstant(env, c, "MSG_CTRUNC", MSG_CTRUNC); initConstant(env, c, "MSG_DONTROUTE", MSG_DONTROUTE); initConstant(env, c, "MSG_EOR", MSG_EOR); diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp index 805b32fb47..9e44e63fe4 100644 --- a/luni/src/main/native/libcore_io_Linux.cpp +++ b/luni/src/main/native/libcore_io_Linux.cpp @@ -1837,6 +1837,21 @@ static jobject Linux_lstat(JNIEnv* env, jobject, jstring javaPath) { return doStat(env, javaPath, true); } +static jobject Linux_memfd_create(JNIEnv* env, jobject, jstring javaName, jint flags) { +#if defined(__BIONIC__) + ScopedUtfChars name(env, javaName); + if (name.c_str() == NULL) { + return NULL; + } + + int fd = throwIfMinusOne(env, "memfd_create", memfd_create(name.c_str(), flags)); + return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL; +#else + UNUSED(env, javaName, flags); + return NULL; +#endif +} + static void Linux_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) { ScopedByteArrayRW vector(env, javaVector); if (vector.get() == NULL) { @@ -2623,6 +2638,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Linux, listxattr, "(Ljava/lang/String;)[Ljava/lang/String;"), NATIVE_METHOD(Linux, lseek, "(Ljava/io/FileDescriptor;JI)J"), NATIVE_METHOD(Linux, lstat, "(Ljava/lang/String;)Landroid/system/StructStat;"), + NATIVE_METHOD(Linux, memfd_create, "(Ljava/lang/String;I)Ljava/io/FileDescriptor;"), NATIVE_METHOD(Linux, mincore, "(JJ[B)V"), NATIVE_METHOD(Linux, mkdir, "(Ljava/lang/String;I)V"), NATIVE_METHOD(Linux, mkfifo, "(Ljava/lang/String;I)V"), diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java index a56ff000b9..25d56bcbc3 100644 --- a/luni/src/test/java/libcore/android/system/OsTest.java +++ b/luni/src/test/java/libcore/android/system/OsTest.java @@ -1481,4 +1481,72 @@ public class OsTest extends TestCase { assertTrue(address > 0); Os.munmap(address, size); } + + public void testMemfdCreate() throws Exception { + FileDescriptor fd = null; + try { + fd = Os.memfd_create("test_memfd", 0); + assertNotNull(fd); + assertTrue(fd.valid()); + + StructStat stat = Os.fstat(fd); + assertEquals(0, stat.st_size); + + final byte[] expected = new byte[] {1, 2, 3, 4}; + Os.write(fd, expected, 0, expected.length); + stat = Os.fstat(fd); + assertEquals(expected.length, stat.st_size); + + byte[] actual = new byte[expected.length]; + // should be seekable + Os.lseek(fd, 0, SEEK_SET); + Os.read(fd, actual, 0, actual.length); + assertArrayEquals(expected, actual); + } finally { + if (fd != null) { + Os.close(fd); + fd = null; + } + } + } + + public void testMemfdCreateFlags() throws Exception { + FileDescriptor fd = null; + + // test that MFD_CLOEXEC is obeyed + try { + fd = Os.memfd_create("test_memfd", 0); + assertNotNull(fd); + assertTrue(fd.valid()); + int flags = Os.fcntlVoid(fd, F_GETFD); + assertTrue("Expected flags to not include " + FD_CLOEXEC + ", actual value: " + flags, + 0 == (flags & FD_CLOEXEC)); + } finally { + if (fd != null) { + Os.close(fd); + fd = null; + } + } + try { + fd = Os.memfd_create("test_memfd", MFD_CLOEXEC); + assertNotNull(fd); + assertTrue(fd.valid()); + int flags = Os.fcntlVoid(fd, F_GETFD); + assertTrue("Expected flags to include " + FD_CLOEXEC + ", actual value: " + flags, + 0 != (flags & FD_CLOEXEC)); + } finally { + if (fd != null) { + Os.close(fd); + fd = null; + } + } + } + + public void testMemfdCreateErrno() throws Exception { + expectException(() -> Os.memfd_create(null, 0), NullPointerException.class, null, + "memfd_create(null, 0)"); + + expectException(() -> Os.memfd_create("test_memfd", 0xffff), ErrnoException.class, EINVAL, + "memfd_create(\"test_memfd\", 0xffff)"); + } } diff --git a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java index 17f031be2a..218678ee56 100644 --- a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java +++ b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java @@ -226,6 +226,7 @@ public class BlockGuardOsTest { "kill(int,int)", "listen(java.io.FileDescriptor,int)", "listxattr(java.lang.String)", + "memfd_create(java.lang.String,int)", "mincore(long,long,byte[])", "mlock(long,long)", "mmap(long,long,int,int,java.io.FileDescriptor,long)", |