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