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 java.nio.channels.FileChannel;
30 
31 import dalvik.system.BlockGuard;
32 import dalvik.system.CloseGuard;
33 import sun.nio.ch.FileChannelImpl;
34 import libcore.io.IoBridge;
35 import libcore.io.IoTracker;
36 
37 
38 /**
39  * A <code>FileInputStream</code> obtains input bytes
40  * from a file in a file system. What files
41  * are  available depends on the host environment.
42  *
43  * <p><code>FileInputStream</code> is meant for reading streams of raw bytes
44  * such as image data. For reading streams of characters, consider using
45  * <code>FileReader</code>.
46  *
47  * @author  Arthur van Hoff
48  * @see     java.io.File
49  * @see     java.io.FileDescriptor
50  * @see     java.io.FileOutputStream
51  * @see     java.nio.file.Files#newInputStream
52  * @since   JDK1.0
53  */
54 public
55 class FileInputStream extends InputStream
56 {
57     /* File Descriptor - handle to the open file */
58     private final FileDescriptor fd;
59 
60     /**
61      * The path of the referenced file
62      * (null if the stream is created with a file descriptor)
63      */
64     private final String path;
65 
66     private FileChannel channel = null;
67 
68     private final Object closeLock = new Object();
69     private volatile boolean closed = false;
70     private final boolean isFdOwner;
71 
72     private final CloseGuard guard = CloseGuard.get();
73     private final IoTracker tracker = new IoTracker();
74 
75     /**
76      * Creates a <code>FileInputStream</code> by
77      * opening a connection to an actual file,
78      * the file named by the path name <code>name</code>
79      * in the file system.  A new <code>FileDescriptor</code>
80      * object is created to represent this file
81      * connection.
82      * <p>
83      * First, if there is a security
84      * manager, its <code>checkRead</code> method
85      * is called with the <code>name</code> argument
86      * as its argument.
87      * <p>
88      * If the named file does not exist, is a directory rather than a regular
89      * file, or for some other reason cannot be opened for reading then a
90      * <code>FileNotFoundException</code> is thrown.
91      *
92      * @param      name   the system-dependent file name.
93      * @exception  FileNotFoundException  if the file does not exist,
94      *                   is a directory rather than a regular file,
95      *                   or for some other reason cannot be opened for
96      *                   reading.
97      * @exception  SecurityException      if a security manager exists and its
98      *               <code>checkRead</code> method denies read access
99      *               to the file.
100      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
101      */
FileInputStream(String name)102     public FileInputStream(String name) throws FileNotFoundException {
103         this(name != null ? new File(name) : null);
104     }
105 
106     /**
107      * Creates a <code>FileInputStream</code> by
108      * opening a connection to an actual file,
109      * the file named by the <code>File</code>
110      * object <code>file</code> in the file system.
111      * A new <code>FileDescriptor</code> object
112      * is created to represent this file connection.
113      * <p>
114      * First, if there is a security manager,
115      * its <code>checkRead</code> method  is called
116      * with the path represented by the <code>file</code>
117      * argument as its argument.
118      * <p>
119      * If the named file does not exist, is a directory rather than a regular
120      * file, or for some other reason cannot be opened for reading then a
121      * <code>FileNotFoundException</code> is thrown.
122      *
123      * @param      file   the file to be opened for reading.
124      * @exception  FileNotFoundException  if the file does not exist,
125      *                   is a directory rather than a regular file,
126      *                   or for some other reason cannot be opened for
127      *                   reading.
128      * @exception  SecurityException      if a security manager exists and its
129      *               <code>checkRead</code> method denies read access to the file.
130      * @see        java.io.File#getPath()
131      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
132      */
FileInputStream(File file)133     public FileInputStream(File file) throws FileNotFoundException {
134         String name = (file != null ? file.getPath() : null);
135         SecurityManager security = System.getSecurityManager();
136         if (security != null) {
137             security.checkRead(name);
138         }
139         if (name == null) {
140             throw new NullPointerException();
141         }
142         if (file.isInvalid()) {
143             throw new FileNotFoundException("Invalid file path");
144         }
145         fd = new FileDescriptor();
146         isFdOwner = true;
147         this.path = name;
148 
149         BlockGuard.getThreadPolicy().onReadFromDisk();
150         open(name);
151         guard.open("close");
152     }
153 
154     /**
155      * Creates a <code>FileInputStream</code> by using the file descriptor
156      * <code>fdObj</code>, which represents an existing connection to an
157      * actual file in the file system.
158      * <p>
159      * If there is a security manager, its <code>checkRead</code> method is
160      * called with the file descriptor <code>fdObj</code> as its argument to
161      * see if it's ok to read the file descriptor. If read access is denied
162      * to the file descriptor a <code>SecurityException</code> is thrown.
163      * <p>
164      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
165      * is thrown.
166      * <p>
167      * This constructor does not throw an exception if <code>fdObj</code>
168      * is {@link java.io.FileDescriptor#valid() invalid}.
169      * However, if the methods are invoked on the resulting stream to attempt
170      * I/O on the stream, an <code>IOException</code> is thrown.
171      *
172      * @param      fdObj   the file descriptor to be opened for reading.
173      */
FileInputStream(FileDescriptor fdObj)174     public FileInputStream(FileDescriptor fdObj) {
175         this(fdObj, false /* isFdOwner */);
176     }
177 
178     /** @hide */
FileInputStream(FileDescriptor fdObj, boolean isFdOwner)179     public FileInputStream(FileDescriptor fdObj, boolean isFdOwner) {
180         if (fdObj == null) {
181             throw new NullPointerException("fdObj == null");
182         }
183         fd = fdObj;
184         this.isFdOwner = isFdOwner;
185         path = null;
186     }
187 
188     /**
189      * Opens the specified file for reading.
190      * @param name the name of the file
191      */
open0(String name)192     private native void open0(String name) throws FileNotFoundException;
193 
194     // wrap native call to allow instrumentation
195     /**
196      * Opens the specified file for reading.
197      * @param name the name of the file
198      */
open(String name)199     private void open(String name) throws FileNotFoundException {
200         open0(name);
201     }
202 
203     /**
204      * Reads a byte of data from this input stream. This method blocks
205      * if no input is yet available.
206      *
207      * @return     the next byte of data, or <code>-1</code> if the end of the
208      *             file is reached.
209      * @exception  IOException  if an I/O error occurs.
210      */
read()211     public int read() throws IOException {
212         byte[] b = new byte[1];
213         return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
214     }
215 
216     /**
217      * Reads up to <code>b.length</code> bytes of data from this input
218      * stream into an array of bytes. This method blocks until some input
219      * is available.
220      *
221      * @param      b   the buffer into which the data is read.
222      * @return     the total number of bytes read into the buffer, or
223      *             <code>-1</code> if there is no more data because the end of
224      *             the file has been reached.
225      * @exception  IOException  if an I/O error occurs.
226      */
read(byte b[])227     public int read(byte b[]) throws IOException {
228         return read(b, 0, b.length);
229     }
230 
231     /**
232      * Reads up to <code>len</code> bytes of data from this input stream
233      * into an array of bytes. If <code>len</code> is not zero, the method
234      * blocks until some input is available; otherwise, no
235      * bytes are read and <code>0</code> is returned.
236      *
237      * @param      b     the buffer into which the data is read.
238      * @param      off   the start offset in the destination array <code>b</code>
239      * @param      len   the maximum number of bytes read.
240      * @return     the total number of bytes read into the buffer, or
241      *             <code>-1</code> if there is no more data because the end of
242      *             the file has been reached.
243      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
244      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
245      * <code>len</code> is negative, or <code>len</code> is greater than
246      * <code>b.length - off</code>
247      * @exception  IOException  if an I/O error occurs.
248      */
read(byte b[], int off, int len)249     public int read(byte b[], int off, int len) throws IOException {
250         if (closed && len > 0) {
251             throw new IOException("Stream Closed");
252         }
253         tracker.trackIo(len);
254         return IoBridge.read(fd, b, off, len);
255     }
256 
257     /**
258      * Skips over and discards <code>n</code> bytes of data from the
259      * input stream.
260      *
261      * <p>The <code>skip</code> method may, for a variety of
262      * reasons, end up skipping over some smaller number of bytes,
263      * possibly <code>0</code>. If <code>n</code> is negative, the method
264      * will try to skip backwards. In case the backing file does not support
265      * backward skip at its current position, an <code>IOException</code> is
266      * thrown. The actual number of bytes skipped is returned. If it skips
267      * forwards, it returns a positive value. If it skips backwards, it
268      * returns a negative value.
269      *
270      * <p>This method may skip more bytes than what are remaining in the
271      * backing file. This produces no exception and the number of bytes skipped
272      * may include some number of bytes that were beyond the EOF of the
273      * backing file. Attempting to read from the stream after skipping past
274      * the end will result in -1 indicating the end of the file.
275      *
276      * @param      n   the number of bytes to be skipped.
277      * @return     the actual number of bytes skipped.
278      * @exception  IOException  if n is negative, if the stream does not
279      *             support seek, or if an I/O error occurs.
280      */
skip(long n)281     public long skip(long n) throws IOException {
282         if (closed) {
283             throw new IOException("Stream Closed");
284         }
285 
286         try {
287             BlockGuard.getThreadPolicy().onReadFromDisk();
288             return skip0(n);
289         } catch(UseManualSkipException e) {
290             return super.skip(n);
291         }
292     }
293 
skip0(long n)294     private native long skip0(long n) throws IOException, UseManualSkipException;
295 
296     /*
297      * Used to force manual skip when FileInputStream operates on pipe
298      */
299     private static class UseManualSkipException extends Exception {
300     }
301 
302     /**
303      * Returns an estimate of the number of remaining bytes that can be read (or
304      * skipped over) from this input stream without blocking by the next
305      * invocation of a method for this input stream. Returns 0 when the file
306      * position is beyond EOF. The next invocation might be the same thread
307      * or another thread. A single read or skip of this many bytes will not
308      * block, but may read or skip fewer bytes.
309      *
310      * <p> In some cases, a non-blocking read (or skip) may appear to be
311      * blocked when it is merely slow, for example when reading large
312      * files over slow networks.
313      *
314      * @return     an estimate of the number of remaining bytes that can be read
315      *             (or skipped over) from this input stream without blocking.
316      * @exception  IOException  if this file input stream has been closed by calling
317      *             {@code close} or an I/O error occurs.
318      */
available()319     public int available() throws IOException {
320         if (closed) {
321             throw new IOException("Stream Closed");
322         }
323 
324         return available0();
325     }
326 
available0()327     private native int available0() throws IOException;
328 
329     /**
330      * Closes this file input stream and releases any system resources
331      * associated with the stream.
332      *
333      * <p> If this stream has an associated channel then the channel is closed
334      * as well.
335      *
336      * @exception  IOException  if an I/O error occurs.
337      *
338      * @revised 1.4
339      * @spec JSR-51
340      */
close()341     public void close() throws IOException {
342         synchronized (closeLock) {
343             if (closed) {
344                 return;
345             }
346             closed = true;
347         }
348 
349         guard.close();
350 
351         if (channel != null) {
352             /*
353              * Decrement the FD use count associated with the channel
354              * The use count is incremented whenever a new channel
355              * is obtained from this stream.
356              */
357            channel.close();
358         }
359 
360         if (isFdOwner) {
361             IoBridge.closeAndSignalBlockedThreads(fd);
362         }
363     }
364 
365     /**
366      * Returns the <code>FileDescriptor</code>
367      * object  that represents the connection to
368      * the actual file in the file system being
369      * used by this <code>FileInputStream</code>.
370      *
371      * @return     the file descriptor object associated with this stream.
372      * @exception  IOException  if an I/O error occurs.
373      * @see        java.io.FileDescriptor
374      */
getFD()375     public final FileDescriptor getFD() throws IOException {
376         if (fd != null) {
377             return fd;
378         }
379         throw new IOException();
380     }
381 
382     /**
383      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
384      * object associated with this file input stream.
385      *
386      * <p> The initial {@link java.nio.channels.FileChannel#position()
387      * position} of the returned channel will be equal to the
388      * number of bytes read from the file so far.  Reading bytes from this
389      * stream will increment the channel's position.  Changing the channel's
390      * position, either explicitly or by reading, will change this stream's
391      * file position.
392      *
393      * @return  the file channel associated with this file input stream
394      *
395      * @since 1.4
396      * @spec JSR-51
397      */
getChannel()398     public FileChannel getChannel() {
399         synchronized (this) {
400             if (channel == null) {
401                 channel = FileChannelImpl.open(fd, path, true, false, this);
402 
403             }
404             return channel;
405         }
406     }
407 
408     /**
409      * Ensures that the <code>close</code> method of this file input stream is
410      * called when there are no more references to it.
411      *
412      * @exception  IOException  if an I/O error occurs.
413      * @see        java.io.FileInputStream#close()
414      */
finalize()415     protected void finalize() throws IOException {
416         if (guard != null) {
417             guard.warnIfOpen();
418         }
419 
420         if ((fd != null) &&  (fd != FileDescriptor.in)) {
421             close();
422         }
423     }
424 }
425