diff options
author | Jeff Sharkey <jsharkey@android.com> | 2015-07-02 12:04:00 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2015-07-02 13:03:14 -0700 |
commit | 82d076b51f6fe7c1cbd1f37414be36eaaa9b0e56 (patch) | |
tree | 117517ea17821d4134f5b7cdd76d1e0d3d82cbeb /luni | |
parent | 505fb9201a6624009659b6083949c9e5428def11 (diff) | |
download | libcore-82d076b51f6fe7c1cbd1f37414be36eaaa9b0e56.zip libcore-82d076b51f6fe7c1cbd1f37414be36eaaa9b0e56.tar.gz libcore-82d076b51f6fe7c1cbd1f37414be36eaaa9b0e56.tar.bz2 |
Add getxattr/setxattr/removexattr syscalls.
Bug: 20275572
Change-Id: I958056f757f095ad6278624e293a5583d9cee822
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/main/java/android/system/Os.java | 6 | ||||
-rw-r--r-- | luni/src/main/java/android/system/OsConstants.java | 2 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/ForwardingOs.java | 3 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Os.java | 3 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Posix.java | 3 | ||||
-rw-r--r-- | luni/src/main/native/android_system_OsConstants.cpp | 3 | ||||
-rw-r--r-- | luni/src/main/native/libcore_io_Posix.cpp | 63 | ||||
-rw-r--r-- | luni/src/test/java/libcore/io/OsTest.java | 56 |
8 files changed, 139 insertions, 0 deletions
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java index fcecf18..a1e87c8 100644 --- a/luni/src/main/java/android/system/Os.java +++ b/luni/src/main/java/android/system/Os.java @@ -215,6 +215,8 @@ public final class Os { */ public static int getuid() { return Libcore.os.getuid(); } + /** @hide */ public static int getxattr(String path, String name, byte[] outValue) throws ErrnoException { return Libcore.os.getxattr(path, name, outValue); } + /** * See <a href="http://man7.org/linux/man-pages/man3/if_indextoname.3.html">if_indextoname(3)</a>. */ @@ -389,6 +391,8 @@ public final class Os { */ public static void remove(String path) throws ErrnoException { Libcore.os.remove(path); } + /** @hide */ public static void removexattr(String path, String name) throws ErrnoException { Libcore.os.removexattr(path, name); } + /** * See <a href="http://man7.org/linux/man-pages/man2/rename.2.html">rename(2)</a>. */ @@ -468,6 +472,8 @@ public final class Os { */ public static void setuid(int uid) throws ErrnoException { Libcore.os.setuid(uid); } + /** @hide */ public static void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException { Libcore.os.setxattr(path, name, value, flags); }; + /** * See <a href="http://man7.org/linux/man-pages/man2/shutdown.2.html">shutdown(2)</a>. */ diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java index dd6301b..8832f3d 100644 --- a/luni/src/main/java/android/system/OsConstants.java +++ b/luni/src/main/java/android/system/OsConstants.java @@ -496,6 +496,8 @@ public final class OsConstants { public static final int WSTOPPED = placeholder(); public static final int WUNTRACED = placeholder(); public static final int W_OK = placeholder(); + /** @hide */ public static final int XATTR_CREATE = placeholder(); + /** @hide */ public static final int XATTR_REPLACE = placeholder(); public static final int X_OK = placeholder(); public static final int _SC_2_CHAR_TERM = placeholder(); public static final int _SC_2_C_BIND = placeholder(); diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index 5c0c8fd..cb77573 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -96,6 +96,7 @@ public class ForwardingOs implements Os { public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptUcred(fd, level, option); } public int gettid() { return os.gettid(); } public int getuid() { return os.getuid(); } + public int getxattr(String path, String name, byte[] outValue) throws ErrnoException { return os.getxattr(path, name, outValue); } public String if_indextoname(int index) { return os.if_indextoname(index); } public InetAddress inet_pton(int family, String address) { return os.inet_pton(family, address); } public InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException { return os.ioctlInetAddress(fd, cmd, interfaceName); } @@ -131,6 +132,7 @@ public class ForwardingOs implements Os { public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { return os.recvfrom(fd, buffer, flags, srcAddress); } public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { return os.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress); } public void remove(String path) throws ErrnoException { os.remove(path); } + public void removexattr(String path, String name) throws ErrnoException { os.removexattr(path, name); } public void rename(String oldPath, String newPath) throws ErrnoException { os.rename(oldPath, newPath); } public long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException { return os.sendfile(outFd, inFd, inOffset, byteCount); } public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { return os.sendto(fd, buffer, flags, inetAddress, port); } @@ -153,6 +155,7 @@ public class ForwardingOs implements Os { public void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException { os.setsockoptLinger(fd, level, option, value); } public void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException { os.setsockoptTimeval(fd, level, option, value); } public void setuid(int uid) throws ErrnoException { os.setuid(uid); } + public void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException { os.setxattr(path, name, value, flags); } public void shutdown(FileDescriptor fd, int how) throws ErrnoException { os.shutdown(fd, how); } public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException { return os.socket(domain, type, protocol); } public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException { os.socketpair(domain, type, protocol, fd1, fd2); } diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index 987d331..6d28b95 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -88,6 +88,7 @@ public interface Os { public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException; public int gettid(); public int getuid(); + public int getxattr(String path, String name, byte[] outValue) throws ErrnoException; public String if_indextoname(int index); public InetAddress inet_pton(int family, String address); public InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException; @@ -124,6 +125,7 @@ public interface Os { public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException; public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException; public void remove(String path) throws ErrnoException; + public void removexattr(String path, String name) throws ErrnoException; public void rename(String oldPath, String newPath) throws ErrnoException; public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException; public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException; @@ -146,6 +148,7 @@ public interface Os { public void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException; public void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException; public void setuid(int uid) throws ErrnoException; + public void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException; public void shutdown(FileDescriptor fd, int how) throws ErrnoException; public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException; public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index d680200..151809d 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -90,6 +90,7 @@ public final class Posix implements Os { public native StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException; public native int gettid(); public native int getuid(); + public native int getxattr(String path, String name, byte[] outValue) throws ErrnoException; public native String if_indextoname(int index); public native InetAddress inet_pton(int family, String address); public native InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException; @@ -189,6 +190,7 @@ public final class Posix implements Os { } private native int recvfromBytes(FileDescriptor fd, Object buffer, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException; public native void remove(String path) throws ErrnoException; + public native void removexattr(String path, String name) throws ErrnoException; public native void rename(String oldPath, String newPath) throws ErrnoException; public native long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException; public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { @@ -230,6 +232,7 @@ public final class Posix implements Os { public native void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException; public native void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException; public native void setuid(int uid) throws ErrnoException; + public native void setxattr(String path, String name, byte[] value, int flags) throws ErrnoException; public native void shutdown(FileDescriptor fd, int how) throws ErrnoException; public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException; public native void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException; diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp index a44d176..a11ea76 100644 --- a/luni/src/main/native/android_system_OsConstants.cpp +++ b/luni/src/main/native/android_system_OsConstants.cpp @@ -36,6 +36,7 @@ #include <sys/socket.h> #include <sys/stat.h> #include <sys/wait.h> +#include <sys/xattr.h> #include <unistd.h> #include <net/if_arp.h> @@ -556,6 +557,8 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "WSTOPPED", WSTOPPED); initConstant(env, c, "WUNTRACED", WUNTRACED); initConstant(env, c, "W_OK", W_OK); + initConstant(env, c, "XATTR_CREATE", XATTR_CREATE); + initConstant(env, c, "XATTR_REPLACE", XATTR_REPLACE); initConstant(env, c, "X_OK", X_OK); initConstant(env, c, "_SC_2_CHAR_TERM", _SC_2_CHAR_TERM); initConstant(env, c, "_SC_2_C_BIND", _SC_2_C_BIND); diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index f6af483..99b76f9 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -59,6 +59,7 @@ #include <sys/uio.h> #include <sys/utsname.h> #include <sys/wait.h> +#include <sys/xattr.h> #include <termios.h> #include <unistd.h> #include <memory> @@ -1061,6 +1062,28 @@ static jint Posix_getuid(JNIEnv*, jobject) { return getuid(); } +static jint Posix_getxattr(JNIEnv* env, jobject, jstring javaPath, + jstring javaName, jbyteArray javaOutValue) { + ScopedUtfChars path(env, javaPath); + if (path.c_str() == NULL) { + return -1; + } + ScopedUtfChars name(env, javaName); + if (name.c_str() == NULL) { + return -1; + } + ScopedBytesRW outValue(env, javaOutValue); + if (outValue.get() == NULL) { + return -1; + } + size_t outValueLength = env->GetArrayLength(javaOutValue); + ssize_t size = getxattr(path.c_str(), name.c_str(), outValue.get(), outValueLength); + if (size < 0) { + throwErrnoException(env, "getxattr"); + } + return size; +} + static jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) { char buf[IF_NAMESIZE]; char* name = if_indextoname(index, buf); @@ -1424,6 +1447,22 @@ static void Posix_remove(JNIEnv* env, jobject, jstring javaPath) { throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str()))); } +static void Posix_removexattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName) { + ScopedUtfChars path(env, javaPath); + if (path.c_str() == NULL) { + return; + } + ScopedUtfChars name(env, javaName); + if (name.c_str() == NULL) { + return; + } + + int res = removexattr(path.c_str(), name.c_str()); + if (res < 0) { + throwErrnoException(env, "removexattr"); + } +} + static void Posix_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) { ScopedUtfChars oldPath(env, javaOldPath); if (oldPath.c_str() == NULL) { @@ -1664,6 +1703,27 @@ static void Posix_setuid(JNIEnv* env, jobject, jint uid) { throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid))); } +static void Posix_setxattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName, + jbyteArray javaValue, jint flags) { + ScopedUtfChars path(env, javaPath); + if (path.c_str() == NULL) { + return; + } + ScopedUtfChars name(env, javaName); + if (name.c_str() == NULL) { + return; + } + ScopedBytesRO value(env, javaValue); + if (value.get() == NULL) { + return; + } + size_t valueLength = env->GetArrayLength(javaValue); + int res = setxattr(path.c_str(), name.c_str(), value.get(), valueLength, flags); + if (res < 0) { + throwErrnoException(env, "setxattr"); + } +} + static void Posix_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) { int fd = jniGetFDFromFileDescriptor(env, javaFd); throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how))); @@ -1842,6 +1902,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;"), NATIVE_METHOD(Posix, gettid, "()I"), NATIVE_METHOD(Posix, getuid, "()I"), + NATIVE_METHOD(Posix, getxattr, "(Ljava/lang/String;Ljava/lang/String;[B)I"), NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"), NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"), NATIVE_METHOD(Posix, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"), @@ -1873,6 +1934,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"), NATIVE_METHOD(Posix, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"), NATIVE_METHOD(Posix, remove, "(Ljava/lang/String;)V"), + NATIVE_METHOD(Posix, removexattr, "(Ljava/lang/String;Ljava/lang/String;)V"), NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"), NATIVE_METHOD(Posix, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Landroid/util/MutableLong;J)J"), NATIVE_METHOD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"), @@ -1894,6 +1956,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, setsockoptLinger, "(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V"), NATIVE_METHOD(Posix, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V"), NATIVE_METHOD(Posix, setuid, "(I)V"), + NATIVE_METHOD(Posix, setxattr, "(Ljava/lang/String;Ljava/lang/String;[BI)V"), NATIVE_METHOD(Posix, shutdown, "(Ljava/io/FileDescriptor;I)V"), NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"), NATIVE_METHOD(Posix, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"), diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java index e648e8a..9b38ee9 100644 --- a/luni/src/test/java/libcore/io/OsTest.java +++ b/luni/src/test/java/libcore/io/OsTest.java @@ -18,6 +18,7 @@ package libcore.io; import android.system.ErrnoException; import android.system.NetlinkSocketAddress; +import android.system.OsConstants; import android.system.PacketSocketAddress; import android.system.StructTimeval; import android.system.StructUcred; @@ -419,4 +420,59 @@ public class OsTest extends TestCase { checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, true); checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false); } + + private static void assertPartial(byte[] expected, byte[] actual) { + for (int i = 0; i < expected.length; i++) { + if (expected[i] != actual[i]) { + fail("Expected " + Arrays.toString(expected) + " but found " + + Arrays.toString(actual)); + } + } + } + + public void test_xattr() throws Exception { + final String NAME_TEST = "user.meow"; + + final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8); + final byte[] VALUE_PIE = "pie".getBytes(StandardCharsets.UTF_8); + + File file = File.createTempFile("xattr", "test"); + String path = file.getAbsolutePath(); + + byte[] tmp = new byte[1024]; + try { + try { + Libcore.os.getxattr(path, NAME_TEST, tmp); + fail("Expected ENODATA"); + } catch (ErrnoException e) { + assertEquals(OsConstants.ENODATA, e.errno); + } + + Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); + assertEquals(VALUE_CAKE.length, Libcore.os.getxattr(path, NAME_TEST, tmp)); + assertPartial(VALUE_CAKE, tmp); + + try { + Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_CREATE); + fail("Expected EEXIST"); + } catch (ErrnoException e) { + assertEquals(OsConstants.EEXIST, e.errno); + } + + Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_REPLACE); + assertEquals(VALUE_PIE.length, Libcore.os.getxattr(path, NAME_TEST, tmp)); + assertPartial(VALUE_PIE, tmp); + + Libcore.os.removexattr(path, NAME_TEST); + try { + Libcore.os.getxattr(path, NAME_TEST, tmp); + fail("Expected ENODATA"); + } catch (ErrnoException e) { + assertEquals(OsConstants.ENODATA, e.errno); + } + + } finally { + file.delete(); + } + } } |