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 34namespace android { 35 36static jfieldID gFileStatusDevFieldID; 37static jfieldID gFileStatusInoFieldID; 38static jfieldID gFileStatusModeFieldID; 39static jfieldID gFileStatusNlinkFieldID; 40static jfieldID gFileStatusUidFieldID; 41static jfieldID gFileStatusGidFieldID; 42static jfieldID gFileStatusSizeFieldID; 43static jfieldID gFileStatusBlksizeFieldID; 44static jfieldID gFileStatusBlocksFieldID; 45static jfieldID gFileStatusAtimeFieldID; 46static jfieldID gFileStatusMtimeFieldID; 47static jfieldID gFileStatusCtimeFieldID; 48 49jint 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 71jint 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 104jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask) 105{ 106 return umask(mask); 107} 108 109jint 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 130jboolean 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 159static 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 167static const char* const kFileUtilsPathName = "android/os/FileUtils"; 168 169int 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