1 // natFileDescriptorWin32.cc - Native part of FileDescriptor class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
12 // FIXME: In order to support interrupting of IO operations, we
13 // need to change to use the windows asynchronous IO functions
25 #include <java/io/FileDescriptor.h>
26 #include <java/io/SyncFailedException.h>
27 #include <java/io/IOException.h>
28 #include <java/io/InterruptedIOException.h>
29 #include <java/io/EOFException.h>
30 #include <java/lang/ArrayIndexOutOfBoundsException.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/String.h>
33 #include <java/lang/Thread.h>
34 #include <java/io/FileNotFoundException.h>
36 // FIXME: casting a FILE (pointer) to a jint will not work on Win64 --
37 // we should be using gnu.gcj.RawData's.
40 java::io::FileDescriptor::init(void)
42 in
= new java::io::FileDescriptor((jint
)(GetStdHandle (STD_INPUT_HANDLE
)));
43 out
= new java::io::FileDescriptor((jint
)(GetStdHandle (STD_OUTPUT_HANDLE
)));
44 err
= new java::io::FileDescriptor((jint
)(GetStdHandle (STD_ERROR_HANDLE
)));
50 static LPVOID last
= NULL
;
56 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
|
57 FORMAT_MESSAGE_FROM_SYSTEM
|
58 FORMAT_MESSAGE_IGNORE_INSERTS
,
61 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
73 java::io::FileDescriptor::valid (void) {
74 BY_HANDLE_FILE_INFORMATION info
;
75 return GetFileInformationByHandle ((HANDLE
)fd
, &info
) != 0;
79 java::io::FileDescriptor::sync (void) {
80 if (! FlushFileBuffers ((HANDLE
)fd
))
81 throw new SyncFailedException (JvNewStringLatin1 (winerr ()));
85 java::io::FileDescriptor::open (jstring path
, jint jflags
) {
89 DWORD create
= OPEN_EXISTING
;
90 char buf
[MAX_PATH
] = "";
92 jsize total
= JvGetStringUTFRegion(path
, 0, path
->length(), buf
);
95 JvAssert((jflags
& READ
) || (jflags
& WRITE
));
97 if ((jflags
& READ
) && (jflags
& WRITE
))
99 access
= GENERIC_READ
| GENERIC_WRITE
;
101 create
= OPEN_ALWAYS
;
103 create
= CREATE_ALWAYS
;
105 else if(jflags
& READ
)
106 access
= GENERIC_READ
;
109 access
= GENERIC_WRITE
;
111 create
= OPEN_ALWAYS
;
113 create
= CREATE_ALWAYS
;
116 handle
= CreateFile(buf
, access
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, create
, 0, NULL
);
118 if (handle
== INVALID_HANDLE_VALUE
)
120 char msg
[MAX_PATH
+ 1000];
121 sprintf (msg
, "%s: %s", buf
, winerr ());
122 throw new FileNotFoundException (JvNewStringLatin1 (msg
));
125 // For APPEND mode, move the file pointer to the end of the file.
128 DWORD low
= SetFilePointer (handle
, 0, NULL
, FILE_END
);
129 if ((low
== 0xffffffff) && (GetLastError () != NO_ERROR
))
130 throw new FileNotFoundException (JvNewStringLatin1 (winerr ()));
136 java::io::FileDescriptor::write (jint b
)
139 jbyte buf
= (jbyte
)b
;
141 if (WriteFile ((HANDLE
)fd
, &buf
, 1, &bytesWritten
, NULL
))
143 if (java::lang::Thread::interrupted())
145 InterruptedIOException
*iioe
= new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
146 iioe
->bytesTransferred
= bytesWritten
;
149 if (bytesWritten
!= 1)
150 throw new IOException (JvNewStringLatin1 (winerr ()));
153 throw new IOException (JvNewStringLatin1 (winerr ()));
154 // FIXME: loop until bytesWritten == 1
158 java::io::FileDescriptor::write(jbyteArray b
, jint offset
, jint len
)
161 throw new java::lang::NullPointerException
;
162 if(offset
< 0 || len
< 0 || offset
+ len
> JvGetArrayLength (b
))
163 throw new java::lang::ArrayIndexOutOfBoundsException
;
165 jbyte
*buf
= elements (b
) + offset
;
167 if (WriteFile ((HANDLE
)fd
, buf
, len
, &bytesWritten
, NULL
))
169 if (java::lang::Thread::interrupted())
171 InterruptedIOException
*iioe
= new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
172 iioe
->bytesTransferred
= bytesWritten
;
177 throw new IOException (JvNewStringLatin1 (winerr ()));
178 // FIXME: loop until bytesWritten == len
182 java::io::FileDescriptor::close (void)
184 HANDLE save
= (HANDLE
)fd
;
185 fd
= (jint
)INVALID_HANDLE_VALUE
;
186 if (! CloseHandle (save
))
187 throw new IOException (JvNewStringLatin1 (winerr ()));
191 java::io::FileDescriptor::setLength(jlong pos
)
193 LONG liOrigFilePointer
;
194 LONG liNewFilePointer
;
195 LONG liEndFilePointer
;
197 // Get the original file pointer.
198 if (SetFilePointer((HANDLE
) fd
, (LONG
) 0, &liOrigFilePointer
,
199 FILE_CURRENT
) != (BOOL
) 0
200 && (GetLastError() != NO_ERROR
))
201 throw new IOException (JvNewStringLatin1 (winerr ()));
203 // Get the length of the file.
204 if (SetFilePointer((HANDLE
) fd
, (LONG
) 0, &liEndFilePointer
,
205 FILE_END
) != (BOOL
) 0
206 && (GetLastError() != NO_ERROR
))
207 throw new IOException (JvNewStringLatin1 (winerr ()));
209 if ((jlong
)liEndFilePointer
== pos
)
211 // Restore the file pointer.
212 if (liOrigFilePointer
!= liEndFilePointer
)
214 if (SetFilePointer((HANDLE
) fd
, liOrigFilePointer
, &liNewFilePointer
,
215 FILE_BEGIN
) != (BOOL
) 0
216 && (GetLastError() != NO_ERROR
))
217 throw new IOException (JvNewStringLatin1 (winerr ()));
222 // Seek to the new end of file.
223 if (SetFilePointer((HANDLE
) fd
, (LONG
) pos
, &liNewFilePointer
,
224 FILE_BEGIN
) != (BOOL
) 0
225 && (GetLastError() != NO_ERROR
))
226 throw new IOException (JvNewStringLatin1 (winerr ()));
228 // Truncate the file at this point.
229 if (SetEndOfFile((HANDLE
) fd
) != (BOOL
) 0 && (GetLastError() != NO_ERROR
))
230 throw new IOException (JvNewStringLatin1 (winerr ()));
232 if (liOrigFilePointer
< liNewFilePointer
)
234 // Restore the file pointer.
235 if (SetFilePointer((HANDLE
) fd
, liOrigFilePointer
, &liNewFilePointer
,
236 FILE_BEGIN
) != (BOOL
) 0
237 && (GetLastError() != NO_ERROR
))
238 throw new IOException (JvNewStringLatin1 (winerr ()));
243 java::io::FileDescriptor::seek (jlong pos
, jint whence
, jboolean eof_trunc
)
245 JvAssert (whence
== SET
|| whence
== CUR
);
247 jlong len
= length();
248 jlong here
= getFilePointer();
251 && ((whence
== SET
&& pos
> len
) || (whence
== CUR
&& here
+ pos
> len
)))
257 LONG high
= pos
>> 32;
258 DWORD low
= SetFilePointer ((HANDLE
)fd
, (DWORD
)(0xffffffff & pos
), &high
, whence
== SET
? FILE_BEGIN
: FILE_CURRENT
);
259 if ((low
== 0xffffffff) && (GetLastError () != NO_ERROR
))
260 throw new IOException (JvNewStringLatin1 (winerr ()));
265 java::io::FileDescriptor::getFilePointer(void)
268 DWORD low
= SetFilePointer ((HANDLE
)fd
, 0, &high
, FILE_CURRENT
);
269 if ((low
== 0xffffffff) && (GetLastError() != NO_ERROR
))
270 throw new IOException (JvNewStringLatin1 (winerr ()));
271 return (((jlong
)high
) << 32L) | (jlong
)low
;
275 java::io::FileDescriptor::length(void)
280 low
= GetFileSize ((HANDLE
)fd
, &high
);
281 // FIXME: Error checking
282 return (((jlong
)high
) << 32L) | (jlong
)low
;
286 java::io::FileDescriptor::read(void)
291 if (! ReadFile ((HANDLE
)fd
, &buf
, 1, &read
, NULL
))
293 if (GetLastError () == ERROR_BROKEN_PIPE
)
296 throw new IOException (JvNewStringLatin1 (winerr ()));
302 return (jint
)(buf
& 0xff);
306 java::io::FileDescriptor::read(jbyteArray buffer
, jint offset
, jint count
)
309 throw new java::lang::NullPointerException
;
311 jsize bsize
= JvGetArrayLength (buffer
);
312 if (offset
< 0 || count
< 0 || offset
+ count
> bsize
)
313 throw new java::lang::ArrayIndexOutOfBoundsException
;
315 // Must return 0 if an attempt is made to read 0 bytes.
319 jbyte
*bytes
= elements (buffer
) + offset
;
322 if (! ReadFile((HANDLE
)fd
, bytes
, count
, &read
, NULL
))
324 if (GetLastError () == ERROR_BROKEN_PIPE
)
327 throw new IOException (JvNewStringLatin1 (winerr ()));
330 if (read
== 0) return -1;
336 java::io::FileDescriptor::available(void)
339 return length() - getFilePointer();