src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c

Print this page
rev 8725 : 8024854: Basic changes and files to build the class library on AIX
Contributed-by: luchsh@linux.vnet.ibm.com, spoole@linux.vnet.ibm.com, thomas.stuefe@sap.com
Reviewed-by: alanb, prr, sla, chegar, michaelm, mullan

@@ -40,11 +40,11 @@
 
 #ifdef __solaris__
 #include <strings.h>
 #endif
 
-#ifdef __linux__
+#if defined(__linux__) || defined(_AIX)
 #include <string.h>
 #endif
 
 #ifdef _ALLBSD_SOURCE
 #include <string.h>

@@ -292,11 +292,17 @@
 {
     char* msg;
     jsize len;
     jbyteArray bytes;
 
+#ifdef _AIX
+    /* strerror() is not thread-safe on AIX so we have to use strerror_r() */
+    char buffer[256];
+    msg = (strerror_r((int)error, buffer, 256) == 0) ? buffer : "Error while calling strerror_r";
+#else
     msg = strerror((int)error);
+#endif
     len = strlen(msg);
     bytes = (*env)->NewByteArray(env, len);
     if (bytes != NULL) {
         (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
     }

@@ -672,10 +678,19 @@
     DIR* dirp = jlong_to_ptr(value);
 
     /* EINTR not listed as a possible error */
     /* TDB: reentrant version probably not required here */
     res = readdir64_r(dirp, ptr, &result);
+
+#ifdef _AIX
+    /* On AIX, readdir_r() returns EBADF (i.e. '9') and sets 'result' to NULL for the */
+    /* directory stream end. Otherwise, 'errno' will contain the error code. */
+    if (res != 0) {
+        res = (result == NULL && res == EBADF) ? 0 : errno;
+    }
+#endif
+
     if (res != 0) {
         throwUnixException(env, res);
         return NULL;
     } else {
         if (result == NULL) {

@@ -875,10 +890,22 @@
 
     RESTARTABLE(statvfs64(path, &buf), err);
     if (err == -1) {
         throwUnixException(env, errno);
     } else {
+#ifdef _AIX
+        /* AIX returns ULONG_MAX in buf.f_blocks for the /proc file system. */
+        /* This is too big for a Java signed long and fools various tests.  */
+        if (buf.f_blocks == ULONG_MAX) {
+            buf.f_blocks = 0;
+        }
+        /* The number of free or available blocks can never exceed the total number of blocks */
+        if (buf.f_blocks == 0) {
+            buf.f_bfree = 0;
+            buf.f_bavail = 0;
+        }
+#endif
         (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize));
         (*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks));
         (*env)->SetLongField(env, attrs, attrs_f_bfree,  long_to_jlong(buf.f_bfree));
         (*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail));
     }

@@ -951,11 +978,16 @@
         #endif
 
         if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
             /* not found or error */
             if (errno == 0)
+#ifdef _AIX
+                /* On AIX, getpwuid_r returns ESRCH if user does not exist. */
+                errno = ESRCH;
+#else
                 errno = ENOENT;
+#endif
             throwUnixException(env, errno);
         } else {
             jsize len = strlen(p->pw_name);
             result = (*env)->NewByteArray(env, len);
             if (result != NULL) {

@@ -1006,11 +1038,16 @@
                 /* insufficient buffer size so need larger buffer */
                 buflen += ENT_BUF_SIZE;
                 retry = 1;
             } else {
                 if (errno == 0)
+#ifdef _AIX
+                    /* On AIX, getgrgid_r returns ESRCH if group does not exist. */
+                    errno = ESRCH;
+#else
                     errno = ENOENT;
+#endif
                 throwUnixException(env, errno);
             }
         } else {
             jsize len = strlen(g->gr_name);
             result = (*env)->NewByteArray(env, len);