FSF GCC merge 02/23/03
[official-gcc.git] / libjava / java / io / natFileDescriptorWin32.cc
blob87f94e812223894fadd2c4fa4321051dde997677
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>
17 #include <stdio.h>
18 #include <string.h>
20 #include <windows.h>
21 #undef STRICT
23 #include <gcj/cni.h>
24 #include <jvm.h>
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.
39 void
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)));
47 static char *
48 winerr (void)
50 static LPVOID last = NULL;
51 LPVOID old = NULL;
53 if (last)
54 old = last;
56 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
57 FORMAT_MESSAGE_FROM_SYSTEM |
58 FORMAT_MESSAGE_IGNORE_INSERTS,
59 NULL,
60 GetLastError(),
61 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
62 (LPTSTR) &last,
64 NULL);
66 if (old)
67 LocalFree (old);
69 return (char *)last;
72 jboolean
73 java::io::FileDescriptor::valid (void) {
74 BY_HANDLE_FILE_INFORMATION info;
75 return GetFileInformationByHandle ((HANDLE)fd, &info) != 0;
78 void
79 java::io::FileDescriptor::sync (void) {
80 if (! FlushFileBuffers ((HANDLE)fd))
81 throw new SyncFailedException (JvNewStringLatin1 (winerr ()));
84 jint
85 java::io::FileDescriptor::open (jstring path, jint jflags) {
87 HANDLE handle = NULL;
88 DWORD access = 0;
89 DWORD create = OPEN_EXISTING;
90 char buf[MAX_PATH] = "";
92 jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf);
93 buf[total] = '\0';
95 JvAssert((jflags & READ) || (jflags & WRITE));
97 if ((jflags & READ) && (jflags & WRITE))
99 access = GENERIC_READ | GENERIC_WRITE;
100 if (jflags & APPEND)
101 create = OPEN_ALWAYS;
102 else
103 create = CREATE_ALWAYS;
105 else if(jflags & READ)
106 access = GENERIC_READ;
107 else
109 access = GENERIC_WRITE;
110 if (jflags & APPEND)
111 create = OPEN_ALWAYS;
112 else
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.
126 if (jflags & APPEND)
128 DWORD low = SetFilePointer (handle, 0, NULL, FILE_END);
129 if ((low == 0xffffffff) && (GetLastError () != NO_ERROR))
130 throw new FileNotFoundException (JvNewStringLatin1 (winerr ()));
132 return (jint)handle;
135 void
136 java::io::FileDescriptor::write (jint b)
138 DWORD bytesWritten;
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;
147 throw iioe;
149 if (bytesWritten != 1)
150 throw new IOException (JvNewStringLatin1 (winerr ()));
152 else
153 throw new IOException (JvNewStringLatin1 (winerr ()));
154 // FIXME: loop until bytesWritten == 1
157 void
158 java::io::FileDescriptor::write(jbyteArray b, jint offset, jint len)
160 if (! b)
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;
166 DWORD bytesWritten;
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;
173 throw iioe;
176 else
177 throw new IOException (JvNewStringLatin1 (winerr ()));
178 // FIXME: loop until bytesWritten == len
181 void
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 ()));
190 void
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 ()));
219 return;
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 ()));
242 jint
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();
250 if (eof_trunc
251 && ((whence == SET && pos > len) || (whence == CUR && here + pos > len)))
253 whence = SET;
254 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 ()));
261 return low;
264 jlong
265 java::io::FileDescriptor::getFilePointer(void)
267 LONG high = 0;
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;
274 jlong
275 java::io::FileDescriptor::length(void)
277 DWORD high;
278 DWORD low;
280 low = GetFileSize ((HANDLE)fd, &high);
281 // FIXME: Error checking
282 return (((jlong)high) << 32L) | (jlong)low;
285 jint
286 java::io::FileDescriptor::read(void)
288 CHAR buf;
289 DWORD read;
291 if (! ReadFile ((HANDLE)fd, &buf, 1, &read, NULL))
293 if (GetLastError () == ERROR_BROKEN_PIPE)
294 return -1;
295 else
296 throw new IOException (JvNewStringLatin1 (winerr ()));
299 if (! read)
300 return -1;
301 else
302 return (jint)(buf & 0xff);
305 jint
306 java::io::FileDescriptor::read(jbyteArray buffer, jint offset, jint count)
308 if (! buffer)
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.
316 if (count == 0)
317 return 0;
319 jbyte *bytes = elements (buffer) + offset;
321 DWORD read;
322 if (! ReadFile((HANDLE)fd, bytes, count, &read, NULL))
324 if (GetLastError () == ERROR_BROKEN_PIPE)
325 return -1;
326 else
327 throw new IOException (JvNewStringLatin1 (winerr ()));
330 if (read == 0) return -1;
332 return (jint)read;
335 jint
336 java::io::FileDescriptor::available(void)
338 // FIXME:
339 return length() - getFilePointer();