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 /lib-src | |
| 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 'lib-src')
| -rw-r--r-- | lib-src/asset-directory-tool.c | 107 |
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. */ | ||
| 77 | static 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 | ||