Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libjava/io_util_md.c
41119 views
1
/*
2
* Copyright (c) 2001, 2021, 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
#include "jni.h"
26
#include "jni_util.h"
27
#include "jvm.h"
28
#include "io_util.h"
29
#include "io_util_md.h"
30
#include <string.h>
31
#include <unistd.h>
32
33
#if defined(__linux__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
34
#include <sys/ioctl.h>
35
#endif
36
37
#if defined(__linux__)
38
#include <linux/fs.h>
39
#include <sys/stat.h>
40
#endif
41
42
#ifdef MACOSX
43
44
#include <CoreFoundation/CoreFoundation.h>
45
46
__private_extern__
47
jstring newStringPlatform(JNIEnv *env, const char* str)
48
{
49
jstring rv = NULL;
50
CFMutableStringRef csref = CFStringCreateMutable(NULL, 0);
51
if (csref == NULL) {
52
JNU_ThrowOutOfMemoryError(env, "native heap");
53
} else {
54
CFStringAppendCString(csref, str, kCFStringEncodingUTF8);
55
CFStringNormalize(csref, kCFStringNormalizationFormC);
56
int clen = CFStringGetLength(csref);
57
int ulen = (clen + 1) * 2; // utf16 + zero padding
58
char* chars = malloc(ulen);
59
if (chars == NULL) {
60
CFRelease(csref);
61
JNU_ThrowOutOfMemoryError(env, "native heap");
62
} else {
63
if (CFStringGetCString(csref, chars, ulen, kCFStringEncodingUTF16)) {
64
rv = (*env)->NewString(env, (jchar*)chars, clen);
65
}
66
free(chars);
67
CFRelease(csref);
68
}
69
}
70
return rv;
71
}
72
#endif
73
74
FD
75
handleOpen(const char *path, int oflag, int mode) {
76
FD fd;
77
RESTARTABLE(open64(path, oflag, mode), fd);
78
if (fd != -1) {
79
struct stat64 buf64;
80
int result;
81
RESTARTABLE(fstat64(fd, &buf64), result);
82
if (result != -1) {
83
if (S_ISDIR(buf64.st_mode)) {
84
close(fd);
85
errno = EISDIR;
86
fd = -1;
87
}
88
} else {
89
close(fd);
90
fd = -1;
91
}
92
}
93
return fd;
94
}
95
96
FD getFD(JNIEnv *env, jobject obj, jfieldID fid) {
97
jobject fdo = (*env)->GetObjectField(env, obj, fid);
98
if (fdo == NULL) {
99
return -1;
100
}
101
return (*env)->GetIntField(env, fdo, IO_fd_fdID);
102
}
103
104
void
105
fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
106
{
107
WITH_PLATFORM_STRING(env, path, ps) {
108
FD fd;
109
110
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
111
/* Remove trailing slashes, since the kernel won't */
112
char *p = (char *)ps + strlen(ps) - 1;
113
while ((p > ps) && (*p == '/'))
114
*p-- = '\0';
115
#endif
116
fd = handleOpen(ps, flags, 0666);
117
if (fd != -1) {
118
jobject fdobj;
119
jboolean append;
120
fdobj = (*env)->GetObjectField(env, this, fid);
121
if (fdobj != NULL) {
122
// Set FD
123
(*env)->SetIntField(env, fdobj, IO_fd_fdID, fd);
124
append = (flags & O_APPEND) == 0 ? JNI_FALSE : JNI_TRUE;
125
(*env)->SetBooleanField(env, fdobj, IO_append_fdID, append);
126
}
127
} else {
128
throwFileNotFoundException(env, path);
129
}
130
} END_PLATFORM_STRING(env, ps);
131
}
132
133
// Function to close the fd held by this FileDescriptor and set fd to -1.
134
void
135
fileDescriptorClose(JNIEnv *env, jobject this)
136
{
137
FD fd = (*env)->GetIntField(env, this, IO_fd_fdID);
138
if ((*env)->ExceptionOccurred(env)) {
139
return;
140
}
141
142
if (fd == -1) {
143
return; // already closed and set to -1
144
}
145
146
/* Set the fd to -1 before closing it so that the timing window
147
* of other threads using the wrong fd (closed but recycled fd,
148
* that gets re-opened with some other filename) is reduced.
149
* Practically the chance of its occurance is low, however, we are
150
* taking extra precaution over here.
151
*/
152
(*env)->SetIntField(env, this, IO_fd_fdID, -1);
153
if ((*env)->ExceptionOccurred(env)) {
154
return;
155
}
156
/*
157
* Don't close file descriptors 0, 1, or 2. If we close these stream
158
* then a subsequent file open or socket will use them. Instead we
159
* just redirect these file descriptors to /dev/null.
160
*/
161
if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {
162
int devnull = open("/dev/null", O_WRONLY);
163
if (devnull < 0) {
164
(*env)->SetIntField(env, this, IO_fd_fdID, fd);
165
JNU_ThrowIOExceptionWithLastError(env, "open /dev/null failed");
166
} else {
167
dup2(devnull, fd);
168
close(devnull);
169
}
170
} else {
171
int result;
172
#if defined(_AIX)
173
/* AIX allows close to be restarted after EINTR */
174
RESTARTABLE(close(fd), result);
175
#else
176
result = close(fd);
177
#endif
178
if (result == -1 && errno != EINTR) {
179
JNU_ThrowIOExceptionWithLastError(env, "close failed");
180
}
181
}
182
}
183
184
ssize_t
185
handleRead(FD fd, void *buf, jint len)
186
{
187
ssize_t result;
188
RESTARTABLE(read(fd, buf, len), result);
189
return result;
190
}
191
192
ssize_t
193
handleWrite(FD fd, const void *buf, jint len)
194
{
195
ssize_t result;
196
RESTARTABLE(write(fd, buf, len), result);
197
return result;
198
}
199
200
jint
201
handleAvailable(FD fd, jlong *pbytes)
202
{
203
int mode;
204
struct stat64 buf64;
205
jlong size = -1, current = -1;
206
207
int result;
208
RESTARTABLE(fstat64(fd, &buf64), result);
209
if (result != -1) {
210
mode = buf64.st_mode;
211
if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
212
int n;
213
int result;
214
RESTARTABLE(ioctl(fd, FIONREAD, &n), result);
215
if (result >= 0) {
216
*pbytes = n;
217
return 1;
218
}
219
} else if (S_ISREG(mode)) {
220
size = buf64.st_size;
221
}
222
}
223
224
if ((current = lseek64(fd, 0, SEEK_CUR)) == -1) {
225
return 0;
226
}
227
228
if (size < current) {
229
if ((size = lseek64(fd, 0, SEEK_END)) == -1)
230
return 0;
231
else if (lseek64(fd, current, SEEK_SET) == -1)
232
return 0;
233
}
234
235
*pbytes = size - current;
236
return 1;
237
}
238
239
jint
240
handleSetLength(FD fd, jlong length)
241
{
242
int result;
243
RESTARTABLE(ftruncate64(fd, length), result);
244
return result;
245
}
246
247
jlong
248
handleGetLength(FD fd)
249
{
250
struct stat64 sb;
251
int result;
252
RESTARTABLE(fstat64(fd, &sb), result);
253
if (result < 0) {
254
return -1;
255
}
256
#if defined(__linux__) && defined(BLKGETSIZE64)
257
if (S_ISBLK(sb.st_mode)) {
258
uint64_t size;
259
if(ioctl(fd, BLKGETSIZE64, &size) < 0) {
260
return -1;
261
}
262
return (jlong)size;
263
}
264
#endif
265
return sb.st_size;
266
}
267
268