Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
41133 views
1
/*
2
* Copyright (c) 2008, 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 <stdio.h>
27
#include <stdlib.h>
28
#include <limits.h>
29
#include <fcntl.h>
30
#include <dirent.h>
31
#include <unistd.h>
32
#include <errno.h>
33
#include <dlfcn.h>
34
#include <sys/types.h>
35
#include <sys/stat.h>
36
#ifdef MACOSX
37
#include <sys/param.h>
38
#include <sys/mount.h>
39
#else
40
#include <sys/statvfs.h>
41
#endif
42
#include <sys/time.h>
43
44
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
45
#include <sys/xattr.h>
46
#endif
47
48
/* For POSIX-compliant getpwuid_r */
49
#include <pwd.h>
50
#include <grp.h>
51
52
#ifdef __linux__
53
#include <sys/syscall.h>
54
#endif
55
56
#if defined(__linux__) || defined(_AIX)
57
#include <string.h>
58
#endif
59
60
#ifdef _ALLBSD_SOURCE
61
#include <string.h>
62
63
#define stat64 stat
64
#ifndef MACOSX
65
#define statvfs64 statvfs
66
#endif
67
68
#define open64 open
69
#define fstat64 fstat
70
#define lstat64 lstat
71
#define readdir64 readdir
72
#endif
73
74
#include "jni.h"
75
#include "jni_util.h"
76
#include "jlong.h"
77
78
#include "sun_nio_fs_UnixNativeDispatcher.h"
79
80
#if defined(_AIX)
81
#define DIR DIR64
82
#define dirent dirent64
83
#define opendir opendir64
84
#define readdir readdir64
85
#define closedir closedir64
86
#endif
87
88
/**
89
* Size of password or group entry when not available via sysconf
90
*/
91
#define ENT_BUF_SIZE 1024
92
93
#define RESTARTABLE(_cmd, _result) do { \
94
do { \
95
_result = _cmd; \
96
} while((_result == -1) && (errno == EINTR)); \
97
} while(0)
98
99
#define RESTARTABLE_RETURN_PTR(_cmd, _result) do { \
100
do { \
101
_result = _cmd; \
102
} while((_result == NULL) && (errno == EINTR)); \
103
} while(0)
104
105
static jfieldID attrs_st_mode;
106
static jfieldID attrs_st_ino;
107
static jfieldID attrs_st_dev;
108
static jfieldID attrs_st_rdev;
109
static jfieldID attrs_st_nlink;
110
static jfieldID attrs_st_uid;
111
static jfieldID attrs_st_gid;
112
static jfieldID attrs_st_size;
113
static jfieldID attrs_st_atime_sec;
114
static jfieldID attrs_st_atime_nsec;
115
static jfieldID attrs_st_mtime_sec;
116
static jfieldID attrs_st_mtime_nsec;
117
static jfieldID attrs_st_ctime_sec;
118
static jfieldID attrs_st_ctime_nsec;
119
120
#ifdef _DARWIN_FEATURE_64_BIT_INODE
121
static jfieldID attrs_st_birthtime_sec;
122
#endif
123
124
static jfieldID attrs_f_frsize;
125
static jfieldID attrs_f_blocks;
126
static jfieldID attrs_f_bfree;
127
static jfieldID attrs_f_bavail;
128
129
static jfieldID entry_name;
130
static jfieldID entry_dir;
131
static jfieldID entry_fstype;
132
static jfieldID entry_options;
133
static jfieldID entry_dev;
134
135
/**
136
* System calls that may not be available at run time.
137
*/
138
typedef int openat64_func(int, const char *, int, ...);
139
typedef int fstatat64_func(int, const char *, struct stat64 *, int);
140
typedef int unlinkat_func(int, const char*, int);
141
typedef int renameat_func(int, const char*, int, const char*);
142
typedef int futimesat_func(int, const char *, const struct timeval *);
143
typedef int utimensat_func(int, const char *, const struct timespec *, int flags);
144
typedef int futimens_func(int, const struct timespec *);
145
typedef int lutimes_func(const char *, const struct timeval *);
146
typedef DIR* fdopendir_func(int);
147
148
static openat64_func* my_openat64_func = NULL;
149
static fstatat64_func* my_fstatat64_func = NULL;
150
static unlinkat_func* my_unlinkat_func = NULL;
151
static renameat_func* my_renameat_func = NULL;
152
static futimesat_func* my_futimesat_func = NULL;
153
static utimensat_func* my_utimensat_func = NULL;
154
static futimens_func* my_futimens_func = NULL;
155
static lutimes_func* my_lutimes_func = NULL;
156
static fdopendir_func* my_fdopendir_func = NULL;
157
158
#ifdef __ANDROID__
159
/*
160
* TODO: Android lacks support for the methods listed below. In it's place are
161
* alternatives that use existing Android functionality, but lack reentrant
162
* support. Determine if the following are the most suitable alternatives.
163
*
164
*/
165
int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
166
167
*result = NULL;
168
errno = 0;
169
grp = getgrgid(gid);
170
if (grp == NULL) {
171
return errno;
172
}
173
// buf not used by caller (see below)
174
*result = grp;
175
return 0;
176
}
177
178
int getgrnam_r(const char *name, struct group* grp, char* buf, size_t buflen, struct group** result) {
179
180
*result = NULL;
181
errno = 0;
182
grp = getgrnam(name);
183
if (grp == NULL) {
184
return errno;
185
}
186
// buf not used by caller (see below)
187
*result = grp;
188
return 0;
189
190
}
191
#endif
192
193
/**
194
* fstatat missing from glibc on Linux.
195
*/
196
#if defined(__linux__) && (defined(__i386) || defined(__arm__))
197
#define FSTATAT64_SYSCALL_AVAILABLE
198
static int fstatat64_wrapper(int dfd, const char *path,
199
struct stat64 *statbuf, int flag)
200
{
201
#ifndef __NR_fstatat64
202
#define __NR_fstatat64 300
203
#endif
204
return syscall(__NR_fstatat64, dfd, path, statbuf, flag);
205
}
206
#endif
207
208
#if defined(__linux__) && defined(_LP64) && defined(__NR_newfstatat)
209
#define FSTATAT64_SYSCALL_AVAILABLE
210
static int fstatat64_wrapper(int dfd, const char *path,
211
struct stat64 *statbuf, int flag)
212
{
213
return syscall(__NR_newfstatat, dfd, path, statbuf, flag);
214
}
215
#endif
216
217
/**
218
* Call this to throw an internal UnixException when a system/library
219
* call fails
220
*/
221
static void throwUnixException(JNIEnv* env, int errnum) {
222
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
223
"(I)V", errnum);
224
if (x != NULL) {
225
(*env)->Throw(env, x);
226
}
227
}
228
229
/**
230
* Initialization
231
*/
232
JNIEXPORT jint JNICALL
233
Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
234
{
235
jint capabilities = 0;
236
jclass clazz;
237
238
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileAttributes");
239
CHECK_NULL_RETURN(clazz, 0);
240
attrs_st_mode = (*env)->GetFieldID(env, clazz, "st_mode", "I");
241
CHECK_NULL_RETURN(attrs_st_mode, 0);
242
attrs_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J");
243
CHECK_NULL_RETURN(attrs_st_ino, 0);
244
attrs_st_dev = (*env)->GetFieldID(env, clazz, "st_dev", "J");
245
CHECK_NULL_RETURN(attrs_st_dev, 0);
246
attrs_st_rdev = (*env)->GetFieldID(env, clazz, "st_rdev", "J");
247
CHECK_NULL_RETURN(attrs_st_rdev, 0);
248
attrs_st_nlink = (*env)->GetFieldID(env, clazz, "st_nlink", "I");
249
CHECK_NULL_RETURN(attrs_st_nlink, 0);
250
attrs_st_uid = (*env)->GetFieldID(env, clazz, "st_uid", "I");
251
CHECK_NULL_RETURN(attrs_st_uid, 0);
252
attrs_st_gid = (*env)->GetFieldID(env, clazz, "st_gid", "I");
253
CHECK_NULL_RETURN(attrs_st_gid, 0);
254
attrs_st_size = (*env)->GetFieldID(env, clazz, "st_size", "J");
255
CHECK_NULL_RETURN(attrs_st_size, 0);
256
attrs_st_atime_sec = (*env)->GetFieldID(env, clazz, "st_atime_sec", "J");
257
CHECK_NULL_RETURN(attrs_st_atime_sec, 0);
258
attrs_st_atime_nsec = (*env)->GetFieldID(env, clazz, "st_atime_nsec", "J");
259
CHECK_NULL_RETURN(attrs_st_atime_nsec, 0);
260
attrs_st_mtime_sec = (*env)->GetFieldID(env, clazz, "st_mtime_sec", "J");
261
CHECK_NULL_RETURN(attrs_st_mtime_sec, 0);
262
attrs_st_mtime_nsec = (*env)->GetFieldID(env, clazz, "st_mtime_nsec", "J");
263
CHECK_NULL_RETURN(attrs_st_mtime_nsec, 0);
264
attrs_st_ctime_sec = (*env)->GetFieldID(env, clazz, "st_ctime_sec", "J");
265
CHECK_NULL_RETURN(attrs_st_ctime_sec, 0);
266
attrs_st_ctime_nsec = (*env)->GetFieldID(env, clazz, "st_ctime_nsec", "J");
267
CHECK_NULL_RETURN(attrs_st_ctime_nsec, 0);
268
269
#ifdef _DARWIN_FEATURE_64_BIT_INODE
270
attrs_st_birthtime_sec = (*env)->GetFieldID(env, clazz, "st_birthtime_sec", "J");
271
CHECK_NULL_RETURN(attrs_st_birthtime_sec, 0);
272
#endif
273
274
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
275
CHECK_NULL_RETURN(clazz, 0);
276
attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J");
277
CHECK_NULL_RETURN(attrs_f_frsize, 0);
278
attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J");
279
CHECK_NULL_RETURN(attrs_f_blocks, 0);
280
attrs_f_bfree = (*env)->GetFieldID(env, clazz, "f_bfree", "J");
281
CHECK_NULL_RETURN(attrs_f_bfree, 0);
282
attrs_f_bavail = (*env)->GetFieldID(env, clazz, "f_bavail", "J");
283
CHECK_NULL_RETURN(attrs_f_bavail, 0);
284
285
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
286
CHECK_NULL_RETURN(clazz, 0);
287
entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
288
CHECK_NULL_RETURN(entry_name, 0);
289
entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
290
CHECK_NULL_RETURN(entry_dir, 0);
291
entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
292
CHECK_NULL_RETURN(entry_fstype, 0);
293
entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
294
CHECK_NULL_RETURN(entry_options, 0);
295
entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
296
CHECK_NULL_RETURN(entry_dev, 0);
297
298
/* system calls that might not be available at run time */
299
300
#if defined(_ALLBSD_SOURCE)
301
my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
302
my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
303
#else
304
my_openat64_func = (openat64_func*) dlsym(RTLD_DEFAULT, "openat64");
305
my_fstatat64_func = (fstatat64_func*) dlsym(RTLD_DEFAULT, "fstatat64");
306
#endif
307
my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
308
my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
309
#ifndef _ALLBSD_SOURCE
310
my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
311
my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes");
312
#endif
313
#ifdef __ANDROID__
314
my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat");
315
#endif
316
my_futimens_func = (futimens_func*) dlsym(RTLD_DEFAULT, "futimens");
317
#if defined(_AIX)
318
my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64");
319
#else
320
my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir");
321
#endif
322
323
#if defined(FSTATAT64_SYSCALL_AVAILABLE)
324
/* fstatat64 missing from glibc */
325
if (my_fstatat64_func == NULL)
326
my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
327
#endif
328
329
/* supports futimes or futimesat, futimens, and/or lutimes */
330
331
#ifdef _ALLBSD_SOURCE
332
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
333
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
334
#else
335
if (my_futimesat_func != NULL || my_utimensat_func != NULL)
336
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
337
if (my_lutimes_func != NULL)
338
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
339
#endif
340
if (my_futimens_func != NULL)
341
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMENS;
342
343
/* supports openat, etc. */
344
345
if (my_openat64_func != NULL && my_fstatat64_func != NULL &&
346
my_unlinkat_func != NULL && my_renameat_func != NULL &&
347
(my_futimesat_func != NULL || my_utimensat_func != NULL) && my_fdopendir_func != NULL)
348
{
349
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_OPENAT;
350
}
351
352
/* supports file birthtime */
353
354
#ifdef _DARWIN_FEATURE_64_BIT_INODE
355
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME;
356
#endif
357
358
/* supports extended attributes */
359
360
#ifdef _SYS_XATTR_H_
361
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_XATTR;
362
#endif
363
364
return capabilities;
365
}
366
367
JNIEXPORT jbyteArray JNICALL
368
Java_sun_nio_fs_UnixNativeDispatcher_getcwd(JNIEnv* env, jclass this) {
369
jbyteArray result = NULL;
370
char buf[PATH_MAX+1];
371
372
/* EINTR not listed as a possible error */
373
char* cwd = getcwd(buf, sizeof(buf));
374
if (cwd == NULL) {
375
throwUnixException(env, errno);
376
} else {
377
jsize len = (jsize)strlen(buf);
378
result = (*env)->NewByteArray(env, len);
379
if (result != NULL) {
380
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)buf);
381
}
382
}
383
return result;
384
}
385
386
JNIEXPORT jbyteArray
387
Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
388
{
389
char tmpbuf[1024];
390
jsize len;
391
jbyteArray bytes;
392
393
getErrorString((int)errno, tmpbuf, sizeof(tmpbuf));
394
len = strlen(tmpbuf);
395
bytes = (*env)->NewByteArray(env, len);
396
if (bytes != NULL) {
397
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)tmpbuf);
398
}
399
return bytes;
400
}
401
402
JNIEXPORT jint
403
Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) {
404
405
int res = -1;
406
407
RESTARTABLE(dup((int)fd), res);
408
if (res == -1) {
409
throwUnixException(env, errno);
410
}
411
return (jint)res;
412
}
413
414
JNIEXPORT void JNICALL
415
Java_sun_nio_fs_UnixNativeDispatcher_rewind(JNIEnv* env, jclass this, jlong stream)
416
{
417
FILE* fp = jlong_to_ptr(stream);
418
int saved_errno;
419
420
errno = 0;
421
rewind(fp);
422
saved_errno = errno;
423
if (ferror(fp)) {
424
throwUnixException(env, saved_errno);
425
}
426
}
427
428
/**
429
* This function returns line length without NUL terminator or -1 on EOF.
430
*/
431
JNIEXPORT jint JNICALL
432
Java_sun_nio_fs_UnixNativeDispatcher_getlinelen(JNIEnv* env, jclass this, jlong stream)
433
{
434
FILE* fp = jlong_to_ptr(stream);
435
size_t lineSize = 0;
436
char * lineBuffer = NULL;
437
int saved_errno;
438
439
ssize_t res = getline(&lineBuffer, &lineSize, fp);
440
saved_errno = errno;
441
442
/* Should free lineBuffer no matter result, according to man page */
443
if (lineBuffer != NULL)
444
free(lineBuffer);
445
446
if (feof(fp))
447
return -1;
448
449
/* On successfull return res >= 0, otherwise res is -1 */
450
if (res == -1)
451
throwUnixException(env, saved_errno);
452
453
if (res > INT_MAX)
454
throwUnixException(env, EOVERFLOW);
455
456
return (jint)res;
457
}
458
459
JNIEXPORT jint JNICALL
460
Java_sun_nio_fs_UnixNativeDispatcher_open0(JNIEnv* env, jclass this,
461
jlong pathAddress, jint oflags, jint mode)
462
{
463
jint fd;
464
const char* path = (const char*)jlong_to_ptr(pathAddress);
465
466
RESTARTABLE(open64(path, (int)oflags, (mode_t)mode), fd);
467
if (fd == -1) {
468
throwUnixException(env, errno);
469
}
470
return fd;
471
}
472
473
JNIEXPORT jint JNICALL
474
Java_sun_nio_fs_UnixNativeDispatcher_openat0(JNIEnv* env, jclass this, jint dfd,
475
jlong pathAddress, jint oflags, jint mode)
476
{
477
jint fd;
478
const char* path = (const char*)jlong_to_ptr(pathAddress);
479
480
if (my_openat64_func == NULL) {
481
JNU_ThrowInternalError(env, "should not reach here");
482
return -1;
483
}
484
485
RESTARTABLE((*my_openat64_func)(dfd, path, (int)oflags, (mode_t)mode), fd);
486
if (fd == -1) {
487
throwUnixException(env, errno);
488
}
489
return fd;
490
}
491
492
JNIEXPORT void JNICALL
493
Java_sun_nio_fs_UnixNativeDispatcher_close0(JNIEnv* env, jclass this, jint fd) {
494
int res;
495
496
#if defined(_AIX)
497
/* AIX allows close to be restarted after EINTR */
498
RESTARTABLE(close((int)fd), res);
499
#else
500
res = close((int)fd);
501
#endif
502
if (res == -1 && errno != EINTR) {
503
throwUnixException(env, errno);
504
}
505
}
506
507
JNIEXPORT jint JNICALL
508
Java_sun_nio_fs_UnixNativeDispatcher_read(JNIEnv* env, jclass this, jint fd,
509
jlong address, jint nbytes)
510
{
511
ssize_t n;
512
void* bufp = jlong_to_ptr(address);
513
RESTARTABLE(read((int)fd, bufp, (size_t)nbytes), n);
514
if (n == -1) {
515
throwUnixException(env, errno);
516
}
517
return (jint)n;
518
}
519
520
JNIEXPORT jint JNICALL
521
Java_sun_nio_fs_UnixNativeDispatcher_write(JNIEnv* env, jclass this, jint fd,
522
jlong address, jint nbytes)
523
{
524
ssize_t n;
525
void* bufp = jlong_to_ptr(address);
526
RESTARTABLE(write((int)fd, bufp, (size_t)nbytes), n);
527
if (n == -1) {
528
throwUnixException(env, errno);
529
}
530
return (jint)n;
531
}
532
533
/**
534
* Copy stat64 members into sun.nio.fs.UnixFileAttributes
535
*/
536
static void prepAttributes(JNIEnv* env, struct stat64* buf, jobject attrs) {
537
(*env)->SetIntField(env, attrs, attrs_st_mode, (jint)buf->st_mode);
538
(*env)->SetLongField(env, attrs, attrs_st_ino, (jlong)buf->st_ino);
539
(*env)->SetLongField(env, attrs, attrs_st_dev, (jlong)buf->st_dev);
540
(*env)->SetLongField(env, attrs, attrs_st_rdev, (jlong)buf->st_rdev);
541
(*env)->SetIntField(env, attrs, attrs_st_nlink, (jint)buf->st_nlink);
542
(*env)->SetIntField(env, attrs, attrs_st_uid, (jint)buf->st_uid);
543
(*env)->SetIntField(env, attrs, attrs_st_gid, (jint)buf->st_gid);
544
(*env)->SetLongField(env, attrs, attrs_st_size, (jlong)buf->st_size);
545
(*env)->SetLongField(env, attrs, attrs_st_atime_sec, (jlong)buf->st_atime);
546
(*env)->SetLongField(env, attrs, attrs_st_mtime_sec, (jlong)buf->st_mtime);
547
(*env)->SetLongField(env, attrs, attrs_st_ctime_sec, (jlong)buf->st_ctime);
548
549
#ifdef _DARWIN_FEATURE_64_BIT_INODE
550
(*env)->SetLongField(env, attrs, attrs_st_birthtime_sec, (jlong)buf->st_birthtime);
551
#endif
552
553
#ifndef MACOSX
554
(*env)->SetLongField(env, attrs, attrs_st_atime_nsec, (jlong)buf->st_atim.tv_nsec);
555
(*env)->SetLongField(env, attrs, attrs_st_mtime_nsec, (jlong)buf->st_mtim.tv_nsec);
556
(*env)->SetLongField(env, attrs, attrs_st_ctime_nsec, (jlong)buf->st_ctim.tv_nsec);
557
#else
558
(*env)->SetLongField(env, attrs, attrs_st_atime_nsec, (jlong)buf->st_atimespec.tv_nsec);
559
(*env)->SetLongField(env, attrs, attrs_st_mtime_nsec, (jlong)buf->st_mtimespec.tv_nsec);
560
(*env)->SetLongField(env, attrs, attrs_st_ctime_nsec, (jlong)buf->st_ctimespec.tv_nsec);
561
#endif
562
}
563
564
JNIEXPORT void JNICALL
565
Java_sun_nio_fs_UnixNativeDispatcher_stat0(JNIEnv* env, jclass this,
566
jlong pathAddress, jobject attrs)
567
{
568
int err;
569
struct stat64 buf;
570
const char* path = (const char*)jlong_to_ptr(pathAddress);
571
572
RESTARTABLE(stat64(path, &buf), err);
573
if (err == -1) {
574
throwUnixException(env, errno);
575
} else {
576
prepAttributes(env, &buf, attrs);
577
}
578
}
579
580
JNIEXPORT jint JNICALL
581
Java_sun_nio_fs_UnixNativeDispatcher_stat1(JNIEnv* env, jclass this, jlong pathAddress) {
582
int err;
583
struct stat64 buf;
584
const char* path = (const char*)jlong_to_ptr(pathAddress);
585
586
RESTARTABLE(stat64(path, &buf), err);
587
if (err == -1) {
588
return 0;
589
} else {
590
return (jint)buf.st_mode;
591
}
592
}
593
594
JNIEXPORT void JNICALL
595
Java_sun_nio_fs_UnixNativeDispatcher_lstat0(JNIEnv* env, jclass this,
596
jlong pathAddress, jobject attrs)
597
{
598
int err;
599
struct stat64 buf;
600
const char* path = (const char*)jlong_to_ptr(pathAddress);
601
602
RESTARTABLE(lstat64(path, &buf), err);
603
if (err == -1) {
604
throwUnixException(env, errno);
605
} else {
606
prepAttributes(env, &buf, attrs);
607
}
608
}
609
610
JNIEXPORT void JNICALL
611
Java_sun_nio_fs_UnixNativeDispatcher_fstat(JNIEnv* env, jclass this, jint fd,
612
jobject attrs)
613
{
614
int err;
615
struct stat64 buf;
616
617
RESTARTABLE(fstat64((int)fd, &buf), err);
618
if (err == -1) {
619
throwUnixException(env, errno);
620
} else {
621
prepAttributes(env, &buf, attrs);
622
}
623
}
624
625
JNIEXPORT void JNICALL
626
Java_sun_nio_fs_UnixNativeDispatcher_fstatat0(JNIEnv* env, jclass this, jint dfd,
627
jlong pathAddress, jint flag, jobject attrs)
628
{
629
int err;
630
struct stat64 buf;
631
const char* path = (const char*)jlong_to_ptr(pathAddress);
632
633
if (my_fstatat64_func == NULL) {
634
JNU_ThrowInternalError(env, "should not reach here");
635
return;
636
}
637
RESTARTABLE((*my_fstatat64_func)((int)dfd, path, &buf, (int)flag), err);
638
if (err == -1) {
639
throwUnixException(env, errno);
640
} else {
641
prepAttributes(env, &buf, attrs);
642
}
643
}
644
645
JNIEXPORT void JNICALL
646
Java_sun_nio_fs_UnixNativeDispatcher_chmod0(JNIEnv* env, jclass this,
647
jlong pathAddress, jint mode)
648
{
649
int err;
650
const char* path = (const char*)jlong_to_ptr(pathAddress);
651
652
RESTARTABLE(chmod(path, (mode_t)mode), err);
653
if (err == -1) {
654
throwUnixException(env, errno);
655
}
656
}
657
658
JNIEXPORT void JNICALL
659
Java_sun_nio_fs_UnixNativeDispatcher_fchmod(JNIEnv* env, jclass this, jint filedes,
660
jint mode)
661
{
662
int err;
663
664
RESTARTABLE(fchmod((int)filedes, (mode_t)mode), err);
665
if (err == -1) {
666
throwUnixException(env, errno);
667
}
668
}
669
670
671
JNIEXPORT void JNICALL
672
Java_sun_nio_fs_UnixNativeDispatcher_chown0(JNIEnv* env, jclass this,
673
jlong pathAddress, jint uid, jint gid)
674
{
675
int err;
676
const char* path = (const char*)jlong_to_ptr(pathAddress);
677
678
RESTARTABLE(chown(path, (uid_t)uid, (gid_t)gid), err);
679
if (err == -1) {
680
throwUnixException(env, errno);
681
}
682
}
683
684
JNIEXPORT void JNICALL
685
Java_sun_nio_fs_UnixNativeDispatcher_lchown0(JNIEnv* env, jclass this, jlong pathAddress, jint uid, jint gid)
686
{
687
int err;
688
const char* path = (const char*)jlong_to_ptr(pathAddress);
689
690
RESTARTABLE(lchown(path, (uid_t)uid, (gid_t)gid), err);
691
if (err == -1) {
692
throwUnixException(env, errno);
693
}
694
}
695
696
JNIEXPORT void JNICALL
697
Java_sun_nio_fs_UnixNativeDispatcher_fchown(JNIEnv* env, jclass this, jint filedes, jint uid, jint gid)
698
{
699
int err;
700
701
RESTARTABLE(fchown(filedes, (uid_t)uid, (gid_t)gid), err);
702
if (err == -1) {
703
throwUnixException(env, errno);
704
}
705
}
706
707
JNIEXPORT void JNICALL
708
Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this,
709
jlong pathAddress, jlong accessTime, jlong modificationTime)
710
{
711
int err;
712
struct timeval times[2];
713
const char* path = (const char*)jlong_to_ptr(pathAddress);
714
715
times[0].tv_sec = accessTime / 1000000;
716
times[0].tv_usec = accessTime % 1000000;
717
718
times[1].tv_sec = modificationTime / 1000000;
719
times[1].tv_usec = modificationTime % 1000000;
720
721
RESTARTABLE(utimes(path, &times[0]), err);
722
if (err == -1) {
723
throwUnixException(env, errno);
724
}
725
}
726
727
JNIEXPORT void JNICALL
728
Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint filedes,
729
jlong accessTime, jlong modificationTime)
730
{
731
struct timeval times[2];
732
struct timespec times2[2];
733
int err = 0;
734
735
times[0].tv_sec = times2[0].tv_sec = accessTime / 1000000;
736
times[0].tv_usec = accessTime % 1000000;
737
738
times[1].tv_sec = times2[1].tv_sec = modificationTime / 1000000;
739
times[1].tv_usec = modificationTime % 1000000;
740
741
times2[0].tv_nsec = times[0].tv_usec * 1000;
742
times2[1].tv_nsec = times[1].tv_usec * 1000;
743
744
#ifdef _ALLBSD_SOURCE
745
RESTARTABLE(futimes(filedes, &times[0]), err);
746
#else
747
if (my_futimesat_func == NULL && my_utimensat_func == NULL) {
748
JNU_ThrowInternalError(env, "my_futimesat_func and my_utimensat_func are NULL");
749
return;
750
}
751
if (my_futimesat_func != NULL) {
752
RESTARTABLE((*my_futimesat_func)(filedes, NULL, &times[0]), err);
753
} else {
754
RESTARTABLE((*my_utimensat_func)(filedes, NULL, &times2[0], 0), err);
755
}
756
#endif
757
if (err == -1) {
758
throwUnixException(env, errno);
759
}
760
}
761
762
JNIEXPORT void JNICALL
763
Java_sun_nio_fs_UnixNativeDispatcher_futimens(JNIEnv* env, jclass this, jint filedes,
764
jlong accessTime, jlong modificationTime)
765
{
766
struct timespec times[2];
767
int err = 0;
768
769
times[0].tv_sec = accessTime / 1000000000;
770
times[0].tv_nsec = accessTime % 1000000000;
771
772
times[1].tv_sec = modificationTime / 1000000000;
773
times[1].tv_nsec = modificationTime % 1000000000;
774
775
if (my_futimens_func == NULL) {
776
JNU_ThrowInternalError(env, "my_futimens_func is NULL");
777
return;
778
}
779
RESTARTABLE((*my_futimens_func)(filedes, &times[0]), err);
780
if (err == -1) {
781
throwUnixException(env, errno);
782
}
783
}
784
785
JNIEXPORT void JNICALL
786
Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this,
787
jlong pathAddress, jlong accessTime, jlong modificationTime)
788
{
789
int err;
790
struct timeval times[2];
791
const char* path = (const char*)jlong_to_ptr(pathAddress);
792
793
times[0].tv_sec = accessTime / 1000000;
794
times[0].tv_usec = accessTime % 1000000;
795
796
times[1].tv_sec = modificationTime / 1000000;
797
times[1].tv_usec = modificationTime % 1000000;
798
799
#ifdef _ALLBSD_SOURCE
800
RESTARTABLE(lutimes(path, &times[0]), err);
801
#else
802
if (my_lutimes_func == NULL) {
803
JNU_ThrowInternalError(env, "my_lutimes_func is NULL");
804
return;
805
}
806
RESTARTABLE((*my_lutimes_func)(path, &times[0]), err);
807
#endif
808
if (err == -1) {
809
throwUnixException(env, errno);
810
}
811
}
812
813
JNIEXPORT jlong JNICALL
814
Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
815
jlong pathAddress)
816
{
817
DIR* dir;
818
const char* path = (const char*)jlong_to_ptr(pathAddress);
819
820
/* EINTR not listed as a possible error */
821
dir = opendir(path);
822
if (dir == NULL) {
823
throwUnixException(env, errno);
824
}
825
return ptr_to_jlong(dir);
826
}
827
828
JNIEXPORT jlong JNICALL
829
Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) {
830
DIR* dir;
831
832
if (my_fdopendir_func == NULL) {
833
JNU_ThrowInternalError(env, "should not reach here");
834
return (jlong)-1;
835
}
836
837
/* EINTR not listed as a possible error */
838
dir = (*my_fdopendir_func)((int)dfd);
839
if (dir == NULL) {
840
throwUnixException(env, errno);
841
}
842
return ptr_to_jlong(dir);
843
}
844
845
JNIEXPORT void JNICALL
846
Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) {
847
DIR* dirp = jlong_to_ptr(dir);
848
849
if (closedir(dirp) == -1 && errno != EINTR) {
850
throwUnixException(env, errno);
851
}
852
}
853
854
JNIEXPORT jbyteArray JNICALL
855
Java_sun_nio_fs_UnixNativeDispatcher_readdir(JNIEnv* env, jclass this, jlong value) {
856
DIR* dirp = jlong_to_ptr(value);
857
struct dirent* ptr;
858
859
errno = 0;
860
ptr = readdir(dirp);
861
if (ptr == NULL) {
862
if (errno != 0) {
863
throwUnixException(env, errno);
864
}
865
return NULL;
866
} else {
867
jsize len = strlen(ptr->d_name);
868
jbyteArray bytes = (*env)->NewByteArray(env, len);
869
if (bytes != NULL) {
870
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)(ptr->d_name));
871
}
872
return bytes;
873
}
874
}
875
876
JNIEXPORT void JNICALL
877
Java_sun_nio_fs_UnixNativeDispatcher_mkdir0(JNIEnv* env, jclass this,
878
jlong pathAddress, jint mode)
879
{
880
const char* path = (const char*)jlong_to_ptr(pathAddress);
881
882
/* EINTR not listed as a possible error */
883
if (mkdir(path, (mode_t)mode) == -1) {
884
throwUnixException(env, errno);
885
}
886
}
887
888
JNIEXPORT void JNICALL
889
Java_sun_nio_fs_UnixNativeDispatcher_rmdir0(JNIEnv* env, jclass this,
890
jlong pathAddress)
891
{
892
const char* path = (const char*)jlong_to_ptr(pathAddress);
893
894
/* EINTR not listed as a possible error */
895
if (rmdir(path) == -1) {
896
throwUnixException(env, errno);
897
}
898
}
899
900
JNIEXPORT void JNICALL
901
Java_sun_nio_fs_UnixNativeDispatcher_link0(JNIEnv* env, jclass this,
902
jlong existingAddress, jlong newAddress)
903
{
904
int err;
905
const char* existing = (const char*)jlong_to_ptr(existingAddress);
906
const char* newname = (const char*)jlong_to_ptr(newAddress);
907
908
RESTARTABLE(link(existing, newname), err);
909
if (err == -1) {
910
throwUnixException(env, errno);
911
}
912
}
913
914
915
JNIEXPORT void JNICALL
916
Java_sun_nio_fs_UnixNativeDispatcher_unlink0(JNIEnv* env, jclass this,
917
jlong pathAddress)
918
{
919
const char* path = (const char*)jlong_to_ptr(pathAddress);
920
921
/* EINTR not listed as a possible error */
922
if (unlink(path) == -1) {
923
throwUnixException(env, errno);
924
}
925
}
926
927
JNIEXPORT void JNICALL
928
Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0(JNIEnv* env, jclass this, jint dfd,
929
jlong pathAddress, jint flags)
930
{
931
const char* path = (const char*)jlong_to_ptr(pathAddress);
932
933
if (my_unlinkat_func == NULL) {
934
JNU_ThrowInternalError(env, "should not reach here");
935
return;
936
}
937
938
/* EINTR not listed as a possible error */
939
if ((*my_unlinkat_func)((int)dfd, path, (int)flags) == -1) {
940
throwUnixException(env, errno);
941
}
942
}
943
944
JNIEXPORT void JNICALL
945
Java_sun_nio_fs_UnixNativeDispatcher_rename0(JNIEnv* env, jclass this,
946
jlong fromAddress, jlong toAddress)
947
{
948
const char* from = (const char*)jlong_to_ptr(fromAddress);
949
const char* to = (const char*)jlong_to_ptr(toAddress);
950
951
/* EINTR not listed as a possible error */
952
if (rename(from, to) == -1) {
953
throwUnixException(env, errno);
954
}
955
}
956
957
JNIEXPORT void JNICALL
958
Java_sun_nio_fs_UnixNativeDispatcher_renameat0(JNIEnv* env, jclass this,
959
jint fromfd, jlong fromAddress, jint tofd, jlong toAddress)
960
{
961
const char* from = (const char*)jlong_to_ptr(fromAddress);
962
const char* to = (const char*)jlong_to_ptr(toAddress);
963
964
if (my_renameat_func == NULL) {
965
JNU_ThrowInternalError(env, "should not reach here");
966
return;
967
}
968
969
/* EINTR not listed as a possible error */
970
if ((*my_renameat_func)((int)fromfd, from, (int)tofd, to) == -1) {
971
throwUnixException(env, errno);
972
}
973
}
974
975
JNIEXPORT void JNICALL
976
Java_sun_nio_fs_UnixNativeDispatcher_symlink0(JNIEnv* env, jclass this,
977
jlong targetAddress, jlong linkAddress)
978
{
979
const char* target = (const char*)jlong_to_ptr(targetAddress);
980
const char* link = (const char*)jlong_to_ptr(linkAddress);
981
982
/* EINTR not listed as a possible error */
983
if (symlink(target, link) == -1) {
984
throwUnixException(env, errno);
985
}
986
}
987
988
JNIEXPORT jbyteArray JNICALL
989
Java_sun_nio_fs_UnixNativeDispatcher_readlink0(JNIEnv* env, jclass this,
990
jlong pathAddress)
991
{
992
jbyteArray result = NULL;
993
char target[PATH_MAX+1];
994
const char* path = (const char*)jlong_to_ptr(pathAddress);
995
996
/* EINTR not listed as a possible error */
997
int n = readlink(path, target, sizeof(target));
998
if (n == -1) {
999
throwUnixException(env, errno);
1000
} else {
1001
jsize len;
1002
if (n == sizeof(target)) {
1003
/* Traditionally readlink(2) should not return more than */
1004
/* PATH_MAX bytes (no terminating null byte is appended). */
1005
throwUnixException(env, ENAMETOOLONG);
1006
return NULL;
1007
}
1008
target[n] = '\0';
1009
len = (jsize)strlen(target);
1010
result = (*env)->NewByteArray(env, len);
1011
if (result != NULL) {
1012
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)target);
1013
}
1014
}
1015
return result;
1016
}
1017
1018
JNIEXPORT jbyteArray JNICALL
1019
Java_sun_nio_fs_UnixNativeDispatcher_realpath0(JNIEnv* env, jclass this,
1020
jlong pathAddress)
1021
{
1022
jbyteArray result = NULL;
1023
char resolved[PATH_MAX+1];
1024
const char* path = (const char*)jlong_to_ptr(pathAddress);
1025
1026
/* EINTR not listed as a possible error */
1027
if (realpath(path, resolved) == NULL) {
1028
throwUnixException(env, errno);
1029
} else {
1030
jsize len = (jsize)strlen(resolved);
1031
result = (*env)->NewByteArray(env, len);
1032
if (result != NULL) {
1033
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)resolved);
1034
}
1035
}
1036
return result;
1037
}
1038
1039
JNIEXPORT void JNICALL
1040
Java_sun_nio_fs_UnixNativeDispatcher_access0(JNIEnv* env, jclass this,
1041
jlong pathAddress, jint amode)
1042
{
1043
int err;
1044
const char* path = (const char*)jlong_to_ptr(pathAddress);
1045
1046
RESTARTABLE(access(path, (int)amode), err);
1047
if (err == -1) {
1048
throwUnixException(env, errno);
1049
}
1050
}
1051
1052
JNIEXPORT jboolean JNICALL
1053
Java_sun_nio_fs_UnixNativeDispatcher_exists0(JNIEnv* env, jclass this, jlong pathAddress) {
1054
int err;
1055
const char* path = (const char*)jlong_to_ptr(pathAddress);
1056
RESTARTABLE(access(path, F_OK), err);
1057
return (err == 0) ? JNI_TRUE : JNI_FALSE;
1058
}
1059
1060
JNIEXPORT void JNICALL
1061
Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
1062
jlong pathAddress, jobject attrs)
1063
{
1064
int err;
1065
#ifdef MACOSX
1066
struct statfs buf;
1067
#else
1068
struct statvfs64 buf;
1069
#endif
1070
const char* path = (const char*)jlong_to_ptr(pathAddress);
1071
1072
#ifdef MACOSX
1073
RESTARTABLE(statfs(path, &buf), err);
1074
#else
1075
RESTARTABLE(statvfs64(path, &buf), err);
1076
#endif
1077
if (err == -1) {
1078
throwUnixException(env, errno);
1079
} else {
1080
#ifdef _AIX
1081
/* AIX returns ULONG_MAX in buf.f_blocks for the /proc file system. */
1082
/* This is too big for a Java signed long and fools various tests. */
1083
if (buf.f_blocks == ULONG_MAX) {
1084
buf.f_blocks = 0;
1085
}
1086
/* The number of free or available blocks can never exceed the total number of blocks */
1087
if (buf.f_blocks == 0) {
1088
buf.f_bfree = 0;
1089
buf.f_bavail = 0;
1090
}
1091
#endif
1092
#ifdef MACOSX
1093
(*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_bsize));
1094
#else
1095
(*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize));
1096
#endif
1097
(*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks));
1098
(*env)->SetLongField(env, attrs, attrs_f_bfree, long_to_jlong(buf.f_bfree));
1099
(*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail));
1100
}
1101
}
1102
1103
JNIEXPORT void JNICALL
1104
Java_sun_nio_fs_UnixNativeDispatcher_mknod0(JNIEnv* env, jclass this,
1105
jlong pathAddress, jint mode, jlong dev)
1106
{
1107
int err;
1108
const char* path = (const char*)jlong_to_ptr(pathAddress);
1109
1110
RESTARTABLE(mknod(path, (mode_t)mode, (dev_t)dev), err);
1111
if (err == -1) {
1112
throwUnixException(env, errno);
1113
}
1114
}
1115
1116
JNIEXPORT jbyteArray JNICALL
1117
Java_sun_nio_fs_UnixNativeDispatcher_getpwuid(JNIEnv* env, jclass this, jint uid)
1118
{
1119
jbyteArray result = NULL;
1120
int buflen;
1121
char* pwbuf;
1122
1123
/* allocate buffer for password record */
1124
buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
1125
if (buflen == -1)
1126
buflen = ENT_BUF_SIZE;
1127
pwbuf = (char*)malloc(buflen);
1128
if (pwbuf == NULL) {
1129
JNU_ThrowOutOfMemoryError(env, "native heap");
1130
} else {
1131
struct passwd pwent;
1132
struct passwd* p = NULL;
1133
int res = 0;
1134
1135
errno = 0;
1136
RESTARTABLE(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p), res);
1137
1138
if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
1139
/* not found or error */
1140
if (errno == 0)
1141
errno = ENOENT;
1142
throwUnixException(env, errno);
1143
} else {
1144
jsize len = strlen(p->pw_name);
1145
result = (*env)->NewByteArray(env, len);
1146
if (result != NULL) {
1147
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name));
1148
}
1149
}
1150
free(pwbuf);
1151
}
1152
1153
return result;
1154
}
1155
1156
1157
JNIEXPORT jbyteArray JNICALL
1158
Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid)
1159
{
1160
jbyteArray result = NULL;
1161
int buflen;
1162
int retry;
1163
1164
/* initial size of buffer for group record */
1165
buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX);
1166
if (buflen == -1)
1167
buflen = ENT_BUF_SIZE;
1168
1169
do {
1170
struct group grent;
1171
struct group* g = NULL;
1172
int res = 0;
1173
1174
char* grbuf = (char*)malloc(buflen);
1175
if (grbuf == NULL) {
1176
JNU_ThrowOutOfMemoryError(env, "native heap");
1177
return NULL;
1178
}
1179
1180
errno = 0;
1181
RESTARTABLE(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g), res);
1182
1183
retry = 0;
1184
if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
1185
/* not found or error */
1186
if (errno == ERANGE) {
1187
/* insufficient buffer size so need larger buffer */
1188
buflen += ENT_BUF_SIZE;
1189
retry = 1;
1190
} else {
1191
if (errno == 0)
1192
errno = ENOENT;
1193
throwUnixException(env, errno);
1194
}
1195
} else {
1196
jsize len = strlen(g->gr_name);
1197
result = (*env)->NewByteArray(env, len);
1198
if (result != NULL) {
1199
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name));
1200
}
1201
}
1202
1203
free(grbuf);
1204
1205
} while (retry);
1206
1207
return result;
1208
}
1209
1210
JNIEXPORT jint JNICALL
1211
Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this,
1212
jlong nameAddress)
1213
{
1214
jint uid = -1;
1215
int buflen;
1216
char* pwbuf;
1217
1218
/* allocate buffer for password record */
1219
buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
1220
if (buflen == -1)
1221
buflen = ENT_BUF_SIZE;
1222
pwbuf = (char*)malloc(buflen);
1223
if (pwbuf == NULL) {
1224
JNU_ThrowOutOfMemoryError(env, "native heap");
1225
} else {
1226
struct passwd pwent;
1227
struct passwd* p = NULL;
1228
int res = 0;
1229
const char* name = (const char*)jlong_to_ptr(nameAddress);
1230
1231
errno = 0;
1232
RESTARTABLE(getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p), res);
1233
1234
if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
1235
/* not found or error */
1236
if (errno != 0 && errno != ENOENT && errno != ESRCH &&
1237
errno != EBADF && errno != EPERM)
1238
{
1239
throwUnixException(env, errno);
1240
}
1241
} else {
1242
uid = p->pw_uid;
1243
}
1244
free(pwbuf);
1245
}
1246
1247
return uid;
1248
}
1249
1250
JNIEXPORT jint JNICALL
1251
Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0(JNIEnv* env, jclass this,
1252
jlong nameAddress)
1253
{
1254
jint gid = -1;
1255
int buflen, retry;
1256
1257
/* initial size of buffer for group record */
1258
buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX);
1259
if (buflen == -1)
1260
buflen = ENT_BUF_SIZE;
1261
1262
do {
1263
struct group grent;
1264
struct group* g = NULL;
1265
int res = 0;
1266
char *grbuf;
1267
const char* name = (const char*)jlong_to_ptr(nameAddress);
1268
1269
grbuf = (char*)malloc(buflen);
1270
if (grbuf == NULL) {
1271
JNU_ThrowOutOfMemoryError(env, "native heap");
1272
return -1;
1273
}
1274
1275
errno = 0;
1276
RESTARTABLE(getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g), res);
1277
1278
retry = 0;
1279
if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
1280
/* not found or error */
1281
if (errno != 0 && errno != ENOENT && errno != ESRCH &&
1282
errno != EBADF && errno != EPERM)
1283
{
1284
if (errno == ERANGE) {
1285
/* insufficient buffer size so need larger buffer */
1286
buflen += ENT_BUF_SIZE;
1287
retry = 1;
1288
} else {
1289
throwUnixException(env, errno);
1290
}
1291
}
1292
} else {
1293
gid = g->gr_gid;
1294
}
1295
1296
free(grbuf);
1297
1298
} while (retry);
1299
1300
return gid;
1301
}
1302
1303
JNIEXPORT jint JNICALL
1304
Java_sun_nio_fs_UnixNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz,
1305
jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
1306
{
1307
size_t res = -1;
1308
const char* name = jlong_to_ptr(nameAddress);
1309
void* value = jlong_to_ptr(valueAddress);
1310
1311
#ifdef __linux__
1312
res = fgetxattr(fd, name, value, valueLen);
1313
#elif _ALLBSD_SOURCE
1314
res = fgetxattr(fd, name, value, valueLen, 0, 0);
1315
#else
1316
throwUnixException(env, ENOTSUP);
1317
#endif
1318
1319
if (res == (size_t)-1)
1320
throwUnixException(env, errno);
1321
return (jint)res;
1322
}
1323
1324
JNIEXPORT void JNICALL
1325
Java_sun_nio_fs_UnixNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz,
1326
jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
1327
{
1328
int res = -1;
1329
const char* name = jlong_to_ptr(nameAddress);
1330
void* value = jlong_to_ptr(valueAddress);
1331
1332
#ifdef __linux__
1333
res = fsetxattr(fd, name, value, valueLen, 0);
1334
#elif _ALLBSD_SOURCE
1335
res = fsetxattr(fd, name, value, valueLen, 0, 0);
1336
#else
1337
throwUnixException(env, ENOTSUP);
1338
#endif
1339
1340
if (res == -1)
1341
throwUnixException(env, errno);
1342
}
1343
1344
JNIEXPORT void JNICALL
1345
Java_sun_nio_fs_UnixNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz,
1346
jint fd, jlong nameAddress)
1347
{
1348
int res = -1;
1349
const char* name = jlong_to_ptr(nameAddress);
1350
1351
#ifdef __linux__
1352
res = fremovexattr(fd, name);
1353
#elif _ALLBSD_SOURCE
1354
res = fremovexattr(fd, name, 0);
1355
#else
1356
throwUnixException(env, ENOTSUP);
1357
#endif
1358
1359
if (res == -1)
1360
throwUnixException(env, errno);
1361
}
1362
1363
JNIEXPORT jint JNICALL
1364
Java_sun_nio_fs_UnixNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz,
1365
jint fd, jlong listAddress, jint size)
1366
{
1367
size_t res = -1;
1368
char* list = jlong_to_ptr(listAddress);
1369
1370
#ifdef __linux__
1371
res = flistxattr(fd, list, (size_t)size);
1372
#elif _ALLBSD_SOURCE
1373
res = flistxattr(fd, list, (size_t)size, 0);
1374
#else
1375
throwUnixException(env, ENOTSUP);
1376
#endif
1377
1378
if (res == (size_t)-1)
1379
throwUnixException(env, errno);
1380
return (jint)res;
1381
}
1382
1383