mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-18 12:41:25 +08:00
FileChannelImpl.java: New class, renamed from java/nio/channels.
* gnu/java/nio/channels/FileChannelImpl.java: New class, renamed from java/nio/channels. Don't depend on FileDescriptor. (in, out, err): New static fields. (mode): New field. (SET, CUR, READ, WRITE, APPEND, EXCL, SYNC, DSYNC): Moved constants from FileDescriptor. (by): Removed MappedByteBuffer field. (map): New working implementation. * gnu/java/nio/channels/natFileChannelPosix.cc: New file, though some code "ported" from natFileDescriptoPosix.cc. * gnu/java/nio/channels/natFileChannelEcos.cc: Likewise. * gnu/java/nio/channels/natFileChannelWin32.cc Likewise. From-SVN: r78659
This commit is contained in:
parent
2f537af9e7
commit
612e660987
420
libjava/gnu/java/nio/channels/FileChannelImpl.java
Normal file
420
libjava/gnu/java/nio/channels/FileChannelImpl.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
159
libjava/gnu/java/nio/channels/natFileChannelEcos.cc
Normal file
159
libjava/gnu/java/nio/channels/natFileChannelEcos.cc
Normal file
@ -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"));
|
||||
}
|
522
libjava/gnu/java/nio/channels/natFileChannelPosix.cc
Normal file
522
libjava/gnu/java/nio/channels/natFileChannelPosix.cc
Normal file
@ -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
|
||||
}
|
432
libjava/gnu/java/nio/channels/natFileChannelWin32.cc
Normal file
432
libjava/gnu/java/nio/channels/natFileChannelWin32.cc
Normal file
@ -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 ()
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user