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