fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / libjava / java / io / natFileDescriptorPosix.cc
blobe43bb9d113591241b3dfaaa118edc0fc03278648
1 // natFileDescriptor.cc - Native part of FileDescriptor class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 #include <config.h>
13 #include "posix.h"
15 #include <errno.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <sys/stat.h>
19 #include <sys/param.h>
21 #ifdef HAVE_SYS_IOCTL_H
22 #define BSD_COMP /* Get FIONREAD on Solaris2. */
23 #include <sys/ioctl.h>
24 #endif
26 // Pick up FIONREAD on Solaris 2.5.
27 #ifdef HAVE_SYS_FILIO_H
28 #include <sys/filio.h>
29 #endif
31 #include <gcj/cni.h>
32 #include <jvm.h>
33 #include <java/io/FileDescriptor.h>
34 #include <java/io/SyncFailedException.h>
35 #include <java/io/IOException.h>
36 #include <java/io/InterruptedIOException.h>
37 #include <java/io/EOFException.h>
38 #include <java/lang/ArrayIndexOutOfBoundsException.h>
39 #include <java/lang/NullPointerException.h>
40 #include <java/lang/System.h>
41 #include <java/lang/String.h>
42 #include <java/lang/Thread.h>
43 #include <java/io/FileNotFoundException.h>
45 #define NO_FSYNC_MESSAGE "sync unsupported"
47 void
48 java::io::FileDescriptor::init (void)
50 in = new java::io::FileDescriptor(0);
51 out = new java::io::FileDescriptor(1);
52 err = new java::io::FileDescriptor(2);
55 jboolean
56 java::io::FileDescriptor::valid (void)
58 struct stat sb;
59 return fd >= 0 && ::fstat (fd, &sb) == 0;
62 void
63 java::io::FileDescriptor::sync (void)
65 // Some files don't support fsync. We don't bother reporting these
66 // as errors.
67 #ifdef HAVE_FSYNC
68 if (::fsync (fd) && errno != EROFS && errno != EINVAL)
69 throw new SyncFailedException (JvNewStringLatin1 (strerror (errno)));
70 #else
71 throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE));
72 #endif
75 jint
76 java::io::FileDescriptor::open (jstring path, jint jflags)
78 char *buf = (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path) + 1);
79 jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
80 buf[total] = '\0';
81 int flags = 0;
82 #ifdef O_BINARY
83 flags |= O_BINARY;
84 #endif
86 JvAssert ((jflags & READ) || (jflags & WRITE));
87 int mode = 0666;
88 if ((jflags & READ) && (jflags & WRITE))
89 flags |= O_RDWR | O_CREAT;
90 else if ((jflags & READ))
91 flags |= O_RDONLY;
92 else
94 flags |= O_WRONLY | O_CREAT;
95 if ((jflags & APPEND))
96 flags |= O_APPEND;
97 else
98 flags |= O_TRUNC;
100 if ((jflags & EXCL))
102 flags |= O_EXCL;
103 // In this case we are making a temp file.
104 mode = 0600;
108 if ((jflags & SYNC))
109 flags |= O_SYNC;
111 if ((jflags & DSYNC))
112 flags |= O_DSYNC;
114 int fd = ::open (buf, flags, mode);
115 if (fd == -1 && errno == EMFILE)
117 // Because finalize () calls close () we might be able to continue.
118 java::lang::System::gc ();
119 java::lang::System::runFinalization ();
120 fd = ::open (buf, flags, mode);
122 if (fd == -1)
124 char msg[MAXPATHLEN + 200];
125 // We choose the formatting here for JDK compatibility, believe
126 // it or not.
127 sprintf (msg, "%s (%s)", buf, strerror (errno));
128 throw new FileNotFoundException (JvNewStringLatin1 (msg));
131 _Jv_platform_close_on_exec (fd);
133 return fd;
136 void
137 java::io::FileDescriptor::write (jint b)
139 jbyte d = (jbyte) b;
140 int r = 0;
141 while (r != 1)
143 r = ::write (fd, &d, 1);
144 if (r == -1)
146 if (java::lang::Thread::interrupted())
148 InterruptedIOException *iioe
149 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
150 iioe->bytesTransferred = r == -1 ? 0 : r;
151 throw iioe;
153 if (errno != EINTR)
154 throw new IOException (JvNewStringLatin1 (strerror (errno)));
157 position++;
160 void
161 java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
163 if (! b)
164 throw new java::lang::NullPointerException;
165 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
166 throw new java::lang::ArrayIndexOutOfBoundsException;
167 jbyte *bytes = elements (b) + offset;
169 int written = 0;
170 while (len > 0)
172 int r = ::write (fd, bytes, len);
173 if (r == -1)
175 if (java::lang::Thread::interrupted())
177 InterruptedIOException *iioe
178 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
179 iioe->bytesTransferred = written;
180 throw iioe;
182 if (errno != EINTR)
183 throw new IOException (JvNewStringLatin1 (strerror (errno)));
186 written += r;
187 len -= r;
188 bytes += r;
189 position += r;
193 void
194 java::io::FileDescriptor::close (void)
196 jint save = fd;
197 fd = -1;
198 if (::close (save))
199 throw new IOException (JvNewStringLatin1 (strerror (errno)));
202 void
203 java::io::FileDescriptor::setLength (jlong pos)
205 struct stat sb;
207 #ifdef HAVE_FTRUNCATE
208 if (::fstat (fd, &sb))
209 throw new IOException (JvNewStringLatin1 (strerror (errno)));
211 if ((jlong) sb.st_size == pos)
212 return;
214 // If the file is too short, we extend it. We can't rely on
215 // ftruncate() extending the file. So we lseek() to 1 byte less
216 // than we want, and then we write a single byte at the end.
217 if ((jlong) sb.st_size < pos)
219 if (::lseek (fd, (off_t) (pos - 1), SEEK_SET) == -1)
220 throw new IOException (JvNewStringLatin1 (strerror (errno)));
221 char out = '\0';
222 int r = ::write (fd, &out, 1);
223 if (r <= 0 || ::lseek (fd, position, SEEK_SET) == -1)
224 throw new IOException (JvNewStringLatin1 (strerror (errno)));
226 else
228 if (::ftruncate (fd, (off_t) pos))
229 throw new IOException (JvNewStringLatin1 (strerror (errno)));
230 position = pos;
232 #else /* HAVE_FTRUNCATE */
233 throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
234 #endif /* HAVE_FTRUNCATE */
237 jint
238 java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
240 JvAssert (whence == SET || whence == CUR);
242 if (eof_trunc)
244 jlong len = getLength ();
245 if (whence == SET)
247 if (pos > len)
248 pos = len;
250 else
252 jlong here = getFilePointer ();
253 if (here + pos > len)
255 pos = len;
256 whence = SET;
261 off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
262 if (r == -1)
263 throw new IOException (JvNewStringLatin1 (strerror (errno)));
264 position = r;
265 return r;
268 jlong
269 java::io::FileDescriptor::getLength (void)
271 struct stat sb;
272 if (::fstat (fd, &sb))
273 throw new IOException (JvNewStringLatin1 (strerror (errno)));
274 return sb.st_size;
277 jlong
278 java::io::FileDescriptor::getFilePointer (void)
280 return position;
283 jint
284 java::io::FileDescriptor::read (void)
286 jbyte b;
287 int r;
290 r = ::read (fd, &b, 1);
291 if (r == 0)
292 return -1;
293 if (r == -1)
295 if (java::lang::Thread::interrupted())
297 InterruptedIOException *iioe
298 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
299 iioe->bytesTransferred = r == -1 ? 0 : r;
300 throw iioe;
302 if (errno != EINTR)
303 throw new IOException (JvNewStringLatin1 (strerror (errno)));
306 while (r != 1);
307 position++;
308 return b & 0xFF;
311 jint
312 java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
314 if (! buffer)
315 throw new java::lang::NullPointerException;
316 jsize bsize = JvGetArrayLength (buffer);
317 if (offset < 0 || count < 0 || offset + count > bsize)
318 throw new java::lang::ArrayIndexOutOfBoundsException;
320 // Must return 0 if an attempt is made to read 0 bytes.
321 if (count == 0)
322 return 0;
324 jbyte *bytes = elements (buffer) + offset;
325 int r;
328 r = ::read (fd, bytes, count);
329 if (r == 0)
330 return -1;
331 if (r == -1)
333 if (java::lang::Thread::interrupted())
335 InterruptedIOException *iioe
336 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
337 iioe->bytesTransferred = r == -1 ? 0 : r;
338 throw iioe;
340 if (errno != EINTR)
341 throw new IOException (JvNewStringLatin1 (strerror (errno)));
344 while (r <= 0);
345 position += r;
346 return r;
349 jint
350 java::io::FileDescriptor::available (void)
352 #if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
353 long num = 0;
354 int r = 0;
355 bool num_set = false;
357 #if defined (FIONREAD)
358 r = ::ioctl (fd, FIONREAD, &num);
359 if (r == -1 && errno == ENOTTY)
361 // If the ioctl doesn't work, we don't care.
362 r = 0;
363 num = 0;
365 else
366 num_set = true;
367 #elif defined (HAVE_SELECT)
368 if (fd < 0)
370 errno = EBADF;
371 r = -1;
373 #endif
375 if (r == -1)
377 posix_error:
378 throw new IOException (JvNewStringLatin1 (strerror (errno)));
381 // If we didn't get anything, and we have fstat, then see if see if
382 // we're reading a regular file. On many systems, FIONREAD does not
383 // work on regular files; select() likewise returns a useless
384 // result. This is run incorrectly when FIONREAD does work on
385 // regular files and we are at the end of the file. However, this
386 // case probably isn't very important.
387 #if defined (HAVE_FSTAT)
388 if (! num_set)
390 struct stat sb;
391 off_t where = 0;
392 if (fstat (fd, &sb) != -1
393 && S_ISREG (sb.st_mode)
394 && (where = lseek (fd, 0, SEEK_CUR)) != (off_t) -1)
396 num = (long) (sb.st_size - where);
397 num_set = true;
400 #endif /* HAVE_FSTAT */
402 #if defined (HAVE_SELECT)
403 if (! num_set)
405 fd_set rd;
406 FD_ZERO (&rd);
407 FD_SET (fd, &rd);
408 struct timeval tv;
409 tv.tv_sec = 0;
410 tv.tv_usec = 0;
411 r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
412 if (r == -1)
413 goto posix_error;
414 num = r == 0 ? 0 : 1;
416 #endif /* HAVE_SELECT */
418 return (jint) num;
419 #else
420 return 0;
421 #endif