#include "Symlink.h" #include #include #include #include /* #include */ #define JNI_COMMIT_AND_RELEASE 0 #define FAILURE_GET_PATH 1 #define FAILURE_LSTAT 2 #define FAILURE_NEW_BUF 3 #define FAILURE_GET_BUF 4 #define FAILURE_READLINK 5 #define FAILURE_SIZE_MISMATCH 6 #define FAILURE_MALLOC_BUF 7 #define FAILURE_SYMLINK 8 jint packStatus(jint failure, jint status) { if (failure == 0) return status ; else return -((failure * 65536) + status) ; } JNIEXPORT jint JNICALL Java_Symlink_readlink(JNIEnv *env, jclass cl, jstring pathStr, jobjectArray bufHolder) { int failure ; // 0 is success int status = 0 ; const jbyte *path = (*env)->GetStringUTFChars(env, pathStr, NULL) ; if (path != NULL) { struct stat statbuf ; int lstatOk = lstat(path, &statbuf) ; if (lstatOk == 0) { int size = statbuf.st_size ; jbyteArray bufArr = (*env)->NewByteArray(env, size) ; if (bufArr != NULL) { jbyte *buf = (*env)->GetByteArrayElements(env, bufArr, NULL) ; if (buf != NULL) { int bufReleaseMode ; int actualsize = readlink(path, buf, size) ; if (actualsize > -1) { if (actualsize == size) { (*env)->SetObjectArrayElement(env, bufHolder, 0, bufArr) ; failure = 0 ; // success! status = size ; bufReleaseMode = JNI_COMMIT_AND_RELEASE ; } else { failure = FAILURE_SIZE_MISMATCH ; bufReleaseMode = JNI_ABORT ; } } else { failure = FAILURE_READLINK ; status = errno ; bufReleaseMode = JNI_ABORT ; } (*env)->ReleaseByteArrayElements(env, bufArr, buf, bufReleaseMode) ; } else { failure = FAILURE_GET_BUF ; // OutOfMemoryError will already have been thrown } } else { failure = FAILURE_NEW_BUF ; // OutOfMemoryError will already have been thrown } } else { failure = FAILURE_LSTAT ; status = errno ; } (*env)->ReleaseStringUTFChars(env, pathStr, NULL) ; } else { failure = FAILURE_GET_PATH ; // OutOfMemoryError will already have been thrown } return packStatus(failure, status) ; } JNIEXPORT jint JNICALL Java_Symlink_symlink(JNIEnv *env, jclass cl, jstring pathStr, jbyteArray bufArr) { int failure ; // 0 is success int status = 0 ; const jbyte *path = (*env)->GetStringUTFChars(env, pathStr, NULL) ; if (path != NULL) { int size = (*env)->GetArrayLength(env, bufArr) ; jbyte *buf = malloc((size + 1)) ; if (buf != NULL) { (*env)->GetByteArrayRegion(env, bufArr, 0, size, buf) ; buf[size] = (jbyte)0 ; int symlinkOk = symlink(buf, path) ; if (symlinkOk == 0) { failure = 0 ; // success! } else { failure = FAILURE_SYMLINK ; status = errno ; } free(buf) ; } else { failure = FAILURE_MALLOC_BUF ; } (*env)->ReleaseStringUTFChars(env, pathStr, NULL) ; } else { failure = FAILURE_GET_PATH ; // OutOfMemoryError will already have been thrown } return packStatus(failure, status) ; }