diff options
| author | Po Lu | 2024-06-12 16:44:21 +0800 |
|---|---|---|
| committer | Po Lu | 2024-06-12 16:44:21 +0800 |
| commit | 02e70821b3800a082aec215a9ab8adbfafe9ad76 (patch) | |
| tree | 87daf46f3c3efadaaa93ea859f48541bfe7e6b34 /src/androidvfs.c | |
| parent | f543ec18f44fa64d06e1ab45e1484326f8451ebe (diff) | |
| download | emacs-02e70821b3800a082aec215a9ab8adbfafe9ad76.tar.gz emacs-02e70821b3800a082aec215a9ab8adbfafe9ad76.zip | |
Restore functionality on Android 2.2
* java/Makefile.in (install_temp): Do not compress
directory-tree and generate such files in a special format that
stores file sizes.
* lib-src/asset-directory-tool.c (struct directory_tree): New
field st_size.
(need_file_size): New variable.
(main_1, main_2, main): Write file sizes before sibling offsets
if `--api-8' is specified.
* src/android-asset.h (struct android_asset_manager): New field
open.
(struct android_asset): New field name.
(AAssetManager_fromJava): Load AssetManager#open.
(AAssetManager_open): If a directory tree has already been
loaded, search for a matching asset and load its size thence, to
avoid the requirement of an AssetFileDescriptor.
(AAsset_close): Don't assume asset->fd exists. Release
asset->name.
(AAsset_getLength): Likewise.
(android_asset_create_stream): If asset->name exists, call
AssetManager#open, in order to open compressed files.
* src/androidvfs.c (OLD_ANDROID_ASSETS): Define to 1 on API 8.
(android_extract_long, android_scan_directory_tree): Mark
arguments as const. Adjust offsets when OLD_ANDROID_ASSETS.
(android_is_directory, android_init_assets, android_afs_readdir):
Likewise.
* src/lread.c (lread_fstat): Define to sys_fstat, not fstat.
Diffstat (limited to 'src/androidvfs.c')
| -rw-r--r-- | src/androidvfs.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/src/androidvfs.c b/src/androidvfs.c index c0bd86e54b8..d28a74918f6 100644 --- a/src/androidvfs.c +++ b/src/androidvfs.c | |||
| @@ -46,8 +46,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 46 | #if __ANDROID_API__ >= 9 | 46 | #if __ANDROID_API__ >= 9 |
| 47 | #include <android/asset_manager.h> | 47 | #include <android/asset_manager.h> |
| 48 | #include <android/asset_manager_jni.h> | 48 | #include <android/asset_manager_jni.h> |
| 49 | #define OLD_ANDROID_ASSETS 0 | ||
| 49 | #else /* __ANDROID_API__ < 9 */ | 50 | #else /* __ANDROID_API__ < 9 */ |
| 50 | #include "android-asset.h" | 51 | #include "android-asset.h" |
| 52 | #define OLD_ANDROID_ASSETS 1 | ||
| 51 | #endif /* __ANDROID_API__ >= 9 */ | 53 | #endif /* __ANDROID_API__ >= 9 */ |
| 52 | 54 | ||
| 53 | #include <android/log.h> | 55 | #include <android/log.h> |
| @@ -1001,7 +1003,7 @@ static AAssetManager *asset_manager; | |||
| 1001 | /* Read an unaligned (32-bit) long from the address POINTER. */ | 1003 | /* Read an unaligned (32-bit) long from the address POINTER. */ |
| 1002 | 1004 | ||
| 1003 | static unsigned int | 1005 | static unsigned int |
| 1004 | android_extract_long (char *pointer) | 1006 | android_extract_long (const char *pointer) |
| 1005 | { | 1007 | { |
| 1006 | unsigned int number; | 1008 | unsigned int number; |
| 1007 | 1009 | ||
| @@ -1022,16 +1024,20 @@ android_extract_long (char *pointer) | |||
| 1022 | directory. */ | 1024 | directory. */ |
| 1023 | 1025 | ||
| 1024 | static const char * | 1026 | static const char * |
| 1025 | android_scan_directory_tree (char *file, size_t *limit_return) | 1027 | android_scan_directory_tree (const char *file, size_t *limit_return) |
| 1026 | { | 1028 | { |
| 1027 | char *token, *saveptr, *copy, *start, *max, *limit; | 1029 | char *token, *saveptr, *copy, *start, *max, *limit; |
| 1028 | size_t token_length, ntokens, i, len; | 1030 | size_t token_length, ntokens, i, len; |
| 1029 | char *tokens[10]; | 1031 | char *tokens[20]; |
| 1030 | 1032 | ||
| 1031 | USE_SAFE_ALLOCA; | 1033 | USE_SAFE_ALLOCA; |
| 1032 | 1034 | ||
| 1033 | /* Skip past the 5 byte header. */ | 1035 | /* Skip past the 5 or 9 byte header. */ |
| 1036 | #if !OLD_ANDROID_ASSETS | ||
| 1034 | start = (char *) directory_tree + 5; | 1037 | start = (char *) directory_tree + 5; |
| 1038 | #else /* OLD_ANDROID_ASSETS */ | ||
| 1039 | start = (char *) directory_tree + 9; | ||
| 1040 | #endif /* OLD_ANDROID_ASSETS */ | ||
| 1035 | 1041 | ||
| 1036 | /* Figure out the current limit. */ | 1042 | /* Figure out the current limit. */ |
| 1037 | limit = (char *) directory_tree + directory_tree_size; | 1043 | limit = (char *) directory_tree + directory_tree_size; |
| @@ -1098,9 +1104,9 @@ android_scan_directory_tree (char *file, size_t *limit_return) | |||
| 1098 | { | 1104 | { |
| 1099 | /* They probably match. Find the NULL byte. It must be | 1105 | /* They probably match. Find the NULL byte. It must be |
| 1100 | either one byte past start + token_length, with the last | 1106 | either one byte past start + token_length, with the last |
| 1101 | byte a trailing slash (indicating that it is a | 1107 | byte a trailing slash (indicating that it is a directory), |
| 1102 | directory), or just start + token_length. Return 4 bytes | 1108 | or just start + token_length. Return 4 or 8 bytes past the |
| 1103 | past the next NULL byte. */ | 1109 | next NULL byte. */ |
| 1104 | 1110 | ||
| 1105 | max = memchr (start, 0, limit - start); | 1111 | max = memchr (start, 0, limit - start); |
| 1106 | 1112 | ||
| @@ -1113,13 +1119,14 @@ android_scan_directory_tree (char *file, size_t *limit_return) | |||
| 1113 | last token. Otherwise, set it as start and the limit as | 1119 | last token. Otherwise, set it as start and the limit as |
| 1114 | start + the offset and continue the loop. */ | 1120 | start + the offset and continue the loop. */ |
| 1115 | 1121 | ||
| 1116 | if (max && max + 5 <= limit) | 1122 | if (max && max + (OLD_ANDROID_ASSETS ? 9 : 5) <= limit) |
| 1117 | { | 1123 | { |
| 1118 | if (i < ntokens - 1) | 1124 | if (i < ntokens - 1) |
| 1119 | { | 1125 | { |
| 1120 | start = max + 5; | 1126 | start = max + (OLD_ANDROID_ASSETS ? 9 : 5); |
| 1121 | limit = ((char *) directory_tree | 1127 | limit = ((char *) directory_tree |
| 1122 | + android_extract_long (max + 1)); | 1128 | + android_extract_long (max + (OLD_ANDROID_ASSETS |
| 1129 | ? 5 : 1))); | ||
| 1123 | 1130 | ||
| 1124 | /* Make sure limit is still in range. */ | 1131 | /* Make sure limit is still in range. */ |
| 1125 | if (limit > directory_tree + directory_tree_size | 1132 | if (limit > directory_tree + directory_tree_size |
| @@ -1137,10 +1144,12 @@ android_scan_directory_tree (char *file, size_t *limit_return) | |||
| 1137 | { | 1144 | { |
| 1138 | /* Figure out the limit. */ | 1145 | /* Figure out the limit. */ |
| 1139 | if (limit_return) | 1146 | if (limit_return) |
| 1140 | *limit_return = android_extract_long (max + 1); | 1147 | *limit_return |
| 1148 | = android_extract_long (max + (OLD_ANDROID_ASSETS | ||
| 1149 | ? 5 : 1)); | ||
| 1141 | 1150 | ||
| 1142 | /* Go to the end of this file. */ | 1151 | /* Go to the end of this file. */ |
| 1143 | max += 5; | 1152 | max += (OLD_ANDROID_ASSETS ? 9 : 5); |
| 1144 | } | 1153 | } |
| 1145 | 1154 | ||
| 1146 | SAFE_FREE (); | 1155 | SAFE_FREE (); |
| @@ -1161,11 +1170,12 @@ android_scan_directory_tree (char *file, size_t *limit_return) | |||
| 1161 | 1170 | ||
| 1162 | start = memchr (start, 0, limit - start); | 1171 | start = memchr (start, 0, limit - start); |
| 1163 | 1172 | ||
| 1164 | if (!start || start + 5 > limit) | 1173 | if (!start || start + (OLD_ANDROID_ASSETS ? 9 : 5) > limit) |
| 1165 | goto fail; | 1174 | goto fail; |
| 1166 | 1175 | ||
| 1167 | start = ((char *) directory_tree | 1176 | start = ((char *) directory_tree |
| 1168 | + android_extract_long (start + 1)); | 1177 | + android_extract_long (start |
| 1178 | + (OLD_ANDROID_ASSETS ? 5 : 1))); | ||
| 1169 | 1179 | ||
| 1170 | /* Make sure start is still in bounds. */ | 1180 | /* Make sure start is still in bounds. */ |
| 1171 | 1181 | ||
| @@ -1192,13 +1202,20 @@ android_is_directory (const char *dir) | |||
| 1192 | { | 1202 | { |
| 1193 | /* If the directory is the directory tree, then it is a | 1203 | /* If the directory is the directory tree, then it is a |
| 1194 | directory. */ | 1204 | directory. */ |
| 1195 | if (dir == directory_tree + 5) | 1205 | if (dir == directory_tree + (OLD_ANDROID_ASSETS ? 9 : 5)) |
| 1196 | return true; | 1206 | return true; |
| 1197 | 1207 | ||
| 1208 | #if !OLD_ANDROID_ASSETS | ||
| 1198 | /* Otherwise, look 5 bytes behind. If it is `/', then it is a | 1209 | /* Otherwise, look 5 bytes behind. If it is `/', then it is a |
| 1199 | directory. */ | 1210 | directory. */ |
| 1200 | return (dir - 6 >= directory_tree | 1211 | return (dir - 6 >= directory_tree |
| 1201 | && *(dir - 6) == '/'); | 1212 | && *(dir - 6) == '/'); |
| 1213 | #else /* OLD_ANDROID_ASSETS */ | ||
| 1214 | /* Otherwise, look 9 bytes behind. If it is `/', then it is a | ||
| 1215 | directory. */ | ||
| 1216 | return (dir - 10 >= directory_tree | ||
| 1217 | && *(dir - 10) == '/'); | ||
| 1218 | #endif /* OLD_ANDROID_ASSETS */ | ||
| 1202 | } | 1219 | } |
| 1203 | 1220 | ||
| 1204 | /* Initialize asset retrieval. ENV should be a JNI environment for | 1221 | /* Initialize asset retrieval. ENV should be a JNI environment for |
| @@ -1232,6 +1249,7 @@ android_init_assets (JNIEnv *env, jobject manager) | |||
| 1232 | /* Now figure out how big the directory tree is, and compare the | 1249 | /* Now figure out how big the directory tree is, and compare the |
| 1233 | first few bytes. */ | 1250 | first few bytes. */ |
| 1234 | directory_tree_size = AAsset_getLength (asset); | 1251 | directory_tree_size = AAsset_getLength (asset); |
| 1252 | #if !OLD_ANDROID_ASSETS | ||
| 1235 | if (directory_tree_size < 5 | 1253 | if (directory_tree_size < 5 |
| 1236 | || memcmp (directory_tree, "EMACS", 5)) | 1254 | || memcmp (directory_tree, "EMACS", 5)) |
| 1237 | { | 1255 | { |
| @@ -1239,6 +1257,15 @@ android_init_assets (JNIEnv *env, jobject manager) | |||
| 1239 | "Directory tree has bad magic"); | 1257 | "Directory tree has bad magic"); |
| 1240 | emacs_abort (); | 1258 | emacs_abort (); |
| 1241 | } | 1259 | } |
| 1260 | #else /* OLD_ANDROID_ASSETS */ | ||
| 1261 | if (directory_tree_size < 9 | ||
| 1262 | || memcmp (directory_tree, "EMACS____", 9)) | ||
| 1263 | { | ||
| 1264 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 1265 | "Directory tree has bad magic"); | ||
| 1266 | emacs_abort (); | ||
| 1267 | } | ||
| 1268 | #endif /* OLD_ANDROID_ASSETS */ | ||
| 1242 | 1269 | ||
| 1243 | /* Hold a VM reference to the asset manager to prevent the native | 1270 | /* Hold a VM reference to the asset manager to prevent the native |
| 1244 | object from being deleted. */ | 1271 | object from being deleted. */ |
| @@ -2287,8 +2314,13 @@ android_afs_readdir (struct android_vdir *vdir) | |||
| 2287 | dirent.d_type = DT_REG; | 2314 | dirent.d_type = DT_REG; |
| 2288 | 2315 | ||
| 2289 | /* Forward dir->asset_dir to the file past last. */ | 2316 | /* Forward dir->asset_dir to the file past last. */ |
| 2317 | #if !OLD_ANDROID_ASSETS | ||
| 2290 | dir->asset_dir = ((char *) directory_tree | 2318 | dir->asset_dir = ((char *) directory_tree |
| 2291 | + android_extract_long ((char *) last)); | 2319 | + android_extract_long ((char *) last)); |
| 2320 | #else /* OLD_ANDROID_ASSETS */ | ||
| 2321 | dir->asset_dir = ((char *) directory_tree | ||
| 2322 | + android_extract_long ((char *) last + 4)); | ||
| 2323 | #endif /* OLD_ANDROID_ASSETS */ | ||
| 2292 | 2324 | ||
| 2293 | return &dirent; | 2325 | return &dirent; |
| 2294 | } | 2326 | } |