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