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
23 #include <java/io/FileDescriptor.h>
24 #include <java/io/SyncFailedException.h>
25 #include <java/io/IOException.h>
26 #include <java/io/InterruptedIOException.h>
27 #include <java/io/EOFException.h>
28 #include <java/lang/ArrayIndexOutOfBoundsException.h>
29 #include <java/lang/NullPointerException.h>
30 #include <java/lang/String.h>
31 #include <java/lang/Thread.h>
32 #include <java/io/FileNotFoundException.h>
34 static bool testCanUseGetHandleInfo()
36 /* Test to see whether GetHandleInformation can be used
37 for console input or screen buffers. This is better
38 a kludgy OS version check. */
40 return GetHandleInformation (GetStdHandle (STD_INPUT_HANDLE
),
44 // FIXME: casting a FILE (pointer) to a jint will not work on Win64 --
45 // we should be using gnu.gcj.RawData's.
48 java::io::FileDescriptor::init(void)
50 in
= new java::io::FileDescriptor((jint
)(GetStdHandle (STD_INPUT_HANDLE
)));
51 out
= new java::io::FileDescriptor((jint
)(GetStdHandle (STD_OUTPUT_HANDLE
)));
52 err
= new java::io::FileDescriptor((jint
)(GetStdHandle (STD_ERROR_HANDLE
)));
56 java::io::FileDescriptor::valid (void) {
57 static bool bCanUseGetHandleInfo
= testCanUseGetHandleInfo();
58 if (bCanUseGetHandleInfo
)
60 /* As with UNIX, a "file" descriptor can be one of
61 a gazillion possible underlying things like a pipe
62 or socket, so we can't get too fancy here. */
64 HANDLE h
= (HANDLE
) fd
;
65 return GetHandleInformation (h
, &dwFlags
) != 0;
69 /* Can't use GetHandleInformation() for console handles on < WinNT 5. */
75 java::io::FileDescriptor::sync (void) {
76 if (! FlushFileBuffers ((HANDLE
)fd
))
78 DWORD dwErrorCode
= GetLastError ();
79 throw new SyncFailedException (_Jv_WinStrError (dwErrorCode
));
84 java::io::FileDescriptor::open (jstring path
, jint jflags
) {
88 DWORD create
= OPEN_EXISTING
;
90 JV_TEMP_STRING_WIN32(cpath
, path
)
92 JvAssert((jflags
& READ
) || (jflags
& WRITE
));
94 if ((jflags
& READ
) && (jflags
& WRITE
))
96 access
= GENERIC_READ
| GENERIC_WRITE
;
98 create
= CREATE_NEW
; // this will raise error if file exists.
100 create
= OPEN_ALWAYS
; // equivalent to O_CREAT
102 else if (jflags
& READ
)
104 access
= GENERIC_READ
;
105 create
= OPEN_EXISTING
; // ignore EXCL
109 access
= GENERIC_WRITE
;
112 else if (jflags
& APPEND
)
113 create
= OPEN_ALWAYS
;
115 create
= CREATE_ALWAYS
;
118 handle
= CreateFile(cpath
, access
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
119 NULL
, create
, 0, NULL
);
121 if (handle
== INVALID_HANDLE_VALUE
)
123 DWORD dwErrorCode
= GetLastError ();
124 throw new FileNotFoundException (_Jv_WinStrError (cpath
, dwErrorCode
));
127 // For APPEND mode, move the file pointer to the end of the file.
130 DWORD low
= SetFilePointer (handle
, 0, NULL
, FILE_END
);
131 if ((low
== 0xffffffff) && (GetLastError () != NO_ERROR
))
133 DWORD dwErrorCode
= GetLastError ();
134 throw new FileNotFoundException (_Jv_WinStrError (cpath
, dwErrorCode
));
138 // Make this handle non-inheritable so that child
139 // processes don't inadvertently prevent us from
140 // closing this file.
141 _Jv_platform_close_on_exec (handle
);
143 return (jint
) handle
;
147 java::io::FileDescriptor::write (jint b
)
150 jbyte buf
= (jbyte
)b
;
152 if (WriteFile ((HANDLE
)fd
, &buf
, 1, &bytesWritten
, NULL
))
154 if (java::lang::Thread::interrupted())
156 InterruptedIOException
*iioe
= new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
157 iioe
->bytesTransferred
= bytesWritten
;
160 if (bytesWritten
!= 1)
161 _Jv_ThrowIOException ();
164 _Jv_ThrowIOException ();
165 // FIXME: loop until bytesWritten == 1
169 java::io::FileDescriptor::write(jbyteArray b
, jint offset
, jint len
)
172 throw new java::lang::NullPointerException
;
173 if(offset
< 0 || len
< 0 || offset
+ len
> JvGetArrayLength (b
))
174 throw new java::lang::ArrayIndexOutOfBoundsException
;
176 jbyte
*buf
= elements (b
) + offset
;
179 if (WriteFile ((HANDLE
)fd
, buf
, len
, &bytesWritten
, NULL
))
181 if (java::lang::Thread::interrupted())
183 InterruptedIOException
*iioe
= new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
184 iioe
->bytesTransferred
= bytesWritten
;
189 _Jv_ThrowIOException ();
190 // FIXME: loop until bytesWritten == len
194 java::io::FileDescriptor::close (void)
196 HANDLE save
= (HANDLE
)fd
;
197 fd
= (jint
)INVALID_HANDLE_VALUE
;
198 if (! CloseHandle (save
))
199 _Jv_ThrowIOException ();
203 java::io::FileDescriptor::setLength(jlong pos
)
205 LONG liOrigFilePointer
;
206 LONG liNewFilePointer
;
207 LONG liEndFilePointer
;
209 // Get the original file pointer.
210 if (SetFilePointer((HANDLE
) fd
, (LONG
) 0, &liOrigFilePointer
,
211 FILE_CURRENT
) != (BOOL
) 0
212 && (GetLastError() != NO_ERROR
))
213 _Jv_ThrowIOException ();
215 // Get the length of the file.
216 if (SetFilePointer((HANDLE
) fd
, (LONG
) 0, &liEndFilePointer
,
217 FILE_END
) != (BOOL
) 0
218 && (GetLastError() != NO_ERROR
))
219 _Jv_ThrowIOException ();
221 if ((jlong
)liEndFilePointer
== pos
)
223 // Restore the file pointer.
224 if (liOrigFilePointer
!= liEndFilePointer
)
226 if (SetFilePointer((HANDLE
) fd
, liOrigFilePointer
, &liNewFilePointer
,
227 FILE_BEGIN
) != (BOOL
) 0
228 && (GetLastError() != NO_ERROR
))
229 _Jv_ThrowIOException ();
234 // Seek to the new end of file.
235 if (SetFilePointer((HANDLE
) fd
, (LONG
) pos
, &liNewFilePointer
,
236 FILE_BEGIN
) != (BOOL
) 0
237 && (GetLastError() != NO_ERROR
))
238 _Jv_ThrowIOException ();
240 // Truncate the file at this point.
241 if (SetEndOfFile((HANDLE
) fd
) != (BOOL
) 0 && (GetLastError() != NO_ERROR
))
242 _Jv_ThrowIOException ();
244 if (liOrigFilePointer
< liNewFilePointer
)
246 // Restore the file pointer.
247 if (SetFilePointer((HANDLE
) fd
, liOrigFilePointer
, &liNewFilePointer
,
248 FILE_BEGIN
) != (BOOL
) 0
249 && (GetLastError() != NO_ERROR
))
250 _Jv_ThrowIOException ();
255 java::io::FileDescriptor::seek (jlong pos
, jint whence
, jboolean eof_trunc
)
257 JvAssert (whence
== SET
|| whence
== CUR
);
259 jlong len
= getLength();
260 jlong here
= getFilePointer();
263 && ((whence
== SET
&& pos
> len
) || (whence
== CUR
&& here
+ pos
> len
)))
269 LONG high
= pos
>> 32;
270 DWORD low
= SetFilePointer ((HANDLE
)fd
, (DWORD
)(0xffffffff & pos
), &high
, whence
== SET
? FILE_BEGIN
: FILE_CURRENT
);
271 if ((low
== 0xffffffff) && (GetLastError () != NO_ERROR
))
272 _Jv_ThrowIOException ();
277 java::io::FileDescriptor::getFilePointer(void)
280 DWORD low
= SetFilePointer ((HANDLE
)fd
, 0, &high
, FILE_CURRENT
);
281 if ((low
== 0xffffffff) && (GetLastError() != NO_ERROR
))
282 _Jv_ThrowIOException ();
283 return (((jlong
)high
) << 32L) | (jlong
)low
;
287 java::io::FileDescriptor::getLength(void)
292 low
= GetFileSize ((HANDLE
)fd
, &high
);
293 // FIXME: Error checking
294 return (((jlong
)high
) << 32L) | (jlong
)low
;
298 java::io::FileDescriptor::read(void)
303 if (! ReadFile ((HANDLE
)fd
, &buf
, 1, &read
, NULL
))
305 if (GetLastError () == ERROR_BROKEN_PIPE
)
308 _Jv_ThrowIOException ();
314 return (jint
)(buf
& 0xff);
318 java::io::FileDescriptor::read(jbyteArray buffer
, jint offset
, jint count
)
321 throw new java::lang::NullPointerException
;
323 jsize bsize
= JvGetArrayLength (buffer
);
324 if (offset
< 0 || count
< 0 || offset
+ count
> bsize
)
325 throw new java::lang::ArrayIndexOutOfBoundsException
;
327 // Must return 0 if an attempt is made to read 0 bytes.
331 jbyte
*bytes
= elements (buffer
) + offset
;
334 if (! ReadFile((HANDLE
)fd
, bytes
, count
, &read
, NULL
))
336 if (GetLastError () == ERROR_BROKEN_PIPE
)
339 _Jv_ThrowIOException ();
342 if (read
== 0) return -1;
348 java::io::FileDescriptor::available(void)
351 return getLength() - getFilePointer();