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