Hi list -

I've been using this patch for years to a) allow access to the integer
file descriptor in jni as in [1], and b) to use the FileChannel.map()
method to map special files under linux using jamvm / classpath-0.98
(e.g. /dev/fb0).

Thought I would submit it to the list for inclusion in any new releases.

Feedback from any people wanting to validate is welcome.

If I recall correctly, one shortcoming is that the returned mapped
byte buffer is not 'direct'. Getting a direct map would require some
manipulation of fields in an underlying byte[] somewhere. Obviously, a
direct-mapped byte buffer would be more ideal. I think that requires
using some kind of Unsafe class somewhere, and I stopped at that
point. I don't mind doing the legwork for a direct mapped byte buffer
too, to make it for inclusion in the next release.

C

[1] http://www.kfu.com/~nsayer/Java/jni-filedesc.html
diff --git a/gnu/java/nio/FileChannelImpl.java b/gnu/java/nio/FileChannelImpl.java
index d4a374b..06fa205 100644
--- a/gnu/java/nio/FileChannelImpl.java
+++ b/gnu/java/nio/FileChannelImpl.java
@@ -176,7 +176,7 @@ public final class FileChannelImpl extends FileChannel
    *
    * @param mode READ or WRITE
    */
-  FileChannelImpl (VMChannel ch, int mode)
+  public FileChannelImpl (VMChannel ch, int mode)
   {
     this.mode = mode;
     this.description = "descriptor(" + ch.getState() + ")";
@@ -564,9 +564,14 @@ public final class FileChannelImpl extends FileChannel
 
   /**
    * @return The native file descriptor.
-   * /
+   */
   public int getNativeFD()
   {
-    return fd;
-  }*/
+	  int fd = -1;
+	  try {
+		  fd = ch.getState().getNativeFD();
+	  } catch(IOException e) {
+	  }
+	  return fd;
+  }
 }
diff --git a/java/io/FileDescriptor.java b/java/io/FileDescriptor.java
index cf9ff20..c3da2a9 100644
--- a/java/io/FileDescriptor.java
+++ b/java/io/FileDescriptor.java
@@ -40,6 +40,7 @@ exception statement from your version. */
 package java.io;
 
 import gnu.java.nio.FileChannelImpl;
+import gnu.java.nio.VMChannel;
 
 import java.nio.channels.ByteChannel;
 import java.nio.channels.FileChannel;
@@ -80,6 +81,7 @@ public final class FileDescriptor
   = new FileDescriptor (FileChannelImpl.err);
 
   final ByteChannel channel;
+  int fd;
 
   /**
    * This method is used to initialize an invalid FileDescriptor object.
@@ -97,6 +99,17 @@ public final class FileDescriptor
     this.channel = channel;
   }
 
+  FileDescriptor(FileChannelImpl channel)
+  {
+    this.channel = channel;
+    this.fd = channel.getNativeFD();
+  }
+
+  FileDescriptor(int fd, int mode) throws IOException
+  {
+    channel = new FileChannelImpl(new VMChannel(fd), mode);
+    this.fd = fd;
+  }
 
   /**
    * This method forces all data that has not yet been physically written to
@@ -135,6 +148,8 @@ public final class FileDescriptor
   public boolean valid ()
   { 
     ByteChannel c = channel;
-    return (c != null) && (c.isOpen());
+    boolean valid = (c != null) && (c.isOpen());
+    valid = (channel instanceof FileChannel) ? (fd >= 0) : valid;
+    return valid;
   }
 }
diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c
index 7899f0b..0f12efd 100644
--- a/native/jni/java-nio/gnu_java_nio_VMChannel.c
+++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c
@@ -1944,18 +1944,20 @@ Java_gnu_java_nio_VMChannel_map (JNIEnv *env,
         }
       if (position + size > st.st_size)
         {
-          if (ftruncate(fd, position + size) == -1)
+          if ( !(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) )
             {
-              JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
-              return NULL;
+              if (ftruncate(fd, position + size) == -1)
+                {
+                  JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+                  return NULL;
+                }
             }
         }
       prot |= PROT_WRITE;
     }
 
   flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED);
-  p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags,
-	    fd, ALIGN_DOWN (position, pagesize));
+  p = mmap (NULL, (unsigned)size, prot, flags, fd, position);
   if (p == MAP_FAILED)
     {
       JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
@@ -1979,14 +1981,14 @@ Java_gnu_java_nio_VMChannel_map (JNIEnv *env,
 
   if ((*env)->ExceptionOccurred (env))
     {
-      munmap (p, ALIGN_UP (size, pagesize));
+      munmap (p, size);
       return NULL;
     }
   if (MappedByteBufferImpl_init == NULL)
     {
       JCL_ThrowException (env, "java/lang/InternalError",
                           "could not get MappedByteBufferImpl constructor");
-      munmap (p, ALIGN_UP (size, pagesize));
+      munmap (p, size);
       return NULL;
     }
 
diff --git a/vm/reference/gnu/java/nio/VMChannel.java b/vm/reference/gnu/java/nio/VMChannel.java
index a9d1452..7d8f13e 100644
--- a/vm/reference/gnu/java/nio/VMChannel.java
+++ b/vm/reference/gnu/java/nio/VMChannel.java
@@ -85,7 +85,7 @@ public final class VMChannel
    * @param native_fd The native file descriptor integer.
    * @throws IOException
    */
-  VMChannel(final int native_fd) throws IOException
+  public VMChannel(final int native_fd) throws IOException
   {
     this();
     this.nfd.setNativeFD(native_fd);

Reply via email to