1 /*
2  * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.io;
27 
28 import android.system.ErrnoException;
29 import android.system.Os;
30 import android.system.OsConstants;
31 
32 import static android.system.OsConstants.F_DUPFD_CLOEXEC;
33 
34 import dalvik.annotation.optimization.CriticalNative;
35 
36 import libcore.io.Libcore;
37 
38 import java.util.concurrent.atomic.AtomicInteger;
39 
40 /**
41  * Instances of the file descriptor class serve as an opaque handle
42  * to the underlying machine-specific structure representing an open
43  * file, an open socket, or another source or sink of bytes. The
44  * main practical use for a file descriptor is to create a
45  * <code>FileInputStream</code> or <code>FileOutputStream</code> to
46  * contain it.
47  * <p>
48  * Applications should not create their own file descriptors.
49  *
50  * @author  Pavani Diwanji
51  * @see     java.io.FileInputStream
52  * @see     java.io.FileOutputStream
53  * @since   JDK1.0
54  */
55 public final class FileDescriptor {
56     // Android-changed: Removed parent reference counting.
57     // The creator is responsible for closing the file descriptor.
58 
59     // Android-changed: Renamed fd to descriptor.
60     // Renaming is to avoid issues with JNI/reflection fetching the descriptor value.
61     private int descriptor;
62 
63     // Android-added: Track fd owner to guard against accidental closure. http://b/110100358
64     // The owner on the libc side is an pointer-sized value that can be set to an arbitrary
65     // value (with 0 meaning 'unowned'). libcore chooses to use System.identityHashCode.
66     private long ownerId = NO_OWNER;
67 
68     /**
69      * true, if file is opened for appending.
70      */
71     private boolean append;
72 
73     // Android-added: value of ownerId indicating that a FileDescriptor is unowned.
74     /** @hide */
75     public static final long NO_OWNER = 0L;
76 
77     // Android-added: lock for release$.
78     private final Object releaseLock = new Object();
79 
80     /**
81      * Constructs an (invalid) FileDescriptor
82      * object.
83      */
FileDescriptor()84     public /**/ FileDescriptor() {
85         descriptor = -1;
86     }
87 
FileDescriptor(int fd)88     private /* */ FileDescriptor(int fd) {
89         this.descriptor = fd;
90         this.append = getAppend(fd);
91     }
92 
93     /**
94      * A handle to the standard input stream. Usually, this file
95      * descriptor is not used directly, but rather via the input stream
96      * known as <code>System.in</code>.
97      *
98      * @see     java.lang.System#in
99      */
100     public static final FileDescriptor in = new FileDescriptor(0);
101 
102     /**
103      * A handle to the standard output stream. Usually, this file
104      * descriptor is not used directly, but rather via the output stream
105      * known as <code>System.out</code>.
106      * @see     java.lang.System#out
107      */
108     public static final FileDescriptor out = new FileDescriptor(1);
109 
110     /**
111      * A handle to the standard error stream. Usually, this file
112      * descriptor is not used directly, but rather via the output stream
113      * known as <code>System.err</code>.
114      *
115      * @see     java.lang.System#err
116      */
117     public static final FileDescriptor err = new FileDescriptor(2);
118 
119     /**
120      * Tests if this file descriptor object is valid.
121      *
122      * @return  <code>true</code> if the file descriptor object represents a
123      *          valid, open file, socket, or other active I/O connection;
124      *          <code>false</code> otherwise.
125      */
valid()126     public boolean valid() {
127         return descriptor != -1;
128     }
129 
130     /**
131      * Force all system buffers to synchronize with the underlying
132      * device.  This method returns after all modified data and
133      * attributes of this FileDescriptor have been written to the
134      * relevant device(s).  In particular, if this FileDescriptor
135      * refers to a physical storage medium, such as a file in a file
136      * system, sync will not return until all in-memory modified copies
137      * of buffers associated with this FileDescriptor have been
138      * written to the physical medium.
139      *
140      * sync is meant to be used by code that requires physical
141      * storage (such as a file) to be in a known state  For
142      * example, a class that provided a simple transaction facility
143      * might use sync to ensure that all changes to a file caused
144      * by a given transaction were recorded on a storage medium.
145      *
146      * sync only affects buffers downstream of this FileDescriptor.  If
147      * any in-memory buffering is being done by the application (for
148      * example, by a BufferedOutputStream object), those buffers must
149      * be flushed into the FileDescriptor (for example, by invoking
150      * OutputStream.flush) before that data will be affected by sync.
151      *
152      * @exception SyncFailedException
153      *        Thrown when the buffers cannot be flushed,
154      *        or because the system cannot guarantee that all the
155      *        buffers have been synchronized with physical media.
156      * @since     JDK1.1
157      */
sync()158     public native void sync() throws SyncFailedException;
159 
160     // Android-removed: initIDs not used to allow compile-time initialization.
161     /* This routine initializes JNI field offsets for the class */
162     //private static native void initIDs();
163 
164     /**
165      * Returns true, if the file was opened for appending.
166      */
167     @CriticalNative
getAppend(int fd)168     private static native boolean getAppend(int fd);
169 
170     // Android-added: Needed for framework to access descriptor value.
171     /**
172      * Returns the int descriptor. It's highly unlikely you should be calling this. Please discuss
173      * your needs with a libcore maintainer before using this method.
174      * @hide internal use only
175      */
getInt$()176     public final int getInt$() {
177         return descriptor;
178     }
179 
180     // Android-added: Needed for framework to access descriptor value.
181     /**
182      * Sets the int descriptor. It's highly unlikely you should be calling this. Please discuss
183      * your needs with a libcore maintainer before using this method.
184      *
185      * @hide This method is @SystemApi(MODULE_LIBRARIES) and used by AFileDescriptor_setFd.
186      */
setInt$(int fd)187     public final void setInt$(int fd) {
188         this.descriptor = fd;
189         if (fd != -1) {
190             this.append = getAppend(fd);
191         }
192     }
193 
194     // BEGIN Android-added: Method to clone standard file descriptors.
195     // Required as a consequence of RuntimeInit#redirectLogStreams. Cloning is used in
196     // ZygoteHooks.onEndPreload().
197     /**
198      * Clones the current native file descriptor and uses this for this FileDescriptor instance.
199      *
200      * This method does not close the current native file descriptor.
201      *
202      * @hide internal use only
203      */
cloneForFork()204     public void cloneForFork() {
205         try {
206             int newDescriptor = Os.fcntlInt(this, F_DUPFD_CLOEXEC, 0);
207             setInt$(newDescriptor);
208         } catch (ErrnoException e) {
209             throw new RuntimeException(e);
210         }
211     }
212     // END Android-added: Method to clone standard file descriptors.
213 
214     // BEGIN Android-added: Methods to enable ownership enforcement of Unix file descriptors.
215     /**
216      * Returns the owner ID of this FileDescriptor. It's highly unlikely you should be calling this.
217      * Please discuss your needs with a libcore maintainer before using this method.
218      * @hide internal use only
219      */
getOwnerId$()220     public long getOwnerId$() {
221         return this.ownerId;
222     }
223 
224     /**
225      * Sets the owner ID of this FileDescriptor. The owner ID does not need to be unique, but it is
226      * assumed that clashes are rare. See bionic/include/android/fdsan.h for more details.
227      *
228      * It's highly unlikely you should be calling this.
229      * Please discuss your needs with a libcore maintainer before using this method.
230      * @param newOwnerId the owner ID of the Object that is responsible for closing this FileDescriptor
231      * @hide internal use only
232      */
setOwnerId$(long newOwnerId)233     public void setOwnerId$(long newOwnerId) {
234         this.ownerId = newOwnerId;
235     }
236 
237     /**
238      * Returns a copy of this FileDescriptor, and sets this to an invalid state.
239      *
240      * The returned instance is not necessarily {@code valid()}, if the original FileDescriptor
241      * was invalid, or if another thread concurrently calls {@code release$()}.
242      *
243      * @hide internal use only
244      */
release$()245     public FileDescriptor release$() {
246       FileDescriptor result = new FileDescriptor();
247       synchronized (releaseLock) {
248           result.descriptor = this.descriptor;
249           result.ownerId = this.ownerId;
250           this.descriptor = -1;
251           this.ownerId = FileDescriptor.NO_OWNER;
252       }
253 
254       return result;
255     }
256     // END Android-added: Methods to enable ownership enforcement of Unix file descriptors.
257 
258     // Android-added: Needed for framework to test if it's a socket.
259     /**
260      * @hide internal use only
261      */
isSocket$()262     public boolean isSocket$() {
263         return isSocket(descriptor);
264     }
265 
266     @CriticalNative
isSocket(int descriptor)267     private static native boolean isSocket(int descriptor);
268     // Set up JavaIOFileDescriptorAccess in SharedSecrets
269     static {
jdk.internal.access.SharedSecrets.setJavaIOFileDescriptorAccess( new jdk.internal.access.JavaIOFileDescriptorAccess() { public void set(FileDescriptor obj, int fd) { obj.descriptor = fd; } public int get(FileDescriptor obj) { return obj.descriptor; } @Override public boolean getAppend(FileDescriptor fdo) { return fdo.append; } public void setHandle(FileDescriptor obj, long handle) { throw new UnsupportedOperationException(); } public long getHandle(FileDescriptor obj) { throw new UnsupportedOperationException(); } } )270         jdk.internal.access.SharedSecrets.setJavaIOFileDescriptorAccess(
271             new jdk.internal.access.JavaIOFileDescriptorAccess() {
272                 public void set(FileDescriptor obj, int fd) {
273                     obj.descriptor = fd;
274                 }
275 
276                 public int get(FileDescriptor obj) {
277                     return obj.descriptor;
278                 }
279 
280                 @Override
281                 public boolean getAppend(FileDescriptor fdo) {
282                     return fdo.append;
283                 }
284 
285                 public void setHandle(FileDescriptor obj, long handle) {
286                     throw new UnsupportedOperationException();
287                 }
288 
289                 public long getHandle(FileDescriptor obj) {
290                     throw new UnsupportedOperationException();
291                 }
292             }
293         );
294     }
295 // Android-removed: Removed method required for parents reference counting.
296 }
297