Home | History | Annotate | Download | only in jni
      1 /* //device/libs/android_runtime/android_util_Process.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "FileUtils"
     19 
     20 #include <utils/Log.h>
     21 
     22 #include <android_runtime/AndroidRuntime.h>
     23 
     24 #include "JNIHelp.h"
     25 
     26 #include <sys/errno.h>
     27 #include <sys/stat.h>
     28 #include <sys/types.h>
     29 #include <fcntl.h>
     30 #include <signal.h>
     31 
     32 #if HAVE_ANDROID_OS
     33 #include <sys/ioctl.h>
     34 #include <linux/msdos_fs.h>
     35 #endif
     36 
     37 namespace android {
     38 
     39 static jclass gFileStatusClass;
     40 static jfieldID gFileStatusDevFieldID;
     41 static jfieldID gFileStatusInoFieldID;
     42 static jfieldID gFileStatusModeFieldID;
     43 static jfieldID gFileStatusNlinkFieldID;
     44 static jfieldID gFileStatusUidFieldID;
     45 static jfieldID gFileStatusGidFieldID;
     46 static jfieldID gFileStatusSizeFieldID;
     47 static jfieldID gFileStatusBlksizeFieldID;
     48 static jfieldID gFileStatusBlocksFieldID;
     49 static jfieldID gFileStatusAtimeFieldID;
     50 static jfieldID gFileStatusMtimeFieldID;
     51 static jfieldID gFileStatusCtimeFieldID;
     52 
     53 jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
     54                                          jstring file, jint mode,
     55                                          jint uid, jint gid)
     56 {
     57     #if HAVE_ANDROID_OS
     58     const jchar* str = env->GetStringCritical(file, 0);
     59     String8 file8;
     60     if (str) {
     61         file8 = String8(str, env->GetStringLength(file));
     62         env->ReleaseStringCritical(file, str);
     63     }
     64     if (file8.size() <= 0) {
     65         return ENOENT;
     66     }
     67     if (uid >= 0 || gid >= 0) {
     68         int res = chown(file8.string(), uid, gid);
     69         if (res != 0) {
     70             return errno;
     71         }
     72     }
     73     return chmod(file8.string(), mode) == 0 ? 0 : errno;
     74     #else
     75     return ENOSYS;
     76     #endif
     77 }
     78 
     79 jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
     80                                          jstring file, jintArray outArray)
     81 {
     82     #if HAVE_ANDROID_OS
     83     const jchar* str = env->GetStringCritical(file, 0);
     84     String8 file8;
     85     if (str) {
     86         file8 = String8(str, env->GetStringLength(file));
     87         env->ReleaseStringCritical(file, str);
     88     }
     89     if (file8.size() <= 0) {
     90         return ENOENT;
     91     }
     92     struct stat st;
     93     if (stat(file8.string(), &st) != 0) {
     94         return errno;
     95     }
     96     jint* array = (jint*)env->GetPrimitiveArrayCritical(outArray, 0);
     97     if (array) {
     98         int len = env->GetArrayLength(outArray);
     99         if (len >= 1) {
    100             array[0] = st.st_mode;
    101         }
    102         if (len >= 2) {
    103             array[1] = st.st_uid;
    104         }
    105         if (len >= 3) {
    106             array[2] = st.st_gid;
    107         }
    108     }
    109     env->ReleasePrimitiveArrayCritical(outArray, array, 0);
    110     return 0;
    111     #else
    112     return ENOSYS;
    113     #endif
    114 }
    115 
    116 jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
    117 {
    118     #if HAVE_ANDROID_OS
    119     if (path == NULL) {
    120         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    121         return -1;
    122     }
    123     const char *pathStr = env->GetStringUTFChars(path, NULL);
    124     int result = -1;
    125     // only if our system supports this ioctl
    126     #ifdef VFAT_IOCTL_GET_VOLUME_ID
    127     int fd = open(pathStr, O_RDONLY);
    128     if (fd >= 0) {
    129         result = ioctl(fd, VFAT_IOCTL_GET_VOLUME_ID);
    130         close(fd);
    131     }
    132     #endif
    133 
    134     env->ReleaseStringUTFChars(path, pathStr);
    135     return result;
    136     #else
    137     return -1;
    138     #endif
    139 }
    140 
    141 jboolean android_os_FileUtils_getFileStatus(JNIEnv* env, jobject clazz, jstring path, jobject fileStatus) {
    142     const char* pathStr = env->GetStringUTFChars(path, NULL);
    143     jboolean ret = false;
    144 
    145     struct stat s;
    146     int res = stat(pathStr, &s);
    147     if (res == 0) {
    148         ret = true;
    149         if (fileStatus != NULL) {
    150             env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
    151             env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
    152             env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
    153             env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
    154             env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
    155             env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
    156             env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
    157             env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
    158             env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
    159             env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
    160             env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
    161             env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
    162         }
    163     }
    164 
    165     env->ReleaseStringUTFChars(path, pathStr);
    166 
    167     return ret;
    168 }
    169 
    170 static const JNINativeMethod methods[] = {
    171     {"setPermissions",  "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
    172     {"getPermissions",  "(Ljava/lang/String;[I)I", (void*)android_os_FileUtils_getPermissions},
    173     {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
    174     {"getFileStatus",  "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z", (void*)android_os_FileUtils_getFileStatus},
    175 };
    176 
    177 static const char* const kFileUtilsPathName = "android/os/FileUtils";
    178 
    179 int register_android_os_FileUtils(JNIEnv* env)
    180 {
    181     jclass clazz;
    182 
    183     clazz = env->FindClass(kFileUtilsPathName);
    184     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.FileUtils");
    185 
    186     gFileStatusClass = env->FindClass("android/os/FileUtils$FileStatus");
    187     LOG_FATAL_IF(gFileStatusClass == NULL, "Unable to find class android.os.FileUtils$FileStatus");
    188 
    189     gFileStatusDevFieldID = env->GetFieldID(gFileStatusClass, "dev", "I");
    190     gFileStatusInoFieldID = env->GetFieldID(gFileStatusClass, "ino", "I");
    191     gFileStatusModeFieldID = env->GetFieldID(gFileStatusClass, "mode", "I");
    192     gFileStatusNlinkFieldID = env->GetFieldID(gFileStatusClass, "nlink", "I");
    193     gFileStatusUidFieldID = env->GetFieldID(gFileStatusClass, "uid", "I");
    194     gFileStatusGidFieldID = env->GetFieldID(gFileStatusClass, "gid", "I");
    195     gFileStatusSizeFieldID = env->GetFieldID(gFileStatusClass, "size", "J");
    196     gFileStatusBlksizeFieldID = env->GetFieldID(gFileStatusClass, "blksize", "I");
    197     gFileStatusBlocksFieldID = env->GetFieldID(gFileStatusClass, "blocks", "J");
    198     gFileStatusAtimeFieldID = env->GetFieldID(gFileStatusClass, "atime", "J");
    199     gFileStatusMtimeFieldID = env->GetFieldID(gFileStatusClass, "mtime", "J");
    200     gFileStatusCtimeFieldID = env->GetFieldID(gFileStatusClass, "ctime", "J");
    201 
    202     return AndroidRuntime::registerNativeMethods(
    203         env, kFileUtilsPathName,
    204         methods, NELEM(methods));
    205 }
    206 
    207 }
    208 
    209