• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.io;
28 
29 import static android.system.OsConstants.O_RDONLY;
30 
31 import java.nio.channels.FileChannel;
32 
33 import dalvik.annotation.optimization.ReachabilitySensitive;
34 import dalvik.system.BlockGuard;
35 import dalvik.system.CloseGuard;
36 import java.util.Arrays;
37 import jdk.internal.util.ArraysSupport;
38 import sun.nio.ch.FileChannelImpl;
39 import libcore.io.IoBridge;
40 import libcore.io.IoTracker;
41 import libcore.io.IoUtils;
42 
43 /**
44  * A {@code FileInputStream} obtains input bytes
45  * from a file in a file system. What files
46  * are  available depends on the host environment.
47  *
48  * <p>{@code FileInputStream} is meant for reading streams of raw bytes
49  * such as image data. For reading streams of characters, consider using
50  * {@code FileReader}.
51  *
52  * @apiNote
53  * To release resources used by this stream {@link #close} should be called
54  * directly or by try-with-resources. Subclasses are responsible for the cleanup
55  * of resources acquired by the subclass.
56  * Subclasses that override {@link #finalize} in order to perform cleanup
57  * should be modified to use alternative cleanup mechanisms such as
58  * {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
59  *
60  * @implSpec
61  * If this FileInputStream has been subclassed and the {@link #close}
62  * method has been overridden, the {@link #close} method will be
63  * called when the FileInputStream is unreachable.
64  * Otherwise, it is implementation specific how the resource cleanup described in
65  * {@link #close} is performed.
66  *
67  * @author  Arthur van Hoff
68  * @see     java.io.File
69  * @see     java.io.FileDescriptor
70  * @see     java.io.FileOutputStream
71  * @see     java.nio.file.Files#newInputStream
72  * @since   1.0
73  */
74 public class FileInputStream extends InputStream
75 {
76     private static final int DEFAULT_BUFFER_SIZE = 8192;
77 
78     /* File Descriptor - handle to the open file */
79     // Android-added: @ReachabilitySensitive
80     @ReachabilitySensitive
81     private final FileDescriptor fd;
82 
83     /**
84      * The path of the referenced file
85      * (null if the stream is created with a file descriptor)
86      */
87     private final String path;
88 
89     private volatile FileChannel channel;
90 
91     private final Object closeLock = new Object();
92 
93     private volatile boolean closed;
94 
95     // Android-added: Field for tracking whether the stream owns the underlying FileDescriptor.
96     private final boolean isFdOwner;
97 
98     // Android-added: CloseGuard support.
99     @ReachabilitySensitive
100     private final CloseGuard guard = CloseGuard.get();
101 
102     // Android-added: Tracking of unbuffered I/O.
103     private final IoTracker tracker = new IoTracker();
104 
105     /**
106      * Creates a {@code FileInputStream} by
107      * opening a connection to an actual file,
108      * the file named by the path name {@code name}
109      * in the file system.  A new {@code FileDescriptor}
110      * object is created to represent this file
111      * connection.
112      * <p>
113      * First, if there is a security
114      * manager, its {@code checkRead} method
115      * is called with the {@code name} argument
116      * as its argument.
117      * <p>
118      * If the named file does not exist, is a directory rather than a regular
119      * file, or for some other reason cannot be opened for reading then a
120      * {@code FileNotFoundException} is thrown.
121      *
122      * @param      name   the system-dependent file name.
123      * @throws     FileNotFoundException  if the file does not exist,
124      *             is a directory rather than a regular file,
125      *             or for some other reason cannot be opened for
126      *             reading.
127      * @throws     SecurityException      if a security manager exists and its
128      *             {@code checkRead} method denies read access
129      *             to the file.
130      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
131      */
FileInputStream(String name)132     public FileInputStream(String name) throws FileNotFoundException {
133         this(name != null ? new File(name) : null);
134     }
135 
136     /**
137      * Creates a {@code FileInputStream} by
138      * opening a connection to an actual file,
139      * the file named by the {@code File}
140      * object {@code file} in the file system.
141      * A new {@code FileDescriptor} object
142      * is created to represent this file connection.
143      * <p>
144      * First, if there is a security manager,
145      * its {@code checkRead} method  is called
146      * with the path represented by the {@code file}
147      * argument as its argument.
148      * <p>
149      * If the named file does not exist, is a directory rather than a regular
150      * file, or for some other reason cannot be opened for reading then a
151      * {@code FileNotFoundException} is thrown.
152      *
153      * @param      file   the file to be opened for reading.
154      * @throws     FileNotFoundException  if the file does not exist,
155      *             is a directory rather than a regular file,
156      *             or for some other reason cannot be opened for
157      *             reading.
158      * @throws     SecurityException      if a security manager exists and its
159      *             {@code checkRead} method denies read access to the file.
160      * @see        java.io.File#getPath()
161      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
162      */
FileInputStream(File file)163     public FileInputStream(File file) throws FileNotFoundException {
164         String name = (file != null ? file.getPath() : null);
165         @SuppressWarnings("removal")
166         SecurityManager security = System.getSecurityManager();
167         if (security != null) {
168             security.checkRead(name);
169         }
170         if (name == null) {
171             throw new NullPointerException();
172         }
173         if (file.isInvalid()) {
174             throw new FileNotFoundException("Invalid file path");
175         }
176         // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
177         // http://b/112107427
178         // fd = new FileDescriptor();
179         fd = IoBridge.open(name, O_RDONLY);
180         // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
181 
182         // Android-changed: Tracking mechanism for FileDescriptor sharing.
183         // fd.attach(this);
184         isFdOwner = true;
185 
186         path = name;
187 
188         // Android-removed: Open files using IoBridge to share BlockGuard & StrictMode logic.
189         // open(name);
190 
191         // Android-added: File descriptor ownership tracking.
192         IoUtils.setFdOwner(this.fd, this);
193 
194         // Android-added: CloseGuard support.
195         guard.open("close");
196         // Android-removed: TODO: Enable this when FileCleanable is imported to replace finalize().
197         // FileCleanable.register(fd);       // open set the fd, register the cleanup
198     }
199 
200     // Android-removed: Documentation around SecurityException. Not thrown on Android.
201     // Android-changed: Added doc for the Android-specific file descriptor ownership.
202     /**
203      * Creates a {@code FileInputStream} by using the file descriptor
204      * {@code fdObj}, which represents an existing connection to an
205      * actual file in the file system.
206      * <p>
207      * If there is a security manager, its {@code checkRead} method is
208      * called with the file descriptor {@code fdObj} as its argument to
209      * see if it's ok to read the file descriptor. If read access is denied
210      * to the file descriptor a {@code SecurityException} is thrown.
211      * <p>
212      * If {@code fdObj} is null then a {@code NullPointerException}
213      * is thrown.
214      * <p>
215      * This constructor does not throw an exception if {@code fdObj}
216      * is {@link java.io.FileDescriptor#valid() invalid}.
217      * However, if the methods are invoked on the resulting stream to attempt
218      * I/O on the stream, an {@code IOException} is thrown.
219      * <p>
220      * Android-specific warning: {@link #close()} method doesn't close the {@code fdObj} provided,
221      * because this object doesn't own the file descriptor, but the caller does. The
222      * caller can call {@link android.system.Os#close(FileDescriptor)} to close the fd.
223      *
224      * @param      fdObj   the file descriptor to be opened for reading.
225      * @throws     SecurityException      if a security manager exists and its
226      *             {@code checkRead} method denies read access to the
227      *             file descriptor.
228      * @see        SecurityManager#checkRead(java.io.FileDescriptor)
229      */
FileInputStream(FileDescriptor fdObj)230     public FileInputStream(FileDescriptor fdObj) {
231         // Android-changed: Delegate to added hidden constructor.
232         this(fdObj, false /* isFdOwner */);
233     }
234 
235     // Android-added: Internal/hidden constructor for specifying FileDescriptor ownership.
236     // Android-removed: SecurityManager calls.
237     /** @hide */
FileInputStream(FileDescriptor fdObj, boolean isFdOwner)238     public FileInputStream(FileDescriptor fdObj, boolean isFdOwner) {
239         if (fdObj == null) {
240             // Android-changed: Improved NullPointerException message.
241             throw new NullPointerException("fdObj == null");
242         }
243         fd = fdObj;
244         path = null;
245 
246         // Android-changed: FileDescriptor ownership tracking mechanism.
247         /*
248         /*
249          * FileDescriptor is being shared by streams.
250          * Register this stream with FileDescriptor tracker.
251          *
252         fd.attach(this);
253         */
254         this.isFdOwner = isFdOwner;
255         if (isFdOwner) {
256             IoUtils.setFdOwner(this.fd, this);
257         }
258     }
259 
260     // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
261     // http://b/112107427
262     /*
263     /**
264      * Opens the specified file for reading.
265      * @param name the name of the file
266      *
267     private native void open0(String name) throws FileNotFoundException;
268 
269     // wrap native call to allow instrumentation
270     /**
271      * Opens the specified file for reading.
272      * @param name the name of the file
273      *
274     private void open(String name) throws FileNotFoundException {
275         open0(name);
276     }
277     */
278     // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
279 
280     /**
281      * Reads a byte of data from this input stream. This method blocks
282      * if no input is yet available.
283      *
284      * @return     the next byte of data, or {@code -1} if the end of the
285      *             file is reached.
286      * @throws     IOException  if an I/O error occurs.
287      */
read()288     public int read() throws IOException {
289         // Android-changed: Read methods delegate to read(byte[], int, int) to share Android logic.
290         byte[] b = new byte[1];
291         return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
292     }
293 
294     // Android-removed: Read methods delegate to read(byte[], int, int) to share Android logic.
295     // private native int read0() throws IOException;
296 
297     // Android-removed: Read methods delegate to read(byte[], int, int) to share Android logic.
298     /*
299     /**
300      * Reads a subarray as a sequence of bytes.
301      * @param     b the data to be written
302      * @param     off the start offset in the data
303      * @param     len the number of bytes that are written
304      * @throws    IOException If an I/O error has occurred.
305      *
306     private native int readBytes(byte b[], int off, int len) throws IOException;
307     */
308 
309     /**
310      * Reads up to {@code b.length} bytes of data from this input
311      * stream into an array of bytes. This method blocks until some input
312      * is available.
313      *
314      * @param      b   the buffer into which the data is read.
315      * @return     the total number of bytes read into the buffer, or
316      *             {@code -1} if there is no more data because the end of
317      *             the file has been reached.
318      * @throws     IOException  if an I/O error occurs.
319      */
read(byte b[])320     public int read(byte b[]) throws IOException {
321         // Android-changed: Read methods delegate to read(byte[], int, int) to share Android logic.
322         return read(b, 0, b.length);
323     }
324 
325     /**
326      * Reads up to {@code len} bytes of data from this input stream
327      * into an array of bytes. If {@code len} is not zero, the method
328      * blocks until some input is available; otherwise, no
329      * bytes are read and {@code 0} is returned.
330      *
331      * @param      b     the buffer into which the data is read.
332      * @param      off   the start offset in the destination array {@code b}
333      * @param      len   the maximum number of bytes read.
334      * @return     the total number of bytes read into the buffer, or
335      *             {@code -1} if there is no more data because the end of
336      *             the file has been reached.
337      * @throws     NullPointerException If {@code b} is {@code null}.
338      * @throws     IndexOutOfBoundsException If {@code off} is negative,
339      *             {@code len} is negative, or {@code len} is greater than
340      *             {@code b.length - off}
341      * @throws     IOException  if an I/O error occurs.
342      */
read(byte b[], int off, int len)343     public int read(byte b[], int off, int len) throws IOException {
344         // Android-added: close() check before I/O.
345         if (closed && len > 0) {
346             throw new IOException("Stream Closed");
347         }
348 
349         // Android-added: Tracking of unbuffered I/O.
350         tracker.trackIo(len, IoTracker.Mode.READ);
351 
352         // Android-changed: Use IoBridge instead of calling native method.
353         return IoBridge.read(fd, b, off, len);
354     }
355 
356     // BEGIN Android-changed: Disable overridden implementation of readAllBytes() and readNBytes().
357     // Use the parent's implementation and avoid perform seek on non-seekable fd.
358     // http://b/325950521
359     /*
360     public byte[] readAllBytes() throws IOException {
361         long length = length();
362         long position = position();
363         long size = length - position;
364 
365         if (length <= 0 || size <= 0)
366             return super.readAllBytes();
367 
368         if (size > (long) Integer.MAX_VALUE) {
369             String msg =
370                 String.format("Required array size too large for %s: %d = %d - %d",
371                     path, size, length, position);
372             throw new OutOfMemoryError(msg);
373         }
374 
375         int capacity = (int)size;
376         byte[] buf = new byte[capacity];
377 
378         int nread = 0;
379         int n;
380         for (;;) {
381             // read to EOF which may read more or less than initial size, e.g.,
382             // file is truncated while we are reading
383             while ((n = read(buf, nread, capacity - nread)) > 0)
384                 nread += n;
385 
386             // if last call to read() returned -1, we are done; otherwise,
387             // try to read one more byte and if that fails we're done too
388             if (n < 0 || (n = read()) < 0)
389                 break;
390 
391             // one more byte was read; need to allocate a larger buffer
392             capacity = Math.max(ArraysSupport.newLength(capacity,
393                                                         1,         // min growth
394                                                         capacity), // pref growth
395                                 DEFAULT_BUFFER_SIZE);
396             buf = Arrays.copyOf(buf, capacity);
397             buf[nread++] = (byte)n;
398         }
399         return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
400     }
401 
402     public byte[] readNBytes(int len) throws IOException {
403         if (len < 0)
404             throw new IllegalArgumentException("len < 0");
405         if (len == 0)
406             return new byte[0];
407 
408         long length = length();
409         long position = position();
410         long size = length - position;
411 
412         if (length <= 0 || size <= 0)
413             return super.readNBytes(len);
414 
415         int capacity = (int)Math.min(len, size);
416         byte[] buf = new byte[capacity];
417 
418         int remaining = capacity;
419         int nread = 0;
420         int n;
421         do {
422             n = read(buf, nread, remaining);
423             if (n > 0 ) {
424                 nread += n;
425                 remaining -= n;
426             } else if (n == 0) {
427                 // Block until a byte is read or EOF is detected
428                 byte b = (byte)read();
429                 if (b == -1 )
430                     break;
431                 buf[nread++] = b;
432                 remaining--;
433             }
434         } while (n >= 0 && remaining > 0);
435         return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
436     }
437     */
438     // END Android-changed: Disable overridden implementation of readAllBytes() and readNBytes().
439 
length()440     private long length() throws IOException {
441         return length0();
442     }
length0()443     private native long length0() throws IOException;
444 
position()445     private long position() throws IOException {
446         return position0();
447     }
position0()448     private native long position0() throws IOException;
449 
450     /**
451      * Skips over and discards {@code n} bytes of data from the
452      * input stream.
453      *
454      * <p>The {@code skip} method may, for a variety of
455      * reasons, end up skipping over some smaller number of bytes,
456      * possibly {@code 0}. If {@code n} is negative, the method
457      * will try to skip backwards. In case the backing file does not support
458      * backward skip at its current position, an {@code IOException} is
459      * thrown. The actual number of bytes skipped is returned. If it skips
460      * forwards, it returns a positive value. If it skips backwards, it
461      * returns a negative value.
462      *
463      * <p>This method may skip more bytes than what are remaining in the
464      * backing file. This produces no exception and the number of bytes skipped
465      * may include some number of bytes that were beyond the EOF of the
466      * backing file. Attempting to read from the stream after skipping past
467      * the end will result in -1 indicating the end of the file.
468      *
469      * @param      n   the number of bytes to be skipped.
470      * @return     the actual number of bytes skipped.
471      * @throws     IOException  if n is negative, if the stream does not
472      *             support seek, or if an I/O error occurs.
473      */
474     // BEGIN Android-changed: skip(long) implementation changed from bare native.
skip(long n)475     public long skip(long n) throws IOException {
476         // Android-added: close() check before I/O.
477         if (closed) {
478             throw new IOException("Stream Closed");
479         }
480 
481         try {
482             // Android-added: BlockGuard support.
483             BlockGuard.getThreadPolicy().onReadFromDisk();
484             return skip0(n);
485         } catch(UseManualSkipException e) {
486             return super.skip(n);
487         }
488     }
489 
skip0(long n)490     private native long skip0(long n) throws IOException, UseManualSkipException;
491 
492     /*
493      * Used to force manual skip when FileInputStream operates on pipe
494      */
495     private static class UseManualSkipException extends Exception {
496     }
497     // END Android-changed: skip(long) implementation changed from bare native.
498 
499     /**
500      * Returns an estimate of the number of remaining bytes that can be read (or
501      * skipped over) from this input stream without blocking by the next
502      * invocation of a method for this input stream. Returns 0 when the file
503      * position is beyond EOF. The next invocation might be the same thread
504      * or another thread. A single read or skip of this many bytes will not
505      * block, but may read or skip fewer bytes.
506      *
507      * <p> In some cases, a non-blocking read (or skip) may appear to be
508      * blocked when it is merely slow, for example when reading large
509      * files over slow networks.
510      *
511      * @return     an estimate of the number of remaining bytes that can be read
512      *             (or skipped over) from this input stream without blocking.
513      * @throws     IOException  if this file input stream has been closed by calling
514      *             {@code close} or an I/O error occurs.
515      */
516     // BEGIN Android-changed: available() implementation changed from bare native.
available()517     public int available() throws IOException {
518         // Android-added: close() check before I/O.
519         if (closed) {
520             throw new IOException("Stream Closed");
521         }
522 
523         return available0();
524     }
525 
available0()526     private native int available0() throws IOException;
527     // END Android-changed: available() implementation changed from bare native.
528 
529     /**
530      * Closes this file input stream and releases any system resources
531      * associated with the stream.
532      *
533      * <p> If this stream has an associated channel then the channel is closed
534      * as well.
535      *
536      * @apiNote
537      * Overriding {@link #close} to perform cleanup actions is reliable
538      * only when called directly or when called by try-with-resources.
539      * Do not depend on finalization to invoke {@code close};
540      * finalization is not reliable and is deprecated.
541      * If cleanup of native resources is needed, other mechanisms such as
542      * {@linkplain java.lang.ref.Cleaner} should be used.
543      *
544      * @throws     IOException  if an I/O error occurs.
545      *
546      * @revised 1.4
547      */
close()548     public void close() throws IOException {
549         if (closed) {
550             return;
551         }
552         synchronized (closeLock) {
553             if (closed) {
554                 return;
555             }
556             closed = true;
557         }
558 
559         // Android-added: CloseGuard support.
560         guard.close();
561 
562         FileChannel fc = channel;
563         if (fc != null) {
564             // possible race with getChannel(), benign since
565             // FileChannel.close is final and idempotent
566             fc.close();
567         }
568 
569         // BEGIN Android-changed: Close handling / notification of blocked threads.
570         /*
571         fd.closeAll(new Closeable() {
572             public void close() throws IOException {
573                fd.close();
574            }
575         });
576         */
577         if (isFdOwner) {
578             IoBridge.closeAndSignalBlockedThreads(fd);
579         }
580         // END Android-changed: Close handling / notification of blocked threads.
581     }
582 
583     /**
584      * Returns the {@code FileDescriptor}
585      * object  that represents the connection to
586      * the actual file in the file system being
587      * used by this {@code FileInputStream}.
588      *
589      * @return     the file descriptor object associated with this stream.
590      * @throws     IOException  if an I/O error occurs.
591      * @see        java.io.FileDescriptor
592      */
getFD()593     public final FileDescriptor getFD() throws IOException {
594         if (fd != null) {
595             return fd;
596         }
597         throw new IOException();
598     }
599 
600     /**
601      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
602      * object associated with this file input stream.
603      *
604      * <p> The initial {@link java.nio.channels.FileChannel#position()
605      * position} of the returned channel will be equal to the
606      * number of bytes read from the file so far.  Reading bytes from this
607      * stream will increment the channel's position.  Changing the channel's
608      * position, either explicitly or by reading, will change this stream's
609      * file position.
610      *
611      * @return  the file channel associated with this file input stream
612      *
613      * @since 1.4
614      */
getChannel()615     public FileChannel getChannel() {
616         FileChannel fc = this.channel;
617         if (fc == null) {
618             synchronized (this) {
619                 fc = this.channel;
620                 if (fc == null) {
621                     this.channel = fc = FileChannelImpl.open(fd, path, true,
622                         // Android-changed: TODO: Remove this patch when direct flag is supported.
623                         // This patch should cause no behavior change as direct is off by default.
624                         // false, false, this);
625                         false, this);
626                     if (closed) {
627                         try {
628                             // possible race with close(), benign since
629                             // FileChannel.close is final and idempotent
630                             fc.close();
631                         } catch (IOException ioe) {
632                             throw new InternalError(ioe); // should not happen
633                         }
634                     }
635                 }
636             }
637         }
638         return fc;
639     }
640 
641     // BEGIN Android-removed: Unused code.
642     /*
643     private static native void initIDs();
644 
645     static {
646         initIDs();
647     }
648     */
649     // END Android-removed: Unused code.
650 
651     // TODO: Remove finalize() when FileCleanable is imported and used.
652     /**
653      * Ensures that the <code>close</code> method of this file input stream is
654      * called when there are no more references to it.
655      *
656      * @exception  IOException  if an I/O error occurs.
657      * @see        java.io.FileInputStream#close()
658      */
finalize()659     protected void finalize() throws IOException {
660         // Android-added: CloseGuard support.
661         if (guard != null) {
662             guard.warnIfOpen();
663         }
664 
665         if ((fd != null) &&  (fd != FileDescriptor.in)) {
666             // Android-removed: Obsoleted comment about shared FileDescriptor handling.
667             close();
668         }
669     }
670 }
671