summaryrefslogtreecommitdiffstats
path: root/libjava
diff options
context:
space:
mode:
Diffstat (limited to 'libjava')
-rw-r--r--libjava/gnu/java/nio/channels/FileChannelImpl.java420
-rw-r--r--libjava/gnu/java/nio/channels/natFileChannelEcos.cc159
-rw-r--r--libjava/gnu/java/nio/channels/natFileChannelPosix.cc522
-rw-r--r--libjava/gnu/java/nio/channels/natFileChannelWin32.cc432
4 files changed, 1533 insertions, 0 deletions
diff --git a/libjava/gnu/java/nio/channels/FileChannelImpl.java b/libjava/gnu/java/nio/channels/FileChannelImpl.java
new file mode 100644
index 00000000000..b5e5ffe6b67
--- /dev/null
+++ b/libjava/gnu/java/nio/channels/FileChannelImpl.java
@@ -0,0 +1,420 @@
+/* FileChannelImpl.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio.channels;
+
+import gnu.classpath.Configuration;
+import gnu.gcj.RawData;
+import gnu.java.nio.FileLockImpl;
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.*;
+
+/**
+ * This file is not user visible !
+ * But alas, Java does not have a concept of friendly packages
+ * so this class is public.
+ * Instances of this class are created by invoking getChannel
+ * Upon a Input/Output/RandomAccessFile object.
+ */
+
+public class FileChannelImpl extends FileChannel
+{
+ int mode;
+ // These are WHENCE values for seek.
+ static final int SET = 0;
+ static final int CUR = 1;
+
+ // These are mode values for open().
+ static final int READ = 1;
+ static final int WRITE = 2;
+ static final int APPEND = 4;
+
+ // EXCL is used only when making a temp file.
+ static final int EXCL = 8;
+ static final int SYNC = 16;
+ static final int DSYNC = 32;
+
+ /**
+ * This is the actual native file descriptor value
+ */
+ // System's notion of file descriptor. It might seem redundant to
+ // initialize this given that it is reassigned in the constructors.
+ // However, this is necessary because if open() throws an exception
+ // we want to make sure this has the value -1. This is the most
+ // efficient way to accomplish that.
+ private int fd = -1;
+
+ int length;
+ private long pos;
+
+ public FileChannelImpl ()
+ {
+ }
+
+ /* Open a file. MODE is a combination of the above mode flags. */
+ public FileChannelImpl (String path, int mode) throws FileNotFoundException
+ {
+ fd = open (path, mode);
+ this.mode = mode;
+ }
+
+ private static native void init();
+ static { init (); }
+
+ public static FileChannelImpl in;
+ public static FileChannelImpl out;
+ public static FileChannelImpl err;
+
+ private native int open (String path, int mode) throws FileNotFoundException;
+
+ /** Attach to an already-opened file. */
+ public FileChannelImpl (int desc, int mode)
+ {
+ fd = desc;
+ this.mode = mode;
+ }
+
+ native int available () throws IOException;
+ private native long implPosition ();
+ private native void seek (long newPosition);
+ private native void implTruncate (long size);
+
+ public native void unlock (long pos, long len);
+
+ public native long size () throws IOException;
+
+ protected native void implCloseChannel() throws IOException;
+
+ public int read (ByteBuffer dst) throws IOException
+ {
+ return implRead (dst);
+ }
+
+ public int read (ByteBuffer dst, long position)
+ throws IOException
+ {
+ if (position < 0)
+ throw new IllegalArgumentException ();
+ long oldPosition = implPosition ();
+ position (position);
+ int result = implRead (dst);
+ position (oldPosition);
+
+ return result;
+ }
+
+ private int implRead (ByteBuffer dst) throws IOException
+ {
+ int result;
+ byte[] buffer = new byte [dst.remaining ()];
+
+ result = read (buffer, 0, buffer.length);
+
+ if (result > 0)
+ dst.put (buffer, 0, result);
+
+ return result;
+ }
+
+ public native int read ()
+ throws IOException;
+
+ public native int read (byte[] buffer, int offset, int length)
+ throws IOException;
+
+ public long read (ByteBuffer[] dsts, int offset, int length)
+ throws IOException
+ {
+ long result = 0;
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ result += read (dsts [i]);
+ }
+
+ return result;
+ }
+
+ public int write (ByteBuffer src) throws IOException
+ {
+ return implWrite (src);
+ }
+
+ public int write (ByteBuffer src, long position)
+ throws IOException
+ {
+ if (position < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ if ((mode & WRITE) == 0)
+ throw new NonWritableChannelException ();
+
+ int result;
+ long oldPosition;
+
+ oldPosition = implPosition ();
+ seek (position);
+ result = implWrite (src);
+ seek (oldPosition);
+
+ return result;
+ }
+
+ private int implWrite (ByteBuffer src) throws IOException
+ {
+ int len = src.remaining ();
+ if (src.hasArray())
+ {
+ byte[] buffer = src.array();
+ write(buffer, src.arrayOffset() + src.position(), len);
+ }
+ else
+ {
+ // Use a more efficient native method! FIXME!
+ byte[] buffer = new byte [len];
+ src.get (buffer, 0, len);
+ write (buffer, 0, len);
+ }
+ return len;
+ }
+
+ public native void write (byte[] buffer, int offset, int length)
+ throws IOException;
+
+ public native void write (int b) throws IOException;
+
+ public long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException
+ {
+ long result = 0;
+
+ for (int i = offset;i < offset + length;i++)
+ {
+ result += write (srcs[i]);
+ }
+
+ return result;
+ }
+
+ public native MappedByteBuffer mapImpl (char mode, long position, int size)
+ throws IOException;
+
+ public MappedByteBuffer map (FileChannel.MapMode mode,
+ long position, long size)
+ throws IOException
+ {
+ char nmode = 0;
+ if (mode == MapMode.READ_ONLY)
+ {
+ nmode = 'r';
+ if ((this.mode & READ) == 0)
+ throw new NonReadableChannelException();
+ }
+ else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
+ {
+ nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
+ if ((this.mode & (READ|WRITE)) != (READ|WRITE))
+ throw new NonWritableChannelException();
+ }
+ else
+ throw new IllegalArgumentException ();
+
+ if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
+ throw new IllegalArgumentException ();
+ return mapImpl(nmode, position, (int) size);
+ }
+
+ /**
+ * msync with the disk
+ */
+ public void force (boolean metaData) throws IOException
+ {
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+ }
+
+ public long transferTo (long position, long count, WritableByteChannel target)
+ throws IOException
+ {
+ if (position < 0
+ || count < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ if ((mode & READ) == 0)
+ throw new NonReadableChannelException ();
+
+ // XXX: count needs to be casted from long to int. Dataloss ?
+ ByteBuffer buffer = ByteBuffer.allocate ((int) count);
+ read (buffer, position);
+ buffer.flip();
+ return target.write (buffer);
+ }
+
+ public long transferFrom (ReadableByteChannel src, long position, long count)
+ throws IOException
+ {
+ if (position < 0
+ || count < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ if ((mode & WRITE) == 0)
+ throw new NonWritableChannelException ();
+
+ // XXX: count needs to be casted from long to int. Dataloss ?
+ ByteBuffer buffer = ByteBuffer.allocate ((int) count);
+ src.read (buffer);
+ buffer.flip();
+ return write (buffer, position);
+ }
+
+ public FileLock tryLock (long position, long size, boolean shared)
+ throws IOException
+ {
+ if (position < 0
+ || size < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ if (shared && (mode & READ) == 0)
+ throw new NonReadableChannelException ();
+
+ if (!shared && (mode & WRITE) == 0)
+ throw new NonWritableChannelException ();
+
+ boolean completed = false;
+
+ try
+ {
+ begin();
+ lock(position, size, shared, true);
+ completed = true;
+ return new FileLockImpl(this, position, size, shared);
+ }
+ finally
+ {
+ end(completed);
+ }
+ }
+
+ /** Try to acquire a lock at the given position and size.
+ * On success return true.
+ * If wait as specified, block until we can get it.
+ * Otherwise return false.
+ */
+ private native boolean lock(long position, long size,
+ boolean shared, boolean wait);
+
+ public FileLock lock (long position, long size, boolean shared)
+ throws IOException
+ {
+ if (position < 0
+ || size < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ boolean completed = false;
+
+ try
+ {
+ boolean lockable = lock(position, size, shared, false);
+ completed = true;
+ return (lockable
+ ? new FileLockImpl(this, position, size, shared)
+ : null);
+ }
+ finally
+ {
+ end(completed);
+ }
+ }
+
+ public long position ()
+ throws IOException
+ {
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ return implPosition ();
+ }
+
+ public FileChannel position (long newPosition)
+ throws IOException
+ {
+ if (newPosition < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ // FIXME note semantics if seeking beyond eof.
+ // We should seek lazily - only on a write.
+ seek (newPosition);
+ return this;
+ }
+
+ public FileChannel truncate (long size)
+ throws IOException
+ {
+ if (size < 0)
+ throw new IllegalArgumentException ();
+
+ if (!isOpen ())
+ throw new ClosedChannelException ();
+
+ if ((mode & WRITE) == 0)
+ throw new NonWritableChannelException ();
+
+ implTruncate (size);
+ return this;
+ }
+}
diff --git a/libjava/gnu/java/nio/channels/natFileChannelEcos.cc b/libjava/gnu/java/nio/channels/natFileChannelEcos.cc
new file mode 100644
index 00000000000..66713079a86
--- /dev/null
+++ b/libjava/gnu/java/nio/channels/natFileChannelEcos.cc
@@ -0,0 +1,159 @@
+// natFileDescriptor.cc - Native part of FileDescriptor class.
+
+/* Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java/io/FileDescriptor.h>
+#include <java/io/SyncFailedException.h>
+#include <java/io/IOException.h>
+#include <java/io/EOFException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/String.h>
+#include <java/io/FileNotFoundException.h>
+
+extern "C" void diag_write_char (char c);
+
+static void
+diag_write (char *data, int len)
+{
+ while (len > 0)
+ {
+ diag_write_char (*data++);
+ len--;
+ }
+}
+
+#define NO_FSYNC_MESSAGE "sync unsupported"
+
+void
+java::io::FileDescriptor::init(void)
+{
+ in = new java::io::FileDescriptor(0);
+ out = new java::io::FileDescriptor(1);
+ err = new java::io::FileDescriptor(2);
+}
+
+jboolean
+java::io::FileDescriptor::valid (void)
+{
+ return true;
+}
+
+void
+java::io::FileDescriptor::sync (void)
+{
+ // Some files don't support fsync. We don't bother reporting these
+ // as errors.
+#ifdef HAVE_FSYNC
+#else
+ throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE));
+#endif
+}
+
+jint
+java::io::FileDescriptor::open (jstring path, jint jflags)
+{
+ return fd;
+}
+
+void
+java::io::FileDescriptor::write (jint b)
+{
+ char d = (char) b;
+ ::diag_write (&d, 1);
+}
+
+void
+java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
+{
+ if (! b)
+ throw new java::lang::NullPointerException;
+ if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+ char *bytes = (char *)elements (b) + offset;
+ ::diag_write (bytes, len);
+}
+
+void
+java::io::FileDescriptor::close (void)
+{
+}
+
+void
+java::io::FileDescriptor::setLength (long)
+{
+}
+
+jint
+java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean)
+{
+ JvAssert (whence == SET || whence == CUR);
+ return 0;
+}
+
+jlong
+java::io::FileDescriptor::getLength (void)
+{
+ return 0;
+}
+
+jlong
+java::io::FileDescriptor::getFilePointer (void)
+{
+ return 0;
+}
+
+jint
+java::io::FileDescriptor::read (void)
+{
+ return 0;
+}
+
+jint
+java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
+{
+ return 0;
+}
+
+jint
+java::io::FileDescriptor::available (void)
+{
+ return 0;
+}
+
+void
+java::io::FileDescriptor::lock (jlong pos, jint len, jboolean shared)
+{
+ throw new IOException (JvNewStringLatin1
+ ("java.io.FileDescriptor.lock() not implemented"));
+}
+
+jboolean
+java::io::FileDescriptor::tryLock (jlong pos, jint len, jboolean shared)
+{
+ throw new IOException (JvNewStringLatin1
+ ("java.io.FileDescriptor.tryLock() not implemented"));
+}
+
+void
+java::io::FileDescriptor::unlock (jlong pos, jint len)
+{
+ throw new IOException (JvNewStringLatin1
+ ("java.io.FileDescriptor.unlock() not implemented"));
+}
diff --git a/libjava/gnu/java/nio/channels/natFileChannelPosix.cc b/libjava/gnu/java/nio/channels/natFileChannelPosix.cc
new file mode 100644
index 00000000000..86537872821
--- /dev/null
+++ b/libjava/gnu/java/nio/channels/natFileChannelPosix.cc
@@ -0,0 +1,522 @@
+
+// natFileChannelImplPosix.cc - Native part of FileChannelImpl class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+#include <platform.h>
+
+#include <gcj/cni.h>
+#include <gcj/javaprims.h>
+#include <jvm.h>
+
+#include "posix.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <gnu/gcj/RawData.h>
+#include <gnu/java/nio/FileLockImpl.h>
+#include <gnu/java/nio/channels/FileChannelImpl.h>
+#include <java/io/FileNotFoundException.h>
+#include <java/io/IOException.h>
+#include <java/io/SyncFailedException.h>
+#include <java/io/InterruptedIOException.h>
+#include <java/io/EOFException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/System.h>
+#include <java/lang/String.h>
+#include <java/lang/Thread.h>
+#include <java/nio/ByteBuffer.h>
+#include <java/nio/MappedByteBufferImpl.h>
+#include <java/nio/channels/FileChannel.h>
+#include <java/nio/channels/FileLock.h>
+#include <gnu/java/nio/channels/FileChannelImpl.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#define BSD_COMP /* Get FIONREAD on Solaris2. */
+#include <sys/ioctl.h>
+#endif
+
+// Pick up FIONREAD on Solaris 2.5.
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+using gnu::gcj::RawData;
+using java::io::IOException;
+using java::nio::MappedByteBufferImpl;
+using java::io::InterruptedIOException;
+using java::io::FileNotFoundException;
+using java::lang::ArrayIndexOutOfBoundsException;
+using gnu::java::nio::channels::FileChannelImpl;
+
+#define NO_FSYNC_MESSAGE "sync unsupported"
+
+void
+FileChannelImpl::init(void)
+{
+ in = new FileChannelImpl((jint) 0, FileChannelImpl::READ);
+ out = new FileChannelImpl((jint) 1, FileChannelImpl::WRITE);
+ err = new FileChannelImpl((jint) 2, FileChannelImpl::WRITE);
+}
+
+#if 0
+jboolean
+FileChannelImpl::valid (void)
+{
+ struct stat sb;
+ return fd >= 0 && ::fstat (fd, &sb) == 0;
+}
+
+void
+FileChannelImpl::sync (void)
+{
+ // Some files don't support fsync. We don't bother reporting these
+ // as errors.
+#ifdef HAVE_FSYNC
+ if (::fsync (fd) && errno != EROFS && errno != EINVAL)
+ throw new SyncFailedException (JvNewStringLatin1 (strerror (errno)));
+#else
+ throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE));
+#endif
+}
+#endif
+
+jint
+FileChannelImpl::open (jstring path, jint jflags)
+{
+ fd = -1;
+ char *buf = (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path) + 1);
+ jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+ buf[total] = '\0';
+ int flags = 0;
+#ifdef O_BINARY
+ flags |= O_BINARY;
+#endif
+
+ JvAssert ((jflags & READ) || (jflags & WRITE));
+ int mode = 0666;
+ if ((jflags & READ) && (jflags & WRITE))
+ flags |= O_RDWR | O_CREAT;
+ else if ((jflags & READ))
+ flags |= O_RDONLY;
+ else
+ {
+ flags |= O_WRONLY | O_CREAT;
+ if ((jflags & APPEND))
+ flags |= O_APPEND;
+ else
+ flags |= O_TRUNC;
+
+ if ((jflags & EXCL))
+ {
+ flags |= O_EXCL;
+ // In this case we are making a temp file.
+ mode = 0600;
+ }
+ }
+
+ if ((jflags & SYNC))
+ flags |= O_SYNC;
+
+ if ((jflags & DSYNC))
+ flags |= O_DSYNC;
+
+ int fd = ::open (buf, flags, mode);
+ if (fd == -1 && errno == EMFILE)
+ {
+ // Because finalize () calls close () we might be able to continue.
+ ::java::lang::System::gc ();
+ ::java::lang::System::runFinalization ();
+ fd = ::open (buf, flags, mode);
+ }
+ if (fd == -1)
+ {
+ char msg[MAXPATHLEN + 200];
+ // We choose the formatting here for JDK compatibility, believe
+ // it or not.
+ sprintf (msg, "%.*s (%.*s)",
+ MAXPATHLEN + 150, buf,
+ 40, strerror (errno));
+ throw new ::java::io::FileNotFoundException (JvNewStringLatin1 (msg));
+ }
+
+ _Jv_platform_close_on_exec (fd);
+
+ return fd;
+}
+
+void
+FileChannelImpl::write (jint b)
+{
+ jbyte d = (jbyte) b;
+ int r = 0;
+ while (r != 1)
+ {
+ r = ::write (fd, &d, 1);
+ if (r == -1)
+ {
+ if (::java::lang::Thread::interrupted())
+ {
+ ::java::io::InterruptedIOException *iioe
+ = new ::java::io::InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ throw iioe;
+ }
+ if (errno != EINTR)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+ }
+ pos++;
+}
+
+void
+FileChannelImpl::write (jbyteArray b, jint offset, jint len)
+{
+ if (! b)
+ throw new ::java::lang::NullPointerException;
+ if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
+ throw new ArrayIndexOutOfBoundsException;
+ jbyte *bytes = elements (b) + offset;
+
+ int written = 0;
+ while (len > 0)
+ {
+ int r = ::write (fd, bytes, len);
+ if (r == -1)
+ {
+ if (::java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
+ iioe->bytesTransferred = written;
+ throw iioe;
+ }
+ if (errno != EINTR)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+
+ written += r;
+ len -= r;
+ bytes += r;
+ pos += r;
+ }
+}
+
+void
+FileChannelImpl::implCloseChannel (void)
+{
+ jint save = fd;
+ fd = -1;
+ if (::close (save))
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+}
+
+void
+FileChannelImpl::implTruncate (jlong size)
+{
+ struct stat sb;
+
+#ifdef HAVE_FTRUNCATE
+ if (::fstat (fd, &sb))
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+
+ if ((jlong) sb.st_size == size)
+ return;
+
+ // If the file is too short, we extend it. We can't rely on
+ // ftruncate() extending the file. So we lseek() to 1 byte less
+ // than we want, and then we write a single byte at the end.
+ if ((jlong) sb.st_size < size)
+ {
+ if (::lseek (fd, (off_t) (size - 1), SEEK_SET) == -1)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ char out = '\0';
+ int r = ::write (fd, &out, 1);
+ if (r <= 0 || ::lseek (fd, pos, SEEK_SET) == -1)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+ else
+ {
+ if (::ftruncate (fd, (off_t) pos))
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ pos = size;
+ }
+#else /* HAVE_FTRUNCATE */
+ throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
+#endif /* HAVE_FTRUNCATE */
+}
+
+void
+FileChannelImpl::seek (jlong newPos)
+{
+ off_t r = ::lseek (fd, (off_t) newPos, SEEK_SET);
+ if (r == -1)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ pos = r;
+}
+
+jlong
+FileChannelImpl::size (void)
+{
+ struct stat sb;
+ if (::fstat (fd, &sb))
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ return sb.st_size;
+}
+
+jlong
+FileChannelImpl::implPosition (void)
+{
+ return pos;
+}
+
+jint
+FileChannelImpl::read (void)
+{
+ jbyte b;
+ int r;
+ do
+ {
+ r = ::read (fd, &b, 1);
+ if (r == 0)
+ return -1;
+ if (r == -1)
+ {
+ if (::java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ throw iioe;
+ }
+ if (errno != EINTR)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+ }
+ while (r != 1);
+ pos++;
+ return b & 0xFF;
+}
+
+jint
+FileChannelImpl::read (jbyteArray buffer, jint offset, jint count)
+{
+ if (! buffer)
+ throw new ::java::lang::NullPointerException;
+ jsize bsize = JvGetArrayLength (buffer);
+ if (offset < 0 || count < 0 || offset + count > bsize)
+ throw new ::java::lang::ArrayIndexOutOfBoundsException;
+
+ // Must return 0 if an attempt is made to read 0 bytes.
+ if (count == 0)
+ return 0;
+
+ jbyte *bytes = elements (buffer) + offset;
+ int r;
+ do
+ {
+ r = ::read (fd, bytes, count);
+ if (r == 0)
+ return -1;
+ if (r == -1)
+ {
+ if (::java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe
+ = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
+ iioe->bytesTransferred = r == -1 ? 0 : r;
+ throw iioe;
+ }
+ if (errno != EINTR)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+ }
+ while (r <= 0);
+ pos += r;
+ return r;
+}
+
+jint
+FileChannelImpl::available (void)
+{
+#if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
+ long num = 0;
+ int r = 0;
+ bool num_set = false;
+
+#if defined (FIONREAD)
+ r = ::ioctl (fd, FIONREAD, &num);
+ if (r == -1 && errno == ENOTTY)
+ {
+ // If the ioctl doesn't work, we don't care.
+ r = 0;
+ num = 0;
+ }
+ else
+ num_set = true;
+#elif defined (HAVE_SELECT)
+ if (fd < 0)
+ {
+ errno = EBADF;
+ r = -1;
+ }
+#endif
+
+ if (r == -1)
+ {
+ posix_error:
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+
+ // If we didn't get anything, and we have fstat, then see if see if
+ // we're reading a regular file. On many systems, FIONREAD does not
+ // work on regular files; select() likewise returns a useless
+ // result. This is run incorrectly when FIONREAD does work on
+ // regular files and we are at the end of the file. However, this
+ // case probably isn't very important.
+#if defined (HAVE_FSTAT)
+ if (! num_set)
+ {
+ struct stat sb;
+ off_t where = 0;
+ if (fstat (fd, &sb) != -1
+ && S_ISREG (sb.st_mode)
+ && (where = lseek (fd, 0, SEEK_CUR)) != (off_t) -1)
+ {
+ num = (long) (sb.st_size - where);
+ num_set = true;
+ }
+ }
+#endif /* HAVE_FSTAT */
+
+#if defined (HAVE_SELECT)
+ if (! num_set)
+ {
+ fd_set rd;
+ FD_ZERO (&rd);
+ FD_SET (fd, &rd);
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
+ if (r == -1)
+ goto posix_error;
+ num = r == 0 ? 0 : 1;
+ }
+#endif /* HAVE_SELECT */
+
+ return (jint) num;
+#else
+ return 0;
+#endif
+}
+
+jboolean
+FileChannelImpl::lock
+(jlong pos, jlong len, jboolean shared, jboolean wait)
+{
+ struct flock lockdata;
+
+ lockdata.l_type = shared ? F_WRLCK : F_RDLCK;
+ lockdata.l_whence = SEEK_SET;
+ lockdata.l_start = pos;
+ lockdata.l_len = len;
+
+ if (::fcntl (fd, wait ? F_SETLKW : F_SETLK, &lockdata) == -1)
+ {
+ if (! wait && (errno == EACCES || errno == EAGAIN))
+ return false;
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+ return true;
+}
+
+void
+FileChannelImpl::unlock (jlong pos, jlong len)
+{
+ struct flock lockdata;
+
+ lockdata.l_type = F_UNLCK;
+ lockdata.l_whence = SEEK_SET;
+ lockdata.l_start = pos;
+ lockdata.l_len = len;
+
+ if (::fcntl (fd, F_SETLK, &lockdata) == -1)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+}
+
+java::nio::MappedByteBuffer *
+FileChannelImpl::mapImpl (jchar mmode, jlong position, jint size)
+{
+#if defined(HAVE_MMAP)
+ int prot, flags;
+ if (mmode == 'r')
+ {
+ prot = PROT_READ;
+ flags = MAP_PRIVATE;
+ }
+ else
+ {
+ prot = PROT_READ|PROT_WRITE;
+ flags = mmode == '+' ? MAP_SHARED : MAP_PRIVATE;
+ }
+ jint page_size = ::getpagesize();
+ jint offset = position & ~(page_size-1);
+ jint align = position - offset;
+ void* ptr = ::mmap(NULL, size + align, prot, flags, fd, offset);
+ MappedByteBufferImpl *buf
+ = new MappedByteBufferImpl ((RawData *) ((char *) ptr + align),
+ size, mmode == 'r');
+ if (ptr == MAP_FAILED)
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ buf->implPtr = reinterpret_cast<RawData*> (ptr);
+ buf->implLen = size+align;
+ return buf;
+#else
+ throw new IOException (JvNewStringUTF ("mmap not implemented"));
+#endif
+}
+
+void
+MappedByteBufferImpl::unmapImpl ()
+{
+#if defined(HAVE_MMAP)
+ munmap((void*) implPtr, implLen);
+#endif
+}
+
+void
+MappedByteBufferImpl::loadImpl ()
+{
+}
+
+jboolean
+MappedByteBufferImpl::isLoadedImpl ()
+{
+ return true;
+}
+
+void
+MappedByteBufferImpl::forceImpl ()
+{
+#if defined(HAVE_MMAP)
+ ::msync((void*) implPtr, implLen, MS_SYNC);
+#endif
+}
diff --git a/libjava/gnu/java/nio/channels/natFileChannelWin32.cc b/libjava/gnu/java/nio/channels/natFileChannelWin32.cc
new file mode 100644
index 00000000000..ca6387df011
--- /dev/null
+++ b/libjava/gnu/java/nio/channels/natFileChannelWin32.cc
@@ -0,0 +1,432 @@
+// natFileChannelImplWin32.cc - Native part of FileChannelImpl class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+// FIXME: In order to support interrupting of IO operations, we
+// need to change to use the windows asynchronous IO functions
+
+#include <config.h>
+#include <platform.h>
+
+#include <gcj/cni.h>
+#include <gcj/javaprims.h>
+#include <jvm.h>
+
+#include <stdio.h>
+
+#include <gnu/gcj/RawData.h>
+#include <gnu/java/nio/FileLockImpl.h>
+#include <gnu/java/nio/channels/FileChannelImpl.h>
+#include <java/io/FileNotFoundException.h>
+#include <java/io/IOException.h>
+#include <java/io/SyncFailedException.h>
+#include <java/io/InterruptedIOException.h>
+#include <java/io/EOFException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/System.h>
+#include <java/lang/String.h>
+#include <java/lang/Thread.h>
+#include <java/nio/ByteBuffer.h>
+#include <java/nio/MappedByteBufferImpl.h>
+#include <java/nio/channels/FileChannel.h>
+#include <java/nio/channels/FileLock.h>
+#include <gnu/java/nio/channels/FileChannelImpl.h>
+
+using gnu::gcj::RawData;
+using java::io::IOException;
+using java::nio::MappedByteBufferImpl;
+using java::io::InterruptedIOException;
+using java::io::FileNotFoundException;
+using java::lang::ArrayIndexOutOfBoundsException;
+using gnu::java::nio::channels::FileChannelImpl;
+
+#undef STRICT
+
+static bool testCanUseGetHandleInfo()
+{
+ /* Test to see whether GetHandleInformation can be used
+ for console input or screen buffers. This is better
+ a kludgy OS version check. */
+ DWORD dwFlags;
+ return GetHandleInformation (GetStdHandle (STD_INPUT_HANDLE),
+ &dwFlags) != 0;
+}
+
+// FIXME: casting a FILE (pointer) to a jint will not work on Win64 --
+// we should be using gnu.gcj.RawData's.
+
+void
+FileChannelImpl::init(void)
+{
+ in = new FileChannelImpl((jint)(GetStdHandle (STD_INPUT_HANDLE)),
+ FileChannelImpl::READ);
+ out = new FileChannelImpl((jint)(GetStdHandle (STD_OUTPUT_HANDLE)),
+ FileChannelImpl::WRITE);
+ err = new FileChannelImpl((jint)(GetStdHandle (STD_ERROR_HANDLE)),
+ FileChannelImpl::WRITE);
+}
+
+#if 0
+FileChannelImpl::sync (void) {
+ if (! FlushFileBuffers ((HANDLE)fd))
+ {
+ DWORD dwErrorCode = GetLastError ();
+ throw new SyncFailedException (_Jv_WinStrError (dwErrorCode));
+ }
+}
+#endif
+
+jint
+FileChannelImpl::open (jstring path, jint jflags) {
+
+ HANDLE handle = NULL;
+ DWORD access = 0;
+ DWORD create = OPEN_EXISTING;
+
+ JV_TEMP_STRING_WIN32(cpath, path)
+
+ JvAssert((jflags & READ) || (jflags & WRITE));
+
+ if ((jflags & READ) && (jflags & WRITE))
+ {
+ access = GENERIC_READ | GENERIC_WRITE;
+ if (jflags & EXCL)
+ create = CREATE_NEW; // this will raise error if file exists.
+ else
+ create = OPEN_ALWAYS; // equivalent to O_CREAT
+ }
+ else if (jflags & READ)
+ {
+ access = GENERIC_READ;
+ create = OPEN_EXISTING; // ignore EXCL
+ }
+ else
+ {
+ access = GENERIC_WRITE;
+ if (jflags & EXCL)
+ create = CREATE_NEW;
+ else if (jflags & APPEND)
+ create = OPEN_ALWAYS;
+ else
+ create = CREATE_ALWAYS;
+ }
+
+ handle = CreateFile(cpath, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, create, 0, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ DWORD dwErrorCode = GetLastError ();
+ throw new FileNotFoundException (_Jv_WinStrError (cpath, dwErrorCode));
+ }
+
+ // For APPEND mode, move the file pointer to the end of the file.
+ if (jflags & APPEND)
+ {
+ DWORD low = SetFilePointer (handle, 0, NULL, FILE_END);
+ if ((low == (DWORD) 0xffffffff) && (GetLastError () != NO_ERROR))
+ {
+ DWORD dwErrorCode = GetLastError ();
+ throw new FileNotFoundException (_Jv_WinStrError (cpath, dwErrorCode));
+ }
+ }
+
+ // Make this handle non-inheritable so that child
+ // processes don't inadvertently prevent us from
+ // closing this file.
+ _Jv_platform_close_on_exec (handle);
+
+ return (jint) handle;
+}
+
+void
+FileChannelImpl::write (jint b)
+{
+ DWORD bytesWritten;
+ jbyte buf = (jbyte)b;
+
+ if (WriteFile ((HANDLE)fd, &buf, 1, &bytesWritten, NULL))
+ {
+ if (::java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe = new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
+ iioe->bytesTransferred = bytesWritten;
+ throw iioe;
+ }
+ if (bytesWritten != 1)
+ _Jv_ThrowIOException ();
+ }
+ else
+ _Jv_ThrowIOException ();
+ // FIXME: loop until bytesWritten == 1
+}
+
+void
+FileChannelImpl::write(jbyteArray b, jint offset, jint len)
+{
+ if (! b)
+ throw new ::java::lang::NullPointerException;
+ if(offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
+ throw new ArrayIndexOutOfBoundsException;
+
+ jbyte *buf = elements (b) + offset;
+ DWORD bytesWritten;
+
+ if (WriteFile ((HANDLE)fd, buf, len, &bytesWritten, NULL))
+ {
+ if (::java::lang::Thread::interrupted())
+ {
+ InterruptedIOException *iioe = new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
+ iioe->bytesTransferred = bytesWritten;
+ throw iioe;
+ }
+ }
+ else
+ _Jv_ThrowIOException ();
+ // FIXME: loop until bytesWritten == len
+}
+
+void
+FileChannelImpl::implCloseChannel (void)
+{
+ HANDLE save = (HANDLE)fd;
+ fd = (jint)INVALID_HANDLE_VALUE;
+ if (! CloseHandle (save))
+ _Jv_ThrowIOException ();
+}
+
+void
+FileChannelImpl::implTruncate (jlong size)
+{
+ LONG liOrigFilePointer;
+ LONG liNewFilePointer;
+ LONG liEndFilePointer;
+
+ // Get the original file pointer.
+ if (SetFilePointer((HANDLE) fd, (LONG) 0, &liOrigFilePointer,
+ FILE_CURRENT) != (BOOL) 0
+ && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+
+ // Get the length of the file.
+ if (SetFilePointer((HANDLE) fd, (LONG) 0, &liEndFilePointer,
+ FILE_END) != (BOOL) 0
+ && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+
+ if ((jlong)liEndFilePointer == size)
+ {
+ // Restore the file pointer.
+ if (liOrigFilePointer != liEndFilePointer)
+ {
+ if (SetFilePointer((HANDLE) fd, liOrigFilePointer, &liNewFilePointer,
+ FILE_BEGIN) != (BOOL) 0
+ && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+ }
+ return;
+ }
+
+ // Seek to the new end of file.
+ if (SetFilePointer((HANDLE) fd, (LONG) size, &liNewFilePointer,
+ FILE_BEGIN) != (BOOL) 0
+ && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+
+ // Truncate the file at this point.
+ if (SetEndOfFile((HANDLE) fd) != (BOOL) 0 && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+
+ if (liOrigFilePointer < liNewFilePointer)
+ {
+ // Restore the file pointer.
+ if (SetFilePointer((HANDLE) fd, liOrigFilePointer, &liNewFilePointer,
+ FILE_BEGIN) != (BOOL) 0
+ && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+ }
+}
+
+void
+FileChannelImpl::seek (jlong newPos)
+{
+ LONG high = pos >> 32;
+ DWORD low = SetFilePointer ((HANDLE)fd, (DWORD)(0xffffffff & newPos), &high, FILE_BEGIN);
+ if ((low == 0xffffffff) && (GetLastError () != NO_ERROR))
+ _Jv_ThrowIOException ();
+}
+
+jlong
+FileChannelImpl::implPosition (void)
+{
+ LONG high = 0;
+ DWORD low = SetFilePointer ((HANDLE)fd, 0, &high, FILE_CURRENT);
+ if ((low == 0xffffffff) && (GetLastError() != NO_ERROR))
+ _Jv_ThrowIOException ();
+ return (((jlong)high) << 32L) | (jlong)low;
+}
+
+jlong
+FileChannelImpl::size (void)
+{
+ DWORD high;
+ DWORD low;
+
+ low = GetFileSize ((HANDLE)fd, &high);
+ // FIXME: Error checking
+ return (((jlong)high) << 32L) | (jlong)low;
+}
+
+jint
+FileChannelImpl::read (void)
+{
+ CHAR buf;
+ DWORD read;
+
+ if (! ReadFile ((HANDLE)fd, &buf, 1, &read, NULL))
+ {
+ if (GetLastError () == ERROR_BROKEN_PIPE)
+ return -1;
+ else
+ _Jv_ThrowIOException ();
+ }
+
+ if (! read)
+ return -1;
+ else
+ return (jint)(buf & 0xff);
+}
+
+jint
+FileChannelImpl::read (jbyteArray buffer, jint offset, jint count)
+{
+ if (! buffer)
+ throw new ::java::lang::NullPointerException;
+
+ jsize bsize = JvGetArrayLength (buffer);
+ if (offset < 0 || count < 0 || offset + count > bsize)
+ throw new ArrayIndexOutOfBoundsException;
+
+ // Must return 0 if an attempt is made to read 0 bytes.
+ if (count == 0)
+ return 0;
+
+ jbyte *bytes = elements (buffer) + offset;
+
+ DWORD read;
+ if (! ReadFile((HANDLE)fd, bytes, count, &read, NULL))
+ {
+ if (GetLastError () == ERROR_BROKEN_PIPE)
+ return -1;
+ else
+ _Jv_ThrowIOException ();
+ }
+
+ if (read == 0) return -1;
+
+ return (jint)read;
+}
+
+jint
+FileChannelImpl::available (void)
+{
+ // FIXME:
+ return size() - position();
+}
+
+jboolean
+FileChannelImpl::lock
+(jlong /*pos*/, jlong /*len*/, jboolean /*shared*/, jboolean /*wait*/)
+{
+ throw new IOException (JvNewStringLatin1
+ ("FileChannel.lock() not implemented"));
+}
+
+void
+FileChannelImpl::unlock (jlong /*pos*/, jlong /*len*/)
+{
+ throw new IOException (JvNewStringLatin1
+ ("FileChannel.unlock() not implemented"));
+}
+
+java::nio::MappedByteBuffer *
+FileChannelImpl::mapImpl (jchar mmode, jlong position, jint size)
+{
+ SYSTEM_INFO siSysInfo;
+ GetSystemInfo(&siSysInfo);
+ DWORD page_size = siSysInfo.dwPageSize;
+ jlong offset = position & ~(page_size-1);
+ jint align = position - offset;
+ jlong high = position + size;
+ jlong max_size;
+ if (mmode == '+')
+ max_size = high - offset;
+ else
+ max_size = 0;
+ DWORD access, protect;
+ if (mmode == 'r')
+ {
+ access = FILE_MAP_READ;
+ protect = PAGE_READONLY;
+ }
+ else if (mmode == '+')
+ {
+ access = FILE_MAP_WRITE;
+ protect = PAGE_READWRITE;
+ }
+ else
+ {
+ access = FILE_MAP_COPY;
+ protect = PAGE_WRITECOPY;
+ }
+ HANDLE hFileMapping = CreateFileMapping((HANDLE) fd,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ protect,
+ (DWORD) (max_size >> 32),
+ (DWORD) max_size,
+ (LPCTSTR) NULL);
+ if (hFileMapping == NULL)
+ throw new IOException();
+ void *ptr = MapViewOfFile(hFileMapping, access,
+ (DWORD) (offset >> 32), (DWORD) offset,
+ (SIZE_T) (high - offset));
+ if (ptr == NULL)
+ throw new IOException();
+ MappedByteBufferImpl *buf
+ = new MappedByteBufferImpl((RawData *) ((char *) ptr + align),
+ size, mode == 'r');
+ buf->implPtr = reinterpret_cast<RawData*> (ptr);
+ buf->implLen = (jlong) (size_t) hFileMapping;
+ return buf;
+}
+
+void
+MappedByteBufferImpl::unmapImpl ()
+{
+ UnmapViewOfFile((void*)implPtr);
+ CloseHandle((HANDLE) (size_t) implLen);
+}
+
+void
+MappedByteBufferImpl::loadImpl ()
+{
+}
+
+jboolean
+MappedByteBufferImpl::isLoadedImpl ()
+{
+ return true;
+}
+
+void
+MappedByteBufferImpl::forceImpl ()
+{
+}
OpenPOWER on IntegriCloud