2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / io / natFileDescriptorWin32.cc
blob7811a73f4938c799103d9f93a0b8109e6477702b
1 // natFileDescriptorWin32.cc - Native part of FileDescriptor class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
4 Foundation, Inc.
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
10 details. */
12 // FIXME: In order to support interrupting of IO operations, we
13 // need to change to use the windows asynchronous IO functions
15 #include <config.h>
16 #include <platform.h>
18 #include <stdio.h>
19 #include <string.h>
21 #undef STRICT
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. */
39 DWORD dwFlags;
40 return GetHandleInformation (GetStdHandle (STD_INPUT_HANDLE),
41 &dwFlags) != 0;
44 // FIXME: casting a FILE (pointer) to a jint will not work on Win64 --
45 // we should be using gnu.gcj.RawData's.
47 void
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)));
55 jboolean
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. */
63 DWORD dwFlags;
64 HANDLE h = (HANDLE) fd;
65 return GetHandleInformation (h, &dwFlags) != 0;
67 else
69 /* Can't use GetHandleInformation() for console handles on < WinNT 5. */
70 return true;
74 void
75 java::io::FileDescriptor::sync (void) {
76 if (! FlushFileBuffers ((HANDLE)fd))
78 DWORD dwErrorCode = GetLastError ();
79 throw new SyncFailedException (_Jv_WinStrError (dwErrorCode));
83 jint
84 java::io::FileDescriptor::open (jstring path, jint jflags) {
86 HANDLE handle = NULL;
87 DWORD access = 0;
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;
97 if (jflags & EXCL)
98 create = CREATE_NEW; // this will raise error if file exists.
99 else
100 create = OPEN_ALWAYS; // equivalent to O_CREAT
102 else if (jflags & READ)
104 access = GENERIC_READ;
105 create = OPEN_EXISTING; // ignore EXCL
107 else
109 access = GENERIC_WRITE;
110 if (jflags & EXCL)
111 create = CREATE_NEW;
112 else if (jflags & APPEND)
113 create = OPEN_ALWAYS;
114 else
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.
128 if (jflags & APPEND)
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;
146 void
147 java::io::FileDescriptor::write (jint b)
149 DWORD bytesWritten;
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;
158 throw iioe;
160 if (bytesWritten != 1)
161 _Jv_ThrowIOException ();
163 else
164 _Jv_ThrowIOException ();
165 // FIXME: loop until bytesWritten == 1
168 void
169 java::io::FileDescriptor::write(jbyteArray b, jint offset, jint len)
171 if (! b)
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;
177 DWORD bytesWritten;
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;
185 throw iioe;
188 else
189 _Jv_ThrowIOException ();
190 // FIXME: loop until bytesWritten == len
193 void
194 java::io::FileDescriptor::close (void)
196 HANDLE save = (HANDLE)fd;
197 fd = (jint)INVALID_HANDLE_VALUE;
198 if (! CloseHandle (save))
199 _Jv_ThrowIOException ();
202 void
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 ();
231 return;
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 ();
254 jint
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();
262 if (eof_trunc
263 && ((whence == SET && pos > len) || (whence == CUR && here + pos > len)))
265 whence = SET;
266 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 ();
273 return low;
276 jlong
277 java::io::FileDescriptor::getFilePointer(void)
279 LONG high = 0;
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;
286 jlong
287 java::io::FileDescriptor::getLength(void)
289 DWORD high;
290 DWORD low;
292 low = GetFileSize ((HANDLE)fd, &high);
293 // FIXME: Error checking
294 return (((jlong)high) << 32L) | (jlong)low;
297 jint
298 java::io::FileDescriptor::read(void)
300 CHAR buf;
301 DWORD read;
303 if (! ReadFile ((HANDLE)fd, &buf, 1, &read, NULL))
305 if (GetLastError () == ERROR_BROKEN_PIPE)
306 return -1;
307 else
308 _Jv_ThrowIOException ();
311 if (! read)
312 return -1;
313 else
314 return (jint)(buf & 0xff);
317 jint
318 java::io::FileDescriptor::read(jbyteArray buffer, jint offset, jint count)
320 if (! buffer)
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.
328 if (count == 0)
329 return 0;
331 jbyte *bytes = elements (buffer) + offset;
333 DWORD read;
334 if (! ReadFile((HANDLE)fd, bytes, count, &read, NULL))
336 if (GetLastError () == ERROR_BROKEN_PIPE)
337 return -1;
338 else
339 _Jv_ThrowIOException ();
342 if (read == 0) return -1;
344 return (jint)read;
347 jint
348 java::io::FileDescriptor::available(void)
350 // FIXME:
351 return getLength() - getFilePointer();