diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-03-06 16:23:50 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2012-03-06 16:23:50 +0100 |
commit | 59655077c5bf176f01d8d277665ebb92263704ed (patch) | |
tree | 0d4393ea09ebe90e35866d27041faf6372f6e87e | |
parent | 17eedcad9406c43beddab3906c8c693626c351fb (diff) | |
download | busybox-w32-59655077c5bf176f01d8d277665ebb92263704ed.tar.gz busybox-w32-59655077c5bf176f01d8d277665ebb92263704ed.tar.bz2 busybox-w32-59655077c5bf176f01d8d277665ebb92263704ed.zip |
preparatory cleanups for seamless uncompression improvements
unpack_gz_stream_with_info: fix buggy error check
man: fix possible accesses past the end of a string
move seamless uncompression helpers from read_printf.c to open_transformer.c
function old new delta
show_manpage 153 212 +59
unpack_gz_stream_with_info 520 539 +19
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/libarchive/decompress_uncompress.c | 12 | ||||
-rw-r--r-- | archival/libarchive/decompress_unzip.c | 26 | ||||
-rw-r--r-- | archival/libarchive/open_transformer.c | 140 | ||||
-rw-r--r-- | include/libbb.h | 8 | ||||
-rw-r--r-- | libbb/read_printf.c | 139 | ||||
-rw-r--r-- | miscutils/man.c | 41 |
6 files changed, 187 insertions, 179 deletions
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index c6040d04b..289f9e233 100644 --- a/archival/libarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c | |||
@@ -73,7 +73,7 @@ | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | IF_DESKTOP(long long) int FAST_FUNC | 75 | IF_DESKTOP(long long) int FAST_FUNC |
76 | unpack_Z_stream(int fd_in, int fd_out) | 76 | unpack_Z_stream(int src_fd, int dst_fd) |
77 | { | 77 | { |
78 | IF_DESKTOP(long long total_written = 0;) | 78 | IF_DESKTOP(long long total_written = 0;) |
79 | IF_DESKTOP(long long) int retval = -1; | 79 | IF_DESKTOP(long long) int retval = -1; |
@@ -105,14 +105,14 @@ unpack_Z_stream(int fd_in, int fd_out) | |||
105 | 105 | ||
106 | inbuf = xzalloc(IBUFSIZ + 64); | 106 | inbuf = xzalloc(IBUFSIZ + 64); |
107 | outbuf = xzalloc(OBUFSIZ + 2048); | 107 | outbuf = xzalloc(OBUFSIZ + 2048); |
108 | htab = xzalloc(HSIZE); /* wsn't zeroed out before, maybe can xmalloc? */ | 108 | htab = xzalloc(HSIZE); /* wasn't zeroed out before, maybe can xmalloc? */ |
109 | codetab = xzalloc(HSIZE * sizeof(codetab[0])); | 109 | codetab = xzalloc(HSIZE * sizeof(codetab[0])); |
110 | 110 | ||
111 | insize = 0; | 111 | insize = 0; |
112 | 112 | ||
113 | /* xread isn't good here, we have to return - caller may want | 113 | /* xread isn't good here, we have to return - caller may want |
114 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ | 114 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ |
115 | if (full_read(fd_in, inbuf, 1) != 1) { | 115 | if (full_read(src_fd, inbuf, 1) != 1) { |
116 | bb_error_msg("short read"); | 116 | bb_error_msg("short read"); |
117 | goto err; | 117 | goto err; |
118 | } | 118 | } |
@@ -162,7 +162,7 @@ unpack_Z_stream(int fd_in, int fd_out) | |||
162 | } | 162 | } |
163 | 163 | ||
164 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { | 164 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { |
165 | rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ); | 165 | rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ); |
166 | if (rsize < 0) | 166 | if (rsize < 0) |
167 | bb_error_msg_and_die(bb_msg_read_error); | 167 | bb_error_msg_and_die(bb_msg_read_error); |
168 | insize += rsize; | 168 | insize += rsize; |
@@ -268,7 +268,7 @@ unpack_Z_stream(int fd_in, int fd_out) | |||
268 | } | 268 | } |
269 | 269 | ||
270 | if (outpos >= OBUFSIZ) { | 270 | if (outpos >= OBUFSIZ) { |
271 | xwrite(fd_out, outbuf, outpos); | 271 | xwrite(dst_fd, outbuf, outpos); |
272 | IF_DESKTOP(total_written += outpos;) | 272 | IF_DESKTOP(total_written += outpos;) |
273 | outpos = 0; | 273 | outpos = 0; |
274 | } | 274 | } |
@@ -296,7 +296,7 @@ unpack_Z_stream(int fd_in, int fd_out) | |||
296 | } while (rsize > 0); | 296 | } while (rsize > 0); |
297 | 297 | ||
298 | if (outpos > 0) { | 298 | if (outpos > 0) { |
299 | xwrite(fd_out, outbuf, outpos); | 299 | xwrite(dst_fd, outbuf, outpos); |
300 | IF_DESKTOP(total_written += outpos;) | 300 | IF_DESKTOP(total_written += outpos;) |
301 | } | 301 | } |
302 | 302 | ||
diff --git a/archival/libarchive/decompress_unzip.c b/archival/libarchive/decompress_unzip.c index aa5d22d0a..50873e3f6 100644 --- a/archival/libarchive/decompress_unzip.c +++ b/archival/libarchive/decompress_unzip.c | |||
@@ -1182,33 +1182,37 @@ static int check_header_gzip(STATE_PARAM unpack_info_t *info) | |||
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | IF_DESKTOP(long long) int FAST_FUNC | 1184 | IF_DESKTOP(long long) int FAST_FUNC |
1185 | unpack_gz_stream_with_info(int in, int out, unpack_info_t *info) | 1185 | unpack_gz_stream_with_info(int src_fd, int dst_fd, unpack_info_t *info) |
1186 | { | 1186 | { |
1187 | uint32_t v32; | 1187 | uint32_t v32; |
1188 | IF_DESKTOP(long long) int n; | 1188 | IF_DESKTOP(long long) int total, n; |
1189 | DECLARE_STATE; | 1189 | DECLARE_STATE; |
1190 | 1190 | ||
1191 | n = 0; | 1191 | total = 0; |
1192 | 1192 | ||
1193 | ALLOC_STATE; | 1193 | ALLOC_STATE; |
1194 | to_read = -1; | 1194 | to_read = -1; |
1195 | // bytebuffer_max = 0x8000; | 1195 | // bytebuffer_max = 0x8000; |
1196 | bytebuffer = xmalloc(bytebuffer_max); | 1196 | bytebuffer = xmalloc(bytebuffer_max); |
1197 | gunzip_src_fd = in; | 1197 | gunzip_src_fd = src_fd; |
1198 | 1198 | ||
1199 | again: | 1199 | again: |
1200 | if (!check_header_gzip(PASS_STATE info)) { | 1200 | if (!check_header_gzip(PASS_STATE info)) { |
1201 | bb_error_msg("corrupted data"); | 1201 | bb_error_msg("corrupted data"); |
1202 | n = -1; | 1202 | total = -1; |
1203 | goto ret; | 1203 | goto ret; |
1204 | } | 1204 | } |
1205 | n += inflate_unzip_internal(PASS_STATE in, out); | 1205 | |
1206 | if (n < 0) | 1206 | n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd); |
1207 | if (n < 0) { | ||
1208 | total = -1; | ||
1207 | goto ret; | 1209 | goto ret; |
1210 | } | ||
1211 | total += n; | ||
1208 | 1212 | ||
1209 | if (!top_up(PASS_STATE 8)) { | 1213 | if (!top_up(PASS_STATE 8)) { |
1210 | bb_error_msg("corrupted data"); | 1214 | bb_error_msg("corrupted data"); |
1211 | n = -1; | 1215 | total = -1; |
1212 | goto ret; | 1216 | goto ret; |
1213 | } | 1217 | } |
1214 | 1218 | ||
@@ -1216,7 +1220,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info) | |||
1216 | v32 = buffer_read_le_u32(PASS_STATE_ONLY); | 1220 | v32 = buffer_read_le_u32(PASS_STATE_ONLY); |
1217 | if ((~gunzip_crc) != v32) { | 1221 | if ((~gunzip_crc) != v32) { |
1218 | bb_error_msg("crc error"); | 1222 | bb_error_msg("crc error"); |
1219 | n = -1; | 1223 | total = -1; |
1220 | goto ret; | 1224 | goto ret; |
1221 | } | 1225 | } |
1222 | 1226 | ||
@@ -1224,7 +1228,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info) | |||
1224 | v32 = buffer_read_le_u32(PASS_STATE_ONLY); | 1228 | v32 = buffer_read_le_u32(PASS_STATE_ONLY); |
1225 | if ((uint32_t)gunzip_bytes_out != v32) { | 1229 | if ((uint32_t)gunzip_bytes_out != v32) { |
1226 | bb_error_msg("incorrect length"); | 1230 | bb_error_msg("incorrect length"); |
1227 | n = -1; | 1231 | total = -1; |
1228 | } | 1232 | } |
1229 | 1233 | ||
1230 | if (!top_up(PASS_STATE 2)) | 1234 | if (!top_up(PASS_STATE 2)) |
@@ -1242,7 +1246,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info) | |||
1242 | ret: | 1246 | ret: |
1243 | free(bytebuffer); | 1247 | free(bytebuffer); |
1244 | DEALLOC_STATE; | 1248 | DEALLOC_STATE; |
1245 | return n; | 1249 | return total; |
1246 | } | 1250 | } |
1247 | 1251 | ||
1248 | IF_DESKTOP(long long) int FAST_FUNC | 1252 | IF_DESKTOP(long long) int FAST_FUNC |
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index aa8c1021c..743ffee02 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -6,6 +6,16 @@ | |||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "bb_archive.h" | 7 | #include "bb_archive.h" |
8 | 8 | ||
9 | #define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \ | ||
10 | || ENABLE_FEATURE_SEAMLESS_BZ2 \ | ||
11 | || ENABLE_FEATURE_SEAMLESS_GZ \ | ||
12 | /* || ENABLE_FEATURE_SEAMLESS_Z */ \ | ||
13 | ) | ||
14 | |||
15 | #if ZIPPED | ||
16 | # include "bb_archive.h" | ||
17 | #endif | ||
18 | |||
9 | /* transformer(), more than meets the eye */ | 19 | /* transformer(), more than meets the eye */ |
10 | /* | 20 | /* |
11 | * On MMU machine, the transform_prog is removed by macro magic | 21 | * On MMU machine, the transform_prog is removed by macro magic |
@@ -52,3 +62,133 @@ void FAST_FUNC open_transformer(int fd, | |||
52 | close(fd_pipe.wr); /* don't want to write to the child */ | 62 | close(fd_pipe.wr); /* don't want to write to the child */ |
53 | xmove_fd(fd_pipe.rd, fd); | 63 | xmove_fd(fd_pipe.rd, fd); |
54 | } | 64 | } |
65 | |||
66 | |||
67 | /* Used by e.g. rpm which gives us a fd without filename, | ||
68 | * thus we can't guess the format from filename's extension. | ||
69 | */ | ||
70 | #if ZIPPED | ||
71 | void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) | ||
72 | { | ||
73 | const int fail_if_not_detected = 1; | ||
74 | union { | ||
75 | uint8_t b[4]; | ||
76 | uint16_t b16[2]; | ||
77 | uint32_t b32[1]; | ||
78 | } magic; | ||
79 | int offset = -2; | ||
80 | # if BB_MMU | ||
81 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); | ||
82 | enum { xformer_prog = 0 }; | ||
83 | # else | ||
84 | enum { xformer = 0 }; | ||
85 | const char *xformer_prog; | ||
86 | # endif | ||
87 | |||
88 | /* .gz and .bz2 both have 2-byte signature, and their | ||
89 | * unpack_XXX_stream wants this header skipped. */ | ||
90 | xread(fd, magic.b16, sizeof(magic.b16[0])); | ||
91 | if (ENABLE_FEATURE_SEAMLESS_GZ | ||
92 | && magic.b16[0] == GZIP_MAGIC | ||
93 | ) { | ||
94 | # if BB_MMU | ||
95 | xformer = unpack_gz_stream; | ||
96 | # else | ||
97 | xformer_prog = "gunzip"; | ||
98 | # endif | ||
99 | goto found_magic; | ||
100 | } | ||
101 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | ||
102 | && magic.b16[0] == BZIP2_MAGIC | ||
103 | ) { | ||
104 | # if BB_MMU | ||
105 | xformer = unpack_bz2_stream; | ||
106 | # else | ||
107 | xformer_prog = "bunzip2"; | ||
108 | # endif | ||
109 | goto found_magic; | ||
110 | } | ||
111 | if (ENABLE_FEATURE_SEAMLESS_XZ | ||
112 | && magic.b16[0] == XZ_MAGIC1 | ||
113 | ) { | ||
114 | offset = -6; | ||
115 | xread(fd, magic.b32, sizeof(magic.b32[0])); | ||
116 | if (magic.b32[0] == XZ_MAGIC2) { | ||
117 | # if BB_MMU | ||
118 | xformer = unpack_xz_stream; | ||
119 | /* unpack_xz_stream wants fd at position 6, no need to seek */ | ||
120 | //xlseek(fd, offset, SEEK_CUR); | ||
121 | # else | ||
122 | xformer_prog = "unxz"; | ||
123 | # endif | ||
124 | goto found_magic; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /* No known magic seen */ | ||
129 | if (fail_if_not_detected) | ||
130 | bb_error_msg_and_die("no gzip" | ||
131 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
132 | IF_FEATURE_SEAMLESS_XZ("/xz") | ||
133 | " magic"); | ||
134 | xlseek(fd, offset, SEEK_CUR); | ||
135 | return; | ||
136 | |||
137 | found_magic: | ||
138 | # if !BB_MMU | ||
139 | /* NOMMU version of open_transformer execs | ||
140 | * an external unzipper that wants | ||
141 | * file position at the start of the file */ | ||
142 | xlseek(fd, offset, SEEK_CUR); | ||
143 | # endif | ||
144 | open_transformer(fd, xformer, xformer_prog); | ||
145 | } | ||
146 | #endif /* ZIPPED */ | ||
147 | |||
148 | int FAST_FUNC open_zipped(const char *fname) | ||
149 | { | ||
150 | #if !ZIPPED | ||
151 | return open(fname, O_RDONLY); | ||
152 | #else | ||
153 | char *sfx; | ||
154 | int fd; | ||
155 | |||
156 | fd = open(fname, O_RDONLY); | ||
157 | if (fd < 0) | ||
158 | return fd; | ||
159 | |||
160 | sfx = strrchr(fname, '.'); | ||
161 | if (sfx) { | ||
162 | sfx++; | ||
163 | if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0) | ||
164 | /* .lzma has no header/signature, just trust it */ | ||
165 | open_transformer(fd, unpack_lzma_stream, "unlzma"); | ||
166 | else | ||
167 | if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0) | ||
168 | || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0) | ||
169 | || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0) | ||
170 | ) { | ||
171 | setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return fd; | ||
176 | #endif | ||
177 | } | ||
178 | |||
179 | void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) | ||
180 | { | ||
181 | int fd; | ||
182 | char *image; | ||
183 | |||
184 | fd = open_zipped(fname); | ||
185 | if (fd < 0) | ||
186 | return NULL; | ||
187 | |||
188 | image = xmalloc_read(fd, maxsz_p); | ||
189 | if (!image) | ||
190 | bb_perror_msg("read error from '%s'", fname); | ||
191 | close(fd); | ||
192 | |||
193 | return image; | ||
194 | } | ||
diff --git a/include/libbb.h b/include/libbb.h index f743bdfc6..c896e5484 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -713,6 +713,14 @@ extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | |||
713 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 713 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
714 | /* Never returns NULL */ | 714 | /* Never returns NULL */ |
715 | extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 715 | extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
716 | |||
717 | #define SEAMLESS_COMPRESSION (0 \ | ||
718 | || ENABLE_FEATURE_SEAMLESS_XZ \ | ||
719 | || ENABLE_FEATURE_SEAMLESS_LZMA \ | ||
720 | || ENABLE_FEATURE_SEAMLESS_BZ2 \ | ||
721 | || ENABLE_FEATURE_SEAMLESS_GZ \ | ||
722 | || ENABLE_FEATURE_SEAMLESS_Z) | ||
723 | |||
716 | /* Autodetects gzip/bzip2 formats. fd may be in the middle of the file! */ | 724 | /* Autodetects gzip/bzip2 formats. fd may be in the middle of the file! */ |
717 | #if ENABLE_FEATURE_SEAMLESS_LZMA \ | 725 | #if ENABLE_FEATURE_SEAMLESS_LZMA \ |
718 | || ENABLE_FEATURE_SEAMLESS_BZ2 \ | 726 | || ENABLE_FEATURE_SEAMLESS_BZ2 \ |
diff --git a/libbb/read_printf.c b/libbb/read_printf.c index 0bbf7802a..5ed6e3632 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c | |||
@@ -8,16 +8,6 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | #define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \ | ||
12 | || ENABLE_FEATURE_SEAMLESS_BZ2 \ | ||
13 | || ENABLE_FEATURE_SEAMLESS_GZ \ | ||
14 | /* || ENABLE_FEATURE_SEAMLESS_Z */ \ | ||
15 | ) | ||
16 | |||
17 | #if ZIPPED | ||
18 | # include "bb_archive.h" | ||
19 | #endif | ||
20 | |||
21 | 11 | ||
22 | /* Suppose that you are a shell. You start child processes. | 12 | /* Suppose that you are a shell. You start child processes. |
23 | * They work and eventually exit. You want to get user input. | 13 | * They work and eventually exit. You want to get user input. |
@@ -244,132 +234,3 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) | |||
244 | bb_perror_msg_and_die("can't read '%s'", filename); | 234 | bb_perror_msg_and_die("can't read '%s'", filename); |
245 | return buf; | 235 | return buf; |
246 | } | 236 | } |
247 | |||
248 | /* Used by e.g. rpm which gives us a fd without filename, | ||
249 | * thus we can't guess the format from filename's extension. | ||
250 | */ | ||
251 | #if ZIPPED | ||
252 | void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) | ||
253 | { | ||
254 | const int fail_if_not_detected = 1; | ||
255 | union { | ||
256 | uint8_t b[4]; | ||
257 | uint16_t b16[2]; | ||
258 | uint32_t b32[1]; | ||
259 | } magic; | ||
260 | int offset = -2; | ||
261 | # if BB_MMU | ||
262 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); | ||
263 | enum { xformer_prog = 0 }; | ||
264 | # else | ||
265 | enum { xformer = 0 }; | ||
266 | const char *xformer_prog; | ||
267 | # endif | ||
268 | |||
269 | /* .gz and .bz2 both have 2-byte signature, and their | ||
270 | * unpack_XXX_stream wants this header skipped. */ | ||
271 | xread(fd, magic.b16, sizeof(magic.b16[0])); | ||
272 | if (ENABLE_FEATURE_SEAMLESS_GZ | ||
273 | && magic.b16[0] == GZIP_MAGIC | ||
274 | ) { | ||
275 | # if BB_MMU | ||
276 | xformer = unpack_gz_stream; | ||
277 | # else | ||
278 | xformer_prog = "gunzip"; | ||
279 | # endif | ||
280 | goto found_magic; | ||
281 | } | ||
282 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | ||
283 | && magic.b16[0] == BZIP2_MAGIC | ||
284 | ) { | ||
285 | # if BB_MMU | ||
286 | xformer = unpack_bz2_stream; | ||
287 | # else | ||
288 | xformer_prog = "bunzip2"; | ||
289 | # endif | ||
290 | goto found_magic; | ||
291 | } | ||
292 | if (ENABLE_FEATURE_SEAMLESS_XZ | ||
293 | && magic.b16[0] == XZ_MAGIC1 | ||
294 | ) { | ||
295 | offset = -6; | ||
296 | xread(fd, magic.b32, sizeof(magic.b32[0])); | ||
297 | if (magic.b32[0] == XZ_MAGIC2) { | ||
298 | # if BB_MMU | ||
299 | xformer = unpack_xz_stream; | ||
300 | /* unpack_xz_stream wants fd at position 6, no need to seek */ | ||
301 | //xlseek(fd, offset, SEEK_CUR); | ||
302 | # else | ||
303 | xformer_prog = "unxz"; | ||
304 | # endif | ||
305 | goto found_magic; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | /* No known magic seen */ | ||
310 | if (fail_if_not_detected) | ||
311 | bb_error_msg_and_die("no gzip" | ||
312 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
313 | IF_FEATURE_SEAMLESS_XZ("/xz") | ||
314 | " magic"); | ||
315 | xlseek(fd, offset, SEEK_CUR); | ||
316 | return; | ||
317 | |||
318 | found_magic: | ||
319 | # if !BB_MMU | ||
320 | /* NOMMU version of open_transformer execs | ||
321 | * an external unzipper that wants | ||
322 | * file position at the start of the file */ | ||
323 | xlseek(fd, offset, SEEK_CUR); | ||
324 | # endif | ||
325 | open_transformer(fd, xformer, xformer_prog); | ||
326 | } | ||
327 | #endif /* ZIPPED */ | ||
328 | |||
329 | int FAST_FUNC open_zipped(const char *fname) | ||
330 | { | ||
331 | #if !ZIPPED | ||
332 | return open(fname, O_RDONLY); | ||
333 | #else | ||
334 | char *sfx; | ||
335 | int fd; | ||
336 | |||
337 | fd = open(fname, O_RDONLY); | ||
338 | if (fd < 0) | ||
339 | return fd; | ||
340 | |||
341 | sfx = strrchr(fname, '.'); | ||
342 | if (sfx) { | ||
343 | sfx++; | ||
344 | if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0) | ||
345 | /* .lzma has no header/signature, just trust it */ | ||
346 | open_transformer(fd, unpack_lzma_stream, "unlzma"); | ||
347 | else | ||
348 | if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0) | ||
349 | || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0) | ||
350 | || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0) | ||
351 | ) { | ||
352 | setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | return fd; | ||
357 | #endif | ||
358 | } | ||
359 | |||
360 | void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) | ||
361 | { | ||
362 | int fd; | ||
363 | char *image; | ||
364 | |||
365 | fd = open_zipped(fname); | ||
366 | if (fd < 0) | ||
367 | return NULL; | ||
368 | |||
369 | image = xmalloc_read(fd, maxsz_p); | ||
370 | if (!image) | ||
371 | bb_perror_msg("read error from '%s'", fname); | ||
372 | close(fd); | ||
373 | |||
374 | return image; | ||
375 | } | ||
diff --git a/miscutils/man.c b/miscutils/man.c index 3bf7e84b6..611466349 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
@@ -30,16 +30,6 @@ echo ".pl \n(nlu+10" | |||
30 | 30 | ||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #if ENABLE_FEATURE_SEAMLESS_LZMA | ||
34 | #define Z_SUFFIX ".lzma" | ||
35 | #elif ENABLE_FEATURE_SEAMLESS_BZ2 | ||
36 | #define Z_SUFFIX ".bz2" | ||
37 | #elif ENABLE_FEATURE_SEAMLESS_GZ | ||
38 | #define Z_SUFFIX ".gz" | ||
39 | #else | ||
40 | #define Z_SUFFIX "" | ||
41 | #endif | ||
42 | |||
43 | static int show_manpage(const char *pager, char *man_filename, int man, int level); | 33 | static int show_manpage(const char *pager, char *man_filename, int man, int level); |
44 | 34 | ||
45 | static int run_pipe(const char *pager, char *man_filename, int man, int level) | 35 | static int run_pipe(const char *pager, char *man_filename, int man, int level) |
@@ -102,7 +92,7 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level) | |||
102 | 92 | ||
103 | /* Links do not have .gz extensions, even if manpage | 93 | /* Links do not have .gz extensions, even if manpage |
104 | * is compressed */ | 94 | * is compressed */ |
105 | man_filename = xasprintf("%s/%s" Z_SUFFIX, man_filename, linkname); | 95 | man_filename = xasprintf("%s/%s", man_filename, linkname); |
106 | free(line); | 96 | free(line); |
107 | /* Note: we leak "new" man_filename string as well... */ | 97 | /* Note: we leak "new" man_filename string as well... */ |
108 | if (show_manpage(pager, man_filename, man, level + 1)) | 98 | if (show_manpage(pager, man_filename, man, level + 1)) |
@@ -124,32 +114,37 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level) | |||
124 | return 1; | 114 | return 1; |
125 | } | 115 | } |
126 | 116 | ||
127 | /* man_filename is of the form "/dir/dir/dir/name.s" Z_SUFFIX */ | 117 | /* man_filename is of the form "/dir/dir/dir/name.s" */ |
128 | static int show_manpage(const char *pager, char *man_filename, int man, int level) | 118 | static int show_manpage(const char *pager, char *man_filename, int man, int level) |
129 | { | 119 | { |
120 | #if SEAMLESS_COMPRESSION | ||
121 | /* We leak this allocation... */ | ||
122 | char *filename_with_zext = xasprintf("%s.lzma", man_filename); | ||
123 | char *ext = strrchr(filename_with_zext, '.') + 1; | ||
124 | #endif | ||
125 | |||
130 | #if ENABLE_FEATURE_SEAMLESS_LZMA | 126 | #if ENABLE_FEATURE_SEAMLESS_LZMA |
127 | if (run_pipe(pager, filename_with_zext, man, level)) | ||
128 | return 1; | ||
129 | #endif | ||
130 | #if ENABLE_FEATURE_SEAMLESS_XZ | ||
131 | strcpy(ext, "xz"); | ||
131 | if (run_pipe(pager, man_filename, man, level)) | 132 | if (run_pipe(pager, man_filename, man, level)) |
132 | return 1; | 133 | return 1; |
133 | #endif | 134 | #endif |
134 | |||
135 | #if ENABLE_FEATURE_SEAMLESS_BZ2 | 135 | #if ENABLE_FEATURE_SEAMLESS_BZ2 |
136 | #if ENABLE_FEATURE_SEAMLESS_LZMA | 136 | strcpy(ext, "bz2"); |
137 | strcpy(strrchr(man_filename, '.') + 1, "bz2"); | ||
138 | #endif | ||
139 | if (run_pipe(pager, man_filename, man, level)) | 137 | if (run_pipe(pager, man_filename, man, level)) |
140 | return 1; | 138 | return 1; |
141 | #endif | 139 | #endif |
142 | |||
143 | #if ENABLE_FEATURE_SEAMLESS_GZ | 140 | #if ENABLE_FEATURE_SEAMLESS_GZ |
144 | #if ENABLE_FEATURE_SEAMLESS_LZMA || ENABLE_FEATURE_SEAMLESS_BZ2 | 141 | strcpy(ext, "gz"); |
145 | strcpy(strrchr(man_filename, '.') + 1, "gz"); | ||
146 | #endif | ||
147 | if (run_pipe(pager, man_filename, man, level)) | 142 | if (run_pipe(pager, man_filename, man, level)) |
148 | return 1; | 143 | return 1; |
149 | #endif | 144 | #endif |
150 | 145 | ||
151 | #if ENABLE_FEATURE_SEAMLESS_LZMA || ENABLE_FEATURE_SEAMLESS_BZ2 || ENABLE_FEATURE_SEAMLESS_GZ | 146 | #if SEAMLESS_COMPRESSION |
152 | *strrchr(man_filename, '.') = '\0'; | 147 | ext[-1] = '\0'; |
153 | #endif | 148 | #endif |
154 | if (run_pipe(pager, man_filename, man, level)) | 149 | if (run_pipe(pager, man_filename, man, level)) |
155 | return 1; | 150 | return 1; |
@@ -262,7 +257,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
262 | /* Search for cat, then man page */ | 257 | /* Search for cat, then man page */ |
263 | while (cat0man1 < 2) { | 258 | while (cat0man1 < 2) { |
264 | int found_here; | 259 | int found_here; |
265 | man_filename = xasprintf("%s/%s%.*s/%s.%.*s" Z_SUFFIX, | 260 | man_filename = xasprintf("%s/%s%.*s/%s.%.*s", |
266 | cur_path, | 261 | cur_path, |
267 | "cat\0man" + (cat0man1 * 4), | 262 | "cat\0man" + (cat0man1 * 4), |
268 | sect_len, cur_sect, | 263 | sect_len, cur_sect, |