* java/io/FileDescriptor.java (position): New private field.
[official-gcc.git] / libjava / java / io / natFileDescriptorPosix.cc
blobe8ec9a7e733b9d8f856fec2246c3046f0013830f
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 int fd = ::open (buf, flags, mode);
109 if (fd == -1 && errno == EMFILE)
111 // Because finalize () calls close () we might be able to continue.
112 java::lang::System::gc ();
113 java::lang::System::runFinalization ();
114 fd = ::open (buf, flags, mode);
116 if (fd == -1)
118 char msg[MAXPATHLEN + 200];
119 // We choose the formatting here for JDK compatibility, believe
120 // it or not.
121 sprintf (msg, "%s (%s)", buf, strerror (errno));
122 throw new FileNotFoundException (JvNewStringLatin1 (msg));
125 _Jv_platform_close_on_exec (fd);
127 return fd;
130 void
131 java::io::FileDescriptor::write (jint b)
133 jbyte d = (jbyte) b;
134 int r = 0;
135 while (r != 1)
137 r = ::write (fd, &d, 1);
138 if (r == -1)
140 if (java::lang::Thread::interrupted())
142 InterruptedIOException *iioe
143 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
144 iioe->bytesTransferred = r == -1 ? 0 : r;
145 throw iioe;
147 throw new IOException (JvNewStringLatin1 (strerror (errno)));
150 position++;
153 void
154 java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
156 if (! b)
157 throw new java::lang::NullPointerException;
158 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
159 throw new java::lang::ArrayIndexOutOfBoundsException;
160 jbyte *bytes = elements (b) + offset;
162 int written = 0;
163 while (len > 0)
165 int r = ::write (fd, bytes, len);
166 if (r == -1)
168 if (java::lang::Thread::interrupted())
170 InterruptedIOException *iioe
171 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
172 iioe->bytesTransferred = written;
173 throw iioe;
175 throw new IOException (JvNewStringLatin1 (strerror (errno)));
178 written += r;
179 len -= r;
180 bytes += r;
181 position += r;
185 void
186 java::io::FileDescriptor::close (void)
188 jint save = fd;
189 fd = -1;
190 if (::close (save))
191 throw new IOException (JvNewStringLatin1 (strerror (errno)));
194 void
195 java::io::FileDescriptor::setLength (jlong pos)
197 struct stat sb;
199 #ifdef HAVE_FTRUNCATE
200 if (::fstat (fd, &sb))
201 throw new IOException (JvNewStringLatin1 (strerror (errno)));
203 if ((jlong) sb.st_size == pos)
204 return;
206 // If the file is too short, we extend it. We can't rely on
207 // ftruncate() extending the file. So we lseek() to 1 byte less
208 // than we want, and then we write a single byte at the end.
209 if ((jlong) sb.st_size < pos)
211 if (::lseek (fd, (off_t) (pos - 1), SEEK_SET) == -1)
212 throw new IOException (JvNewStringLatin1 (strerror (errno)));
213 char out = '\0';
214 int r = ::write (fd, &out, 1);
215 if (r <= 0 || ::lseek (fd, position, SEEK_SET) == -1)
216 throw new IOException (JvNewStringLatin1 (strerror (errno)));
218 else
220 if (::ftruncate (fd, (off_t) pos))
221 throw new IOException (JvNewStringLatin1 (strerror (errno)));
222 position = pos;
224 #else /* HAVE_FTRUNCATE */
225 throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
226 #endif /* HAVE_FTRUNCATE */
229 jint
230 java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
232 JvAssert (whence == SET || whence == CUR);
234 if (eof_trunc)
236 jlong len = length ();
237 if (whence == SET)
239 if (pos > len)
240 pos = len;
242 else
244 jlong here = getFilePointer ();
245 if (here + pos > len)
247 pos = len;
248 whence = SET;
253 off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
254 if (r == -1)
255 throw new IOException (JvNewStringLatin1 (strerror (errno)));
256 position = r;
257 return r;
260 jlong
261 java::io::FileDescriptor::length (void)
263 struct stat sb;
264 if (::fstat (fd, &sb))
265 throw new IOException (JvNewStringLatin1 (strerror (errno)));
266 return sb.st_size;
269 jlong
270 java::io::FileDescriptor::getFilePointer (void)
272 return position;
275 jint
276 java::io::FileDescriptor::read (void)
278 jbyte b;
279 int r = ::read (fd, &b, 1);
280 if (r == 0)
281 return -1;
282 if (r == -1)
284 if (java::lang::Thread::interrupted())
286 InterruptedIOException *iioe
287 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
288 iioe->bytesTransferred = r == -1 ? 0 : r;
289 throw iioe;
291 throw new IOException (JvNewStringLatin1 (strerror (errno)));
293 position++;
294 return b & 0xFF;
297 jint
298 java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
300 if (! buffer)
301 throw new java::lang::NullPointerException;
302 jsize bsize = JvGetArrayLength (buffer);
303 if (offset < 0 || count < 0 || offset + count > bsize)
304 throw new java::lang::ArrayIndexOutOfBoundsException;
306 // Must return 0 if an attempt is made to read 0 bytes.
307 if (count == 0)
308 return 0;
310 jbyte *bytes = elements (buffer) + offset;
311 int r = ::read (fd, bytes, count);
312 if (r == 0)
313 return -1;
314 if (r == -1)
316 if (java::lang::Thread::interrupted())
318 InterruptedIOException *iioe
319 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
320 iioe->bytesTransferred = r == -1 ? 0 : r;
321 throw iioe;
323 throw new IOException (JvNewStringLatin1 (strerror (errno)));
325 position += r;
326 return r;
329 jint
330 java::io::FileDescriptor::available (void)
332 #if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
333 long num = 0;
334 int r = 0;
335 bool num_set = false;
337 #if defined (FIONREAD)
338 r = ::ioctl (fd, FIONREAD, &num);
339 if (r == -1 && errno == ENOTTY)
341 // If the ioctl doesn't work, we don't care.
342 r = 0;
343 num = 0;
345 else
346 num_set = true;
347 #elif defined (HAVE_SELECT)
348 if (fd < 0)
350 errno = EBADF;
351 r = -1;
353 #endif
355 if (r == -1)
357 posix_error:
358 throw new IOException (JvNewStringLatin1 (strerror (errno)));
361 // If we didn't get anything, and we have fstat, then see if see if
362 // we're reading a regular file. On many systems, FIONREAD does not
363 // work on regular files; select() likewise returns a useless
364 // result. This is run incorrectly when FIONREAD does work on
365 // regular files and we are at the end of the file. However, this
366 // case probably isn't very important.
367 #if defined (HAVE_FSTAT)
368 if (! num_set)
370 struct stat sb;
371 off_t where = 0;
372 if (fstat (fd, &sb) != -1
373 && S_ISREG (sb.st_mode)
374 && (where = lseek (fd, SEEK_CUR, 0)) != (off_t) -1)
376 num = (long) (sb.st_size - where);
377 num_set = true;
380 #endif /* HAVE_FSTAT */
382 #if defined (HAVE_SELECT)
383 if (! num_set)
385 fd_set rd;
386 FD_ZERO (&rd);
387 FD_SET (fd, &rd);
388 struct timeval tv;
389 tv.tv_sec = 0;
390 tv.tv_usec = 0;
391 r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
392 if (r == -1)
393 goto posix_error;
394 num = r == 0 ? 0 : 1;
396 #endif /* HAVE_SELECT */
398 return (jint) num;
399 #else
400 throw new IOException (JvNewStringLatin1 ("unimplemented"));
401 #endif