1 /*
2 * Copyright (c) 2001, 2010, 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 #include "jni.h"
27 #include "jni_util.h"
28 #include "jvm.h"
29 #include "io_util.h"
30 #include "io_util_md.h"
31 #include <string.h>
32
33 // BEGIN Android-added: Fuchsia: Alias *64 functions on Fuchsia. http://b/119496969
34 #if defined(__Fuchsia__)
35 #define stat64 stat
36 #define fstat64 fstat
37 #define open64 open
38 #endif
39 // END Android-added: Fuchsia: Alias *64 functions on Fuchsia. http://b/119496969
40
41 #ifdef MACOSX
42
43 #include <CoreFoundation/CoreFoundation.h>
44
45 __private_extern__
newStringPlatform(JNIEnv * env,const char * str)46 jstring newStringPlatform(JNIEnv *env, const char* str)
47 {
48 jstring rv = NULL;
49 CFMutableStringRef csref = CFStringCreateMutable(NULL, 0);
50 if (csref == NULL) {
51 JNU_ThrowOutOfMemoryError(env, "native heap");
52 } else {
53 CFStringAppendCString(csref, str, kCFStringEncodingUTF8);
54 CFStringNormalize(csref, kCFStringNormalizationFormC);
55 int clen = CFStringGetLength(csref);
56 int ulen = (clen + 1) * 2; // utf16 + zero padding
57 char* chars = malloc(ulen);
58 if (chars == NULL) {
59 CFRelease(csref);
60 JNU_ThrowOutOfMemoryError(env, "native heap");
61 } else {
62 if (CFStringGetCString(csref, chars, ulen, kCFStringEncodingUTF16)) {
63 rv = (*env)->NewString(env, (jchar*)chars, clen);
64 }
65 free(chars);
66 CFRelease(csref);
67 }
68 }
69 return rv;
70 }
71 #endif
72
73 FD
handleOpen(const char * path,int oflag,int mode)74 handleOpen(const char *path, int oflag, int mode) {
75 FD fd;
76 RESTARTABLE(open64(path, oflag, mode), fd);
77 if (fd != -1) {
78 struct stat64 buf64;
79 int result;
80 RESTARTABLE(fstat64(fd, &buf64), result);
81 if (result != -1) {
82 if (S_ISDIR(buf64.st_mode)) {
83 close(fd);
84 errno = EISDIR;
85 fd = -1;
86 }
87 } else {
88 close(fd);
89 fd = -1;
90 }
91 }
92 return fd;
93 }
94
95
96 void
fileOpen(JNIEnv * env,jobject this,jstring path,jfieldID fid,int flags)97 fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
98 {
99 WITH_PLATFORM_STRING(env, path, ps) {
100 FD fd;
101
102 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
103 /* Remove trailing slashes, since the kernel won't */
104 char *p = (char *)ps + strlen(ps) - 1;
105 while ((p > ps) && (*p == '/'))
106 *p-- = '\0';
107 #endif
108 fd = handleOpen(ps, flags, 0666);
109 if (fd != -1) {
110 SET_FD(this, fd, fid);
111 } else {
112 throwFileNotFoundException(env, path);
113 }
114 } END_PLATFORM_STRING(env, ps);
115 }
116
117
118 void
fileClose(JNIEnv * env,jobject this,jfieldID fid)119 fileClose(JNIEnv *env, jobject this, jfieldID fid)
120 {
121 FD fd = GET_FD(this, fid);
122 if (fd == -1) {
123 return;
124 }
125
126 /* Set the fd to -1 before closing it so that the timing window
127 * of other threads using the wrong fd (closed but recycled fd,
128 * that gets re-opened with some other filename) is reduced.
129 * Practically the chance of its occurance is low, however, we are
130 * taking extra precaution over here.
131 */
132 SET_FD(this, -1, fid);
133
134 /*
135 * Don't close file descriptors 0, 1, or 2. If we close these stream
136 * then a subsequent file open or socket will use them. Instead we
137 * just redirect these file descriptors to /dev/null.
138 */
139 if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {
140 int devnull = open("/dev/null", O_WRONLY);
141 if (devnull < 0) {
142 SET_FD(this, fd, fid); // restore fd
143 JNU_ThrowIOExceptionWithLastError(env, "open /dev/null failed");
144 } else {
145 dup2(devnull, fd);
146 close(devnull);
147 }
148 } else if (JVM_Close(fd) == -1) {
149 JNU_ThrowIOExceptionWithLastError(env, "close failed");
150 }
151 }
152