chiark / gitweb /
rough work in progress; may not build
[tripe-android] / jni.c
diff --git a/jni.c b/jni.c
index fd91d0c4ec40b335ecd80de510e80a0dcfbcf5a3..f65e464c7a883d42141ea3b920bc62c8340494c6 100644 (file)
--- a/jni.c
+++ b/jni.c
 /*----- Magic class names and similar -------------------------------------*/
 
 /* The name decoration is horrific.  Hide it. */
-#define JNIFUNC(f) Java_uk_org_distorted_tripe_jni_package_00024_##f
+#define JNIFUNC(f) Java_uk_org_distorted_tripe_sys_package_00024_##f
 
 /* The little class for bundling up error codes. */
-#define ERRENTRY "uk/org/distorted/tripe/jni/package$ErrorEntry"
+#define ERRENTRY "uk/org/distorted/tripe/sys/package$ErrorEntry"
 
 /* The `stat' class. */
-#define STAT "uk/org/distorted/tripe/jni/package$FileInfo"
+#define STAT "uk/org/distorted/tripe/sys/package$FileInfo"
 
 /* Exception class names. */
 #define NULLERR "java/lang/NullPointerException"
-#define TYPEERR "uk/org/distorted/tripe/jni/package$NativeObjectTypeException"
+#define TYPEERR "uk/org/distorted/tripe/sys/package$NativeObjectTypeException"
 #define SYSERR "uk/org/distorted/tripe/sys/package$SystemError"
 #define ARGERR "java/lang/IllegalArgumentException"
 #define BOUNDSERR "java/lang/IndexOutOfBoundsException"
@@ -80,7 +80,7 @@ static void put_cstring(JNIEnv *jni, jbyteArray v, const char *p)
   { if (p) (*jni)->ReleaseByteArrayElements(jni, v, (jbyte *)p, JNI_ABORT); }
 
 static void vexcept(JNIEnv *jni, const char *clsname,
-                   const char *msg, va_list ap)
+                   const char *msg, va_list *ap)
 {
   jclass cls;
   int rc;
@@ -90,7 +90,7 @@ static void vexcept(JNIEnv *jni, const char *clsname,
   if (!msg)
     rc = (*jni)->ThrowNew(jni, cls, 0);
   else {
-    dstr_vputf(&d, msg, &ap);
+    dstr_vputf(&d, msg, ap);
     rc = (*jni)->ThrowNew(jni, cls, d.buf);
     assert(!rc);
     dstr_destroy(&d);
@@ -103,7 +103,7 @@ static void except(JNIEnv *jni, const char *clsname, const char *msg, ...)
   va_list ap;
 
   va_start(ap, msg);
-  vexcept(jni, clsname, msg, ap);
+  vexcept(jni, clsname, msg, &ap);
   va_end(ap);
 }
 
@@ -164,7 +164,7 @@ static const char *get_cstring(JNIEnv *jni, jbyteArray v)
 }
 
 static void vexcept_syserror(JNIEnv *jni, const char *clsname,
-                            int err, const char *msg, va_list ap)
+                            int err, const char *msg, va_list *ap)
 {
   jclass cls;
   int rc;
@@ -175,7 +175,7 @@ static void vexcept_syserror(JNIEnv *jni, const char *clsname,
 
   cls = (*jni)->FindClass(jni, clsname); assert(cls);
   init = (*jni)->GetMethodID(jni, cls, "<init>", "(I[B)V"); assert(init);
-  dstr_vputf(&d, msg, &ap);
+  dstr_vputf(&d, msg, ap);
   msgstr = wrap_cstring(jni, d.buf); assert(msgstr);
   dstr_destroy(&d);
   e = (*jni)->NewObject(jni, cls, init, err, msgstr); assert(e);
@@ -188,7 +188,7 @@ static void except_syserror(JNIEnv *jni, const char *clsname,
   va_list ap;
 
   va_start(ap, msg);
-  vexcept_syserror(jni, clsname, err, msg, ap);
+  vexcept_syserror(jni, clsname, err, msg, &ap);
   va_end(ap);
 }
 
@@ -319,17 +319,17 @@ static const struct errtab { const char *tag; int err; } errtab[] = {
                     ECANCELED ENOKEY EKEYEXPIRED EKEYREVOKED EKEYREJECTED
                     EOWNERDEAD ENOTRECOVERABLE ERFKILL EHWPOISON)))
        (save-excursion
-         (goto-char (point-min))
-         (search-forward (concat "***" "BEGIN errtab" "***"))
-         (beginning-of-line 2)
-         (delete-region (point)
-                        (progn
-                          (search-forward "***END***")
-                          (beginning-of-line)
-                          (point)))
-         (dolist (err errors)
-           (insert (format "#ifdef %s\n  { \"%s\", %s },\n#endif\n"
-                           err err err)))))
+        (goto-char (point-min))
+        (search-forward (concat "***" "BEGIN errtab" "***"))
+        (beginning-of-line 2)
+        (delete-region (point)
+                       (progn
+                         (search-forward "***END***")
+                         (beginning-of-line)
+                         (point)))
+        (dolist (err errors)
+          (insert (format "#ifdef %s\n  { \"%s\", %s },\n#endif\n"
+                          err err err)))))
   */
   /***BEGIN errtab***/
 #ifdef EPERM
@@ -762,6 +762,48 @@ JNIEXPORT jobject JNIFUNC(errtab)(JNIEnv *jni, jobject cls)
 JNIEXPORT jobject JNIFUNC(strerror)(JNIEnv *jni, jobject cls, jint err)
   { return (wrap_cstring(jni, strerror(err))); }
 
+/*----- Messing with file descriptors -------------------------------------*/
+
+static void fdguts(JNIEnv *jni, jclass *cls, jfieldID *fid)
+{
+  *cls = (*jni)->FindClass(jni, "java/io/FileDescriptor"); assert(cls);
+  *fid = (*jni)->GetFieldID(jni, *cls, "fd", "I"); // OpenJDK
+  if (!*fid) *fid = (*jni)->GetFieldID(jni, *cls, "descriptor", "I"); // Android
+  assert(*fid);
+}
+
+static int fdint(JNIEnv *jni, jobject jfd)
+{
+  jclass cls;
+  jfieldID fid;
+
+  fdguts(jni, &cls, &fid);
+  return ((*jni)->GetIntField(jni, jfd, fid));
+}
+
+static jobject newfd(JNIEnv *jni, int fd)
+{
+  jobject jfd;
+  jclass cls;
+  jmethodID init;
+  jfieldID fid;
+
+  fdguts(jni, &cls, &fid);
+  init = (*jni)->GetMethodID(jni, cls, "<init>", "()V"); assert(init);
+  jfd = (*jni)->NewObject(jni, cls, init);
+  (*jni)->SetIntField(jni, jfd, fid, fd);
+  return (jfd);
+}
+
+JNIEXPORT jint JNIFUNC(fdint)(JNIEnv *jni, jobject cls, jobject jfd)
+  { return (fdint(jni, jfd)); }
+
+JNIEXPORT jobject JNIFUNC(newfd)(JNIEnv *jni, jobject cls, jint fd)
+  { return (newfd(jni, fd)); }
+
+JNIEXPORT jboolean JNIFUNC(isatty)(JNIEnv *jni, jobject cls, jobject jfd)
+  { return (isatty(fdint(jni, jfd))); }
+
 /*----- Low-level file operations -----------------------------------------*/
 
 /* Java has these already, as methods on `java.io.File' objects.  Alas, these
@@ -853,8 +895,8 @@ end:
   put_cstring(jni, to, tostr);
 }
 
-#define LKF_EXCL 1u
-#define LKF_WAIT 2u
+#define LKF_EXCL 0x1000u
+#define LKF_WAIT 0x2000u
 struct lockf {
   struct native_base _base;
   int fd;
@@ -875,7 +917,7 @@ JNIEXPORT wrapper JNIFUNC(lock)(JNIEnv *jni, jobject cls,
   pathstr = get_cstring(jni, path); if (!pathstr) goto end;
 
 again:
-  fd = open(pathstr, O_RDWR | O_CREAT); if (fd < 0) goto err;
+  fd = open(pathstr, O_RDWR | O_CREAT, flags&07777); if (fd < 0) goto err;
   if (fstat(fd, &st0)) goto err;
   f = fcntl(fd, F_GETFD); if (f < 0) goto err;
   if (fcntl(fd, F_SETFD, f | FD_CLOEXEC)) goto err;
@@ -927,7 +969,7 @@ static jobject xltstat(JNIEnv *jni, const struct stat *st)
   jclass cls;
   jmethodID init;
   jint modehack;
+
   modehack = st->st_mode&07777;
   if (S_ISFIFO(st->st_mode)) modehack |= 0010000;
   else if (S_ISCHR(st->st_mode)) modehack |= 0020000;
@@ -1193,8 +1235,8 @@ end:
   return (rc);
 }
 
-JNIEXPORT void JNICALL JNIFUNC(close)(JNIEnv *jni, jobject cls,
-                                     wrapper wconn, jint how)
+JNIEXPORT void JNICALL JNIFUNC(closeconn)(JNIEnv *jni, jobject cls,
+                                         wrapper wconn, jint how)
 {
   struct conn conn;
   int rc;