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 #include <sys/ioctl.h>
     32 #include <linux/msdos_fs.h>
     33 
     34 namespace android {
     35 
     36 static jfieldID gFileStatusDevFieldID;
     37 static jfieldID gFileStatusInoFieldID;
     38 static jfieldID gFileStatusModeFieldID;
     39 static jfieldID gFileStatusNlinkFieldID;
     40 static jfieldID gFileStatusUidFieldID;
     41 static jfieldID gFileStatusGidFieldID;
     42 static jfieldID gFileStatusSizeFieldID;
     43 static jfieldID gFileStatusBlksizeFieldID;
     44 static jfieldID gFileStatusBlocksFieldID;
     45 static jfieldID gFileStatusAtimeFieldID;
     46 static jfieldID gFileStatusMtimeFieldID;
     47 static jfieldID gFileStatusCtimeFieldID;
     48 
     49 jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
     50                                          jstring file, jint mode,
     51                                          jint uid, jint gid)
     52 {
     53     const jchar* str = env->GetStringCritical(file, 0);
     54     String8 file8;
     55     if (str) {
     56         file8 = String8(str, env->GetStringLength(file));
     57         env->ReleaseStringCritical(file, str);
     58     }
     59     if (file8.size() <= 0) {
     60         return ENOENT;
     61     }
     62     if (uid >= 0 || gid >= 0) {
     63         int res = chown(file8.string(), uid, gid);
     64         if (res != 0) {
     65             return errno;
     66         }
     67     }
     68     return chmod(file8.string(), mode) == 0 ? 0 : errno;
     69 }
     70 
     71 jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
     72                                          jstring file, jintArray outArray)
     73 {
     74     const jchar* str = env->GetStringCritical(file, 0);
     75     String8 file8;
     76     if (str) {
     77         file8 = String8(str, env->GetStringLength(file));
     78         env->ReleaseStringCritical(file, str);
     79     }
     80     if (file8.size() <= 0) {
     81         return ENOENT;
     82     }
     83     struct stat st;
     84     if (stat(file8.string(), &st) != 0) {
     85         return errno;
     86     }
     87     jint* array = (jint*)env->GetPrimitiveArrayCritical(outArray, 0);
     88     if (array) {
     89         int len = env->GetArrayLength(outArray);
     90         if (len >= 1) {
     91             array[0] = st.st_mode;
     92         }
     93         if (len >= 2) {
     94             array[1] = st.st_uid;
     95         }
     96         if (len >= 3) {
     97             array[2] = st.st_gid;
     98         }
     99     }
    100     env->ReleasePrimitiveArrayCritical(outArray, array, 0);
    101     return 0;
    102 }
    103 
    104 jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
    105 {
    106     return umask(mask);
    107 }
    108 
    109 jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
    110 {
    111     if (path == NULL) {
    112         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    113         return -1;
    114     }
    115     const char *pathStr = env->GetStringUTFChars(path, NULL);
    116     int result = -1;
    117     // only if our system supports this ioctl
    118     #ifdef VFAT_IOCTL_GET_VOLUME_ID
    119     int fd = open(pathStr, O_RDONLY);
    120     if (fd >= 0) {
    121         result = ioctl(fd, VFAT_IOCTL_GET_VOLUME_ID);
    122         close(fd);
    123     }
    124     #endif
    125 
    126     env->ReleaseStringUTFChars(path, pathStr);
    127     return result;
    128 }
    129 
    130 jboolean android_os_FileUtils_getFileStatus(JNIEnv* env, jobject clazz, jstring path, jobject fileStatus) {
    131     const char* pathStr = env->GetStringUTFChars(path, NULL);
    132     jboolean ret = false;
    133 
    134     struct stat s;
    135     int res = stat(pathStr, &s);
    136     if (res == 0) {
    137         ret = true;
    138         if (fileStatus != NULL) {
    139             env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
    140             env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
    141             env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
    142             env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
    143             env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
    144             env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
    145             env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
    146             env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
    147             env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
    148             env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
    149             env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
    150             env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
    151         }
    152     }
    153 
    154     env->ReleaseStringUTFChars(path, pathStr);
    155 
    156     return ret;
    157 }
    158 
    159 static const JNINativeMethod methods[] = {
    160     {"setPermissions",  "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
    161     {"getPermissions",  "(Ljava/lang/String;[I)I", (void*)android_os_FileUtils_getPermissions},
    162     {"setUMask",        "(I)I",                    (void*)android_os_FileUtils_setUMask},
    163     {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
    164     {"getFileStatusNative", "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z", (void*)android_os_FileUtils_getFileStatus},
    165 };
    166 
    167 static const char* const kFileUtilsPathName = "android/os/FileUtils";
    168 
    169 int register_android_os_FileUtils(JNIEnv* env)
    170 {
    171     jclass fileStatusClass = env->FindClass("android/os/FileUtils$FileStatus");
    172     LOG_FATAL_IF(fileStatusClass == NULL, "Unable to find class android.os.FileUtils$FileStatus");
    173 
    174     gFileStatusDevFieldID = env->GetFieldID(fileStatusClass, "dev", "I");
    175     gFileStatusInoFieldID = env->GetFieldID(fileStatusClass, "ino", "I");
    176     gFileStatusModeFieldID = env->GetFieldID(fileStatusClass, "mode", "I");
    177     gFileStatusNlinkFieldID = env->GetFieldID(fileStatusClass, "nlink", "I");
    178     gFileStatusUidFieldID = env->GetFieldID(fileStatusClass, "uid", "I");
    179     gFileStatusGidFieldID = env->GetFieldID(fileStatusClass, "gid", "I");
    180     gFileStatusSizeFieldID = env->GetFieldID(fileStatusClass, "size", "J");
    181     gFileStatusBlksizeFieldID = env->GetFieldID(fileStatusClass, "blksize", "I");
    182     gFileStatusBlocksFieldID = env->GetFieldID(fileStatusClass, "blocks", "J");
    183     gFileStatusAtimeFieldID = env->GetFieldID(fileStatusClass, "atime", "J");
    184     gFileStatusMtimeFieldID = env->GetFieldID(fileStatusClass, "mtime", "J");
    185     gFileStatusCtimeFieldID = env->GetFieldID(fileStatusClass, "ctime", "J");
    186 
    187     return AndroidRuntime::registerNativeMethods(
    188         env, kFileUtilsPathName,
    189         methods, NELEM(methods));
    190 }
    191 
    192 }
    193