• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1994, 2013, 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 sun.nio.ch.FileChannelImpl;
37 import libcore.io.IoBridge;
38 import libcore.io.IoTracker;
39 import libcore.io.IoUtils;
40 
41 
42 /**
43  * A <code>FileInputStream</code> obtains input bytes
44  * from a file in a file system. What files
45  * are  available depends on the host environment.
46  *
47  * <p><code>FileInputStream</code> is meant for reading streams of raw bytes
48  * such as image data. For reading streams of characters, consider using
49  * <code>FileReader</code>.
50  *
51  * @author  Arthur van Hoff
52  * @see     java.io.File
53  * @see     java.io.FileDescriptor
54  * @see     java.io.FileOutputStream
55  * @see     java.nio.file.Files#newInputStream
56  * @since   JDK1.0
57  */
58 public
59 class FileInputStream extends InputStream
60 {
61     /* File Descriptor - handle to the open file */
62     // Android-added: @ReachabilitySensitive
63     @ReachabilitySensitive
64     private final FileDescriptor fd;
65 
66     /**
67      * The path of the referenced file
68      * (null if the stream is created with a file descriptor)
69      */
70     private final String path;
71 
72     private FileChannel channel = null;
73 
74     private final Object closeLock = new Object();
75     private volatile boolean closed = false;
76 
77     // Android-added: Field for tracking whether the stream owns the underlying FileDescriptor.
78     private final boolean isFdOwner;
79 
80     // Android-added: CloseGuard support.
81     @ReachabilitySensitive
82     private final CloseGuard guard = CloseGuard.get();
83 
84     // Android-added: Tracking of unbuffered I/O.
85     private final IoTracker tracker = new IoTracker();
86 
87     /**
88      * Creates a <code>FileInputStream</code> by
89      * opening a connection to an actual file,
90      * the file named by the path name <code>name</code>
91      * in the file system.  A new <code>FileDescriptor</code>
92      * object is created to represent this file
93      * connection.
94      * <p>
95      * First, if there is a security
96      * manager, its <code>checkRead</code> method
97      * is called with the <code>name</code> argument
98      * as its argument.
99      * <p>
100      * If the named file does not exist, is a directory rather than a regular
101      * file, or for some other reason cannot be opened for reading then a
102      * <code>FileNotFoundException</code> is thrown.
103      *
104      * @param      name   the system-dependent file name.
105      * @exception  FileNotFoundException  if the file does not exist,
106      *                   is a directory rather than a regular file,
107      *                   or for some other reason cannot be opened for
108      *                   reading.
109      * @exception  SecurityException      if a security manager exists and its
110      *               <code>checkRead</code> method denies read access
111      *               to the file.
112      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
113      */
FileInputStream(String name)114     public FileInputStream(String name) throws FileNotFoundException {
115         this(name != null ? new File(name) : null);
116     }
117 
118     /**
119      * Creates a <code>FileInputStream</code> by
120      * opening a connection to an actual file,
121      * the file named by the <code>File</code>
122      * object <code>file</code> in the file system.
123      * A new <code>FileDescriptor</code> object
124      * is created to represent this file connection.
125      * <p>
126      * First, if there is a security manager,
127      * its <code>checkRead</code> method  is called
128      * with the path represented by the <code>file</code>
129      * argument as its argument.
130      * <p>
131      * If the named file does not exist, is a directory rather than a regular
132      * file, or for some other reason cannot be opened for reading then a
133      * <code>FileNotFoundException</code> is thrown.
134      *
135      * @param      file   the file to be opened for reading.
136      * @exception  FileNotFoundException  if the file does not exist,
137      *                   is a directory rather than a regular file,
138      *                   or for some other reason cannot be opened for
139      *                   reading.
140      * @exception  SecurityException      if a security manager exists and its
141      *               <code>checkRead</code> method denies read access to the file.
142      * @see        java.io.File#getPath()
143      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
144      */
FileInputStream(File file)145     public FileInputStream(File file) throws FileNotFoundException {
146         String name = (file != null ? file.getPath() : null);
147         SecurityManager security = System.getSecurityManager();
148         if (security != null) {
149             security.checkRead(name);
150         }
151         if (name == null) {
152             throw new NullPointerException();
153         }
154         if (file.isInvalid()) {
155             throw new FileNotFoundException("Invalid file path");
156         }
157         // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
158         // http://b/112107427
159         // fd = new FileDescriptor();
160         fd = IoBridge.open(name, O_RDONLY);
161         // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
162 
163         // Android-changed: Tracking mechanism for FileDescriptor sharing.
164         // fd.attach(this);
165         isFdOwner = true;
166 
167         path = name;
168 
169         // Android-removed: Open files using IoBridge to share BlockGuard & StrictMode logic.
170         // open(name);
171 
172         // Android-added: File descriptor ownership tracking.
173         IoUtils.setFdOwner(this.fd, this);
174 
175         // Android-added: CloseGuard support.
176         guard.open("close");
177     }
178 
179     // Android-removed: Documentation around SecurityException. Not thrown on Android.
180     // Android-changed: Added doc for the Android-specific file descriptor ownership.
181     /**
182      * Creates a <code>FileInputStream</code> by using the file descriptor
183      * <code>fdObj</code>, which represents an existing connection to an
184      * actual file in the file system.
185      * <p>
186      * If there is a security manager, its <code>checkRead</code> method is
187      * called with the file descriptor <code>fdObj</code> as its argument to
188      * see if it's ok to read the file descriptor. If read access is denied
189      * to the file descriptor a <code>SecurityException</code> is thrown.
190      * <p>
191      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
192      * is thrown.
193      * <p>
194      * This constructor does not throw an exception if <code>fdObj</code>
195      * is {@link java.io.FileDescriptor#valid() invalid}.
196      * However, if the methods are invoked on the resulting stream to attempt
197      * I/O on the stream, an <code>IOException</code> is thrown.
198      * <p>
199      * Android-specific warning: {@link #close()} method doesn't close the {@code fdObj} provided,
200      * because this object doesn't own the file descriptor, but the caller does. The caller can
201      * call {@link android.system.Os#close(FileDescriptor)} to close the fd.
202      *
203      * @param      fdObj   the file descriptor to be opened for reading.
204      */
FileInputStream(FileDescriptor fdObj)205     public FileInputStream(FileDescriptor fdObj) {
206         // Android-changed: Delegate to added hidden constructor.
207         this(fdObj, false /* isFdOwner */);
208     }
209 
210     // Android-added: Internal/hidden constructor for specifying FileDescriptor ownership.
211     // Android-removed: SecurityManager calls.
212     /** @hide */
FileInputStream(FileDescriptor fdObj, boolean isFdOwner)213     public FileInputStream(FileDescriptor fdObj, boolean isFdOwner) {
214         if (fdObj == null) {
215             // Android-changed: Improved NullPointerException message.
216             throw new NullPointerException("fdObj == null");
217         }
218         fd = fdObj;
219         path = null;
220 
221         // Android-changed: FileDescriptor ownership tracking mechanism.
222         /*
223         /*
224          * FileDescriptor is being shared by streams.
225          * Register this stream with FileDescriptor tracker.
226          *
227         fd.attach(this);
228         */
229         this.isFdOwner = isFdOwner;
230         if (isFdOwner) {
231             IoUtils.setFdOwner(this.fd, this);
232         }
233     }
234 
235     // BEGIN Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
236     // http://b/112107427
237     /*
238     /**
239      * Opens the specified file for reading.
240      * @param name the name of the file
241      *
242     private native void open0(String name) throws FileNotFoundException;
243 
244     // wrap native call to allow instrumentation
245     /**
246      * Opens the specified file for reading.
247      * @param name the name of the file
248      *
249     private void open(String name) throws FileNotFoundException {
250         open0(name);
251     }
252     */
253     // END Android-changed: Open files using IoBridge to share BlockGuard & StrictMode logic.
254 
255     /**
256      * Reads a byte of data from this input stream. This method blocks
257      * if no input is yet available.
258      *
259      * @return     the next byte of data, or <code>-1</code> if the end of the
260      *             file is reached.
261      * @exception  IOException  if an I/O error occurs.
262      */
read()263     public int read() throws IOException {
264         // Android-changed: Read methods delegate to read(byte[], int, int) to share Android logic.
265         byte[] b = new byte[1];
266         return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
267     }
268 
269     // Android-removed: Read methods delegate to read(byte[], int, int) to share Android logic.
270     // private native int read0() throws IOException;
271 
272     // Android-removed: Read methods delegate to read(byte[], int, int) to share Android logic.
273     /*
274     /**
275      * Reads a subarray as a sequence of bytes.
276      * @param b the data to be written
277      * @param off the start offset in the data
278      * @param len the number of bytes that are written
279      * @exception IOException If an I/O error has occurred.
280      *
281     private native int readBytes(byte b[], int off, int len) throws IOException;
282     */
283 
284     /**
285      * Reads up to <code>b.length</code> bytes of data from this input
286      * stream into an array of bytes. This method blocks until some input
287      * is available.
288      *
289      * @param      b   the buffer into which the data is read.
290      * @return     the total number of bytes read into the buffer, or
291      *             <code>-1</code> if there is no more data because the end of
292      *             the file has been reached.
293      * @exception  IOException  if an I/O error occurs.
294      */
read(byte b[])295     public int read(byte b[]) throws IOException {
296         // Android-changed: Read methods delegate to read(byte[], int, int) to share Android logic.
297         return read(b, 0, b.length);
298     }
299 
300     /**
301      * Reads up to <code>len</code> bytes of data from this input stream
302      * into an array of bytes. If <code>len</code> is not zero, the method
303      * blocks until some input is available; otherwise, no
304      * bytes are read and <code>0</code> is returned.
305      *
306      * @param      b     the buffer into which the data is read.
307      * @param      off   the start offset in the destination array <code>b</code>
308      * @param      len   the maximum number of bytes read.
309      * @return     the total number of bytes read into the buffer, or
310      *             <code>-1</code> if there is no more data because the end of
311      *             the file has been reached.
312      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
313      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
314      * <code>len</code> is negative, or <code>len</code> is greater than
315      * <code>b.length - off</code>
316      * @exception  IOException  if an I/O error occurs.
317      */
read(byte b[], int off, int len)318     public int read(byte b[], int off, int len) throws IOException {
319         // Android-added: close() check before I/O.
320         if (closed && len > 0) {
321             throw new IOException("Stream Closed");
322         }
323 
324         // Android-added: Tracking of unbuffered I/O.
325         tracker.trackIo(len, IoTracker.Mode.READ);
326 
327         // Android-changed: Use IoBridge instead of calling native method.
328         return IoBridge.read(fd, b, off, len);
329     }
330 
331     /**
332      * Skips over and discards <code>n</code> bytes of data from the
333      * input stream.
334      *
335      * <p>The <code>skip</code> method may, for a variety of
336      * reasons, end up skipping over some smaller number of bytes,
337      * possibly <code>0</code>. If <code>n</code> is negative, the method
338      * will try to skip backwards. In case the backing file does not support
339      * backward skip at its current position, an <code>IOException</code> is
340      * thrown. The actual number of bytes skipped is returned. If it skips
341      * forwards, it returns a positive value. If it skips backwards, it
342      * returns a negative value.
343      *
344      * <p>This method may skip more bytes than what are remaining in the
345      * backing file. This produces no exception and the number of bytes skipped
346      * may include some number of bytes that were beyond the EOF of the
347      * backing file. Attempting to read from the stream after skipping past
348      * the end will result in -1 indicating the end of the file.
349      *
350      * @param      n   the number of bytes to be skipped.
351      * @return     the actual number of bytes skipped.
352      * @exception  IOException  if n is negative, if the stream does not
353      *             support seek, or if an I/O error occurs.
354      */
355     // BEGIN Android-changed: skip(long) implementation changed from bare native.
skip(long n)356     public long skip(long n) throws IOException {
357         // Android-added: close() check before I/O.
358         if (closed) {
359             throw new IOException("Stream Closed");
360         }
361 
362         try {
363             // Android-added: BlockGuard support.
364             BlockGuard.getThreadPolicy().onReadFromDisk();
365             return skip0(n);
366         } catch(UseManualSkipException e) {
367             return super.skip(n);
368         }
369     }
370 
skip0(long n)371     private native long skip0(long n) throws IOException, UseManualSkipException;
372 
373     /*
374      * Used to force manual skip when FileInputStream operates on pipe
375      */
376     private static class UseManualSkipException extends Exception {
377     }
378     // END Android-changed: skip(long) implementation changed from bare native.
379 
380     /**
381      * Returns an estimate of the number of remaining bytes that can be read (or
382      * skipped over) from this input stream without blocking by the next
383      * invocation of a method for this input stream. Returns 0 when the file
384      * position is beyond EOF. The next invocation might be the same thread
385      * or another thread. A single read or skip of this many bytes will not
386      * block, but may read or skip fewer bytes.
387      *
388      * <p> In some cases, a non-blocking read (or skip) may appear to be
389      * blocked when it is merely slow, for example when reading large
390      * files over slow networks.
391      *
392      * @return     an estimate of the number of remaining bytes that can be read
393      *             (or skipped over) from this input stream without blocking.
394      * @exception  IOException  if this file input stream has been closed by calling
395      *             {@code close} or an I/O error occurs.
396      */
397     // BEGIN Android-changed: available() implementation changed from bare native.
available()398     public int available() throws IOException {
399         // Android-added: close() check before I/O.
400         if (closed) {
401             throw new IOException("Stream Closed");
402         }
403 
404         return available0();
405     }
406 
available0()407     private native int available0() throws IOException;
408     // END Android-changed: available() implementation changed from bare native.
409 
410     /**
411      * Closes this file input stream and releases any system resources
412      * associated with the stream.
413      *
414      * <p> If this stream has an associated channel then the channel is closed
415      * as well.
416      *
417      * @exception  IOException  if an I/O error occurs.
418      *
419      * @revised 1.4
420      * @spec JSR-51
421      */
close()422     public void close() throws IOException {
423         synchronized (closeLock) {
424             if (closed) {
425                 return;
426             }
427             closed = true;
428         }
429 
430         // Android-added: CloseGuard support.
431         guard.close();
432 
433         if (channel != null) {
434            channel.close();
435         }
436 
437         // BEGIN Android-changed: Close handling / notification of blocked threads.
438         if (isFdOwner) {
439             IoBridge.closeAndSignalBlockedThreads(fd);
440         }
441         // END Android-changed: Close handling / notification of blocked threads.
442     }
443 
444     /**
445      * Returns the <code>FileDescriptor</code>
446      * object  that represents the connection to
447      * the actual file in the file system being
448      * used by this <code>FileInputStream</code>.
449      *
450      * @return     the file descriptor object associated with this stream.
451      * @exception  IOException  if an I/O error occurs.
452      * @see        java.io.FileDescriptor
453      */
getFD()454     public final FileDescriptor getFD() throws IOException {
455         if (fd != null) {
456             return fd;
457         }
458         throw new IOException();
459     }
460 
461     /**
462      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
463      * object associated with this file input stream.
464      *
465      * <p> The initial {@link java.nio.channels.FileChannel#position()
466      * position} of the returned channel will be equal to the
467      * number of bytes read from the file so far.  Reading bytes from this
468      * stream will increment the channel's position.  Changing the channel's
469      * position, either explicitly or by reading, will change this stream's
470      * file position.
471      *
472      * @return  the file channel associated with this file input stream
473      *
474      * @since 1.4
475      * @spec JSR-51
476      */
getChannel()477     public FileChannel getChannel() {
478         synchronized (this) {
479             if (channel == null) {
480                 channel = FileChannelImpl.open(fd, path, true, false, this);
481             }
482             return channel;
483         }
484     }
485 
486     // BEGIN Android-removed: Unused code.
487     /*
488     private static native void initIDs();
489 
490     private native void close0() throws IOException;
491 
492     static {
493         initIDs();
494     }
495     */
496     // END Android-removed: Unused code.
497 
498     /**
499      * Ensures that the <code>close</code> method of this file input stream is
500      * called when there are no more references to it.
501      *
502      * @exception  IOException  if an I/O error occurs.
503      * @see        java.io.FileInputStream#close()
504      */
finalize()505     protected void finalize() throws IOException {
506         // Android-added: CloseGuard support.
507         if (guard != null) {
508             guard.warnIfOpen();
509         }
510 
511         if ((fd != null) &&  (fd != FileDescriptor.in)) {
512             // Android-removed: Obsoleted comment about shared FileDescriptor handling.
513             close();
514         }
515     }
516 }
517