• 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         // Android-changed: Open files through common bridge code.
158         // fd = new FileDescriptor();
159         fd = IoBridge.open(name, O_RDONLY);
160 
161         // Android-changed: Tracking mechanism for FileDescriptor sharing.
162         // fd.attach(this);
163         isFdOwner = true;
164 
165         path = name;
166 
167         // Android-removed: Open files through common bridge code.
168         // open(name);
169 
170         // Android-added: File descriptor ownership tracking.
171         IoUtils.setFdOwner(this.fd, this);
172 
173         // Android-added: CloseGuard support.
174         guard.open("close");
175     }
176 
177     // Android-removed: Documentation around SecurityException. Not thrown on Android.
178     /**
179      * Creates a <code>FileInputStream</code> by using the file descriptor
180      * <code>fdObj</code>, which represents an existing connection to an
181      * actual file in the file system.
182      * <p>
183      * If there is a security manager, its <code>checkRead</code> method is
184      * called with the file descriptor <code>fdObj</code> as its argument to
185      * see if it's ok to read the file descriptor. If read access is denied
186      * to the file descriptor a <code>SecurityException</code> is thrown.
187      * <p>
188      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
189      * is thrown.
190      * <p>
191      * This constructor does not throw an exception if <code>fdObj</code>
192      * is {@link java.io.FileDescriptor#valid() invalid}.
193      * However, if the methods are invoked on the resulting stream to attempt
194      * I/O on the stream, an <code>IOException</code> is thrown.
195      *
196      * @param      fdObj   the file descriptor to be opened for reading.
197      */
FileInputStream(FileDescriptor fdObj)198     public FileInputStream(FileDescriptor fdObj) {
199         // Android-changed: Delegate to added hidden constructor.
200         this(fdObj, false /* isFdOwner */);
201     }
202 
203     // Android-added: Internal/hidden constructor for specifying FileDescriptor ownership.
204     // Android-removed: SecurityManager calls.
205     /** @hide */
FileInputStream(FileDescriptor fdObj, boolean isFdOwner)206     public FileInputStream(FileDescriptor fdObj, boolean isFdOwner) {
207         if (fdObj == null) {
208             // Android-changed: Improved NullPointerException message.
209             throw new NullPointerException("fdObj == null");
210         }
211         fd = fdObj;
212         path = null;
213 
214         // Android-changed: FileDescriptor ownership tracking mechanism.
215         /*
216         /*
217          * FileDescriptor is being shared by streams.
218          * Register this stream with FileDescriptor tracker.
219          *
220         fd.attach(this);
221         */
222         this.isFdOwner = isFdOwner;
223     }
224 
225     /**
226      * Opens the specified file for reading.
227      * @param name the name of the file
228      */
open0(String name)229     private native void open0(String name) throws FileNotFoundException;
230 
231     // wrap native call to allow instrumentation
232     /**
233      * Opens the specified file for reading.
234      * @param name the name of the file
235      */
open(String name)236     private void open(String name) throws FileNotFoundException {
237         open0(name);
238     }
239 
240     /**
241      * Reads a byte of data from this input stream. This method blocks
242      * if no input is yet available.
243      *
244      * @return     the next byte of data, or <code>-1</code> if the end of the
245      *             file is reached.
246      * @exception  IOException  if an I/O error occurs.
247      */
read()248     public int read() throws IOException {
249         // Android-changed: Read methods delegate to read(byte[], int, int) to share Android logic.
250         byte[] b = new byte[1];
251         return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
252     }
253 
254     // Android-removed: Read methods delegate to read(byte[], int, int) to share Android logic.
255     // private native int read0() throws IOException;
256 
257     // Android-removed: Read methods delegate to read(byte[], int, int) to share Android logic.
258     /*
259     /**
260      * Reads a subarray as a sequence of bytes.
261      * @param b the data to be written
262      * @param off the start offset in the data
263      * @param len the number of bytes that are written
264      * @exception IOException If an I/O error has occurred.
265      *
266     private native int readBytes(byte b[], int off, int len) throws IOException;
267     */
268 
269     /**
270      * Reads up to <code>b.length</code> bytes of data from this input
271      * stream into an array of bytes. This method blocks until some input
272      * is available.
273      *
274      * @param      b   the buffer into which the data is read.
275      * @return     the total number of bytes read into the buffer, or
276      *             <code>-1</code> if there is no more data because the end of
277      *             the file has been reached.
278      * @exception  IOException  if an I/O error occurs.
279      */
read(byte b[])280     public int read(byte b[]) throws IOException {
281         // Android-changed: Read methods delegate to read(byte[], int, int) to share Android logic.
282         return read(b, 0, b.length);
283     }
284 
285     /**
286      * Reads up to <code>len</code> bytes of data from this input stream
287      * into an array of bytes. If <code>len</code> is not zero, the method
288      * blocks until some input is available; otherwise, no
289      * bytes are read and <code>0</code> is returned.
290      *
291      * @param      b     the buffer into which the data is read.
292      * @param      off   the start offset in the destination array <code>b</code>
293      * @param      len   the maximum number of bytes read.
294      * @return     the total number of bytes read into the buffer, or
295      *             <code>-1</code> if there is no more data because the end of
296      *             the file has been reached.
297      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
298      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
299      * <code>len</code> is negative, or <code>len</code> is greater than
300      * <code>b.length - off</code>
301      * @exception  IOException  if an I/O error occurs.
302      */
read(byte b[], int off, int len)303     public int read(byte b[], int off, int len) throws IOException {
304         // Android-added: close() check before I/O.
305         if (closed && len > 0) {
306             throw new IOException("Stream Closed");
307         }
308 
309         // Android-added: Tracking of unbuffered I/O.
310         tracker.trackIo(len);
311 
312         // Android-changed: Use IoBridge instead of calling native method.
313         return IoBridge.read(fd, b, off, len);
314     }
315 
316     /**
317      * Skips over and discards <code>n</code> bytes of data from the
318      * input stream.
319      *
320      * <p>The <code>skip</code> method may, for a variety of
321      * reasons, end up skipping over some smaller number of bytes,
322      * possibly <code>0</code>. If <code>n</code> is negative, the method
323      * will try to skip backwards. In case the backing file does not support
324      * backward skip at its current position, an <code>IOException</code> is
325      * thrown. The actual number of bytes skipped is returned. If it skips
326      * forwards, it returns a positive value. If it skips backwards, it
327      * returns a negative value.
328      *
329      * <p>This method may skip more bytes than what are remaining in the
330      * backing file. This produces no exception and the number of bytes skipped
331      * may include some number of bytes that were beyond the EOF of the
332      * backing file. Attempting to read from the stream after skipping past
333      * the end will result in -1 indicating the end of the file.
334      *
335      * @param      n   the number of bytes to be skipped.
336      * @return     the actual number of bytes skipped.
337      * @exception  IOException  if n is negative, if the stream does not
338      *             support seek, or if an I/O error occurs.
339      */
340     // BEGIN Android-changed: skip(long) implementation changed from bare native.
skip(long n)341     public long skip(long n) throws IOException {
342         // Android-added: close() check before I/O.
343         if (closed) {
344             throw new IOException("Stream Closed");
345         }
346 
347         try {
348             // Android-added: BlockGuard support.
349             BlockGuard.getThreadPolicy().onReadFromDisk();
350             return skip0(n);
351         } catch(UseManualSkipException e) {
352             return super.skip(n);
353         }
354     }
355 
skip0(long n)356     private native long skip0(long n) throws IOException, UseManualSkipException;
357 
358     /*
359      * Used to force manual skip when FileInputStream operates on pipe
360      */
361     private static class UseManualSkipException extends Exception {
362     }
363     // END Android-changed: skip(long) implementation changed from bare native.
364 
365     /**
366      * Returns an estimate of the number of remaining bytes that can be read (or
367      * skipped over) from this input stream without blocking by the next
368      * invocation of a method for this input stream. Returns 0 when the file
369      * position is beyond EOF. The next invocation might be the same thread
370      * or another thread. A single read or skip of this many bytes will not
371      * block, but may read or skip fewer bytes.
372      *
373      * <p> In some cases, a non-blocking read (or skip) may appear to be
374      * blocked when it is merely slow, for example when reading large
375      * files over slow networks.
376      *
377      * @return     an estimate of the number of remaining bytes that can be read
378      *             (or skipped over) from this input stream without blocking.
379      * @exception  IOException  if this file input stream has been closed by calling
380      *             {@code close} or an I/O error occurs.
381      */
382     // BEGIN Android-changed: available() implementation changed from bare native.
available()383     public int available() throws IOException {
384         // Android-added: close() check before I/O.
385         if (closed) {
386             throw new IOException("Stream Closed");
387         }
388 
389         return available0();
390     }
391 
available0()392     private native int available0() throws IOException;
393     // END Android-changed: available() implementation changed from bare native.
394 
395     /**
396      * Closes this file input stream and releases any system resources
397      * associated with the stream.
398      *
399      * <p> If this stream has an associated channel then the channel is closed
400      * as well.
401      *
402      * @exception  IOException  if an I/O error occurs.
403      *
404      * @revised 1.4
405      * @spec JSR-51
406      */
close()407     public void close() throws IOException {
408         synchronized (closeLock) {
409             if (closed) {
410                 return;
411             }
412             closed = true;
413         }
414 
415         // Android-added: CloseGuard support.
416         guard.close();
417 
418         if (channel != null) {
419            channel.close();
420         }
421 
422         // BEGIN Android-changed: Close handling / notification of blocked threads.
423         if (isFdOwner) {
424             IoBridge.closeAndSignalBlockedThreads(fd);
425         }
426         // END Android-changed: Close handling / notification of blocked threads.
427     }
428 
429     /**
430      * Returns the <code>FileDescriptor</code>
431      * object  that represents the connection to
432      * the actual file in the file system being
433      * used by this <code>FileInputStream</code>.
434      *
435      * @return     the file descriptor object associated with this stream.
436      * @exception  IOException  if an I/O error occurs.
437      * @see        java.io.FileDescriptor
438      */
getFD()439     public final FileDescriptor getFD() throws IOException {
440         if (fd != null) {
441             return fd;
442         }
443         throw new IOException();
444     }
445 
446     /**
447      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
448      * object associated with this file input stream.
449      *
450      * <p> The initial {@link java.nio.channels.FileChannel#position()
451      * position} of the returned channel will be equal to the
452      * number of bytes read from the file so far.  Reading bytes from this
453      * stream will increment the channel's position.  Changing the channel's
454      * position, either explicitly or by reading, will change this stream's
455      * file position.
456      *
457      * @return  the file channel associated with this file input stream
458      *
459      * @since 1.4
460      * @spec JSR-51
461      */
getChannel()462     public FileChannel getChannel() {
463         synchronized (this) {
464             if (channel == null) {
465                 channel = FileChannelImpl.open(fd, path, true, false, this);
466             }
467             return channel;
468         }
469     }
470 
471     // BEGIN Android-removed: Unused code.
472     /*
473     private static native void initIDs();
474 
475     private native void close0() throws IOException;
476 
477     static {
478         initIDs();
479     }
480     */
481     // END Android-removed: Unused code.
482 
483     /**
484      * Ensures that the <code>close</code> method of this file input stream is
485      * called when there are no more references to it.
486      *
487      * @exception  IOException  if an I/O error occurs.
488      * @see        java.io.FileInputStream#close()
489      */
finalize()490     protected void finalize() throws IOException {
491         // Android-added: CloseGuard support.
492         if (guard != null) {
493             guard.warnIfOpen();
494         }
495 
496         if ((fd != null) &&  (fd != FileDescriptor.in)) {
497             // Android-removed: Obsoleted comment about shared FileDescriptor handling.
498             close();
499         }
500     }
501 }
502