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
19 #include <sys/param.h>
21 #ifdef HAVE_SYS_IOCTL_H
22 #define BSD_COMP /* Get FIONREAD on Solaris2. */
23 #include <sys/ioctl.h>
26 // Pick up FIONREAD on Solaris 2.5.
27 #ifdef HAVE_SYS_FILIO_H
28 #include <sys/filio.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"
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);
56 java::io::FileDescriptor::valid (void)
59 return fd >= 0 && ::fstat (fd, &sb) == 0;
63 java::io::FileDescriptor::sync (void)
65 // Some files don't support fsync. We don't bother reporting these
68 if (::fsync (fd) && errno != EROFS && errno != EINVAL)
69 throw new SyncFailedException (JvNewStringLatin1 (strerror (errno)));
71 throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE));
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);
86 JvAssert ((jflags & READ) || (jflags & WRITE));
88 if ((jflags & READ) && (jflags & WRITE))
89 flags |= O_RDWR | O_CREAT;
90 else if ((jflags & READ))
94 flags |= O_WRONLY | O_CREAT;
95 if ((jflags & APPEND))
103 // In this case we are making a temp file.
111 if ((jflags & 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);
124 char msg[MAXPATHLEN + 200];
125 // We choose the formatting here for JDK compatibility, believe
127 sprintf (msg, "%s (%s)", buf, strerror (errno));
128 throw new FileNotFoundException (JvNewStringLatin1 (msg));
131 _Jv_platform_close_on_exec (fd);
137 java::io::FileDescriptor::write (jint b)
143 r = ::write (fd, &d, 1);
146 if (java::lang::Thread::interrupted())
148 InterruptedIOException *iioe
149 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
150 iioe->bytesTransferred = r == -1 ? 0 : r;
153 throw new IOException (JvNewStringLatin1 (strerror (errno)));
160 java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
163 throw new java::lang::NullPointerException;
164 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
165 throw new java::lang::ArrayIndexOutOfBoundsException;
166 jbyte *bytes = elements (b) + offset;
171 int r = ::write (fd, bytes, len);
174 if (java::lang::Thread::interrupted())
176 InterruptedIOException *iioe
177 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
178 iioe->bytesTransferred = written;
181 throw new IOException (JvNewStringLatin1 (strerror (errno)));
192 java::io::FileDescriptor::close (void)
197 throw new IOException (JvNewStringLatin1 (strerror (errno)));
201 java::io::FileDescriptor::setLength (jlong pos)
205 #ifdef HAVE_FTRUNCATE
206 if (::fstat (fd, &sb))
207 throw new IOException (JvNewStringLatin1 (strerror (errno)));
209 if ((jlong) sb.st_size == pos)
212 // If the file is too short, we extend it. We can't rely on
213 // ftruncate() extending the file. So we lseek() to 1 byte less
214 // than we want, and then we write a single byte at the end.
215 if ((jlong) sb.st_size < pos)
217 if (::lseek (fd, (off_t) (pos - 1), SEEK_SET) == -1)
218 throw new IOException (JvNewStringLatin1 (strerror (errno)));
220 int r = ::write (fd, &out, 1);
221 if (r <= 0 || ::lseek (fd, position, SEEK_SET) == -1)
222 throw new IOException (JvNewStringLatin1 (strerror (errno)));
226 if (::ftruncate (fd, (off_t) pos))
227 throw new IOException (JvNewStringLatin1 (strerror (errno)));
230 #else /* HAVE_FTRUNCATE */
231 throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
232 #endif /* HAVE_FTRUNCATE */
236 java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
238 JvAssert (whence == SET || whence == CUR);
242 jlong len = getLength ();
250 jlong here = getFilePointer ();
251 if (here + pos > len)
259 off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
261 throw new IOException (JvNewStringLatin1 (strerror (errno)));
267 java::io::FileDescriptor::getLength (void)
270 if (::fstat (fd, &sb))
271 throw new IOException (JvNewStringLatin1 (strerror (errno)));
276 java::io::FileDescriptor::getFilePointer (void)
282 java::io::FileDescriptor::read (void)
285 int r = ::read (fd, &b, 1);
290 if (java::lang::Thread::interrupted())
292 InterruptedIOException *iioe
293 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
294 iioe->bytesTransferred = r == -1 ? 0 : r;
297 throw new IOException (JvNewStringLatin1 (strerror (errno)));
304 java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
307 throw new java::lang::NullPointerException;
308 jsize bsize = JvGetArrayLength (buffer);
309 if (offset < 0 || count < 0 || offset + count > bsize)
310 throw new java::lang::ArrayIndexOutOfBoundsException;
312 // Must return 0 if an attempt is made to read 0 bytes.
316 jbyte *bytes = elements (buffer) + offset;
317 int r = ::read (fd, bytes, count);
322 if (java::lang::Thread::interrupted())
324 InterruptedIOException *iioe
325 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
326 iioe->bytesTransferred = r == -1 ? 0 : r;
329 throw new IOException (JvNewStringLatin1 (strerror (errno)));
336 java::io::FileDescriptor::available (void)
338 #if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
341 bool num_set = false;
343 #if defined (FIONREAD)
344 r = ::ioctl (fd, FIONREAD, &num);
345 if (r == -1 && errno == ENOTTY)
347 // If the ioctl doesn't work, we don't care.
353 #elif defined (HAVE_SELECT)
364 throw new IOException (JvNewStringLatin1 (strerror (errno)));
367 // If we didn't get anything, and we have fstat, then see if see if
368 // we're reading a regular file. On many systems, FIONREAD does not
369 // work on regular files; select() likewise returns a useless
370 // result. This is run incorrectly when FIONREAD does work on
371 // regular files and we are at the end of the file. However, this
372 // case probably isn't very important.
373 #if defined (HAVE_FSTAT)
378 if (fstat (fd, &sb) != -1
379 && S_ISREG (sb.st_mode)
380 && (where = lseek (fd, 0, SEEK_CUR)) != (off_t) -1)
382 num = (long) (sb.st_size - where);
386 #endif /* HAVE_FSTAT */
388 #if defined (HAVE_SELECT)
397 r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
400 num = r == 0 ? 0 : 1;
402 #endif /* HAVE_SELECT */