/** * A main() is provided so that quick testing of this * library can be done. */ int main(int argc, char **argv) { char **groupname; struct hadoop_group_info *ginfo; int ret, reentrant = !getenv("NONREENTRANT"); if (!reentrant) { fprintf(stderr, "testing non-reentrant...\n"); } ginfo = hadoop_group_info_alloc(reentrant); if (!ginfo) { fprintf(stderr, "hadoop_group_info_alloc returned NULL.\n"); return EXIT_FAILURE; } for (groupname = argv + 1; *groupname; groupname++) { gid_t gid = atoi(*groupname); if (gid == 0) { fprintf(stderr, "won't accept non-parseable group-name or gid 0: %s\n", *groupname); return EXIT_FAILURE; } ret = hadoop_group_info_fetch(ginfo, gid); if (!ret) { fprintf(stderr, "gid[%lld] : gr_name = %s\n", (long long)gid, ginfo->group.gr_name); } else { fprintf(stderr, "group[%lld] : error %d (%s)\n", (long long)gid, ret, strerror(ret)); } } hadoop_group_info_free(ginfo); return EXIT_SUCCESS; }
JNIEXPORT jobjectArray JNICALL Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_getGroupsForUser (JNIEnv *env, jclass clazz, jstring jusername) { const char *username = NULL; struct hadoop_user_info *uinfo = NULL; struct hadoop_group_info *ginfo = NULL; jstring jgroupname = NULL; int i, ret, nvalid; int pw_lock_locked = 0; jobjectArray jgroups = NULL, jnewgroups = NULL; if (pw_lock_object != NULL) { if ((*env)->MonitorEnter(env, pw_lock_object) != JNI_OK) { goto done; // exception thrown } pw_lock_locked = 1; } username = (*env)->GetStringUTFChars(env, jusername, NULL); if (username == NULL) { goto done; // exception thrown } uinfo = hadoop_user_info_alloc(); if (!uinfo) { THROW(env, "java/lang/OutOfMemoryError", NULL); goto done; } ret = hadoop_user_info_fetch(uinfo, username); if (ret == ENOENT) { jgroups = (*env)->NewObjectArray(env, 0, g_string_clazz, NULL); goto done; } ginfo = hadoop_group_info_alloc(); if (!ginfo) { THROW(env, "java/lang/OutOfMemoryError", NULL); goto done; } ret = hadoop_user_info_getgroups(uinfo); if (ret) { if (ret == ENOMEM) { THROW(env, "java/lang/OutOfMemoryError", NULL); } else { char buf[128]; snprintf(buf, sizeof(buf), "getgrouplist error %d (%s)", ret, terror(ret)); THROW(env, "java/lang/RuntimeException", buf); } goto done; } jgroups = (jobjectArray)(*env)->NewObjectArray(env, uinfo->num_gids, g_string_clazz, NULL); for (nvalid = 0, i = 0; i < uinfo->num_gids; i++) { ret = hadoop_group_info_fetch(ginfo, uinfo->gids[i]); if (ret) { logError(env, clazz, uinfo->gids[i], ret); } else { jgroupname = (*env)->NewStringUTF(env, ginfo->group.gr_name); if (!jgroupname) { // exception raised (*env)->DeleteLocalRef(env, jgroups); jgroups = NULL; goto done; } (*env)->SetObjectArrayElement(env, jgroups, nvalid++, jgroupname); // We delete the local reference once the element is in the array. // This is OK because the array has a reference to it. // Technically JNI only mandates that the JVM allow up to 16 local // references at a time (though many JVMs allow more than that.) (*env)->DeleteLocalRef(env, jgroupname); } } if (nvalid != uinfo->num_gids) { // If some group names could not be looked up, allocate a smaller array // with just the entries that could be resolved. Java has no equivalent to // realloc, so we have to do this manually. jnewgroups = (jobjectArray)(*env)->NewObjectArray(env, nvalid, (*env)->FindClass(env, "java/lang/String"), NULL); if (!jnewgroups) { // exception raised (*env)->DeleteLocalRef(env, jgroups); jgroups = NULL; goto done; } for (i = 0; i < nvalid; i++) { jgroupname = (*env)->GetObjectArrayElement(env, jgroups, i); (*env)->SetObjectArrayElement(env, jnewgroups, i, jgroupname); (*env)->DeleteLocalRef(env, jgroupname); } (*env)->DeleteLocalRef(env, jgroups); jgroups = jnewgroups; } done: if (pw_lock_locked) { (*env)->MonitorExit(env, pw_lock_object); } if (username) { (*env)->ReleaseStringUTFChars(env, jusername, username); } if (uinfo) { hadoop_user_info_free(uinfo); } if (ginfo) { hadoop_group_info_free(ginfo); } if (jgroupname) { (*env)->DeleteLocalRef(env, jgroupname); } return jgroups; }