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
android_os_FileUtils_setPermissions(JNIEnv * env,jobject clazz,jstring file,jint mode,jint uid,jint gid)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
android_os_FileUtils_getPermissions(JNIEnv * env,jobject clazz,jstring file,jintArray outArray)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
android_os_FileUtils_getFatVolumeId(JNIEnv * env,jobject clazz,jstring path)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
android_os_FileUtils_getFileStatus(JNIEnv * env,jobject clazz,jstring path,jobject fileStatus)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
register_android_os_FileUtils(JNIEnv * env)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