diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-24 17:03:28 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-24 17:03:28 +0200 |
commit | dff2bd733fc2dac08d34f2cfad0e68aeb8e7a7a2 (patch) | |
tree | 0085fabf15b8ca5034636f39e97e9ba306ca7671 | |
parent | 309f5e3775ed9cc0837c6d93482735bc4f117d5b (diff) | |
download | busybox-w32-dff2bd733fc2dac08d34f2cfad0e68aeb8e7a7a2.tar.gz busybox-w32-dff2bd733fc2dac08d34f2cfad0e68aeb8e7a7a2.tar.bz2 busybox-w32-dff2bd733fc2dac08d34f2cfad0e68aeb8e7a7a2.zip |
libarchive: treat one "FIXME: avoid seek"
function old new delta
xmalloc_read_with_initial_buf - 205 +205
setup_transformer_on_fd 154 150 -4
xmalloc_open_zipped_read_close 143 135 -8
xmalloc_read 201 10 -191
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/3 up/down: 205/-203) Total: 2 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/libarchive/open_transformer.c | 44 | ||||
-rw-r--r-- | include/bb_archive.h | 6 | ||||
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | libbb/read_printf.c | 12 |
4 files changed, 41 insertions, 22 deletions
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 4a4bf3916..97bcc32f0 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -159,47 +159,44 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog) | |||
159 | */ | 159 | */ |
160 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) | 160 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) |
161 | { | 161 | { |
162 | union { | ||
163 | uint8_t b[4]; | ||
164 | uint16_t b16[2]; | ||
165 | uint32_t b32[1]; | ||
166 | } magic; | ||
167 | transformer_state_t *xstate; | 162 | transformer_state_t *xstate; |
168 | 163 | ||
169 | xstate = xzalloc(sizeof(*xstate)); | 164 | xstate = xzalloc(sizeof(*xstate)); |
170 | xstate->src_fd = fd; | 165 | xstate->src_fd = fd; |
171 | xstate->signature_skipped = 2; | ||
172 | 166 | ||
173 | /* .gz and .bz2 both have 2-byte signature, and their | 167 | /* .gz and .bz2 both have 2-byte signature, and their |
174 | * unpack_XXX_stream wants this header skipped. */ | 168 | * unpack_XXX_stream wants this header skipped. */ |
175 | xread(fd, magic.b16, sizeof(magic.b16[0])); | 169 | xstate->signature_skipped = 2; |
170 | xread(fd, xstate->magic.b16, 2); | ||
176 | if (ENABLE_FEATURE_SEAMLESS_GZ | 171 | if (ENABLE_FEATURE_SEAMLESS_GZ |
177 | && magic.b16[0] == GZIP_MAGIC | 172 | && xstate->magic.b16[0] == GZIP_MAGIC |
178 | ) { | 173 | ) { |
179 | xstate->xformer = unpack_gz_stream; | 174 | xstate->xformer = unpack_gz_stream; |
180 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) | 175 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) |
181 | goto found_magic; | 176 | goto found_magic; |
182 | } | 177 | } |
183 | if (ENABLE_FEATURE_SEAMLESS_Z | 178 | if (ENABLE_FEATURE_SEAMLESS_Z |
184 | && magic.b16[0] == COMPRESS_MAGIC | 179 | && xstate->magic.b16[0] == COMPRESS_MAGIC |
185 | ) { | 180 | ) { |
186 | xstate->xformer = unpack_Z_stream; | 181 | xstate->xformer = unpack_Z_stream; |
187 | USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) | 182 | USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) |
188 | goto found_magic; | 183 | goto found_magic; |
189 | } | 184 | } |
190 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | 185 | if (ENABLE_FEATURE_SEAMLESS_BZ2 |
191 | && magic.b16[0] == BZIP2_MAGIC | 186 | && xstate->magic.b16[0] == BZIP2_MAGIC |
192 | ) { | 187 | ) { |
193 | xstate->xformer = unpack_bz2_stream; | 188 | xstate->xformer = unpack_bz2_stream; |
194 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) | 189 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) |
195 | goto found_magic; | 190 | goto found_magic; |
196 | } | 191 | } |
197 | if (ENABLE_FEATURE_SEAMLESS_XZ | 192 | if (ENABLE_FEATURE_SEAMLESS_XZ |
198 | && magic.b16[0] == XZ_MAGIC1 | 193 | && xstate->magic.b16[0] == XZ_MAGIC1 |
199 | ) { | 194 | ) { |
195 | uint32_t v32; | ||
200 | xstate->signature_skipped = 6; | 196 | xstate->signature_skipped = 6; |
201 | xread(fd, magic.b32, sizeof(magic.b32[0])); | 197 | xread(fd, &xstate->magic.b16[1], 4); |
202 | if (magic.b32[0] == XZ_MAGIC2) { | 198 | move_from_unaligned32(v32, &xstate->magic.b16[1]); |
199 | if (v32 == XZ_MAGIC2) { | ||
203 | xstate->xformer = unpack_xz_stream; | 200 | xstate->xformer = unpack_xz_stream; |
204 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) | 201 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) |
205 | goto found_magic; | 202 | goto found_magic; |
@@ -344,11 +341,24 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ | |||
344 | *maxsz_p = xstate->mem_output_size; | 341 | *maxsz_p = xstate->mem_output_size; |
345 | } | 342 | } |
346 | } else { | 343 | } else { |
347 | /* File is not compressed */ | 344 | /* File is not compressed. |
348 | //FIXME: avoid seek | 345 | * We already read first few bytes, account for that. |
349 | xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); | 346 | * Exmaple where it happens: |
347 | * "modinfo MODULE.ko" (not compressed) | ||
348 | * open("MODULE.ko", O_RDONLY|O_LARGEFILE) = 4 | ||
349 | * read(4, "\177E", 2) = 2 | ||
350 | * fstat64(4, ...) | ||
351 | * mmap(...) | ||
352 | * read(4, "LF\2\1\1\0\0\0\0"... | ||
353 | * ...and we avoided seeking on the fd! :) | ||
354 | */ | ||
350 | xstate->signature_skipped = 0; | 355 | xstate->signature_skipped = 0; |
351 | image = xmalloc_read(xstate->src_fd, maxsz_p); | 356 | image = xmalloc_read_with_initial_buf( |
357 | xstate->src_fd, | ||
358 | maxsz_p, | ||
359 | xmemdup(&xstate->magic, xstate->signature_skipped), | ||
360 | xstate->signature_skipped | ||
361 | ); | ||
352 | } | 362 | } |
353 | 363 | ||
354 | if (!image) | 364 | if (!image) |
diff --git a/include/bb_archive.h b/include/bb_archive.h index 561dd0c9d..9b1db5b3e 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h | |||
@@ -235,6 +235,12 @@ typedef struct transformer_state_t { | |||
235 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ | 235 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ |
236 | uint32_t crc32; | 236 | uint32_t crc32; |
237 | time_t mtime; /* gunzip code may set this on exit */ | 237 | time_t mtime; /* gunzip code may set this on exit */ |
238 | |||
239 | union { /* if we read magic, it's saved here */ | ||
240 | uint8_t b[8]; | ||
241 | uint16_t b16[4]; | ||
242 | uint32_t b32[2]; | ||
243 | } magic; | ||
238 | } transformer_state_t; | 244 | } transformer_state_t; |
239 | 245 | ||
240 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; | 246 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; |
diff --git a/include/libbb.h b/include/libbb.h index 57cfce385..33766e989 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -881,6 +881,7 @@ extern ssize_t open_read_close(const char *filename, void *buf, size_t maxsz) FA | |||
881 | extern char *xmalloc_reads(int fd, size_t *maxsz_p) FAST_FUNC; | 881 | extern char *xmalloc_reads(int fd, size_t *maxsz_p) FAST_FUNC; |
882 | /* Reads block up to *maxsz_p (default: INT_MAX - 4095) */ | 882 | /* Reads block up to *maxsz_p (default: INT_MAX - 4095) */ |
883 | extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 883 | extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
884 | extern void *xmalloc_read_with_initial_buf(int fd, size_t *maxsz_p, char *buf, size_t total) FAST_FUNC; | ||
884 | /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ | 885 | /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ |
885 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 886 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
886 | /* Never returns NULL */ | 887 | /* Never returns NULL */ |
diff --git a/libbb/read_printf.c b/libbb/read_printf.c index b6a17cc36..cb582c080 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c | |||
@@ -102,10 +102,9 @@ char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p) | |||
102 | 102 | ||
103 | // Read (potentially big) files in one go. File size is estimated | 103 | // Read (potentially big) files in one go. File size is estimated |
104 | // by stat. Extra '\0' byte is appended. | 104 | // by stat. Extra '\0' byte is appended. |
105 | void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | 105 | void* FAST_FUNC xmalloc_read_with_initial_buf(int fd, size_t *maxsz_p, char *buf, size_t total) |
106 | { | 106 | { |
107 | char *buf; | 107 | size_t size, rd_size; |
108 | size_t size, rd_size, total; | ||
109 | size_t to_read; | 108 | size_t to_read; |
110 | struct stat st; | 109 | struct stat st; |
111 | 110 | ||
@@ -118,8 +117,6 @@ void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | |||
118 | /* In order to make such files readable, we add small const */ | 117 | /* In order to make such files readable, we add small const */ |
119 | size = (st.st_size | 0x3ff) + 1; | 118 | size = (st.st_size | 0x3ff) + 1; |
120 | 119 | ||
121 | total = 0; | ||
122 | buf = NULL; | ||
123 | while (1) { | 120 | while (1) { |
124 | if (to_read < size) | 121 | if (to_read < size) |
125 | size = to_read; | 122 | size = to_read; |
@@ -148,6 +145,11 @@ void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | |||
148 | return buf; | 145 | return buf; |
149 | } | 146 | } |
150 | 147 | ||
148 | void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | ||
149 | { | ||
150 | return xmalloc_read_with_initial_buf(fd, maxsz_p, NULL, 0); | ||
151 | } | ||
152 | |||
151 | #ifdef USING_LSEEK_TO_GET_SIZE | 153 | #ifdef USING_LSEEK_TO_GET_SIZE |
152 | /* Alternatively, file size can be obtained by lseek to the end. | 154 | /* Alternatively, file size can be obtained by lseek to the end. |
153 | * The code is slightly bigger. Retained in case fstat approach | 155 | * The code is slightly bigger. Retained in case fstat approach |