• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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