aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2024-06-12 16:44:21 +0800
committerPo Lu2024-06-12 16:44:21 +0800
commit02e70821b3800a082aec215a9ab8adbfafe9ad76 (patch)
tree87daf46f3c3efadaaa93ea859f48541bfe7e6b34
parentf543ec18f44fa64d06e1ab45e1484326f8451ebe (diff)
downloademacs-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.
-rw-r--r--java/Makefile.in4
-rw-r--r--lib-src/asset-directory-tool.c107
-rw-r--r--src/android-asset.h128
-rw-r--r--src/androidvfs.c62
-rw-r--r--src/lread.c2
5 files changed, 229 insertions, 74 deletions
diff --git a/java/Makefile.in b/java/Makefile.in
index fd076c089ff..8cc2235b9f3 100644
--- a/java/Makefile.in
+++ b/java/Makefile.in
@@ -258,7 +258,8 @@ install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES)
258 { hostname; date +%s; } > install_temp/assets/build_info 258 { hostname; date +%s; } > install_temp/assets/build_info
259# Produce the file index. 259# Produce the file index.
260 $(AM_V_SILENT) $(libsrc)/asset-directory-tool \ 260 $(AM_V_SILENT) $(libsrc)/asset-directory-tool \
261 install_temp/assets install_temp/assets/directory-tree 261 install_temp/assets install_temp/assets/directory-tree\
262 $(if $(ANDROID_SDK_8_OR_EARLIER),--api-8)
262# If the package targets Android 2.2, move compressable and 263# If the package targets Android 2.2, move compressable and
263# non-compressable assets to separate directories. 264# non-compressable assets to separate directories.
264 $(AM_V_SILENT) \ 265 $(AM_V_SILENT) \
@@ -266,6 +267,7 @@ install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES)
266 echo "Moving large and gzipped files to separate directories...">&2;\ 267 echo "Moving large and gzipped files to separate directories...">&2;\
267 mkdir -p install_temp/assets_raw; \ 268 mkdir -p install_temp/assets_raw; \
268 cd install_temp/assets; \ 269 cd install_temp/assets; \
270 mv directory-tree ../assets_raw; \
269 find . \( -size +1536 -o -size 1536 \) \ 271 find . \( -size +1536 -o -size 1536 \) \
270 \( \! -name '*.gz' \) -type f > files.txt; \ 272 \( \! -name '*.gz' \) -type f > files.txt; \
271 tar cf ../assets_raw/largefiles.tar -T files.txt; \ 273 tar cf ../assets_raw/largefiles.tar -T files.txt; \
diff --git a/lib-src/asset-directory-tool.c b/lib-src/asset-directory-tool.c
index 31735586193..23f4655448c 100644
--- a/lib-src/asset-directory-tool.c
+++ b/lib-src/asset-directory-tool.c
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
20#include <config.h> 20#include <config.h>
21 21
22#include <stdio.h> 22#include <stdio.h>
23#include <verify.h>
23#include <fcntl.h> 24#include <fcntl.h>
24#include <errno.h> 25#include <errno.h>
25#include <byteswap.h> 26#include <byteswap.h>
@@ -35,17 +36,19 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
35 application package. 36 application package.
36 37
37 Such a file records the layout of the `assets' directory in the 38 Such a file records the layout of the `assets' directory in the
38 package. Emacs records this information itself and uses it in the 39 package, and, in packages targeting Android 2.2, the size of each of
39 Android emulation of readdir, because the system asset manager APIs 40 its members. Emacs records this information itself and uses it in
40 are routinely buggy, and are often unable to locate directories or 41 the Android emulation of readdir, because the system asset manager
41 files. 42 APIs are often unable to locate directories or files, or provide
42 43 corresponding metadata.
43 The file is packed, with no data alignment guarantees made. The 44
44 file starts with the bytes "EMACS", following which is the name of 45 The file is packed, with no data alignment guarantees made. The file
45 the first file or directory, a NULL byte and an unsigned int 46 starts with the bytes "EMACS", or EMACS____ on Android 2.2, following
46 indicating the offset from the start of the file to the start of 47 which is the name of the first file or directory, a NULL byte, an
47 the next sibling. Following that is a list of subdirectories or 48 unsigned int holding its size (on Android 2.2), and an unsigned int
48 files in the same format. The long is stored LSB first. 49 indicating the offset from the start of the file to the start of the
50 next sibling. Following that is a list of subdirectories or files in
51 the same format. The long is stored LSB first.
49 52
50 Directories can be distinguished from ordinary files through the 53 Directories can be distinguished from ordinary files through the
51 last bytes of their file names (immediately previous to their 54 last bytes of their file names (immediately previous to their
@@ -62,10 +65,19 @@ struct directory_tree
62 /* The name of this directory or file. */ 65 /* The name of this directory or file. */
63 char *name; 66 char *name;
64 67
68 /* st_size of this entry. */
69 off_t st_size;
70
65 /* Subdirectories and files inside this directory. */ 71 /* Subdirectories and files inside this directory. */
66 struct directory_tree *children, *next; 72 struct directory_tree *children, *next;
67}; 73};
68 74
75/* Whether the size of each entry should be prepended to the start
76 pointer. */
77static bool need_file_size;
78
79
80
69/* Exit with EXIT_FAILURE, after printing a description of a failing 81/* Exit with EXIT_FAILURE, after printing a description of a failing
70 function WHAT along with the details of the error. */ 82 function WHAT along with the details of the error. */
71 83
@@ -138,11 +150,14 @@ main_1 (DIR *dir, struct directory_tree *parent)
138 last = &this->next; 150 last = &this->next;
139 this->name = xmalloc (length + 2); 151 this->name = xmalloc (length + 2);
140 strcpy (this->name, dirent->d_name); 152 strcpy (this->name, dirent->d_name);
153 this->st_size = 0;
141 154
142 /* Now record the offset to the end of this directory. This 155 /* Now record the offset to the end of this directory. This
143 is length + 1, for the file name, and 5 more bytes for 156 is length + 1, for the file name, 5 more bytes for the
144 the trailing NULL and long. */ 157 trailing NULL and long, and 4 further bytes if a file size
145 this->offset = parent->offset + length + 6; 158 is required. */
159 this->offset = (parent->offset
160 + length + 6 + (need_file_size ? 4 : 0));
146 161
147 /* Terminate that with a slash and trailing NULL byte. */ 162 /* Terminate that with a slash and trailing NULL byte. */
148 this->name[length] = '/'; 163 this->name[length] = '/';
@@ -175,11 +190,22 @@ main_1 (DIR *dir, struct directory_tree *parent)
175 *last = this; 190 *last = this;
176 last = &this->next; 191 last = &this->next;
177 this->name = xmalloc (length + 1); 192 this->name = xmalloc (length + 1);
193 this->st_size = statb.st_size;
178 strcpy (this->name, dirent->d_name); 194 strcpy (this->name, dirent->d_name);
179 195
180 /* This is one byte shorter because there is no trailing 196 if (this->st_size >= 0x1ffffff)
197 {
198 fprintf (stderr,
199 "asset-directory-tool: file size exceeds maximum"
200 " representable in a directory-tree: %s\n",
201 dirent->d_name);
202 exit (EXIT_FAILURE);
203 }
204
205 /* This is one byte the shorter because there is no trailing
181 slash. */ 206 slash. */
182 this->offset = parent->offset + length + 5; 207 this->offset = (parent->offset + length + 5
208 + (need_file_size ? 4 : 0));
183 parent->offset = this->offset; 209 parent->offset = this->offset;
184 } 210 }
185 } 211 }
@@ -194,7 +220,7 @@ main_2 (int fd, struct directory_tree *tree, size_t *offset)
194{ 220{
195 ssize_t size; 221 ssize_t size;
196 struct directory_tree *child; 222 struct directory_tree *child;
197 unsigned int output; 223 unsigned int output[2];
198 224
199 /* Write tree->name with the trailing NULL byte. */ 225 /* Write tree->name with the trailing NULL byte. */
200 size = strlen (tree->name) + 1; 226 size = strlen (tree->name) + 1;
@@ -203,13 +229,26 @@ main_2 (int fd, struct directory_tree *tree, size_t *offset)
203 229
204 /* Write the offset. */ 230 /* Write the offset. */
205#ifdef WORDS_BIGENDIAN 231#ifdef WORDS_BIGENDIAN
206 output = bswap_32 (tree->offset); 232 output[1] = bswap_32 (tree->offset);
207#else 233 output[0] = bswap_32 ((unsigned int) tree->st_size);
208 output = tree->offset; 234#else /* !WORDS_BIGENDIAN */
209#endif 235 output[1] = tree->offset;
210 if (write (fd, &output, 4) < 1) 236 output[0] = (unsigned int) tree->st_size;
211 croak ("write"); 237#endif /* !WORDS_BIGENDIAN */
212 size += 4; 238
239 verify (sizeof output == 8 && sizeof output[0] == 4);
240 if (!need_file_size)
241 {
242 if (write (fd, output + 1, 4) < 1)
243 croak ("write");
244 size += 4;
245 }
246 else
247 {
248 if (write (fd, output, 8) < 1)
249 croak ("write");
250 size += 8;
251 }
213 252
214 /* Now update offset. */ 253 /* Now update offset. */
215 *offset += size; 254 *offset += size;
@@ -240,13 +279,16 @@ main (int argc, char **argv)
240 struct directory_tree tree; 279 struct directory_tree tree;
241 size_t offset; 280 size_t offset;
242 281
243 if (argc != 3) 282 if (argc != 3 && argc != 4)
244 { 283 {
245 fprintf (stderr, "usage: %s directory output-file\n", 284 fprintf (stderr, "usage: %s directory output-file "
246 argv[0]); 285 "[--api-8]\n", argv[0]);
247 return EXIT_FAILURE; 286 return EXIT_FAILURE;
248 } 287 }
249 288
289 if (argc == 4 && !strcmp (argv[3], "--api-8"))
290 need_file_size = true;
291
250 fd = open (argv[2], O_CREAT | O_TRUNC | O_RDWR, 292 fd = open (argv[2], O_CREAT | O_TRUNC | O_RDWR,
251 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 293 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
252 294
@@ -272,16 +314,23 @@ main (int argc, char **argv)
272 return EXIT_FAILURE; 314 return EXIT_FAILURE;
273 } 315 }
274 316
317 /* And a further 4 bytes of padding if need_file_size. */
318 if (need_file_size && write (fd, "____", 4) < 4)
319 {
320 perror ("write");
321 return EXIT_FAILURE;
322 }
323
275 /* Now iterate through children of INDIR, building the directory 324 /* Now iterate through children of INDIR, building the directory
276 tree. */ 325 tree. */
277 tree.offset = 5; 326 tree.offset = 5 + (need_file_size ? 4 : 0);
278 tree.children = NULL; 327 tree.children = NULL;
279 328
280 main_1 (indir, &tree); 329 main_1 (indir, &tree);
281 closedir (indir); 330 closedir (indir);
282 331
283 /* Finally, write the directory tree to the output file. */ 332 /* Finally, write the directory tree to the output file. */
284 offset = 5; 333 offset = 5 + (need_file_size ? 4 : 0);
285 for (; tree.children; tree.children = tree.children->next) 334 for (; tree.children; tree.children = tree.children->next)
286 main_2 (fd, tree.children, &offset); 335 main_2 (fd, tree.children, &offset);
287 336
diff --git a/src/android-asset.h b/src/android-asset.h
index a6b5aa3366c..273ab1fa734 100644
--- a/src/android-asset.h
+++ b/src/android-asset.h
@@ -19,6 +19,17 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20#include <android/log.h> 20#include <android/log.h>
21 21
22
23
24/* Forward declarations. */
25
26static const char *directory_tree;
27
28static const char *android_scan_directory_tree (const char *, size_t *);
29static unsigned int android_extract_long (const char *);
30
31
32
22/* This file contains an emulation of the Android asset manager API 33/* This file contains an emulation of the Android asset manager API
23 used on builds for Android 2.2. It is included by android.c 34 used on builds for Android 2.2. It is included by android.c
24 whenever appropriate. 35 whenever appropriate.
@@ -34,6 +45,7 @@ struct android_asset_manager
34 /* Asset manager class and functions. */ 45 /* Asset manager class and functions. */
35 jclass class; 46 jclass class;
36 jmethodID open_fd; 47 jmethodID open_fd;
48 jmethodID open;
37 49
38 /* Asset file descriptor class and functions. */ 50 /* Asset file descriptor class and functions. */
39 jclass fd_class; 51 jclass fd_class;
@@ -63,6 +75,9 @@ struct android_asset
63 /* The asset file descriptor and input stream. */ 75 /* The asset file descriptor and input stream. */
64 jobject fd, stream; 76 jobject fd, stream;
65 77
78 /* Alternatively, the name of the file. */
79 jstring name;
80
66 /* The mode. */ 81 /* The mode. */
67 int mode; 82 int mode;
68}; 83};
@@ -98,6 +113,12 @@ AAssetManager_fromJava (JNIEnv *env, jobject java_manager)
98 = (*env)->GetMethodID (env, manager->class, "openFd", 113 = (*env)->GetMethodID (env, manager->class, "openFd",
99 "(Ljava/lang/String;)" 114 "(Ljava/lang/String;)"
100 "Landroid/content/res/AssetFileDescriptor;"); 115 "Landroid/content/res/AssetFileDescriptor;");
116 assert (manager->open_fd);
117
118 manager->open
119 = (*env)->GetMethodID (env, manager->class, "open",
120 "(Ljava/lang/String;)"
121 "Ljava/io/InputStream;");
101 assert (manager->open); 122 assert (manager->open);
102 123
103 manager->fd_class 124 manager->fd_class
@@ -168,6 +189,8 @@ AAssetManager_open (AAssetManager *manager, const char *c_name,
168 jobject desc; 189 jobject desc;
169 jstring name; 190 jstring name;
170 AAsset *asset; 191 AAsset *asset;
192 const char *asset_dir;
193 jlong st_size = -1;
171 194
172 /* Push a local frame. */ 195 /* Push a local frame. */
173 asset = NULL; 196 asset = NULL;
@@ -177,53 +200,86 @@ AAssetManager_open (AAssetManager *manager, const char *c_name,
177 if ((*(manager->env))->ExceptionCheck (manager->env)) 200 if ((*(manager->env))->ExceptionCheck (manager->env))
178 goto fail; 201 goto fail;
179 202
180 /* Encoding issues can be ignored for now as there are only ASCII 203 /* If the directory tree has been initialized, it is possible to avoid
181 file names in Emacs. */ 204 opening an AssetFileDescriptor and thereby access compressed
205 assets, without sacrificing the possibility of reading the file
206 size. */
207 if (directory_tree)
208 {
209 /* Search for a matching asset. */
210 asset_dir = android_scan_directory_tree (c_name, NULL);
211 if (!asset_dir)
212 goto fail;
213
214 /* Extract the size of the asset from this directory. */
215 st_size = android_extract_long (asset_dir - 8);
216 }
217
218 /* Encoding issues can be ignored for the time being as there are only
219 ASCII file names in Emacs. */
182 name = (*(manager->env))->NewStringUTF (manager->env, c_name); 220 name = (*(manager->env))->NewStringUTF (manager->env, c_name);
183 221
184 if (!name) 222 if (!name)
185 goto fail; 223 goto fail;
186 224
187 /* Now try to open an ``AssetFileDescriptor''. */ 225 /* If st_size has been set, it ought to be possible to open an input
188 desc = (*(manager->env))->CallObjectMethod (manager->env, 226 stream directly upon the first attempt to read from the asset,
189 manager->asset_manager, 227 sidestepping the intermediate AssetFileDescriptor. */
190 manager->open_fd,
191 name);
192 228
193 if (!desc) 229 desc = NULL;
194 goto fail; 230
231 if (st_size < 0)
232 /* Otherwise attempt to open an ``AssetFileDescriptor''. */
233 desc = (*(manager->env))->CallObjectMethod (manager->env,
234 manager->asset_manager,
235 manager->open_fd,
236 name);
195 237
196 /* Allocate the asset. */ 238 /* Allocate the asset. */
197 asset = calloc (1, sizeof *asset); 239 asset = calloc (1, sizeof *asset);
198 240
199 if (!asset) 241 if (!asset)
242 goto fail;
243
244 if (desc)
200 { 245 {
201 (*(manager->env))->CallVoidMethod (manager->env, 246 /* Pop the local frame and return desc. */
202 desc, 247 desc = (*(manager->env))->NewGlobalRef (manager->env, desc);
203 manager->close);
204 goto fail;
205 }
206 248
207 /* Pop the local frame and return desc. */ 249 if (!desc)
208 desc = (*(manager->env))->NewGlobalRef (manager->env, desc); 250 goto fail;
209 251
210 if (!desc) 252 /* Will be released by PopLocalFrame. */
211 goto fail; 253 name = NULL;
254 }
255 else /* if (name) */
256 {
257 /* Pop the local frame and return name. */
258 name = (*(manager->env))->NewGlobalRef (manager->env, name);
259
260 if (!name)
261 goto fail;
262 }
212 263
213 (*(manager->env))->PopLocalFrame (manager->env, NULL); 264 (*(manager->env))->PopLocalFrame (manager->env, NULL);
214 265
215 asset->manager = manager; 266 asset->manager = manager;
216 asset->length = -1; 267 asset->length = st_size;
217 asset->fd = desc; 268 asset->fd = desc;
269 asset->name = name;
218 asset->mode = mode; 270 asset->mode = mode;
219 271
220 return asset; 272 return asset;
221 273
222 fail: 274 fail:
275 if (desc)
276 (*(manager->env))->CallVoidMethod (manager->env,
277 desc,
278 manager->close);
279
223 (*(manager->env))->ExceptionClear (manager->env); 280 (*(manager->env))->ExceptionClear (manager->env);
224 (*(manager->env))->PopLocalFrame (manager->env, NULL); 281 (*(manager->env))->PopLocalFrame (manager->env, NULL);
225 free (asset); 282 free (asset);
226
227 return NULL; 283 return NULL;
228} 284}
229 285
@@ -234,11 +290,14 @@ AAsset_close (AAsset *asset)
234 290
235 env = asset->manager->env; 291 env = asset->manager->env;
236 292
237 (*env)->CallVoidMethod (asset->manager->env, 293 if (asset->fd)
238 asset->fd, 294 {
239 asset->manager->close); 295 (*env)->CallVoidMethod (asset->manager->env,
240 (*env)->DeleteGlobalRef (asset->manager->env, 296 asset->fd,
241 asset->fd); 297 asset->manager->close);
298 (*env)->DeleteGlobalRef (asset->manager->env,
299 asset->fd);
300 }
242 301
243 if (asset->stream) 302 if (asset->stream)
244 { 303 {
@@ -249,6 +308,10 @@ AAsset_close (AAsset *asset)
249 asset->stream); 308 asset->stream);
250 } 309 }
251 310
311 if (asset->name)
312 (*env)->DeleteGlobalRef (asset->manager->env,
313 asset->name);
314
252 free (asset); 315 free (asset);
253} 316}
254 317
@@ -264,10 +327,17 @@ android_asset_create_stream (AAsset *asset)
264 jobject stream; 327 jobject stream;
265 JNIEnv *env; 328 JNIEnv *env;
266 329
330 assert (asset->fd || asset->name);
331
267 env = asset->manager->env; 332 env = asset->manager->env;
268 stream 333
269 = (*env)->CallObjectMethod (env, asset->fd, 334 if (asset->name)
270 asset->manager->create_input_stream); 335 stream = (*env)->CallObjectMethod (env, asset->manager->asset_manager,
336 asset->manager->open, asset->name);
337 else
338 stream
339 = (*env)->CallObjectMethod (env, asset->fd,
340 asset->manager->create_input_stream);
271 341
272 if (!stream) 342 if (!stream)
273 { 343 {
@@ -380,6 +450,8 @@ AAsset_getLength (AAsset *asset)
380 450
381 if (asset->length != -1) 451 if (asset->length != -1)
382 return asset->length; 452 return asset->length;
453 if (!asset->fd)
454 return 0;
383 455
384 env = asset->manager->env; 456 env = asset->manager->env;
385 asset->length 457 asset->length
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
1003static unsigned int 1005static unsigned int
1004android_extract_long (char *pointer) 1006android_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
1024static const char * 1026static const char *
1025android_scan_directory_tree (char *file, size_t *limit_return) 1027android_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}
diff --git a/src/lread.c b/src/lread.c
index f5c79a8c0ea..1bc5b0c993d 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -69,7 +69,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
69#define lread_fd_cmp(n) (fd == (n)) 69#define lread_fd_cmp(n) (fd == (n))
70#define lread_fd_p (fd >= 0) 70#define lread_fd_p (fd >= 0)
71#define lread_close emacs_close 71#define lread_close emacs_close
72#define lread_fstat fstat 72#define lread_fstat sys_fstat
73#define lread_read_quit emacs_read_quit 73#define lread_read_quit emacs_read_quit
74#define lread_lseek lseek 74#define lread_lseek lseek
75 75