42 #include <strings.h>
43 #endif
44
45 #ifdef __linux__
46 #include <string.h>
47 #endif
48
49 #ifdef _ALLBSD_SOURCE
50 #include <string.h>
51
52 #define stat64 stat
53 #define statvfs64 statvfs
54
55 #define open64 open
56 #define fstat64 fstat
57 #define lstat64 lstat
58 #define dirent64 dirent
59 #define readdir64_r readdir_r
60 #endif
61
62 #include "jni.h"
63 #include "jni_util.h"
64 #include "jlong.h"
65
66 #include "sun_nio_fs_UnixNativeDispatcher.h"
67
68 /**
69 * Size of password or group entry when not available via sysconf
70 */
71 #define ENT_BUF_SIZE 1024
72
73 #define RESTARTABLE(_cmd, _result) do { \
74 do { \
75 _result = _cmd; \
76 } while((_result == -1) && (errno == EINTR)); \
77 } while(0)
78
79 #define RESTARTABLE_RETURN_PTR(_cmd, _result) do { \
80 do { \
81 _result = _cmd; \
88 static jfieldID attrs_st_rdev;
89 static jfieldID attrs_st_nlink;
90 static jfieldID attrs_st_uid;
91 static jfieldID attrs_st_gid;
92 static jfieldID attrs_st_size;
93 static jfieldID attrs_st_atime;
94 static jfieldID attrs_st_mtime;
95 static jfieldID attrs_st_ctime;
96
97 static jfieldID attrs_f_frsize;
98 static jfieldID attrs_f_blocks;
99 static jfieldID attrs_f_bfree;
100 static jfieldID attrs_f_bavail;
101
102 static jfieldID entry_name;
103 static jfieldID entry_dir;
104 static jfieldID entry_fstype;
105 static jfieldID entry_options;
106 static jfieldID entry_dev;
107
108 /**
109 * System calls that may not be available at run time.
110 */
111 typedef int openat64_func(int, const char *, int, ...);
112 typedef int fstatat64_func(int, const char *, struct stat64 *, int);
113 typedef int unlinkat_func(int, const char*, int);
114 typedef int renameat_func(int, const char*, int, const char*);
115 typedef int futimesat_func(int, const char *, const struct timeval *);
116 typedef DIR* fdopendir_func(int);
117
118 static openat64_func* my_openat64_func = NULL;
119 static fstatat64_func* my_fstatat64_func = NULL;
120 static unlinkat_func* my_unlinkat_func = NULL;
121 static renameat_func* my_renameat_func = NULL;
122 static futimesat_func* my_futimesat_func = NULL;
123 static fdopendir_func* my_fdopendir_func = NULL;
124
125 /**
126 * fstatat missing from glibc on Linux. Temporary workaround
127 * for x86/x64.
189
190 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
191 if (clazz == NULL) {
192 return 0;
193 }
194 attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J");
195 attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J");
196 attrs_f_bfree = (*env)->GetFieldID(env, clazz, "f_bfree", "J");
197 attrs_f_bavail = (*env)->GetFieldID(env, clazz, "f_bavail", "J");
198
199 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
200 if (clazz == NULL) {
201 return 0;
202 }
203 entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
204 entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
205 entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
206 entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
207 entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
208
209 /* system calls that might not be available at run time */
210
211 #if (defined(__solaris__) && defined(_LP64)) || defined(_ALLBSD_SOURCE)
212 /* Solaris 64-bit does not have openat64/fstatat64 */
213 my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
214 my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
215 #else
216 my_openat64_func = (openat64_func*) dlsym(RTLD_DEFAULT, "openat64");
217 my_fstatat64_func = (fstatat64_func*) dlsym(RTLD_DEFAULT, "fstatat64");
218 #endif
219 my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
220 my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
221 my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
222 my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir");
223
224 #if defined(FSTATAT64_SYSCALL_AVAILABLE)
225 /* fstatat64 missing from glibc */
226 if (my_fstatat64_func == NULL)
227 my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
228 #endif
246 char* cwd = getcwd(buf, sizeof(buf));
247 if (cwd == NULL) {
248 throwUnixException(env, errno);
249 } else {
250 jsize len = (jsize)strlen(buf);
251 result = (*env)->NewByteArray(env, len);
252 if (result != NULL) {
253 (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)buf);
254 }
255 }
256 return result;
257 }
258
259 JNIEXPORT jbyteArray
260 Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
261 {
262 char* msg;
263 jsize len;
264 jbyteArray bytes;
265
266 msg = strerror((int)error);
267 len = strlen(msg);
268 bytes = (*env)->NewByteArray(env, len);
269 if (bytes != NULL) {
270 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
271 }
272 return bytes;
273 }
274
275 JNIEXPORT jint
276 Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) {
277
278 int res = -1;
279
280 RESTARTABLE(dup((int)fd), res);
281 if (res == -1) {
282 throwUnixException(env, errno);
283 }
284 return (jint)res;
285 }
286
533 JNIEXPORT void JNICALL
534 Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this,
535 jlong pathAddress, jlong accessTime, jlong modificationTime)
536 {
537 int err;
538 struct timeval times[2];
539 const char* path = (const char*)jlong_to_ptr(pathAddress);
540
541 times[0].tv_sec = accessTime / 1000000;
542 times[0].tv_usec = accessTime % 1000000;
543
544 times[1].tv_sec = modificationTime / 1000000;
545 times[1].tv_usec = modificationTime % 1000000;
546
547 RESTARTABLE(utimes(path, ×[0]), err);
548 if (err == -1) {
549 throwUnixException(env, errno);
550 }
551 }
552
553 JNIEXPORT void JNICALL
554 Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint filedes,
555 jlong accessTime, jlong modificationTime)
556 {
557 struct timeval times[2];
558 int err = 0;
559
560 times[0].tv_sec = accessTime / 1000000;
561 times[0].tv_usec = accessTime % 1000000;
562
563 times[1].tv_sec = modificationTime / 1000000;
564 times[1].tv_usec = modificationTime % 1000000;
565
566 #ifdef _ALLBSD_SOURCE
567 RESTARTABLE(futimes(filedes, ×[0]), err);
568 #else
569 if (my_futimesat_func == NULL) {
570 JNU_ThrowInternalError(env, "my_ftimesat_func is NULL");
571 return;
572 }
573 RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err);
574 #endif
575 if (err == -1) {
576 throwUnixException(env, errno);
577 }
578 }
579
580 JNIEXPORT jlong JNICALL
581 Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
582 jlong pathAddress)
583 {
584 DIR* dir;
585 const char* path = (const char*)jlong_to_ptr(pathAddress);
586
587 /* EINTR not listed as a possible error */
588 dir = opendir(path);
589 if (dir == NULL) {
590 throwUnixException(env, errno);
591 }
592 return ptr_to_jlong(dir);
593 }
594
595 JNIEXPORT jlong JNICALL
596 Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) {
597 DIR* dir;
609 return ptr_to_jlong(dir);
610 }
611
612 JNIEXPORT void JNICALL
613 Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) {
614 DIR* dirp = jlong_to_ptr(dir);
615
616 if (closedir(dirp) == -1 && errno != EINTR) {
617 throwUnixException(env, errno);
618 }
619 }
620
621 JNIEXPORT jbyteArray JNICALL
622 Java_sun_nio_fs_UnixNativeDispatcher_readdir(JNIEnv* env, jclass this, jlong value) {
623 struct dirent64* result;
624 struct {
625 struct dirent64 buf;
626 char name_extra[PATH_MAX + 1 - sizeof result->d_name];
627 } entry;
628 struct dirent64* ptr = &entry.buf;
629 int res;
630 DIR* dirp = jlong_to_ptr(value);
631
632 /* EINTR not listed as a possible error */
633 /* TDB: reentrant version probably not required here */
634 res = readdir64_r(dirp, ptr, &result);
635 if (res != 0) {
636 throwUnixException(env, res);
637 return NULL;
638 } else {
639 if (result == NULL) {
640 return NULL;
641 } else {
642 jsize len = strlen(ptr->d_name);
643 jbyteArray bytes = (*env)->NewByteArray(env, len);
644 if (bytes != NULL) {
645 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)(ptr->d_name));
646 }
647 return bytes;
648 }
649 }
650 }
651
652 JNIEXPORT void JNICALL
653 Java_sun_nio_fs_UnixNativeDispatcher_mkdir0(JNIEnv* env, jclass this,
654 jlong pathAddress, jint mode)
818
819 RESTARTABLE(access(path, (int)amode), err);
820 if (err == -1) {
821 throwUnixException(env, errno);
822 }
823 }
824
825 JNIEXPORT void JNICALL
826 Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
827 jlong pathAddress, jobject attrs)
828 {
829 int err;
830 struct statvfs64 buf;
831 const char* path = (const char*)jlong_to_ptr(pathAddress);
832
833
834 RESTARTABLE(statvfs64(path, &buf), err);
835 if (err == -1) {
836 throwUnixException(env, errno);
837 } else {
838 (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize));
839 (*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks));
840 (*env)->SetLongField(env, attrs, attrs_f_bfree, long_to_jlong(buf.f_bfree));
841 (*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail));
842 }
843 }
844
845 JNIEXPORT jlong JNICALL
846 Java_sun_nio_fs_UnixNativeDispatcher_pathconf0(JNIEnv* env, jclass this,
847 jlong pathAddress, jint name)
848 {
849 long err;
850 const char* path = (const char*)jlong_to_ptr(pathAddress);
851
852 err = pathconf(path, (int)name);
853 if (err == -1) {
854 throwUnixException(env, errno);
855 }
856 return (jlong)err;
857 }
894 if (buflen == -1)
895 buflen = ENT_BUF_SIZE;
896 pwbuf = (char*)malloc(buflen);
897 if (pwbuf == NULL) {
898 JNU_ThrowOutOfMemoryError(env, "native heap");
899 } else {
900 struct passwd pwent;
901 struct passwd* p = NULL;
902 int res = 0;
903
904 errno = 0;
905 #ifdef __solaris__
906 RESTARTABLE_RETURN_PTR(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen), p);
907 #else
908 RESTARTABLE(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p), res);
909 #endif
910
911 if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
912 /* not found or error */
913 if (errno == 0)
914 errno = ENOENT;
915 throwUnixException(env, errno);
916 } else {
917 jsize len = strlen(p->pw_name);
918 result = (*env)->NewByteArray(env, len);
919 if (result != NULL) {
920 (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name));
921 }
922 }
923 free(pwbuf);
924 }
925
926 return result;
927 }
928
929
930 JNIEXPORT jbyteArray JNICALL
931 Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid)
932 {
933 jbyteArray result = NULL;
934 int buflen;
949 JNU_ThrowOutOfMemoryError(env, "native heap");
950 return NULL;
951 }
952
953 errno = 0;
954 #ifdef __solaris__
955 RESTARTABLE_RETURN_PTR(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen), g);
956 #else
957 RESTARTABLE(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g), res);
958 #endif
959
960 retry = 0;
961 if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
962 /* not found or error */
963 if (errno == ERANGE) {
964 /* insufficient buffer size so need larger buffer */
965 buflen += ENT_BUF_SIZE;
966 retry = 1;
967 } else {
968 if (errno == 0)
969 errno = ENOENT;
970 throwUnixException(env, errno);
971 }
972 } else {
973 jsize len = strlen(g->gr_name);
974 result = (*env)->NewByteArray(env, len);
975 if (result != NULL) {
976 (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name));
977 }
978 }
979
980 free(grbuf);
981
982 } while (retry);
983
984 return result;
985 }
986
987 JNIEXPORT jint JNICALL
988 Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this,
989 jlong nameAddress)
|
42 #include <strings.h>
43 #endif
44
45 #ifdef __linux__
46 #include <string.h>
47 #endif
48
49 #ifdef _ALLBSD_SOURCE
50 #include <string.h>
51
52 #define stat64 stat
53 #define statvfs64 statvfs
54
55 #define open64 open
56 #define fstat64 fstat
57 #define lstat64 lstat
58 #define dirent64 dirent
59 #define readdir64_r readdir_r
60 #endif
61
62 /* Needed for strerror */
63 #if defined(_AIX) || defined (__hpux__)
64 #include <string.h>
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; \
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;
99 static jfieldID attrs_st_mtime;
100 static jfieldID attrs_st_ctime;
101
102 static jfieldID attrs_f_frsize;
103 static jfieldID attrs_f_blocks;
104 static jfieldID attrs_f_bfree;
105 static jfieldID attrs_f_bavail;
106
107 static jfieldID entry_name;
108 static jfieldID entry_dir;
109 static jfieldID entry_fstype;
110 static jfieldID entry_options;
111 static jfieldID entry_dev;
112
113 /* AIX and HP-UX need a couple more references for futimes emulation */
114 #if defined(_AIX) || defined (__hpux__)
115 static jmethodID disp_copy2buf;
116 static jfieldID buffer_address;
117 static jmethodID buffer_release;
118 #endif
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.
201
202 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
203 if (clazz == NULL) {
204 return 0;
205 }
206 attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J");
207 attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J");
208 attrs_f_bfree = (*env)->GetFieldID(env, clazz, "f_bfree", "J");
209 attrs_f_bavail = (*env)->GetFieldID(env, clazz, "f_bavail", "J");
210
211 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
212 if (clazz == NULL) {
213 return 0;
214 }
215 entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
216 entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
217 entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
218 entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
219 entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
220
221 /* AIX and HP-UX need a couple more references for futimes emulation */
222 #if defined(_AIX) || defined (__hpux__)
223 disp_copy2buf = (*env)->GetStaticMethodID(env, this, "copyToNativeBuffer", "(Lsun/nio/fs/UnixPath;)Lsun/nio/fs/NativeBuffer;");
224 clazz = (*env)->FindClass(env, "sun/nio/fs/NativeBuffer");
225 if (clazz == NULL) {
226 return 0;
227 }
228 buffer_address = (*env)->GetFieldID(env, clazz, "address", "J");
229 buffer_release = (*env)->GetMethodID(env, clazz, "release", "()V");
230 #endif
231
232 /* system calls that might not be available at run time */
233
234 #if (defined(__solaris__) && defined(_LP64)) || defined(_ALLBSD_SOURCE)
235 /* Solaris 64-bit does not have openat64/fstatat64 */
236 my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
237 my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
238 #else
239 my_openat64_func = (openat64_func*) dlsym(RTLD_DEFAULT, "openat64");
240 my_fstatat64_func = (fstatat64_func*) dlsym(RTLD_DEFAULT, "fstatat64");
241 #endif
242 my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
243 my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
244 my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
245 my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir");
246
247 #if defined(FSTATAT64_SYSCALL_AVAILABLE)
248 /* fstatat64 missing from glibc */
249 if (my_fstatat64_func == NULL)
250 my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
251 #endif
269 char* cwd = getcwd(buf, sizeof(buf));
270 if (cwd == NULL) {
271 throwUnixException(env, errno);
272 } else {
273 jsize len = (jsize)strlen(buf);
274 result = (*env)->NewByteArray(env, len);
275 if (result != NULL) {
276 (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)buf);
277 }
278 }
279 return result;
280 }
281
282 JNIEXPORT jbyteArray
283 Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
284 {
285 char* msg;
286 jsize len;
287 jbyteArray bytes;
288
289 /* strerror is not thread-safe on AIX */
290 #ifdef _AIX
291 char buffer[256];
292 msg = (strerror_r((int)error, buffer, 256) == 0) ? buffer : "Error while calling strerror_r";
293 #else
294 msg = strerror((int)error);
295 #endif
296 len = strlen(msg);
297 bytes = (*env)->NewByteArray(env, len);
298 if (bytes != NULL) {
299 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
300 }
301 return bytes;
302 }
303
304 JNIEXPORT jint
305 Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) {
306
307 int res = -1;
308
309 RESTARTABLE(dup((int)fd), res);
310 if (res == -1) {
311 throwUnixException(env, errno);
312 }
313 return (jint)res;
314 }
315
562 JNIEXPORT void JNICALL
563 Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this,
564 jlong pathAddress, jlong accessTime, jlong modificationTime)
565 {
566 int err;
567 struct timeval times[2];
568 const char* path = (const char*)jlong_to_ptr(pathAddress);
569
570 times[0].tv_sec = accessTime / 1000000;
571 times[0].tv_usec = accessTime % 1000000;
572
573 times[1].tv_sec = modificationTime / 1000000;
574 times[1].tv_usec = modificationTime % 1000000;
575
576 RESTARTABLE(utimes(path, ×[0]), err);
577 if (err == -1) {
578 throwUnixException(env, errno);
579 }
580 }
581
582 /* Added path of file "filedes" for platform ports (only needed on AIX and HPUX) */
583 JNIEXPORT void JNICALL
584 Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint filedes,
585 jlong accessTime, jlong modificationTime, jobject path)
586 {
587 struct timeval times[2];
588 int err = 0;
589
590 times[0].tv_sec = accessTime / 1000000;
591 times[0].tv_usec = accessTime % 1000000;
592
593 times[1].tv_sec = modificationTime / 1000000;
594 times[1].tv_usec = modificationTime % 1000000;
595
596 #ifdef _ALLBSD_SOURCE
597 RESTARTABLE(futimes(filedes, ×[0]), err);
598
599 if (err == -1) {
600 throwUnixException(env, errno);
601 }
602 #else
603 if (my_futimesat_func != NULL) {
604 RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err);
605
606 if (err == -1) {
607 throwUnixException(env, errno);
608 }
609 }
610 /* AIX and HP-UX does not provide futimes as system call => use utimes instead */
611 #if defined(_AIX) || defined (__hpux__)
612 else {
613 jobject buffer = (*env)->CallStaticObjectMethod(env, this, disp_copy2buf, path);
614 jlong path_address = (*env)->GetLongField(env, buffer, buffer_address);
615 const char* path = (const char*)jlong_to_ptr(path_address);
616 RESTARTABLE(utimes(path, ×[0]), err);
617 if (err == -1) {
618 throwUnixException(env, errno);
619 }
620 (*env)->CallVoidMethod(env, buffer, buffer_release);
621 }
622 #else
623 else {
624 JNU_ThrowInternalError(env, "my_ftimesat_func is NULL");
625 return;
626 }
627 #endif
628
629 #endif
630 }
631
632 JNIEXPORT jlong JNICALL
633 Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
634 jlong pathAddress)
635 {
636 DIR* dir;
637 const char* path = (const char*)jlong_to_ptr(pathAddress);
638
639 /* EINTR not listed as a possible error */
640 dir = opendir(path);
641 if (dir == NULL) {
642 throwUnixException(env, errno);
643 }
644 return ptr_to_jlong(dir);
645 }
646
647 JNIEXPORT jlong JNICALL
648 Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) {
649 DIR* dir;
661 return ptr_to_jlong(dir);
662 }
663
664 JNIEXPORT void JNICALL
665 Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) {
666 DIR* dirp = jlong_to_ptr(dir);
667
668 if (closedir(dirp) == -1 && errno != EINTR) {
669 throwUnixException(env, errno);
670 }
671 }
672
673 JNIEXPORT jbyteArray JNICALL
674 Java_sun_nio_fs_UnixNativeDispatcher_readdir(JNIEnv* env, jclass this, jlong value) {
675 struct dirent64* result;
676 struct {
677 struct dirent64 buf;
678 char name_extra[PATH_MAX + 1 - sizeof result->d_name];
679 } entry;
680 struct dirent64* ptr = &entry.buf;
681
682 int res;
683 DIR* dirp = jlong_to_ptr(value);
684
685 /* EINTR not listed as a possible error */
686 /* TDB: reentrant version probably not required here */
687 res = readdir64_r(dirp, ptr, &result);
688
689 /* AIX returns EBADF for directory stream end which is no error. */
690 #ifdef _AIX
691 if (res != 0) {
692 res = (result == NULL && res == EBADF) ? 0 : errno;
693 }
694 #endif
695
696 if (res != 0) {
697 throwUnixException(env, res);
698 return NULL;
699 } else {
700 if (result == NULL) {
701 return NULL;
702 } else {
703 jsize len = strlen(ptr->d_name);
704 jbyteArray bytes = (*env)->NewByteArray(env, len);
705 if (bytes != NULL) {
706 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)(ptr->d_name));
707 }
708 return bytes;
709 }
710 }
711 }
712
713 JNIEXPORT void JNICALL
714 Java_sun_nio_fs_UnixNativeDispatcher_mkdir0(JNIEnv* env, jclass this,
715 jlong pathAddress, jint mode)
879
880 RESTARTABLE(access(path, (int)amode), err);
881 if (err == -1) {
882 throwUnixException(env, errno);
883 }
884 }
885
886 JNIEXPORT void JNICALL
887 Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
888 jlong pathAddress, jobject attrs)
889 {
890 int err;
891 struct statvfs64 buf;
892 const char* path = (const char*)jlong_to_ptr(pathAddress);
893
894
895 RESTARTABLE(statvfs64(path, &buf), err);
896 if (err == -1) {
897 throwUnixException(env, errno);
898 } else {
899 /* Number of blocks (f_blocks) may be too big for signed long on AIX for /proc. */
900 #ifdef _AIX
901 if (buf.f_blocks == ULONG_MAX) {
902 buf.f_blocks = 0;
903 }
904 /* Number of free or available blocks can never exceed total number of blocks (seen on /QOpt as400) */
905 if (buf.f_blocks == 0) {
906 buf.f_bfree = 0;
907 buf.f_bavail = 0;
908 }
909 #endif
910 (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize));
911 (*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks));
912 (*env)->SetLongField(env, attrs, attrs_f_bfree, long_to_jlong(buf.f_bfree));
913 (*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail));
914 }
915 }
916
917 JNIEXPORT jlong JNICALL
918 Java_sun_nio_fs_UnixNativeDispatcher_pathconf0(JNIEnv* env, jclass this,
919 jlong pathAddress, jint name)
920 {
921 long err;
922 const char* path = (const char*)jlong_to_ptr(pathAddress);
923
924 err = pathconf(path, (int)name);
925 if (err == -1) {
926 throwUnixException(env, errno);
927 }
928 return (jlong)err;
929 }
966 if (buflen == -1)
967 buflen = ENT_BUF_SIZE;
968 pwbuf = (char*)malloc(buflen);
969 if (pwbuf == NULL) {
970 JNU_ThrowOutOfMemoryError(env, "native heap");
971 } else {
972 struct passwd pwent;
973 struct passwd* p = NULL;
974 int res = 0;
975
976 errno = 0;
977 #ifdef __solaris__
978 RESTARTABLE_RETURN_PTR(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen), p);
979 #else
980 RESTARTABLE(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p), res);
981 #endif
982
983 if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
984 /* not found or error */
985 if (errno == 0)
986 /* getpwuid_r returns ESRCH if user does not exist on AIX */
987 #ifdef _AIX
988 errno = ESRCH;
989 #else
990 errno = ENOENT;
991 #endif
992 throwUnixException(env, errno);
993 } else {
994 jsize len = strlen(p->pw_name);
995 result = (*env)->NewByteArray(env, len);
996 if (result != NULL) {
997 (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name));
998 }
999 }
1000 free(pwbuf);
1001 }
1002
1003 return result;
1004 }
1005
1006
1007 JNIEXPORT jbyteArray JNICALL
1008 Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid)
1009 {
1010 jbyteArray result = NULL;
1011 int buflen;
1026 JNU_ThrowOutOfMemoryError(env, "native heap");
1027 return NULL;
1028 }
1029
1030 errno = 0;
1031 #ifdef __solaris__
1032 RESTARTABLE_RETURN_PTR(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen), g);
1033 #else
1034 RESTARTABLE(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g), res);
1035 #endif
1036
1037 retry = 0;
1038 if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
1039 /* not found or error */
1040 if (errno == ERANGE) {
1041 /* insufficient buffer size so need larger buffer */
1042 buflen += ENT_BUF_SIZE;
1043 retry = 1;
1044 } else {
1045 if (errno == 0)
1046 /* getgrgid_r returns ESRCH if group does not exist on AIX */
1047 #ifdef _AIX
1048 errno = ESRCH;
1049 #else
1050 errno = ENOENT;
1051 #endif
1052 throwUnixException(env, errno);
1053 }
1054 } else {
1055 jsize len = strlen(g->gr_name);
1056 result = (*env)->NewByteArray(env, len);
1057 if (result != NULL) {
1058 (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name));
1059 }
1060 }
1061
1062 free(grbuf);
1063
1064 } while (retry);
1065
1066 return result;
1067 }
1068
1069 JNIEXPORT jint JNICALL
1070 Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this,
1071 jlong nameAddress)
|