1 |
/* FileDescriptor.java -- Opaque file handle class |
/* FileDescriptor.java -- Opaque file handle class |
2 |
Copyright (C) 1998 Free Software Foundation, Inc. |
Copyright (C) 1998,2003 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
45 |
* be used only to pass to other methods that expect an object of this |
* be used only to pass to other methods that expect an object of this |
46 |
* type. No system specific information can be obtained from this object. |
* type. No system specific information can be obtained from this object. |
47 |
* |
* |
|
* @version 0.1 |
|
|
* |
|
48 |
* @author Aaron M. Renn (arenn@urbanophile.com) |
* @author Aaron M. Renn (arenn@urbanophile.com) |
49 |
*/ |
*/ |
50 |
public final class FileDescriptor |
public final class FileDescriptor |
51 |
{ |
{ |
52 |
|
|
53 |
/*************************************************************************/ |
/*************************************************************************/ |
54 |
|
|
55 |
/* |
/* |
56 |
* Class Variables and Initializers |
* Class Variables and Initializers |
57 |
*/ |
*/ |
58 |
|
|
59 |
|
static |
60 |
|
{ |
61 |
|
if (Configuration.INIT_LOAD_LIBRARY) |
62 |
|
{ |
63 |
|
System.loadLibrary ("javaio"); |
64 |
|
} |
65 |
|
|
66 |
|
// nativeInit() should override these values if appropriate |
67 |
|
in = new FileDescriptor(0); |
68 |
|
out = new FileDescriptor(1); |
69 |
|
err = new FileDescriptor(2); |
70 |
|
|
71 |
|
SET = 0; |
72 |
|
CUR = 1; |
73 |
|
END = 2; |
74 |
|
|
75 |
|
nativeInit(); |
76 |
|
} |
77 |
|
|
78 |
|
// Use for seeking |
79 |
|
static final int SET; |
80 |
|
static final int CUR; |
81 |
|
static final int END; |
82 |
|
|
83 |
|
/** |
84 |
|
* A <code>FileDescriptor</code> representing the system standard input |
85 |
|
* stream. This will usually be accessed through the |
86 |
|
* <code>System.in</code>variable. |
87 |
|
*/ |
88 |
|
public static final FileDescriptor in; |
89 |
|
|
90 |
|
/** |
91 |
|
* A <code>FileDescriptor</code> representing the system standard output |
92 |
|
* stream. This will usually be accessed through the |
93 |
|
* <code>System.out</code>variable. |
94 |
|
*/ |
95 |
|
public static final FileDescriptor out; |
96 |
|
|
97 |
|
/** |
98 |
|
* A <code>FileDescriptor</code> representing the system standard error |
99 |
|
* stream. This will usually be accessed through the |
100 |
|
* <code>System.err</code>variable. |
101 |
|
*/ |
102 |
|
public static final FileDescriptor err; |
103 |
|
|
104 |
|
/*************************************************************************/ |
105 |
|
|
106 |
|
/** |
107 |
|
* Instance Variables |
108 |
|
*/ |
109 |
|
|
110 |
|
/** |
111 |
|
* This is the actual native file descriptor value |
112 |
|
*/ |
113 |
|
private long nativeFd = -1L; |
114 |
|
|
115 |
|
/*************************************************************************/ |
116 |
|
|
117 |
|
/* |
118 |
|
* Constructors |
119 |
|
*/ |
120 |
|
|
121 |
|
/** |
122 |
|
* This method is used to initialize an invalid FileDescriptor object. |
123 |
|
*/ |
124 |
|
public FileDescriptor() |
125 |
|
{ |
126 |
|
} |
127 |
|
|
128 |
/** |
private FileDescriptor(int nativeFd) |
129 |
* This is a <code>FileDescriptor</code> object representing the standard |
{ |
130 |
* input stream. |
this.nativeFd = nativeFd; |
131 |
*/ |
} |
|
public static final FileDescriptor in = new FileDescriptor(0); |
|
132 |
|
|
133 |
/** |
/*************************************************************************/ |
|
* This is a <code>FileDescriptor</code> object representing the standard |
|
|
* output stream. |
|
|
*/ |
|
|
public static final FileDescriptor out = new FileDescriptor(1); |
|
134 |
|
|
135 |
/** |
/* |
136 |
* This is a <code>FileDescriptor</code> object representing the standard |
* Instance Methods |
137 |
* error stream. |
*/ |
138 |
*/ |
|
139 |
public static final FileDescriptor err = new FileDescriptor(2); |
/** |
140 |
|
* This method forces all data that has not yet been physically written to |
141 |
|
* the underlying storage medium associated with this |
142 |
|
* <code>FileDescriptor</code> |
143 |
|
* to be written out. This method will not return until all data has |
144 |
|
* been fully written to the underlying device. If the device does not |
145 |
|
* support this functionality or if an error occurs, then an exception |
146 |
|
* will be thrown. |
147 |
|
*/ |
148 |
|
public void sync() throws SyncFailedException |
149 |
|
{ |
150 |
|
if (nativeFd == -1L) |
151 |
|
throw new SyncFailedException("Invalid FileDescriptor"); |
152 |
|
|
153 |
static |
nativeSync(nativeFd); |
154 |
|
} |
155 |
|
|
156 |
|
/** |
157 |
|
* This methods tests whether or not this object represents a valid open |
158 |
|
* native file handle. |
159 |
|
* |
160 |
|
* @return <code>true</code> if this object represents a valid |
161 |
|
* native file handle, <code>false</code> otherwise |
162 |
|
*/ |
163 |
|
public boolean valid() |
164 |
{ |
{ |
165 |
if (Configuration.INIT_LOAD_LIBRARY) |
if (nativeFd == -1L) |
166 |
|
return(false); |
167 |
|
|
168 |
|
try |
169 |
{ |
{ |
170 |
System.loadLibrary ("javaio"); |
return(nativeValid(nativeFd)); |
171 |
|
} |
172 |
|
catch (IOException e) |
173 |
|
{ |
174 |
|
return(false); |
175 |
} |
} |
176 |
} |
} |
177 |
|
|
178 |
/*************************************************************************/ |
void open(String path, String mode) throws IOException |
179 |
|
{ |
180 |
|
// We don't want fd leakage. |
181 |
|
if (nativeFd != -1L) |
182 |
|
throw new IOException("FileDescriptor already open"); |
183 |
|
|
184 |
|
if ((path == null) || path.equals("")) |
185 |
|
throw new IllegalArgumentException("Path cannot be null"); |
186 |
|
|
187 |
|
if (!mode.equals("r") && !mode.equals("rw") && !mode.equals("rws") && |
188 |
|
!mode.equals("rwd") & !mode.equals("ra")) |
189 |
|
throw new IllegalArgumentException("Invalid mode value: " + mode); |
190 |
|
// Note above implicitly checks mode for null value |
191 |
|
|
192 |
/** |
nativeFd = nativeOpen(path, mode); |
193 |
* Instance Variables |
} |
|
*/ |
|
194 |
|
|
195 |
/** |
void close() throws IOException |
196 |
* This is the actual native file descriptor value |
{ |
197 |
*/ |
if (nativeFd == -1L) |
198 |
private int native_fd; |
return; |
199 |
|
|
200 |
/*************************************************************************/ |
nativeClose(nativeFd); |
201 |
|
nativeFd = -1L; |
202 |
|
} |
203 |
|
|
204 |
/* |
void write(int b) throws IOException |
205 |
* Class Methods |
{ |
206 |
*/ |
if (nativeFd == -1L) |
207 |
private static FileDescriptor |
throw new IOException("Invalid FileDescriptor"); |
|
getFileDescriptor(int native_fd) |
|
|
{ |
|
|
return(new FileDescriptor(native_fd)); |
|
|
} |
|
208 |
|
|
209 |
/*************************************************************************/ |
nativeWriteByte(nativeFd, (long)(b & 0xFF)); |
210 |
|
} |
211 |
|
|
212 |
/* |
void write(byte[] buf, long offset, long len) throws IOException |
213 |
* Constructors |
{ |
214 |
*/ |
if (nativeFd == -1L) |
215 |
|
throw new IOException("Invalid FileDescriptor"); |
216 |
|
|
217 |
/** |
if (len == 0) |
218 |
* This method is used to initialize an invalid FileDescriptor object. |
return; |
|
*/ |
|
|
public |
|
|
FileDescriptor() |
|
|
{ |
|
|
; |
|
|
} |
|
219 |
|
|
220 |
/*************************************************************************/ |
if ((offset < 0) || (offset > buf.length)) |
221 |
|
throw new IllegalArgumentException("Offset invalid: " + offset); |
222 |
|
|
223 |
/** |
if ((len < 0) || (len > (buf.length - offset))) |
224 |
* This method is used to initialize a <code>FileDescriptor</code> that will |
throw new IllegalArgumentException("Length invalid: " + len); |
|
* represent the specified native file handle. |
|
|
* |
|
|
* @param native_fd The native file handle this object should represent |
|
|
*/ |
|
|
FileDescriptor(int native_fd) |
|
|
{ |
|
|
this.native_fd = native_fd; |
|
|
} |
|
225 |
|
|
226 |
/*************************************************************************/ |
// Note that above ops implicitly bomb if buf == null |
227 |
|
|
228 |
/* |
nativeWriteBuf(nativeFd, buf, offset, len); |
229 |
* Instance Methods |
} |
|
*/ |
|
230 |
|
|
231 |
/** |
int read() throws IOException |
232 |
* This method forces all data that has not yet been physically written to |
{ |
233 |
* the underlying storage medium associated with this <code>FileDescriptor</code> |
if (nativeFd == -1L) |
234 |
* to be written out. This method will not return until all data has |
throw new IOException("Invalid FileDescriptor"); |
|
* been fully written to the underlying device. If the device does not |
|
|
* support this functionality or if an error occurs, then an exception |
|
|
* will be thrown. |
|
|
*/ |
|
|
public void |
|
|
sync() throws SyncFailedException |
|
|
{ |
|
|
syncInternal(native_fd); |
|
|
} |
|
235 |
|
|
236 |
/*************************************************************************/ |
long byteRead = nativeReadByte(nativeFd); |
237 |
|
if (byteRead == -1L) |
238 |
|
return(-1); |
239 |
|
|
240 |
/** |
return((int)(byteRead & 0xFF)); |
241 |
* This is the native method where the actual sync'ing of data to disk |
} |
242 |
* is performed. |
|
243 |
* |
int read(byte[] buf, int offset, int len) throws IOException |
244 |
* @param native_fd The native file handle |
{ |
245 |
* |
if (nativeFd == -1L) |
246 |
* @exception SyncFailedException If an error occurs or sync is not supported |
throw new IOException("Invalid FileDescriptor"); |
|
*/ |
|
|
native void |
|
|
syncInternal(int native_fd); |
|
247 |
|
|
248 |
/*************************************************************************/ |
if (len == 0) |
249 |
|
return(0); |
250 |
|
|
251 |
/** |
if ((offset < 0) || (offset > buf.length)) |
252 |
* This methods tests whether or not this object represents a valid open |
throw new IllegalArgumentException("Offset invalid: " + offset); |
|
* native file handle. |
|
|
* |
|
|
* @return <code>true</code> if this object represents a valid native file handle, <code>false</code> otherwise |
|
|
*/ |
|
|
public boolean |
|
|
valid() |
|
|
{ |
|
|
return(validInternal(native_fd)); |
|
|
} |
|
253 |
|
|
254 |
/*************************************************************************/ |
if ((len < 0) || (len > (buf.length - offset))) |
255 |
|
throw new IllegalArgumentException("Length invalid: " + len); |
256 |
|
|
257 |
/** |
// Note that above ops implicitly bomb if buf == null |
|
* This is the native method which actually tests whether or not this |
|
|
* object represents a valid native file handle. |
|
|
* |
|
|
* @param native_fd The native file handle |
|
|
* |
|
|
* @return <code>true</code> if this object represents a valid native file handle, <code>false</code> otherwise |
|
|
*/ |
|
|
native boolean |
|
|
validInternal(int native_fd); |
|
258 |
|
|
259 |
/*************************************************************************/ |
long bytesRead = nativeReadBuf(nativeFd, buf, offset, len); |
260 |
|
if (bytesRead == -1L) |
261 |
|
return(-1); |
262 |
|
|
263 |
/** |
return((int)(bytesRead & 0xFFFF)); |
264 |
* This method eturns the native file handle represented by this object |
} |
|
* |
|
|
* @return The native file handle this object represents |
|
|
*/ |
|
|
int |
|
|
getNativeFD() |
|
|
{ |
|
|
return(native_fd); |
|
|
} |
|
265 |
|
|
266 |
/*************************************************************************/ |
int available() throws IOException |
267 |
|
{ |
268 |
|
if (nativeFd == -1L) |
269 |
|
throw new IOException("Invalid FileDescriptor"); |
270 |
|
|
271 |
|
long bytesAvail = nativeAvailable(nativeFd); |
272 |
|
|
273 |
|
// FIXME: Is this right? |
274 |
|
if (bytesAvail > 0xFFFFL) |
275 |
|
return(0xFFFF); |
276 |
|
else |
277 |
|
return((int)(bytesAvail & 0xFFFF)); |
278 |
|
} |
279 |
|
|
280 |
/** |
long seek(long offset, int whence, boolean stopAtEof) throws IOException |
281 |
* This method sets the native file descriptor this object represents to |
{ |
282 |
* the specified value. |
if (nativeFd == -1L) |
283 |
* |
throw new IOException("Invalid FileDescriptor"); |
284 |
* @param The native file handle this object should represent. |
|
285 |
*/ |
if ((whence != SET) && (whence != CUR) && (whence != END)) |
286 |
void |
throw new IllegalArgumentException("Invalid whence value: " + whence); |
287 |
setNativeFD(int native_fd) |
|
288 |
{ |
return(nativeSeek(nativeFd, offset, whence, stopAtEof)); |
289 |
this.native_fd = native_fd; |
} |
290 |
} |
|
291 |
|
long getFilePointer() throws IOException |
292 |
|
{ |
293 |
|
if (nativeFd == -1L) |
294 |
|
throw new IOException("Invalid FileDescriptor"); |
295 |
|
|
296 |
|
return(nativeGetFilePointer(nativeFd)); |
297 |
|
} |
298 |
|
|
299 |
|
long getLength() throws IOException |
300 |
|
{ |
301 |
|
if (nativeFd == -1L) |
302 |
|
throw new IOException("Invalid FileDescriptor"); |
303 |
|
|
304 |
|
return(nativeGetLength(nativeFd)); |
305 |
|
} |
306 |
|
|
307 |
|
void setLength(long len) throws IOException |
308 |
|
{ |
309 |
|
if (nativeFd == -1L) |
310 |
|
throw new IOException("Invalid FileDescriptor"); |
311 |
|
|
312 |
|
if (len < 0) |
313 |
|
throw new IllegalArgumentException("Length cannot be less than zero " + |
314 |
|
len); |
315 |
|
|
316 |
|
nativeSetLength(nativeFd, len); |
317 |
|
} |
318 |
|
|
319 |
|
// Don't do anything crazy with this |
320 |
|
long getNativeFd() |
321 |
|
{ |
322 |
|
return(nativeFd); |
323 |
|
} |
324 |
|
|
325 |
|
private void setNativeFd(long nativeFd) |
326 |
|
{ |
327 |
|
this.nativeFd = nativeFd; |
328 |
|
} |
329 |
|
|
330 |
|
protected void finalize() throws Throwable |
331 |
|
{ |
332 |
|
close(); |
333 |
|
} |
334 |
|
|
335 |
|
/*************************************************************************/ |
336 |
|
|
337 |
|
/* |
338 |
|
* Native FileDescriptor provider interface |
339 |
|
* |
340 |
|
* Platform implementors must implement these methods. Note that this |
341 |
|
* class guarantees that valid data will be passed to these methods, |
342 |
|
* so basic error checking on input values can be skipped. |
343 |
|
*/ |
344 |
|
|
345 |
|
/** |
346 |
|
* This method is called in the class initializer to do any require |
347 |
|
* native library initialization. It is also responsible for initializing |
348 |
|
* the in, out, and err variables. |
349 |
|
*/ |
350 |
|
private static native void nativeInit(); |
351 |
|
|
352 |
|
/** |
353 |
|
* Opens the specified file in the specified mode. This can be done |
354 |
|
* in one of the specified modes: |
355 |
|
* <ul> |
356 |
|
* <li>r - Read Only |
357 |
|
* <li>rw - Read / Write |
358 |
|
* <li>ra - Read / Write - append to end of file |
359 |
|
* <li>rws - Read / Write - synchronous writes of data/metadata |
360 |
|
* <li>rwd - Read / Write - synchronous writes of data. |
361 |
|
* |
362 |
|
* @param path Name of the file to open |
363 |
|
* @param mode Mode to open |
364 |
|
* |
365 |
|
* @returns The resulting file descriptor for the opened file, or -1 |
366 |
|
* on failure (exception also signaled). |
367 |
|
* |
368 |
|
* @exception IOException If an error occurs. |
369 |
|
*/ |
370 |
|
private native long nativeOpen(String path, String mode) throws IOException; |
371 |
|
|
372 |
|
/** |
373 |
|
* Closes this specified file descriptor |
374 |
|
* |
375 |
|
* @param fd The native file descriptor to close |
376 |
|
* |
377 |
|
* @returns The return code of the native close command. |
378 |
|
* |
379 |
|
* @exception IOException If an error occurs |
380 |
|
*/ |
381 |
|
private native long nativeClose(long fd) throws IOException; |
382 |
|
|
383 |
|
/** |
384 |
|
* Writes a single byte to the file |
385 |
|
* |
386 |
|
* @param fd The native file descriptor to write to |
387 |
|
* @param b The byte to write, encoded in the low eight bits |
388 |
|
* |
389 |
|
* @return The return code of the native write command |
390 |
|
* |
391 |
|
* @exception IOException If an error occurs |
392 |
|
*/ |
393 |
|
private native long nativeWriteByte(long fd, long b) throws IOException; |
394 |
|
// I hate name mangling. |
395 |
|
|
396 |
|
/** |
397 |
|
* Writes a byte buffer to the file |
398 |
|
* |
399 |
|
* @param fd The native file descriptor to write to |
400 |
|
* @param buf The byte buffer to write from |
401 |
|
* @param int The offset into the buffer to start writing from |
402 |
|
* @param len The number of bytes to write. |
403 |
|
* |
404 |
|
* @return The return code of the native write command |
405 |
|
* |
406 |
|
* @exception IOException If an error occurs |
407 |
|
*/ |
408 |
|
private native long nativeWriteBuf(long fd, byte[] buf, long offset, long len) |
409 |
|
throws IOException; |
410 |
|
// I hate name mangling. |
411 |
|
|
412 |
|
/** |
413 |
|
* Reads a single byte from the file |
414 |
|
* |
415 |
|
* @param fd The native file descriptor to read from |
416 |
|
* |
417 |
|
* @return The byte read, in the low eight bits on a long, or -1 |
418 |
|
* if end of file |
419 |
|
* |
420 |
|
* @exception IOException If an error occurs |
421 |
|
*/ |
422 |
|
private native long nativeReadByte(long fd) throws IOException; |
423 |
|
// I hate name mangling. |
424 |
|
|
425 |
|
/** |
426 |
|
* Reads a buffer of bytes from the file |
427 |
|
* |
428 |
|
* @param fd The native file descriptor to read from |
429 |
|
* @param buf The buffer to read bytes into |
430 |
|
* @param offset The offset into the buffer to start storing bytes |
431 |
|
* @param len The number of bytes to read. |
432 |
|
* |
433 |
|
* @return The number of bytes read, or -1 if end of file. |
434 |
|
* |
435 |
|
* @exception IOException If an error occurs |
436 |
|
*/ |
437 |
|
private native long nativeReadBuf(long fd, byte[] buf, long offset, long len) |
438 |
|
throws IOException; |
439 |
|
// I hate name mangling. |
440 |
|
|
441 |
|
/** |
442 |
|
* Returns the number of bytes available for reading |
443 |
|
* |
444 |
|
* @param fd The native file descriptor |
445 |
|
* |
446 |
|
* @return The number of bytes available for reading |
447 |
|
* |
448 |
|
* @exception IOException If an error occurs |
449 |
|
*/ |
450 |
|
private native long nativeAvailable(long fd) throws IOException; |
451 |
|
|
452 |
|
/** |
453 |
|
* Method to do a "seek" operation on the file |
454 |
|
* |
455 |
|
* @param fd The native file descriptor |
456 |
|
* @param offset The number of bytes to seek |
457 |
|
* @param whence The position to seek from, either |
458 |
|
* SET (0) for the beginning of the file, CUR (1) for the |
459 |
|
* current position or END (2) for the end position. |
460 |
|
* @param stopAtEof <code>true</code> to ensure that there is no |
461 |
|
* seeking past the end of the file, <code>false</code> otherwise. |
462 |
|
* |
463 |
|
* @return The new file position, or -1 if end of file. |
464 |
|
* |
465 |
|
* @exception IOException If an error occurs |
466 |
|
*/ |
467 |
|
private native long nativeSeek(long fd, long offset, int whence, |
468 |
|
boolean stopAtEof) |
469 |
|
throws IOException; |
470 |
|
|
471 |
|
/** |
472 |
|
* Returns the current position of the file pointer in the file |
473 |
|
* |
474 |
|
* @param fd The native file descriptor |
475 |
|
* |
476 |
|
* @exception IOException If an error occurs |
477 |
|
*/ |
478 |
|
private native long nativeGetFilePointer(long fd) throws IOException; |
479 |
|
// Really could implement in terms of seek |
480 |
|
|
481 |
|
/** |
482 |
|
* Returns the length of the file in bytes |
483 |
|
* |
484 |
|
* @param fd The native file descriptor |
485 |
|
* |
486 |
|
* @return The length of the file in bytes |
487 |
|
* |
488 |
|
* @exception IOException If an error occurs |
489 |
|
*/ |
490 |
|
private native long nativeGetLength(long fd) throws IOException; |
491 |
|
|
492 |
|
/** |
493 |
|
* Sets the length of the file to the specified number of bytes |
494 |
|
* This can result in truncation or extension. |
495 |
|
* |
496 |
|
* @param fd The native file descriptor |
497 |
|
* |
498 |
|
* @param len The new length of the file |
499 |
|
* |
500 |
|
* @exception IOException If an error occurs |
501 |
|
*/ |
502 |
|
private native void nativeSetLength(long fd, long len) throws IOException; |
503 |
|
|
504 |
|
/** |
505 |
|
* Tests a file descriptor for validity |
506 |
|
* |
507 |
|
* @param fd The native file descriptor |
508 |
|
* |
509 |
|
* @return <code>true</code> if the fd is valid, <code>false</code> |
510 |
|
* otherwise |
511 |
|
* |
512 |
|
* @exception IOException If an error occurs |
513 |
|
*/ |
514 |
|
private native boolean nativeValid(long fd) throws IOException; |
515 |
|
|
516 |
|
/** |
517 |
|
* Flushes any buffered contents to disk |
518 |
|
* |
519 |
|
* @param fd The native file descriptor |
520 |
|
* |
521 |
|
* @exception IOException If an error occurs |
522 |
|
*/ |
523 |
|
private native void nativeSync(long fd) throws SyncFailedException; |
524 |
|
|
525 |
} // class FileDescriptor |
} // class FileDescriptor |
526 |
|
|