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
;
154 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
161 java::io::FileDescriptor::write (jbyteArray b
, jint offset
, jint len
)
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
;
172 int r
= ::write (fd
, bytes
, len
);
175 if (java::lang::Thread::interrupted())
177 InterruptedIOException
*iioe
178 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
179 iioe
->bytesTransferred
= written
;
183 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
194 java::io::FileDescriptor::close (void)
199 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
203 java::io::FileDescriptor::setLength (jlong pos
)
207 #ifdef HAVE_FTRUNCATE
208 if (::fstat (fd
, &sb
))
209 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
211 if ((jlong
) sb
.st_size
== pos
)
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
)));
222 int r
= ::write (fd
, &out
, 1);
223 if (r
<= 0 || ::lseek (fd
, position
, SEEK_SET
) == -1)
224 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
228 if (::ftruncate (fd
, (off_t
) pos
))
229 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
232 #else /* HAVE_FTRUNCATE */
233 throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
234 #endif /* HAVE_FTRUNCATE */
238 java::io::FileDescriptor::seek (jlong pos
, jint whence
, jboolean eof_trunc
)
240 JvAssert (whence
== SET
|| whence
== CUR
);
244 jlong len
= getLength ();
252 jlong here
= getFilePointer ();
253 if (here
+ pos
> len
)
261 off_t r
= ::lseek (fd
, (off_t
) pos
, whence
== SET
? SEEK_SET
: SEEK_CUR
);
263 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
269 java::io::FileDescriptor::getLength (void)
272 if (::fstat (fd
, &sb
))
273 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
278 java::io::FileDescriptor::getFilePointer (void)
284 java::io::FileDescriptor::read (void)
290 r
= ::read (fd
, &b
, 1);
295 if (java::lang::Thread::interrupted())
297 InterruptedIOException
*iioe
298 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
299 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
303 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
312 java::io::FileDescriptor::read (jbyteArray buffer
, jint offset
, jint count
)
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.
324 jbyte
*bytes
= elements (buffer
) + offset
;
328 r
= ::read (fd
, bytes
, count
);
333 if (java::lang::Thread::interrupted())
335 InterruptedIOException
*iioe
336 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
337 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
341 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
350 java::io::FileDescriptor::available (void)
352 #if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
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.
367 #elif defined (HAVE_SELECT)
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)
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
);
400 #endif /* HAVE_FSTAT */
402 #if defined (HAVE_SELECT)
411 r
= _Jv_select (fd
+ 1, &rd
, NULL
, NULL
, &tv
);
414 num
= r
== 0 ? 0 : 1;
416 #endif /* HAVE_SELECT */