mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
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
This commit is contained in:
@@ -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()
|
||||
FileDescriptor(ByteChannel channel)
|
||||
{
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
// Open a file. MODE is a combination of the above mode flags.
|
||||
FileDescriptor (String path, int mode) throws FileNotFoundException
|
||||
{
|
||||
fd = open (path, mode);
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
// 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"));
|
||||
}
|
||||
@@ -1,467 +0,0 @@
|
||||
// natFileDescriptor.cc - Native part of FileDescriptor class.
|
||||
|
||||
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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 "posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.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
|
||||
|
||||
#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/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/io/FileNotFoundException.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
struct stat sb;
|
||||
return fd >= 0 && ::fstat (fd, &sb) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
java::io::FileDescriptor::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
|
||||
}
|
||||
|
||||
jint
|
||||
java::io::FileDescriptor::open (jstring path, jint jflags)
|
||||
{
|
||||
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)", buf, strerror (errno));
|
||||
throw new FileNotFoundException (JvNewStringLatin1 (msg));
|
||||
}
|
||||
|
||||
_Jv_platform_close_on_exec (fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
java::io::FileDescriptor::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())
|
||||
{
|
||||
InterruptedIOException *iioe
|
||||
= new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
|
||||
iioe->bytesTransferred = r == -1 ? 0 : r;
|
||||
throw iioe;
|
||||
}
|
||||
if (errno != EINTR)
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
}
|
||||
}
|
||||
position++;
|
||||
}
|
||||
|
||||
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 *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;
|
||||
position += r;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
java::io::FileDescriptor::close (void)
|
||||
{
|
||||
jint save = fd;
|
||||
fd = -1;
|
||||
if (::close (save))
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
}
|
||||
|
||||
void
|
||||
java::io::FileDescriptor::setLength (jlong pos)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
if (::fstat (fd, &sb))
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
|
||||
if ((jlong) sb.st_size == pos)
|
||||
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 < pos)
|
||||
{
|
||||
if (::lseek (fd, (off_t) (pos - 1), SEEK_SET) == -1)
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
char out = '\0';
|
||||
int r = ::write (fd, &out, 1);
|
||||
if (r <= 0 || ::lseek (fd, position, SEEK_SET) == -1)
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (::ftruncate (fd, (off_t) pos))
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
position = pos;
|
||||
}
|
||||
#else /* HAVE_FTRUNCATE */
|
||||
throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
|
||||
#endif /* HAVE_FTRUNCATE */
|
||||
}
|
||||
|
||||
jint
|
||||
java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
|
||||
{
|
||||
JvAssert (whence == SET || whence == CUR);
|
||||
|
||||
if (eof_trunc)
|
||||
{
|
||||
jlong len = getLength ();
|
||||
if (whence == SET)
|
||||
{
|
||||
if (pos > len)
|
||||
pos = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
jlong here = getFilePointer ();
|
||||
if (here + pos > len)
|
||||
{
|
||||
pos = len;
|
||||
whence = SET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
|
||||
if (r == -1)
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
position = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
jlong
|
||||
java::io::FileDescriptor::getLength (void)
|
||||
{
|
||||
struct stat sb;
|
||||
if (::fstat (fd, &sb))
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
return sb.st_size;
|
||||
}
|
||||
|
||||
jlong
|
||||
java::io::FileDescriptor::getFilePointer (void)
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
jint
|
||||
java::io::FileDescriptor::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);
|
||||
position++;
|
||||
return b & 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;
|
||||
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);
|
||||
position += r;
|
||||
return r;
|
||||
}
|
||||
|
||||
jint
|
||||
java::io::FileDescriptor::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
|
||||
}
|
||||
|
||||
void
|
||||
java::io::FileDescriptor::lock (jlong pos, jint len, jboolean shared)
|
||||
{
|
||||
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, F_SETLK, &lockdata) == -1)
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
}
|
||||
|
||||
jboolean
|
||||
java::io::FileDescriptor::tryLock (jlong pos, jint len, jboolean shared)
|
||||
{
|
||||
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, F_GETLK, &lockdata) == -1)
|
||||
throw new IOException (JvNewStringLatin1 (strerror (errno)));
|
||||
|
||||
return lockdata.l_type == F_UNLCK;
|
||||
}
|
||||
|
||||
void
|
||||
java::io::FileDescriptor::unlock (jlong pos, jint 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)));
|
||||
}
|
||||
@@ -1,373 +0,0 @@
|
||||
// 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"));
|
||||
}
|
||||
Reference in New Issue
Block a user