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