diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-10 23:06:00 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-10 23:06:00 +0000 |
commit | 0381d422d9b40c0cf887d299224c7759875aefd8 (patch) | |
tree | 764583282951c07bb6b611bef2858c5375647094 | |
parent | b6052724ffc9d45894147b70e7aff226938bd2d3 (diff) | |
download | busybox-w32-0381d422d9b40c0cf887d299224c7759875aefd8.tar.gz busybox-w32-0381d422d9b40c0cf887d299224c7759875aefd8.tar.bz2 busybox-w32-0381d422d9b40c0cf887d299224c7759875aefd8.zip |
dpkg_deb: slight code shrink
ar: reuse existing ar unpacking code
get_header_tar: handle autodetection for tiny .tar.gz files too
unarchive.h: do not include CONFIGed out things
function old new delta
get_header_tar 1521 1534 +13
dpkg_deb_main 400 380 -20
ar_main 260 196 -64
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 13/-84) Total: -71 bytes
-rw-r--r-- | archival/Config.in | 11 | ||||
-rw-r--r-- | archival/ar.c | 10 | ||||
-rw-r--r-- | archival/dpkg_deb.c | 29 | ||||
-rw-r--r-- | archival/libunarchive/filter_accept_list_reassign.c | 20 | ||||
-rw-r--r-- | archival/libunarchive/get_header_ar.c | 5 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar.c | 27 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar_gz.c | 1 | ||||
-rw-r--r-- | archival/libunarchive/unpack_ar_archive.c | 3 | ||||
-rw-r--r-- | include/unarchive.h | 4 |
9 files changed, 65 insertions, 45 deletions
diff --git a/archival/Config.in b/archival/Config.in index 4599b68d4..02daae1a0 100644 --- a/archival/Config.in +++ b/archival/Config.in | |||
@@ -90,10 +90,11 @@ config DPKG | |||
90 | bool "dpkg" | 90 | bool "dpkg" |
91 | default n | 91 | default n |
92 | help | 92 | help |
93 | dpkg is a medium-level tool to install, build, remove and manage Debian packages. | 93 | dpkg is a medium-level tool to install, build, remove and manage |
94 | Debian packages. | ||
94 | 95 | ||
95 | This implementation of dpkg has a number of limitations, you should use the | 96 | This implementation of dpkg has a number of limitations, |
96 | official dpkg if possible. | 97 | you should use the official dpkg if possible. |
97 | 98 | ||
98 | config DPKG_DEB | 99 | config DPKG_DEB |
99 | bool "dpkg_deb" | 100 | bool "dpkg_deb" |
@@ -103,8 +104,8 @@ config DPKG_DEB | |||
103 | 104 | ||
104 | This implementation of dpkg-deb cannot pack archives. | 105 | This implementation of dpkg-deb cannot pack archives. |
105 | 106 | ||
106 | Unless you have a specific application which requires dpkg-deb, you should | 107 | Unless you have a specific application which requires dpkg-deb, |
107 | probably say N here. | 108 | say N here. |
108 | 109 | ||
109 | config FEATURE_DPKG_DEB_EXTRACT_ONLY | 110 | config FEATURE_DPKG_DEB_EXTRACT_ONLY |
110 | bool "Extract only (-x)" | 111 | bool "Extract only (-x)" |
diff --git a/archival/ar.c b/archival/ar.c index d49329ce9..dbff6775e 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
@@ -45,7 +45,6 @@ int ar_main(int argc, char **argv) | |||
45 | 45 | ||
46 | archive_handle_t *archive_handle; | 46 | archive_handle_t *archive_handle; |
47 | unsigned opt; | 47 | unsigned opt; |
48 | char magic[8]; | ||
49 | 48 | ||
50 | archive_handle = init_handle(); | 49 | archive_handle = init_handle(); |
51 | 50 | ||
@@ -82,14 +81,7 @@ int ar_main(int argc, char **argv) | |||
82 | llist_add_to(&(archive_handle->accept), argv[optind++]); | 81 | llist_add_to(&(archive_handle->accept), argv[optind++]); |
83 | } | 82 | } |
84 | 83 | ||
85 | xread(archive_handle->src_fd, magic, 7); | 84 | unpack_ar_archive(archive_handle); |
86 | if (strncmp(magic, "!<arch>", 7) != 0) { | ||
87 | bb_error_msg_and_die("invalid ar magic"); | ||
88 | } | ||
89 | archive_handle->offset += 7; | ||
90 | |||
91 | while (get_header_ar(archive_handle) == EXIT_SUCCESS) | ||
92 | continue; | ||
93 | 85 | ||
94 | return EXIT_SUCCESS; | 86 | return EXIT_SUCCESS; |
95 | } | 87 | } |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index cbacc91f8..9e6340fd3 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -20,8 +20,8 @@ int dpkg_deb_main(int argc, char **argv) | |||
20 | archive_handle_t *tar_archive; | 20 | archive_handle_t *tar_archive; |
21 | llist_t *control_tar_llist = NULL; | 21 | llist_t *control_tar_llist = NULL; |
22 | unsigned opt; | 22 | unsigned opt; |
23 | const char *extract_dir = NULL; | 23 | const char *extract_dir; |
24 | short argcount = 1; | 24 | int need_args; |
25 | 25 | ||
26 | /* Setup the tar archive handle */ | 26 | /* Setup the tar archive handle */ |
27 | tar_archive = init_handle(); | 27 | tar_archive = init_handle(); |
@@ -43,17 +43,21 @@ int dpkg_deb_main(int argc, char **argv) | |||
43 | 43 | ||
44 | opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX"; | 44 | opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX"; |
45 | opt = getopt32(argv, "cefXx"); | 45 | opt = getopt32(argv, "cefXx"); |
46 | argv += optind; | ||
47 | argc -= optind; | ||
46 | 48 | ||
47 | if (opt & DPKG_DEB_OPT_CONTENTS) { | 49 | if (opt & DPKG_DEB_OPT_CONTENTS) { |
48 | tar_archive->action_header = header_verbose_list; | 50 | tar_archive->action_header = header_verbose_list; |
49 | } | 51 | } |
52 | extract_dir = NULL; | ||
53 | need_args = 1; | ||
50 | if (opt & DPKG_DEB_OPT_CONTROL) { | 54 | if (opt & DPKG_DEB_OPT_CONTROL) { |
51 | ar_archive->accept = control_tar_llist; | 55 | ar_archive->accept = control_tar_llist; |
52 | tar_archive->action_data = data_extract_all; | 56 | tar_archive->action_data = data_extract_all; |
53 | if (optind + 1 == argc) { | 57 | if (1 == argc) { |
54 | extract_dir = "./DEBIAN"; | 58 | extract_dir = "./DEBIAN"; |
55 | } else { | 59 | } else { |
56 | argcount++; | 60 | need_args++; |
57 | } | 61 | } |
58 | } | 62 | } |
59 | if (opt & DPKG_DEB_OPT_FIELD) { | 63 | if (opt & DPKG_DEB_OPT_FIELD) { |
@@ -70,28 +74,31 @@ int dpkg_deb_main(int argc, char **argv) | |||
70 | } | 74 | } |
71 | if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) { | 75 | if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) { |
72 | tar_archive->action_data = data_extract_all; | 76 | tar_archive->action_data = data_extract_all; |
73 | argcount = 2; | 77 | need_args = 2; |
74 | } | 78 | } |
75 | 79 | ||
76 | if ((optind + argcount) != argc) { | 80 | if (need_args != argc) { |
77 | bb_show_usage(); | 81 | bb_show_usage(); |
78 | } | 82 | } |
79 | 83 | ||
80 | tar_archive->src_fd = ar_archive->src_fd = xopen(argv[optind++], O_RDONLY); | 84 | tar_archive->src_fd = ar_archive->src_fd = xopen(argv[0], O_RDONLY); |
81 | 85 | ||
82 | /* Workout where to extract the files */ | 86 | /* Work out where to extract the files */ |
83 | /* 2nd argument is a dir name */ | 87 | /* 2nd argument is a dir name */ |
84 | if (argv[optind]) { | 88 | if (argv[1]) { |
85 | extract_dir = argv[optind]; | 89 | extract_dir = argv[1]; |
86 | } | 90 | } |
87 | if (extract_dir) { | 91 | if (extract_dir) { |
88 | mkdir(extract_dir, 0777); /* bb_make_directory(extract_dir, 0777, 0) */ | 92 | mkdir(extract_dir, 0777); /* bb_make_directory(extract_dir, 0777, 0) */ |
89 | xchdir(extract_dir); | 93 | xchdir(extract_dir); |
90 | } | 94 | } |
95 | |||
96 | /* Do it */ | ||
91 | unpack_ar_archive(ar_archive); | 97 | unpack_ar_archive(ar_archive); |
92 | 98 | ||
93 | /* Cleanup */ | 99 | /* Cleanup */ |
94 | close(ar_archive->src_fd); | 100 | if (ENABLE_FEATURE_CLEAN_UP) |
101 | close(ar_archive->src_fd); | ||
95 | 102 | ||
96 | return EXIT_SUCCESS; | 103 | return EXIT_SUCCESS; |
97 | } | 104 | } |
diff --git a/archival/libunarchive/filter_accept_list_reassign.c b/archival/libunarchive/filter_accept_list_reassign.c index 4f2d4cde5..4dbc2d13e 100644 --- a/archival/libunarchive/filter_accept_list_reassign.c +++ b/archival/libunarchive/filter_accept_list_reassign.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include "unarchive.h" | 9 | #include "unarchive.h" |
10 | 10 | ||
11 | /* Built and used only if ENABLE_DPKG || ENABLE_DPKG_DEB */ | ||
12 | |||
11 | /* | 13 | /* |
12 | * Reassign the subarchive metadata parser based on the filename extension | 14 | * Reassign the subarchive metadata parser based on the filename extension |
13 | * e.g. if its a .tar.gz modify archive_handle->sub_archive to process a .tar.gz | 15 | * e.g. if its a .tar.gz modify archive_handle->sub_archive to process a .tar.gz |
@@ -19,23 +21,25 @@ char FAST_FUNC filter_accept_list_reassign(archive_handle_t *archive_handle) | |||
19 | if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) { | 21 | if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) { |
20 | const char *name_ptr; | 22 | const char *name_ptr; |
21 | 23 | ||
22 | /* Extract the last 2 extensions */ | 24 | /* Find extension */ |
23 | name_ptr = strrchr(archive_handle->file_header->name, '.'); | 25 | name_ptr = strrchr(archive_handle->file_header->name, '.'); |
24 | 26 | ||
25 | /* Modify the subarchive handler based on the extension */ | 27 | /* Modify the subarchive handler based on the extension */ |
26 | #if ENABLE_FEATURE_DEB_TAR_GZ | 28 | if (ENABLE_FEATURE_DEB_TAR_GZ |
27 | if (strcmp(name_ptr, ".gz") == 0) { | 29 | && strcmp(name_ptr, ".gz") == 0 |
30 | ) { | ||
28 | archive_handle->action_data_subarchive = get_header_tar_gz; | 31 | archive_handle->action_data_subarchive = get_header_tar_gz; |
29 | return EXIT_SUCCESS; | 32 | return EXIT_SUCCESS; |
30 | } | 33 | } |
31 | #endif | 34 | if (ENABLE_FEATURE_DEB_TAR_BZ2 |
32 | #if ENABLE_FEATURE_DEB_TAR_BZ2 | 35 | && strcmp(name_ptr, ".bz2") == 0 |
33 | if (strcmp(name_ptr, ".bz2") == 0) { | 36 | ) { |
34 | archive_handle->action_data_subarchive = get_header_tar_bz2; | 37 | archive_handle->action_data_subarchive = get_header_tar_bz2; |
35 | return EXIT_SUCCESS; | 38 | return EXIT_SUCCESS; |
36 | } | 39 | } |
37 | #endif | 40 | if (ENABLE_FEATURE_DEB_TAR_LZMA |
38 | if (ENABLE_FEATURE_DEB_TAR_LZMA && !strcmp(name_ptr, ".lzma")) { | 41 | && strcmp(name_ptr, ".lzma") == 0 |
42 | ) { | ||
39 | archive_handle->action_data_subarchive = get_header_tar_lzma; | 43 | archive_handle->action_data_subarchive = get_header_tar_lzma; |
40 | return EXIT_SUCCESS; | 44 | return EXIT_SUCCESS; |
41 | } | 45 | } |
diff --git a/archival/libunarchive/get_header_ar.c b/archival/libunarchive/get_header_ar.c index 59fd34c73..d476a9d24 100644 --- a/archival/libunarchive/get_header_ar.c +++ b/archival/libunarchive/get_header_ar.c | |||
@@ -108,12 +108,13 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) | |||
108 | 108 | ||
109 | if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { | 109 | if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { |
110 | archive_handle->action_header(typed); | 110 | archive_handle->action_header(typed); |
111 | #if ENABLE_DPKG || ENABLE_DPKG_DEB | ||
111 | if (archive_handle->sub_archive) { | 112 | if (archive_handle->sub_archive) { |
112 | while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS) | 113 | while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS) |
113 | continue; | 114 | continue; |
114 | } else { | 115 | } else |
116 | #endif | ||
115 | archive_handle->action_data(archive_handle); | 117 | archive_handle->action_data(archive_handle); |
116 | } | ||
117 | } else { | 118 | } else { |
118 | data_skip(archive_handle); | 119 | data_skip(archive_handle); |
119 | } | 120 | } |
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index 69362f1cc..cf35d41a0 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c | |||
@@ -92,22 +92,32 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
92 | again_after_align: | 92 | again_after_align: |
93 | 93 | ||
94 | #if ENABLE_DESKTOP | 94 | #if ENABLE_DESKTOP |
95 | /* to prevent misdetection of bz2 sig */ | ||
96 | *(uint32_t*)(&tar) = 0; | ||
95 | i = full_read(archive_handle->src_fd, &tar, 512); | 97 | i = full_read(archive_handle->src_fd, &tar, 512); |
96 | /* If GNU tar sees EOF in above read, it says: | 98 | /* If GNU tar sees EOF in above read, it says: |
97 | * "tar: A lone zero block at N", where N = kilobyte | 99 | * "tar: A lone zero block at N", where N = kilobyte |
98 | * where EOF was met (not EOF block, actual EOF!), | 100 | * where EOF was met (not EOF block, actual EOF!), |
99 | * and tar will exit with error code 0. | 101 | * and exits with EXIT_SUCCESS. |
100 | * We will mimic exit(EXIT_SUCCESS), although we will not mimic | 102 | * We will mimic exit(EXIT_SUCCESS), although we will not mimic |
101 | * the message and we don't check whether we indeed | 103 | * the message and we don't check whether we indeed |
102 | * saw zero block directly before this. */ | 104 | * saw zero block directly before this. */ |
103 | if (i == 0) | 105 | if (i == 0) { |
104 | xfunc_error_retval = 0; | 106 | xfunc_error_retval = 0; |
105 | if (i != 512) | 107 | short_read: |
106 | bb_error_msg_and_die("short read"); | 108 | bb_error_msg_and_die("short read"); |
109 | } | ||
110 | if (i != 512) { | ||
111 | if (ENABLE_FEATURE_TAR_AUTODETECT) | ||
112 | goto autodetect; | ||
113 | goto short_read; | ||
114 | } | ||
115 | |||
107 | #else | 116 | #else |
108 | xread(archive_handle->src_fd, &tar, 512); | 117 | i = 512; |
118 | xread(archive_handle->src_fd, &tar, i); | ||
109 | #endif | 119 | #endif |
110 | archive_handle->offset += 512; | 120 | archive_handle->offset += i; |
111 | 121 | ||
112 | /* If there is no filename its an empty header */ | 122 | /* If there is no filename its an empty header */ |
113 | if (tar.name[0] == 0 && tar.prefix[0] == 0) { | 123 | if (tar.name[0] == 0 && tar.prefix[0] == 0) { |
@@ -133,6 +143,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
133 | #if ENABLE_FEATURE_TAR_AUTODETECT | 143 | #if ENABLE_FEATURE_TAR_AUTODETECT |
134 | char FAST_FUNC (*get_header_ptr)(archive_handle_t *); | 144 | char FAST_FUNC (*get_header_ptr)(archive_handle_t *); |
135 | 145 | ||
146 | USE_DESKTOP(autodetect:) | ||
136 | /* tar gz/bz autodetect: check for gz/bz2 magic. | 147 | /* tar gz/bz autodetect: check for gz/bz2 magic. |
137 | * If we see the magic, and it is the very first block, | 148 | * If we see the magic, and it is the very first block, |
138 | * we can switch to get_header_tar_gz/bz2/lzma(). | 149 | * we can switch to get_header_tar_gz/bz2/lzma(). |
@@ -154,7 +165,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
154 | /* Two different causes for lseek() != 0: | 165 | /* Two different causes for lseek() != 0: |
155 | * unseekable fd (would like to support that too, but...), | 166 | * unseekable fd (would like to support that too, but...), |
156 | * or not first block (false positive, it's not .gz/.bz2!) */ | 167 | * or not first block (false positive, it's not .gz/.bz2!) */ |
157 | if (lseek(archive_handle->src_fd, -512, SEEK_CUR) != 0) | 168 | if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0) |
158 | goto err; | 169 | goto err; |
159 | while (get_header_ptr(archive_handle) == EXIT_SUCCESS) | 170 | while (get_header_ptr(archive_handle) == EXIT_SUCCESS) |
160 | continue; | 171 | continue; |
@@ -328,7 +339,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
328 | p_linkname = NULL; | 339 | p_linkname = NULL; |
329 | } | 340 | } |
330 | #endif | 341 | #endif |
331 | if (!strncmp(file_header->name, "/../"+1, 3) | 342 | if (strncmp(file_header->name, "/../"+1, 3) == 0 |
332 | || strstr(file_header->name, "/../") | 343 | || strstr(file_header->name, "/../") |
333 | ) { | 344 | ) { |
334 | bb_error_msg_and_die("name with '..' encountered: '%s'", | 345 | bb_error_msg_and_die("name with '..' encountered: '%s'", |
@@ -340,7 +351,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
340 | cp = last_char_is(file_header->name, '/'); | 351 | cp = last_char_is(file_header->name, '/'); |
341 | 352 | ||
342 | if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { | 353 | if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { |
343 | archive_handle->action_header(archive_handle->file_header); | 354 | archive_handle->action_header(/*archive_handle->*/ file_header); |
344 | /* Note that we kill the '/' only after action_header() */ | 355 | /* Note that we kill the '/' only after action_header() */ |
345 | /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */ | 356 | /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */ |
346 | if (cp) *cp = '\0'; | 357 | if (cp) *cp = '\0'; |
diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c index 086c6df42..e88b720a8 100644 --- a/archival/libunarchive/get_header_tar_gz.c +++ b/archival/libunarchive/get_header_tar_gz.c | |||
@@ -20,6 +20,7 @@ char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle) | |||
20 | * need the header. */ | 20 | * need the header. */ |
21 | #if BB_MMU | 21 | #if BB_MMU |
22 | xread(archive_handle->src_fd, &magic, 2); | 22 | xread(archive_handle->src_fd, &magic, 2); |
23 | /* Can skip this check, but error message will be less clear */ | ||
23 | if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { | 24 | if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { |
24 | bb_error_msg_and_die("invalid gzip magic"); | 25 | bb_error_msg_and_die("invalid gzip magic"); |
25 | } | 26 | } |
diff --git a/archival/libunarchive/unpack_ar_archive.c b/archival/libunarchive/unpack_ar_archive.c index 9c2f68b14..dc2eec223 100644 --- a/archival/libunarchive/unpack_ar_archive.c +++ b/archival/libunarchive/unpack_ar_archive.c | |||
@@ -16,5 +16,6 @@ void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) | |||
16 | } | 16 | } |
17 | ar_archive->offset += 7; | 17 | ar_archive->offset += 7; |
18 | 18 | ||
19 | while (get_header_ar(ar_archive) == EXIT_SUCCESS); | 19 | while (get_header_ar(ar_archive) == EXIT_SUCCESS) |
20 | continue; | ||
20 | } | 21 | } |
diff --git a/include/unarchive.h b/include/unarchive.h index 0e380db08..5b71d3e62 100644 --- a/include/unarchive.h +++ b/include/unarchive.h | |||
@@ -47,11 +47,13 @@ typedef struct archive_handle_t { | |||
47 | /* Process the data component, e.g. extract to filesystem */ | 47 | /* Process the data component, e.g. extract to filesystem */ |
48 | void FAST_FUNC (*action_data)(struct archive_handle_t *); | 48 | void FAST_FUNC (*action_data)(struct archive_handle_t *); |
49 | 49 | ||
50 | #if ENABLE_DPKG || ENABLE_DPKG_DEB | ||
51 | /* "subarchive" is used only by dpkg[-deb] applets */ | ||
50 | /* How to process any sub archive, e.g. get_header_tar_gz */ | 52 | /* How to process any sub archive, e.g. get_header_tar_gz */ |
51 | char FAST_FUNC (*action_data_subarchive)(struct archive_handle_t *); | 53 | char FAST_FUNC (*action_data_subarchive)(struct archive_handle_t *); |
52 | |||
53 | /* Contains the handle to a sub archive */ | 54 | /* Contains the handle to a sub archive */ |
54 | struct archive_handle_t *sub_archive; | 55 | struct archive_handle_t *sub_archive; |
56 | #endif | ||
55 | 57 | ||
56 | /* The raw stream as read from disk or stdin */ | 58 | /* The raw stream as read from disk or stdin */ |
57 | int src_fd; | 59 | int src_fd; |