Commit ef3916ef by Per Bothner

FileDescriptor.java: Implement on top of FileChannel.


	* java/io/FileDescriptor.java:  Implement on top of FileChannel.
	Remove native methods.

	* java/io/natFileDescriptorEcos.cc:  Remove file.
	* java/io/natFileDescriptorPosix.cc:  Remove file.
	* java/io/natFileDescriptorWin32.cc:  Remove file.
	* java/io/FileInputStream.java (ch):  Change type to FileChannelImpl.
	(<init>(File)):  Allocate a FileChannelImpl, not a FileDescriptor.
	(<init>(FileChannelImpl)):  New package-private constructor.
	(<init>(FileDescriptor)):  Extract FileChannelImpl from arg.
	(available, close, read, skip):  Implement using FileChannelImpl.
	(getFD):  Allocate FileDescriptor if needed.
	(getChannel):  Is now trivial.
	* java/io/FileOutputStream.java:  Corresponding changes.
	* java/io/RandomAccessFile.java:  Corresponding changes.

From-SVN: r78661
parent d5fe0403
......@@ -39,7 +39,9 @@ exception statement from your version. */
package java.io;
import gnu.classpath.Configuration;
import java.nio.channels.ByteChannel;
import java.nio.channels.FileChannel;
import gnu.java.nio.channels.FileChannelImpl;
/**
* This class represents an opaque file handle as a Java class. It should
......@@ -57,82 +59,35 @@ public final class FileDescriptor
* stream. This will usually be accessed through the
* <code>System.in</code>variable.
*/
public static final FileDescriptor in = null;
public static final FileDescriptor in
= new FileDescriptor (FileChannelImpl.in);
/**
* A <code>FileDescriptor</code> representing the system standard output
* stream. This will usually be accessed through the
* <code>System.out</code>variable.
*/
public static final FileDescriptor out = null;
public static final FileDescriptor out
= new FileDescriptor (FileChannelImpl.out);
/**
* A <code>FileDescriptor</code> representing the system standard error
* stream. This will usually be accessed through the
* <code>System.err</code>variable.
*/
public static final FileDescriptor err = null;
public static final FileDescriptor err
= new FileDescriptor (FileChannelImpl.err);
private static native void init();
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary("javaio");
}
init();
}
// 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;
private long position = 0;
final ByteChannel channel;
/**
* This method is used to initialize an invalid FileDescriptor object.
*/
public FileDescriptor()
{
}
// Open a file. MODE is a combination of the above mode flags.
FileDescriptor (String path, int mode) throws FileNotFoundException
FileDescriptor(ByteChannel channel)
{
fd = open (path, mode);
this.channel = channel;
}
// Attach to an already-opened file. This is not private because we
// need access to it from other packages, for instance java.net.
// Ordinarily that wouldn't work, either, but in our case we know
// the access comes from C++, where "package private" is translated
// into "public". Eww.
FileDescriptor (int desc)
{
fd = desc;
}
/**
* This method forces all data that has not yet been physically written to
......@@ -143,7 +98,23 @@ public final class FileDescriptor
* support this functionality or if an error occurs, then an exception
* will be thrown.
*/
public native void sync() throws SyncFailedException;
public void sync () throws SyncFailedException
{
if (channel instanceof FileChannel)
{
try
{
((FileChannel) channel).force(true);
}
catch (IOException ex)
{
if (ex instanceof SyncFailedException)
throw (SyncFailedException) ex;
else
throw new SyncFailedException(ex.getMessage());
}
}
}
/**
* This methods tests whether or not this object represents a valid open
......@@ -152,70 +123,8 @@ public final class FileDescriptor
* @return <code>true</code> if this object represents a valid
* native file handle, <code>false</code> otherwise
*/
public native boolean valid();
/**
* Opens the specified file in the specified mode. This can be done
* in one of the specified modes:
* <ul>
* <li>r - Read Only
* <li>rw - Read / Write
* <li>ra - Read / Write - append to end of file
* <li>rws - Read / Write - synchronous writes of data/metadata
* <li>rwd - Read / Write - synchronous writes of data.
*
* @param path Name of the file to open
* @param mode Mode to open
*
* @exception IOException If an error occurs.
*/
native int open(String path, int mode) throws FileNotFoundException;
/**
* Close the file descriptor.
*/
native void close() throws IOException;
/**
* Write oe byte of data.
*/
native void write(int b) throws IOException;
/**
* Write data.
*/
native void write(byte[] b, int offset, int len)
throws IOException, NullPointerException, IndexOutOfBoundsException;
/**
* Read one byte of data.
*/
native int read() throws IOException;
/**
* Read data.
*/
native int read(byte[] bytes, int offset, int len) throws IOException;
native int available() throws IOException;
// EOF_TRUNC is true if a request to seek past the end of file
// should actually stop at the end of file. If false, then a seek
// past the end is ok (and if a subsequent write occurs the file
// will grow).
native int seek(long pos, int whence, boolean eof_trunc) throws IOException;
native long getFilePointer() throws IOException;
native long getLength() throws IOException;
native void setLength(long pos) throws IOException;
native void lock(long pos, int len, boolean shared) throws IOException;
native boolean tryLock(long pos, int lent, boolean shared) throws IOException;
native void unlock(long pos, int len) throws IOException;
// When collected, close.
protected void finalize() throws Throwable
public boolean valid ()
{
if (valid())
close();
return channel.isOpen();
}
}
/* FileInputStream.java -- An input stream that reads from disk files.
Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 1998, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
......@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannelImpl;
import gnu.java.nio.channels.FileChannelImpl;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
......@@ -60,7 +60,7 @@ public class FileInputStream extends InputStream
*/
private FileDescriptor fd;
private FileChannel ch; /* cached associated file-channel */
private FileChannelImpl ch;
/**
* This method initializes a <code>FileInputStream</code> to read from the
......@@ -107,7 +107,7 @@ public class FileInputStream extends InputStream
if (file.isDirectory())
throw new FileNotFoundException(file.getPath() + " is a directory");
fd = new FileDescriptor(file.getPath(), FileDescriptor.READ);
ch = new FileChannelImpl (file.getPath(), FileChannelImpl.READ);
}
/**
......@@ -133,6 +133,12 @@ public class FileInputStream extends InputStream
s.checkRead(fdObj);
fd = fdObj;
ch = (FileChannelImpl) fdObj.channel;
}
FileInputStream(FileChannelImpl ch)
{
this.ch = ch;
}
/**
......@@ -156,7 +162,7 @@ public class FileInputStream extends InputStream
*/
public int available() throws IOException
{
return fd.available();
return ch.available();
}
/**
......@@ -168,8 +174,7 @@ public class FileInputStream extends InputStream
*/
public void close() throws IOException
{
if (fd.valid())
fd.close();
ch.close();
}
protected void finalize() throws IOException
......@@ -189,9 +194,12 @@ public class FileInputStream extends InputStream
*/
public final FileDescriptor getFD() throws IOException
{
if (!fd.valid())
throw new IOException();
return fd;
synchronized (this)
{
if (fd == null)
fd = new FileDescriptor (ch);
return fd;
}
}
/**
......@@ -207,7 +215,7 @@ public class FileInputStream extends InputStream
*/
public int read() throws IOException
{
return fd.read();
return ch.read();
}
/**
......@@ -258,7 +266,7 @@ public class FileInputStream extends InputStream
|| offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException();
return fd.read(buf, offset, len);
return ch.read(buf, offset, len);
}
/**
......@@ -281,9 +289,9 @@ public class FileInputStream extends InputStream
if (numBytes == 0)
return 0;
long curPos = fd.getFilePointer ();
long newPos = fd.seek (numBytes, FileDescriptor.CUR, true);
return newPos - curPos;
long oldPos = ch.position ();
ch.position(oldPos + numBytes);
return ch.position() - oldPos;
}
/**
......@@ -294,9 +302,6 @@ public class FileInputStream extends InputStream
*/
public synchronized FileChannel getChannel ()
{
if (ch == null)
ch = new FileChannelImpl (fd, false, this);
return ch;
}
......
/* FileOutputStream.java -- Writes to a file on disk.
Copyright (C) 1998, 2001, 2003 Free Software Foundation, Inc.
Copyright (C) 1998, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
......@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannelImpl;
import gnu.java.nio.channels.FileChannelImpl;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
......@@ -57,7 +57,7 @@ public class FileOutputStream extends OutputStream
{
private FileDescriptor fd;
private FileChannel ch; /* cached associated file-channel */
private FileChannelImpl ch;
/**
* This method initializes a <code>FileOutputStream</code> object to write
......@@ -84,10 +84,10 @@ public class FileOutputStream extends OutputStream
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkWrite(path);
fd = new FileDescriptor (path, (append
? FileDescriptor.WRITE
| FileDescriptor.APPEND
: FileDescriptor.WRITE));
ch = new FileChannelImpl (path, (append
? FileChannelImpl.WRITE
| FileChannelImpl.APPEND
: FileChannelImpl.WRITE));
}
/**
......@@ -188,6 +188,12 @@ public class FileOutputStream extends OutputStream
s.checkWrite(fdObj);
fd = fdObj;
ch = (FileChannelImpl) fdObj.channel;
}
FileOutputStream(FileChannelImpl ch)
{
this.ch = ch;
}
protected void finalize () throws IOException
......@@ -206,9 +212,12 @@ public class FileOutputStream extends OutputStream
*/
public final FileDescriptor getFD () throws IOException
{
if (! fd.valid())
throw new IOException ();
return fd;
synchronized (this)
{
if (fd == null)
fd = new FileDescriptor (ch);
return fd;
}
}
/**
......@@ -220,7 +229,7 @@ public class FileOutputStream extends OutputStream
*/
public void write (int b) throws IOException
{
fd.write (b);
ch.write (b);
}
/**
......@@ -255,7 +264,7 @@ public class FileOutputStream extends OutputStream
|| offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException ();
fd.write (buf, offset, len);
ch.write (buf, offset, len);
}
/**
......@@ -267,8 +276,7 @@ public class FileOutputStream extends OutputStream
*/
public void close () throws IOException
{
if (fd.valid())
fd.close();
ch.close();
}
/**
......@@ -279,9 +287,6 @@ public class FileOutputStream extends OutputStream
*/
public synchronized FileChannel getChannel()
{
if (ch == null)
ch = new FileChannelImpl (fd, true, this);
return ch;
}
......
/* RandomAccessFile.java -- Class supporting random file I/O
Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
......@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannelImpl;
import gnu.java.nio.channels.FileChannelImpl;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
......@@ -61,12 +61,12 @@ public class RandomAccessFile implements DataOutput, DataInput
{
// The underlying file.
private FileChannelImpl ch;
private FileDescriptor fd;
// The corresponding input and output streams.
private DataOutputStream out;
private DataInputStream in;
private FileChannel ch; /* cached associated file-channel */
/**
* This method initializes a new instance of <code>RandomAccessFile</code>
......@@ -119,18 +119,18 @@ public class RandomAccessFile implements DataOutput, DataInput
{
int fdmode;
if (mode.equals("r"))
fdmode = FileDescriptor.READ;
fdmode = FileChannelImpl.READ;
else if (mode.equals("rw"))
fdmode = FileDescriptor.READ | FileDescriptor.WRITE;
fdmode = FileChannelImpl.READ | FileChannelImpl.WRITE;
else if (mode.equals("rws"))
{
fdmode = (FileDescriptor.READ | FileDescriptor.WRITE
| FileDescriptor.SYNC);
fdmode = (FileChannelImpl.READ | FileChannelImpl.WRITE
| FileChannelImpl.SYNC);
}
else if (mode.equals("rwd"))
{
fdmode = (FileDescriptor.READ | FileDescriptor.WRITE
| FileDescriptor.DSYNC);
fdmode = (FileChannelImpl.READ | FileChannelImpl.WRITE
| FileChannelImpl.DSYNC);
}
else
throw new IllegalArgumentException ("invalid mode: " + mode);
......@@ -141,11 +141,12 @@ public class RandomAccessFile implements DataOutput, DataInput
{
s.checkRead(fileName);
if ((fdmode & FileDescriptor.WRITE) != 0)
if ((fdmode & FileChannelImpl.WRITE) != 0)
s.checkWrite(fileName);
}
fd = new FileDescriptor (fileName, fdmode);
ch = new FileChannelImpl (fileName, fdmode);
fd = new FileDescriptor(ch);
out = new DataOutputStream (new FileOutputStream (fd));
in = new DataInputStream (new FileInputStream (fd));
}
......@@ -158,8 +159,7 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public void close () throws IOException
{
if (fd.valid())
fd.close();
ch.close();
}
/**
......@@ -172,10 +172,12 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final FileDescriptor getFD () throws IOException
{
if (! fd.valid())
throw new IOException ();
return fd;
synchronized (this)
{
if (fd == null)
fd = new FileDescriptor (ch);
return fd;
}
}
/**
......@@ -188,7 +190,7 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public long getFilePointer () throws IOException
{
return fd.getFilePointer();
return ch.position();
}
/**
......@@ -206,7 +208,7 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public void setLength (long newLen) throws IOException
{
fd.setLength (newLen);
ch.truncate (newLen);
}
/**
......@@ -218,7 +220,7 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public long length () throws IOException
{
return fd.getLength ();
return ch.size();
}
/**
......@@ -702,7 +704,7 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public void seek (long pos) throws IOException
{
fd.seek (pos, FileDescriptor.SET, false);
ch.position(pos);
}
/**
......@@ -726,10 +728,13 @@ public class RandomAccessFile implements DataOutput, DataInput
if (numBytes == 0)
return 0;
long curPos = fd.getFilePointer ();
long newPos = fd.seek (numBytes, FileDescriptor.CUR, true);
return (int) (newPos - curPos);
long oldPos = ch.position();
long newPos = oldPos + numBytes;
long size = ch.size();
if (newPos > size)
newPos = size;
ch.position(newPos);
return (int) (ch.position() - oldPos);
}
/**
......@@ -962,9 +967,6 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final synchronized FileChannel getChannel ()
{
if (ch == null)
ch = new FileChannelImpl (fd, true, this);
return ch;
}
......
// 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"));
}
// natFileDescriptorWin32.cc - Native part of FileDescriptor class.
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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 <stdio.h>
#include <string.h>
#undef STRICT
#include <java/io/FileDescriptor.h>
#include <java/io/SyncFailedException.h>
#include <java/io/IOException.h>
#include <java/io/InterruptedIOException.h>
#include <java/io/EOFException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/String.h>
#include <java/lang/Thread.h>
#include <java/io/FileNotFoundException.h>
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
java::io::FileDescriptor::init(void)
{
in = new java::io::FileDescriptor((jint)(GetStdHandle (STD_INPUT_HANDLE)));
out = new java::io::FileDescriptor((jint)(GetStdHandle (STD_OUTPUT_HANDLE)));
err = new java::io::FileDescriptor((jint)(GetStdHandle (STD_ERROR_HANDLE)));
}
jboolean
java::io::FileDescriptor::valid (void) {
static bool bCanUseGetHandleInfo = testCanUseGetHandleInfo();
if (bCanUseGetHandleInfo)
{
/* As with UNIX, a "file" descriptor can be one of
a gazillion possible underlying things like a pipe
or socket, so we can't get too fancy here. */
DWORD dwFlags;
HANDLE h = (HANDLE) fd;
return GetHandleInformation (h, &dwFlags) != 0;
}
else
{
/* Can't use GetHandleInformation() for console handles on < WinNT 5. */
return true;
}
}
void
java::io::FileDescriptor::sync (void) {
if (! FlushFileBuffers ((HANDLE)fd))
{
DWORD dwErrorCode = GetLastError ();
throw new SyncFailedException (_Jv_WinStrError (dwErrorCode));
}
}
jint
java::io::FileDescriptor::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 == 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
java::io::FileDescriptor::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
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;
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
java::io::FileDescriptor::close (void)
{
HANDLE save = (HANDLE)fd;
fd = (jint)INVALID_HANDLE_VALUE;
if (! CloseHandle (save))
_Jv_ThrowIOException ();
}
void
java::io::FileDescriptor::setLength(jlong pos)
{
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 == pos)
{
// 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) pos, &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 ();
}
}
jint
java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
{
JvAssert (whence == SET || whence == CUR);
jlong len = getLength();
jlong here = getFilePointer();
if (eof_trunc
&& ((whence == SET && pos > len) || (whence == CUR && here + pos > len)))
{
whence = SET;
pos = len;
}
LONG high = pos >> 32;
DWORD low = SetFilePointer ((HANDLE)fd, (DWORD)(0xffffffff & pos), &high, whence == SET ? FILE_BEGIN : FILE_CURRENT);
if ((low == 0xffffffff) && (GetLastError () != NO_ERROR))
_Jv_ThrowIOException ();
return low;
}
jlong
java::io::FileDescriptor::getFilePointer(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
java::io::FileDescriptor::getLength(void)
{
DWORD high;
DWORD low;
low = GetFileSize ((HANDLE)fd, &high);
// FIXME: Error checking
return (((jlong)high) << 32L) | (jlong)low;
}
jint
java::io::FileDescriptor::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
java::io::FileDescriptor::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;
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
java::io::FileDescriptor::available(void)
{
// FIXME:
return getLength() - getFilePointer();
}
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"));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment