OSDN Git Service

* java/io/RandomAccessFile.java (seek): Let seek go past end of
[pf3gnuchains/gcc-fork.git] / libjava / java / io / natFileDescriptorWin32.cc
1 // natFileDescriptorWin32.cc - Native part of FileDescriptor class.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001  Red Hat, Inc.
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 // FIXME: In order to support interrupting of IO operations, we
12 // need to change to use the windows asynchronous IO functions
13
14 #include <config.h>
15
16 #include <stdio.h>
17 #include <string.h>
18
19 #include <windows.h>
20
21 #include <gcj/cni.h>
22 #include <jvm.h>
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>
33
34 static char *
35 winerr (void)
36 {
37   static LPVOID last = NULL;
38   LPVOID old = NULL;
39
40   if (last)
41     old = last;
42
43   FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
44     FORMAT_MESSAGE_FROM_SYSTEM |
45     FORMAT_MESSAGE_IGNORE_INSERTS,
46     NULL,
47     GetLastError(),
48     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
49     (LPTSTR) &last,
50     0,
51     NULL);
52
53   if (old)
54     LocalFree (old);
55
56   return (char *)last;
57 }
58
59 jboolean
60 java::io::FileDescriptor::valid (void) {
61   BY_HANDLE_FILE_INFORMATION info;
62   return GetFileInformationByHandle ((HANDLE)fd, &info) != 0;
63 }
64
65 void
66 java::io::FileDescriptor::sync (void) {
67   if (! FlushFileBuffers ((HANDLE)fd))
68     throw new SyncFailedException (JvNewStringLatin1 (winerr ()));
69 }
70
71 jint
72 java::io::FileDescriptor::open (jstring path, jint jflags) {
73
74   HANDLE handle = NULL;
75   DWORD access = 0;
76   DWORD share = FILE_SHARE_READ;
77   DWORD create = OPEN_EXISTING;
78   char buf[MAX_PATH] = "";
79
80   jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf);
81   buf[total] = '\0';
82
83   JvAssert((jflags & READ) || (jflags & WRITE));
84
85   if ((jflags & READ) && (jflags & WRITE))
86     {
87       access = GENERIC_READ | GENERIC_WRITE;
88       share = 0;
89       if (jflags & APPEND)
90         create = OPEN_ALWAYS;
91       else
92         create = CREATE_ALWAYS;
93     }
94   else if(jflags & READ)
95     access = GENERIC_READ;
96   else
97     {
98       access = GENERIC_WRITE;
99       share = 0;
100       if (jflags & APPEND)
101         create = OPEN_ALWAYS;
102       else
103         create = CREATE_ALWAYS;
104     }
105
106   handle = CreateFile(buf, access, share, NULL, create, 0, NULL);
107
108   if (handle == INVALID_HANDLE_VALUE)
109     {
110       char msg[MAX_PATH + 1000];
111       sprintf (msg, "%s: %s", buf, winerr ());
112       throw new FileNotFoundException (JvNewStringLatin1 (msg));
113     }
114
115   return (jint)handle;
116 }
117
118 void
119 java::io::FileDescriptor::write (jint b)
120 {
121   DWORD bytesWritten;
122   jbyte buf = (jbyte)b;
123
124   if (WriteFile ((HANDLE)fd, &buf, 1, &bytesWritten, NULL))
125     {
126       if (java::lang::Thread::interrupted())
127         {
128           InterruptedIOException *iioe = new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
129           iioe->bytesTransferred = bytesWritten;
130           throw iioe;
131         }
132       if (bytesWritten != 1)
133         throw new IOException (JvNewStringLatin1 (winerr ()));
134     }
135   else
136     throw new IOException (JvNewStringLatin1 (winerr ()));
137   // FIXME: loop until bytesWritten == 1
138 }
139
140 void
141 java::io::FileDescriptor::write(jbyteArray b, jint offset, jint len)
142 {
143   if (! b)
144     throw new java::lang::NullPointerException;
145   if(offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
146     throw new java::lang::ArrayIndexOutOfBoundsException;
147
148   jbyte *buf = elements (b) + offset;
149   DWORD bytesWritten;
150   if (WriteFile ((HANDLE)fd, buf, len, &bytesWritten, NULL))
151     {
152       if (java::lang::Thread::interrupted())
153         {
154           InterruptedIOException *iioe = new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
155           iioe->bytesTransferred = bytesWritten;
156           throw iioe;
157         }
158     }
159   else
160     throw new IOException (JvNewStringLatin1 (winerr ()));
161   // FIXME: loop until bytesWritten == len
162 }
163
164 void
165 java::io::FileDescriptor::close (void)
166 {
167   HANDLE save = (HANDLE)fd;
168   fd = (jint)INVALID_HANDLE_VALUE;
169   if (! CloseHandle (save))
170     throw new IOException (JvNewStringLatin1 (winerr ()));
171 }
172
173 jint
174 java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
175 {
176   JvAssert (whence == SET || whence == CUR);
177
178   jlong len = length();
179   jlong here = getFilePointer();
180
181   if (eof_trunc
182       && ((whence == SET && pos > len) || (whence == CUR && here + pos > len)))
183     {
184       whence = SET;
185       pos = len;
186     }
187
188   LONG high = pos >> 32;
189   DWORD low = SetFilePointer ((HANDLE)fd, (DWORD)(0xffffffff & pos), &high, whence == SET ? FILE_BEGIN : FILE_CURRENT);
190   if ((low == 0xffffffff) && (GetLastError () != NO_ERROR))
191     throw new IOException (JvNewStringLatin1 (winerr ()));
192   return low;
193 }
194
195 jlong
196 java::io::FileDescriptor::getFilePointer(void)
197 {
198   LONG high = 0;
199   DWORD low = SetFilePointer ((HANDLE)fd, 0, &high, FILE_CURRENT);
200   if ((low == 0xffffffff) && (GetLastError() != NO_ERROR))
201     throw new IOException (JvNewStringLatin1 (winerr ()));
202   return (((jlong)high) << 32L) | (jlong)low;
203 }
204
205 jlong
206 java::io::FileDescriptor::length(void)
207 {
208   DWORD high;
209   DWORD low;
210
211   low = GetFileSize ((HANDLE)fd, &high);
212   // FIXME: Error checking
213   return (((jlong)high) << 32L) | (jlong)low;
214 }
215
216 jint
217 java::io::FileDescriptor::read(void)
218 {
219   CHAR buf;
220   DWORD read;
221
222   if (! ReadFile ((HANDLE)fd, &buf, 1, &read, NULL))
223     throw new IOException (JvNewStringLatin1 (winerr ()));
224   if (! read)
225     return -1;
226   else
227     return (jint)(buf & 0xff);
228 }
229
230 jint
231 java::io::FileDescriptor::read(jbyteArray buffer, jint offset, jint count)
232 {
233   if (! buffer)
234     throw new java::lang::NullPointerException;
235
236   jsize bsize = JvGetArrayLength (buffer);
237   if (offset < 0 || count < 0 || offset + count > bsize)
238     throw new java::lang::ArrayIndexOutOfBoundsException;
239
240   jbyte *bytes = elements (buffer) + offset;
241
242   DWORD read;
243   if (! ReadFile((HANDLE)fd, bytes, count, &read, NULL))
244     throw new IOException (JvNewStringLatin1 (winerr ()));
245
246   return (jint)read;
247 }
248
249 jint
250 java::io::FileDescriptor::available(void)
251 {
252   // FIXME:
253   return length() - getFilePointer();
254 }