blob: 32758b9ad4cdf34532b6d297f093f17678832c2d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <jni.h>
#if defined MACOSX
#include <CoreServices/CoreServices.h>
#endif
#include "unixfile.h"
/* The lstat stat field st_mode. */
static jfieldID attrs_st_mode;
/* The lstat stat field st_size. */
static jfieldID attrs_st_size;
/* The lstat stat field st_mtime_sec. */
static jfieldID attrs_st_mtime;
/* The lstat stat field st_mtime_nsec divided by 1 000 000. Only filled on Linux based operating systems. */
static jfieldID attrs_st_mtime_msec;
/* Only filled on MACOSX. */
static jfieldID attrs_st_flags;
/*
* Class: Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_initializeStructStatFieldIDs
* Method: initializeStructStatFieldIDs
* Signature: ()V
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_initializeStructStatFieldIDs
(JNIEnv *env, jclass clazz)
{
jclass structStatClass = (*env)->FindClass(env, "org/eclipse/core/internal/filesystem/local/unix/StructStat");
attrs_st_mode = (*env)->GetFieldID(env, structStatClass, "st_mode", "I");
attrs_st_size = (*env)->GetFieldID(env, structStatClass, "st_size", "J");
attrs_st_mtime = (*env)->GetFieldID(env, structStatClass, "st_mtime", "J");
#ifdef MACOSX
attrs_st_flags = (*env)->GetFieldID(env, structStatClass, "st_flags", "J");
#endif
#ifndef MACOSX
attrs_st_mtime_msec = (*env)->GetFieldID(env, structStatClass, "st_mtime_msec", "J");
#endif
}
/*
* Get a null-terminated byte array from a java byte array. The returned bytearray
* needs to be freed when not used anymore. Use free(result) to do that.
*/
jbyte* getByteArray(JNIEnv *env, jbyteArray target)
{
unsigned int len;
jbyte *temp, *result;
temp = (*env)->GetByteArrayElements(env, target, 0);
len = (*env)->GetArrayLength(env, target);
result = malloc((len + 1) * sizeof(jbyte));
memcpy(result, temp, len * sizeof(jbyte));
result[len] = '\0';
(*env)->ReleaseByteArrayElements(env, target, temp, 0);
return result;
}
/*
* Fills StructStat object with data from struct stat.
*/
jint convertStatToObject(JNIEnv *env, struct stat info, jobject stat_object)
{
jclass cls;
jfieldID fid;
jboolean readOnly;
cls = (*env)->GetObjectClass(env, stat_object);
if (cls == 0) return -1;
if (attrs_st_mode == 0) return -1;
(*env)->SetIntField(env, stat_object, attrs_st_mode, info.st_mode);
if (attrs_st_size == 0) return -1;
(*env)->SetLongField(env, stat_object, attrs_st_size, info.st_size);
if (attrs_st_mtime == 0) return -1;
(*env)->SetLongField(env, stat_object, attrs_st_mtime, info.st_mtime);
#ifndef MACOSX
if (attrs_st_mtime_msec == 0) return -1;
(*env)->SetLongField(env, stat_object, attrs_st_mtime_msec, (info.st_mtim.tv_nsec / (1000 * 1000)));
#endif
#ifdef MACOSX
if (attrs_st_flags == 0) return -1;
(*env)->SetLongField(env, stat_object, attrs_st_flags, info.st_flags);
#endif
return 0;
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: chmod
* Signature: ([BI)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_chmod
(JNIEnv *env, jclass clazz, jbyteArray path, jint mode)
{
int code;
char *name;
name = (char*) getByteArray(env, path);
code = chmod(name, mode);
free(name);
return code;
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: chflags
* Signature: ([BI)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_chflags
(JNIEnv *env, jclass clazz, jbyteArray path, jint flags)
{
#ifdef MACOSX
int code;
char *name;
name = (char*) getByteArray(env, path);
code = chflags(name, flags);
free(name);
return code;
#else
return -1;
#endif
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: stat
* Signature: ([BLorg/eclipse/core/internal/filesystem/local/unix/StructStat;)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_stat
(JNIEnv *env, jclass clazz, jbyteArray path, jobject buf)
{
jint code;
char *name;
struct stat info;
name = (char*) getByteArray(env, path);
code = stat(name, &info);
free(name);
if (code != -1)
return convertStatToObject(env, info, buf);
else
return code;
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: lstat
* Signature: ([BLorg/eclipse/core/internal/filesystem/local/unix/StructStat;)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_lstat
(JNIEnv *env, jclass clazz, jbyteArray path, jobject buf)
{
jint code;
char *name;
struct stat info;
name = (char*) getByteArray(env, path);
code = lstat(name, &info);
free(name);
if (code != -1)
return convertStatToObject(env, info, buf);
else
return code;
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: readlink
* Signature: ([B[BJ)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_readlink
(JNIEnv *env, jclass clazz, jbyteArray path, jbyteArray buf, jlong bufsiz) {
jint code;
jbyte *name;
int len;
char temp[PATH_MAX+1];
jstring linkTarget = NULL;
name = getByteArray(env, path);
len = readlink((const char*)name, temp, PATH_MAX);
free(name);
if (len > 0) {
temp[len] = 0;
(*env)->SetByteArrayRegion(env, buf, 0, len, (jbyte*) temp);
}
else {
temp[0] = 0;
(*env)->SetByteArrayRegion(env, buf, 0, 0, (jbyte*) temp);
}
return len;
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: errno
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_errno
(JNIEnv *env, jclass clazz)
{
return errno;
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: libattr
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_libattr
(JNIEnv *env, jclass clazz)
{
#ifdef MACOSX
return UNICODE_SUPPORTED | CHFLAGS_SUPPORTED;
#else
return 0;
#endif
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: tounicode
* Signature: ([C)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_tounicode
(JNIEnv *env, jclass clazz, jcharArray buf)
{
#ifdef MACOSX
jchar *temp;
jsize length;
CFStringRef str_ref;
CFIndex str_size;
jbyte *unicode_bytes;
jbyteArray ret;
temp = (*env)->GetCharArrayElements(env, buf, 0);
length = (*env)->GetArrayLength(env, buf);
str_ref = CFStringCreateWithCharacters(kCFAllocatorDefault, temp, length);
str_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
unicode_bytes = (jbyte*) calloc(str_size, sizeof(jbyte));
CFStringGetCString(str_ref, (char*) unicode_bytes, str_size, kCFStringEncodingUTF8);
ret = (*env)->NewByteArray(env, str_size);
if (ret == NULL)
return NULL;
(*env)->SetByteArrayRegion(env, ret, 0, str_size, unicode_bytes);
CFRelease(str_ref);
(*env)->ReleaseCharArrayElements(env, buf, temp, 0);
free(unicode_bytes);
return ret;
#else
return NULL;
#endif
}
/*
* Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives
* Method: getflag
* Signature: ([B)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_getflag
(JNIEnv *env, jclass clazz, jbyteArray buf)
{
char *flag;
jint ret = -1;
flag = (char*) getByteArray(env, buf);
if (strcmp(flag, "PATH_MAX") == 0)
ret = PATH_MAX;
else if (strcmp(flag, "S_IFMT") == 0)
ret = S_IFMT;
else if (strcmp(flag, "S_IFLNK") == 0)
ret = S_IFLNK;
else if (strcmp(flag, "S_IFDIR") == 0)
ret = S_IFDIR;
else if (strcmp(flag, "S_IRUSR") == 0)
ret = S_IRUSR;
else if (strcmp(flag, "S_IWUSR") == 0)
ret = S_IWUSR;
else if (strcmp(flag, "S_IXUSR") == 0)
ret = S_IXUSR;
else if (strcmp(flag, "S_IRGRP") == 0)
ret = S_IRGRP;
else if (strcmp(flag, "S_IWGRP") == 0)
ret = S_IWGRP;
else if (strcmp(flag, "S_IXGRP") == 0)
ret = S_IXGRP;
else if (strcmp(flag, "S_IROTH") == 0)
ret = S_IROTH;
else if (strcmp(flag, "S_IWOTH") == 0)
ret = S_IWOTH;
else if (strcmp(flag, "S_IXOTH") == 0)
ret = S_IXOTH;
#ifdef MACOSX
else if (strcmp(flag, "UF_IMMUTABLE") == 0)
ret = UF_IMMUTABLE;
else if (strcmp(flag, "SF_IMMUTABLE") == 0)
ret = SF_IMMUTABLE;
#endif
free(flag);
return ret;
}