changeset 1260:d77f928a7e03

Implement BsdFileSystem.getMountEntries() using getfsstat(2) which is available on all BSD's and Apple.
author kurt
date Wed, 27 May 2009 08:52:21 -0400
parents c261bf3f5df2
children 308af07c8341
files make/java/nio/Makefile make/java/nio/mapfile-bsd src/solaris/classes/sun/nio/fs/BsdFileSystem.java src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c
diffstat 5 files changed, 277 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/nio/Makefile	Wed May 27 08:47:16 2009 -0400
+++ b/make/java/nio/Makefile	Wed May 27 08:52:21 2009 -0400
@@ -275,6 +275,7 @@
 	sun/nio/fs/BsdFileStore.java \
 	sun/nio/fs/BsdFileSystem.java \
 	sun/nio/fs/BsdFileSystemProvider.java \
+	sun/nio/fs/BsdNativeDispatcher.java \
 	sun/nio/fs/PollingWatchService.java \
 	sun/nio/fs/UnixChannelFactory.java \
 	sun/nio/fs/UnixCopyFile.java \
@@ -303,6 +304,7 @@
 	UnixAsynchronousSocketChannelImpl.c \
 	\
 	GnomeFileTypeDetector.c \
+	BsdNativeDispatcher.c \
 	UnixCopyFile.c \
 	UnixNativeDispatcher.c
 
@@ -313,6 +315,7 @@
 	sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \
 	\
 	sun/nio/fs/GnomeFileTypeDetector.java \
+	sun/nio/fs/BsdNativeDispatcher.java \
 	sun/nio/fs/UnixCopyFile.java \
 	sun/nio/fs/UnixNativeDispatcher.java
 	
--- a/make/java/nio/mapfile-bsd	Wed May 27 08:47:16 2009 -0400
+++ b/make/java/nio/mapfile-bsd	Wed May 27 08:52:21 2009 -0400
@@ -103,6 +103,10 @@
 		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
 		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
 		Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
+		Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
+		Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
+		Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
+		Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
 		Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio;
 		Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio;
 		Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs;
--- a/src/solaris/classes/sun/nio/fs/BsdFileSystem.java	Wed May 27 08:47:16 2009 -0400
+++ b/src/solaris/classes/sun/nio/fs/BsdFileSystem.java	Wed May 27 08:52:21 2009 -0400
@@ -31,7 +31,6 @@
 import java.util.*;
 import java.security.AccessController;
 import sun.security.action.GetPropertyAction;
-import static sun.nio.fs.UnixNativeDispatcher.*;
 
 /**
  * Bsd implementation of FileSystem
@@ -95,24 +94,23 @@
     }
 
     /**
-     * Returns object to iterate over entries in /etc/fstab
+     * Returns object to iterate over mount entries
      */
     @Override
     Iterable<UnixMountEntry> getMountEntries() {
         ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
         try {
-            UnixPath fstab = new UnixPath(this, "/etc/fstab");
-            long fp = fopen(fstab, "r");
+            long iter = BsdNativeDispatcher.getfsstat();
             try {
                 for (;;) {
                     UnixMountEntry entry = new UnixMountEntry();
-                    int res = getextmntent(fp, entry);
+                    int res = BsdNativeDispatcher.fsstatEntry(iter, entry);
                     if (res < 0)
                         break;
                     entries.add(entry);
                 }
             } finally {
-                fclose(fp);
+                BsdNativeDispatcher.endfsstat(iter);
             }
 
         } catch (UnixException x) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java	Wed May 27 08:52:21 2009 -0400
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.nio.fs;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Bsd specific system calls.
+ */
+
+class BsdNativeDispatcher extends UnixNativeDispatcher {
+    private BsdNativeDispatcher() { }
+
+   /**
+    * struct fsstat_iter *getfsstat();
+    */
+    static native long getfsstat() throws UnixException;
+
+   /**
+    * int fsstatEntry(struct fsstat_iter * iter, UnixMountEntry entry);
+    */
+    static native int fsstatEntry(long iter, UnixMountEntry entry)
+        throws UnixException;
+
+   /**
+    * void endfsstat(struct fsstat_iter * iter);
+    */
+    static native void endfsstat(long iter) throws UnixException;
+
+    // initialize field IDs
+    private static native void initIDs();
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("nio");
+                return null;
+        }});
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c	Wed May 27 08:52:21 2009 -0400
@@ -0,0 +1,201 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+static jfieldID entry_name;
+static jfieldID entry_dir;
+static jfieldID entry_fstype;
+static jfieldID entry_options;
+static jfieldID entry_dev;
+
+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);
+    if (x != NULL) {
+        (*env)->Throw(env, x);
+    }
+}
+
+/**
+ * Initialize jfieldIDs
+ */
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_BsdNativeDispatcher_initIDs(JNIEnv* env, jclass this)
+{
+    jclass clazz;
+
+    clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
+    if (clazz == NULL) {
+        return;
+    }
+    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 jlong JNICALL
+Java_sun_nio_fs_BsdNativeDispatcher_getfsstat(JNIEnv* env, jclass this)
+{
+    int nentries;
+    size_t bufsize;
+    struct fsstat_iter *iter = (struct fsstat_iter *)malloc(sizeof(*iter));
+
+    if (iter == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "native heap");
+        return NULL;
+    }
+
+    iter->pos = 0;
+    iter->nentries = 0;
+    iter->buf = NULL;
+
+    nentries = getfsstat(NULL, 0, MNT_NOWAIT);
+
+    if (nentries <= 0) {
+        free(iter);
+        throwUnixException(env, errno);
+        return NULL;
+    }
+
+    // It's possible that a new filesystem gets mounted between
+    // the first getfsstat and the second so loop until consistant
+
+    while (nentries != iter->nentries) {
+        if (iter->buf != NULL)
+            free(iter->buf);
+
+        bufsize = nentries * sizeof(struct statfs);
+        iter->nentries = nentries;
+
+        iter->buf = (struct statfs *)malloc(bufsize);
+        if (iter->buf == NULL) {
+            free(iter);
+            JNU_ThrowOutOfMemoryError(env, "native heap");
+            return NULL;
+        }
+
+        nentries = getfsstat(iter->buf, bufsize, MNT_WAIT);
+        if (nentries <= 0) {
+            free(iter->buf);
+            free(iter);
+            throwUnixException(env, errno);
+            return NULL;
+        }
+    }
+
+    return (jlong)iter;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry(JNIEnv* env, jclass this,
+    jlong value, jobject entry)
+{
+    struct fsstat_iter *iter = jlong_to_ptr(value);
+    jsize len;
+    jbyteArray bytes;
+    char* name;
+    char* dir;
+    char* fstype;
+    char* options;
+    dev_t dev;
+
+    if (iter == NULL || iter->pos >= iter->nentries)
+       return -1;
+
+    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 & MNT_RDONLY)
+        options="ro";
+    else
+        options="";
+    dev = 0;
+
+    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_endfsstat(JNIEnv* env, jclass this, jlong value)
+{
+    struct fsstat_iter *iter = jlong_to_ptr(value);
+
+    if (iter != NULL) {
+        free(iter->buf);
+        free(iter);
+    }
+}