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