Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libjava/UnixFileSystem_md.c
41119 views
1
/*
2
* Copyright (c) 1998, 2020, 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 <unistd.h>
27
#include <assert.h>
28
#include <sys/types.h>
29
#include <sys/time.h>
30
#include <sys/stat.h>
31
#ifdef MACOSX
32
#include <sys/param.h>
33
#include <sys/mount.h>
34
#else
35
#include <sys/statvfs.h>
36
#endif
37
#include <string.h>
38
#include <stdlib.h>
39
#include <dlfcn.h>
40
#include <limits.h>
41
#include <errno.h>
42
#include <fcntl.h>
43
#include <dirent.h>
44
45
#include "jni.h"
46
#include "jni_util.h"
47
#include "jlong.h"
48
#include "jdk_util.h"
49
#include "io_util.h"
50
#include "io_util_md.h"
51
#include "java_io_FileSystem.h"
52
#include "java_io_UnixFileSystem.h"
53
54
#if defined(_AIX)
55
#if !defined(NAME_MAX)
56
#define NAME_MAX MAXNAMLEN
57
#endif
58
#define DIR DIR64
59
#define dirent dirent64
60
#define opendir opendir64
61
#define readdir readdir64
62
#define closedir closedir64
63
#define stat stat64
64
#endif
65
66
#if defined(_ALLBSD_SOURCE)
67
#ifndef MACOSX
68
#define statvfs64 statvfs
69
#define stat64 stat
70
#endif
71
#endif
72
73
/* -- Field IDs -- */
74
75
static struct {
76
jfieldID path;
77
} ids;
78
79
80
JNIEXPORT void JNICALL
81
Java_java_io_UnixFileSystem_initIDs(JNIEnv *env, jclass cls)
82
{
83
jclass fileClass = (*env)->FindClass(env, "java/io/File");
84
if (!fileClass) return;
85
ids.path = (*env)->GetFieldID(env, fileClass,
86
"path", "Ljava/lang/String;");
87
}
88
89
/* -- Path operations -- */
90
91
JNIEXPORT jstring JNICALL
92
Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,
93
jstring pathname)
94
{
95
jstring rv = NULL;
96
97
WITH_PLATFORM_STRING(env, pathname, path) {
98
char canonicalPath[PATH_MAX];
99
if (JDK_Canonicalize((char *)path,
100
canonicalPath, PATH_MAX) < 0) {
101
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
102
} else {
103
#ifdef MACOSX
104
rv = newStringPlatform(env, canonicalPath);
105
#else
106
rv = JNU_NewStringPlatform(env, canonicalPath);
107
#endif
108
}
109
} END_PLATFORM_STRING(env, path);
110
return rv;
111
}
112
113
114
/* -- Attribute accessors -- */
115
116
117
static jboolean
118
statMode(const char *path, int *mode)
119
{
120
struct stat64 sb;
121
if (stat64(path, &sb) == 0) {
122
*mode = sb.st_mode;
123
return JNI_TRUE;
124
}
125
return JNI_FALSE;
126
}
127
128
129
JNIEXPORT jint JNICALL
130
Java_java_io_UnixFileSystem_getBooleanAttributes0(JNIEnv *env, jobject this,
131
jobject file)
132
{
133
jint rv = 0;
134
135
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
136
int mode;
137
if (statMode(path, &mode)) {
138
int fmt = mode & S_IFMT;
139
rv = (jint) (java_io_FileSystem_BA_EXISTS
140
| ((fmt == S_IFREG) ? java_io_FileSystem_BA_REGULAR : 0)
141
| ((fmt == S_IFDIR) ? java_io_FileSystem_BA_DIRECTORY : 0));
142
}
143
} END_PLATFORM_STRING(env, path);
144
return rv;
145
}
146
147
JNIEXPORT jboolean JNICALL
148
Java_java_io_UnixFileSystem_checkAccess(JNIEnv *env, jobject this,
149
jobject file, jint a)
150
{
151
jboolean rv = JNI_FALSE;
152
int mode = 0;
153
switch (a) {
154
case java_io_FileSystem_ACCESS_READ:
155
mode = R_OK;
156
break;
157
case java_io_FileSystem_ACCESS_WRITE:
158
mode = W_OK;
159
break;
160
case java_io_FileSystem_ACCESS_EXECUTE:
161
mode = X_OK;
162
break;
163
default: assert(0);
164
}
165
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
166
int res;
167
RESTARTABLE(access(path, mode), res);
168
if (res == 0) {
169
rv = JNI_TRUE;
170
}
171
} END_PLATFORM_STRING(env, path);
172
return rv;
173
}
174
175
176
JNIEXPORT jboolean JNICALL
177
Java_java_io_UnixFileSystem_setPermission(JNIEnv *env, jobject this,
178
jobject file,
179
jint access,
180
jboolean enable,
181
jboolean owneronly)
182
{
183
jboolean rv = JNI_FALSE;
184
185
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
186
int amode = 0;
187
int mode;
188
int res;
189
switch (access) {
190
case java_io_FileSystem_ACCESS_READ:
191
if (owneronly)
192
amode = S_IRUSR;
193
else
194
amode = S_IRUSR | S_IRGRP | S_IROTH;
195
break;
196
case java_io_FileSystem_ACCESS_WRITE:
197
if (owneronly)
198
amode = S_IWUSR;
199
else
200
amode = S_IWUSR | S_IWGRP | S_IWOTH;
201
break;
202
case java_io_FileSystem_ACCESS_EXECUTE:
203
if (owneronly)
204
amode = S_IXUSR;
205
else
206
amode = S_IXUSR | S_IXGRP | S_IXOTH;
207
break;
208
default:
209
assert(0);
210
}
211
if (statMode(path, &mode)) {
212
if (enable)
213
mode |= amode;
214
else
215
mode &= ~amode;
216
RESTARTABLE(chmod(path, mode), res);
217
if (res == 0) {
218
rv = JNI_TRUE;
219
}
220
}
221
} END_PLATFORM_STRING(env, path);
222
return rv;
223
}
224
225
JNIEXPORT jlong JNICALL
226
Java_java_io_UnixFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
227
jobject file)
228
{
229
jlong rv = 0;
230
231
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
232
struct stat64 sb;
233
if (stat64(path, &sb) == 0) {
234
#if defined(_AIX)
235
rv = (jlong)sb.st_mtime * 1000;
236
rv += (jlong)sb.st_mtime_n / 1000000;
237
#elif defined(MACOSX)
238
rv = (jlong)sb.st_mtimespec.tv_sec * 1000;
239
rv += (jlong)sb.st_mtimespec.tv_nsec / 1000000;
240
#else
241
rv = (jlong)sb.st_mtim.tv_sec * 1000;
242
rv += (jlong)sb.st_mtim.tv_nsec / 1000000;
243
#endif
244
}
245
} END_PLATFORM_STRING(env, path);
246
return rv;
247
}
248
249
250
JNIEXPORT jlong JNICALL
251
Java_java_io_UnixFileSystem_getLength(JNIEnv *env, jobject this,
252
jobject file)
253
{
254
jlong rv = 0;
255
256
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
257
struct stat64 sb;
258
if (stat64(path, &sb) == 0) {
259
rv = sb.st_size;
260
}
261
} END_PLATFORM_STRING(env, path);
262
return rv;
263
}
264
265
266
/* -- File operations -- */
267
268
269
JNIEXPORT jboolean JNICALL
270
Java_java_io_UnixFileSystem_createFileExclusively(JNIEnv *env, jclass cls,
271
jstring pathname)
272
{
273
jboolean rv = JNI_FALSE;
274
275
WITH_PLATFORM_STRING(env, pathname, path) {
276
FD fd;
277
/* The root directory always exists */
278
if (strcmp (path, "/")) {
279
fd = handleOpen(path, O_RDWR | O_CREAT | O_EXCL, 0666);
280
if (fd < 0) {
281
if (errno != EEXIST)
282
JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
283
} else {
284
if (close(fd) == -1)
285
JNU_ThrowIOExceptionWithLastError(env, "Could not close file");
286
rv = JNI_TRUE;
287
}
288
}
289
} END_PLATFORM_STRING(env, path);
290
return rv;
291
}
292
293
294
JNIEXPORT jboolean JNICALL
295
Java_java_io_UnixFileSystem_delete0(JNIEnv *env, jobject this,
296
jobject file)
297
{
298
jboolean rv = JNI_FALSE;
299
300
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
301
if (remove(path) == 0) {
302
rv = JNI_TRUE;
303
}
304
} END_PLATFORM_STRING(env, path);
305
return rv;
306
}
307
308
309
JNIEXPORT jobjectArray JNICALL
310
Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
311
jobject file)
312
{
313
DIR *dir = NULL;
314
struct dirent *ptr;
315
int len, maxlen;
316
jobjectArray rv, old;
317
jclass str_class;
318
319
str_class = JNU_ClassString(env);
320
CHECK_NULL_RETURN(str_class, NULL);
321
322
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
323
dir = opendir(path);
324
} END_PLATFORM_STRING(env, path);
325
if (dir == NULL) return NULL;
326
327
/* Allocate an initial String array */
328
len = 0;
329
maxlen = 16;
330
rv = (*env)->NewObjectArray(env, maxlen, str_class, NULL);
331
if (rv == NULL) goto error;
332
333
/* Scan the directory */
334
while ((ptr = readdir(dir)) != NULL) {
335
jstring name;
336
if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, ".."))
337
continue;
338
if (len == maxlen) {
339
old = rv;
340
rv = (*env)->NewObjectArray(env, maxlen <<= 1, str_class, NULL);
341
if (rv == NULL) goto error;
342
if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
343
(*env)->DeleteLocalRef(env, old);
344
}
345
#ifdef MACOSX
346
name = newStringPlatform(env, ptr->d_name);
347
#else
348
name = JNU_NewStringPlatform(env, ptr->d_name);
349
#endif
350
if (name == NULL) goto error;
351
(*env)->SetObjectArrayElement(env, rv, len++, name);
352
(*env)->DeleteLocalRef(env, name);
353
}
354
closedir(dir);
355
356
/* Copy the final results into an appropriately-sized array */
357
if (len < maxlen) {
358
old = rv;
359
rv = (*env)->NewObjectArray(env, len, str_class, NULL);
360
if (rv == NULL) {
361
return NULL;
362
}
363
if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
364
return NULL;
365
}
366
}
367
return rv;
368
369
error:
370
closedir(dir);
371
return NULL;
372
}
373
374
375
JNIEXPORT jboolean JNICALL
376
Java_java_io_UnixFileSystem_createDirectory(JNIEnv *env, jobject this,
377
jobject file)
378
{
379
jboolean rv = JNI_FALSE;
380
381
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
382
if (mkdir(path, 0777) == 0) {
383
rv = JNI_TRUE;
384
}
385
} END_PLATFORM_STRING(env, path);
386
return rv;
387
}
388
389
390
JNIEXPORT jboolean JNICALL
391
Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,
392
jobject from, jobject to)
393
{
394
jboolean rv = JNI_FALSE;
395
396
WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {
397
WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {
398
if (rename(fromPath, toPath) == 0) {
399
rv = JNI_TRUE;
400
}
401
} END_PLATFORM_STRING(env, toPath);
402
} END_PLATFORM_STRING(env, fromPath);
403
return rv;
404
}
405
406
JNIEXPORT jboolean JNICALL
407
Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
408
jobject file, jlong time)
409
{
410
jboolean rv = JNI_FALSE;
411
412
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
413
struct stat64 sb;
414
415
if (stat64(path, &sb) == 0) {
416
struct timeval tv[2];
417
418
/* Preserve access time */
419
#if defined(_AIX)
420
tv[0].tv_sec = sb.st_atime;
421
tv[0].tv_usec = sb.st_atime_n / 1000;
422
#elif defined(MACOSX)
423
tv[0].tv_sec = sb.st_atimespec.tv_sec;
424
tv[0].tv_usec = sb.st_atimespec.tv_nsec / 1000;
425
#else
426
tv[0].tv_sec = sb.st_atim.tv_sec;
427
tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
428
#endif
429
/* Change last-modified time */
430
tv[1].tv_sec = time / 1000;
431
tv[1].tv_usec = (time % 1000) * 1000;
432
433
if (utimes(path, tv) == 0)
434
rv = JNI_TRUE;
435
}
436
} END_PLATFORM_STRING(env, path);
437
438
return rv;
439
}
440
441
442
JNIEXPORT jboolean JNICALL
443
Java_java_io_UnixFileSystem_setReadOnly(JNIEnv *env, jobject this,
444
jobject file)
445
{
446
jboolean rv = JNI_FALSE;
447
448
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
449
int mode;
450
int res;
451
if (statMode(path, &mode)) {
452
RESTARTABLE(chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)), res);
453
if (res == 0) {
454
rv = JNI_TRUE;
455
}
456
}
457
} END_PLATFORM_STRING(env, path);
458
return rv;
459
}
460
461
JNIEXPORT jlong JNICALL
462
Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
463
jobject file, jint t)
464
{
465
jlong rv = 0L;
466
467
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
468
#ifdef MACOSX
469
struct statfs fsstat;
470
#else
471
struct statvfs64 fsstat;
472
int res;
473
#endif
474
memset(&fsstat, 0, sizeof(fsstat));
475
#ifdef MACOSX
476
if (statfs(path, &fsstat) == 0) {
477
switch(t) {
478
case java_io_FileSystem_SPACE_TOTAL:
479
rv = jlong_mul(long_to_jlong(fsstat.f_bsize),
480
long_to_jlong(fsstat.f_blocks));
481
break;
482
case java_io_FileSystem_SPACE_FREE:
483
rv = jlong_mul(long_to_jlong(fsstat.f_bsize),
484
long_to_jlong(fsstat.f_bfree));
485
break;
486
case java_io_FileSystem_SPACE_USABLE:
487
rv = jlong_mul(long_to_jlong(fsstat.f_bsize),
488
long_to_jlong(fsstat.f_bavail));
489
break;
490
default:
491
assert(0);
492
}
493
}
494
#else
495
RESTARTABLE(statvfs64(path, &fsstat), res);
496
if (res == 0) {
497
switch(t) {
498
case java_io_FileSystem_SPACE_TOTAL:
499
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
500
long_to_jlong(fsstat.f_blocks));
501
break;
502
case java_io_FileSystem_SPACE_FREE:
503
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
504
long_to_jlong(fsstat.f_bfree));
505
break;
506
case java_io_FileSystem_SPACE_USABLE:
507
rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
508
long_to_jlong(fsstat.f_bavail));
509
break;
510
default:
511
assert(0);
512
}
513
}
514
#endif
515
} END_PLATFORM_STRING(env, path);
516
return rv;
517
}
518
519
JNIEXPORT jlong JNICALL
520
Java_java_io_UnixFileSystem_getNameMax0(JNIEnv *env, jobject this,
521
jstring pathname)
522
{
523
jlong length = -1;
524
WITH_PLATFORM_STRING(env, pathname, path) {
525
length = (jlong)pathconf(path, _PC_NAME_MAX);
526
} END_PLATFORM_STRING(env, path);
527
return length != -1 ? length : (jlong)NAME_MAX;
528
}
529
530