Expose the portable "strerror_r" used by jniThrowIOException.
Also add one example caller I used to test this, and update the
libnativehelper README file.
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.cpp b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
index 7d27056..abc6e16 100644
--- a/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
+++ b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
@@ -75,7 +75,9 @@
}
static void jniThrowSocketException(JNIEnv* env) {
- jniThrowException(env, "java/net/SocketException", strerror(errno));
+ char buf[BUFSIZ];
+ jniThrowException(env, "java/net/SocketException",
+ jniStrError(errno, buf, sizeof(buf)));
}
// Creates an InetAddress[] of size 'addressCount' from the ifc_req structs
diff --git a/libnativehelper/JNIHelp.c b/libnativehelper/JNIHelp.c
index aacecb6..fa6b532 100644
--- a/libnativehelper/JNIHelp.c
+++ b/libnativehelper/JNIHelp.c
@@ -59,30 +59,30 @@
*/
int jniThrowIOException(JNIEnv* env, int errnum)
{
- // note: glibc has a nonstandard
- // strerror_r that looks like this:
- // char *strerror_r(int errnum, char *buf, size_t n);
-
- const char* message;
char buffer[80];
- char* ret;
-
- buffer[0] = 0;
- ret = (char*) strerror_r(errnum, buffer, sizeof(buffer));
-
- if (((int)ret) == 0) {
- //POSIX strerror_r, success
- message = buffer;
- } else if (((int)ret) == -1) {
- //POSIX strerror_r, failure
-
- snprintf (buffer, sizeof(buffer), "errno %d", errnum);
- message = buffer;
- } else {
- //glibc strerror_r returning a string
- message = ret;
- }
-
+ const char* message = jniStrError(errnum, buffer, sizeof(buffer));
return jniThrowException(env, "java/io/IOException", message);
}
+const char* jniStrError(int errnum, char* buf, size_t buflen)
+{
+ // note: glibc has a nonstandard strerror_r that returns char* rather
+ // than POSIX's int.
+ // char *strerror_r(int errnum, char *buf, size_t n);
+ char* ret = (char*) strerror_r(errnum, buf, buflen);
+ if (((int)ret) == 0) {
+ //POSIX strerror_r, success
+ return buf;
+ } else if (((int)ret) == -1) {
+ //POSIX strerror_r, failure
+ // (Strictly, POSIX only guarantees a value other than 0. The safest
+ // way to implement this function is to use C++ and overload on the
+ // type of strerror_r to accurately distinguish GNU from POSIX. But
+ // realistic implementations will always return -1.)
+ snprintf(buf, buflen, "errno %d", errnum);
+ return buf;
+ } else {
+ //glibc strerror_r returning a string
+ return ret;
+ }
+}
diff --git a/libnativehelper/README b/libnativehelper/README
index 56ec178..fa757c0 100644
--- a/libnativehelper/README
+++ b/libnativehelper/README
@@ -4,10 +4,9 @@
These are VM-agnostic native functions that implement methods for system
class libraries. All code here:
- - MUST be associated with a standard java.* class (no Android-specific stuff)
- - MUST use JNI
- - SHOULD be written in C rather than C++ (it's usually smaller and all of
- our VMs are written in C)
+ - MUST not be associated with an android.* class (that code lives in
+ frameworks/base/).
+ - SHOULD be written in C rather than C++ where possible.
-Some helper functions are defined in ../include/nativehelper/JNIHelp.h.
+Some helper functions are defined in include/nativehelper/JNIHelp.h.
diff --git a/libnativehelper/include/nativehelper/JNIHelp.h b/libnativehelper/include/nativehelper/JNIHelp.h
index 3982797..1e268f8 100644
--- a/libnativehelper/include/nativehelper/JNIHelp.h
+++ b/libnativehelper/include/nativehelper/JNIHelp.h
@@ -58,6 +58,14 @@
int jniThrowIOException(C_JNIEnv* env, int errnum);
/*
+ * Return a pointer to a locale-dependent error string explaining errno
+ * value 'errnum'. The returned pointer may or may not be equal to 'buf'.
+ * This function is thread-safe (unlike strerror) and portable (unlike
+ * strerror_r).
+ */
+const char* jniStrError(int errnum, char* buf, size_t buflen);
+
+/*
* Create a java.io.FileDescriptor given an integer fd
*/
jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd);