aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-10 23:06:00 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-10 23:06:00 +0000
commit0381d422d9b40c0cf887d299224c7759875aefd8 (patch)
tree764583282951c07bb6b611bef2858c5375647094
parentb6052724ffc9d45894147b70e7aff226938bd2d3 (diff)
downloadbusybox-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.in11
-rw-r--r--archival/ar.c10
-rw-r--r--archival/dpkg_deb.c29
-rw-r--r--archival/libunarchive/filter_accept_list_reassign.c20
-rw-r--r--archival/libunarchive/get_header_ar.c5
-rw-r--r--archival/libunarchive/get_header_tar.c27
-rw-r--r--archival/libunarchive/get_header_tar_gz.c1
-rw-r--r--archival/libunarchive/unpack_ar_archive.c3
-rw-r--r--include/unarchive.h4
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
98config DPKG_DEB 99config 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
109config FEATURE_DPKG_DEB_EXTRACT_ONLY 110config 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;