7014794: (file) lookupPrincipalByGroupName fails to find large NIS groups

Reviewed-by: chegar
This commit is contained in:
Alan Bateman 2011-02-03 13:37:42 +00:00
parent 1d6cc8fc42
commit 6232632ef8

View File

@ -55,12 +55,23 @@
#include "sun_nio_fs_UnixNativeDispatcher.h" #include "sun_nio_fs_UnixNativeDispatcher.h"
/**
* Size of password or group entry when not available via sysconf
*/
#define ENT_BUF_SIZE 1024
#define RESTARTABLE(_cmd, _result) do { \ #define RESTARTABLE(_cmd, _result) do { \
do { \ do { \
_result = _cmd; \ _result = _cmd; \
} while((_result == -1) && (errno == EINTR)); \ } while((_result == -1) && (errno == EINTR)); \
} while(0) } while(0)
#define RESTARTABLE_RETURN_PTR(_cmd, _result) do { \
do { \
_result = _cmd; \
} while((_result == NULL) && (errno == EINTR)); \
} while(0)
static jfieldID attrs_st_mode; static jfieldID attrs_st_mode;
static jfieldID attrs_st_ino; static jfieldID attrs_st_ino;
static jfieldID attrs_st_dev; static jfieldID attrs_st_dev;
@ -858,37 +869,41 @@ Java_sun_nio_fs_UnixNativeDispatcher_getpwuid(JNIEnv* env, jclass this, jint uid
{ {
jbyteArray result = NULL; jbyteArray result = NULL;
int buflen; int buflen;
char* pwbuf;
/* allocate buffer for password record */
buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
if (buflen == -1) { if (buflen == -1)
throwUnixException(env, errno); buflen = ENT_BUF_SIZE;
pwbuf = (char*)malloc(buflen);
if (pwbuf == NULL) {
JNU_ThrowOutOfMemoryError(env, "native heap");
} else { } else {
char* pwbuf = (char*)malloc(buflen); struct passwd pwent;
if (pwbuf == NULL) { struct passwd* p = NULL;
JNU_ThrowOutOfMemoryError(env, "native heap"); int res = 0;
} else {
struct passwd pwent;
struct passwd* p;
int res = 0;
#ifdef __solaris__ errno = 0;
p = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen); #ifdef __solaris__
#else RESTARTABLE_RETURN_PTR(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen), p);
res = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p); #else
#endif RESTARTABLE(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p), res);
#endif
if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
/* not found or error */
if (errno != 0 && errno != ENOENT)
throwUnixException(env, errno); throwUnixException(env, errno);
} else { } else {
jsize len = strlen(p->pw_name); jsize len = strlen(p->pw_name);
result = (*env)->NewByteArray(env, len); result = (*env)->NewByteArray(env, len);
if (result != NULL) { if (result != NULL) {
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name)); (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name));
}
} }
free(pwbuf);
} }
free(pwbuf);
} }
return result; return result;
} }
@ -898,36 +913,55 @@ Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid
{ {
jbyteArray result = NULL; jbyteArray result = NULL;
int buflen; int buflen;
int retry;
/* initial size of buffer for group record */
buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX); buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX);
if (buflen == -1) { if (buflen == -1)
throwUnixException(env, errno); buflen = ENT_BUF_SIZE;
} else {
do {
struct group grent;
struct group* g = NULL;
int res = 0;
char* grbuf = (char*)malloc(buflen); char* grbuf = (char*)malloc(buflen);
if (grbuf == NULL) { if (grbuf == NULL) {
JNU_ThrowOutOfMemoryError(env, "native heap"); JNU_ThrowOutOfMemoryError(env, "native heap");
} else { return NULL;
struct group grent; }
struct group* g;
int res = 0;
#ifdef __solaris__ errno = 0;
g = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen); #ifdef __solaris__
#else RESTARTABLE_RETURN_PTR(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen), g);
res = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g); #else
#endif RESTARTABLE(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g), res);
if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { #endif
throwUnixException(env, errno);
} else { retry = 0;
jsize len = strlen(g->gr_name); if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
result = (*env)->NewByteArray(env, len); /* not found or error */
if (result != NULL) { if (errno != 0 && errno != ENOENT) {
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name)); if (errno == ERANGE) {
/* insufficient buffer size so need larger buffer */
buflen += ENT_BUF_SIZE;
retry = 1;
} else {
throwUnixException(env, errno);
} }
} }
free(grbuf); } else {
jsize len = strlen(g->gr_name);
result = (*env)->NewByteArray(env, len);
if (result != NULL) {
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name));
}
} }
}
free(grbuf);
} while (retry);
return result; return result;
} }
@ -938,35 +972,36 @@ Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this,
jint uid = -1; jint uid = -1;
int buflen; int buflen;
char* pwbuf; char* pwbuf;
struct passwd pwent;
struct passwd* p;
int res = 0;
const char* name = (const char*)jlong_to_ptr(nameAddress);
/* allocate buffer for password record */
buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
if (buflen == -1) { if (buflen == -1)
throwUnixException(env, errno); buflen = ENT_BUF_SIZE;
return -1;
}
pwbuf = (char*)malloc(buflen); pwbuf = (char*)malloc(buflen);
if (pwbuf == NULL) { if (pwbuf == NULL) {
JNU_ThrowOutOfMemoryError(env, "native heap"); JNU_ThrowOutOfMemoryError(env, "native heap");
return -1;
}
#ifdef __solaris__
p = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen);
#else
res = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p);
#endif
if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
/* not found or error */
} else { } else {
uid = p->pw_uid; struct passwd pwent;
} struct passwd* p = NULL;
int res = 0;
const char* name = (const char*)jlong_to_ptr(nameAddress);
free(pwbuf); errno = 0;
#ifdef __solaris__
RESTARTABLE_RETURN_PTR(getpwnam_r(name, &pwent, pwbuf, (size_t)buflen), p);
#else
RESTARTABLE(getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p), res);
#endif
if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') {
/* not found or error */
if (errno != 0 && errno != ENOENT)
throwUnixException(env, errno);
} else {
uid = p->pw_uid;
}
free(pwbuf);
}
return uid; return uid;
} }
@ -976,36 +1011,52 @@ Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0(JNIEnv* env, jclass this,
jlong nameAddress) jlong nameAddress)
{ {
jint gid = -1; jint gid = -1;
int buflen; int buflen, retry;
char* grbuf;
struct group grent;
struct group* g;
int res = 0;
const char* name = (const char*)jlong_to_ptr(nameAddress);
/* initial size of buffer for group record */
buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX); buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX);
if (buflen == -1) { if (buflen == -1)
throwUnixException(env, errno); buflen = ENT_BUF_SIZE;
return -1;
}
grbuf = (char*)malloc(buflen);
if (grbuf == NULL) {
JNU_ThrowOutOfMemoryError(env, "native heap");
return -1;
}
#ifdef __solaris__ do {
g = getgrnam_r(name, &grent, grbuf, (size_t)buflen); struct group grent;
#else struct group* g = NULL;
res = getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g); int res = 0;
#endif char *grbuf;
const char* name = (const char*)jlong_to_ptr(nameAddress);
if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { grbuf = (char*)malloc(buflen);
/* not found or error */ if (grbuf == NULL) {
} else { JNU_ThrowOutOfMemoryError(env, "native heap");
gid = g->gr_gid; return -1;
} }
free(grbuf);
errno = 0;
#ifdef __solaris__
RESTARTABLE_RETURN_PTR(getgrnam_r(name, &grent, grbuf, (size_t)buflen), g);
#else
RESTARTABLE(getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g), res);
#endif
retry = 0;
if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') {
/* not found or error */
if (errno != 0 && errno != ENOENT) {
if (errno == ERANGE) {
/* insufficient buffer size so need larger buffer */
buflen += ENT_BUF_SIZE;
retry = 1;
} else {
throwUnixException(env, errno);
}
}
} else {
gid = g->gr_gid;
}
free(grbuf);
} while (retry);
return gid; return gid;
} }