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