diff options
Diffstat (limited to 'libjava/gnu/java/nio/channels')
-rw-r--r-- | libjava/gnu/java/nio/channels/FileChannelImpl.h | 118 | ||||
-rw-r--r-- | libjava/gnu/java/nio/channels/FileChannelImpl.java | 544 | ||||
-rw-r--r-- | libjava/gnu/java/nio/channels/natFileChannelEcos.cc | 192 | ||||
-rw-r--r-- | libjava/gnu/java/nio/channels/natFileChannelPosix.cc | 557 | ||||
-rw-r--r-- | libjava/gnu/java/nio/channels/natFileChannelWin32.cc | 466 |
5 files changed, 1877 insertions, 0 deletions
diff --git a/libjava/gnu/java/nio/channels/FileChannelImpl.h b/libjava/gnu/java/nio/channels/FileChannelImpl.h new file mode 100644 index 000000000..34099c52f --- /dev/null +++ b/libjava/gnu/java/nio/channels/FileChannelImpl.h @@ -0,0 +1,118 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_java_nio_channels_FileChannelImpl__ +#define __gnu_java_nio_channels_FileChannelImpl__ + +#pragma interface + +#include <java/nio/channels/FileChannel.h> +#include <gcj/array.h> + +extern "Java" +{ + namespace gnu + { + namespace java + { + namespace nio + { + namespace channels + { + class FileChannelImpl; + } + } + } + } + namespace java + { + namespace nio + { + class ByteBuffer; + class MappedByteBuffer; + namespace channels + { + class FileChannel; + class FileChannel$MapMode; + class FileLock; + class ReadableByteChannel; + class WritableByteChannel; + } + } + } +} + +class gnu::java::nio::channels::FileChannelImpl : public ::java::nio::channels::FileChannel +{ + + static void init(); +public: + FileChannelImpl(); + static ::gnu::java::nio::channels::FileChannelImpl * create(::java::io::File *, jint); +private: + FileChannelImpl(::java::io::File *, jint); +public: // actually package-private + FileChannelImpl(jint, jint); +private: + jint open(::java::lang::String *, jint); +public: + jint available(); +private: + jlong implPosition(); + void seek(jlong); + void implTruncate(jlong); +public: + void unlock(jlong, jlong); + jlong size(); +public: // actually protected + void implCloseChannel(); + void finalize(); +public: + jint read(::java::nio::ByteBuffer *); + jint read(::java::nio::ByteBuffer *, jlong); + jint read(); + jint read(JArray< jbyte > *, jint, jint); + jlong read(JArray< ::java::nio::ByteBuffer * > *, jint, jint); + jint write(::java::nio::ByteBuffer *); + jint write(::java::nio::ByteBuffer *, jlong); + void write(JArray< jbyte > *, jint, jint); + void write(jint); + jlong write(JArray< ::java::nio::ByteBuffer * > *, jint, jint); + ::java::nio::MappedByteBuffer * mapImpl(jchar, jlong, jint); + ::java::nio::MappedByteBuffer * map(::java::nio::channels::FileChannel$MapMode *, jlong, jlong); + void force(jboolean); +private: + jint smallTransferTo(jlong, jint, ::java::nio::channels::WritableByteChannel *); +public: + jlong transferTo(jlong, jlong, ::java::nio::channels::WritableByteChannel *); +private: + jint smallTransferFrom(::java::nio::channels::ReadableByteChannel *, jlong, jint); +public: + jlong transferFrom(::java::nio::channels::ReadableByteChannel *, jlong, jlong); + ::java::nio::channels::FileLock * tryLock(jlong, jlong, jboolean); +private: + jboolean lock(jlong, jlong, jboolean, jboolean); +public: + ::java::nio::channels::FileLock * lock(jlong, jlong, jboolean); + jlong position(); + ::java::nio::channels::FileChannel * position(jlong); + ::java::nio::channels::FileChannel * truncate(jlong); + jint getNativeFD(); + static const jint READ = 1; + static const jint WRITE = 2; + static const jint APPEND = 4; + static const jint EXCL = 8; + static const jint SYNC = 16; + static const jint DSYNC = 32; +private: + jint __attribute__((aligned(__alignof__( ::java::nio::channels::FileChannel)))) fd; + jlong pos; + jint mode; +public: + static ::gnu::java::nio::channels::FileChannelImpl * in; + static ::gnu::java::nio::channels::FileChannelImpl * out; + static ::gnu::java::nio::channels::FileChannelImpl * err; + static ::java::lang::Class class$; +}; + +#endif // __gnu_java_nio_channels_FileChannelImpl__ diff --git a/libjava/gnu/java/nio/channels/FileChannelImpl.java b/libjava/gnu/java/nio/channels/FileChannelImpl.java new file mode 100644 index 000000000..c1f79a436 --- /dev/null +++ b/libjava/gnu/java/nio/channels/FileChannelImpl.java @@ -0,0 +1,544 @@ +/* FileChannelImpl.java -- + Copyright (C) 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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.java.nio.FileLockImpl; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.NonReadableChannelException; +import java.nio.channels.NonWritableChannelException; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * 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 final class FileChannelImpl extends FileChannel +{ + // These are mode values for open(). + public static final int READ = 1; + public static final int WRITE = 2; + public static final int APPEND = 4; + + // EXCL is used only when making a temp file. + public static final int EXCL = 8; + public static final int SYNC = 16; + public static final int DSYNC = 32; + + private static native void init(); + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javanio"); + } + + init(); + } + + /** + * 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; + + private long pos; + private int mode; + + public FileChannelImpl () + { + } + + /* Open a file. MODE is a combination of the above mode flags. */ + /* This is a static factory method, so that VM implementors can decide + * substitute subclasses of FileChannelImpl. */ + public static FileChannelImpl create(File file, int mode) + throws FileNotFoundException + { + return new FileChannelImpl(file, mode); + } + + /* Open a file. MODE is a combination of the above mode flags. */ + private FileChannelImpl (File file, int mode) throws FileNotFoundException + { + final String path = file.getPath(); + fd = open (path, mode); + this.mode = mode; + + // First open the file and then check if it is a a directory + // to avoid race condition. + if (file.isDirectory()) + { + try + { + close(); + } + catch (IOException e) + { + /* ignore it */ + } + + throw new FileNotFoundException(path + " is a directory"); + } + } + + /* Used by init() (native code) */ + FileChannelImpl (int fd, int mode) + { + this.fd = fd; + this.mode = mode; + } + + public static FileChannelImpl in; + public static FileChannelImpl out; + public static FileChannelImpl err; + + private native int open (String path, int mode) throws FileNotFoundException; + + public native int available () throws IOException; + private native long implPosition () throws IOException; + private native void seek (long newPosition) throws IOException; + private native void implTruncate (long size) throws IOException; + + public native void unlock (long pos, long len) throws IOException; + + public native long size () throws IOException; + + protected native void implCloseChannel() throws IOException; + + /** + * Makes sure the Channel is properly closed. + */ + protected void finalize() throws IOException + { + this.close(); + } + + public int read (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 int read (ByteBuffer dst, long position) + throws IOException + { + if (position < 0) + throw new IllegalArgumentException (); + long oldPosition = implPosition (); + position (position); + int result = read(dst); + position (oldPosition); + + 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 + { + int len = src.remaining (); + if (src.hasArray()) + { + byte[] buffer = src.array(); + write(buffer, src.arrayOffset() + src.position(), len); + src.position(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 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 = write(src); + seek (oldPosition); + + return result; + } + + 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 (); + } + + // like transferTo, but with a count of less than 2Gbytes + private int smallTransferTo (long position, int count, + WritableByteChannel target) + throws IOException + { + ByteBuffer buffer; + try + { + // Try to use a mapped buffer if we can. If this fails for + // any reason we'll fall back to using a ByteBuffer. + buffer = map (MapMode.READ_ONLY, position, count); + } + catch (IOException e) + { + buffer = ByteBuffer.allocate (count); + read (buffer, position); + buffer.flip(); + } + + return target.write (buffer); + } + + 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 (); + + final int pageSize = 65536; + long total = 0; + + while (count > 0) + { + int transferred + = smallTransferTo (position, (int)Math.min (count, pageSize), + target); + if (transferred < 0) + break; + total += transferred; + position += transferred; + count -= transferred; + } + + return total; + } + + // like transferFrom, but with a count of less than 2Gbytes + private int smallTransferFrom (ReadableByteChannel src, long position, + int count) + throws IOException + { + ByteBuffer buffer = null; + + if (src instanceof FileChannel) + { + try + { + // Try to use a mapped buffer if we can. If this fails + // for any reason we'll fall back to using a ByteBuffer. + buffer = ((FileChannel)src).map (MapMode.READ_ONLY, position, + count); + } + catch (IOException e) + { + } + } + + if (buffer == null) + { + buffer = ByteBuffer.allocate ((int) count); + src.read (buffer); + buffer.flip(); + } + + return write (buffer, position); + } + + 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 (); + + final int pageSize = 65536; + long total = 0; + + while (count > 0) + { + int transferred = smallTransferFrom (src, position, + (int)Math.min (count, pageSize)); + if (transferred < 0) + break; + total += transferred; + position += transferred; + count -= transferred; + } + + return total; + } + + 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(); + boolean lockable = lock(position, size, shared, false); + completed = true; + return (lockable + ? new FileLockImpl(this, position, size, shared) + : null); + } + 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) throws IOException; + + 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, true); + 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 (); + + if (size < size ()) + implTruncate (size); + + return this; + } + + /** + * @return The native file descriptor. + */ + public int getNativeFD() + { + return fd; + } +} diff --git a/libjava/gnu/java/nio/channels/natFileChannelEcos.cc b/libjava/gnu/java/nio/channels/natFileChannelEcos.cc new file mode 100644 index 000000000..78575e7e6 --- /dev/null +++ b/libjava/gnu/java/nio/channels/natFileChannelEcos.cc @@ -0,0 +1,192 @@ +// 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> +#include <gnu/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 gnu::java::nio::MappedByteBufferImpl; +using java::io::InterruptedIOException; +using java::io::FileNotFoundException; +using java::lang::ArrayIndexOutOfBoundsException; +using java::lang::NullPointerException; +using gnu::java::nio::channels::FileChannelImpl; + +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 +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) +{ + return true; +} + +void +FileChannelImpl::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 +} +#endif + +jint +FileChannelImpl::open (jstring, jint) +{ + return fd; +} + +void +FileChannelImpl::write (jint) +{ + char d = (char) b; + ::diag_write (&d, 1); +} + +void +FileChannelImpl::write (jbyteArray b, jint offset, jint len) +{ + if (! b) + throw new NullPointerException; + if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b)) + throw new ArrayIndexOutOfBoundsException; + char *bytes = (char *)elements (b) + offset; + ::diag_write (bytes, len); +} + +void +FileChannelImpl::implCloseChannel (void) +{ +} + +void +FileChannelImpl::implTruncate (jlong) +{ +} + +void +FileChannelImpl::seek (jlong) +{ +} + +jlong +FileChannelImpl::size (void) +{ + return 0; +} + +jlong +FileChannelImpl::implPosition (void) +{ + return 0; +} + +jint +FileChannelImpl::read (void) +{ + return 0; +} + +jint +FileChannelImpl::read (jbyteArray buffer, jint offset, jint count) +{ + return 0; +} + +jint +FileChannelImpl::available (void) +{ + return 0; +} + +jboolean +FileChannelImpl::lock (jlong, jlong, jboolean, jboolean) +{ + throw new IOException (JvNewStringLatin1 + ("gnu.java.nio.FileChannelImpl.lock() not implemented")); +} + +void +FileChannelImpl::unlock (jlong, jlong) +{ + throw new IOException (JvNewStringLatin1 + ("gnu.java.nio.channels.FileChannelImpl.unlock() not implemented")); +} + +java::nio::MappedByteBuffer * +FileChannelImpl::mapImpl (jchar, jlong, jint) +{ + return NULL; +} + +void +MappedByteBufferImpl::unmapImpl () +{ +} + +void +MappedByteBufferImpl::loadImpl () +{ +} + +jboolean +MappedByteBufferImpl::isLoadedImpl () +{ + return true; +} + +void +MappedByteBufferImpl::forceImpl () +{ +} diff --git a/libjava/gnu/java/nio/channels/natFileChannelPosix.cc b/libjava/gnu/java/nio/channels/natFileChannelPosix.cc new file mode 100644 index 000000000..e05904c50 --- /dev/null +++ b/libjava/gnu/java/nio/channels/natFileChannelPosix.cc @@ -0,0 +1,557 @@ + +// natFileChannelImplPosix.cc - Native part of FileChannelImpl class. + +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007 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/StringBuffer.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> + +// Use overload resolution to find out the argument types. +// E.g. Solaris 2.6 uses different argument types for munmap and msync. +// This is in case _POSIX_C_SOURCES is smaller than 3. + +template <typename T_implPtr, typename T_implLen> +static inline int +munmap_adaptor(int (*munmap)(T_implPtr caddr, T_implLen sizet), + void* caddr, size_t sizet) +{ + return munmap ((T_implPtr) caddr, (T_implLen) sizet); +} + +template <typename T_implPtr, typename T_implLen, typename T_msync> +static inline int +msync_adaptor(int (*msync)(T_implPtr caddr, T_implLen sizet, T_msync msynct), + void* caddr, size_t sizet, int msynct) +{ + return msync ((T_implPtr) caddr, (T_implLen) sizet, (T_msync) msynct); +} +#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) + { + // We choose the formatting here for JDK compatibility, believe + // it or not. + ::java::lang::StringBuffer *msg = new ::java::lang::StringBuffer (path); + msg->append (JvNewStringUTF (" (")); + msg->append (JvNewStringUTF (strerror (errno))); + msg->append (JvNewStringUTF (")")); + throw new ::java::io::FileNotFoundException (msg->toString ()); + } + + 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))); + continue; + } + + 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) size)) + throw new IOException (JvNewStringLatin1 (strerror (errno))); + if (pos > size + && ::lseek (fd, (off_t) size, SEEK_SET) == -1) + 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) + int 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 = (int) (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_RDLCK : F_WRLCK; + 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; + + // If the file is too short, we must extend it. While using + // ftruncate() to extend a file is not portable in general, it + // should work on all systems where you can mmap() a file. + struct stat st; + if (fstat (fd, &st) == -1) + throw new IOException (JvNewStringLatin1 (strerror (errno))); + if (position + size > st.st_size) + { + if (ftruncate (fd, position + size) == -1) + throw new IOException (JvNewStringLatin1 (strerror (errno))); + } + } + 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 == (void *) 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_adaptor(munmap, implPtr, implLen); +#endif +} + +void +MappedByteBufferImpl::loadImpl () +{ +} + +jboolean +MappedByteBufferImpl::isLoadedImpl () +{ + return true; +} + +void +MappedByteBufferImpl::forceImpl () +{ +#if defined(HAVE_MMAP) + ::msync_adaptor(msync, 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 000000000..ab238e623 --- /dev/null +++ b/libjava/gnu/java/nio/channels/natFileChannelWin32.cc @@ -0,0 +1,466 @@ +// 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) +{ + DWORD flags = 0; + OVERLAPPED ovlpd; + + ZeroMemory(&ovlpd,sizeof(OVERLAPPED)); + + if(!shared) + flags |= LOCKFILE_EXCLUSIVE_LOCK; + if(!wait) + flags |= LOCKFILE_FAIL_IMMEDIATELY; + + ovlpd.Offset = (DWORD)pos; + ovlpd.OffsetHigh = pos>>32; + + DWORD lenlow = (DWORD)len; + DWORD lenhigh = len>>32; + + BOOL ret = LockFileEx((HANDLE)fd,flags,0,lenlow,lenhigh,&ovlpd); + + if(ret==ERROR_IO_PENDING && !shared && wait) + ret = GetOverlappedResult((HANDLE)fd,&ovlpd,NULL,wait); + + if(!ret) + _Jv_ThrowIOException(GetLastError()); + + return true; +} + +void +FileChannelImpl::unlock (jlong pos, jlong len) +{ + OVERLAPPED ovlpd; + + ZeroMemory(&ovlpd,sizeof(OVERLAPPED)); + + ovlpd.Offset = (DWORD)pos; + ovlpd.OffsetHigh = pos>>32; + + DWORD lenlow = (DWORD)len; + DWORD lenhigh = len>>32; + + BOOL ret = UnlockFileEx((HANDLE)fd,0,lenlow,lenhigh,&ovlpd); + + if(!ret) + _Jv_ThrowIOException(GetLastError()); +} + +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 () +{ +} |