aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorPo Lu2024-06-12 16:44:21 +0800
committerPo Lu2024-06-12 16:44:21 +0800
commit02e70821b3800a082aec215a9ab8adbfafe9ad76 (patch)
tree87daf46f3c3efadaaa93ea859f48541bfe7e6b34 /lib-src
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.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/asset-directory-tool.c107
1 files changed, 78 insertions, 29 deletions
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