aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-09-25 02:47:48 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-09-25 02:47:48 +0000
commit7ca04f328e22fcbee4659d73f9a72dfdf1dd6a23 (patch)
treef38c7ef4317eea28c6abdb0adbbb286fe041711e
parentecfa290cfd4953598e6d91989bd66ac16e135f84 (diff)
downloadbusybox-w32-7ca04f328e22fcbee4659d73f9a72dfdf1dd6a23.tar.gz
busybox-w32-7ca04f328e22fcbee4659d73f9a72dfdf1dd6a23.tar.bz2
busybox-w32-7ca04f328e22fcbee4659d73f9a72dfdf1dd6a23.zip
New common unarchive code.
-rw-r--r--archival/ar.c123
-rw-r--r--archival/config.in6
-rw-r--r--archival/cpio.c216
-rw-r--r--archival/dpkg_deb.c139
-rw-r--r--archival/gunzip.c40
-rw-r--r--archival/libunarchive/Makefile.in43
-rw-r--r--archival/libunarchive/add_to_list.c15
-rw-r--r--archival/libunarchive/check_header_gzip.c75
-rw-r--r--archival/libunarchive/check_trailer_gzip.c62
-rw-r--r--archival/libunarchive/copy_file_chunk_fd.c33
-rw-r--r--archival/libunarchive/data_align.c13
-rw-r--r--archival/libunarchive/data_extract_all.c76
-rw-r--r--archival/libunarchive/data_extract_to_stdout.c8
-rw-r--r--archival/libunarchive/data_skip.c27
-rw-r--r--archival/libunarchive/decompress_unzip.c747
-rw-r--r--archival/libunarchive/filter_accept_all.c10
-rw-r--r--archival/libunarchive/filter_accept_list.c16
-rw-r--r--archival/libunarchive/filter_accept_reject_list.c34
-rw-r--r--archival/libunarchive/get_header_ar.c96
-rw-r--r--archival/libunarchive/get_header_tar.c111
-rw-r--r--archival/libunarchive/get_header_tar_gz.c73
-rw-r--r--archival/libunarchive/header_list.c7
-rw-r--r--archival/libunarchive/header_skip.c7
-rw-r--r--archival/libunarchive/header_verbose_list.c29
-rw-r--r--archival/libunarchive/init_handle.c18
-rw-r--r--archival/libunarchive/seek_sub_file.c22
-rw-r--r--archival/libunarchive/unpack_ar_archive.c34
-rw-r--r--archival/libunarchive/unzip.c747
-rw-r--r--archival/rpm2cpio.c57
-rw-r--r--archival/tar.c243
-rw-r--r--archival/unzip.c228
-rw-r--r--include/libbb.h21
-rw-r--r--include/unarchive.h109
-rw-r--r--libbb/Makefile.in30
-rw-r--r--libbb/unzip.c747
-rw-r--r--libbb/xfuncs.c56
36 files changed, 2420 insertions, 1898 deletions
diff --git a/archival/ar.c b/archival/ar.c
index ac8c41f96..b5fa7956e 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -21,41 +21,100 @@
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * 23 *
24 * There is no signle standard to adhere to so ar may not portable
25 * between different systems
26 * http://www.unix-systems.org/single_unix_specification_v2/xcu/ar.html
24 */ 27 */
28#include <sys/types.h>
25#include <fcntl.h> 29#include <fcntl.h>
30#include <fnmatch.h>
26#include <stdio.h> 31#include <stdio.h>
27#include <stdlib.h> 32#include <stdlib.h>
28#include <string.h> 33#include <string.h>
34#include <time.h>
35#include <utime.h>
36#include <unistd.h>
29#include <getopt.h> 37#include <getopt.h>
30#include "unarchive.h" 38#include "unarchive.h"
31#include "busybox.h" 39#include "busybox.h"
32 40
41static void header_verbose_list_ar(const file_header_t *file_header)
42{
43 const char *mode = mode_string(file_header->mode);
44 char *mtime;
45
46 mtime = ctime(&file_header->mtime);
47 mtime[16] = ' ';
48 memmove(&mtime[17], &mtime[20], 4);
49 mtime[21] = '\0';
50 printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid, (int) file_header->size, &mtime[4], file_header->name);
51}
52
53#if defined CONFIG_TAR | defined CONFIG_DPKG_DEB | defined CONFIG_CPIO
54/* This is simpler than data_extract_all */
55static void data_extract_regular_file(archive_handle_t *archive_handle)
56{
57 file_header_t *file_header;
58 int dst_fd;
59
60 file_header = archive_handle->file_header;
61 dst_fd = xopen(file_header->name, O_WRONLY | O_CREAT);
62 copy_file_chunk_fd(archive_handle->src_fd, dst_fd, file_header->size);
63 close(dst_fd);
64
65 chmod(file_header->name, file_header->mode);
66 chown(file_header->name, file_header->uid, file_header->gid);
67
68 if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
69 struct utimbuf t;
70 t.actime = t.modtime = file_header->mtime;
71 utime(file_header->name, &t);
72 }
73
74 return;
75}
76#endif
77
33extern int ar_main(int argc, char **argv) 78extern int ar_main(int argc, char **argv)
34{ 79{
35 FILE *src_stream = NULL; 80 archive_handle_t *archive_handle;
36 char **extract_names = NULL;
37 char ar_magic[8];
38 int extract_function = extract_unconditional;
39 int opt; 81 int opt;
40 int num_of_entries = 0;
41 extern off_t archive_offset;
42 82
43 while ((opt = getopt(argc, argv, "ovtpx")) != -1) { 83#if defined CONFIG_TAR | defined CONFIG_DPKG_DEB | defined CONFIG_CPIO
84 archive_handle = init_handle();
85#else
86 char magic[8];
87
88 archive_handle = xcalloc(1, sizeof(archive_handle_t));
89 archive_handle->filter = filter_accept_all;
90 archive_handle->action_data = data_skip;
91 archive_handle->action_header = header_skip;
92 archive_handle->file_header =xmalloc(sizeof(file_header_t));
93#endif
94
95 while ((opt = getopt(argc, argv, "covtpxX")) != -1) {
44 switch (opt) { 96 switch (opt) {
45 case 'o': 97 case 'p': /* print */
46 extract_function |= extract_preserve_date; 98 archive_handle->action_data = data_extract_to_stdout;
47 break; 99 break;
48 case 'v': 100 case 't': /* list contents */
49 extract_function |= extract_verbose_list; 101 archive_handle->action_header = header_list;
50 break; 102 break;
51 case 't': 103 case 'X':
52 extract_function |= extract_list; 104 archive_handle->action_header = header_verbose_list_ar;
105 case 'x': /* extract */
106#if defined CONFIG_TAR | defined CONFIG_DPKG_DEB | defined CONFIG_CPIO
107 archive_handle->action_data = data_extract_all;
108#else
109 archive_handle->action_data = data_extract_regular_file;
110#endif
53 break; 111 break;
54 case 'p': 112 /* Modifiers */
55 extract_function |= extract_to_stdout; 113 case 'o': /* preserve original dates */
114 archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
56 break; 115 break;
57 case 'x': 116 case 'v': /* verbose */
58 extract_function |= extract_all_to_fs; 117 archive_handle->action_header = header_verbose_list_ar;
59 break; 118 break;
60 default: 119 default:
61 show_usage(); 120 show_usage();
@@ -67,24 +126,26 @@ extern int ar_main(int argc, char **argv)
67 show_usage(); 126 show_usage();
68 } 127 }
69 128
70 src_stream = xfopen(argv[optind++], "r"); 129 archive_handle->src_fd = xopen(argv[optind++], O_RDONLY);
71 130
72 /* check ar magic */ 131 /* TODO: This is the same as in tar, seperate function ? */
73 fread(ar_magic, 1, 8, src_stream);
74 archive_offset = 8;
75 if (strncmp(ar_magic,"!<arch>",7) != 0) {
76 error_msg_and_die("invalid magic");
77 }
78
79 /* Create a list of files to extract */
80 while (optind < argc) { 132 while (optind < argc) {
81 extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); 133 archive_handle->filter = filter_accept_list;
82 extract_names[num_of_entries] = xstrdup(argv[optind]); 134 archive_handle->accept = add_to_list(archive_handle->accept, argv[optind]);
83 num_of_entries++;
84 extract_names[num_of_entries] = NULL;
85 optind++; 135 optind++;
86 } 136 }
87 137
88 unarchive(src_stream, stdout, &get_header_ar, extract_function, "./", extract_names, NULL); 138#if defined CONFIG_DPKG_DEB
139 unpack_ar_archive(archive_handle);
140#else
141 xread_all(archive_handle->src_fd, magic, 7);
142 if (strncmp(magic, "!<arch>", 7) != 0) {
143 error_msg_and_die("Invalid ar magic");
144 }
145 archive_handle->offset += 7;
146
147 while (get_header_ar(archive_handle) == EXIT_SUCCESS);
148#endif
149
89 return EXIT_SUCCESS; 150 return EXIT_SUCCESS;
90} 151}
diff --git a/archival/config.in b/archival/config.in
index 3de671514..dd97909f9 100644
--- a/archival/config.in
+++ b/archival/config.in
@@ -7,10 +7,16 @@ mainmenu_option next_comment
7comment 'Archival Utilities' 7comment 'Archival Utilities'
8 8
9bool 'ar' CONFIG_AR 9bool 'ar' CONFIG_AR
10if [ "$CONFIG_AR" = "y" ] ; then
11 bool ' Enable support for long filenames (not need for debs)' CONFIG_FEATURE_AR_LONG_FILENAMES
12fi
10bool 'bunzip2' CONFIG_BUNZIP2 13bool 'bunzip2' CONFIG_BUNZIP2
11bool 'cpio' CONFIG_CPIO 14bool 'cpio' CONFIG_CPIO
12bool 'dpkg' CONFIG_DPKG 15bool 'dpkg' CONFIG_DPKG
13bool 'dpkg_deb' CONFIG_DPKG_DEB 16bool 'dpkg_deb' CONFIG_DPKG_DEB
17if [ "$CONFIG_DPKG_DEB" = "y" ] ; then
18 bool ' -x support only' CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
19fi
14bool 'gunzip' CONFIG_GUNZIP 20bool 'gunzip' CONFIG_GUNZIP
15bool 'gzip' CONFIG_GZIP 21bool 'gzip' CONFIG_GZIP
16bool 'rpm2cpio' CONFIG_RPM2CPIO 22bool 'rpm2cpio' CONFIG_RPM2CPIO
diff --git a/archival/cpio.c b/archival/cpio.c
index baaa72ea1..761517516 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -31,66 +31,210 @@
31#include "unarchive.h" 31#include "unarchive.h"
32#include "busybox.h" 32#include "busybox.h"
33 33
34typedef struct hardlinks_s {
35 file_header_t *entry;
36 int inode;
37 struct hardlinks_s *next;
38} hardlinks_t;
39
34extern int cpio_main(int argc, char **argv) 40extern int cpio_main(int argc, char **argv)
35{ 41{
36 FILE *src_stream = stdin; 42 archive_handle_t *archive_handle;
37 char **extract_names = NULL; 43 int opt;
38 int extract_function = 0; 44
39 int num_of_entries = 0; 45 /* Initialise */
40 int opt = 0; 46 archive_handle = init_handle();
41 mode_t oldmask = 0; 47 archive_handle->src_fd = fileno(stdin);
48 archive_handle->action_header = header_list;
42 49
43 while ((opt = getopt(argc, argv, "idmuvtF:")) != -1) { 50 while ((opt = getopt(argc, argv, "idmuvtF:")) != -1) {
44 switch (opt) { 51 switch (opt) {
45 case 'i': // extract 52 case 'i': /* extract */
46 extract_function |= extract_all_to_fs; 53 archive_handle->action_data = data_extract_all;
47 break; 54 break;
48 case 'd': // create _leading_ directories 55 case 'd': /* create _leading_ directories */
49 extract_function |= extract_create_leading_dirs; 56 archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS;
50 oldmask = umask(077); /* Make make_directory act like GNU cpio */
51 break; 57 break;
52 case 'm': // preserve modification time 58 case 'm': /* preserve modification time */
53 extract_function |= extract_preserve_date; 59 archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
54 break; 60 break;
55 case 'v': // verbosly list files 61 case 'v': /* verbosly list files */
56 extract_function |= extract_verbose_list; 62 archive_handle->action_header = header_verbose_list;
57 break; 63 break;
58 case 'u': // unconditional 64 case 'u': /* unconditional */
59 extract_function |= extract_unconditional; 65 archive_handle->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
60 break; 66 break;
61 case 't': // list files 67 case 't': /* list files */
62 extract_function |= extract_list; 68 archive_handle->action_header = header_list;
63 break; 69 break;
64 case 'F': 70 case 'F':
65 src_stream = xfopen(optarg, "r"); 71 archive_handle->src_fd = xopen(optarg, O_RDONLY);
66 break; 72 break;
67 default: 73 default:
68 show_usage(); 74 show_usage();
69 } 75 }
70 } 76 }
71 77
72 if ((extract_function & extract_all_to_fs) && (extract_function & extract_list)) { 78 while (optind < argc) {
73 extract_function ^= extract_all_to_fs; /* If specify t, don't extract*/ 79 archive_handle->filter = filter_accept_list;
80 archive_handle->accept = add_to_list(archive_handle->accept, argv[optind]);
81 optind++;
74 } 82 }
75 83
76 if ((extract_function & extract_all_to_fs) && (extract_function & extract_verbose_list)) { 84 while (1) {
77 /* The meaning of v changes on extract */ 85 static hardlinks_t *saved_hardlinks = NULL;
78 extract_function ^= extract_verbose_list; 86 static unsigned short pending_hardlinks = 0;
79 extract_function |= extract_list; 87 file_header_t *file_header = archive_handle->file_header;
88 char cpio_header[110];
89 int namesize;
90 char dummy[16];
91 int major, minor, nlink, inode;
92 char extract_flag;
93
94 if (pending_hardlinks) { /* Deal with any pending hardlinks */
95 hardlinks_t *tmp;
96 hardlinks_t *oldtmp;
97
98 tmp = saved_hardlinks;
99 oldtmp = NULL;
100
101 while (tmp) {
102 error_msg_and_die("need to fix this\n");
103 if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */
104 file_header = tmp->entry;
105 if (oldtmp) {
106 oldtmp->next = tmp->next; /* Remove item from linked list */
107 } else {
108 saved_hardlinks = tmp->next;
109 }
110 free(tmp);
111 continue;
112 }
113 oldtmp = tmp;
114 tmp = tmp->next;
115 }
116 pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */
80 } 117 }
81 118
82 while (optind < argc) { 119 /* There can be padding before archive header */
83 extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); 120 archive_handle->offset += data_align(archive_handle->src_fd, archive_handle->offset, 4);
84 extract_names[num_of_entries] = xstrdup(argv[optind]); 121
85 num_of_entries++; 122 if (xread_all_eof(archive_handle->src_fd, cpio_header, 110) == 0) {
86 extract_names[num_of_entries] = NULL; 123 return(EXIT_FAILURE);
87 optind++; 124 }
125 archive_handle->offset += 110;
126
127 if (strncmp(&cpio_header[0], "07070", 5) != 0) {
128 printf("cpio header is %x-%x-%x-%x-%x\n",
129 cpio_header[0],
130 cpio_header[1],
131 cpio_header[2],
132 cpio_header[3],
133 cpio_header[4]);
134 error_msg_and_die("Unsupported cpio format");
135 }
136
137 if ((cpio_header[5] != '1') && (cpio_header[5] != '2')) {
138 error_msg_and_die("Unsupported cpio format, use newc or crc");
139 }
140
141 sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
142 dummy, &inode, (unsigned int*)&file_header->mode,
143 (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
144 &nlink, &file_header->mtime, &file_header->size,
145 dummy, &major, &minor, &namesize, dummy);
146
147 file_header->name = (char *) xmalloc(namesize + 1);
148 xread(archive_handle->src_fd, file_header->name, namesize); /* Read in filename */
149 file_header->name[namesize] = '\0';
150 archive_handle->offset += namesize;
151
152 /* Update offset amount and skip padding before file contents */
153 archive_handle->offset += data_align(archive_handle->src_fd, archive_handle->offset, 4);
154
155 if (strcmp(file_header->name, "TRAILER!!!") == 0) {
156 printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */
157 if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
158 hardlinks_t *tmp = saved_hardlinks;
159 hardlinks_t *oldtmp = NULL;
160 while (tmp) {
161 error_msg("%s not created: cannot resolve hardlink", tmp->entry->name);
162 oldtmp = tmp;
163 tmp = tmp->next;
164 free (oldtmp->entry->name);
165 free (oldtmp->entry);
166 free (oldtmp);
167 }
168 saved_hardlinks = NULL;
169 pending_hardlinks = 0;
88 } 170 }
171 return(EXIT_FAILURE);
172 }
173
174 if (S_ISLNK(file_header->mode)) {
175 file_header->link_name = (char *) xmalloc(file_header->size + 1);
176 xread(archive_handle->src_fd, file_header->link_name, file_header->size);
177 file_header->link_name[file_header->size] = '\0';
178 archive_handle->offset += file_header->size;
179 file_header->size = 0; /* Stop possible seeks in future */
180 }
181 if (nlink > 1 && !S_ISDIR(file_header->mode)) {
182 if (file_header->size == 0) { /* Put file on a linked list for later */
183 hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
184 new->next = saved_hardlinks;
185 new->inode = inode;
186 new->entry = file_header;
187 saved_hardlinks = new;
188 continue;
189 } else { /* Found the file with data in */
190 hardlinks_t *tmp = saved_hardlinks;
191 pending_hardlinks = 1;
192 while (tmp) {
193 if (tmp->inode == inode) {
194 tmp->entry->link_name = xstrdup(file_header->name);
195 nlink--;
196 }
197 tmp = tmp->next;
198 }
199 if (nlink > 1) {
200 error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
201 }
202 }
203 }
204 file_header->device = (major << 8) | minor;
205
206 extract_flag = FALSE;
207 if (archive_handle->filter(archive_handle->accept, archive_handle->reject, file_header->name) == EXIT_SUCCESS) {
208 struct stat statbuf;
89 209
90 unarchive(src_stream, stdout, &get_header_cpio, extract_function, "./", extract_names, NULL); 210 extract_flag = TRUE;
91 if (oldmask) { 211
92 umask(oldmask); /* Restore umask if we changed it */ 212 /* Check if the file already exists */
213 if (lstat (file_header->name, &statbuf) == 0) {
214 if ((archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) || (statbuf.st_mtime < file_header->mtime)) {
215 /* Remove file if flag set or its older than the file to be extracted */
216 if (unlink(file_header->name) == -1) {
217 perror_msg_and_die("Couldnt remove old file");
218 }
219 } else {
220 if (! archive_handle->flags & ARCHIVE_EXTRACT_QUIET) {
221 error_msg("%s not created: newer or same age file exists", file_header->name);
222 }
223 extract_flag = FALSE;
224 }
225 }
226 archive_handle->action_header(file_header);
227 }
228
229 archive_handle->action_header(file_header);
230 if (extract_flag) {
231 archive_handle->action_data(archive_handle);
232 } else {
233 data_skip(archive_handle);
234 }
235 archive_handle->offset += file_header->size;
93 } 236 }
94 return EXIT_SUCCESS; 237
238 return(EXIT_SUCCESS);
95} 239}
96 240
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c
index 29692f7d7..06a810cc1 100644
--- a/archival/dpkg_deb.c
+++ b/archival/dpkg_deb.c
@@ -13,119 +13,100 @@
13 * along with this program; if not, write to the Free Software 13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */ 15 */
16 16#include <fcntl.h>
17#include <stdlib.h> 17#include <stdlib.h>
18#include <string.h> 18#include <string.h>
19#include <unistd.h>
19#include <getopt.h> 20#include <getopt.h>
20#include "unarchive.h" 21#include "unarchive.h"
21#include "busybox.h" 22#include "busybox.h"
22 23
23extern int dpkg_deb_main(int argc, char **argv) 24extern int dpkg_deb_main(int argc, char **argv)
24{ 25{
25 char *prefix = NULL; 26 archive_handle_t *ar_archive;
26 char *filename = NULL; 27 archive_handle_t *tar_gz_archive;
27 char *output_buffer = NULL;
28 int opt = 0; 28 int opt = 0;
29 int arg_type = 0; 29#ifndef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
30 int deb_extract_funct = extract_create_leading_dirs | extract_unconditional; 30 const llist_t *control_tar_gz_llist = add_to_list(NULL, "control.tar.gz");
31#endif
32#ifndef CONFIG_AR
33 char magic[7];
34#endif
35
36 /* a .deb file is an ar archive that contain three files,
37 * data.tar.gz, control.tar.gz and debian
38 */
31 39
32 const int arg_type_prefix = 1; 40 /* Setup the tar archive handle */
33 const int arg_type_field = 2; 41 tar_gz_archive = init_handle();
34 const int arg_type_filename = 4;
35// const int arg_type_un_ar_gz = 8;
36 42
37 while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { 43 /* Setup an ar archive handle that refers to the gzip sub archive */
44 ar_archive = init_handle();
45 ar_archive->action_data_subarchive = get_header_tar_gz;
46 ar_archive->sub_archive = tar_gz_archive;
47 ar_archive->filter = filter_accept_list;
48 ar_archive->accept = add_to_list(NULL, "data.tar.gz");
49
50#ifndef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
51 while ((opt = getopt(argc, argv, "cefXx")) != -1) {
52#else
53 while ((opt = getopt(argc, argv, "x")) != -1) {
54#endif
38 switch (opt) { 55 switch (opt) {
56#ifndef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
39 case 'c': 57 case 'c':
40 deb_extract_funct |= extract_data_tar_gz; 58 tar_gz_archive->action_header = header_verbose_list;
41 deb_extract_funct |= extract_verbose_list;
42 break; 59 break;
43 case 'e': 60 case 'e':
44 arg_type = arg_type_prefix; 61 ar_archive->accept = control_tar_gz_llist;
45 deb_extract_funct |= extract_control_tar_gz; 62 tar_gz_archive->action_data = data_extract_all;
46 deb_extract_funct |= extract_all_to_fs;
47 break; 63 break;
48 case 'f': 64 case 'f':
49 arg_type = arg_type_field; 65 /* Print the entire control file
50 deb_extract_funct |= extract_control_tar_gz; 66 * it should accept a second argument which specifies a
51 deb_extract_funct |= extract_one_to_buffer; 67 * specific field to print */
52 filename = xstrdup("./control"); 68 ar_archive->accept = control_tar_gz_llist;
53 break; 69 tar_gz_archive->accept = add_to_list(NULL, "./control");;
54 case 't': /* --fsys-tarfile, i just made up this short name */ 70 tar_gz_archive->filter = filter_accept_list;
55 /* Integrate the functionality needed with some code from ar.c */ 71 tar_gz_archive->action_data = data_extract_to_stdout;
56 error_msg_and_die("Option disabled");
57// arg_type = arg_type_un_ar_gz;
58 break; 72 break;
59 case 'X': 73 case 'X':
60 arg_type = arg_type_prefix; 74 tar_gz_archive->action_header = header_list;
61 deb_extract_funct |= extract_data_tar_gz; 75#endif
62 deb_extract_funct |= extract_all_to_fs;
63 deb_extract_funct |= extract_list;
64 case 'x': 76 case 'x':
65 arg_type = arg_type_prefix; 77 tar_gz_archive->action_data = data_extract_all;
66 deb_extract_funct |= extract_data_tar_gz;
67 deb_extract_funct |= extract_all_to_fs;
68 break;
69 case 'I':
70 arg_type = arg_type_filename;
71 deb_extract_funct |= extract_control_tar_gz;
72 deb_extract_funct |= extract_one_to_buffer;
73 break; 78 break;
74 default: 79 default:
75 show_usage(); 80 show_usage();
76 } 81 }
77 } 82 }
78 83
79 if (optind == argc) { 84 if (optind + 2 < argc) {
80 show_usage(); 85 show_usage();
81 } 86 }
82 87
88 tar_gz_archive->src_fd = ar_archive->src_fd = xopen(argv[optind++], O_RDONLY);
89
83 /* Workout where to extract the files */ 90 /* Workout where to extract the files */
84 if (arg_type == arg_type_prefix) { 91 /* 2nd argument is a dir name */
85 /* argument is a dir name */ 92 mkdir(argv[optind], 0777);
86 if ((optind + 1) == argc ) { 93 chdir(argv[optind]);
87 prefix = xstrdup("./DEBIAN/");
88 } else {
89 prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2);
90 strcpy(prefix, argv[optind + 1]);
91 /* Make sure the directory has a trailing '/' */
92 if (last_char_is(prefix, '/') == NULL) {
93 strcat(prefix, "/");
94 }
95 }
96 mkdir(prefix, 0777);
97 }
98 94
99 if (arg_type == arg_type_filename) { 95#ifdef CONFIG_AR
100 if ((optind + 1) != argc) { 96 unpack_ar_archive(ar_archive);
101 filename = xstrdup(argv[optind + 1]); 97#else
102 } else { 98 xread_all(ar_archive->src_fd, magic, 7);
103 error_msg_and_die("-I currently requires a filename to be specified"); 99 if (strncmp(magic, "!<arch>", 7) != 0) {
104 } 100 error_msg_and_die("Invalid ar magic");
105 } 101 }
102 ar_archive->offset += 7;
106 103
107 output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename); 104 while (get_header_ar(ar_archive) == EXIT_SUCCESS);
105#endif
108 106
109 if ((arg_type == arg_type_filename) && (output_buffer != NULL)) { 107 /* Cleanup */
110 puts(output_buffer); 108 close (ar_archive->src_fd);
111 }
112 else if (arg_type == arg_type_field) {
113 char *field = NULL;
114 char *name;
115 char *value;
116 int field_start = 0;
117
118 while (1) {
119 field_start += read_package_field(&output_buffer[field_start], &name, &value);
120 if (name == NULL) {
121 break;
122 }
123 if (strcmp(name, argv[optind + 1]) == 0) {
124 puts(value);
125 }
126 free(field);
127 }
128 }
129 109
130 return(EXIT_SUCCESS); 110 return(EXIT_SUCCESS);
131} 111}
112
diff --git a/archival/gunzip.c b/archival/gunzip.c
index ac2fb17ed..4489204fb 100644
--- a/archival/gunzip.c
+++ b/archival/gunzip.c
@@ -64,7 +64,12 @@ static char *license_msg[] = {
64#include <string.h> 64#include <string.h>
65#include <unistd.h> 65#include <unistd.h>
66#include <getopt.h> 66#include <getopt.h>
67#include <sys/types.h>
68#include <sys/stat.h>
69#include <fcntl.h>
70
67#include "busybox.h" 71#include "busybox.h"
72#include "unarchive.h"
68 73
69const char gunzip_to_stdout = 1; 74const char gunzip_to_stdout = 1;
70const char gunzip_force = 2; 75const char gunzip_force = 2;
@@ -100,23 +105,20 @@ extern int gunzip_main(int argc, char **argv)
100 } 105 }
101 106
102 do { 107 do {
103 FILE *in_file, *out_file;
104 struct stat stat_buf; 108 struct stat stat_buf;
105 const char *old_path = argv[optind]; 109 const char *old_path = argv[optind];
106 const char *delete_path = NULL; 110 const char *delete_path = NULL;
107 char *new_path = NULL; 111 char *new_path = NULL;
112 int src_fd;
113 int dst_fd;
108 114
109 optind++; 115 optind++;
110 116
111 if (old_path == NULL || strcmp(old_path, "-") == 0) { 117 if (old_path == NULL || strcmp(old_path, "-") == 0) {
112 in_file = stdin; 118 src_fd = fileno(stdin);
113 flags |= gunzip_to_stdout; 119 flags |= gunzip_to_stdout;
114 } else { 120 } else {
115 in_file = wfopen(old_path, "r"); 121 src_fd = xopen(old_path, O_RDONLY);
116 if (in_file == NULL) {
117 status = EXIT_FAILURE;
118 break;
119 }
120 122
121 /* Get the time stamp on the input file. */ 123 /* Get the time stamp on the input file. */
122 if (stat(old_path, &stat_buf) < 0) { 124 if (stat(old_path, &stat_buf) < 0) {
@@ -125,16 +127,16 @@ extern int gunzip_main(int argc, char **argv)
125 } 127 }
126 128
127 /* Check that the input is sane. */ 129 /* Check that the input is sane. */
128 if (isatty(fileno(in_file)) && ((flags & gunzip_force) == 0)) { 130 if (isatty(src_fd) && ((flags & gunzip_force) == 0)) {
129 error_msg_and_die 131 error_msg_and_die
130 ("compressed data not read from terminal. Use -f to force it."); 132 ("compressed data not read from terminal. Use -f to force it.");
131 } 133 }
132 134
133 /* Set output filename and number */ 135 /* Set output filename and number */
134 if (flags & gunzip_test) { 136 if (flags & gunzip_test) {
135 out_file = xfopen("/dev/null", "w"); /* why does test use filenum 2 ? */ 137 dst_fd = xopen("/dev/null", O_WRONLY); /* why does test use filenum 2 ? */
136 } else if (flags & gunzip_to_stdout) { 138 } else if (flags & gunzip_to_stdout) {
137 out_file = stdout; 139 dst_fd = fileno(stdout);
138 } else { 140 } else {
139 char *extension; 141 char *extension;
140 142
@@ -151,7 +153,7 @@ extern int gunzip_main(int argc, char **argv)
151 } 153 }
152 154
153 /* Open output file */ 155 /* Open output file */
154 out_file = xfopen(new_path, "w"); 156 dst_fd = xopen(new_path, O_WRONLY | O_CREAT);
155 157
156 /* Set permissions on the file */ 158 /* Set permissions on the file */
157 chmod(new_path, stat_buf.st_mode); 159 chmod(new_path, stat_buf.st_mode);
@@ -161,16 +163,22 @@ extern int gunzip_main(int argc, char **argv)
161 } 163 }
162 164
163 /* do the decompression, and cleanup */ 165 /* do the decompression, and cleanup */
164 if ((unzip(in_file, out_file) != 0) && (new_path)) { 166 check_header_gzip(src_fd);
167 if (inflate(src_fd, dst_fd) != 0) {
168 error_msg("Error inflating");
169 }
170 check_trailer_gzip(src_fd);
171
172 if ((status != EXIT_SUCCESS) && (new_path)) {
165 /* Unzip failed, remove new path instead of old path */ 173 /* Unzip failed, remove new path instead of old path */
166 delete_path = new_path; 174 delete_path = new_path;
167 } 175 }
168 176
169 if (out_file != stdout) { 177 if (dst_fd != fileno(stdout)) {
170 fclose(out_file); 178 close(dst_fd);
171 } 179 }
172 if (in_file != stdin) { 180 if (src_fd != fileno(stdin)) {
173 fclose(in_file); 181 close(src_fd);
174 } 182 }
175 183
176 /* delete_path will be NULL if in test mode or from stdin */ 184 /* delete_path will be NULL if in test mode or from stdin */
diff --git a/archival/libunarchive/Makefile.in b/archival/libunarchive/Makefile.in
index cd68be732..e2ac546ab 100644
--- a/archival/libunarchive/Makefile.in
+++ b/archival/libunarchive/Makefile.in
@@ -22,14 +22,41 @@ ifndef $(LIBUNARCHIVE_DIR)
22LIBUNARCHIVE_DIR:=$(TOPDIR)archival/libunarchive/ 22LIBUNARCHIVE_DIR:=$(TOPDIR)archival/libunarchive/
23endif 23endif
24 24
25LIBUNARCHIVE-y:=unarchive.o seek_sub_file.o 25LIBUNARCHIVE-y:= \
26LIBUNARCHIVE-$(CONFIG_DPKG) += deb_extract.o get_header_ar.o get_header_tar.o 26\
27LIBUNARCHIVE-$(CONFIG_DPKG_DEB) += deb_extract.o get_header_ar.o get_header_tar.o 27 data_skip.o \
28LIBUNARCHIVE-$(CONFIG_AR) += get_header_ar.o 28 data_extract_all.o \
29LIBUNARCHIVE-$(CONFIG_CPIO) += get_header_cpio.o 29 data_extract_to_stdout.o \
30LIBUNARCHIVE-$(CONFIG_RPM2CPIO) += get_header_cpio.o 30\
31LIBUNARCHIVE-$(CONFIG_TAR) += get_header_tar.o 31 filter_accept_all.o \
32LIBUNARCHIVE-$(CONFIG_UNZIP) += get_header_zip.o 32 filter_accept_list.o \
33 filter_accept_reject_list.o \
34\
35 get_header_ar.o \
36 get_header_tar.o \
37 get_header_tar_gz.o \
38\
39 header_skip.o \
40 header_list.o \
41 header_verbose_list.o \
42\
43 add_to_list.o \
44 check_header_gzip.o \
45 check_trailer_gzip.o \
46 copy_file_chunk_fd.o \
47 data_align.o \
48 init_handle.o \
49 seek_sub_file.o \
50 unpack_ar_archive.o \
51
52LIBUNARCHIVE-$(CONFIG_DPKG) +=
53LIBUNARCHIVE-$(CONFIG_DPKG_DEB) +=
54LIBUNARCHIVE-$(CONFIG_AR) +=
55LIBUNARCHIVE-$(CONFIG_CPIO) +=
56LIBUNARCHIVE-$(CONFIG_GUNZIP) +=
57LIBUNARCHIVE-$(CONFIG_RPM2CPIO) +=
58LIBUNARCHIVE-$(CONFIG_TAR) +=
59LIBUNARCHIVE-$(CONFIG_UNZIP) +=
33 60
34libraries-y+=$(LIBUNARCHIVE_DIR)$(LIBUNARCHIVE_AR) 61libraries-y+=$(LIBUNARCHIVE_DIR)$(LIBUNARCHIVE_AR)
35 62
diff --git a/archival/libunarchive/add_to_list.c b/archival/libunarchive/add_to_list.c
new file mode 100644
index 000000000..052bca351
--- /dev/null
+++ b/archival/libunarchive/add_to_list.c
@@ -0,0 +1,15 @@
1#include <stdlib.h>
2#include <string.h>
3#include "unarchive.h"
4#include "libbb.h"
5
6extern const llist_t *add_to_list(const llist_t *old_head, const char *new_item)
7{
8 llist_t *new_head;
9
10 new_head = xmalloc(sizeof(llist_t));
11 new_head->data = new_item;
12 new_head->link = old_head;
13
14 return(new_head);
15}
diff --git a/archival/libunarchive/check_header_gzip.c b/archival/libunarchive/check_header_gzip.c
new file mode 100644
index 000000000..508d30924
--- /dev/null
+++ b/archival/libunarchive/check_header_gzip.c
@@ -0,0 +1,75 @@
1#include <stdlib.h>
2#include <unistd.h>
3#include "libbb.h"
4
5extern void check_header_gzip(int src_fd)
6{
7 union {
8 unsigned char raw[10];
9 struct {
10 unsigned char magic[2];
11 unsigned char method;
12 unsigned char flags;
13 unsigned int mtime;
14 unsigned char xtra_flags;
15 unsigned char os_flags;
16 } formated;
17 } header;
18
19 xread_all(src_fd, header.raw, 10);
20
21 /* Magic header for gzip files, 1F 8B = \037\213 */
22 if ((header.formated.magic[0] != 0x1F)
23 || (header.formated.magic[1] != 0x8b)) {
24 error_msg_and_die("Invalid gzip magic");
25 }
26
27 /* Check the compression method */
28 if (header.formated.method != 8) {
29 error_msg_and_die("Unknown compression method %d",
30 header.formated.method);
31 }
32
33 if (header.formated.flags & 0x04) {
34 /* bit 2 set: extra field present */
35 unsigned char extra_short;
36
37 extra_short = xread_char(src_fd);
38 extra_short += xread_char(src_fd) << 8;
39 while (extra_short > 0) {
40 /* Ignore extra field */
41 xread_char(src_fd);
42 extra_short--;
43 }
44 }
45
46 /* Discard original name if any */
47 if (header.formated.flags & 0x08) {
48 /* bit 3 set: original file name present */
49 char tmp;
50
51 do {
52 read(src_fd, &tmp, 1);
53 } while (tmp != 0);
54 }
55
56 /* Discard file comment if any */
57 if (header.formated.flags & 0x10) {
58 /* bit 4 set: file comment present */
59 char tmp;
60
61 do {
62 read(src_fd, &tmp, 1);
63 } while (tmp != 0);
64 }
65
66 /* Read the header checksum */
67 if (header.formated.flags & 0x02) {
68 char tmp;
69
70 read(src_fd, &tmp, 1);
71 read(src_fd, &tmp, 1);
72 }
73
74 return;
75}
diff --git a/archival/libunarchive/check_trailer_gzip.c b/archival/libunarchive/check_trailer_gzip.c
new file mode 100644
index 000000000..215e8293f
--- /dev/null
+++ b/archival/libunarchive/check_trailer_gzip.c
@@ -0,0 +1,62 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * busybox gunzip trailing header handler
4 * Copyright Glenn McGrath 2002
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21
22#include <sys/types.h>
23#include <sys/wait.h>
24#include <signal.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include "config.h"
30#include "busybox.h"
31#include "unarchive.h"
32
33extern unsigned int gunzip_crc;
34extern unsigned int gunzip_bytes_out;
35extern unsigned char *gunzip_in_buffer;
36extern unsigned char gunzip_in_buffer_count;
37
38extern void check_trailer_gzip(int src_fd)
39{
40
41 unsigned int stored_crc = 0;
42 unsigned char count;
43
44 /* top up the input buffer with the rest of the trailer */
45 xread_all(src_fd, &gunzip_in_buffer[gunzip_in_buffer_count], 8 - gunzip_in_buffer_count);
46 for (count = 0; count != 4; count++) {
47 stored_crc |= (gunzip_in_buffer[count] << (count * 8));
48 }
49
50 /* Validate decompression - crc */
51 if (stored_crc != (gunzip_crc ^ 0xffffffffL)) {
52 error_msg("invalid compressed data--crc error");
53 }
54
55 /* Validate decompression - size */
56 if (gunzip_bytes_out !=
57 (gunzip_in_buffer[4] | (gunzip_in_buffer[5] << 8) |
58 (gunzip_in_buffer[6] << 16) | (gunzip_in_buffer[7] << 24))) {
59 error_msg("invalid compressed data--length error");
60 }
61
62}
diff --git a/archival/libunarchive/copy_file_chunk_fd.c b/archival/libunarchive/copy_file_chunk_fd.c
new file mode 100644
index 000000000..fb513e6d5
--- /dev/null
+++ b/archival/libunarchive/copy_file_chunk_fd.c
@@ -0,0 +1,33 @@
1#include <unistd.h>
2#include <sys/types.h>
3#include "libbb.h"
4
5/* Copy CHUNKSIZE bytes (or untill EOF if chunksize == -1)
6 * from SRC_FILE to DST_FILE. */
7extern int copy_file_chunk_fd(int src_fd, int dst_fd, off_t chunksize)
8{
9 size_t nread, size;
10 char buffer[BUFSIZ];
11
12 while (chunksize != 0) {
13 if (chunksize > BUFSIZ) {
14 size = BUFSIZ;
15 } else {
16 size = chunksize;
17 }
18 nread = xread(src_fd, buffer, size);
19 if (nread == 0) {
20 return 1;
21 }
22
23 if (write (dst_fd, buffer, nread) != nread) {
24 error_msg_and_die ("Short write");
25 }
26
27 if (chunksize != -1) {
28 chunksize -= nread;
29 }
30 }
31
32 return 0;
33}
diff --git a/archival/libunarchive/data_align.c b/archival/libunarchive/data_align.c
new file mode 100644
index 000000000..d6243bc19
--- /dev/null
+++ b/archival/libunarchive/data_align.c
@@ -0,0 +1,13 @@
1#include <errno.h>
2#include <sys/types.h>
3#include <unistd.h>
4#include "unarchive.h"
5#include "libbb.h"
6
7extern const unsigned short data_align(const int src_fd, const unsigned int offset, const unsigned short align_to)
8{
9 const unsigned short skip_amount = (align_to - (offset % align_to)) % align_to;
10 seek_sub_file(src_fd, skip_amount);
11
12 return(skip_amount);
13}
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c
new file mode 100644
index 000000000..20d99aa58
--- /dev/null
+++ b/archival/libunarchive/data_extract_all.c
@@ -0,0 +1,76 @@
1#include <sys/types.h>
2#include <errno.h>
3#include <fcntl.h>
4#include <stdlib.h>
5#include <string.h>
6#include <utime.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include "libbb.h"
10#include "unarchive.h"
11
12extern void data_extract_all(archive_handle_t *archive_handle)
13{
14 file_header_t *file_header = archive_handle->file_header;
15 int dst_fd;
16 int res;
17
18 if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
19 char *dir = dirname(strdup(file_header->name));
20 make_directory (dir, 0777, FILEUTILS_RECUR);
21 free(dir);
22 }
23
24 /* Create the file */
25 switch(file_header->mode & S_IFMT) {
26 case S_IFREG: {
27#ifdef CONFIG_CPIO
28 if (file_header->link_name) {
29 /* hard link */
30 res = link(file_header->link_name, file_header->name);
31 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
32 perror_msg("Couldnt create hard link");
33 }
34 } else
35#endif
36 {
37 /* Regular file */
38 dst_fd = xopen(file_header->name, O_WRONLY | O_CREAT);
39 copy_file_chunk_fd(archive_handle->src_fd, dst_fd, file_header->size);
40 close(dst_fd);
41 }
42 break;
43 }
44 case S_IFDIR:
45 res = mkdir(file_header->name, file_header->mode);
46 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
47 perror_msg("extract_archive: %s", file_header->name);
48 }
49 break;
50 case S_IFLNK:
51 /* Symlink */
52 res = symlink(file_header->link_name, file_header->name);
53 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
54 perror_msg("Cannot create symlink from %s to '%s'", file_header->name, file_header->link_name);
55 }
56 break;
57 case S_IFSOCK:
58 case S_IFBLK:
59 case S_IFCHR:
60 case S_IFIFO:
61 res = mknod(file_header->name, file_header->mode, file_header->device);
62 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
63 perror_msg("Cannot create node %s", file_header->name);
64 }
65 break;
66 }
67
68 chmod(file_header->name, file_header->mode);
69 chown(file_header->name, file_header->uid, file_header->gid);
70
71 if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
72 struct utimbuf t;
73 t.actime = t.modtime = file_header->mtime;
74 utime(file_header->name, &t);
75 }
76}
diff --git a/archival/libunarchive/data_extract_to_stdout.c b/archival/libunarchive/data_extract_to_stdout.c
new file mode 100644
index 000000000..00687b315
--- /dev/null
+++ b/archival/libunarchive/data_extract_to_stdout.c
@@ -0,0 +1,8 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include "unarchive.h"
4
5extern void data_extract_to_stdout(archive_handle_t *archive_handle)
6{
7 copy_file_chunk_fd(archive_handle->src_fd, fileno(stdout), archive_handle->file_header->size);
8}
diff --git a/archival/libunarchive/data_skip.c b/archival/libunarchive/data_skip.c
new file mode 100644
index 000000000..4e63d4304
--- /dev/null
+++ b/archival/libunarchive/data_skip.c
@@ -0,0 +1,27 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#include <sys/types.h>
18#include <errno.h>
19#include <unistd.h>
20#include <stdlib.h>
21#include "unarchive.h"
22#include "libbb.h"
23
24extern void data_skip(archive_handle_t *archive_handle)
25{
26 seek_sub_file(archive_handle->src_fd, archive_handle->file_header->size);
27}
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c
index d84067068..20bf88f55 100644
--- a/archival/libunarchive/decompress_unzip.c
+++ b/archival/libunarchive/decompress_unzip.c
@@ -65,114 +65,126 @@ static char *license_msg[] = {
65#include <signal.h> 65#include <signal.h>
66#include <stdlib.h> 66#include <stdlib.h>
67#include <string.h> 67#include <string.h>
68#include <unistd.h>
69#include <fcntl.h>
68#include "config.h" 70#include "config.h"
69#include "libbb.h" 71#include "busybox.h"
72#include "unarchive.h"
70 73
71#ifdef CONFIG_FEATURE_UNCOMPRESS 74typedef struct huft_s {
72int uncompress(FILE * in, FILE * out); 75 unsigned char e; /* number of extra bits or operation */
73#endif 76 unsigned char b; /* number of bits in this code or subcode */
74 77 union {
75static FILE *in_file, *out_file; 78 unsigned short n; /* literal, length base, or distance base */
79 struct huft_s *t; /* pointer to next level of table */
80 } v;
81} huft_t;
76 82
77/* these are freed by gz_close */ 83static int gunzip_src_fd;
78static unsigned char *window; 84static int gunzip_dst_fd;
79static unsigned long *crc_table; 85unsigned int gunzip_bytes_out; /* number of output bytes */
86static unsigned int gunzip_outbuf_count; /* bytes in output buffer */
80 87
81static unsigned long crc; /* shift register contents */ 88/* This is used to sanify any unused bits from the bitbuffer
89 * so they arent skipped when reading trailers (trailing headers) */
90unsigned char gunzip_in_buffer_count;
91unsigned char *gunzip_in_buffer;
82 92
83/* Return codes from gzip */ 93/* gunzip_window size--must be a power of two, and
84#define ERROR 1 94 * at least 32K for zip's deflate method */
95static const int gunzip_wsize = 0x8000;
85 96
86/* 97static unsigned char *gunzip_window;
87 * window size--must be a power of two, and 98static unsigned int *gunzip_crc_table;
88 * at least 32K for zip's deflate method 99unsigned int gunzip_crc;
89 */
90#define WSIZE 0x8000
91 100
92/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ 101/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
93#define BMAX 16 /* maximum bit length of any code (16 for explode) */ 102#define BMAX 16 /* maximum bit length of any code (16 for explode) */
94#define N_MAX 288 /* maximum number of codes in any set */ 103#define N_MAX 288 /* maximum number of codes in any set */
95 104
96static long bytes_out; /* number of output bytes */ 105static unsigned int gunzip_hufts; /* track memory usage */
97static unsigned long outcnt; /* bytes in output buffer */ 106static unsigned int gunzip_bb; /* bit buffer */
98 107static unsigned char gunzip_bk; /* bits in bit buffer */
99static unsigned hufts; /* track memory usage */
100static unsigned long bb; /* bit buffer */
101static unsigned bk; /* bits in bit buffer */
102
103typedef struct huft_s {
104 unsigned char e; /* number of extra bits or operation */
105 unsigned char b; /* number of bits in this code or subcode */
106 union {
107 unsigned short n; /* literal, length base, or distance base */
108 struct huft_s *t; /* pointer to next level of table */
109 } v;
110} huft_t;
111 108
112static const unsigned short mask_bits[] = { 109static const unsigned short mask_bits[] = {
113 0x0000, 110 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
114 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
115 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 111 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
116}; 112};
117 113
118/* static int error_number = 0; */ 114/* Copy lengths for literal codes 257..285 */
119/* ======================================================================== 115static const unsigned short cplens[] = {
120 * Signal and error handler. 116 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
121 */ 117 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
118};
119
120/* note: see note #13 above about the 258 in this list. */
121/* Extra bits for literal codes 257..285 */
122static const unsigned char cplext[] = {
123 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
124 5, 5, 5, 0, 99, 99
125}; /* 99==invalid */
126
127/* Copy offsets for distance codes 0..29 */
128static const unsigned short cpdist[] = {
129 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
130 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
131};
132
133/* Extra bits for distance codes */
134static const unsigned char cpdext[] = {
135 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
136 11, 11, 12, 12, 13, 13
137};
138
139/* Tables for deflate from PKZIP's appnote.txt. */
140/* Order of the bit length code lengths */
141static const unsigned char border[] = {
142 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
143};
144
145static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
146{
147 while (*current < required) {
148 bitbuffer |= ((unsigned int) xread_char(gunzip_src_fd)) << *current;
149 *current += 8;
150 }
151
152 return(bitbuffer);
153}
122 154
123static void abort_gzip(void) 155static void abort_gzip(void)
124{ 156{
125 error_msg("gzip aborted\n"); 157 error_msg("gzip aborted\n");
126 exit(ERROR); 158 exit(-1);
127} 159}
128 160
129static void make_crc_table(void) 161static void make_gunzip_crc_table(void)
130{ 162{
131 const unsigned long poly = 0xedb88320; /* polynomial exclusive-or pattern */ 163 const unsigned int poly = 0xedb88320; /* polynomial exclusive-or pattern */
132 unsigned short i; /* counter for all possible eight bit values */ 164 unsigned short i; /* counter for all possible eight bit values */
133 165
134 /* initial shift register value */ 166 /* initial shift register value */
135 crc = 0xffffffffL; 167 gunzip_crc = 0xffffffffL;
136 crc_table = (unsigned long *) malloc(256 * sizeof(unsigned long)); 168 gunzip_crc_table = (unsigned int *) malloc(256 * sizeof(unsigned int));
137 169
138 /* Compute and print table of CRC's, five per line */ 170 /* Compute and print table of CRC's, five per line */
139 for (i = 0; i < 256; i++) { 171 for (i = 0; i < 256; i++) {
140 unsigned long table_entry; /* crc shift register */ 172 unsigned int table_entry; /* crc shift register */
141 char k; /* byte being shifted into crc apparatus */ 173 unsigned char k; /* byte being shifted into crc apparatus */
142 174
143 table_entry = i; 175 table_entry = i;
144 /* The idea to initialize the register with the byte instead of 176 /* The idea to initialize the register with the byte instead of
145 * zero was stolen from Haruhiko Okumura's ar002 177 * zero was stolen from Haruhiko Okumura's ar002
146 */ 178 */
147 for (k = 8; k; k--) { 179 for (k = 8; k; k--) {
148 table_entry = 180 if (table_entry & 1) {
149 table_entry & 1 ? (table_entry >> 1) ^ poly : table_entry >> 181 table_entry = (table_entry >> 1) ^ poly;
150 1; 182 } else {
151 } 183 table_entry >>= 1;
152 crc_table[i] = table_entry;
153 } 184 }
154}
155
156/* ===========================================================================
157 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
158 * (Used for the decompressed data only.)
159 */
160static void flush_window(void)
161{
162 int n;
163
164 if (outcnt == 0)
165 return;
166
167 for (n = 0; n < outcnt; n++) {
168 crc = crc_table[((int) crc ^ (window[n])) & 0xff] ^ (crc >> 8);
169 } 185 }
170 186 gunzip_crc_table[i] = table_entry;
171 if (fwrite(window, 1, outcnt, out_file) != outcnt) {
172 error_msg_and_die("Couldnt write");
173 } 187 }
174 bytes_out += (unsigned long) outcnt;
175 outcnt = 0;
176} 188}
177 189
178/* 190/*
@@ -183,7 +195,8 @@ static void flush_window(void)
183 */ 195 */
184static int huft_free(huft_t * t) 196static int huft_free(huft_t * t)
185{ 197{
186 huft_t *p, *q; 198 huft_t *p;
199 huft_t *q;
187 200
188 /* Go through linked list, freeing from the malloced (t[-1]) address. */ 201 /* Go through linked list, freeing from the malloced (t[-1]) address. */
189 p = t; 202 p = t;
@@ -195,8 +208,6 @@ static int huft_free(huft_t * t)
195 return 0; 208 return 0;
196} 209}
197 210
198typedef unsigned char extra_bits_t;
199
200/* Given a list of code lengths and a maximum table size, make a set of 211/* Given a list of code lengths and a maximum table size, make a set of
201 * tables to decode that set of codes. Return zero on success, one if 212 * tables to decode that set of codes. Return zero on success, one if
202 * the given code set is incomplete (the tables are still built in this 213 * the given code set is incomplete (the tables are still built in this
@@ -213,7 +224,7 @@ typedef unsigned char extra_bits_t;
213 */ 224 */
214static int huft_build(unsigned int *b, const unsigned int n, 225static int huft_build(unsigned int *b, const unsigned int n,
215 const unsigned int s, const unsigned short *d, 226 const unsigned int s, const unsigned short *d,
216 const extra_bits_t * e, huft_t ** t, int *m) 227 const unsigned char *e, huft_t ** t, int *m)
217{ 228{
218 unsigned a; /* counter for codes of length k */ 229 unsigned a; /* counter for codes of length k */
219 unsigned c[BMAX + 1]; /* bit length count table */ 230 unsigned c[BMAX + 1]; /* bit length count table */
@@ -251,26 +262,35 @@ static int huft_build(unsigned int *b, const unsigned int n,
251 262
252 /* Find minimum and maximum length, bound *m by those */ 263 /* Find minimum and maximum length, bound *m by those */
253 l = *m; 264 l = *m;
254 for (j = 1; j <= BMAX; j++) 265 for (j = 1; j <= BMAX; j++) {
255 if (c[j]) 266 if (c[j]) {
256 break; 267 break;
268 }
269 }
257 k = j; /* minimum code length */ 270 k = j; /* minimum code length */
258 if ((unsigned) l < j) 271 if ((unsigned) l < j) {
259 l = j; 272 l = j;
260 for (i = BMAX; i; i--) 273 }
261 if (c[i]) 274 for (i = BMAX; i; i--) {
275 if (c[i]) {
262 break; 276 break;
277 }
278 }
263 g = i; /* maximum code length */ 279 g = i; /* maximum code length */
264 if ((unsigned) l > i) 280 if ((unsigned) l > i) {
265 l = i; 281 l = i;
282 }
266 *m = l; 283 *m = l;
267 284
268 /* Adjust last length count to fill out codes, if needed */ 285 /* Adjust last length count to fill out codes, if needed */
269 for (y = 1 << j; j < i; j++, y <<= 1) 286 for (y = 1 << j; j < i; j++, y <<= 1) {
270 if ((y -= c[j]) < 0) 287 if ((y -= c[j]) < 0) {
271 return 2; /* bad input: more codes than bits */ 288 return 2; /* bad input: more codes than bits */
272 if ((y -= c[i]) < 0) 289 }
290 }
291 if ((y -= c[i]) < 0) {
273 return 2; 292 return 2;
293 }
274 c[i] += y; 294 c[i] += y;
275 295
276 /* Generate starting offsets into the value table for each length */ 296 /* Generate starting offsets into the value table for each length */
@@ -285,8 +305,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
285 p = b; 305 p = b;
286 i = 0; 306 i = 0;
287 do { 307 do {
288 if ((j = *p++) != 0) 308 if ((j = *p++) != 0) {
289 v[x[j]++] = i; 309 v[x[j]++] = i;
310 }
290 } while (++i < n); 311 } while (++i < n);
291 312
292 /* Generate the Huffman codes and for each, make the table entries */ 313 /* Generate the Huffman codes and for each, make the table entries */
@@ -314,8 +335,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
314 f -= a + 1; /* deduct codes from patterns left */ 335 f -= a + 1; /* deduct codes from patterns left */
315 xp = c + k; 336 xp = c + k;
316 while (++j < z) { /* try smaller tables up to z bits */ 337 while (++j < z) { /* try smaller tables up to z bits */
317 if ((f <<= 1) <= *++xp) 338 if ((f <<= 1) <= *++xp) {
318 break; /* enough codes to use up j bits */ 339 break; /* enough codes to use up j bits */
340 }
319 f -= *xp; /* else deduct codes from patterns */ 341 f -= *xp; /* else deduct codes from patterns */
320 } 342 }
321 } 343 }
@@ -324,7 +346,7 @@ static int huft_build(unsigned int *b, const unsigned int n,
324 /* allocate and link in new table */ 346 /* allocate and link in new table */
325 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); 347 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t));
326 348
327 hufts += z + 1; /* track memory usage */ 349 gunzip_hufts += z + 1; /* track memory usage */
328 *t = q + 1; /* link to list for huft_free() */ 350 *t = q + 1; /* link to list for huft_free() */
329 *(t = &(q->v.t)) = NULL; 351 *(t = &(q->v.t)) = NULL;
330 u[h] = ++q; /* table starts after link */ 352 u[h] = ++q; /* table starts after link */
@@ -342,9 +364,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
342 364
343 /* set up table entry in r */ 365 /* set up table entry in r */
344 r.b = (unsigned char) (k - w); 366 r.b = (unsigned char) (k - w);
345 if (p >= v + n) 367 if (p >= v + n) {
346 r.e = 99; /* out of values--invalid code */ 368 r.e = 99; /* out of values--invalid code */
347 else if (*p < s) { 369 } else if (*p < s) {
348 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */ 370 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
349 r.v.n = (unsigned short) (*p); /* simple code is just the value */ 371 r.v.n = (unsigned short) (*p); /* simple code is just the value */
350 p++; /* one compiler does not like *p++ */ 372 p++; /* one compiler does not like *p++ */
@@ -355,12 +377,14 @@ static int huft_build(unsigned int *b, const unsigned int n,
355 377
356 /* fill code-like entries with r */ 378 /* fill code-like entries with r */
357 f = 1 << (k - w); 379 f = 1 << (k - w);
358 for (j = i >> w; j < z; j += f) 380 for (j = i >> w; j < z; j += f) {
359 q[j] = r; 381 q[j] = r;
382 }
360 383
361 /* backwards increment the k-bit code i */ 384 /* backwards increment the k-bit code i */
362 for (j = 1 << (k - 1); i & j; j >>= 1) 385 for (j = 1 << (k - 1); i & j; j >>= 1) {
363 i ^= j; 386 i ^= j;
387 }
364 i ^= j; 388 i ^= j;
365 389
366 /* backup over finished tables */ 390 /* backup over finished tables */
@@ -374,6 +398,25 @@ static int huft_build(unsigned int *b, const unsigned int n,
374 return y != 0 && g != 1; 398 return y != 0 && g != 1;
375} 399}
376 400
401/* ===========================================================================
402 * Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out.
403 * (Used for the decompressed data only.)
404 */
405static void flush_gunzip_window(void)
406{
407 int n;
408
409 for (n = 0; n < gunzip_outbuf_count; n++) {
410 gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
411 }
412
413 if (write(gunzip_dst_fd, gunzip_window, gunzip_outbuf_count) != gunzip_outbuf_count) {
414 error_msg_and_die("Couldnt write");
415 }
416 gunzip_bytes_out += gunzip_outbuf_count;
417 gunzip_outbuf_count = 0;
418}
419
377/* 420/*
378 * inflate (decompress) the codes in a deflated (compressed) block. 421 * inflate (decompress) the codes in a deflated (compressed) block.
379 * Return an error code or zero if it all goes ok. 422 * Return an error code or zero if it all goes ok.
@@ -381,32 +424,26 @@ static int huft_build(unsigned int *b, const unsigned int n,
381 * tl, td: literal/length and distance decoder tables 424 * tl, td: literal/length and distance decoder tables
382 * bl, bd: number of bits decoded by tl[] and td[] 425 * bl, bd: number of bits decoded by tl[] and td[]
383 */ 426 */
384static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd) 427static int inflate_codes(huft_t * tl, huft_t * td, const unsigned int bl, const unsigned int bd)
385{ 428{
386 register unsigned long e; /* table entry flag/number of extra bits */ 429 unsigned int e; /* table entry flag/number of extra bits */
387 unsigned long n, d; /* length and index for copy */ 430 unsigned int n, d; /* length and index for copy */
388 unsigned long w; /* current window position */ 431 unsigned int w; /* current gunzip_window position */
389 huft_t *t; /* pointer to table entry */ 432 huft_t *t; /* pointer to table entry */
390 unsigned ml, md; /* masks for bl and bd bits */ 433 unsigned int ml, md; /* masks for bl and bd bits */
391 register unsigned long b; /* bit buffer */ 434 unsigned int b; /* bit buffer */
392 register unsigned k; /* number of bits in bit buffer */ 435 unsigned int k; /* number of bits in bit buffer */
393 register int input_char;
394 436
395 /* make local copies of globals */ 437 /* make local copies of globals */
396 b = bb; /* initialize bit buffer */ 438 b = gunzip_bb; /* initialize bit buffer */
397 k = bk; 439 k = gunzip_bk;
398 w = outcnt; /* initialize window position */ 440 w = gunzip_outbuf_count; /* initialize gunzip_window position */
399 441
400 /* inflate the coded data */ 442 /* inflate the coded data */
401 ml = mask_bits[bl]; /* precompute masks for speed */ 443 ml = mask_bits[bl]; /* precompute masks for speed */
402 md = mask_bits[bd]; 444 md = mask_bits[bd];
403 for (;;) { /* do until end of block */ 445 while (1) { /* do until end of block */
404 while (k < (unsigned) bl) { 446 b = fill_bitbuffer(b, &k, bl);
405 input_char = fgetc(in_file);
406 if (input_char == EOF) return 1;
407 b |= ((unsigned long)input_char) << k;
408 k += 8;
409 }
410 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) 447 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
411 do { 448 do {
412 if (e == 99) { 449 if (e == 99) {
@@ -415,20 +452,16 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
415 b >>= t->b; 452 b >>= t->b;
416 k -= t->b; 453 k -= t->b;
417 e -= 16; 454 e -= 16;
418 while (k < e) { 455 b = fill_bitbuffer(b, &k, e);
419 input_char = fgetc(in_file);
420 if (input_char == EOF) return 1;
421 b |= ((unsigned long)input_char) << k;
422 k += 8;
423 }
424 } while ((e = 456 } while ((e =
425 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); 457 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
426 b >>= t->b; 458 b >>= t->b;
427 k -= t->b; 459 k -= t->b;
428 if (e == 16) { /* then it's a literal */ 460 if (e == 16) { /* then it's a literal */
429 window[w++] = (unsigned char) t->v.n; 461 gunzip_window[w++] = (unsigned char) t->v.n;
430 if (w == WSIZE) { 462 if (w == gunzip_wsize) {
431 outcnt = (w), flush_window(); 463 gunzip_outbuf_count = (w);
464 flush_gunzip_window();
432 w = 0; 465 w = 0;
433 } 466 }
434 } else { /* it's an EOB or a length */ 467 } else { /* it's an EOB or a length */
@@ -439,24 +472,13 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
439 } 472 }
440 473
441 /* get length of block to copy */ 474 /* get length of block to copy */
442 while (k < e) { 475 b = fill_bitbuffer(b, &k, e);
443 input_char = fgetc(in_file);
444 if (input_char == EOF) return 1;
445 b |= ((unsigned long)input_char) << k;
446 k += 8;
447 }
448 n = t->v.n + ((unsigned) b & mask_bits[e]); 476 n = t->v.n + ((unsigned) b & mask_bits[e]);
449 b >>= e; 477 b >>= e;
450 k -= e; 478 k -= e;
451 479
452 /* decode distance of block to copy */ 480 /* decode distance of block to copy */
453 while (k < (unsigned) bd) { 481 b = fill_bitbuffer(b, &k, bd);
454 input_char = fgetc(in_file);
455 if (input_char == EOF) return 1;
456 b |= ((unsigned long)input_char) << k;
457 k += 8;
458 }
459
460 if ((e = (t = td + ((unsigned) b & md))->e) > 16) 482 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
461 do { 483 do {
462 if (e == 99) 484 if (e == 99)
@@ -464,23 +486,13 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
464 b >>= t->b; 486 b >>= t->b;
465 k -= t->b; 487 k -= t->b;
466 e -= 16; 488 e -= 16;
467 while (k < e) { 489 b = fill_bitbuffer(b, &k, e);
468 input_char = fgetc(in_file);
469 if (input_char == EOF) return 1;
470 b |= ((unsigned long)input_char) << k;
471 k += 8;
472 }
473 } while ((e = 490 } while ((e =
474 (t = 491 (t =
475 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); 492 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
476 b >>= t->b; 493 b >>= t->b;
477 k -= t->b; 494 k -= t->b;
478 while (k < e) { 495 b = fill_bitbuffer(b, &k, e);
479 input_char = fgetc(in_file);
480 if (input_char == EOF) return 1;
481 b |= ((unsigned long)input_char) << k;
482 k += 8;
483 }
484 d = w - t->v.n - ((unsigned) b & mask_bits[e]); 496 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
485 b >>= e; 497 b >>= e;
486 k -= e; 498 k -= e;
@@ -489,60 +501,38 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
489 do { 501 do {
490 n -= (e = 502 n -= (e =
491 (e = 503 (e =
492 WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n : e); 504 gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
493#if !defined(NOMEMCPY) && !defined(DEBUG) 505 /* copy to new buffer to prevent possible overwrite */
494 if (w - d >= e) { /* (this test assumes unsigned comparison) */ 506 if (w - d >= e) { /* (this test assumes unsigned comparison) */
495 memcpy(window + w, window + d, e); 507 memcpy(gunzip_window + w, gunzip_window + d, e);
496 w += e; 508 w += e;
497 d += e; 509 d += e;
498 } else /* do it slow to avoid memcpy() overlap */ 510 } else {
499#endif /* !NOMEMCPY */ 511 /* do it slow to avoid memcpy() overlap */
512 /* !NOMEMCPY */
500 do { 513 do {
501 window[w++] = window[d++]; 514 gunzip_window[w++] = gunzip_window[d++];
502 } while (--e); 515 } while (--e);
503 if (w == WSIZE) { 516 }
504 outcnt = (w), flush_window(); 517 if (w == gunzip_wsize) {
518 gunzip_outbuf_count = (w);
519 flush_gunzip_window();
505 w = 0; 520 w = 0;
506 } 521 }
522
507 } while (n); 523 } while (n);
508 } 524 }
509 } 525 }
510 526
511 /* restore the globals from the locals */ 527 /* restore the globals from the locals */
512 outcnt = w; /* restore global window pointer */ 528 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
513 bb = b; /* restore global bit buffer */ 529 gunzip_bb = b; /* restore global bit buffer */
514 bk = k; 530 gunzip_bk = k;
515 531
516 /* done */ 532 /* done */
517 return 0; 533 return 0;
518} 534}
519 535
520static const unsigned short cplens[] = { /* Copy lengths for literal codes 257..285 */
521 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
522 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
523};
524
525/* note: see note #13 above about the 258 in this list. */
526static const extra_bits_t cplext[] = { /* Extra bits for literal codes 257..285 */
527 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
528 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
529}; /* 99==invalid */
530static const unsigned short cpdist[] = { /* Copy offsets for distance codes 0..29 */
531 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
532 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
533 8193, 12289, 16385, 24577
534};
535static const extra_bits_t cpdext[] = { /* Extra bits for distance codes */
536 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
537 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
538 12, 12, 13, 13
539};
540
541/* Tables for deflate from PKZIP's appnote.txt. */
542static const extra_bits_t border[] = { /* Order of the bit length code lengths */
543 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
544};
545
546/* 536/*
547 * decompress an inflated block 537 * decompress an inflated block
548 * e: last block flag 538 * e: last block flag
@@ -552,53 +542,43 @@ static const extra_bits_t border[] = { /* Order of the bit length code lengths *
552static int inflate_block(int *e) 542static int inflate_block(int *e)
553{ 543{
554 unsigned t; /* block type */ 544 unsigned t; /* block type */
555 register unsigned long b; /* bit buffer */ 545 register unsigned int b; /* bit buffer */
556 register unsigned k; /* number of bits in bit buffer */ 546 unsigned int k; /* number of bits in bit buffer */
557 int input_char;
558 547
559 /* make local bit buffer */ 548 /* make local bit buffer */
560 b = bb; 549
561 k = bk; 550 b = gunzip_bb;
551 k = gunzip_bk;
562 552
563 /* read in last block bit */ 553 /* read in last block bit */
564 while (k < 1) { 554 b = fill_bitbuffer(b, &k, 1);
565 input_char = fgetc(in_file);
566 if (input_char == EOF) return 1;
567 b |= ((unsigned long)input_char) << k;
568 k += 8;
569 }
570 *e = (int) b & 1; 555 *e = (int) b & 1;
571 b >>= 1; 556 b >>= 1;
572 k -= 1; 557 k -= 1;
573 558
574 /* read in block type */ 559 /* read in block type */
575 while (k < 2) { 560 b = fill_bitbuffer(b, &k, 2);
576 input_char = fgetc(in_file);
577 if (input_char == EOF) return 1;
578 b |= ((unsigned long)input_char) << k;
579 k += 8;
580 }
581 t = (unsigned) b & 3; 561 t = (unsigned) b & 3;
582 b >>= 2; 562 b >>= 2;
583 k -= 2; 563 k -= 2;
584 564
585 /* restore the global bit buffer */ 565 /* restore the global bit buffer */
586 bb = b; 566 gunzip_bb = b;
587 bk = k; 567 gunzip_bk = k;
588 568
589 /* inflate that block type */ 569 /* inflate that block type */
590 switch (t) { 570 switch (t) {
591 case 0: /* Inflate stored */ 571 case 0: /* Inflate stored */
592 { 572 {
593 unsigned long n; /* number of bytes in block */ 573 unsigned int n; /* number of bytes in block */
594 unsigned long w; /* current window position */ 574 unsigned int w; /* current gunzip_window position */
595 register unsigned long b_stored; /* bit buffer */ 575 unsigned int b_stored; /* bit buffer */
596 register unsigned long k_stored; /* number of bits in bit buffer */ 576 unsigned int k_stored; /* number of bits in bit buffer */
597 577
598 /* make local copies of globals */ 578 /* make local copies of globals */
599 b_stored = bb; /* initialize bit buffer */ 579 b_stored = gunzip_bb; /* initialize bit buffer */
600 k_stored = bk; 580 k_stored = gunzip_bk;
601 w = outcnt; /* initialize window position */ 581 w = gunzip_outbuf_count; /* initialize gunzip_window position */
602 582
603 /* go to byte boundary */ 583 /* go to byte boundary */
604 n = k_stored & 7; 584 n = k_stored & 7;
@@ -606,21 +586,12 @@ static int inflate_block(int *e)
606 k_stored -= n; 586 k_stored -= n;
607 587
608 /* get the length and its complement */ 588 /* get the length and its complement */
609 while (k_stored < 16) { 589 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
610 input_char = fgetc(in_file);
611 if (input_char == EOF) return 1;
612 b_stored |= ((unsigned long)input_char) << k_stored;
613 k_stored += 8;
614 }
615 n = ((unsigned) b_stored & 0xffff); 590 n = ((unsigned) b_stored & 0xffff);
616 b_stored >>= 16; 591 b_stored >>= 16;
617 k_stored -= 16; 592 k_stored -= 16;
618 while (k_stored < 16) { 593
619 input_char = fgetc(in_file); 594 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
620 if (input_char == EOF) return 1;
621 b_stored |= ((unsigned long)input_char) << k_stored;
622 k_stored += 8;
623 }
624 if (n != (unsigned) ((~b_stored) & 0xffff)) { 595 if (n != (unsigned) ((~b_stored) & 0xffff)) {
625 return 1; /* error in compressed data */ 596 return 1; /* error in compressed data */
626 } 597 }
@@ -629,15 +600,11 @@ static int inflate_block(int *e)
629 600
630 /* read and output the compressed data */ 601 /* read and output the compressed data */
631 while (n--) { 602 while (n--) {
632 while (k_stored < 8) { 603 b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
633 input_char = fgetc(in_file); 604 gunzip_window[w++] = (unsigned char) b_stored;
634 if (input_char == EOF) return 1; 605 if (w == (unsigned int) gunzip_wsize) {
635 b_stored |= ((unsigned long)input_char) << k_stored; 606 gunzip_outbuf_count = (w);
636 k_stored += 8; 607 flush_gunzip_window();
637 }
638 window[w++] = (unsigned char) b_stored;
639 if (w == (unsigned long) WSIZE) {
640 outcnt = (w), flush_window();
641 w = 0; 608 w = 0;
642 } 609 }
643 b_stored >>= 8; 610 b_stored >>= 8;
@@ -645,9 +612,9 @@ static int inflate_block(int *e)
645 } 612 }
646 613
647 /* restore the globals from the locals */ 614 /* restore the globals from the locals */
648 outcnt = w; /* restore global window pointer */ 615 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
649 bb = b_stored; /* restore global bit buffer */ 616 gunzip_bb = b_stored; /* restore global bit buffer */
650 bk = k_stored; 617 gunzip_bk = k_stored;
651 return 0; 618 return 0;
652 } 619 }
653 case 1: /* Inflate fixed 620 case 1: /* Inflate fixed
@@ -659,8 +626,8 @@ static int inflate_block(int *e)
659 int i; /* temporary variable */ 626 int i; /* temporary variable */
660 huft_t *tl; /* literal/length code table */ 627 huft_t *tl; /* literal/length code table */
661 huft_t *td; /* distance code table */ 628 huft_t *td; /* distance code table */
662 int bl; /* lookup bits for tl */ 629 unsigned int bl; /* lookup bits for tl */
663 int bd; /* lookup bits for td */ 630 unsigned int bd; /* lookup bits for td */
664 unsigned int l[288]; /* length list for huft_build */ 631 unsigned int l[288]; /* length list for huft_build */
665 632
666 /* set up literal table */ 633 /* set up literal table */
@@ -692,8 +659,9 @@ static int inflate_block(int *e)
692 } 659 }
693 660
694 /* decompress until an end-of-block code */ 661 /* decompress until an end-of-block code */
695 if (inflate_codes(tl, td, bl, bd)) 662 if (inflate_codes(tl, td, bl, bd)) {
696 return 1; 663 return 1;
664 }
697 665
698 /* free the decoding tables, return */ 666 /* free the decoding tables, return */
699 huft_free(tl); 667 huft_free(tl);
@@ -705,53 +673,41 @@ static int inflate_block(int *e)
705 const int dbits = 6; /* bits in base distance lookup table */ 673 const int dbits = 6; /* bits in base distance lookup table */
706 const int lbits = 9; /* bits in base literal/length lookup table */ 674 const int lbits = 9; /* bits in base literal/length lookup table */
707 675
708 int i; /* temporary variables */
709 unsigned j;
710 unsigned l; /* last length */
711 unsigned m; /* mask for bit lengths table */
712 unsigned n; /* number of lengths to get */
713 huft_t *tl; /* literal/length code table */ 676 huft_t *tl; /* literal/length code table */
714 huft_t *td; /* distance code table */ 677 huft_t *td; /* distance code table */
715 int bl; /* lookup bits for tl */ 678 unsigned int i; /* temporary variables */
716 int bd; /* lookup bits for td */ 679 unsigned int j;
717 unsigned nb; /* number of bit length codes */ 680 unsigned int l; /* last length */
718 unsigned nl; /* number of literal/length codes */ 681 unsigned int m; /* mask for bit lengths table */
719 unsigned nd; /* number of distance codes */ 682 unsigned int n; /* number of lengths to get */
720 683 unsigned int bl; /* lookup bits for tl */
721 unsigned ll[286 + 30]; /* literal/length and distance code lengths */ 684 unsigned int bd; /* lookup bits for td */
722 register unsigned long b_dynamic; /* bit buffer */ 685 unsigned int nb; /* number of bit length codes */
723 register unsigned k_dynamic; /* number of bits in bit buffer */ 686 unsigned int nl; /* number of literal/length codes */
687 unsigned int nd; /* number of distance codes */
688
689 unsigned int ll[286 + 30]; /* literal/length and distance code lengths */
690 unsigned int b_dynamic; /* bit buffer */
691 unsigned int k_dynamic; /* number of bits in bit buffer */
724 692
725 /* make local bit buffer */ 693 /* make local bit buffer */
726 b_dynamic = bb; 694 b_dynamic = gunzip_bb;
727 k_dynamic = bk; 695 k_dynamic = gunzip_bk;
728 696
729 /* read in table lengths */ 697 /* read in table lengths */
730 while (k_dynamic < 5) { 698 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
731 input_char = fgetc(in_file); 699 nl = 257 + ((unsigned int) b_dynamic & 0x1f); /* number of literal/length codes */
732 if (input_char == EOF) return 1; 700
733 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
734 k_dynamic += 8;
735 }
736 nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */
737 b_dynamic >>= 5; 701 b_dynamic >>= 5;
738 k_dynamic -= 5; 702 k_dynamic -= 5;
739 while (k_dynamic < 5) { 703 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
740 input_char = fgetc(in_file); 704 nd = 1 + ((unsigned int) b_dynamic & 0x1f); /* number of distance codes */
741 if (input_char == EOF) return 1; 705
742 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
743 k_dynamic += 8;
744 }
745 nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */
746 b_dynamic >>= 5; 706 b_dynamic >>= 5;
747 k_dynamic -= 5; 707 k_dynamic -= 5;
748 while (k_dynamic < 4) { 708 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 4);
749 input_char = fgetc(in_file); 709 nb = 4 + ((unsigned int) b_dynamic & 0xf); /* number of bit length codes */
750 if (input_char == EOF) return 1; 710
751 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
752 k_dynamic += 8;
753 }
754 nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */
755 b_dynamic >>= 4; 711 b_dynamic >>= 4;
756 k_dynamic -= 4; 712 k_dynamic -= 4;
757 if (nl > 286 || nd > 30) { 713 if (nl > 286 || nd > 30) {
@@ -760,13 +716,8 @@ static int inflate_block(int *e)
760 716
761 /* read in bit-length-code lengths */ 717 /* read in bit-length-code lengths */
762 for (j = 0; j < nb; j++) { 718 for (j = 0; j < nb; j++) {
763 while (k_dynamic < 3) { 719 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
764 input_char = fgetc(in_file); 720 ll[border[j]] = (unsigned int) b_dynamic & 7;
765 if (input_char == EOF) return 1;
766 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
767 k_dynamic += 8;
768 }
769 ll[border[j]] = (unsigned) b_dynamic & 7;
770 b_dynamic >>= 3; 721 b_dynamic >>= 3;
771 k_dynamic -= 3; 722 k_dynamic -= 3;
772 } 723 }
@@ -776,7 +727,8 @@ static int inflate_block(int *e)
776 727
777 /* build decoding table for trees--single level, 7 bit lookup */ 728 /* build decoding table for trees--single level, 7 bit lookup */
778 bl = 7; 729 bl = 7;
779 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) { 730 i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl);
731 if (i != 0) {
780 if (i == 1) { 732 if (i == 1) {
781 huft_free(tl); 733 huft_free(tl);
782 } 734 }
@@ -787,46 +739,31 @@ static int inflate_block(int *e)
787 n = nl + nd; 739 n = nl + nd;
788 m = mask_bits[bl]; 740 m = mask_bits[bl];
789 i = l = 0; 741 i = l = 0;
790 while ((unsigned) i < n) { 742 while ((unsigned int) i < n) {
791 while (k_dynamic < (unsigned) bl) { 743 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, (unsigned int)bl);
792 input_char = fgetc(in_file); 744 j = (td = tl + ((unsigned int) b_dynamic & m))->b;
793 if (input_char == EOF) return 1;
794 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
795 k_dynamic += 8;
796 }
797 j = (td = tl + ((unsigned) b_dynamic & m))->b;
798 b_dynamic >>= j; 745 b_dynamic >>= j;
799 k_dynamic -= j; 746 k_dynamic -= j;
800 j = td->v.n; 747 j = td->v.n;
801 if (j < 16) { /* length of code in bits (0..15) */ 748 if (j < 16) { /* length of code in bits (0..15) */
802 ll[i++] = l = j; /* save last length in l */ 749 ll[i++] = l = j; /* save last length in l */
803 } else if (j == 16) { /* repeat last length 3 to 6 times */ 750 } else if (j == 16) { /* repeat last length 3 to 6 times */
804 while (k_dynamic < 2) { 751 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 2);
805 input_char = fgetc(in_file); 752 j = 3 + ((unsigned int) b_dynamic & 3);
806 if (input_char == EOF) return 1;
807 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
808 k_dynamic += 8;
809 }
810 j = 3 + ((unsigned) b_dynamic & 3);
811 b_dynamic >>= 2; 753 b_dynamic >>= 2;
812 k_dynamic -= 2; 754 k_dynamic -= 2;
813 if ((unsigned) i + j > n) { 755 if ((unsigned int) i + j > n) {
814 return 1; 756 return 1;
815 } 757 }
816 while (j--) { 758 while (j--) {
817 ll[i++] = l; 759 ll[i++] = l;
818 } 760 }
819 } else if (j == 17) { /* 3 to 10 zero length codes */ 761 } else if (j == 17) { /* 3 to 10 zero length codes */
820 while (k_dynamic < 3) { 762 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
821 input_char = fgetc(in_file); 763 j = 3 + ((unsigned int) b_dynamic & 7);
822 if (input_char == EOF) return 1;
823 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
824 k_dynamic += 8;
825 }
826 j = 3 + ((unsigned) b_dynamic & 7);
827 b_dynamic >>= 3; 764 b_dynamic >>= 3;
828 k_dynamic -= 3; 765 k_dynamic -= 3;
829 if ((unsigned) i + j > n) { 766 if ((unsigned int) i + j > n) {
830 return 1; 767 return 1;
831 } 768 }
832 while (j--) { 769 while (j--) {
@@ -834,16 +771,11 @@ static int inflate_block(int *e)
834 } 771 }
835 l = 0; 772 l = 0;
836 } else { /* j == 18: 11 to 138 zero length codes */ 773 } else { /* j == 18: 11 to 138 zero length codes */
837 while (k_dynamic < 7) { 774 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 7);
838 input_char = fgetc(in_file); 775 j = 11 + ((unsigned int) b_dynamic & 0x7f);
839 if (input_char == EOF) return 1;
840 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
841 k_dynamic += 8;
842 }
843 j = 11 + ((unsigned) b_dynamic & 0x7f);
844 b_dynamic >>= 7; 776 b_dynamic >>= 7;
845 k_dynamic -= 7; 777 k_dynamic -= 7;
846 if ((unsigned) i + j > n) { 778 if ((unsigned int) i + j > n) {
847 return 1; 779 return 1;
848 } 780 }
849 while (j--) { 781 while (j--) {
@@ -857,22 +789,24 @@ static int inflate_block(int *e)
857 huft_free(tl); 789 huft_free(tl);
858 790
859 /* restore the global bit buffer */ 791 /* restore the global bit buffer */
860 bb = b_dynamic; 792 gunzip_bb = b_dynamic;
861 bk = k_dynamic; 793 gunzip_bk = k_dynamic;
862 794
863 /* build the decoding tables for literal/length and distance codes */ 795 /* build the decoding tables for literal/length and distance codes */
864 bl = lbits; 796 bl = lbits;
797
865 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) { 798 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
866 if (i == 1) { 799 if (i == 1) {
867 error_msg("Incomplete literal tree"); 800 error_msg_and_die("Incomplete literal tree");
868 huft_free(tl); 801 huft_free(tl);
869 } 802 }
870 return i; /* incomplete code set */ 803 return i; /* incomplete code set */
871 } 804 }
805
872 bd = dbits; 806 bd = dbits;
873 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) { 807 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
874 if (i == 1) { 808 if (i == 1) {
875 error_msg("incomplete distance tree"); 809 error_msg_and_die("incomplete distance tree");
876 huft_free(td); 810 huft_free(td);
877 } 811 }
878 huft_free(tl); 812 huft_free(tl);
@@ -880,8 +814,9 @@ static int inflate_block(int *e)
880 } 814 }
881 815
882 /* decompress until an end-of-block code */ 816 /* decompress until an end-of-block code */
883 if (inflate_codes(tl, td, bl, bd)) 817 if (inflate_codes(tl, td, bl, bd)) {
884 return 1; 818 return 1;
819 }
885 820
886 /* free the decoding tables, return */ 821 /* free the decoding tables, return */
887 huft_free(tl); 822 huft_free(tl);
@@ -890,6 +825,7 @@ static int inflate_block(int *e)
890 } 825 }
891 default: 826 default:
892 /* bad block type */ 827 /* bad block type */
828 error_msg("bad block type %d\n", t);
893 return 2; 829 return 2;
894 } 830 }
895} 831}
@@ -897,72 +833,24 @@ static int inflate_block(int *e)
897/* 833/*
898 * decompress an inflated entry 834 * decompress an inflated entry
899 * 835 *
900 * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr 836 * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr
901 */ 837 */
902extern int inflate(FILE * in, FILE * out) 838extern int inflate(int in, int out)
903{ 839{
840 typedef void (*sig_type) (int);
904 int e; /* last block flag */ 841 int e; /* last block flag */
905 int r; /* result code */ 842 int r; /* result code */
906 unsigned h = 0; /* maximum struct huft's malloc'ed */ 843 unsigned h = 0; /* maximum struct huft's malloc'ed */
907 844
908 /* initialize window, bit buffer */
909 outcnt = 0;
910 bk = 0;
911 bb = 0;
912
913 in_file = in;
914 out_file = out;
915
916 /* Allocate all global buffers (for DYN_ALLOC option) */ 845 /* Allocate all global buffers (for DYN_ALLOC option) */
917 window = xmalloc((size_t) (((2L * WSIZE) + 1L) * sizeof(unsigned char))); 846 gunzip_window = xmalloc(0x8000);
918 bytes_out = 0L; 847 gunzip_outbuf_count = 0;
848 gunzip_bytes_out = 0;
919 849
920 /* Create the crc table */ 850 gunzip_src_fd = in;
921 make_crc_table(); 851 gunzip_dst_fd = out;
922 852
923 /* decompress until the last block */ 853 gunzip_in_buffer = malloc(8);
924 do {
925 hufts = 0;
926 if ((r = inflate_block(&e)) != 0) {
927 return r;
928 }
929 if (hufts > h) {
930 h = hufts;
931 }
932 } while (!e);
933
934 /* Undo too much lookahead. The next read will be byte aligned so we
935 * can discard unused bits in the last meaningful byte.
936 */
937 while (bk >= 8) {
938 bk -= 8;
939 ungetc((bb << bk), in_file);
940 }
941
942 /* flush out window */
943 flush_window();
944 free(window);
945 free(crc_table);
946
947 /* return success */
948 return 0;
949}
950
951/* ===========================================================================
952 * Unzip in to out. This routine works on gzip files only.
953 *
954 * IN assertions: the buffer inbuf contains already the beginning of
955 * the compressed data, from offsets inptr to insize-1 included.
956 * The magic header has already been checked. The output buffer is cleared.
957 * in, out: input and output file descriptors
958 */
959extern int unzip(FILE * l_in_file, FILE * l_out_file)
960{
961 unsigned char buf[8]; /* extended local header */
962 unsigned char flags; /* compression flags */
963 typedef void (*sig_type) (int);
964 unsigned short i;
965 unsigned char magic[2];
966 854
967 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 855 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
968 (void) signal(SIGINT, (sig_type) abort_gzip); 856 (void) signal(SIGINT, (sig_type) abort_gzip);
@@ -973,97 +861,44 @@ extern int unzip(FILE * l_in_file, FILE * l_out_file)
973 } 861 }
974#endif 862#endif
975 863
976 magic[0] = fgetc(l_in_file); 864 /* initialize gunzip_window, bit buffer */
977 magic[1] = fgetc(l_in_file); 865 gunzip_bk = 0;
978 866 gunzip_bb = 0;
979#ifdef CONFIG_FEATURE_UNCOMPRESS
980 /* Magic header for compress files, 1F 9d = \037\235 */
981 if ((magic[0] == 0x1F) && (magic[1] == 0x9d)) {
982 return uncompress(l_in_file, l_out_file);
983 }
984#endif
985
986 /* Magic header for gzip files, 1F 8B = \037\213 */
987 if ((magic[0] != 0x1F) || (magic[1] != 0x8b)) {
988 error_msg("Invalid gzip magic");
989 return EXIT_FAILURE;
990 }
991
992 /* Check the compression method */
993 if (fgetc(l_in_file) != 8) /* also catches EOF */ {
994 error_msg("Unknown compression method");
995 return (-1);
996 }
997
998 flags = (unsigned char) fgetc(l_in_file);
999
1000 /* Ignore time stamp(4), extra flags(1), OS type(1) */
1001 for (i = 0; i < 6; i++) {
1002 fgetc(l_in_file);
1003 }
1004 867
1005 if (flags & 0x04) { 868 /* Create the crc table */
1006 /* bit 2 set: extra field present */ 869 make_gunzip_crc_table();
1007 const unsigned short extra =
1008 fgetc(l_in_file) + (fgetc(l_in_file) << 8);
1009 if (feof(in_file)) return 1;
1010 for (i = 0; i < extra; i++) {
1011 fgetc(l_in_file);
1012 }
1013 }
1014
1015 /* Discard original name if any */
1016 if (flags & 0x08) {
1017 /* bit 3 set: original file name present */
1018 while (fgetc(l_in_file) != 0 && !feof(l_in_file)); /* null */
1019 }
1020 870
1021 /* Discard file comment if any */ 871 /* decompress until the last block */
1022 if (flags & 0x10) { 872 do {
1023 /* bit 4 set: file comment present */ 873 gunzip_hufts = 0;
1024 while (fgetc(l_in_file) != 0 && !feof(l_in_file)); /* null */ 874 r = inflate_block(&e);
875 if (r != 0) {
876 error_msg_and_die("inflate error %d", r);
877 return r;
1025 } 878 }
1026 879 if (gunzip_hufts > h) {
1027 /* Decompress */ 880 h = gunzip_hufts;
1028 if (inflate(l_in_file, l_out_file) != 0) {
1029 error_msg("invalid compressed data--format violated");
1030 } 881 }
882 } while (!e);
1031 883
1032 /* Get the crc and original length 884 /* write any buffered uncompressed data */
1033 * crc32 (see algorithm.doc) 885 flush_gunzip_window();
1034 * uncompressed input size modulo 2^32 886 free(gunzip_window);
1035 */ 887
1036 fread(buf, 1, 8, l_in_file); 888 /* Cleanup */
1037 889 free(gunzip_crc_table);
1038 /* Validate decompression - crc */ 890
1039 if ((unsigned int) ((buf[0] | (buf[1] << 8)) | 891 /* Store unused bytes in a global buffer so calling applets can access it */
1040 ((buf[2] | (buf[3] << 8)) << 16)) != 892 gunzip_in_buffer_count = 0;
1041 (crc ^ 0xffffffffL)) { 893 if (gunzip_bk >= 8) {
1042 error_msg("invalid compressed data--crc error"); 894 /* Undo too much lookahead. The next read will be byte aligned
1043 } 895 * so we can discard unused bits in the last meaningful byte. */
1044 /* Validate decompression - size */ 896 gunzip_in_buffer[gunzip_in_buffer_count] = gunzip_bb & 0xff;
1045 if (((buf[4] | (buf[5] << 8)) | ((buf[6] | (buf[7] << 8)) << 16)) != 897 gunzip_in_buffer_count++;
1046 (unsigned long) bytes_out) { 898 gunzip_bb >>= 8;
1047 error_msg("invalid compressed data--length error"); 899 gunzip_bk -= 8;
1048 } 900 }
1049 901
902 /* return success */
1050 return 0; 903 return 0;
1051} 904}
1052
1053/*
1054 * This needs access to global variables window and crc_table, so its not in its own file.
1055 */
1056extern void gz_close(int gunzip_pid)
1057{
1058 if (kill(gunzip_pid, SIGTERM) == -1) {
1059 error_msg_and_die
1060 ("*** Couldnt kill old gunzip process *** aborting");
1061 }
1062
1063 if (waitpid(gunzip_pid, NULL, 0) == -1) {
1064 printf("Couldnt wait ?");
1065 }
1066
1067 free(window);
1068 free(crc_table);
1069}
diff --git a/archival/libunarchive/filter_accept_all.c b/archival/libunarchive/filter_accept_all.c
new file mode 100644
index 000000000..0471ccef0
--- /dev/null
+++ b/archival/libunarchive/filter_accept_all.c
@@ -0,0 +1,10 @@
1#include <fnmatch.h>
2#include <stdlib.h>
3#include "unarchive.h"
4/*
5 * Accept names that are in the accept list
6 */
7extern char filter_accept_all(const llist_t *accept_list, const llist_t *reject_list, const char *key)
8{
9 return(EXIT_SUCCESS);
10}
diff --git a/archival/libunarchive/filter_accept_list.c b/archival/libunarchive/filter_accept_list.c
new file mode 100644
index 000000000..06b1dd3dd
--- /dev/null
+++ b/archival/libunarchive/filter_accept_list.c
@@ -0,0 +1,16 @@
1#include <fnmatch.h>
2#include <stdlib.h>
3#include "unarchive.h"
4/*
5 * Accept names that are in the accept list
6 */
7extern char filter_accept_list(const llist_t *accept_list, const llist_t *reject_list, const char *key)
8{
9 while (accept_list) {
10 if (fnmatch(accept_list->data, key, 0) == 0) {
11 return(EXIT_SUCCESS);
12 }
13 accept_list = accept_list->link;
14 }
15 return(EXIT_FAILURE);
16}
diff --git a/archival/libunarchive/filter_accept_reject_list.c b/archival/libunarchive/filter_accept_reject_list.c
new file mode 100644
index 000000000..c893dfcfc
--- /dev/null
+++ b/archival/libunarchive/filter_accept_reject_list.c
@@ -0,0 +1,34 @@
1#include <fnmatch.h>
2#include <stdlib.h>
3#include "unarchive.h"
4
5static char check_list(const llist_t *list, const char *filename)
6{
7 if (list) {
8 while (list) {
9 if (fnmatch(list->data, filename, 0) == 0) {
10 return(EXIT_SUCCESS);
11 }
12 list = list->link;
13 }
14 }
15 return(EXIT_FAILURE);
16}
17
18/*
19 * Accept names that are in the accept list
20 */
21extern char filter_accept_reject_list(const llist_t *accept_list, const llist_t *reject_list, const char *key)
22{
23 /* Fail if an accept list was specified and the key wasnt in there */
24 if ((accept_list) && (check_list(accept_list, key) == EXIT_FAILURE)) {
25 return(EXIT_FAILURE);
26 }
27
28 /* If the key is in a reject list fail */
29 if (check_list(reject_list, key) == EXIT_FAILURE) {
30 return(EXIT_FAILURE);
31 }
32
33 return(EXIT_SUCCESS);
34}
diff --git a/archival/libunarchive/get_header_ar.c b/archival/libunarchive/get_header_ar.c
index f172fa7c9..b7f2cfbcd 100644
--- a/archival/libunarchive/get_header_ar.c
+++ b/archival/libunarchive/get_header_ar.c
@@ -17,12 +17,13 @@
17#include <stdio.h> 17#include <stdio.h>
18#include <stdlib.h> 18#include <stdlib.h>
19#include <string.h> 19#include <string.h>
20#include <unistd.h>
20#include "unarchive.h" 21#include "unarchive.h"
21#include "libbb.h" 22#include "libbb.h"
22 23
23file_header_t *get_header_ar(FILE *src_stream) 24extern char get_header_ar(archive_handle_t *archive_handle)
24{ 25{
25 file_header_t *typed; 26 file_header_t *typed = archive_handle->file_header;
26 union { 27 union {
27 char raw[60]; 28 char raw[60];
28 struct { 29 struct {
@@ -35,72 +36,87 @@ file_header_t *get_header_ar(FILE *src_stream)
35 char magic[2]; 36 char magic[2];
36 } formated; 37 } formated;
37 } ar; 38 } ar;
39#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
38 static char *ar_long_names; 40 static char *ar_long_names;
41 static unsigned int ar_long_name_size;
42#endif
39 43
40 if (fread(ar.raw, 1, 60, src_stream) != 60) { 44 /* dont use xread as we want to handle the error ourself */
41 return(NULL); 45 if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
42 } 46 /* End Of File */
43 archive_offset += 60; 47 return(EXIT_FAILURE);
44 /* align the headers based on the header magic */
45 if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
46 /* some version of ar, have an extra '\n' after each data entry,
47 * this puts the next header out by 1 */
48 if (ar.formated.magic[1] != '`') {
49 error_msg("Invalid magic");
50 return(NULL);
51 }
52 /* read the next char out of what would be the data section,
53 * if its a '\n' then it is a valid header offset by 1*/
54 archive_offset++;
55 if (fgetc(src_stream) != '\n') {
56 error_msg("Invalid magic");
57 return(NULL);
58 } 48 }
49
50 /* Some ar entries have a trailing '\n' after the previous data entry */
51 if (ar.raw[0] == '\n') {
59 /* fix up the header, we started reading 1 byte too early */ 52 /* fix up the header, we started reading 1 byte too early */
60 /* raw_header[60] wont be '\n' as it should, but it doesnt matter */
61 memmove(ar.raw, &ar.raw[1], 59); 53 memmove(ar.raw, &ar.raw[1], 59);
54 ar.raw[59] = xread_char(archive_handle->src_fd);
55 archive_handle->offset++;
62 } 56 }
57 archive_handle->offset += 60;
63 58
64 typed = (file_header_t *) xcalloc(1, sizeof(file_header_t)); 59 /* align the headers based on the header magic */
60 if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
61 error_msg_and_die("Invalid ar header");
62 }
63
64 typed->mode = strtol(ar.formated.mode, NULL, 8);
65 typed->mtime = atoi(ar.formated.date);
66 typed->uid = atoi(ar.formated.uid);
67 typed->gid = atoi(ar.formated.gid);
68 typed->size = atoi(ar.formated.size);
65 69
66 typed->size = (size_t) atoi(ar.formated.size);
67 /* long filenames have '/' as the first character */ 70 /* long filenames have '/' as the first character */
68 if (ar.formated.name[0] == '/') { 71 if (ar.formated.name[0] == '/') {
72#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
69 if (ar.formated.name[1] == '/') { 73 if (ar.formated.name[1] == '/') {
70 /* If the second char is a '/' then this entries data section 74 /* If the second char is a '/' then this entries data section
71 * stores long filename for multiple entries, they are stored 75 * stores long filename for multiple entries, they are stored
72 * in static variable long_names for use in future entries */ 76 * in static variable long_names for use in future entries */
73 ar_long_names = (char *) xrealloc(ar_long_names, typed->size); 77 ar_long_name_size = typed->size;
74 fread(ar_long_names, 1, typed->size, src_stream); 78 ar_long_names = xmalloc(ar_long_name_size);
75 archive_offset += typed->size; 79 xread_all(archive_handle->src_fd, ar_long_names, ar_long_name_size);
80 archive_handle->offset += ar_long_name_size;
76 /* This ar entries data section only contained filenames for other records 81 /* This ar entries data section only contained filenames for other records
77 * they are stored in the static ar_long_names for future reference */ 82 * they are stored in the static ar_long_names for future reference */
78 return (get_header_ar(src_stream)); /* Return next header */ 83 return (get_header_ar(archive_handle)); /* Return next header */
79 } else if (ar.formated.name[1] == ' ') { 84 } else if (ar.formated.name[1] == ' ') {
80 /* This is the index of symbols in the file for compilers */ 85 /* This is the index of symbols in the file for compilers */
81 seek_sub_file(src_stream, typed->size); 86 data_skip(archive_handle);
82 return (get_header_ar(src_stream)); /* Return next header */ 87 return (get_header_ar(archive_handle)); /* Return next header */
83 } else { 88 } else {
84 /* The number after the '/' indicates the offset in the ar data section 89 /* The number after the '/' indicates the offset in the ar data section
85 (saved in variable long_name) that conatains the real filename */ 90 (saved in variable long_name) that conatains the real filename */
86 if (!ar_long_names) { 91 const unsigned int long_offset = atoi(&ar.formated.name[1]);
87 error_msg("Cannot resolve long file name"); 92 if (long_offset >= ar_long_name_size) {
88 return (NULL); 93 error_msg_and_die("Cant resolve long filename");
89 } 94 }
90 typed->name = xstrdup(ar_long_names + atoi(&ar.formated.name[1])); 95 typed->name = xstrdup(ar_long_names + long_offset);
91 } 96 }
97#else
98 error_msg_and_die("long filenames not supported");
99#endif
92 } else { 100 } else {
93 /* short filenames */ 101 /* short filenames */
94 typed->name = xstrndup(ar.formated.name, 16); 102 typed->name = xstrndup(ar.formated.name, 16);
95 } 103 }
96 typed->name[strcspn(typed->name, " /")]='\0';
97 104
98 /* convert the rest of the now valid char header to its typed struct */ 105 typed->name[strcspn(typed->name, " /")] = '\0';
99 parse_mode(ar.formated.mode, &typed->mode); 106
100 typed->mtime = atoi(ar.formated.date); 107 if (archive_handle->filter(archive_handle->accept, archive_handle->reject, typed->name) == EXIT_SUCCESS) {
101 typed->uid = atoi(ar.formated.uid); 108 archive_handle->action_header(typed);
102 typed->gid = atoi(ar.formated.gid); 109 if (archive_handle->sub_archive) {
110 while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS);
111 } else {
112 archive_handle->action_data(archive_handle);
113 }
114 } else {
115 data_skip(archive_handle);
116 }
117
118 archive_handle->offset += typed->size + 1;
103 119
104 return(typed); 120 return(EXIT_SUCCESS);
105} 121}
106 122
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c
index e6747b72f..2c8fc0aa0 100644
--- a/archival/libunarchive/get_header_tar.c
+++ b/archival/libunarchive/get_header_tar.c
@@ -20,8 +20,9 @@
20#include "unarchive.h" 20#include "unarchive.h"
21#include "libbb.h" 21#include "libbb.h"
22 22
23file_header_t *get_header_tar(FILE * tar_stream) 23extern char get_header_tar(archive_handle_t *archive_handle)
24{ 24{
25 file_header_t *file_header = archive_handle->file_header;
25 union { 26 union {
26 unsigned char raw[512]; 27 unsigned char raw[512];
27 struct { 28 struct {
@@ -44,20 +45,22 @@ file_header_t *get_header_tar(FILE * tar_stream)
44 char padding[12]; /* 500-512 */ 45 char padding[12]; /* 500-512 */
45 } formated; 46 } formated;
46 } tar; 47 } tar;
47 file_header_t *tar_entry = NULL;
48 long sum = 0; 48 long sum = 0;
49 long i; 49 long i;
50 50
51 if (archive_offset % 512 != 0) { 51 /* Align header */
52 seek_sub_file(tar_stream, 512 - (archive_offset % 512)); 52 archive_handle->offset += data_align(archive_handle->src_fd, archive_handle->offset, 512);
53
54 if (xread_all_eof(archive_handle->src_fd, tar.raw, 512) == 0) {
55 /* End of file */
56 return(EXIT_FAILURE);
53 } 57 }
58 archive_handle->offset += 512;
54 59
55 if (fread(tar.raw, 1, 512, tar_stream) != 512) { 60 /* If there is no filename its an empty header */
56 /* Unfortunatly its common for tar files to have all sorts of 61 if (tar.formated.name[0] == 0) {
57 * trailing garbage, fail silently */ 62 return(EXIT_SUCCESS);
58 return (NULL);
59 } 63 }
60 archive_offset += 512;
61 64
62 /* Check header has valid magic, "ustar" is for the proper tar 65 /* Check header has valid magic, "ustar" is for the proper tar
63 * 0's are for the old tar format 66 * 0's are for the old tar format
@@ -66,100 +69,102 @@ file_header_t *get_header_tar(FILE * tar_stream)
66#ifdef CONFIG_FEATURE_TAR_OLD_FORMAT 69#ifdef CONFIG_FEATURE_TAR_OLD_FORMAT
67 if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0) 70 if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0)
68#endif 71#endif
69 return (NULL); 72 error_msg_and_die("Invalid tar magic");
70 }
71
72 /* If there is no filename its an empty header, skip it */
73 if (tar.formated.name[0] == 0) {
74 return (NULL);
75 } 73 }
76 74
77 /* Do checksum on headers */ 75 /* Do checksum on headers */
78 for (i = 0; i < 148; i++) { 76 for (i = 0; i < 148 ; i++) {
79 sum += tar.raw[i]; 77 sum += tar.raw[i];
80 } 78 }
81 sum += ' ' * 8; 79 sum += ' ' * 8;
82 for (i = 156; i < 512; i++) { 80 for (i = 156; i < 512 ; i++) {
83 sum += tar.raw[i]; 81 sum += tar.raw[i];
84 } 82 }
85 if (sum != strtol(tar.formated.chksum, NULL, 8)) { 83 if (sum != strtol(tar.formated.chksum, NULL, 8)) {
86 error_msg("Invalid tar header checksum"); 84 error_msg("Invalid tar header checksum");
87 return (NULL); 85 return(EXIT_FAILURE);
88 } 86 }
89 87
90 /* convert to type'ed variables */ 88 /* convert to type'ed variables */
91 tar_entry = xcalloc(1, sizeof(file_header_t));
92 if (tar.formated.prefix[0] == 0) { 89 if (tar.formated.prefix[0] == 0) {
93 tar_entry->name = xstrdup(tar.formated.name); 90 file_header->name = strdup(tar.formated.name);
94 } else { 91 } else {
95 tar_entry->name = 92 file_header->name = concat_path_file(tar.formated.prefix, tar.formated.name);
96 concat_path_file(tar.formated.prefix, tar.formated.name);
97 } 93 }
98 94 file_header->mode = strtol(tar.formated.mode, NULL, 8);
99 tar_entry->mode = strtol(tar.formated.mode, NULL, 8); 95 file_header->uid = strtol(tar.formated.uid, NULL, 8);
100 tar_entry->uid = strtol(tar.formated.uid, NULL, 8); 96 file_header->gid = strtol(tar.formated.gid, NULL, 8);
101 tar_entry->gid = strtol(tar.formated.gid, NULL, 8); 97 file_header->size = strtol(tar.formated.size, NULL, 8);
102 tar_entry->size = strtol(tar.formated.size, NULL, 8); 98 file_header->mtime = strtol(tar.formated.mtime, NULL, 8);
103 tar_entry->mtime = strtol(tar.formated.mtime, NULL, 8); 99 file_header->link_name = (tar.formated.linkname[0] != '\0') ?
104 tar_entry->link_name = 100 xstrdup(tar.formated.linkname) : NULL;
105 strlen(tar.formated.linkname) ? xstrdup(tar.formated.linkname) : NULL; 101 file_header->device = (dev_t) ((strtol(tar.formated.devmajor, NULL, 8) << 8) +
106 tar_entry->device =
107 (dev_t) ((strtol(tar.formated.devmajor, NULL, 8) << 8) +
108 strtol(tar.formated.devminor, NULL, 8)); 102 strtol(tar.formated.devminor, NULL, 8));
109 103
110#if defined CONFIG_FEATURE_TAR_OLD_FORMAT || defined CONFIG_FEATURE_GNUTAR_LONG_FILENAME 104#if defined CONFIG_FEATURE_TAR_OLD_FORMAT || defined CONFIG_FEATURE_GNUTAR_LONG_FILENAME
105 /* Fix mode, used by the old format */
111 switch (tar.formated.typeflag) { 106 switch (tar.formated.typeflag) {
112# ifdef CONFIG_FEATURE_TAR_OLD_FORMAT 107# ifdef CONFIG_FEATURE_TAR_OLD_FORMAT
113 case 0: 108 case 0:
114 tar_entry->mode |= S_IFREG; 109 file_header->mode |= S_IFREG;
115 break; 110 break;
116 case 1: 111 case 1:
117 error_msg("internal hard link not handled\n"); 112 error_msg("Internal hard link not supported");
118 break; 113 break;
119 case 2: 114 case 2:
120 tar_entry->mode |= S_IFLNK; 115 file_header->mode |= S_IFLNK;
121 break; 116 break;
122 case 3: 117 case 3:
123 tar_entry->mode |= S_IFCHR; 118 file_header->mode |= S_IFCHR;
124 break; 119 break;
125 case 4: 120 case 4:
126 tar_entry->mode |= S_IFBLK; 121 file_header->mode |= S_IFBLK;
127 break; 122 break;
128 case 5: 123 case 5:
129 tar_entry->mode |= S_IFDIR; 124 file_header->mode |= S_IFDIR;
130 break; 125 break;
131 case 6: 126 case 6:
132 tar_entry->mode |= S_IFIFO; 127 file_header->mode |= S_IFIFO;
133 break; 128 break;
134# endif 129# endif
135# ifdef CONFIG_FEATURE_GNUTAR_LONG_FILENAME 130# ifdef CONFIG_FEATURE_GNUTAR_LONG_FILENAME
136 case 'L': { 131 case 'L': {
137 char *longname; 132 char *longname;
138 133
139 longname = xmalloc(tar_entry->size + 1); 134 longname = xmalloc(file_header->size + 1);
140 fread(longname, 1, tar_entry->size, tar_stream); 135 xread_all(archive_handle->src_fd, longname, file_header->size);
141 archive_offset += tar_entry->size; 136 longname[file_header->size] = '\0';
142 longname[tar_entry->size] = '\0'; 137 archive_handle->offset += file_header->size;
143 138
144 tar_entry = get_header_tar(tar_stream); 139 get_header_tar(archive_handle);
145 tar_entry->name = longname; 140 file_header->name = longname;
146 break; 141 break;
147 } 142 }
148 case 'K': { 143 case 'K': {
149 char *longname; 144 char *linkname;
150 145
151 longname = xmalloc(tar_entry->size + 1); 146 linkname = xmalloc(file_header->size + 1);
152 fread(longname, 1, tar_entry->size, tar_stream); 147 xread_all(archive_handle->src_fd, linkname, file_header->size);
153 archive_offset += tar_entry->size; 148 linkname[file_header->size] = '\0';
154 longname[tar_entry->size] = '\0'; 149 archive_handle->offset += file_header->size;
155 150
156 tar_entry = get_header_tar(tar_stream); 151 get_header_tar(archive_handle);
157 tar_entry->link_name = longname; 152 file_header->name = linkname;
158 break; 153 break;
159 } 154 }
160# endif 155# endif
161 } 156 }
162#endif 157#endif
163 158
164 return (tar_entry); 159 if (archive_handle->filter(archive_handle->accept, archive_handle->reject, archive_handle->file_header->name) == EXIT_SUCCESS) {
160 archive_handle->action_header(archive_handle->file_header);
161 archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
162 archive_handle->action_data(archive_handle);
163 } else {
164 data_skip(archive_handle);
165 }
166 archive_handle->offset += file_header->size;
167
168 return(EXIT_SUCCESS);
165} 169}
170
diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c
new file mode 100644
index 000000000..c06beac9d
--- /dev/null
+++ b/archival/libunarchive/get_header_tar_gz.c
@@ -0,0 +1,73 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#include <sys/types.h>
18#include <signal.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include "libbb.h"
24#include "unarchive.h"
25
26extern char get_header_tar_gz(archive_handle_t *archive_handle)
27{
28 int fd_pipe[2];
29 int pid;
30
31 check_header_gzip(archive_handle->src_fd);
32
33 if (pipe(fd_pipe) != 0) {
34 error_msg_and_die("Can't create pipe\n");
35 }
36
37 pid = fork();
38 if (pid == -1) {
39 error_msg_and_die("Fork failed\n");
40 }
41
42 if (pid == 0) {
43 /* child process */
44 close(fd_pipe[0]); /* We don't wan't to read from the pipe */
45 inflate(archive_handle->src_fd, fd_pipe[1]);
46 check_trailer_gzip(archive_handle->src_fd);
47 close(fd_pipe[1]); /* Send EOF */
48 exit(0);
49 /* notreached */
50 }
51 /* parent process */
52 close(fd_pipe[1]); /* Don't want to write down the pipe */
53 close(archive_handle->src_fd);
54
55 archive_handle->src_fd = fd_pipe[0];
56
57 while (get_header_tar(archive_handle) == EXIT_SUCCESS);
58
59 if (kill(pid, SIGTERM) == -1) {
60 error_msg_and_die("Couldnt kill gunzip process");
61 }
62
63 /* I dont think this is needed */
64#if 0
65 if (waitpid(pid, NULL, 0) == -1) {
66 error_msg("Couldnt wait ?");
67 }
68#endif
69
70 /* Can only do one file at a time */
71 return(EXIT_FAILURE);
72}
73
diff --git a/archival/libunarchive/header_list.c b/archival/libunarchive/header_list.c
new file mode 100644
index 000000000..5849a762e
--- /dev/null
+++ b/archival/libunarchive/header_list.c
@@ -0,0 +1,7 @@
1#include <stdio.h>
2#include "unarchive.h"
3
4extern void header_list(const file_header_t *file_header)
5{
6 puts(file_header->name);
7}
diff --git a/archival/libunarchive/header_skip.c b/archival/libunarchive/header_skip.c
new file mode 100644
index 000000000..4430178f8
--- /dev/null
+++ b/archival/libunarchive/header_skip.c
@@ -0,0 +1,7 @@
1#include <stdio.h>
2#include "unarchive.h"
3
4extern void header_skip(const file_header_t *file_header)
5{
6 return;
7}
diff --git a/archival/libunarchive/header_verbose_list.c b/archival/libunarchive/header_verbose_list.c
new file mode 100644
index 000000000..ff7b3bca2
--- /dev/null
+++ b/archival/libunarchive/header_verbose_list.c
@@ -0,0 +1,29 @@
1#include <stdio.h>
2#include <string.h>
3#include <time.h>
4#include "libbb.h"
5#include "unarchive.h"
6
7extern void header_verbose_list(const file_header_t *file_header)
8{
9 struct tm *mtime = localtime(&file_header->mtime);
10
11 printf("%s %d/%d%10u %4u-%02u-%02u %02u:%02u:%02u %s",
12 mode_string(file_header->mode),
13 file_header->uid,
14 file_header->gid,
15 (unsigned int) file_header->size,
16 1900 + mtime->tm_year,
17 1 + mtime->tm_mon,
18 mtime->tm_mday,
19 mtime->tm_hour,
20 mtime->tm_min,
21 mtime->tm_sec,
22 file_header->name);
23
24 if (file_header->link_name) {
25 printf(" -> %s", file_header->link_name);
26 }
27 /* putchar isnt used anywhere else i dont think */
28 puts("");
29}
diff --git a/archival/libunarchive/init_handle.c b/archival/libunarchive/init_handle.c
new file mode 100644
index 000000000..12d9e7183
--- /dev/null
+++ b/archival/libunarchive/init_handle.c
@@ -0,0 +1,18 @@
1#include <string.h>
2#include "libbb.h"
3#include "unarchive.h"
4
5archive_handle_t *init_handle(void)
6{
7 archive_handle_t *archive_handle;
8
9 /* Initialise default values */
10 archive_handle = xmalloc(sizeof(archive_handle_t));
11 memset(archive_handle, 0, sizeof(archive_handle_t));
12 archive_handle->file_header = xmalloc(sizeof(file_header_t));
13 archive_handle->action_header = header_skip;
14 archive_handle->action_data = data_skip;
15 archive_handle->filter = filter_accept_all;
16
17 return(archive_handle);
18}
diff --git a/archival/libunarchive/seek_sub_file.c b/archival/libunarchive/seek_sub_file.c
index 7523a52ab..733bb36a9 100644
--- a/archival/libunarchive/seek_sub_file.c
+++ b/archival/libunarchive/seek_sub_file.c
@@ -14,23 +14,19 @@
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */ 15 */
16 16
17#include <stdio.h> 17#include <sys/types.h>
18#include <errno.h> 18#include <errno.h>
19#include <stdlib.h>
20#include <unistd.h> 19#include <unistd.h>
20#include <stdlib.h>
21#include "unarchive.h"
22#include "libbb.h"
21 23
22off_t archive_offset; 24extern void seek_sub_file(const int src_fd, const unsigned int amount)
23
24void seek_sub_file(FILE *src_stream, const int count)
25{ 25{
26 /* Try to fseek as faster */ 26 if ((lseek(src_fd, amount, SEEK_CUR) == -1) && (errno == ESPIPE)) {
27 archive_offset += count; 27 unsigned int i;
28 if (fseek(src_stream, count, SEEK_CUR) != 0 && errno == ESPIPE) { 28 for (i = 0; i < amount; i++) {
29 int i; 29 xread_char(src_fd);
30 for (i = 0; i < count; i++) {
31 fgetc(src_stream);
32 } 30 }
33 } 31 }
34 return;
35} 32}
36
diff --git a/archival/libunarchive/unpack_ar_archive.c b/archival/libunarchive/unpack_ar_archive.c
new file mode 100644
index 000000000..923b8a068
--- /dev/null
+++ b/archival/libunarchive/unpack_ar_archive.c
@@ -0,0 +1,34 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16#include <fcntl.h>
17#include <stdlib.h>
18#include <string.h>
19#include <getopt.h>
20#include "unarchive.h"
21#include "busybox.h"
22
23extern void unpack_ar_archive(archive_handle_t *ar_archive)
24{
25 char magic[7];
26
27 xread_all(ar_archive->src_fd, magic, 7);
28 if (strncmp(magic, "!<arch>", 7) != 0) {
29 error_msg_and_die("Invalid ar magic");
30 }
31 ar_archive->offset += 7;
32
33 while (get_header_ar(ar_archive) == EXIT_SUCCESS);
34}
diff --git a/archival/libunarchive/unzip.c b/archival/libunarchive/unzip.c
index d84067068..20bf88f55 100644
--- a/archival/libunarchive/unzip.c
+++ b/archival/libunarchive/unzip.c
@@ -65,114 +65,126 @@ static char *license_msg[] = {
65#include <signal.h> 65#include <signal.h>
66#include <stdlib.h> 66#include <stdlib.h>
67#include <string.h> 67#include <string.h>
68#include <unistd.h>
69#include <fcntl.h>
68#include "config.h" 70#include "config.h"
69#include "libbb.h" 71#include "busybox.h"
72#include "unarchive.h"
70 73
71#ifdef CONFIG_FEATURE_UNCOMPRESS 74typedef struct huft_s {
72int uncompress(FILE * in, FILE * out); 75 unsigned char e; /* number of extra bits or operation */
73#endif 76 unsigned char b; /* number of bits in this code or subcode */
74 77 union {
75static FILE *in_file, *out_file; 78 unsigned short n; /* literal, length base, or distance base */
79 struct huft_s *t; /* pointer to next level of table */
80 } v;
81} huft_t;
76 82
77/* these are freed by gz_close */ 83static int gunzip_src_fd;
78static unsigned char *window; 84static int gunzip_dst_fd;
79static unsigned long *crc_table; 85unsigned int gunzip_bytes_out; /* number of output bytes */
86static unsigned int gunzip_outbuf_count; /* bytes in output buffer */
80 87
81static unsigned long crc; /* shift register contents */ 88/* This is used to sanify any unused bits from the bitbuffer
89 * so they arent skipped when reading trailers (trailing headers) */
90unsigned char gunzip_in_buffer_count;
91unsigned char *gunzip_in_buffer;
82 92
83/* Return codes from gzip */ 93/* gunzip_window size--must be a power of two, and
84#define ERROR 1 94 * at least 32K for zip's deflate method */
95static const int gunzip_wsize = 0x8000;
85 96
86/* 97static unsigned char *gunzip_window;
87 * window size--must be a power of two, and 98static unsigned int *gunzip_crc_table;
88 * at least 32K for zip's deflate method 99unsigned int gunzip_crc;
89 */
90#define WSIZE 0x8000
91 100
92/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ 101/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
93#define BMAX 16 /* maximum bit length of any code (16 for explode) */ 102#define BMAX 16 /* maximum bit length of any code (16 for explode) */
94#define N_MAX 288 /* maximum number of codes in any set */ 103#define N_MAX 288 /* maximum number of codes in any set */
95 104
96static long bytes_out; /* number of output bytes */ 105static unsigned int gunzip_hufts; /* track memory usage */
97static unsigned long outcnt; /* bytes in output buffer */ 106static unsigned int gunzip_bb; /* bit buffer */
98 107static unsigned char gunzip_bk; /* bits in bit buffer */
99static unsigned hufts; /* track memory usage */
100static unsigned long bb; /* bit buffer */
101static unsigned bk; /* bits in bit buffer */
102
103typedef struct huft_s {
104 unsigned char e; /* number of extra bits or operation */
105 unsigned char b; /* number of bits in this code or subcode */
106 union {
107 unsigned short n; /* literal, length base, or distance base */
108 struct huft_s *t; /* pointer to next level of table */
109 } v;
110} huft_t;
111 108
112static const unsigned short mask_bits[] = { 109static const unsigned short mask_bits[] = {
113 0x0000, 110 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
114 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
115 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 111 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
116}; 112};
117 113
118/* static int error_number = 0; */ 114/* Copy lengths for literal codes 257..285 */
119/* ======================================================================== 115static const unsigned short cplens[] = {
120 * Signal and error handler. 116 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
121 */ 117 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
118};
119
120/* note: see note #13 above about the 258 in this list. */
121/* Extra bits for literal codes 257..285 */
122static const unsigned char cplext[] = {
123 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
124 5, 5, 5, 0, 99, 99
125}; /* 99==invalid */
126
127/* Copy offsets for distance codes 0..29 */
128static const unsigned short cpdist[] = {
129 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
130 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
131};
132
133/* Extra bits for distance codes */
134static const unsigned char cpdext[] = {
135 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
136 11, 11, 12, 12, 13, 13
137};
138
139/* Tables for deflate from PKZIP's appnote.txt. */
140/* Order of the bit length code lengths */
141static const unsigned char border[] = {
142 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
143};
144
145static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
146{
147 while (*current < required) {
148 bitbuffer |= ((unsigned int) xread_char(gunzip_src_fd)) << *current;
149 *current += 8;
150 }
151
152 return(bitbuffer);
153}
122 154
123static void abort_gzip(void) 155static void abort_gzip(void)
124{ 156{
125 error_msg("gzip aborted\n"); 157 error_msg("gzip aborted\n");
126 exit(ERROR); 158 exit(-1);
127} 159}
128 160
129static void make_crc_table(void) 161static void make_gunzip_crc_table(void)
130{ 162{
131 const unsigned long poly = 0xedb88320; /* polynomial exclusive-or pattern */ 163 const unsigned int poly = 0xedb88320; /* polynomial exclusive-or pattern */
132 unsigned short i; /* counter for all possible eight bit values */ 164 unsigned short i; /* counter for all possible eight bit values */
133 165
134 /* initial shift register value */ 166 /* initial shift register value */
135 crc = 0xffffffffL; 167 gunzip_crc = 0xffffffffL;
136 crc_table = (unsigned long *) malloc(256 * sizeof(unsigned long)); 168 gunzip_crc_table = (unsigned int *) malloc(256 * sizeof(unsigned int));
137 169
138 /* Compute and print table of CRC's, five per line */ 170 /* Compute and print table of CRC's, five per line */
139 for (i = 0; i < 256; i++) { 171 for (i = 0; i < 256; i++) {
140 unsigned long table_entry; /* crc shift register */ 172 unsigned int table_entry; /* crc shift register */
141 char k; /* byte being shifted into crc apparatus */ 173 unsigned char k; /* byte being shifted into crc apparatus */
142 174
143 table_entry = i; 175 table_entry = i;
144 /* The idea to initialize the register with the byte instead of 176 /* The idea to initialize the register with the byte instead of
145 * zero was stolen from Haruhiko Okumura's ar002 177 * zero was stolen from Haruhiko Okumura's ar002
146 */ 178 */
147 for (k = 8; k; k--) { 179 for (k = 8; k; k--) {
148 table_entry = 180 if (table_entry & 1) {
149 table_entry & 1 ? (table_entry >> 1) ^ poly : table_entry >> 181 table_entry = (table_entry >> 1) ^ poly;
150 1; 182 } else {
151 } 183 table_entry >>= 1;
152 crc_table[i] = table_entry;
153 } 184 }
154}
155
156/* ===========================================================================
157 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
158 * (Used for the decompressed data only.)
159 */
160static void flush_window(void)
161{
162 int n;
163
164 if (outcnt == 0)
165 return;
166
167 for (n = 0; n < outcnt; n++) {
168 crc = crc_table[((int) crc ^ (window[n])) & 0xff] ^ (crc >> 8);
169 } 185 }
170 186 gunzip_crc_table[i] = table_entry;
171 if (fwrite(window, 1, outcnt, out_file) != outcnt) {
172 error_msg_and_die("Couldnt write");
173 } 187 }
174 bytes_out += (unsigned long) outcnt;
175 outcnt = 0;
176} 188}
177 189
178/* 190/*
@@ -183,7 +195,8 @@ static void flush_window(void)
183 */ 195 */
184static int huft_free(huft_t * t) 196static int huft_free(huft_t * t)
185{ 197{
186 huft_t *p, *q; 198 huft_t *p;
199 huft_t *q;
187 200
188 /* Go through linked list, freeing from the malloced (t[-1]) address. */ 201 /* Go through linked list, freeing from the malloced (t[-1]) address. */
189 p = t; 202 p = t;
@@ -195,8 +208,6 @@ static int huft_free(huft_t * t)
195 return 0; 208 return 0;
196} 209}
197 210
198typedef unsigned char extra_bits_t;
199
200/* Given a list of code lengths and a maximum table size, make a set of 211/* Given a list of code lengths and a maximum table size, make a set of
201 * tables to decode that set of codes. Return zero on success, one if 212 * tables to decode that set of codes. Return zero on success, one if
202 * the given code set is incomplete (the tables are still built in this 213 * the given code set is incomplete (the tables are still built in this
@@ -213,7 +224,7 @@ typedef unsigned char extra_bits_t;
213 */ 224 */
214static int huft_build(unsigned int *b, const unsigned int n, 225static int huft_build(unsigned int *b, const unsigned int n,
215 const unsigned int s, const unsigned short *d, 226 const unsigned int s, const unsigned short *d,
216 const extra_bits_t * e, huft_t ** t, int *m) 227 const unsigned char *e, huft_t ** t, int *m)
217{ 228{
218 unsigned a; /* counter for codes of length k */ 229 unsigned a; /* counter for codes of length k */
219 unsigned c[BMAX + 1]; /* bit length count table */ 230 unsigned c[BMAX + 1]; /* bit length count table */
@@ -251,26 +262,35 @@ static int huft_build(unsigned int *b, const unsigned int n,
251 262
252 /* Find minimum and maximum length, bound *m by those */ 263 /* Find minimum and maximum length, bound *m by those */
253 l = *m; 264 l = *m;
254 for (j = 1; j <= BMAX; j++) 265 for (j = 1; j <= BMAX; j++) {
255 if (c[j]) 266 if (c[j]) {
256 break; 267 break;
268 }
269 }
257 k = j; /* minimum code length */ 270 k = j; /* minimum code length */
258 if ((unsigned) l < j) 271 if ((unsigned) l < j) {
259 l = j; 272 l = j;
260 for (i = BMAX; i; i--) 273 }
261 if (c[i]) 274 for (i = BMAX; i; i--) {
275 if (c[i]) {
262 break; 276 break;
277 }
278 }
263 g = i; /* maximum code length */ 279 g = i; /* maximum code length */
264 if ((unsigned) l > i) 280 if ((unsigned) l > i) {
265 l = i; 281 l = i;
282 }
266 *m = l; 283 *m = l;
267 284
268 /* Adjust last length count to fill out codes, if needed */ 285 /* Adjust last length count to fill out codes, if needed */
269 for (y = 1 << j; j < i; j++, y <<= 1) 286 for (y = 1 << j; j < i; j++, y <<= 1) {
270 if ((y -= c[j]) < 0) 287 if ((y -= c[j]) < 0) {
271 return 2; /* bad input: more codes than bits */ 288 return 2; /* bad input: more codes than bits */
272 if ((y -= c[i]) < 0) 289 }
290 }
291 if ((y -= c[i]) < 0) {
273 return 2; 292 return 2;
293 }
274 c[i] += y; 294 c[i] += y;
275 295
276 /* Generate starting offsets into the value table for each length */ 296 /* Generate starting offsets into the value table for each length */
@@ -285,8 +305,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
285 p = b; 305 p = b;
286 i = 0; 306 i = 0;
287 do { 307 do {
288 if ((j = *p++) != 0) 308 if ((j = *p++) != 0) {
289 v[x[j]++] = i; 309 v[x[j]++] = i;
310 }
290 } while (++i < n); 311 } while (++i < n);
291 312
292 /* Generate the Huffman codes and for each, make the table entries */ 313 /* Generate the Huffman codes and for each, make the table entries */
@@ -314,8 +335,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
314 f -= a + 1; /* deduct codes from patterns left */ 335 f -= a + 1; /* deduct codes from patterns left */
315 xp = c + k; 336 xp = c + k;
316 while (++j < z) { /* try smaller tables up to z bits */ 337 while (++j < z) { /* try smaller tables up to z bits */
317 if ((f <<= 1) <= *++xp) 338 if ((f <<= 1) <= *++xp) {
318 break; /* enough codes to use up j bits */ 339 break; /* enough codes to use up j bits */
340 }
319 f -= *xp; /* else deduct codes from patterns */ 341 f -= *xp; /* else deduct codes from patterns */
320 } 342 }
321 } 343 }
@@ -324,7 +346,7 @@ static int huft_build(unsigned int *b, const unsigned int n,
324 /* allocate and link in new table */ 346 /* allocate and link in new table */
325 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); 347 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t));
326 348
327 hufts += z + 1; /* track memory usage */ 349 gunzip_hufts += z + 1; /* track memory usage */
328 *t = q + 1; /* link to list for huft_free() */ 350 *t = q + 1; /* link to list for huft_free() */
329 *(t = &(q->v.t)) = NULL; 351 *(t = &(q->v.t)) = NULL;
330 u[h] = ++q; /* table starts after link */ 352 u[h] = ++q; /* table starts after link */
@@ -342,9 +364,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
342 364
343 /* set up table entry in r */ 365 /* set up table entry in r */
344 r.b = (unsigned char) (k - w); 366 r.b = (unsigned char) (k - w);
345 if (p >= v + n) 367 if (p >= v + n) {
346 r.e = 99; /* out of values--invalid code */ 368 r.e = 99; /* out of values--invalid code */
347 else if (*p < s) { 369 } else if (*p < s) {
348 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */ 370 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
349 r.v.n = (unsigned short) (*p); /* simple code is just the value */ 371 r.v.n = (unsigned short) (*p); /* simple code is just the value */
350 p++; /* one compiler does not like *p++ */ 372 p++; /* one compiler does not like *p++ */
@@ -355,12 +377,14 @@ static int huft_build(unsigned int *b, const unsigned int n,
355 377
356 /* fill code-like entries with r */ 378 /* fill code-like entries with r */
357 f = 1 << (k - w); 379 f = 1 << (k - w);
358 for (j = i >> w; j < z; j += f) 380 for (j = i >> w; j < z; j += f) {
359 q[j] = r; 381 q[j] = r;
382 }
360 383
361 /* backwards increment the k-bit code i */ 384 /* backwards increment the k-bit code i */
362 for (j = 1 << (k - 1); i & j; j >>= 1) 385 for (j = 1 << (k - 1); i & j; j >>= 1) {
363 i ^= j; 386 i ^= j;
387 }
364 i ^= j; 388 i ^= j;
365 389
366 /* backup over finished tables */ 390 /* backup over finished tables */
@@ -374,6 +398,25 @@ static int huft_build(unsigned int *b, const unsigned int n,
374 return y != 0 && g != 1; 398 return y != 0 && g != 1;
375} 399}
376 400
401/* ===========================================================================
402 * Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out.
403 * (Used for the decompressed data only.)
404 */
405static void flush_gunzip_window(void)
406{
407 int n;
408
409 for (n = 0; n < gunzip_outbuf_count; n++) {
410 gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
411 }
412
413 if (write(gunzip_dst_fd, gunzip_window, gunzip_outbuf_count) != gunzip_outbuf_count) {
414 error_msg_and_die("Couldnt write");
415 }
416 gunzip_bytes_out += gunzip_outbuf_count;
417 gunzip_outbuf_count = 0;
418}
419
377/* 420/*
378 * inflate (decompress) the codes in a deflated (compressed) block. 421 * inflate (decompress) the codes in a deflated (compressed) block.
379 * Return an error code or zero if it all goes ok. 422 * Return an error code or zero if it all goes ok.
@@ -381,32 +424,26 @@ static int huft_build(unsigned int *b, const unsigned int n,
381 * tl, td: literal/length and distance decoder tables 424 * tl, td: literal/length and distance decoder tables
382 * bl, bd: number of bits decoded by tl[] and td[] 425 * bl, bd: number of bits decoded by tl[] and td[]
383 */ 426 */
384static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd) 427static int inflate_codes(huft_t * tl, huft_t * td, const unsigned int bl, const unsigned int bd)
385{ 428{
386 register unsigned long e; /* table entry flag/number of extra bits */ 429 unsigned int e; /* table entry flag/number of extra bits */
387 unsigned long n, d; /* length and index for copy */ 430 unsigned int n, d; /* length and index for copy */
388 unsigned long w; /* current window position */ 431 unsigned int w; /* current gunzip_window position */
389 huft_t *t; /* pointer to table entry */ 432 huft_t *t; /* pointer to table entry */
390 unsigned ml, md; /* masks for bl and bd bits */ 433 unsigned int ml, md; /* masks for bl and bd bits */
391 register unsigned long b; /* bit buffer */ 434 unsigned int b; /* bit buffer */
392 register unsigned k; /* number of bits in bit buffer */ 435 unsigned int k; /* number of bits in bit buffer */
393 register int input_char;
394 436
395 /* make local copies of globals */ 437 /* make local copies of globals */
396 b = bb; /* initialize bit buffer */ 438 b = gunzip_bb; /* initialize bit buffer */
397 k = bk; 439 k = gunzip_bk;
398 w = outcnt; /* initialize window position */ 440 w = gunzip_outbuf_count; /* initialize gunzip_window position */
399 441
400 /* inflate the coded data */ 442 /* inflate the coded data */
401 ml = mask_bits[bl]; /* precompute masks for speed */ 443 ml = mask_bits[bl]; /* precompute masks for speed */
402 md = mask_bits[bd]; 444 md = mask_bits[bd];
403 for (;;) { /* do until end of block */ 445 while (1) { /* do until end of block */
404 while (k < (unsigned) bl) { 446 b = fill_bitbuffer(b, &k, bl);
405 input_char = fgetc(in_file);
406 if (input_char == EOF) return 1;
407 b |= ((unsigned long)input_char) << k;
408 k += 8;
409 }
410 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) 447 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
411 do { 448 do {
412 if (e == 99) { 449 if (e == 99) {
@@ -415,20 +452,16 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
415 b >>= t->b; 452 b >>= t->b;
416 k -= t->b; 453 k -= t->b;
417 e -= 16; 454 e -= 16;
418 while (k < e) { 455 b = fill_bitbuffer(b, &k, e);
419 input_char = fgetc(in_file);
420 if (input_char == EOF) return 1;
421 b |= ((unsigned long)input_char) << k;
422 k += 8;
423 }
424 } while ((e = 456 } while ((e =
425 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); 457 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
426 b >>= t->b; 458 b >>= t->b;
427 k -= t->b; 459 k -= t->b;
428 if (e == 16) { /* then it's a literal */ 460 if (e == 16) { /* then it's a literal */
429 window[w++] = (unsigned char) t->v.n; 461 gunzip_window[w++] = (unsigned char) t->v.n;
430 if (w == WSIZE) { 462 if (w == gunzip_wsize) {
431 outcnt = (w), flush_window(); 463 gunzip_outbuf_count = (w);
464 flush_gunzip_window();
432 w = 0; 465 w = 0;
433 } 466 }
434 } else { /* it's an EOB or a length */ 467 } else { /* it's an EOB or a length */
@@ -439,24 +472,13 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
439 } 472 }
440 473
441 /* get length of block to copy */ 474 /* get length of block to copy */
442 while (k < e) { 475 b = fill_bitbuffer(b, &k, e);
443 input_char = fgetc(in_file);
444 if (input_char == EOF) return 1;
445 b |= ((unsigned long)input_char) << k;
446 k += 8;
447 }
448 n = t->v.n + ((unsigned) b & mask_bits[e]); 476 n = t->v.n + ((unsigned) b & mask_bits[e]);
449 b >>= e; 477 b >>= e;
450 k -= e; 478 k -= e;
451 479
452 /* decode distance of block to copy */ 480 /* decode distance of block to copy */
453 while (k < (unsigned) bd) { 481 b = fill_bitbuffer(b, &k, bd);
454 input_char = fgetc(in_file);
455 if (input_char == EOF) return 1;
456 b |= ((unsigned long)input_char) << k;
457 k += 8;
458 }
459
460 if ((e = (t = td + ((unsigned) b & md))->e) > 16) 482 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
461 do { 483 do {
462 if (e == 99) 484 if (e == 99)
@@ -464,23 +486,13 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
464 b >>= t->b; 486 b >>= t->b;
465 k -= t->b; 487 k -= t->b;
466 e -= 16; 488 e -= 16;
467 while (k < e) { 489 b = fill_bitbuffer(b, &k, e);
468 input_char = fgetc(in_file);
469 if (input_char == EOF) return 1;
470 b |= ((unsigned long)input_char) << k;
471 k += 8;
472 }
473 } while ((e = 490 } while ((e =
474 (t = 491 (t =
475 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); 492 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
476 b >>= t->b; 493 b >>= t->b;
477 k -= t->b; 494 k -= t->b;
478 while (k < e) { 495 b = fill_bitbuffer(b, &k, e);
479 input_char = fgetc(in_file);
480 if (input_char == EOF) return 1;
481 b |= ((unsigned long)input_char) << k;
482 k += 8;
483 }
484 d = w - t->v.n - ((unsigned) b & mask_bits[e]); 496 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
485 b >>= e; 497 b >>= e;
486 k -= e; 498 k -= e;
@@ -489,60 +501,38 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
489 do { 501 do {
490 n -= (e = 502 n -= (e =
491 (e = 503 (e =
492 WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n : e); 504 gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
493#if !defined(NOMEMCPY) && !defined(DEBUG) 505 /* copy to new buffer to prevent possible overwrite */
494 if (w - d >= e) { /* (this test assumes unsigned comparison) */ 506 if (w - d >= e) { /* (this test assumes unsigned comparison) */
495 memcpy(window + w, window + d, e); 507 memcpy(gunzip_window + w, gunzip_window + d, e);
496 w += e; 508 w += e;
497 d += e; 509 d += e;
498 } else /* do it slow to avoid memcpy() overlap */ 510 } else {
499#endif /* !NOMEMCPY */ 511 /* do it slow to avoid memcpy() overlap */
512 /* !NOMEMCPY */
500 do { 513 do {
501 window[w++] = window[d++]; 514 gunzip_window[w++] = gunzip_window[d++];
502 } while (--e); 515 } while (--e);
503 if (w == WSIZE) { 516 }
504 outcnt = (w), flush_window(); 517 if (w == gunzip_wsize) {
518 gunzip_outbuf_count = (w);
519 flush_gunzip_window();
505 w = 0; 520 w = 0;
506 } 521 }
522
507 } while (n); 523 } while (n);
508 } 524 }
509 } 525 }
510 526
511 /* restore the globals from the locals */ 527 /* restore the globals from the locals */
512 outcnt = w; /* restore global window pointer */ 528 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
513 bb = b; /* restore global bit buffer */ 529 gunzip_bb = b; /* restore global bit buffer */
514 bk = k; 530 gunzip_bk = k;
515 531
516 /* done */ 532 /* done */
517 return 0; 533 return 0;
518} 534}
519 535
520static const unsigned short cplens[] = { /* Copy lengths for literal codes 257..285 */
521 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
522 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
523};
524
525/* note: see note #13 above about the 258 in this list. */
526static const extra_bits_t cplext[] = { /* Extra bits for literal codes 257..285 */
527 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
528 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
529}; /* 99==invalid */
530static const unsigned short cpdist[] = { /* Copy offsets for distance codes 0..29 */
531 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
532 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
533 8193, 12289, 16385, 24577
534};
535static const extra_bits_t cpdext[] = { /* Extra bits for distance codes */
536 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
537 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
538 12, 12, 13, 13
539};
540
541/* Tables for deflate from PKZIP's appnote.txt. */
542static const extra_bits_t border[] = { /* Order of the bit length code lengths */
543 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
544};
545
546/* 536/*
547 * decompress an inflated block 537 * decompress an inflated block
548 * e: last block flag 538 * e: last block flag
@@ -552,53 +542,43 @@ static const extra_bits_t border[] = { /* Order of the bit length code lengths *
552static int inflate_block(int *e) 542static int inflate_block(int *e)
553{ 543{
554 unsigned t; /* block type */ 544 unsigned t; /* block type */
555 register unsigned long b; /* bit buffer */ 545 register unsigned int b; /* bit buffer */
556 register unsigned k; /* number of bits in bit buffer */ 546 unsigned int k; /* number of bits in bit buffer */
557 int input_char;
558 547
559 /* make local bit buffer */ 548 /* make local bit buffer */
560 b = bb; 549
561 k = bk; 550 b = gunzip_bb;
551 k = gunzip_bk;
562 552
563 /* read in last block bit */ 553 /* read in last block bit */
564 while (k < 1) { 554 b = fill_bitbuffer(b, &k, 1);
565 input_char = fgetc(in_file);
566 if (input_char == EOF) return 1;
567 b |= ((unsigned long)input_char) << k;
568 k += 8;
569 }
570 *e = (int) b & 1; 555 *e = (int) b & 1;
571 b >>= 1; 556 b >>= 1;
572 k -= 1; 557 k -= 1;
573 558
574 /* read in block type */ 559 /* read in block type */
575 while (k < 2) { 560 b = fill_bitbuffer(b, &k, 2);
576 input_char = fgetc(in_file);
577 if (input_char == EOF) return 1;
578 b |= ((unsigned long)input_char) << k;
579 k += 8;
580 }
581 t = (unsigned) b & 3; 561 t = (unsigned) b & 3;
582 b >>= 2; 562 b >>= 2;
583 k -= 2; 563 k -= 2;
584 564
585 /* restore the global bit buffer */ 565 /* restore the global bit buffer */
586 bb = b; 566 gunzip_bb = b;
587 bk = k; 567 gunzip_bk = k;
588 568
589 /* inflate that block type */ 569 /* inflate that block type */
590 switch (t) { 570 switch (t) {
591 case 0: /* Inflate stored */ 571 case 0: /* Inflate stored */
592 { 572 {
593 unsigned long n; /* number of bytes in block */ 573 unsigned int n; /* number of bytes in block */
594 unsigned long w; /* current window position */ 574 unsigned int w; /* current gunzip_window position */
595 register unsigned long b_stored; /* bit buffer */ 575 unsigned int b_stored; /* bit buffer */
596 register unsigned long k_stored; /* number of bits in bit buffer */ 576 unsigned int k_stored; /* number of bits in bit buffer */
597 577
598 /* make local copies of globals */ 578 /* make local copies of globals */
599 b_stored = bb; /* initialize bit buffer */ 579 b_stored = gunzip_bb; /* initialize bit buffer */
600 k_stored = bk; 580 k_stored = gunzip_bk;
601 w = outcnt; /* initialize window position */ 581 w = gunzip_outbuf_count; /* initialize gunzip_window position */
602 582
603 /* go to byte boundary */ 583 /* go to byte boundary */
604 n = k_stored & 7; 584 n = k_stored & 7;
@@ -606,21 +586,12 @@ static int inflate_block(int *e)
606 k_stored -= n; 586 k_stored -= n;
607 587
608 /* get the length and its complement */ 588 /* get the length and its complement */
609 while (k_stored < 16) { 589 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
610 input_char = fgetc(in_file);
611 if (input_char == EOF) return 1;
612 b_stored |= ((unsigned long)input_char) << k_stored;
613 k_stored += 8;
614 }
615 n = ((unsigned) b_stored & 0xffff); 590 n = ((unsigned) b_stored & 0xffff);
616 b_stored >>= 16; 591 b_stored >>= 16;
617 k_stored -= 16; 592 k_stored -= 16;
618 while (k_stored < 16) { 593
619 input_char = fgetc(in_file); 594 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
620 if (input_char == EOF) return 1;
621 b_stored |= ((unsigned long)input_char) << k_stored;
622 k_stored += 8;
623 }
624 if (n != (unsigned) ((~b_stored) & 0xffff)) { 595 if (n != (unsigned) ((~b_stored) & 0xffff)) {
625 return 1; /* error in compressed data */ 596 return 1; /* error in compressed data */
626 } 597 }
@@ -629,15 +600,11 @@ static int inflate_block(int *e)
629 600
630 /* read and output the compressed data */ 601 /* read and output the compressed data */
631 while (n--) { 602 while (n--) {
632 while (k_stored < 8) { 603 b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
633 input_char = fgetc(in_file); 604 gunzip_window[w++] = (unsigned char) b_stored;
634 if (input_char == EOF) return 1; 605 if (w == (unsigned int) gunzip_wsize) {
635 b_stored |= ((unsigned long)input_char) << k_stored; 606 gunzip_outbuf_count = (w);
636 k_stored += 8; 607 flush_gunzip_window();
637 }
638 window[w++] = (unsigned char) b_stored;
639 if (w == (unsigned long) WSIZE) {
640 outcnt = (w), flush_window();
641 w = 0; 608 w = 0;
642 } 609 }
643 b_stored >>= 8; 610 b_stored >>= 8;
@@ -645,9 +612,9 @@ static int inflate_block(int *e)
645 } 612 }
646 613
647 /* restore the globals from the locals */ 614 /* restore the globals from the locals */
648 outcnt = w; /* restore global window pointer */ 615 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
649 bb = b_stored; /* restore global bit buffer */ 616 gunzip_bb = b_stored; /* restore global bit buffer */
650 bk = k_stored; 617 gunzip_bk = k_stored;
651 return 0; 618 return 0;
652 } 619 }
653 case 1: /* Inflate fixed 620 case 1: /* Inflate fixed
@@ -659,8 +626,8 @@ static int inflate_block(int *e)
659 int i; /* temporary variable */ 626 int i; /* temporary variable */
660 huft_t *tl; /* literal/length code table */ 627 huft_t *tl; /* literal/length code table */
661 huft_t *td; /* distance code table */ 628 huft_t *td; /* distance code table */
662 int bl; /* lookup bits for tl */ 629 unsigned int bl; /* lookup bits for tl */
663 int bd; /* lookup bits for td */ 630 unsigned int bd; /* lookup bits for td */
664 unsigned int l[288]; /* length list for huft_build */ 631 unsigned int l[288]; /* length list for huft_build */
665 632
666 /* set up literal table */ 633 /* set up literal table */
@@ -692,8 +659,9 @@ static int inflate_block(int *e)
692 } 659 }
693 660
694 /* decompress until an end-of-block code */ 661 /* decompress until an end-of-block code */
695 if (inflate_codes(tl, td, bl, bd)) 662 if (inflate_codes(tl, td, bl, bd)) {
696 return 1; 663 return 1;
664 }
697 665
698 /* free the decoding tables, return */ 666 /* free the decoding tables, return */
699 huft_free(tl); 667 huft_free(tl);
@@ -705,53 +673,41 @@ static int inflate_block(int *e)
705 const int dbits = 6; /* bits in base distance lookup table */ 673 const int dbits = 6; /* bits in base distance lookup table */
706 const int lbits = 9; /* bits in base literal/length lookup table */ 674 const int lbits = 9; /* bits in base literal/length lookup table */
707 675
708 int i; /* temporary variables */
709 unsigned j;
710 unsigned l; /* last length */
711 unsigned m; /* mask for bit lengths table */
712 unsigned n; /* number of lengths to get */
713 huft_t *tl; /* literal/length code table */ 676 huft_t *tl; /* literal/length code table */
714 huft_t *td; /* distance code table */ 677 huft_t *td; /* distance code table */
715 int bl; /* lookup bits for tl */ 678 unsigned int i; /* temporary variables */
716 int bd; /* lookup bits for td */ 679 unsigned int j;
717 unsigned nb; /* number of bit length codes */ 680 unsigned int l; /* last length */
718 unsigned nl; /* number of literal/length codes */ 681 unsigned int m; /* mask for bit lengths table */
719 unsigned nd; /* number of distance codes */ 682 unsigned int n; /* number of lengths to get */
720 683 unsigned int bl; /* lookup bits for tl */
721 unsigned ll[286 + 30]; /* literal/length and distance code lengths */ 684 unsigned int bd; /* lookup bits for td */
722 register unsigned long b_dynamic; /* bit buffer */ 685 unsigned int nb; /* number of bit length codes */
723 register unsigned k_dynamic; /* number of bits in bit buffer */ 686 unsigned int nl; /* number of literal/length codes */
687 unsigned int nd; /* number of distance codes */
688
689 unsigned int ll[286 + 30]; /* literal/length and distance code lengths */
690 unsigned int b_dynamic; /* bit buffer */
691 unsigned int k_dynamic; /* number of bits in bit buffer */
724 692
725 /* make local bit buffer */ 693 /* make local bit buffer */
726 b_dynamic = bb; 694 b_dynamic = gunzip_bb;
727 k_dynamic = bk; 695 k_dynamic = gunzip_bk;
728 696
729 /* read in table lengths */ 697 /* read in table lengths */
730 while (k_dynamic < 5) { 698 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
731 input_char = fgetc(in_file); 699 nl = 257 + ((unsigned int) b_dynamic & 0x1f); /* number of literal/length codes */
732 if (input_char == EOF) return 1; 700
733 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
734 k_dynamic += 8;
735 }
736 nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */
737 b_dynamic >>= 5; 701 b_dynamic >>= 5;
738 k_dynamic -= 5; 702 k_dynamic -= 5;
739 while (k_dynamic < 5) { 703 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
740 input_char = fgetc(in_file); 704 nd = 1 + ((unsigned int) b_dynamic & 0x1f); /* number of distance codes */
741 if (input_char == EOF) return 1; 705
742 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
743 k_dynamic += 8;
744 }
745 nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */
746 b_dynamic >>= 5; 706 b_dynamic >>= 5;
747 k_dynamic -= 5; 707 k_dynamic -= 5;
748 while (k_dynamic < 4) { 708 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 4);
749 input_char = fgetc(in_file); 709 nb = 4 + ((unsigned int) b_dynamic & 0xf); /* number of bit length codes */
750 if (input_char == EOF) return 1; 710
751 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
752 k_dynamic += 8;
753 }
754 nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */
755 b_dynamic >>= 4; 711 b_dynamic >>= 4;
756 k_dynamic -= 4; 712 k_dynamic -= 4;
757 if (nl > 286 || nd > 30) { 713 if (nl > 286 || nd > 30) {
@@ -760,13 +716,8 @@ static int inflate_block(int *e)
760 716
761 /* read in bit-length-code lengths */ 717 /* read in bit-length-code lengths */
762 for (j = 0; j < nb; j++) { 718 for (j = 0; j < nb; j++) {
763 while (k_dynamic < 3) { 719 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
764 input_char = fgetc(in_file); 720 ll[border[j]] = (unsigned int) b_dynamic & 7;
765 if (input_char == EOF) return 1;
766 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
767 k_dynamic += 8;
768 }
769 ll[border[j]] = (unsigned) b_dynamic & 7;
770 b_dynamic >>= 3; 721 b_dynamic >>= 3;
771 k_dynamic -= 3; 722 k_dynamic -= 3;
772 } 723 }
@@ -776,7 +727,8 @@ static int inflate_block(int *e)
776 727
777 /* build decoding table for trees--single level, 7 bit lookup */ 728 /* build decoding table for trees--single level, 7 bit lookup */
778 bl = 7; 729 bl = 7;
779 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) { 730 i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl);
731 if (i != 0) {
780 if (i == 1) { 732 if (i == 1) {
781 huft_free(tl); 733 huft_free(tl);
782 } 734 }
@@ -787,46 +739,31 @@ static int inflate_block(int *e)
787 n = nl + nd; 739 n = nl + nd;
788 m = mask_bits[bl]; 740 m = mask_bits[bl];
789 i = l = 0; 741 i = l = 0;
790 while ((unsigned) i < n) { 742 while ((unsigned int) i < n) {
791 while (k_dynamic < (unsigned) bl) { 743 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, (unsigned int)bl);
792 input_char = fgetc(in_file); 744 j = (td = tl + ((unsigned int) b_dynamic & m))->b;
793 if (input_char == EOF) return 1;
794 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
795 k_dynamic += 8;
796 }
797 j = (td = tl + ((unsigned) b_dynamic & m))->b;
798 b_dynamic >>= j; 745 b_dynamic >>= j;
799 k_dynamic -= j; 746 k_dynamic -= j;
800 j = td->v.n; 747 j = td->v.n;
801 if (j < 16) { /* length of code in bits (0..15) */ 748 if (j < 16) { /* length of code in bits (0..15) */
802 ll[i++] = l = j; /* save last length in l */ 749 ll[i++] = l = j; /* save last length in l */
803 } else if (j == 16) { /* repeat last length 3 to 6 times */ 750 } else if (j == 16) { /* repeat last length 3 to 6 times */
804 while (k_dynamic < 2) { 751 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 2);
805 input_char = fgetc(in_file); 752 j = 3 + ((unsigned int) b_dynamic & 3);
806 if (input_char == EOF) return 1;
807 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
808 k_dynamic += 8;
809 }
810 j = 3 + ((unsigned) b_dynamic & 3);
811 b_dynamic >>= 2; 753 b_dynamic >>= 2;
812 k_dynamic -= 2; 754 k_dynamic -= 2;
813 if ((unsigned) i + j > n) { 755 if ((unsigned int) i + j > n) {
814 return 1; 756 return 1;
815 } 757 }
816 while (j--) { 758 while (j--) {
817 ll[i++] = l; 759 ll[i++] = l;
818 } 760 }
819 } else if (j == 17) { /* 3 to 10 zero length codes */ 761 } else if (j == 17) { /* 3 to 10 zero length codes */
820 while (k_dynamic < 3) { 762 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
821 input_char = fgetc(in_file); 763 j = 3 + ((unsigned int) b_dynamic & 7);
822 if (input_char == EOF) return 1;
823 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
824 k_dynamic += 8;
825 }
826 j = 3 + ((unsigned) b_dynamic & 7);
827 b_dynamic >>= 3; 764 b_dynamic >>= 3;
828 k_dynamic -= 3; 765 k_dynamic -= 3;
829 if ((unsigned) i + j > n) { 766 if ((unsigned int) i + j > n) {
830 return 1; 767 return 1;
831 } 768 }
832 while (j--) { 769 while (j--) {
@@ -834,16 +771,11 @@ static int inflate_block(int *e)
834 } 771 }
835 l = 0; 772 l = 0;
836 } else { /* j == 18: 11 to 138 zero length codes */ 773 } else { /* j == 18: 11 to 138 zero length codes */
837 while (k_dynamic < 7) { 774 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 7);
838 input_char = fgetc(in_file); 775 j = 11 + ((unsigned int) b_dynamic & 0x7f);
839 if (input_char == EOF) return 1;
840 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
841 k_dynamic += 8;
842 }
843 j = 11 + ((unsigned) b_dynamic & 0x7f);
844 b_dynamic >>= 7; 776 b_dynamic >>= 7;
845 k_dynamic -= 7; 777 k_dynamic -= 7;
846 if ((unsigned) i + j > n) { 778 if ((unsigned int) i + j > n) {
847 return 1; 779 return 1;
848 } 780 }
849 while (j--) { 781 while (j--) {
@@ -857,22 +789,24 @@ static int inflate_block(int *e)
857 huft_free(tl); 789 huft_free(tl);
858 790
859 /* restore the global bit buffer */ 791 /* restore the global bit buffer */
860 bb = b_dynamic; 792 gunzip_bb = b_dynamic;
861 bk = k_dynamic; 793 gunzip_bk = k_dynamic;
862 794
863 /* build the decoding tables for literal/length and distance codes */ 795 /* build the decoding tables for literal/length and distance codes */
864 bl = lbits; 796 bl = lbits;
797
865 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) { 798 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
866 if (i == 1) { 799 if (i == 1) {
867 error_msg("Incomplete literal tree"); 800 error_msg_and_die("Incomplete literal tree");
868 huft_free(tl); 801 huft_free(tl);
869 } 802 }
870 return i; /* incomplete code set */ 803 return i; /* incomplete code set */
871 } 804 }
805
872 bd = dbits; 806 bd = dbits;
873 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) { 807 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
874 if (i == 1) { 808 if (i == 1) {
875 error_msg("incomplete distance tree"); 809 error_msg_and_die("incomplete distance tree");
876 huft_free(td); 810 huft_free(td);
877 } 811 }
878 huft_free(tl); 812 huft_free(tl);
@@ -880,8 +814,9 @@ static int inflate_block(int *e)
880 } 814 }
881 815
882 /* decompress until an end-of-block code */ 816 /* decompress until an end-of-block code */
883 if (inflate_codes(tl, td, bl, bd)) 817 if (inflate_codes(tl, td, bl, bd)) {
884 return 1; 818 return 1;
819 }
885 820
886 /* free the decoding tables, return */ 821 /* free the decoding tables, return */
887 huft_free(tl); 822 huft_free(tl);
@@ -890,6 +825,7 @@ static int inflate_block(int *e)
890 } 825 }
891 default: 826 default:
892 /* bad block type */ 827 /* bad block type */
828 error_msg("bad block type %d\n", t);
893 return 2; 829 return 2;
894 } 830 }
895} 831}
@@ -897,72 +833,24 @@ static int inflate_block(int *e)
897/* 833/*
898 * decompress an inflated entry 834 * decompress an inflated entry
899 * 835 *
900 * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr 836 * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr
901 */ 837 */
902extern int inflate(FILE * in, FILE * out) 838extern int inflate(int in, int out)
903{ 839{
840 typedef void (*sig_type) (int);
904 int e; /* last block flag */ 841 int e; /* last block flag */
905 int r; /* result code */ 842 int r; /* result code */
906 unsigned h = 0; /* maximum struct huft's malloc'ed */ 843 unsigned h = 0; /* maximum struct huft's malloc'ed */
907 844
908 /* initialize window, bit buffer */
909 outcnt = 0;
910 bk = 0;
911 bb = 0;
912
913 in_file = in;
914 out_file = out;
915
916 /* Allocate all global buffers (for DYN_ALLOC option) */ 845 /* Allocate all global buffers (for DYN_ALLOC option) */
917 window = xmalloc((size_t) (((2L * WSIZE) + 1L) * sizeof(unsigned char))); 846 gunzip_window = xmalloc(0x8000);
918 bytes_out = 0L; 847 gunzip_outbuf_count = 0;
848 gunzip_bytes_out = 0;
919 849
920 /* Create the crc table */ 850 gunzip_src_fd = in;
921 make_crc_table(); 851 gunzip_dst_fd = out;
922 852
923 /* decompress until the last block */ 853 gunzip_in_buffer = malloc(8);
924 do {
925 hufts = 0;
926 if ((r = inflate_block(&e)) != 0) {
927 return r;
928 }
929 if (hufts > h) {
930 h = hufts;
931 }
932 } while (!e);
933
934 /* Undo too much lookahead. The next read will be byte aligned so we
935 * can discard unused bits in the last meaningful byte.
936 */
937 while (bk >= 8) {
938 bk -= 8;
939 ungetc((bb << bk), in_file);
940 }
941
942 /* flush out window */
943 flush_window();
944 free(window);
945 free(crc_table);
946
947 /* return success */
948 return 0;
949}
950
951/* ===========================================================================
952 * Unzip in to out. This routine works on gzip files only.
953 *
954 * IN assertions: the buffer inbuf contains already the beginning of
955 * the compressed data, from offsets inptr to insize-1 included.
956 * The magic header has already been checked. The output buffer is cleared.
957 * in, out: input and output file descriptors
958 */
959extern int unzip(FILE * l_in_file, FILE * l_out_file)
960{
961 unsigned char buf[8]; /* extended local header */
962 unsigned char flags; /* compression flags */
963 typedef void (*sig_type) (int);
964 unsigned short i;
965 unsigned char magic[2];
966 854
967 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 855 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
968 (void) signal(SIGINT, (sig_type) abort_gzip); 856 (void) signal(SIGINT, (sig_type) abort_gzip);
@@ -973,97 +861,44 @@ extern int unzip(FILE * l_in_file, FILE * l_out_file)
973 } 861 }
974#endif 862#endif
975 863
976 magic[0] = fgetc(l_in_file); 864 /* initialize gunzip_window, bit buffer */
977 magic[1] = fgetc(l_in_file); 865 gunzip_bk = 0;
978 866 gunzip_bb = 0;
979#ifdef CONFIG_FEATURE_UNCOMPRESS
980 /* Magic header for compress files, 1F 9d = \037\235 */
981 if ((magic[0] == 0x1F) && (magic[1] == 0x9d)) {
982 return uncompress(l_in_file, l_out_file);
983 }
984#endif
985
986 /* Magic header for gzip files, 1F 8B = \037\213 */
987 if ((magic[0] != 0x1F) || (magic[1] != 0x8b)) {
988 error_msg("Invalid gzip magic");
989 return EXIT_FAILURE;
990 }
991
992 /* Check the compression method */
993 if (fgetc(l_in_file) != 8) /* also catches EOF */ {
994 error_msg("Unknown compression method");
995 return (-1);
996 }
997
998 flags = (unsigned char) fgetc(l_in_file);
999
1000 /* Ignore time stamp(4), extra flags(1), OS type(1) */
1001 for (i = 0; i < 6; i++) {
1002 fgetc(l_in_file);
1003 }
1004 867
1005 if (flags & 0x04) { 868 /* Create the crc table */
1006 /* bit 2 set: extra field present */ 869 make_gunzip_crc_table();
1007 const unsigned short extra =
1008 fgetc(l_in_file) + (fgetc(l_in_file) << 8);
1009 if (feof(in_file)) return 1;
1010 for (i = 0; i < extra; i++) {
1011 fgetc(l_in_file);
1012 }
1013 }
1014
1015 /* Discard original name if any */
1016 if (flags & 0x08) {
1017 /* bit 3 set: original file name present */
1018 while (fgetc(l_in_file) != 0 && !feof(l_in_file)); /* null */
1019 }
1020 870
1021 /* Discard file comment if any */ 871 /* decompress until the last block */
1022 if (flags & 0x10) { 872 do {
1023 /* bit 4 set: file comment present */ 873 gunzip_hufts = 0;
1024 while (fgetc(l_in_file) != 0 && !feof(l_in_file)); /* null */ 874 r = inflate_block(&e);
875 if (r != 0) {
876 error_msg_and_die("inflate error %d", r);
877 return r;
1025 } 878 }
1026 879 if (gunzip_hufts > h) {
1027 /* Decompress */ 880 h = gunzip_hufts;
1028 if (inflate(l_in_file, l_out_file) != 0) {
1029 error_msg("invalid compressed data--format violated");
1030 } 881 }
882 } while (!e);
1031 883
1032 /* Get the crc and original length 884 /* write any buffered uncompressed data */
1033 * crc32 (see algorithm.doc) 885 flush_gunzip_window();
1034 * uncompressed input size modulo 2^32 886 free(gunzip_window);
1035 */ 887
1036 fread(buf, 1, 8, l_in_file); 888 /* Cleanup */
1037 889 free(gunzip_crc_table);
1038 /* Validate decompression - crc */ 890
1039 if ((unsigned int) ((buf[0] | (buf[1] << 8)) | 891 /* Store unused bytes in a global buffer so calling applets can access it */
1040 ((buf[2] | (buf[3] << 8)) << 16)) != 892 gunzip_in_buffer_count = 0;
1041 (crc ^ 0xffffffffL)) { 893 if (gunzip_bk >= 8) {
1042 error_msg("invalid compressed data--crc error"); 894 /* Undo too much lookahead. The next read will be byte aligned
1043 } 895 * so we can discard unused bits in the last meaningful byte. */
1044 /* Validate decompression - size */ 896 gunzip_in_buffer[gunzip_in_buffer_count] = gunzip_bb & 0xff;
1045 if (((buf[4] | (buf[5] << 8)) | ((buf[6] | (buf[7] << 8)) << 16)) != 897 gunzip_in_buffer_count++;
1046 (unsigned long) bytes_out) { 898 gunzip_bb >>= 8;
1047 error_msg("invalid compressed data--length error"); 899 gunzip_bk -= 8;
1048 } 900 }
1049 901
902 /* return success */
1050 return 0; 903 return 0;
1051} 904}
1052
1053/*
1054 * This needs access to global variables window and crc_table, so its not in its own file.
1055 */
1056extern void gz_close(int gunzip_pid)
1057{
1058 if (kill(gunzip_pid, SIGTERM) == -1) {
1059 error_msg_and_die
1060 ("*** Couldnt kill old gunzip process *** aborting");
1061 }
1062
1063 if (waitpid(gunzip_pid, NULL, 0) == -1) {
1064 printf("Couldnt wait ?");
1065 }
1066
1067 free(window);
1068 free(crc_table);
1069}
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c
index 22051dabf..e1e93988f 100644
--- a/archival/rpm2cpio.c
+++ b/archival/rpm2cpio.c
@@ -18,10 +18,13 @@
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21#include <sys/types.h>
22#include "busybox.h"
23#include <netinet/in.h> /* For ntohl & htonl function */ 22#include <netinet/in.h> /* For ntohl & htonl function */
23#include <fcntl.h>
24#include <unistd.h>
24#include <string.h> 25#include <string.h>
26#include "busybox.h"
27#include "unarchive.h"
25 28
26#define RPM_MAGIC "\355\253\356\333" 29#define RPM_MAGIC "\355\253\356\333"
27#define RPM_HEADER_MAGIC "\216\255\350" 30#define RPM_HEADER_MAGIC "\216\255\350"
@@ -45,46 +48,54 @@ struct rpm_header {
45 u_int32_t size; /* Size of store (4 bytes) */ 48 u_int32_t size; /* Size of store (4 bytes) */
46}; 49};
47 50
48void skip_header(FILE *rpmfile) 51void skip_header(int rpm_fd)
49{ 52{
50 struct rpm_header header; 53 struct rpm_header header;
51 54
52 fread(&header, sizeof(struct rpm_header), 1, rpmfile); 55 xread_all(rpm_fd, &header, sizeof(struct rpm_header));
53 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */ 56 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) {
54 if (header.version != 1) error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */ 57 error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */
58 }
59 if (header.version != 1) {
60 error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */
61 }
55 header.entries = ntohl(header.entries); 62 header.entries = ntohl(header.entries);
56 header.size = ntohl(header.size); 63 header.size = ntohl(header.size);
57 fseek (rpmfile, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ 64 lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */
58 fseek (rpmfile, header.size, SEEK_CUR); /* Seek past store */ 65 lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */
59} 66}
60 67
61/* No getopt required */ 68/* No getopt required */
62extern int rpm2cpio_main(int argc, char **argv) 69extern int rpm2cpio_main(int argc, char **argv)
63{ 70{
64 struct rpm_lead lead; 71 struct rpm_lead lead;
65 int gunzip_pid; 72 int rpm_fd;
66 FILE *rpmfile, *cpiofile;
67 73
68 if (argc == 1) { 74 if (argc == 1) {
69 rpmfile = stdin; 75 rpm_fd = fileno(stdin);
70 } else { 76 } else {
71 rpmfile = xfopen(argv[1], "r"); 77 rpm_fd = xopen(argv[1], O_RDONLY);
72 /* set the buffer size */ 78 }
73 setvbuf(rpmfile, NULL, _IOFBF, 0x8000); 79
80 xread_all(rpm_fd, &lead, sizeof(struct rpm_lead));
81 if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) {
82 error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */
74 } 83 }
75 84
76 fread (&lead, sizeof(struct rpm_lead), 1, rpmfile);
77 if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */
78 /* Skip the signature header */ 85 /* Skip the signature header */
79 skip_header(rpmfile); 86 skip_header(rpm_fd);
80 fseek(rpmfile, (8 - (ftell(rpmfile) % 8)) % 8, SEEK_CUR); /* Pad to 8 byte boundary */ 87 data_align(rpm_fd, lseek(rpm_fd, 0, SEEK_CUR), 8);
88
81 /* Skip the main header */ 89 /* Skip the main header */
82 skip_header(rpmfile); 90 skip_header(rpm_fd);
91
92 check_header_gzip(rpm_fd);
93 if (inflate(rpm_fd, fileno(stdout)) != 0) {
94 error_msg("Error inflating");
95 }
96 check_trailer_gzip(rpm_fd);
83 97
84 cpiofile = gz_open(rpmfile, &gunzip_pid); 98 close(rpm_fd);
85 99
86 copyfd(fileno(cpiofile), fileno(stdout));
87 gz_close(gunzip_pid);
88 fclose(rpmfile);
89 return 0; 100 return 0;
90} 101}
diff --git a/archival/tar.c b/archival/tar.c
index 2ab022954..6ef698edf 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -115,7 +115,7 @@ struct TarBallInfo {
115 tarball lives, so we can avoid trying 115 tarball lives, so we can avoid trying
116 to include the tarball into itself */ 116 to include the tarball into itself */
117 int verboseFlag; /* Whether to print extra stuff or not */ 117 int verboseFlag; /* Whether to print extra stuff or not */
118 char **excludeList; /* List of files to not include */ 118 const llist_t *excludeList; /* List of files to not include */
119 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */ 119 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
120 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */ 120 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
121}; 121};
@@ -325,16 +325,15 @@ static inline int writeTarHeader(struct TarBallInfo *tbInfo,
325} 325}
326 326
327# if defined CONFIG_FEATURE_TAR_EXCLUDE 327# if defined CONFIG_FEATURE_TAR_EXCLUDE
328static inline int exclude_file(char **excluded_files, const char *file) 328static inline int exclude_file(const llist_t *excluded_files, const char *file)
329{ 329{
330 int i; 330 if (excluded_files == NULL) {
331
332 if (excluded_files == NULL)
333 return 0; 331 return 0;
332 }
334 333
335 for (i = 0; excluded_files[i] != NULL; i++) { 334 while (excluded_files) {
336 if (excluded_files[i][0] == '/') { 335 if (excluded_files->data[0] == '/') {
337 if (fnmatch(excluded_files[i], file, 336 if (fnmatch(excluded_files->data, file,
338 FNM_PATHNAME | FNM_LEADING_DIR) == 0) 337 FNM_PATHNAME | FNM_LEADING_DIR) == 0)
339 return 1; 338 return 1;
340 } else { 339 } else {
@@ -342,11 +341,12 @@ static inline int exclude_file(char **excluded_files, const char *file)
342 341
343 for (p = file; p[0] != '\0'; p++) { 342 for (p = file; p[0] != '\0'; p++) {
344 if ((p == file || p[-1] == '/') && p[0] != '/' && 343 if ((p == file || p[-1] == '/') && p[0] != '/' &&
345 fnmatch(excluded_files[i], p, 344 fnmatch(excluded_files->data, p,
346 FNM_PATHNAME | FNM_LEADING_DIR) == 0) 345 FNM_PATHNAME | FNM_LEADING_DIR) == 0)
347 return 1; 346 return 1;
348 } 347 }
349 } 348 }
349 excluded_files = excluded_files->link;
350 } 350 }
351 351
352 return 0; 352 return 0;
@@ -455,8 +455,8 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
455 return (TRUE); 455 return (TRUE);
456} 456}
457 457
458static inline int writeTarFile(const char *tarName, int verboseFlag, 458static inline int writeTarFile(const char *tarName, const int verboseFlag,
459 char **argv, char **excludeList, int gzip) 459 const llist_t *include, const llist_t *exclude, const int gzip)
460{ 460{
461#ifdef CONFIG_FEATURE_TAR_GZIP 461#ifdef CONFIG_FEATURE_TAR_GZIP
462 int gzipDataPipe[2] = { -1, -1 }; 462 int gzipDataPipe[2] = { -1, -1 };
@@ -471,8 +471,9 @@ static inline int writeTarFile(const char *tarName, int verboseFlag,
471 tbInfo.hlInfoHead = NULL; 471 tbInfo.hlInfoHead = NULL;
472 472
473 /* Make sure there is at least one file to tar up. */ 473 /* Make sure there is at least one file to tar up. */
474 if (*argv == NULL) 474 if (include == NULL) {
475 error_msg_and_die("Cowardly refusing to create an empty archive"); 475 error_msg_and_die("Cowardly refusing to create an empty archive");
476 }
476 477
477 /* Open the tar file for writing. */ 478 /* Open the tar file for writing. */
478 if (tarName == NULL) { 479 if (tarName == NULL) {
@@ -544,15 +545,16 @@ static inline int writeTarFile(const char *tarName, int verboseFlag,
544 } 545 }
545#endif 546#endif
546 547
547 tbInfo.excludeList = excludeList; 548 tbInfo.excludeList = exclude;
548 549
549 /* Read the directory/files and iterate over them one at a time */ 550 /* Read the directory/files and iterate over them one at a time */
550 while (*argv != NULL) { 551 while (include) {
551 if (!recursive_action(*argv++, TRUE, FALSE, FALSE, 552 if (!recursive_action(include->data, TRUE, FALSE, FALSE,
552 writeFileToTarball, writeFileToTarball, 553 writeFileToTarball, writeFileToTarball,
553 (void *) &tbInfo)) { 554 (void *) &tbInfo)) {
554 errorFlag = TRUE; 555 errorFlag = TRUE;
555 } 556 }
557 include = include->link;
556 } 558 }
557 /* Write two empty blocks to the end of the archive */ 559 /* Write two empty blocks to the end of the archive */
558 for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++) { 560 for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++) {
@@ -582,64 +584,48 @@ static inline int writeTarFile(const char *tarName, int verboseFlag,
582} 584}
583#endif /* tar_create */ 585#endif /* tar_create */
584 586
585void append_file_to_list(const char *new_name, char ***list, int *list_count) 587#ifdef CONFIG_FEATURE_TAR_EXCLUDE
586{ 588static const llist_t *append_file_list_to_list(const char *filename, const llist_t *list)
587 *list = realloc(*list, sizeof(char *) * (*list_count + 2));
588 (*list)[*list_count] = xstrdup(new_name);
589 (*list_count)++;
590 (*list)[*list_count] = NULL;
591}
592
593void append_file_list_to_list(char *filename, char ***name_list,
594 int *num_of_entries)
595{ 589{
596 FILE *src_stream; 590 FILE *src_stream = xfopen(filename, "r");
597 char *line; 591 while(1) {
598 592 char *line = get_line_from_file(src_stream);
599 src_stream = xfopen(filename, "r"); 593 if (line == NULL) {
600 while ((line = get_line_from_file(src_stream)) != NULL) { 594 break;
595 }
601 chomp(line); 596 chomp(line);
602 append_file_to_list(line, name_list, num_of_entries); 597 list = add_to_list(list, line);
603 free(line); 598 free(line);
604 } 599 }
605 fclose(src_stream); 600 fclose(src_stream);
601
602 return (list);
606} 603}
604#endif
607 605
608int tar_main(int argc, char **argv) 606int tar_main(int argc, char **argv)
609{ 607{
610 enum untar_funct_e { 608#ifdef CONFIG_FEATURE_TAR_GZIP
611 /* This is optional */ 609 char (*get_header_ptr)(archive_handle_t *) = get_header_tar;
612 untar_unzip = 1, 610#endif
613 /* Require one and only one of these */ 611 archive_handle_t *tar_handle;
614 untar_list = 2,
615 untar_create = 4,
616 untar_extract = 8
617 };
618
619 FILE *src_stream = NULL;
620 FILE *uncompressed_stream = NULL;
621 char **include_list = NULL;
622 char **exclude_list = NULL;
623 char *src_filename = NULL;
624 char *dst_prefix = NULL;
625 int opt; 612 int opt;
626 unsigned short untar_funct = 0; 613 char *base_dir = NULL;
627 unsigned short untar_funct_required = 0;
628 unsigned short extract_function = 0;
629 int include_list_count = 0;
630 614
631#ifdef CONFIG_FEATURE_TAR_EXCLUDE 615#ifdef CONFIG_FEATURE_TAR_CREATE
632 int exclude_list_count = 0; 616 char *src_filename = NULL;
633#endif 617 unsigned char tar_create = FALSE;
634#ifdef CONFIG_FEATURE_TAR_GZIP
635 int gunzip_pid;
636 int gz_fd = 0;
637#endif 618#endif
638 619
639 if (argc < 2) { 620 if (argc < 2) {
640 show_usage(); 621 show_usage();
641 } 622 }
642 623
624 /* Initialise default values */
625 tar_handle = init_handle();
626 tar_handle->src_fd = fileno(stdin);
627 tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS;
628
643 /* Prepend '-' to the first argument if required */ 629 /* Prepend '-' to the first argument if required */
644 if (argv[1][0] != '-') { 630 if (argv[1][0] != '-') {
645 char *tmp = xmalloc(strlen(argv[1]) + 2); 631 char *tmp = xmalloc(strlen(argv[1]) + 2);
@@ -648,61 +634,69 @@ int tar_main(int argc, char **argv)
648 strcpy(tmp + 1, argv[1]); 634 strcpy(tmp + 1, argv[1]);
649 argv[1] = tmp; 635 argv[1] = tmp;
650 } 636 }
651
652 while ((opt = getopt(argc, argv, "ctxT:X:C:f:Opvz")) != -1) { 637 while ((opt = getopt(argc, argv, "ctxT:X:C:f:Opvz")) != -1) {
653 switch (opt) { 638 switch (opt) {
654
655 /* One and only one of these is required */ 639 /* One and only one of these is required */
640#ifdef CONFIG_FEATURE_TAR_CREATE
656 case 'c': 641 case 'c':
657 untar_funct_required |= untar_create; 642 tar_create = TRUE;
658 break; 643 break;
644#endif
659 case 't': 645 case 't':
660 untar_funct_required |= untar_list; 646 if ((tar_handle->action_header == header_list) ||
661 extract_function |= extract_list | extract_unconditional; 647 (tar_handle->action_header == header_verbose_list)) {
648 tar_handle->action_header = header_verbose_list;
649 } else {
650 tar_handle->action_header = header_list;
651 }
662 break; 652 break;
663 case 'x': 653 case 'x':
664 untar_funct_required |= untar_extract; 654 tar_handle->action_data = data_extract_all;
665 extract_function |=
666 (extract_all_to_fs | extract_unconditional |
667 extract_create_leading_dirs);
668 break; 655 break;
669 656
670 /* These are optional */ 657 /* These are optional */
671 /* Exclude or Include files listed in <filename> */ 658 /* Exclude or Include files listed in <filename> */
672#ifdef CONFIG_FEATURE_TAR_EXCLUDE 659#ifdef CONFIG_FEATURE_TAR_EXCLUDE
673 case 'X': 660 case 'X':
674 append_file_list_to_list(optarg, &exclude_list, 661 tar_handle->reject =
675 &exclude_list_count); 662 append_file_list_to_list(optarg, tar_handle->reject);
676 break; 663 break;
677#endif 664#endif
678 case 'T': 665 case 'T':
679 /* by default a list is an include list */ 666 /* by default a list is an include list */
680 append_file_list_to_list(optarg, &include_list,
681 &include_list_count);
682 break; 667 break;
683
684 case 'C': /* Change to dir <optarg> */ 668 case 'C': /* Change to dir <optarg> */
685 /* Make sure dst_prefix ends in a '/' */ 669 base_dir = optarg;
686 dst_prefix = concat_path_file(optarg, "/");
687 break; 670 break;
688 case 'f': /* archive filename */ 671 case 'f': /* archive filename */
689 if (strcmp(optarg, "-") == 0) { 672#ifdef CONFIG_FEATURE_TAR_CREATE
690 src_filename = NULL; 673 src_filename = optarg;
691 } else { 674#endif
692 src_filename = xstrdup(optarg); 675 tar_handle->src_fd = xopen(optarg, O_RDONLY);
693 }
694 break; 676 break;
695 case 'O': 677 case 'O': /* To stdout */
696 extract_function |= extract_to_stdout; 678 tar_handle->action_data = data_extract_to_stdout;
697 break; 679 break;
698 case 'p': 680 case 'p':
681 tar_handle->flags |= ARCHIVE_PRESERVE_DATE;
699 break; 682 break;
700 case 'v': 683 case 'v':
701 extract_function |= extract_verbose_list; 684 if ((tar_handle->action_header == header_list) ||
685 (tar_handle->action_header == header_verbose_list)) {
686 tar_handle->action_header = header_verbose_list;
687 } else {
688 tar_handle->action_header = header_list;
689 }
702 break; 690 break;
703#ifdef CONFIG_FEATURE_TAR_GZIP 691#ifdef CONFIG_FEATURE_TAR_GZIP
704 case 'z': 692 case 'z':
705 untar_funct |= untar_unzip; 693 get_header_ptr = get_header_tar_gz;
694 break;
695#endif
696#ifdef CONFIG_FEATURE_TAR_BZIP2
697 /* Not enabled yet */
698 case 'j':
699 archive_handle->archive_action = bunzip2;
706 break; 700 break;
707#endif 701#endif
708 default: 702 default:
@@ -710,77 +704,54 @@ int tar_main(int argc, char **argv)
710 } 704 }
711 } 705 }
712 706
713 /* Make sure the valid arguments were passed */
714 if (untar_funct_required == 0) {
715 error_msg_and_die("You must specify one of the `-ctx' options");
716 }
717 if ((untar_funct_required != untar_create) &&
718 (untar_funct_required != untar_extract) &&
719 (untar_funct_required != untar_list)) {
720 error_msg_and_die("You may not specify more than one `ctx' option.");
721 }
722 untar_funct |= untar_funct_required;
723
724 /* Setup an array of filenames to work with */ 707 /* Setup an array of filenames to work with */
708 /* TODO: This is the same as in ar, seperate function ? */
725 while (optind < argc) { 709 while (optind < argc) {
726 append_file_to_list(argv[optind], &include_list, &include_list_count); 710 char absolute_path[PATH_MAX];
711
712 realpath(argv[optind], absolute_path);
713 tar_handle->accept = add_to_list(tar_handle->accept, absolute_path);
727 optind++; 714 optind++;
728 } 715#ifdef CONFIG_FEATURE_TAR_EXCLUDE
729 if (extract_function & (extract_list | extract_all_to_fs)) { 716 if (tar_handle->reject) {
730 if (dst_prefix == NULL) { 717 tar_handle->filter = filter_accept_reject_list;
731 dst_prefix = xstrdup("./"); 718 } else
719#endif
720 tar_handle->filter = filter_accept_list;
732 } 721 }
733 722
734 /* Setup the source of the tar data */ 723 if ((base_dir) && (chdir(base_dir))) {
735 if (src_filename != NULL) { 724 perror_msg_and_die("Couldnt chdir");
736 src_stream = xfopen(src_filename, "r");
737 } else {
738 src_stream = stdin;
739 } 725 }
740#ifdef CONFIG_FEATURE_TAR_GZIP
741 /* Get a binary tree of all the tar file headers */
742 if (untar_funct & untar_unzip) {
743 uncompressed_stream = gz_open(src_stream, &gunzip_pid);
744 } else
745#endif /* CONFIG_FEATURE_TAR_GZIP */
746 uncompressed_stream = src_stream;
747 726
748 /* extract or list archive */
749 unarchive(uncompressed_stream, stdout, &get_header_tar,
750 extract_function, dst_prefix, include_list, exclude_list);
751 fclose(uncompressed_stream);
752 }
753#ifdef CONFIG_FEATURE_TAR_CREATE 727#ifdef CONFIG_FEATURE_TAR_CREATE
754 /* create an archive */ 728 /* create an archive */
755 else if (untar_funct & untar_create) { 729 if (tar_create == TRUE) {
756 int verboseFlag = FALSE; 730 int verboseFlag = FALSE;
757 int gzipFlag = FALSE; 731 int gzipFlag = FALSE;
758 732
759#ifdef CONFIG_FEATURE_TAR_GZIP 733# ifdef CONFIG_FEATURE_TAR_GZIP
760 if (untar_funct & untar_unzip) 734 if (get_header_ptr == get_header_tar_gz) {
761 gzipFlag = TRUE; 735 gzipFlag = TRUE;
762 736 }
763#endif /* CONFIG_FEATURE_TAR_GZIP */ 737# endif
764 if (extract_function & extract_verbose_list) 738 if (tar_handle->action_header == header_verbose_list) {
765 verboseFlag = TRUE; 739 verboseFlag = TRUE;
766
767 writeTarFile(src_filename, verboseFlag, include_list, exclude_list,
768 gzipFlag);
769 } 740 }
770#endif /* CONFIG_FEATURE_TAR_CREATE */ 741 writeTarFile(src_filename, verboseFlag, tar_handle->accept,
771 742 tar_handle->reject, gzipFlag);
772 /* Cleanups */ 743 } else
744#endif
773#ifdef CONFIG_FEATURE_TAR_GZIP 745#ifdef CONFIG_FEATURE_TAR_GZIP
774 if (!(untar_funct & untar_create) && (untar_funct & untar_unzip)) { 746 if (get_header_ptr == get_header_tar_gz) {
775 fclose(src_stream); 747 get_header_tar_gz(tar_handle);
776 close(gz_fd); 748 } else
777 gz_close(gunzip_pid); 749#endif
778 } 750 while (get_header_tar(tar_handle) == EXIT_SUCCESS);
779#endif /* CONFIG_FEATURE_TAR_GZIP */ 751
780#ifdef CONFIG_FEATURE_CLEAN_UP 752#ifdef CONFIG_FEATURE_CLEAN_UP
781 if (src_filename) { 753 close(tar_handle->src_fd);
782 free(src_filename);
783 }
784#endif 754#endif
785 return (EXIT_SUCCESS); 755
756 return(EXIT_SUCCESS);
786} 757}
diff --git a/archival/unzip.c b/archival/unzip.c
index ae0d7c1dc..5a22d242a 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -20,6 +20,10 @@
20 * 20 *
21 */ 21 */
22 22
23/* For reference to format see http://www.pkware.com/support/appnote.html */
24
25/* TODO Endian issues, exclude, should we accept input from stdin ? */
26
23#include <fcntl.h> 27#include <fcntl.h>
24#include <getopt.h> 28#include <getopt.h>
25#include <stdlib.h> 29#include <stdlib.h>
@@ -28,67 +32,213 @@
28#include "unarchive.h" 32#include "unarchive.h"
29#include "busybox.h" 33#include "busybox.h"
30 34
35#define ZIP_FILEHEADER_MAGIC 0x04034b50
36#define ZIP_CDS_MAGIC 0x02014b50
37#define ZIP_CDS_END_MAGIC 0x06054b50
38#define ZIP_DD_MAGIC 0x08074b50
39
40extern unsigned int gunzip_crc;
41extern unsigned int gunzip_bytes_out;
42
43static void header_list_unzip(const file_header_t *file_header)
44{
45 printf(" inflating: %s\n", file_header->name);
46}
47
48static void header_verbose_list_unzip(const file_header_t *file_header)
49{
50 unsigned int dostime = (unsigned int) file_header->mtime;
51
52 /* can printf arguments cut of the decade component ? */
53 unsigned short year = 1980 + ((dostime & 0xfe000000) >> 25);
54 while (year >= 100) {
55 year -= 100;
56 }
57
58 printf("%9u %02u-%02u-%02u %02u:%02u %s\n",
59 (unsigned int) file_header->size,
60 (dostime & 0x01e00000) >> 21,
61 (dostime & 0x001f0000) >> 16,
62 year,
63 (dostime & 0x0000f800) >> 11,
64 (dostime & 0x000007e0) >> 5,
65 file_header->name);
66}
67
31extern int unzip_main(int argc, char **argv) 68extern int unzip_main(int argc, char **argv)
32{ 69{
33 FILE *src_stream; 70 union {
34 int extract_function = extract_all_to_fs | extract_create_leading_dirs; 71 unsigned char raw[26];
35 char **extract_names = NULL; 72 struct {
36 char **exclude_names = NULL; 73 unsigned short version; /* 0-1 */
74 unsigned short flags; /* 2-3 */
75 unsigned short method; /* 4-5 */
76 unsigned short modtime; /* 6-7 */
77 unsigned short moddate; /* 8-9 */
78 unsigned int crc32 __attribute__ ((packed)); /* 10-13 */
79 unsigned int cmpsize __attribute__ ((packed));; /* 14-17 */
80 unsigned int ucmpsize __attribute__ ((packed));; /* 18-21 */
81 unsigned short filename_len; /* 22-23 */
82 unsigned short extra_len; /* 24-25 */
83 } formated __attribute__ ((packed));
84 } zip_header;
85
86 archive_handle_t *archive_handle;
87 unsigned int total_size = 0;
88 unsigned int total_entries = 0;
89 char *base_dir = NULL;
37 int opt = 0; 90 int opt = 0;
38 int num_of_entries = 0;
39 int exclude = 0;
40 char *outdir = "./";
41 FILE *msgout = stdout;
42 91
43 while ((opt = getopt(argc, argv, "lnopqxd:")) != -1) { 92 /* Initialise */
93 archive_handle = init_handle();
94 archive_handle->action_data = NULL;
95 archive_handle->action_header = header_list_unzip;
96
97 while ((opt = getopt(argc, argv, "lnopqd:")) != -1) {
44 switch (opt) { 98 switch (opt) {
45 case 'l': 99 case 'l': /* list */
46 extract_function |= extract_verbose_list; 100 archive_handle->action_header = header_verbose_list_unzip;
47 extract_function ^= extract_all_to_fs; 101 archive_handle->action_data = data_skip;
48 break; 102 break;
49 case 'n': 103 case 'n': /* never overwright existing files */
50 break; 104 break;
51 case 'o': 105 case 'o':
52 extract_function |= extract_unconditional; 106 archive_handle->flags = ARCHIVE_EXTRACT_UNCONDITIONAL;
53 break; 107 break;
54 case 'p': 108 case 'p': /* extract files to stdout */
55 extract_function |= extract_to_stdout; 109 archive_handle->action_data = data_extract_to_stdout;
56 extract_function ^= extract_all_to_fs;
57 /* FALLTHROUGH */
58 case 'q':
59 msgout = xfopen("/dev/null", "w");
60 break; 110 break;
61 case 'd': 111 case 'q': /* Extract files quietly */
62 outdir = xstrdup(optarg); 112 archive_handle->action_header = header_skip;
63 strcat(outdir, "/");
64 break; 113 break;
65 case 'x': 114 case 'd': /* Extract files to specified base directory*/
66 exclude = 1; 115 base_dir = optarg;
67 break; 116 break;
117#if 0
118 case 'x': /* Exclude the specified files */
119 archive_handle->filter = filter_accept_reject_list;
120 break;
121#endif
122 default:
123 show_usage();
68 } 124 }
69 } 125 }
70 126
71 if (optind == argc) { 127 if (argc == optind) {
72 show_usage(); 128 show_usage();
73 } 129 }
74 130
75 if (*argv[optind] == '-') src_stream = stdin; 131 printf("Archive: %s\n", argv[optind]);
76 else src_stream = xfopen(argv[optind++], "r"); 132 if (archive_handle->action_header == header_verbose_list_unzip) {
133 printf(" Length Date Time Name\n");
134 printf(" -------- ---- ---- ----\n");
135 }
77 136
78 while (optind < argc) { 137 if (*argv[optind] == '-') {
79 if (exclude) { 138 archive_handle->src_fd = fileno(stdin);
80 exclude_names = xrealloc(exclude_names, sizeof(char *) * (num_of_entries + 2));
81 exclude_names[num_of_entries] = xstrdup(argv[optind]);
82 } else { 139 } else {
83 extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); 140 archive_handle->src_fd = xopen(argv[optind++], O_RDONLY);
84 extract_names[num_of_entries] = xstrdup(argv[optind]);
85 } 141 }
86 num_of_entries++; 142
87 if (exclude) exclude_names[num_of_entries] = NULL; 143 if ((base_dir) && (chdir(base_dir))) {
88 else extract_names[num_of_entries] = NULL; 144 perror_msg_and_die("Couldnt chdir");
145 }
146
147 while (optind < argc) {
148 archive_handle->filter = filter_accept_list;
149 archive_handle->accept = add_to_list(archive_handle->accept, argv[optind]);
89 optind++; 150 optind++;
90 } 151 }
91 152
92 unarchive(src_stream, msgout, &get_header_zip, extract_function, outdir, extract_names, exclude_names); 153 while (1) {
93 return EXIT_SUCCESS; 154 unsigned int magic;
155 int dst_fd;
156
157 /* TODO Endian issues */
158 xread_all(archive_handle->src_fd, &magic, 4);
159 archive_handle->offset += 4;
160
161 if (magic == ZIP_CDS_MAGIC) {
162 break;
163 }
164 else if (magic != ZIP_FILEHEADER_MAGIC) {
165 error_msg_and_die("Invlaide zip magic");
166 }
167
168 /* Read the file header */
169 xread_all(archive_handle->src_fd, zip_header.raw, 26);
170 archive_handle->offset += 26;
171 archive_handle->file_header->mode = S_IFREG | 0777;
172
173 if (zip_header.formated.method != 8) {
174 error_msg_and_die("Unsupported compression method %d\n", zip_header.formated.method);
175 }
176
177 /* Read filename */
178 archive_handle->file_header->name = xmalloc(zip_header.formated.filename_len + 1);
179 xread_all(archive_handle->src_fd, archive_handle->file_header->name, zip_header.formated.filename_len);
180 archive_handle->offset += zip_header.formated.filename_len;
181 archive_handle->file_header->name[zip_header.formated.filename_len] = '\0';
182
183 /* Skip extra header bits */
184 archive_handle->file_header->size = zip_header.formated.extra_len;
185 data_skip(archive_handle);
186 archive_handle->offset += zip_header.formated.extra_len;
187
188 /* Handle directories */
189 archive_handle->file_header->mode = S_IFREG | 0777;
190 if (last_char_is(archive_handle->file_header->name, '/')) {
191 archive_handle->file_header->mode ^= S_IFREG;
192 archive_handle->file_header->mode |= S_IFDIR;
193 }
194
195 /* Data section */
196 archive_handle->file_header->size = zip_header.formated.cmpsize;
197 if (archive_handle->action_data) {
198 archive_handle->action_data(archive_handle);
199 } else {
200 dst_fd = xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT);
201 inflate(archive_handle->src_fd, dst_fd);
202 close(dst_fd);
203 chmod(archive_handle->file_header->name, archive_handle->file_header->mode);
204
205 /* Validate decompression - crc */
206 if (zip_header.formated.crc32 != (gunzip_crc ^ 0xffffffffL)) {
207 error_msg("Invalid compressed data--crc error");
208 }
209
210 /* Validate decompression - size */
211 if (gunzip_bytes_out != zip_header.formated.ucmpsize) {
212 error_msg("Invalid compressed data--length error");
213 }
214 }
215
216 /* local file descriptor section */
217 archive_handle->offset += zip_header.formated.cmpsize;
218 /* This ISNT unix time */
219 archive_handle->file_header->mtime = zip_header.formated.modtime | (zip_header.formated.moddate << 16);
220 archive_handle->file_header->size = zip_header.formated.ucmpsize;
221 total_size += archive_handle->file_header->size;
222 total_entries++;
223
224 archive_handle->action_header(archive_handle->file_header);
225
226 /* Data descriptor section */
227 if (zip_header.formated.flags & 4) {
228 /* skip over duplicate crc, compressed size and uncompressed size */
229 unsigned short i;
230 for (i = 0; i != 12; i++) {
231 xread_char(archive_handle->src_fd);
232 }
233 archive_handle->offset += 12;
234 }
235 }
236 /* Central directory section */
237
238 if (archive_handle->action_header == header_verbose_list_unzip) {
239 printf(" -------- -------\n");
240 printf("%9d %d files\n", total_size, total_entries);
241 }
242
243 return(EXIT_SUCCESS);
94} 244}
diff --git a/include/libbb.h b/include/libbb.h
index 6ab942bd8..bd0d1e942 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -48,10 +48,6 @@
48# include "sha1.h" 48# include "sha1.h"
49#endif 49#endif
50 50
51/* Compatability with ANSI C */
52#ifndef inline
53# define inline
54#endif
55 51
56#if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__) 52#if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__)
57/* libc5 doesn't define socklen_t */ 53/* libc5 doesn't define socklen_t */
@@ -74,6 +70,9 @@ char *strtok_r(char *s, const char *delim, char **ptrptr);
74#define BUF_SIZE 8192 70#define BUF_SIZE 8192
75#define EXPAND_ALLOC 1024 71#define EXPAND_ALLOC 1024
76 72
73static inline int is_decimal(int ch) { return ((ch >= '0') && (ch <= '9')); }
74static inline int is_octal(int ch) { return ((ch >= '0') && (ch <= '7')); }
75
77/* Macros for min/max. */ 76/* Macros for min/max. */
78#ifndef MIN 77#ifndef MIN
79#define MIN(a,b) (((a)<(b))?(a):(b)) 78#define MIN(a,b) (((a)<(b))?(a):(b))
@@ -83,8 +82,6 @@ char *strtok_r(char *s, const char *delim, char **ptrptr);
83#define MAX(a,b) (((a)>(b))?(a):(b)) 82#define MAX(a,b) (((a)>(b))?(a):(b))
84#endif 83#endif
85 84
86
87
88extern void show_usage(void) __attribute__ ((noreturn)); 85extern void show_usage(void) __attribute__ ((noreturn));
89extern void error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); 86extern void error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
90extern void error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); 87extern void error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
@@ -228,10 +225,7 @@ extern long arith (const char *startbuf, int *errcode);
228int read_package_field(const char *package_buffer, char **field_name, char **field_value); 225int read_package_field(const char *package_buffer, char **field_name, char **field_value);
229char *fgets_str(FILE *file, const char *terminating_string); 226char *fgets_str(FILE *file, const char *terminating_string);
230 227
231extern int inflate(FILE *in, FILE *out); 228extern int inflate(int in, int out);
232extern int unzip(FILE *l_in_file, FILE *l_out_file);
233extern void gz_close(int gunzip_pid);
234extern FILE *gz_open(FILE *compressed_file, int *pid);
235 229
236extern struct hostent *xgethostbyname(const char *name); 230extern struct hostent *xgethostbyname(const char *name);
237extern struct hostent *xgethostbyname2(const char *name, int af); 231extern struct hostent *xgethostbyname2(const char *name, int af);
@@ -335,4 +329,11 @@ extern char *pw_encrypt(const char *clear, const char *salt);
335extern struct spwd *pwd_to_spwd(const struct passwd *pw); 329extern struct spwd *pwd_to_spwd(const struct passwd *pw);
336extern int obscure(const char *old, const char *newval, const struct passwd *pwdp); 330extern int obscure(const char *old, const char *newval, const struct passwd *pwdp);
337 331
332//extern int xopen(const char *pathname, int flags, mode_t mode);
333extern int xopen(const char *pathname, int flags);
334extern ssize_t xread(int fd, void *buf, size_t count);
335extern ssize_t xread_all_eof(int fd, void *buf, size_t count);
336extern void xread_all(int fd, void *buf, size_t count);
337extern unsigned char xread_char(int fd);
338
338#endif /* __LIBCONFIG_H__ */ 339#endif /* __LIBCONFIG_H__ */
diff --git a/include/unarchive.h b/include/unarchive.h
index ffddc89f4..e564e9572 100644
--- a/include/unarchive.h
+++ b/include/unarchive.h
@@ -1,21 +1,19 @@
1#include <stdio.h> /* for FILE */ 1#ifndef __UNARCHIVE_H__
2#include <unistd.h> /* for off_t */ 2#define __UNARCHIVE_H__
3 3
4enum extract_functions_e { 4#define ARCHIVE_PRESERVE_DATE 1
5 extract_verbose_list = 1, 5#define ARCHIVE_CREATE_LEADING_DIRS 2
6 extract_list = 2, 6#define ARCHIVE_EXTRACT_UNCONDITIONAL 4
7 extract_one_to_buffer = 4, 7#define ARCHIVE_EXTRACT_QUIET 8
8 extract_to_stdout = 8, 8
9 extract_all_to_fs = 16, 9#include <sys/types.h>
10 extract_preserve_date = 32, 10
11 extract_data_tar_gz = 64, 11typedef struct gunzip_s {
12 extract_control_tar_gz = 128, 12 unsigned short buffer_count;
13 extract_unzip_only = 256, 13 unsigned char *buffer;
14 extract_unconditional = 512, 14 unsigned int crc;
15 extract_create_leading_dirs = 1024, 15 unsigned int count;
16 extract_quiet = 2048, 16} gunzip_t;
17 extract_exclude_list = 4096
18};
19 17
20typedef struct file_headers_s { 18typedef struct file_headers_s {
21 char *name; 19 char *name;
@@ -26,23 +24,70 @@ typedef struct file_headers_s {
26 mode_t mode; 24 mode_t mode;
27 time_t mtime; 25 time_t mtime;
28 dev_t device; 26 dev_t device;
29 int (*extract_func) (FILE *, FILE *);
30} file_header_t; 27} file_header_t;
31 28
32file_header_t *get_header_ar(FILE * in_file); 29typedef struct llist_s {
33file_header_t *get_header_cpio(FILE * src_stream); 30 const char *data;
34file_header_t *get_header_tar(FILE * tar_stream); 31 const struct llist_s *link;
35file_header_t *get_header_zip(FILE * zip_stream); 32} llist_t;
33
34typedef struct archive_handle_s {
35 /* define if the header and data compenent should processed */
36 char (*filter)(const llist_t *, const llist_t *, const char *);
37 const llist_t *accept;
38 const llist_t *reject;
39
40 /* Contains the processed header entry */
41 file_header_t *file_header;
42
43 /* process the header component, e.g. tar -t */
44 void (*action_header)(const file_header_t *);
45
46 /* process the data componenet, e.g. extract to filesystem */
47 void (*action_data)(struct archive_handle_s *);
48 char (*action_data_subarchive)(struct archive_handle_s *);
49
50 /* Contains the handle to a sub archive */
51 struct archive_handle_s *sub_archive;
52
53 /* The raw stream as read from disk or stdin */
54 int src_fd;
55
56 /* Count the number of bytes processed */
57 off_t offset;
58
59 /* Misc. stuff */
60 unsigned char flags;
61
62} archive_handle_t;
63
64extern archive_handle_t *init_handle(void);
65
66extern char filter_accept_all(const llist_t *accept_list, const llist_t *reject_list, const char *key);
67extern char filter_accept_list(const llist_t *accept_list, const llist_t *reject_list, const char *key);
68extern char filter_accept_reject_list(const llist_t *accept_list, const llist_t *reject_list, const char *key);
69
70extern void unpack_ar_archive(archive_handle_t *ar_archive);
71
72extern void data_gunzip(archive_handle_t *archive_handle);
73extern void data_skip(archive_handle_t *archive_handle);
74extern void data_extract_all(archive_handle_t *archive_handle);
75extern void data_extract_to_stdout(archive_handle_t *archive_handle);
76
77extern void header_skip(const file_header_t *file_header);
78extern void header_list(const file_header_t *file_header);
79extern void header_verbose_list(const file_header_t *file_header);
36 80
37void seek_sub_file(FILE * src_stream, const int count); 81extern void check_header_gzip(int src_fd);
82extern void check_trailer_gzip(int src_fd);
38 83
39extern off_t archive_offset; 84extern char get_header_ar(archive_handle_t *archive_handle);
85extern char get_header_tar(archive_handle_t *archive_handle);
86extern char get_header_tar_gz(archive_handle_t *archive_handle);
40 87
41char *unarchive(FILE * src_stream, FILE * out_stream, 88//extern void seek_sub_file(int src_fd, unsigned int amount);
42 file_header_t * (*get_headers) (FILE *), 89extern const unsigned short data_align(const int src_fd, const unsigned int offset, const unsigned short align_to);
43 const int extract_function, const char *prefix, 90extern const llist_t *add_to_list(const llist_t *old_head, const char *new_item);
44 char **include_name, char **exclude_name); 91extern int copy_file_chunk_fd(int src_fd, int dst_fd, unsigned long long chunksize);
45 92
46char *deb_extract(const char *package_filename, FILE * out_stream, 93#endif
47 const int extract_function, const char *prefix,
48 const char *filename);
diff --git a/libbb/Makefile.in b/libbb/Makefile.in
index e7ca9aa55..449d23c68 100644
--- a/libbb/Makefile.in
+++ b/libbb/Makefile.in
@@ -28,20 +28,22 @@ LIBBB_SRC:= \
28 copy_file_chunk.c dump.c libc5.c device_open.c error_msg.c \ 28 copy_file_chunk.c dump.c libc5.c device_open.c error_msg.c \
29 error_msg_and_die.c fgets_str.c find_mount_point.c find_pid_by_name.c \ 29 error_msg_and_die.c fgets_str.c find_mount_point.c find_pid_by_name.c \
30 find_root_device.c full_read.c full_write.c get_console.c \ 30 find_root_device.c full_read.c full_write.c get_console.c \
31 get_last_path_component.c get_line_from_file.c gz_open.c human_readable.c \ 31 get_last_path_component.c get_line_from_file.c \
32 isdirectory.c kernel_version.c loop.c mode_string.c module_syscalls.c mtab.c \ 32 human_readable.c isdirectory.c kernel_version.c loop.c \
33 mtab_file.c my_getgrnam.c my_getgrgid.c my_getpwnam.c my_getpwnamegid.c \ 33 mode_string.c module_syscalls.c mtab.c mtab_file.c my_getgrnam.c \
34 my_getpwuid.c parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \ 34 my_getgrgid.c my_getpwnam.c my_getpwnamegid.c my_getpwuid.c \
35 print_file.c process_escape_sequence.c read_package_field.c recursive_action.c \ 35 parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \
36 safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \ 36 print_file.c process_escape_sequence.c read_package_field.c \
37 trim.c unzip.c uncompress.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c \ 37 recursive_action.c safe_read.c safe_strncpy.c syscalls.c \
38 xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ 38 syslog_msg_with_name.c time_string.c trim.c unzip.c uncompress.c \
39 copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \ 39 vdprintf.c verror_msg.c vperror_msg.c wfopen.c xgetcwd.c xreadlink.c \
40 dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \ 40 xregcomp.c interface.c remove_file.c last_char_is.c copyfd.c \
41 simplify_path.c inet_common.c inode_hash.c obscure.c pwd2spwd.c xfuncs.c \ 41 vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
42 correct_password.c change_identity.c setup_environment.c run_shell.c \ 42 dirname.c make_directory.c create_icmp_socket.c u_signal_names.c \
43 pw_encrypt.c restricted_shell.c xgethostbyname2.c create_icmp6_socket.c \ 43 arith.c simplify_path.c inet_common.c inode_hash.c obscure.c \
44 xconnect.c bb_asprintf.c 44 pwd2spwd.c xfuncs.c correct_password.c change_identity.c \
45 setup_environment.c run_shell.c pw_encrypt.c restricted_shell.c \
46 xgethostbyname2.c create_icmp6_socket.c xconnect.c bb_asprintf.c
45 47
46LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) 48LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC))
47 49
diff --git a/libbb/unzip.c b/libbb/unzip.c
index d84067068..20bf88f55 100644
--- a/libbb/unzip.c
+++ b/libbb/unzip.c
@@ -65,114 +65,126 @@ static char *license_msg[] = {
65#include <signal.h> 65#include <signal.h>
66#include <stdlib.h> 66#include <stdlib.h>
67#include <string.h> 67#include <string.h>
68#include <unistd.h>
69#include <fcntl.h>
68#include "config.h" 70#include "config.h"
69#include "libbb.h" 71#include "busybox.h"
72#include "unarchive.h"
70 73
71#ifdef CONFIG_FEATURE_UNCOMPRESS 74typedef struct huft_s {
72int uncompress(FILE * in, FILE * out); 75 unsigned char e; /* number of extra bits or operation */
73#endif 76 unsigned char b; /* number of bits in this code or subcode */
74 77 union {
75static FILE *in_file, *out_file; 78 unsigned short n; /* literal, length base, or distance base */
79 struct huft_s *t; /* pointer to next level of table */
80 } v;
81} huft_t;
76 82
77/* these are freed by gz_close */ 83static int gunzip_src_fd;
78static unsigned char *window; 84static int gunzip_dst_fd;
79static unsigned long *crc_table; 85unsigned int gunzip_bytes_out; /* number of output bytes */
86static unsigned int gunzip_outbuf_count; /* bytes in output buffer */
80 87
81static unsigned long crc; /* shift register contents */ 88/* This is used to sanify any unused bits from the bitbuffer
89 * so they arent skipped when reading trailers (trailing headers) */
90unsigned char gunzip_in_buffer_count;
91unsigned char *gunzip_in_buffer;
82 92
83/* Return codes from gzip */ 93/* gunzip_window size--must be a power of two, and
84#define ERROR 1 94 * at least 32K for zip's deflate method */
95static const int gunzip_wsize = 0x8000;
85 96
86/* 97static unsigned char *gunzip_window;
87 * window size--must be a power of two, and 98static unsigned int *gunzip_crc_table;
88 * at least 32K for zip's deflate method 99unsigned int gunzip_crc;
89 */
90#define WSIZE 0x8000
91 100
92/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ 101/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
93#define BMAX 16 /* maximum bit length of any code (16 for explode) */ 102#define BMAX 16 /* maximum bit length of any code (16 for explode) */
94#define N_MAX 288 /* maximum number of codes in any set */ 103#define N_MAX 288 /* maximum number of codes in any set */
95 104
96static long bytes_out; /* number of output bytes */ 105static unsigned int gunzip_hufts; /* track memory usage */
97static unsigned long outcnt; /* bytes in output buffer */ 106static unsigned int gunzip_bb; /* bit buffer */
98 107static unsigned char gunzip_bk; /* bits in bit buffer */
99static unsigned hufts; /* track memory usage */
100static unsigned long bb; /* bit buffer */
101static unsigned bk; /* bits in bit buffer */
102
103typedef struct huft_s {
104 unsigned char e; /* number of extra bits or operation */
105 unsigned char b; /* number of bits in this code or subcode */
106 union {
107 unsigned short n; /* literal, length base, or distance base */
108 struct huft_s *t; /* pointer to next level of table */
109 } v;
110} huft_t;
111 108
112static const unsigned short mask_bits[] = { 109static const unsigned short mask_bits[] = {
113 0x0000, 110 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
114 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
115 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 111 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
116}; 112};
117 113
118/* static int error_number = 0; */ 114/* Copy lengths for literal codes 257..285 */
119/* ======================================================================== 115static const unsigned short cplens[] = {
120 * Signal and error handler. 116 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
121 */ 117 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
118};
119
120/* note: see note #13 above about the 258 in this list. */
121/* Extra bits for literal codes 257..285 */
122static const unsigned char cplext[] = {
123 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
124 5, 5, 5, 0, 99, 99
125}; /* 99==invalid */
126
127/* Copy offsets for distance codes 0..29 */
128static const unsigned short cpdist[] = {
129 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
130 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
131};
132
133/* Extra bits for distance codes */
134static const unsigned char cpdext[] = {
135 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
136 11, 11, 12, 12, 13, 13
137};
138
139/* Tables for deflate from PKZIP's appnote.txt. */
140/* Order of the bit length code lengths */
141static const unsigned char border[] = {
142 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
143};
144
145static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
146{
147 while (*current < required) {
148 bitbuffer |= ((unsigned int) xread_char(gunzip_src_fd)) << *current;
149 *current += 8;
150 }
151
152 return(bitbuffer);
153}
122 154
123static void abort_gzip(void) 155static void abort_gzip(void)
124{ 156{
125 error_msg("gzip aborted\n"); 157 error_msg("gzip aborted\n");
126 exit(ERROR); 158 exit(-1);
127} 159}
128 160
129static void make_crc_table(void) 161static void make_gunzip_crc_table(void)
130{ 162{
131 const unsigned long poly = 0xedb88320; /* polynomial exclusive-or pattern */ 163 const unsigned int poly = 0xedb88320; /* polynomial exclusive-or pattern */
132 unsigned short i; /* counter for all possible eight bit values */ 164 unsigned short i; /* counter for all possible eight bit values */
133 165
134 /* initial shift register value */ 166 /* initial shift register value */
135 crc = 0xffffffffL; 167 gunzip_crc = 0xffffffffL;
136 crc_table = (unsigned long *) malloc(256 * sizeof(unsigned long)); 168 gunzip_crc_table = (unsigned int *) malloc(256 * sizeof(unsigned int));
137 169
138 /* Compute and print table of CRC's, five per line */ 170 /* Compute and print table of CRC's, five per line */
139 for (i = 0; i < 256; i++) { 171 for (i = 0; i < 256; i++) {
140 unsigned long table_entry; /* crc shift register */ 172 unsigned int table_entry; /* crc shift register */
141 char k; /* byte being shifted into crc apparatus */ 173 unsigned char k; /* byte being shifted into crc apparatus */
142 174
143 table_entry = i; 175 table_entry = i;
144 /* The idea to initialize the register with the byte instead of 176 /* The idea to initialize the register with the byte instead of
145 * zero was stolen from Haruhiko Okumura's ar002 177 * zero was stolen from Haruhiko Okumura's ar002
146 */ 178 */
147 for (k = 8; k; k--) { 179 for (k = 8; k; k--) {
148 table_entry = 180 if (table_entry & 1) {
149 table_entry & 1 ? (table_entry >> 1) ^ poly : table_entry >> 181 table_entry = (table_entry >> 1) ^ poly;
150 1; 182 } else {
151 } 183 table_entry >>= 1;
152 crc_table[i] = table_entry;
153 } 184 }
154}
155
156/* ===========================================================================
157 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
158 * (Used for the decompressed data only.)
159 */
160static void flush_window(void)
161{
162 int n;
163
164 if (outcnt == 0)
165 return;
166
167 for (n = 0; n < outcnt; n++) {
168 crc = crc_table[((int) crc ^ (window[n])) & 0xff] ^ (crc >> 8);
169 } 185 }
170 186 gunzip_crc_table[i] = table_entry;
171 if (fwrite(window, 1, outcnt, out_file) != outcnt) {
172 error_msg_and_die("Couldnt write");
173 } 187 }
174 bytes_out += (unsigned long) outcnt;
175 outcnt = 0;
176} 188}
177 189
178/* 190/*
@@ -183,7 +195,8 @@ static void flush_window(void)
183 */ 195 */
184static int huft_free(huft_t * t) 196static int huft_free(huft_t * t)
185{ 197{
186 huft_t *p, *q; 198 huft_t *p;
199 huft_t *q;
187 200
188 /* Go through linked list, freeing from the malloced (t[-1]) address. */ 201 /* Go through linked list, freeing from the malloced (t[-1]) address. */
189 p = t; 202 p = t;
@@ -195,8 +208,6 @@ static int huft_free(huft_t * t)
195 return 0; 208 return 0;
196} 209}
197 210
198typedef unsigned char extra_bits_t;
199
200/* Given a list of code lengths and a maximum table size, make a set of 211/* Given a list of code lengths and a maximum table size, make a set of
201 * tables to decode that set of codes. Return zero on success, one if 212 * tables to decode that set of codes. Return zero on success, one if
202 * the given code set is incomplete (the tables are still built in this 213 * the given code set is incomplete (the tables are still built in this
@@ -213,7 +224,7 @@ typedef unsigned char extra_bits_t;
213 */ 224 */
214static int huft_build(unsigned int *b, const unsigned int n, 225static int huft_build(unsigned int *b, const unsigned int n,
215 const unsigned int s, const unsigned short *d, 226 const unsigned int s, const unsigned short *d,
216 const extra_bits_t * e, huft_t ** t, int *m) 227 const unsigned char *e, huft_t ** t, int *m)
217{ 228{
218 unsigned a; /* counter for codes of length k */ 229 unsigned a; /* counter for codes of length k */
219 unsigned c[BMAX + 1]; /* bit length count table */ 230 unsigned c[BMAX + 1]; /* bit length count table */
@@ -251,26 +262,35 @@ static int huft_build(unsigned int *b, const unsigned int n,
251 262
252 /* Find minimum and maximum length, bound *m by those */ 263 /* Find minimum and maximum length, bound *m by those */
253 l = *m; 264 l = *m;
254 for (j = 1; j <= BMAX; j++) 265 for (j = 1; j <= BMAX; j++) {
255 if (c[j]) 266 if (c[j]) {
256 break; 267 break;
268 }
269 }
257 k = j; /* minimum code length */ 270 k = j; /* minimum code length */
258 if ((unsigned) l < j) 271 if ((unsigned) l < j) {
259 l = j; 272 l = j;
260 for (i = BMAX; i; i--) 273 }
261 if (c[i]) 274 for (i = BMAX; i; i--) {
275 if (c[i]) {
262 break; 276 break;
277 }
278 }
263 g = i; /* maximum code length */ 279 g = i; /* maximum code length */
264 if ((unsigned) l > i) 280 if ((unsigned) l > i) {
265 l = i; 281 l = i;
282 }
266 *m = l; 283 *m = l;
267 284
268 /* Adjust last length count to fill out codes, if needed */ 285 /* Adjust last length count to fill out codes, if needed */
269 for (y = 1 << j; j < i; j++, y <<= 1) 286 for (y = 1 << j; j < i; j++, y <<= 1) {
270 if ((y -= c[j]) < 0) 287 if ((y -= c[j]) < 0) {
271 return 2; /* bad input: more codes than bits */ 288 return 2; /* bad input: more codes than bits */
272 if ((y -= c[i]) < 0) 289 }
290 }
291 if ((y -= c[i]) < 0) {
273 return 2; 292 return 2;
293 }
274 c[i] += y; 294 c[i] += y;
275 295
276 /* Generate starting offsets into the value table for each length */ 296 /* Generate starting offsets into the value table for each length */
@@ -285,8 +305,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
285 p = b; 305 p = b;
286 i = 0; 306 i = 0;
287 do { 307 do {
288 if ((j = *p++) != 0) 308 if ((j = *p++) != 0) {
289 v[x[j]++] = i; 309 v[x[j]++] = i;
310 }
290 } while (++i < n); 311 } while (++i < n);
291 312
292 /* Generate the Huffman codes and for each, make the table entries */ 313 /* Generate the Huffman codes and for each, make the table entries */
@@ -314,8 +335,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
314 f -= a + 1; /* deduct codes from patterns left */ 335 f -= a + 1; /* deduct codes from patterns left */
315 xp = c + k; 336 xp = c + k;
316 while (++j < z) { /* try smaller tables up to z bits */ 337 while (++j < z) { /* try smaller tables up to z bits */
317 if ((f <<= 1) <= *++xp) 338 if ((f <<= 1) <= *++xp) {
318 break; /* enough codes to use up j bits */ 339 break; /* enough codes to use up j bits */
340 }
319 f -= *xp; /* else deduct codes from patterns */ 341 f -= *xp; /* else deduct codes from patterns */
320 } 342 }
321 } 343 }
@@ -324,7 +346,7 @@ static int huft_build(unsigned int *b, const unsigned int n,
324 /* allocate and link in new table */ 346 /* allocate and link in new table */
325 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); 347 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t));
326 348
327 hufts += z + 1; /* track memory usage */ 349 gunzip_hufts += z + 1; /* track memory usage */
328 *t = q + 1; /* link to list for huft_free() */ 350 *t = q + 1; /* link to list for huft_free() */
329 *(t = &(q->v.t)) = NULL; 351 *(t = &(q->v.t)) = NULL;
330 u[h] = ++q; /* table starts after link */ 352 u[h] = ++q; /* table starts after link */
@@ -342,9 +364,9 @@ static int huft_build(unsigned int *b, const unsigned int n,
342 364
343 /* set up table entry in r */ 365 /* set up table entry in r */
344 r.b = (unsigned char) (k - w); 366 r.b = (unsigned char) (k - w);
345 if (p >= v + n) 367 if (p >= v + n) {
346 r.e = 99; /* out of values--invalid code */ 368 r.e = 99; /* out of values--invalid code */
347 else if (*p < s) { 369 } else if (*p < s) {
348 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */ 370 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
349 r.v.n = (unsigned short) (*p); /* simple code is just the value */ 371 r.v.n = (unsigned short) (*p); /* simple code is just the value */
350 p++; /* one compiler does not like *p++ */ 372 p++; /* one compiler does not like *p++ */
@@ -355,12 +377,14 @@ static int huft_build(unsigned int *b, const unsigned int n,
355 377
356 /* fill code-like entries with r */ 378 /* fill code-like entries with r */
357 f = 1 << (k - w); 379 f = 1 << (k - w);
358 for (j = i >> w; j < z; j += f) 380 for (j = i >> w; j < z; j += f) {
359 q[j] = r; 381 q[j] = r;
382 }
360 383
361 /* backwards increment the k-bit code i */ 384 /* backwards increment the k-bit code i */
362 for (j = 1 << (k - 1); i & j; j >>= 1) 385 for (j = 1 << (k - 1); i & j; j >>= 1) {
363 i ^= j; 386 i ^= j;
387 }
364 i ^= j; 388 i ^= j;
365 389
366 /* backup over finished tables */ 390 /* backup over finished tables */
@@ -374,6 +398,25 @@ static int huft_build(unsigned int *b, const unsigned int n,
374 return y != 0 && g != 1; 398 return y != 0 && g != 1;
375} 399}
376 400
401/* ===========================================================================
402 * Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out.
403 * (Used for the decompressed data only.)
404 */
405static void flush_gunzip_window(void)
406{
407 int n;
408
409 for (n = 0; n < gunzip_outbuf_count; n++) {
410 gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
411 }
412
413 if (write(gunzip_dst_fd, gunzip_window, gunzip_outbuf_count) != gunzip_outbuf_count) {
414 error_msg_and_die("Couldnt write");
415 }
416 gunzip_bytes_out += gunzip_outbuf_count;
417 gunzip_outbuf_count = 0;
418}
419
377/* 420/*
378 * inflate (decompress) the codes in a deflated (compressed) block. 421 * inflate (decompress) the codes in a deflated (compressed) block.
379 * Return an error code or zero if it all goes ok. 422 * Return an error code or zero if it all goes ok.
@@ -381,32 +424,26 @@ static int huft_build(unsigned int *b, const unsigned int n,
381 * tl, td: literal/length and distance decoder tables 424 * tl, td: literal/length and distance decoder tables
382 * bl, bd: number of bits decoded by tl[] and td[] 425 * bl, bd: number of bits decoded by tl[] and td[]
383 */ 426 */
384static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd) 427static int inflate_codes(huft_t * tl, huft_t * td, const unsigned int bl, const unsigned int bd)
385{ 428{
386 register unsigned long e; /* table entry flag/number of extra bits */ 429 unsigned int e; /* table entry flag/number of extra bits */
387 unsigned long n, d; /* length and index for copy */ 430 unsigned int n, d; /* length and index for copy */
388 unsigned long w; /* current window position */ 431 unsigned int w; /* current gunzip_window position */
389 huft_t *t; /* pointer to table entry */ 432 huft_t *t; /* pointer to table entry */
390 unsigned ml, md; /* masks for bl and bd bits */ 433 unsigned int ml, md; /* masks for bl and bd bits */
391 register unsigned long b; /* bit buffer */ 434 unsigned int b; /* bit buffer */
392 register unsigned k; /* number of bits in bit buffer */ 435 unsigned int k; /* number of bits in bit buffer */
393 register int input_char;
394 436
395 /* make local copies of globals */ 437 /* make local copies of globals */
396 b = bb; /* initialize bit buffer */ 438 b = gunzip_bb; /* initialize bit buffer */
397 k = bk; 439 k = gunzip_bk;
398 w = outcnt; /* initialize window position */ 440 w = gunzip_outbuf_count; /* initialize gunzip_window position */
399 441
400 /* inflate the coded data */ 442 /* inflate the coded data */
401 ml = mask_bits[bl]; /* precompute masks for speed */ 443 ml = mask_bits[bl]; /* precompute masks for speed */
402 md = mask_bits[bd]; 444 md = mask_bits[bd];
403 for (;;) { /* do until end of block */ 445 while (1) { /* do until end of block */
404 while (k < (unsigned) bl) { 446 b = fill_bitbuffer(b, &k, bl);
405 input_char = fgetc(in_file);
406 if (input_char == EOF) return 1;
407 b |= ((unsigned long)input_char) << k;
408 k += 8;
409 }
410 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) 447 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
411 do { 448 do {
412 if (e == 99) { 449 if (e == 99) {
@@ -415,20 +452,16 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
415 b >>= t->b; 452 b >>= t->b;
416 k -= t->b; 453 k -= t->b;
417 e -= 16; 454 e -= 16;
418 while (k < e) { 455 b = fill_bitbuffer(b, &k, e);
419 input_char = fgetc(in_file);
420 if (input_char == EOF) return 1;
421 b |= ((unsigned long)input_char) << k;
422 k += 8;
423 }
424 } while ((e = 456 } while ((e =
425 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); 457 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
426 b >>= t->b; 458 b >>= t->b;
427 k -= t->b; 459 k -= t->b;
428 if (e == 16) { /* then it's a literal */ 460 if (e == 16) { /* then it's a literal */
429 window[w++] = (unsigned char) t->v.n; 461 gunzip_window[w++] = (unsigned char) t->v.n;
430 if (w == WSIZE) { 462 if (w == gunzip_wsize) {
431 outcnt = (w), flush_window(); 463 gunzip_outbuf_count = (w);
464 flush_gunzip_window();
432 w = 0; 465 w = 0;
433 } 466 }
434 } else { /* it's an EOB or a length */ 467 } else { /* it's an EOB or a length */
@@ -439,24 +472,13 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
439 } 472 }
440 473
441 /* get length of block to copy */ 474 /* get length of block to copy */
442 while (k < e) { 475 b = fill_bitbuffer(b, &k, e);
443 input_char = fgetc(in_file);
444 if (input_char == EOF) return 1;
445 b |= ((unsigned long)input_char) << k;
446 k += 8;
447 }
448 n = t->v.n + ((unsigned) b & mask_bits[e]); 476 n = t->v.n + ((unsigned) b & mask_bits[e]);
449 b >>= e; 477 b >>= e;
450 k -= e; 478 k -= e;
451 479
452 /* decode distance of block to copy */ 480 /* decode distance of block to copy */
453 while (k < (unsigned) bd) { 481 b = fill_bitbuffer(b, &k, bd);
454 input_char = fgetc(in_file);
455 if (input_char == EOF) return 1;
456 b |= ((unsigned long)input_char) << k;
457 k += 8;
458 }
459
460 if ((e = (t = td + ((unsigned) b & md))->e) > 16) 482 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
461 do { 483 do {
462 if (e == 99) 484 if (e == 99)
@@ -464,23 +486,13 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
464 b >>= t->b; 486 b >>= t->b;
465 k -= t->b; 487 k -= t->b;
466 e -= 16; 488 e -= 16;
467 while (k < e) { 489 b = fill_bitbuffer(b, &k, e);
468 input_char = fgetc(in_file);
469 if (input_char == EOF) return 1;
470 b |= ((unsigned long)input_char) << k;
471 k += 8;
472 }
473 } while ((e = 490 } while ((e =
474 (t = 491 (t =
475 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); 492 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
476 b >>= t->b; 493 b >>= t->b;
477 k -= t->b; 494 k -= t->b;
478 while (k < e) { 495 b = fill_bitbuffer(b, &k, e);
479 input_char = fgetc(in_file);
480 if (input_char == EOF) return 1;
481 b |= ((unsigned long)input_char) << k;
482 k += 8;
483 }
484 d = w - t->v.n - ((unsigned) b & mask_bits[e]); 496 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
485 b >>= e; 497 b >>= e;
486 k -= e; 498 k -= e;
@@ -489,60 +501,38 @@ static int inflate_codes(huft_t * tl, huft_t * td, int bl, int bd)
489 do { 501 do {
490 n -= (e = 502 n -= (e =
491 (e = 503 (e =
492 WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n : e); 504 gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
493#if !defined(NOMEMCPY) && !defined(DEBUG) 505 /* copy to new buffer to prevent possible overwrite */
494 if (w - d >= e) { /* (this test assumes unsigned comparison) */ 506 if (w - d >= e) { /* (this test assumes unsigned comparison) */
495 memcpy(window + w, window + d, e); 507 memcpy(gunzip_window + w, gunzip_window + d, e);
496 w += e; 508 w += e;
497 d += e; 509 d += e;
498 } else /* do it slow to avoid memcpy() overlap */ 510 } else {
499#endif /* !NOMEMCPY */ 511 /* do it slow to avoid memcpy() overlap */
512 /* !NOMEMCPY */
500 do { 513 do {
501 window[w++] = window[d++]; 514 gunzip_window[w++] = gunzip_window[d++];
502 } while (--e); 515 } while (--e);
503 if (w == WSIZE) { 516 }
504 outcnt = (w), flush_window(); 517 if (w == gunzip_wsize) {
518 gunzip_outbuf_count = (w);
519 flush_gunzip_window();
505 w = 0; 520 w = 0;
506 } 521 }
522
507 } while (n); 523 } while (n);
508 } 524 }
509 } 525 }
510 526
511 /* restore the globals from the locals */ 527 /* restore the globals from the locals */
512 outcnt = w; /* restore global window pointer */ 528 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
513 bb = b; /* restore global bit buffer */ 529 gunzip_bb = b; /* restore global bit buffer */
514 bk = k; 530 gunzip_bk = k;
515 531
516 /* done */ 532 /* done */
517 return 0; 533 return 0;
518} 534}
519 535
520static const unsigned short cplens[] = { /* Copy lengths for literal codes 257..285 */
521 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
522 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
523};
524
525/* note: see note #13 above about the 258 in this list. */
526static const extra_bits_t cplext[] = { /* Extra bits for literal codes 257..285 */
527 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
528 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
529}; /* 99==invalid */
530static const unsigned short cpdist[] = { /* Copy offsets for distance codes 0..29 */
531 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
532 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
533 8193, 12289, 16385, 24577
534};
535static const extra_bits_t cpdext[] = { /* Extra bits for distance codes */
536 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
537 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
538 12, 12, 13, 13
539};
540
541/* Tables for deflate from PKZIP's appnote.txt. */
542static const extra_bits_t border[] = { /* Order of the bit length code lengths */
543 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
544};
545
546/* 536/*
547 * decompress an inflated block 537 * decompress an inflated block
548 * e: last block flag 538 * e: last block flag
@@ -552,53 +542,43 @@ static const extra_bits_t border[] = { /* Order of the bit length code lengths *
552static int inflate_block(int *e) 542static int inflate_block(int *e)
553{ 543{
554 unsigned t; /* block type */ 544 unsigned t; /* block type */
555 register unsigned long b; /* bit buffer */ 545 register unsigned int b; /* bit buffer */
556 register unsigned k; /* number of bits in bit buffer */ 546 unsigned int k; /* number of bits in bit buffer */
557 int input_char;
558 547
559 /* make local bit buffer */ 548 /* make local bit buffer */
560 b = bb; 549
561 k = bk; 550 b = gunzip_bb;
551 k = gunzip_bk;
562 552
563 /* read in last block bit */ 553 /* read in last block bit */
564 while (k < 1) { 554 b = fill_bitbuffer(b, &k, 1);
565 input_char = fgetc(in_file);
566 if (input_char == EOF) return 1;
567 b |= ((unsigned long)input_char) << k;
568 k += 8;
569 }
570 *e = (int) b & 1; 555 *e = (int) b & 1;
571 b >>= 1; 556 b >>= 1;
572 k -= 1; 557 k -= 1;
573 558
574 /* read in block type */ 559 /* read in block type */
575 while (k < 2) { 560 b = fill_bitbuffer(b, &k, 2);
576 input_char = fgetc(in_file);
577 if (input_char == EOF) return 1;
578 b |= ((unsigned long)input_char) << k;
579 k += 8;
580 }
581 t = (unsigned) b & 3; 561 t = (unsigned) b & 3;
582 b >>= 2; 562 b >>= 2;
583 k -= 2; 563 k -= 2;
584 564
585 /* restore the global bit buffer */ 565 /* restore the global bit buffer */
586 bb = b; 566 gunzip_bb = b;
587 bk = k; 567 gunzip_bk = k;
588 568
589 /* inflate that block type */ 569 /* inflate that block type */
590 switch (t) { 570 switch (t) {
591 case 0: /* Inflate stored */ 571 case 0: /* Inflate stored */
592 { 572 {
593 unsigned long n; /* number of bytes in block */ 573 unsigned int n; /* number of bytes in block */
594 unsigned long w; /* current window position */ 574 unsigned int w; /* current gunzip_window position */
595 register unsigned long b_stored; /* bit buffer */ 575 unsigned int b_stored; /* bit buffer */
596 register unsigned long k_stored; /* number of bits in bit buffer */ 576 unsigned int k_stored; /* number of bits in bit buffer */
597 577
598 /* make local copies of globals */ 578 /* make local copies of globals */
599 b_stored = bb; /* initialize bit buffer */ 579 b_stored = gunzip_bb; /* initialize bit buffer */
600 k_stored = bk; 580 k_stored = gunzip_bk;
601 w = outcnt; /* initialize window position */ 581 w = gunzip_outbuf_count; /* initialize gunzip_window position */
602 582
603 /* go to byte boundary */ 583 /* go to byte boundary */
604 n = k_stored & 7; 584 n = k_stored & 7;
@@ -606,21 +586,12 @@ static int inflate_block(int *e)
606 k_stored -= n; 586 k_stored -= n;
607 587
608 /* get the length and its complement */ 588 /* get the length and its complement */
609 while (k_stored < 16) { 589 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
610 input_char = fgetc(in_file);
611 if (input_char == EOF) return 1;
612 b_stored |= ((unsigned long)input_char) << k_stored;
613 k_stored += 8;
614 }
615 n = ((unsigned) b_stored & 0xffff); 590 n = ((unsigned) b_stored & 0xffff);
616 b_stored >>= 16; 591 b_stored >>= 16;
617 k_stored -= 16; 592 k_stored -= 16;
618 while (k_stored < 16) { 593
619 input_char = fgetc(in_file); 594 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
620 if (input_char == EOF) return 1;
621 b_stored |= ((unsigned long)input_char) << k_stored;
622 k_stored += 8;
623 }
624 if (n != (unsigned) ((~b_stored) & 0xffff)) { 595 if (n != (unsigned) ((~b_stored) & 0xffff)) {
625 return 1; /* error in compressed data */ 596 return 1; /* error in compressed data */
626 } 597 }
@@ -629,15 +600,11 @@ static int inflate_block(int *e)
629 600
630 /* read and output the compressed data */ 601 /* read and output the compressed data */
631 while (n--) { 602 while (n--) {
632 while (k_stored < 8) { 603 b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
633 input_char = fgetc(in_file); 604 gunzip_window[w++] = (unsigned char) b_stored;
634 if (input_char == EOF) return 1; 605 if (w == (unsigned int) gunzip_wsize) {
635 b_stored |= ((unsigned long)input_char) << k_stored; 606 gunzip_outbuf_count = (w);
636 k_stored += 8; 607 flush_gunzip_window();
637 }
638 window[w++] = (unsigned char) b_stored;
639 if (w == (unsigned long) WSIZE) {
640 outcnt = (w), flush_window();
641 w = 0; 608 w = 0;
642 } 609 }
643 b_stored >>= 8; 610 b_stored >>= 8;
@@ -645,9 +612,9 @@ static int inflate_block(int *e)
645 } 612 }
646 613
647 /* restore the globals from the locals */ 614 /* restore the globals from the locals */
648 outcnt = w; /* restore global window pointer */ 615 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
649 bb = b_stored; /* restore global bit buffer */ 616 gunzip_bb = b_stored; /* restore global bit buffer */
650 bk = k_stored; 617 gunzip_bk = k_stored;
651 return 0; 618 return 0;
652 } 619 }
653 case 1: /* Inflate fixed 620 case 1: /* Inflate fixed
@@ -659,8 +626,8 @@ static int inflate_block(int *e)
659 int i; /* temporary variable */ 626 int i; /* temporary variable */
660 huft_t *tl; /* literal/length code table */ 627 huft_t *tl; /* literal/length code table */
661 huft_t *td; /* distance code table */ 628 huft_t *td; /* distance code table */
662 int bl; /* lookup bits for tl */ 629 unsigned int bl; /* lookup bits for tl */
663 int bd; /* lookup bits for td */ 630 unsigned int bd; /* lookup bits for td */
664 unsigned int l[288]; /* length list for huft_build */ 631 unsigned int l[288]; /* length list for huft_build */
665 632
666 /* set up literal table */ 633 /* set up literal table */
@@ -692,8 +659,9 @@ static int inflate_block(int *e)
692 } 659 }
693 660
694 /* decompress until an end-of-block code */ 661 /* decompress until an end-of-block code */
695 if (inflate_codes(tl, td, bl, bd)) 662 if (inflate_codes(tl, td, bl, bd)) {
696 return 1; 663 return 1;
664 }
697 665
698 /* free the decoding tables, return */ 666 /* free the decoding tables, return */
699 huft_free(tl); 667 huft_free(tl);
@@ -705,53 +673,41 @@ static int inflate_block(int *e)
705 const int dbits = 6; /* bits in base distance lookup table */ 673 const int dbits = 6; /* bits in base distance lookup table */
706 const int lbits = 9; /* bits in base literal/length lookup table */ 674 const int lbits = 9; /* bits in base literal/length lookup table */
707 675
708 int i; /* temporary variables */
709 unsigned j;
710 unsigned l; /* last length */
711 unsigned m; /* mask for bit lengths table */
712 unsigned n; /* number of lengths to get */
713 huft_t *tl; /* literal/length code table */ 676 huft_t *tl; /* literal/length code table */
714 huft_t *td; /* distance code table */ 677 huft_t *td; /* distance code table */
715 int bl; /* lookup bits for tl */ 678 unsigned int i; /* temporary variables */
716 int bd; /* lookup bits for td */ 679 unsigned int j;
717 unsigned nb; /* number of bit length codes */ 680 unsigned int l; /* last length */
718 unsigned nl; /* number of literal/length codes */ 681 unsigned int m; /* mask for bit lengths table */
719 unsigned nd; /* number of distance codes */ 682 unsigned int n; /* number of lengths to get */
720 683 unsigned int bl; /* lookup bits for tl */
721 unsigned ll[286 + 30]; /* literal/length and distance code lengths */ 684 unsigned int bd; /* lookup bits for td */
722 register unsigned long b_dynamic; /* bit buffer */ 685 unsigned int nb; /* number of bit length codes */
723 register unsigned k_dynamic; /* number of bits in bit buffer */ 686 unsigned int nl; /* number of literal/length codes */
687 unsigned int nd; /* number of distance codes */
688
689 unsigned int ll[286 + 30]; /* literal/length and distance code lengths */
690 unsigned int b_dynamic; /* bit buffer */
691 unsigned int k_dynamic; /* number of bits in bit buffer */
724 692
725 /* make local bit buffer */ 693 /* make local bit buffer */
726 b_dynamic = bb; 694 b_dynamic = gunzip_bb;
727 k_dynamic = bk; 695 k_dynamic = gunzip_bk;
728 696
729 /* read in table lengths */ 697 /* read in table lengths */
730 while (k_dynamic < 5) { 698 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
731 input_char = fgetc(in_file); 699 nl = 257 + ((unsigned int) b_dynamic & 0x1f); /* number of literal/length codes */
732 if (input_char == EOF) return 1; 700
733 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
734 k_dynamic += 8;
735 }
736 nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */
737 b_dynamic >>= 5; 701 b_dynamic >>= 5;
738 k_dynamic -= 5; 702 k_dynamic -= 5;
739 while (k_dynamic < 5) { 703 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
740 input_char = fgetc(in_file); 704 nd = 1 + ((unsigned int) b_dynamic & 0x1f); /* number of distance codes */
741 if (input_char == EOF) return 1; 705
742 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
743 k_dynamic += 8;
744 }
745 nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */
746 b_dynamic >>= 5; 706 b_dynamic >>= 5;
747 k_dynamic -= 5; 707 k_dynamic -= 5;
748 while (k_dynamic < 4) { 708 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 4);
749 input_char = fgetc(in_file); 709 nb = 4 + ((unsigned int) b_dynamic & 0xf); /* number of bit length codes */
750 if (input_char == EOF) return 1; 710
751 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
752 k_dynamic += 8;
753 }
754 nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */
755 b_dynamic >>= 4; 711 b_dynamic >>= 4;
756 k_dynamic -= 4; 712 k_dynamic -= 4;
757 if (nl > 286 || nd > 30) { 713 if (nl > 286 || nd > 30) {
@@ -760,13 +716,8 @@ static int inflate_block(int *e)
760 716
761 /* read in bit-length-code lengths */ 717 /* read in bit-length-code lengths */
762 for (j = 0; j < nb; j++) { 718 for (j = 0; j < nb; j++) {
763 while (k_dynamic < 3) { 719 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
764 input_char = fgetc(in_file); 720 ll[border[j]] = (unsigned int) b_dynamic & 7;
765 if (input_char == EOF) return 1;
766 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
767 k_dynamic += 8;
768 }
769 ll[border[j]] = (unsigned) b_dynamic & 7;
770 b_dynamic >>= 3; 721 b_dynamic >>= 3;
771 k_dynamic -= 3; 722 k_dynamic -= 3;
772 } 723 }
@@ -776,7 +727,8 @@ static int inflate_block(int *e)
776 727
777 /* build decoding table for trees--single level, 7 bit lookup */ 728 /* build decoding table for trees--single level, 7 bit lookup */
778 bl = 7; 729 bl = 7;
779 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) { 730 i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl);
731 if (i != 0) {
780 if (i == 1) { 732 if (i == 1) {
781 huft_free(tl); 733 huft_free(tl);
782 } 734 }
@@ -787,46 +739,31 @@ static int inflate_block(int *e)
787 n = nl + nd; 739 n = nl + nd;
788 m = mask_bits[bl]; 740 m = mask_bits[bl];
789 i = l = 0; 741 i = l = 0;
790 while ((unsigned) i < n) { 742 while ((unsigned int) i < n) {
791 while (k_dynamic < (unsigned) bl) { 743 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, (unsigned int)bl);
792 input_char = fgetc(in_file); 744 j = (td = tl + ((unsigned int) b_dynamic & m))->b;
793 if (input_char == EOF) return 1;
794 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
795 k_dynamic += 8;
796 }
797 j = (td = tl + ((unsigned) b_dynamic & m))->b;
798 b_dynamic >>= j; 745 b_dynamic >>= j;
799 k_dynamic -= j; 746 k_dynamic -= j;
800 j = td->v.n; 747 j = td->v.n;
801 if (j < 16) { /* length of code in bits (0..15) */ 748 if (j < 16) { /* length of code in bits (0..15) */
802 ll[i++] = l = j; /* save last length in l */ 749 ll[i++] = l = j; /* save last length in l */
803 } else if (j == 16) { /* repeat last length 3 to 6 times */ 750 } else if (j == 16) { /* repeat last length 3 to 6 times */
804 while (k_dynamic < 2) { 751 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 2);
805 input_char = fgetc(in_file); 752 j = 3 + ((unsigned int) b_dynamic & 3);
806 if (input_char == EOF) return 1;
807 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
808 k_dynamic += 8;
809 }
810 j = 3 + ((unsigned) b_dynamic & 3);
811 b_dynamic >>= 2; 753 b_dynamic >>= 2;
812 k_dynamic -= 2; 754 k_dynamic -= 2;
813 if ((unsigned) i + j > n) { 755 if ((unsigned int) i + j > n) {
814 return 1; 756 return 1;
815 } 757 }
816 while (j--) { 758 while (j--) {
817 ll[i++] = l; 759 ll[i++] = l;
818 } 760 }
819 } else if (j == 17) { /* 3 to 10 zero length codes */ 761 } else if (j == 17) { /* 3 to 10 zero length codes */
820 while (k_dynamic < 3) { 762 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
821 input_char = fgetc(in_file); 763 j = 3 + ((unsigned int) b_dynamic & 7);
822 if (input_char == EOF) return 1;
823 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
824 k_dynamic += 8;
825 }
826 j = 3 + ((unsigned) b_dynamic & 7);
827 b_dynamic >>= 3; 764 b_dynamic >>= 3;
828 k_dynamic -= 3; 765 k_dynamic -= 3;
829 if ((unsigned) i + j > n) { 766 if ((unsigned int) i + j > n) {
830 return 1; 767 return 1;
831 } 768 }
832 while (j--) { 769 while (j--) {
@@ -834,16 +771,11 @@ static int inflate_block(int *e)
834 } 771 }
835 l = 0; 772 l = 0;
836 } else { /* j == 18: 11 to 138 zero length codes */ 773 } else { /* j == 18: 11 to 138 zero length codes */
837 while (k_dynamic < 7) { 774 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 7);
838 input_char = fgetc(in_file); 775 j = 11 + ((unsigned int) b_dynamic & 0x7f);
839 if (input_char == EOF) return 1;
840 b_dynamic |= ((unsigned long)input_char) << k_dynamic;
841 k_dynamic += 8;
842 }
843 j = 11 + ((unsigned) b_dynamic & 0x7f);
844 b_dynamic >>= 7; 776 b_dynamic >>= 7;
845 k_dynamic -= 7; 777 k_dynamic -= 7;
846 if ((unsigned) i + j > n) { 778 if ((unsigned int) i + j > n) {
847 return 1; 779 return 1;
848 } 780 }
849 while (j--) { 781 while (j--) {
@@ -857,22 +789,24 @@ static int inflate_block(int *e)
857 huft_free(tl); 789 huft_free(tl);
858 790
859 /* restore the global bit buffer */ 791 /* restore the global bit buffer */
860 bb = b_dynamic; 792 gunzip_bb = b_dynamic;
861 bk = k_dynamic; 793 gunzip_bk = k_dynamic;
862 794
863 /* build the decoding tables for literal/length and distance codes */ 795 /* build the decoding tables for literal/length and distance codes */
864 bl = lbits; 796 bl = lbits;
797
865 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) { 798 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
866 if (i == 1) { 799 if (i == 1) {
867 error_msg("Incomplete literal tree"); 800 error_msg_and_die("Incomplete literal tree");
868 huft_free(tl); 801 huft_free(tl);
869 } 802 }
870 return i; /* incomplete code set */ 803 return i; /* incomplete code set */
871 } 804 }
805
872 bd = dbits; 806 bd = dbits;
873 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) { 807 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
874 if (i == 1) { 808 if (i == 1) {
875 error_msg("incomplete distance tree"); 809 error_msg_and_die("incomplete distance tree");
876 huft_free(td); 810 huft_free(td);
877 } 811 }
878 huft_free(tl); 812 huft_free(tl);
@@ -880,8 +814,9 @@ static int inflate_block(int *e)
880 } 814 }
881 815
882 /* decompress until an end-of-block code */ 816 /* decompress until an end-of-block code */
883 if (inflate_codes(tl, td, bl, bd)) 817 if (inflate_codes(tl, td, bl, bd)) {
884 return 1; 818 return 1;
819 }
885 820
886 /* free the decoding tables, return */ 821 /* free the decoding tables, return */
887 huft_free(tl); 822 huft_free(tl);
@@ -890,6 +825,7 @@ static int inflate_block(int *e)
890 } 825 }
891 default: 826 default:
892 /* bad block type */ 827 /* bad block type */
828 error_msg("bad block type %d\n", t);
893 return 2; 829 return 2;
894 } 830 }
895} 831}
@@ -897,72 +833,24 @@ static int inflate_block(int *e)
897/* 833/*
898 * decompress an inflated entry 834 * decompress an inflated entry
899 * 835 *
900 * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr 836 * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr
901 */ 837 */
902extern int inflate(FILE * in, FILE * out) 838extern int inflate(int in, int out)
903{ 839{
840 typedef void (*sig_type) (int);
904 int e; /* last block flag */ 841 int e; /* last block flag */
905 int r; /* result code */ 842 int r; /* result code */
906 unsigned h = 0; /* maximum struct huft's malloc'ed */ 843 unsigned h = 0; /* maximum struct huft's malloc'ed */
907 844
908 /* initialize window, bit buffer */
909 outcnt = 0;
910 bk = 0;
911 bb = 0;
912
913 in_file = in;
914 out_file = out;
915
916 /* Allocate all global buffers (for DYN_ALLOC option) */ 845 /* Allocate all global buffers (for DYN_ALLOC option) */
917 window = xmalloc((size_t) (((2L * WSIZE) + 1L) * sizeof(unsigned char))); 846 gunzip_window = xmalloc(0x8000);
918 bytes_out = 0L; 847 gunzip_outbuf_count = 0;
848 gunzip_bytes_out = 0;
919 849
920 /* Create the crc table */ 850 gunzip_src_fd = in;
921 make_crc_table(); 851 gunzip_dst_fd = out;
922 852
923 /* decompress until the last block */ 853 gunzip_in_buffer = malloc(8);
924 do {
925 hufts = 0;
926 if ((r = inflate_block(&e)) != 0) {
927 return r;
928 }
929 if (hufts > h) {
930 h = hufts;
931 }
932 } while (!e);
933
934 /* Undo too much lookahead. The next read will be byte aligned so we
935 * can discard unused bits in the last meaningful byte.
936 */
937 while (bk >= 8) {
938 bk -= 8;
939 ungetc((bb << bk), in_file);
940 }
941
942 /* flush out window */
943 flush_window();
944 free(window);
945 free(crc_table);
946
947 /* return success */
948 return 0;
949}
950
951/* ===========================================================================
952 * Unzip in to out. This routine works on gzip files only.
953 *
954 * IN assertions: the buffer inbuf contains already the beginning of
955 * the compressed data, from offsets inptr to insize-1 included.
956 * The magic header has already been checked. The output buffer is cleared.
957 * in, out: input and output file descriptors
958 */
959extern int unzip(FILE * l_in_file, FILE * l_out_file)
960{
961 unsigned char buf[8]; /* extended local header */
962 unsigned char flags; /* compression flags */
963 typedef void (*sig_type) (int);
964 unsigned short i;
965 unsigned char magic[2];
966 854
967 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 855 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
968 (void) signal(SIGINT, (sig_type) abort_gzip); 856 (void) signal(SIGINT, (sig_type) abort_gzip);
@@ -973,97 +861,44 @@ extern int unzip(FILE * l_in_file, FILE * l_out_file)
973 } 861 }
974#endif 862#endif
975 863
976 magic[0] = fgetc(l_in_file); 864 /* initialize gunzip_window, bit buffer */
977 magic[1] = fgetc(l_in_file); 865 gunzip_bk = 0;
978 866 gunzip_bb = 0;
979#ifdef CONFIG_FEATURE_UNCOMPRESS
980 /* Magic header for compress files, 1F 9d = \037\235 */
981 if ((magic[0] == 0x1F) && (magic[1] == 0x9d)) {
982 return uncompress(l_in_file, l_out_file);
983 }
984#endif
985
986 /* Magic header for gzip files, 1F 8B = \037\213 */
987 if ((magic[0] != 0x1F) || (magic[1] != 0x8b)) {
988 error_msg("Invalid gzip magic");
989 return EXIT_FAILURE;
990 }
991
992 /* Check the compression method */
993 if (fgetc(l_in_file) != 8) /* also catches EOF */ {
994 error_msg("Unknown compression method");
995 return (-1);
996 }
997
998 flags = (unsigned char) fgetc(l_in_file);
999
1000 /* Ignore time stamp(4), extra flags(1), OS type(1) */
1001 for (i = 0; i < 6; i++) {
1002 fgetc(l_in_file);
1003 }
1004 867
1005 if (flags & 0x04) { 868 /* Create the crc table */
1006 /* bit 2 set: extra field present */ 869 make_gunzip_crc_table();
1007 const unsigned short extra =
1008 fgetc(l_in_file) + (fgetc(l_in_file) << 8);
1009 if (feof(in_file)) return 1;
1010 for (i = 0; i < extra; i++) {
1011 fgetc(l_in_file);
1012 }
1013 }
1014
1015 /* Discard original name if any */
1016 if (flags & 0x08) {
1017 /* bit 3 set: original file name present */
1018 while (fgetc(l_in_file) != 0 && !feof(l_in_file)); /* null */
1019 }
1020 870
1021 /* Discard file comment if any */ 871 /* decompress until the last block */
1022 if (flags & 0x10) { 872 do {
1023 /* bit 4 set: file comment present */ 873 gunzip_hufts = 0;
1024 while (fgetc(l_in_file) != 0 && !feof(l_in_file)); /* null */ 874 r = inflate_block(&e);
875 if (r != 0) {
876 error_msg_and_die("inflate error %d", r);
877 return r;
1025 } 878 }
1026 879 if (gunzip_hufts > h) {
1027 /* Decompress */ 880 h = gunzip_hufts;
1028 if (inflate(l_in_file, l_out_file) != 0) {
1029 error_msg("invalid compressed data--format violated");
1030 } 881 }
882 } while (!e);
1031 883
1032 /* Get the crc and original length 884 /* write any buffered uncompressed data */
1033 * crc32 (see algorithm.doc) 885 flush_gunzip_window();
1034 * uncompressed input size modulo 2^32 886 free(gunzip_window);
1035 */ 887
1036 fread(buf, 1, 8, l_in_file); 888 /* Cleanup */
1037 889 free(gunzip_crc_table);
1038 /* Validate decompression - crc */ 890
1039 if ((unsigned int) ((buf[0] | (buf[1] << 8)) | 891 /* Store unused bytes in a global buffer so calling applets can access it */
1040 ((buf[2] | (buf[3] << 8)) << 16)) != 892 gunzip_in_buffer_count = 0;
1041 (crc ^ 0xffffffffL)) { 893 if (gunzip_bk >= 8) {
1042 error_msg("invalid compressed data--crc error"); 894 /* Undo too much lookahead. The next read will be byte aligned
1043 } 895 * so we can discard unused bits in the last meaningful byte. */
1044 /* Validate decompression - size */ 896 gunzip_in_buffer[gunzip_in_buffer_count] = gunzip_bb & 0xff;
1045 if (((buf[4] | (buf[5] << 8)) | ((buf[6] | (buf[7] << 8)) << 16)) != 897 gunzip_in_buffer_count++;
1046 (unsigned long) bytes_out) { 898 gunzip_bb >>= 8;
1047 error_msg("invalid compressed data--length error"); 899 gunzip_bk -= 8;
1048 } 900 }
1049 901
902 /* return success */
1050 return 0; 903 return 0;
1051} 904}
1052
1053/*
1054 * This needs access to global variables window and crc_table, so its not in its own file.
1055 */
1056extern void gz_close(int gunzip_pid)
1057{
1058 if (kill(gunzip_pid, SIGTERM) == -1) {
1059 error_msg_and_die
1060 ("*** Couldnt kill old gunzip process *** aborting");
1061 }
1062
1063 if (waitpid(gunzip_pid, NULL, 0) == -1) {
1064 printf("Couldnt wait ?");
1065 }
1066
1067 free(window);
1068 free(crc_table);
1069}
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 869c04a4c..2249e263a 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -19,10 +19,13 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#include <sys/types.h>
23#include <sys/stat.h>
22#include <stdio.h> 24#include <stdio.h>
23#include <string.h> 25#include <string.h>
24#include <stdlib.h> 26#include <stdlib.h>
25#include <unistd.h> 27#include <unistd.h>
28#include <fcntl.h>
26#include "libbb.h" 29#include "libbb.h"
27 30
28 31
@@ -85,6 +88,59 @@ FILE *xfopen(const char *path, const char *mode)
85 return fp; 88 return fp;
86} 89}
87 90
91extern int xopen(const char *pathname, int flags)
92{
93 int ret;
94
95 ret = open(pathname, flags);
96 if (ret == -1) {
97 perror_msg_and_die("%s", pathname);
98 }
99 return ret;
100}
101
102extern ssize_t xread(int fd, void *buf, size_t count)
103{
104 ssize_t size;
105
106 size = read(fd, buf, count);
107 if (size == -1) {
108 perror_msg_and_die("Read error");
109 }
110 return(size);
111}
112
113extern void xread_all(int fd, void *buf, size_t count)
114{
115 ssize_t size;
116
117 size = xread(fd, buf, count);
118 if (size != count) {
119 error_msg_and_die("Short read");
120 }
121 return;
122}
123
124extern ssize_t xread_all_eof(int fd, void *buf, size_t count)
125{
126 ssize_t size;
127
128 size = xread(fd, buf, count);
129 if ((size != 0) && (size != count)) {
130 error_msg_and_die("Short read");
131 }
132 return(size);
133}
134
135extern unsigned char xread_char(int fd)
136{
137 char tmp;
138
139 xread_all(fd, &tmp, 1);
140
141 return(tmp);
142}
143
88/* Stupid gcc always includes its own builtin strlen()... */ 144/* Stupid gcc always includes its own builtin strlen()... */
89#undef strlen 145#undef strlen
90size_t xstrlen(const char *string) 146size_t xstrlen(const char *string)