$OpenBSD: patch-jdk_src_solaris_native_sun_nio_fs_BsdNativeDispatcher_c,v 1.1 2009/06/10 19:01:09 kurt Exp $
--- jdk/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c.orig	Tue Jun  2 13:44:48 2009
+++ jdk/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c	Wed Jun  3 16:14:03 2009
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,23 +28,35 @@
 #include "jvm.h"
 #include "jlong.h"
 
-#include <stdio.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <mntent.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#ifdef ST_RDONLY
+#define statfs statvfs
+#define getfsstat getvfsstat
+#define f_flags f_flag
+#define ISREADONLY ST_RDONLY
+#else
+#define ISREADONLY MNT_RDONLY
+#endif
 
-#include "sun_nio_fs_BsdNativeDispatcher.h"
+#include <stdlib.h>
+#include <string.h>
 
-typedef size_t fgetxattr_func(int fd, const char* name, void* value, size_t size);
-typedef int fsetxattr_func(int fd, const char* name, void* value, size_t size, int flags);
-typedef int fremovexattr_func(int fd, const char* name);
-typedef int flistxattr_func(int fd, char* list, size_t size);
+static jfieldID entry_name;
+static jfieldID entry_dir;
+static jfieldID entry_fstype;
+static jfieldID entry_options;
+static jfieldID entry_dev;
 
-fgetxattr_func* my_fgetxattr_func = NULL;
-fsetxattr_func* my_fsetxattr_func = NULL;
-fremovexattr_func* my_fremovexattr_func = NULL;
-flistxattr_func* my_flistxattr_func = NULL;
 
+struct fsstat_iter {
+    struct statfs *buf;
+    int pos;
+    int nentries;
+};
+
+#include "sun_nio_fs_BsdNativeDispatcher.h"
+
 static void throwUnixException(JNIEnv* env, int errnum) {
     jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
         "(I)V", errnum);
@@ -53,108 +65,146 @@ static void throwUnixException(JNIEnv* env, int errnum
     }
 }
 
+/**
+ * Initialize jfieldIDs
+ */
 JNIEXPORT void JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_init(JNIEnv *env, jclass clazz)
+Java_sun_nio_fs_BsdNativeDispatcher_initIDs(JNIEnv* env, jclass this)
 {
-    my_fgetxattr_func = (fgetxattr_func*)dlsym(RTLD_DEFAULT, "fgetxattr");
-    my_fsetxattr_func = (fsetxattr_func*)dlsym(RTLD_DEFAULT, "fsetxattr");
-    my_fremovexattr_func = (fremovexattr_func*)dlsym(RTLD_DEFAULT, "fremovexattr");
-    my_flistxattr_func = (flistxattr_func*)dlsym(RTLD_DEFAULT, "flistxattr");
-}
+    jclass clazz;
 
-JNIEXPORT jint JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz,
-    jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
-{
-    size_t res = -1;
-    const char* name = jlong_to_ptr(nameAddress);
-    void* value = jlong_to_ptr(valueAddress);
-
-    if (my_fgetxattr_func == NULL) {
-        errno = ENOTSUP;
-    } else {
-        /* EINTR not documented */
-        res = (*my_fgetxattr_func)(fd, name, value, valueLen);
+    clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
+    if (clazz == NULL) {
+        return;
     }
-    if (res == (size_t)-1)
-        throwUnixException(env, errno);
-    return (jint)res;
+    entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
+    entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
+    entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
+    entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
+    entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
 }
 
-JNIEXPORT void JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz,
-    jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
+JNIEXPORT jlong JNICALL
+Java_sun_nio_fs_BsdNativeDispatcher_getfsstat(JNIEnv* env, jclass this)
 {
-    int res = -1;
-    const char* name = jlong_to_ptr(nameAddress);
-    void* value = jlong_to_ptr(valueAddress);
+    int nentries;
+    size_t bufsize;
+    struct fsstat_iter *iter = malloc(sizeof(*iter));
 
-    if (my_fsetxattr_func == NULL) {
-        errno = ENOTSUP;
-    } else {
-        /* EINTR not documented */
-        res = (*my_fsetxattr_func)(fd, name, value, valueLen, 0);
+    if (iter == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "native heap");
+        return 0;
     }
-    if (res == -1)
+
+    iter->pos = 0;
+    iter->nentries = 0;
+    iter->buf = NULL;
+
+    nentries = getfsstat(NULL, 0, MNT_NOWAIT);
+
+    if (nentries <= 0) {
+        free(iter);
         throwUnixException(env, errno);
-}
+        return 0;
+    }
 
-JNIEXPORT void JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz,
-    jint fd, jlong nameAddress)
-{
-    int res = -1;
-    const char* name = jlong_to_ptr(nameAddress);
+    // It's possible that a new filesystem gets mounted between
+    // the first getfsstat and the second so loop until consistant
 
-    if (my_fremovexattr_func == NULL) {
-        errno = ENOTSUP;
-    } else {
-        /* EINTR not documented */
-        res = (*my_fremovexattr_func)(fd, name);
+    while (nentries != iter->nentries) {
+        if (iter->buf != NULL)
+            free(iter->buf);
+
+        bufsize = nentries * sizeof(struct statfs);
+        iter->nentries = nentries;
+
+        iter->buf = malloc(bufsize);
+        if (iter->buf == NULL) {
+            free(iter);
+            JNU_ThrowOutOfMemoryError(env, "native heap");
+            return 0;
+        }
+
+        nentries = getfsstat(iter->buf, bufsize, MNT_WAIT);
+        if (nentries <= 0) {
+            free(iter->buf);
+            free(iter);
+            throwUnixException(env, errno);
+            return 0;
+        }
     }
-    if (res == -1)
-        throwUnixException(env, errno);
+
+    return (jlong)iter;
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz,
-    jint fd, jlong listAddress, jint size)
+Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry(JNIEnv* env, jclass this,
+    jlong value, jobject entry)
 {
-    size_t res = -1;
-    char* list = jlong_to_ptr(listAddress);
+    struct fsstat_iter *iter = jlong_to_ptr(value);
+    jsize len;
+    jbyteArray bytes;
+    char* name;
+    char* dir;
+    char* fstype;
+    char* options;
+    dev_t dev;
 
-    if (my_flistxattr_func == NULL) {
-        errno = ENOTSUP;
-    } else {
-        /* EINTR not documented */
-        res = (*my_flistxattr_func)(fd, list, (size_t)size);
-    }
-    if (res == (size_t)-1)
-        throwUnixException(env, errno);
-    return (jint)res;
-}
+    if (iter == NULL || iter->pos >= iter->nentries)
+       return -1;
 
-JNIEXPORT jlong JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_setmntent0(JNIEnv* env, jclass this, jlong pathAddress,
-                                                 jlong modeAddress)
-{
-    FILE* fp = NULL;
-    const char* path = (const char*)jlong_to_ptr(pathAddress);
-    const char* mode = (const char*)jlong_to_ptr(modeAddress);
+    name = iter->buf[iter->pos].f_mntfromname;
+    dir = iter->buf[iter->pos].f_mntonname;
+    fstype = iter->buf[iter->pos].f_fstypename;
+    if (iter->buf[iter->pos].f_flags & ISREADONLY)
+        options="ro";
+    else
+        options="";
+    dev = 0;
 
-    do {
-        fp = setmntent(path, mode);
-    } while (fp == NULL && errno == EINTR);
-    if (fp == NULL) {
-        throwUnixException(env, errno);
-    }
-    return ptr_to_jlong(fp);
+    iter->pos++;
+
+    len = strlen(name);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
+    (*env)->SetObjectField(env, entry, entry_name, bytes);
+
+    len = strlen(dir);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
+    (*env)->SetObjectField(env, entry, entry_dir, bytes);
+
+    len = strlen(fstype);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
+    (*env)->SetObjectField(env, entry, entry_fstype, bytes);
+
+    len = strlen(options);
+    bytes = (*env)->NewByteArray(env, len);
+    if (bytes == NULL)
+        return -1;
+    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
+    (*env)->SetObjectField(env, entry, entry_options, bytes);
+
+    if (dev != 0)
+        (*env)->SetLongField(env, entry, entry_dev, (jlong)dev);
+
+    return 0;
 }
 
 JNIEXPORT void JNICALL
-Java_sun_nio_fs_BsdNativeDispatcher_endmntent(JNIEnv* env, jclass this, jlong stream)
+Java_sun_nio_fs_BsdNativeDispatcher_endfsstat(JNIEnv* env, jclass this, jlong value)
 {
-    FILE* fp = jlong_to_ptr(stream);
-    /* FIXME - man page doesn't explain how errors are returned */
-    endmntent(fp);
+    struct fsstat_iter *iter = jlong_to_ptr(value);
+
+    if (iter != NULL) {
+        free(iter->buf);
+        free(iter);
+    }
 }
