summaryrefslogtreecommitdiff
path: root/busybox/archival
diff options
context:
space:
mode:
authornobody <nobody@localhost>2004-10-13 09:42:10 +0000
committernobody <nobody@localhost>2004-10-13 09:42:10 +0000
commit8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373 (patch)
tree1826706cd4fd009fcd14f4f8021005ec8ec0fa59 /busybox/archival
downloadbusybox-w32-8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373.tar.gz
busybox-w32-8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373.tar.bz2
busybox-w32-8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373.zip
This commit was manufactured by cvs2svn to create tag 'busybox_1_00'.
Diffstat (limited to 'busybox/archival')
-rw-r--r--busybox/archival/Config.in258
-rw-r--r--busybox/archival/Makefile32
-rw-r--r--busybox/archival/Makefile.in48
-rw-r--r--busybox/archival/ar.c110
-rw-r--r--busybox/archival/bunzip2.c91
-rw-r--r--busybox/archival/cpio.c99
-rw-r--r--busybox/archival/dpkg.c1833
-rw-r--r--busybox/archival/dpkg_deb.c112
-rw-r--r--busybox/archival/gunzip.c198
-rw-r--r--busybox/archival/gzip.c2548
-rw-r--r--busybox/archival/libunarchive/Makefile32
-rw-r--r--busybox/archival/libunarchive/Makefile.in84
-rw-r--r--busybox/archival/libunarchive/archive_xread_all.c32
-rw-r--r--busybox/archival/libunarchive/archive_xread_all_eof.c32
-rw-r--r--busybox/archival/libunarchive/check_header_gzip.c57
-rw-r--r--busybox/archival/libunarchive/data_align.c33
-rw-r--r--busybox/archival/libunarchive/data_extract_all.c124
-rw-r--r--busybox/archival/libunarchive/data_extract_to_buffer.c28
-rw-r--r--busybox/archival/libunarchive/data_extract_to_stdout.c23
-rw-r--r--busybox/archival/libunarchive/data_skip.c27
-rw-r--r--busybox/archival/libunarchive/decompress_bunzip2.c611
-rw-r--r--busybox/archival/libunarchive/decompress_uncompress.c293
-rw-r--r--busybox/archival/libunarchive/decompress_unzip.c982
-rw-r--r--busybox/archival/libunarchive/filter_accept_all.c32
-rw-r--r--busybox/archival/libunarchive/filter_accept_list.c34
-rw-r--r--busybox/archival/libunarchive/filter_accept_list_reassign.c55
-rw-r--r--busybox/archival/libunarchive/filter_accept_reject_list.c45
-rw-r--r--busybox/archival/libunarchive/find_list_entry.c30
-rw-r--r--busybox/archival/libunarchive/get_header_ar.c126
-rw-r--r--busybox/archival/libunarchive/get_header_cpio.c161
-rw-r--r--busybox/archival/libunarchive/get_header_tar.c215
-rw-r--r--busybox/archival/libunarchive/get_header_tar_bz2.c38
-rw-r--r--busybox/archival/libunarchive/get_header_tar_gz.c42
-rw-r--r--busybox/archival/libunarchive/header_list.c7
-rw-r--r--busybox/archival/libunarchive/header_skip.c7
-rw-r--r--busybox/archival/libunarchive/header_verbose_list.c29
-rw-r--r--busybox/archival/libunarchive/init_handle.c36
-rw-r--r--busybox/archival/libunarchive/open_transformer.c51
-rw-r--r--busybox/archival/libunarchive/seek_by_char.c32
-rw-r--r--busybox/archival/libunarchive/seek_by_jump.c35
-rw-r--r--busybox/archival/libunarchive/unpack_ar_archive.c34
-rw-r--r--busybox/archival/rpm.c349
-rw-r--r--busybox/archival/rpm2cpio.c106
-rw-r--r--busybox/archival/tar.c891
-rw-r--r--busybox/archival/uncompress.c115
-rw-r--r--busybox/archival/unzip.c247
46 files changed, 10404 insertions, 0 deletions
diff --git a/busybox/archival/Config.in b/busybox/archival/Config.in
new file mode 100644
index 000000000..db358db08
--- /dev/null
+++ b/busybox/archival/Config.in
@@ -0,0 +1,258 @@
1#
2# For a description of the syntax of this configuration file,
3# see scripts/kbuild/config-language.txt.
4#
5
6menu "Archival Utilities"
7
8config CONFIG_AR
9 bool "ar"
10 default n
11 help
12 ar is an archival utility program used to create, modify, and
13 extract contents from archives. An archive is a single file holding
14 a collection of other files in a structure that makes it possible to
15 retrieve the original individual files (called archive members).
16 The original files' contents, mode (permissions), timestamp, owner,
17 and group are preserved in the archive, and can be restored on
18 extraction.
19
20 The stored filename is limited to 15 characters. (for more information
21 see long filename support).
22 ar has 60 bytes of overheads for every stored file.
23
24 This implementation of ar can extract archives, it cannot create or
25 modify them.
26 On an x86 system, the ar applet adds about 1K.
27
28 Unless you have a specific application which requires ar, you should
29 probably say N here.
30
31config CONFIG_FEATURE_AR_LONG_FILENAMES
32 bool " Enable support for long filenames (not need for debs)"
33 default n
34 depends on CONFIG_AR
35 help
36 By default the ar format can only store the first 15 characters of the
37 filename, this option removes that limitation.
38 It supports the GNU ar long filename method which moves multiple long
39 filenames into a the data section of a new ar entry.
40
41config CONFIG_BUNZIP2
42 bool "bunzip2"
43 default n
44 help
45 bunzip2 is a compression utility using the Burrows-Wheeler block
46 sorting text compression algorithm, and Huffman coding. Compression
47 is generally considerably better than that achieved by more
48 conventional LZ77/LZ78-based compressors, and approaches the
49 performance of the PPM family of statistical compressors.
50
51 The BusyBox bunzip2 applet is limited to de-compression only.
52 On an x86 system, this applet adds about 11K.
53
54 Unless you have a specific application which requires bunzip2, you
55 should probably say N here.
56
57config CONFIG_CPIO
58 bool "cpio"
59 default n
60 help
61 cpio is an archival utility program used to create, modify, and extract
62 contents from archives.
63 cpio has 110 bytes of overheads for every stored file.
64
65 This implementation of cpio can extract cpio archives created in the
66 "newc" or "crc" format, it cannot create or modify them.
67
68 Unless you have a specific application which requires cpio, you should
69 probably say N here.
70
71config CONFIG_DPKG
72 bool "dpkg"
73 default n
74 help
75 dpkg is a medium-level tool to install, build, remove and manage Debian packages.
76
77 This implementation of dpkg has a number of limitations, you should use the
78 official dpkg if possible.
79
80config CONFIG_DPKG_DEB
81 bool "dpkg_deb"
82 default n
83 help
84 dpkg-deb packs, unpacks and provides information about Debian archives.
85
86 This implementation of dpkg-deb cannot pack archives.
87
88 Unless you have a specific application which requires dpkg-deb, you should
89 probably say N here.
90
91config CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
92 bool " extract only (-x)"
93 default n
94 depends on CONFIG_DPKG_DEB
95 help
96 This reduces dpkg-deb to the equivalent of "ar -p <deb> data.tar.gz | tar -zx".
97 However it saves space as none of the extra dpkg-deb, ar or tar options are
98 needed, they are linked to internally.
99
100config CONFIG_GUNZIP
101 bool "gunzip"
102 default n
103 help
104 gunzip is used to decompress archives created by gzip.
105 You can use the `-t' option to test the integrity of
106 an archive, without decompressing it.
107
108config CONFIG_FEATURE_GUNZIP_UNCOMPRESS
109 bool " Uncompress support"
110 default n
111 depends on CONFIG_GUNZIP
112 help
113 Enable if you want gunzip to have the ability to decompress
114 archives created by the program compress (not much
115 used anymore).
116
117config CONFIG_GZIP
118 bool "gzip"
119 default n
120 help
121 gzip is used to compress files.
122 It's probably the most widely used UNIX compression program.
123
124config CONFIG_RPM2CPIO
125 bool "rpm2cpio"
126 default n
127 help
128 Converts an RPM file into a CPIO archive.
129
130config CONFIG_RPM
131 bool "rpm"
132 default n
133 help
134 Mini RPM applet - queries and extracts
135
136config CONFIG_TAR
137 bool "tar"
138 default n
139 help
140 tar is an archiving program. It's commonly used with gzip to
141 create compressed archives. It's probably the most widely used
142 UNIX archive program.
143
144config CONFIG_FEATURE_TAR_CREATE
145 bool " Enable archive creation"
146 default y
147 depends on CONFIG_TAR
148 help
149 If you enable this option you'll be able to create
150 tar archives using the `-c' option.
151
152config CONFIG_FEATURE_TAR_BZIP2
153 bool " Enable -j option to handle .tar.bz2 files"
154 default n
155 depends on CONFIG_TAR
156 help
157 If you enable this option you'll be able to extract
158 archives compressed with bzip2.
159
160config CONFIG_FEATURE_TAR_FROM
161 bool " Enable -X (exclude from) and -T (include from) options)"
162 default n
163 depends on CONFIG_TAR
164 help
165 If you enable this option you'll be able to specify
166 a list of files to include or exclude from an archive.
167
168config CONFIG_FEATURE_TAR_GZIP
169 bool " Enable -z option"
170 default y
171 depends on CONFIG_TAR
172 help
173 If you enable this option tar will be able to call gzip,
174 when creating or extracting tar gziped archives.
175
176config CONFIG_FEATURE_TAR_COMPRESS
177 bool " Enable -Z option"
178 default n
179 depends on CONFIG_TAR
180 help
181 If you enable this option tar will be able to call uncompress,
182 when extracting .tar.Z archives.
183
184config CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
185 bool " Enable support for old tar header format"
186 default N
187 depends on CONFIG_TAR
188 help
189 This option is required to unpack archives created in
190 the old GNU format; help to kill this old format by
191 repacking your ancient archives with the new format.
192
193config CONFIG_FEATURE_TAR_GNU_EXTENSIONS
194 bool " Enable support for some GNU tar extensions"
195 default y
196 depends on CONFIG_TAR
197 help
198 With this option busybox supports GNU long filenames and
199 linknames.
200
201config CONFIG_FEATURE_TAR_LONG_OPTIONS
202 bool " Enable long options"
203 default n
204 depends on CONFIG_TAR
205 help
206 Enable use of long options, increases size by about 400 Bytes
207
208config CONFIG_UNCOMPRESS
209 bool "uncompress"
210 default n
211 help
212 uncompress is used to decompress archives created by compress.
213 Not much used anymore, replaced by gzip/gunzip.
214
215config CONFIG_UNZIP
216 bool "unzip"
217 default n
218 help
219 unzip will list or extract files from a ZIP archive,
220 commonly found on DOS/WIN systems. The default behavior
221 (with no options) is to extract the archive into the
222 current directory. Use the `-d' option to extract to a
223 directory of your choice.
224
225comment "Common options for cpio and tar"
226 depends on CONFIG_CPIO || CONFIG_TAR
227
228config CONFIG_FEATURE_UNARCHIVE_TAPE
229 bool " Enable tape drive support"
230 default n
231 depends on CONFIG_CPIO || CONFIG_TAR
232 help
233 I don't think this is needed anymore.
234
235comment "Common options for dpkg and dpkg_deb"
236 depends on CONFIG_DPKG || CONFIG_DPKG_DEB
237
238config CONFIG_FEATURE_DEB_TAR_GZ
239 bool " gzip debian packages (normal)"
240 default y if CONFIG_DPKG || CONFIG_DPKG_DEB
241 depends on CONFIG_DPKG || CONFIG_DPKG_DEB
242 help
243 This is the default compression method inside the debian ar file.
244
245 If you want compatibility with standard .deb's you should say yes here.
246
247config CONFIG_FEATURE_DEB_TAR_BZ2
248 bool " bzip2 debian packages"
249 default n
250 depends on CONFIG_DPKG || CONFIG_DPKG_DEB
251 help
252 This allows dpkg and dpkg-deb to extract deb's that are compressed internally
253 with bzip2 instead of gzip.
254
255 You only want this if you are creating your own custom debian packages that
256 use an internal control.tar.bz2 or data.tar.bz2.
257
258endmenu
diff --git a/busybox/archival/Makefile b/busybox/archival/Makefile
new file mode 100644
index 000000000..a96daa4df
--- /dev/null
+++ b/busybox/archival/Makefile
@@ -0,0 +1,32 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20top_srcdir=..
21top_builddir=..
22ARCHIVAL_DIR:=./
23srcdir=$(top_srcdir)/archival
24include $(top_builddir)/Rules.mak
25include $(top_builddir)/.config
26include $(srcdir)/Makefile.in
27all: $(libraries-y)
28-include $(top_builddir)/.depend
29
30clean:
31 rm -f *.o *.a $(AR_TARGET)
32
diff --git a/busybox/archival/Makefile.in b/busybox/archival/Makefile.in
new file mode 100644
index 000000000..76ab6cd08
--- /dev/null
+++ b/busybox/archival/Makefile.in
@@ -0,0 +1,48 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20ARCHIVAL_AR:=archival.a
21ifndef $(ARCHIVAL_DIR)
22ARCHIVAL_DIR:=$(top_builddir)/archival/
23endif
24srcdir=$(top_srcdir)/archival
25
26ARCHIVAL-y:=
27ARCHIVAL-$(CONFIG_APT_GET) +=
28ARCHIVAL-$(CONFIG_AR) += ar.o
29ARCHIVAL-$(CONFIG_BUNZIP2) += bunzip2.o
30ARCHIVAL-$(CONFIG_CPIO) += cpio.o
31ARCHIVAL-$(CONFIG_DPKG) += dpkg.o
32ARCHIVAL-$(CONFIG_DPKG_DEB) += dpkg_deb.o
33ARCHIVAL-$(CONFIG_GUNZIP) += gunzip.o
34ARCHIVAL-$(CONFIG_GZIP) += gzip.o
35ARCHIVAL-$(CONFIG_RPM2CPIO) += rpm2cpio.o
36ARCHIVAL-$(CONFIG_RPM) += rpm.o
37ARCHIVAL-$(CONFIG_TAR) += tar.o
38ARCHIVAL-$(CONFIG_UNCOMPRESS) += uncompress.o
39ARCHIVAL-$(CONFIG_UNZIP) += unzip.o
40
41libraries-y+=$(ARCHIVAL_DIR)$(ARCHIVAL_AR)
42
43$(ARCHIVAL_DIR)$(ARCHIVAL_AR): $(patsubst %,$(ARCHIVAL_DIR)%, $(ARCHIVAL-y))
44 $(AR) -ro $@ $(patsubst %,$(ARCHIVAL_DIR)%, $(ARCHIVAL-y))
45
46$(ARCHIVAL_DIR)%.o: $(srcdir)/%.c
47 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
48
diff --git a/busybox/archival/ar.c b/busybox/archival/ar.c
new file mode 100644
index 000000000..44c5db035
--- /dev/null
+++ b/busybox/archival/ar.c
@@ -0,0 +1,110 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini ar implementation for busybox
4 *
5 * Copyright (C) 2000 by Glenn McGrath
6 * Written by Glenn McGrath <bug1@iinet.net.au> 1 June 2000
7 *
8 * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
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
23 *
24 * There is no single 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
27 */
28
29#include <fcntl.h>
30#include <getopt.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
35#include <utime.h>
36#include <unistd.h>
37
38#include "unarchive.h"
39#include "busybox.h"
40
41static void header_verbose_list_ar(const file_header_t *file_header)
42{
43 const char *mode = bb_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#define AR_CTX_PRINT 0x01
54#define AR_CTX_LIST 0x02
55#define AR_CTX_EXTRACT 0x04
56#define AR_OPT_PRESERVE_DATE 0x08
57#define AR_OPT_VERBOSE 0x10
58#define AR_OPT_CREATE 0x20
59
60extern int ar_main(int argc, char **argv)
61{
62 archive_handle_t *archive_handle;
63 unsigned long opt;
64 char magic[8];
65
66 archive_handle = init_handle();
67
68 bb_opt_complementaly = "p~tx:t~px:x~pt";
69 opt = bb_getopt_ulflags(argc, argv, "ptxovc");
70
71 if ((opt & 0x80000000UL) || (optind == argc)) {
72 bb_show_usage();
73 }
74
75 if (opt & AR_CTX_PRINT) {
76 archive_handle->action_data = data_extract_to_stdout;
77 }
78 if (opt & AR_CTX_LIST) {
79 archive_handle->action_header = header_list;
80 }
81 if (opt & AR_CTX_EXTRACT) {
82 archive_handle->action_data = data_extract_all;
83 }
84 if (opt & AR_OPT_PRESERVE_DATE) {
85 archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
86 }
87 if (opt & AR_OPT_VERBOSE) {
88 archive_handle->action_header = header_verbose_list_ar;
89 }
90 if (opt & AR_OPT_CREATE) {
91 bb_error_msg_and_die("Archive creation not supported. Install binutils 'ar'.");
92 }
93
94 archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY);
95
96 while (optind < argc) {
97 archive_handle->filter = filter_accept_list;
98 archive_handle->accept = llist_add_to(archive_handle->accept, argv[optind++]);
99 }
100
101 archive_xread_all(archive_handle, magic, 7);
102 if (strncmp(magic, "!<arch>", 7) != 0) {
103 bb_error_msg_and_die("Invalid ar magic");
104 }
105 archive_handle->offset += 7;
106
107 while (get_header_ar(archive_handle) == EXIT_SUCCESS);
108
109 return EXIT_SUCCESS;
110}
diff --git a/busybox/archival/bunzip2.c b/busybox/archival/bunzip2.c
new file mode 100644
index 000000000..bedd38c22
--- /dev/null
+++ b/busybox/archival/bunzip2.c
@@ -0,0 +1,91 @@
1/*
2 * Modified for busybox by Glenn McGrath <bug1@iinet.net.au>
3 * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <fcntl.h>
21#include <getopt.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include "busybox.h"
28#include "unarchive.h"
29
30#define BUNZIP2_OPT_STDOUT 1
31#define BUNZIP2_OPT_FORCE 2
32
33int bunzip2_main(int argc, char **argv)
34{
35 char *compressed_name;
36 /* Note: Ignore the warning about save_name being used uninitialized.
37 * That is not the case, but gcc has trouble working that out... */
38 char *save_name;
39 unsigned long opt;
40 int status;
41 int src_fd;
42 int dst_fd;
43
44 opt = bb_getopt_ulflags(argc, argv, "cf");
45
46 /* if called as bzcat force the stdout flag */
47 if (bb_applet_name[2] == 'c') {
48 opt |= BUNZIP2_OPT_STDOUT;
49 }
50
51 /* Set input filename and number */
52 compressed_name = argv[optind];
53 if ((compressed_name) && (compressed_name[0] != '-') && (compressed_name[1] != '\0')) {
54 /* Open input file */
55 src_fd = bb_xopen(compressed_name, O_RDONLY);
56 } else {
57 src_fd = STDIN_FILENO;
58 opt |= BUNZIP2_OPT_STDOUT;
59 }
60
61 /* Check that the input is sane. */
62 if (isatty(src_fd) && (opt & BUNZIP2_OPT_FORCE) == 0) {
63 bb_error_msg_and_die("compressed data not read from terminal. Use -f to force it.");
64 }
65
66 if (opt & BUNZIP2_OPT_STDOUT) {
67 dst_fd = STDOUT_FILENO;
68 } else {
69 int len = strlen(compressed_name) - 4;
70 if (strcmp(compressed_name + len, ".bz2") != 0) {
71 bb_error_msg_and_die("Invalid extension");
72 }
73 save_name = bb_xstrndup(compressed_name, len);
74 dst_fd = bb_xopen(save_name, O_WRONLY | O_CREAT);
75 }
76
77 status = uncompressStream(src_fd, dst_fd);
78 if(!(opt & BUNZIP2_OPT_STDOUT)) {
79 char *delete_name;
80 if (status) {
81 delete_name = save_name;
82 } else {
83 delete_name = compressed_name;
84 }
85 if (unlink(delete_name) < 0) {
86 bb_error_msg_and_die("Couldn't remove %s", delete_name);
87 }
88 }
89
90 return status;
91}
diff --git a/busybox/archival/cpio.c b/busybox/archival/cpio.c
new file mode 100644
index 000000000..0fbe7b8e5
--- /dev/null
+++ b/busybox/archival/cpio.c
@@ -0,0 +1,99 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini cpio implementation for busybox
4 *
5 * Copyright (C) 2001 by Glenn McGrath
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
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
20 *
21 * Limitations:
22 * Doesn't check CRC's
23 * Only supports new ASCII and CRC formats
24 *
25 */
26#include <fcntl.h>
27#include <getopt.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31#include "unarchive.h"
32#include "busybox.h"
33
34#define CPIO_OPT_EXTRACT 0x01
35#define CPIO_OPT_TEST 0x02
36#define CPIO_OPT_UNCONDITIONAL 0x04
37#define CPIO_OPT_VERBOSE 0x08
38#define CPIO_OPT_FILE 0x10
39#define CPIO_OPT_CREATE_LEADING_DIR 0x20
40#define CPIO_OPT_PRESERVE_MTIME 0x40
41
42extern int cpio_main(int argc, char **argv)
43{
44 archive_handle_t *archive_handle;
45 char *cpio_filename = NULL;
46 unsigned long opt;
47
48 /* Initialise */
49 archive_handle = init_handle();
50 archive_handle->src_fd = STDIN_FILENO;
51 archive_handle->seek = seek_by_char;
52 archive_handle->flags = ARCHIVE_EXTRACT_NEWER | ARCHIVE_PRESERVE_DATE;
53
54 opt = bb_getopt_ulflags(argc, argv, "ituvF:dm", &cpio_filename);
55
56 /* One of either extract or test options must be given */
57 if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
58 bb_show_usage();
59 }
60
61 if (opt & CPIO_OPT_TEST) {
62 /* if both extract and test option are given, ignore extract option */
63 if (opt & CPIO_OPT_EXTRACT) {
64 opt &= ~CPIO_OPT_EXTRACT;
65 }
66 archive_handle->action_header = header_list;
67 }
68 if (opt & CPIO_OPT_EXTRACT) {
69 archive_handle->action_data = data_extract_all;
70 }
71 if (opt & CPIO_OPT_UNCONDITIONAL) {
72 archive_handle->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
73 archive_handle->flags &= ~ARCHIVE_EXTRACT_NEWER;
74 }
75 if (opt & CPIO_OPT_VERBOSE) {
76 if (archive_handle->action_header == header_list) {
77 archive_handle->action_header = header_verbose_list;
78 } else {
79 archive_handle->action_header = header_list;
80 }
81 }
82 if (cpio_filename) { /* CPIO_OPT_FILE */
83 archive_handle->src_fd = bb_xopen(cpio_filename, O_RDONLY);
84 archive_handle->seek = seek_by_jump;
85 }
86 if (opt & CPIO_OPT_CREATE_LEADING_DIR) {
87 archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS;
88 }
89
90 while (optind < argc) {
91 archive_handle->filter = filter_accept_list;
92 archive_handle->accept = llist_add_to(archive_handle->accept, argv[optind]);
93 optind++;
94 }
95
96 while (get_header_cpio(archive_handle) == EXIT_SUCCESS);
97
98 return(EXIT_SUCCESS);
99}
diff --git a/busybox/archival/dpkg.c b/busybox/archival/dpkg.c
new file mode 100644
index 000000000..c096518a2
--- /dev/null
+++ b/busybox/archival/dpkg.c
@@ -0,0 +1,1833 @@
1/*
2 * Mini dpkg implementation for busybox.
3 * This is not meant as a replacement for dpkg
4 *
5 * Written By Glenn McGrath with the help of others
6 * Copyright (C) 2001 by Glenn McGrath
7 *
8 * Started life as a busybox implementation of udpkg
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
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.
23 */
24
25/*
26 * Known difference between busybox dpkg and the official dpkg that i don't
27 * consider important, its worth keeping a note of differences anyway, just to
28 * make it easier to maintain.
29 * - The first value for the Confflile: field isnt placed on a new line.
30 * - When installing a package the Status: field is placed at the end of the
31 * section, rather than just after the Package: field.
32 *
33 * Bugs that need to be fixed
34 * - (unknown, please let me know when you find any)
35 *
36 */
37
38#include <fcntl.h>
39#include <getopt.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43#include "unarchive.h"
44#include "busybox.h"
45
46/* NOTE: If you vary HASH_PRIME sizes be aware,
47 * 1) Tweaking these will have a big effect on how much memory this program uses.
48 * 2) For computational efficiency these hash tables should be at least 20%
49 * larger than the maximum number of elements stored in it.
50 * 3) All _HASH_PRIME's must be a prime number or chaos is assured, if your looking
51 * for a prime, try http://www.utm.edu/research/primes/lists/small/10000.txt
52 * 4) If you go bigger than 15 bits you may get into trouble (untested) as its
53 * sometimes cast to an unsigned int, if you go to 16 bit you will overlap
54 * int's and chaos is assured, 16381 is the max prime for 14 bit field
55 */
56
57/* NAME_HASH_PRIME, Stores package names and versions,
58 * I estimate it should be at least 50% bigger than PACKAGE_HASH_PRIME,
59 * as there a lot of duplicate version numbers */
60#define NAME_HASH_PRIME 16381
61char *name_hashtable[NAME_HASH_PRIME + 1];
62
63/* PACKAGE_HASH_PRIME, Maximum number of unique packages,
64 * It must not be smaller than STATUS_HASH_PRIME,
65 * Currently only packages from status_hashtable are stored in here, but in
66 * future this may be used to store packages not only from a status file,
67 * but an available_hashtable, and even multiple packages files.
68 * Package can be stored more than once if they have different versions.
69 * e.g. The same package may have different versions in the status file
70 * and available file */
71#define PACKAGE_HASH_PRIME 10007
72typedef struct edge_s {
73 unsigned int operator:3;
74 unsigned int type:4;
75 unsigned int name:14;
76 unsigned int version:14;
77} edge_t;
78
79typedef struct common_node_s {
80 unsigned int name:14;
81 unsigned int version:14;
82 unsigned int num_of_edges:14;
83 edge_t **edge;
84} common_node_t;
85common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1];
86
87/* Currently it doesnt store packages that have state-status of not-installed
88 * So it only really has to be the size of the maximum number of packages
89 * likely to be installed at any one time, so there is a bit of leeway here */
90#define STATUS_HASH_PRIME 8191
91typedef struct status_node_s {
92 unsigned int package:14; /* has to fit PACKAGE_HASH_PRIME */
93 unsigned int status:14; /* has to fit STATUS_HASH_PRIME */
94} status_node_t;
95status_node_t *status_hashtable[STATUS_HASH_PRIME + 1];
96
97/* Even numbers are for 'extras', like ored dependencies or null */
98enum edge_type_e {
99 EDGE_NULL = 0,
100 EDGE_PRE_DEPENDS = 1,
101 EDGE_OR_PRE_DEPENDS = 2,
102 EDGE_DEPENDS = 3,
103 EDGE_OR_DEPENDS = 4,
104 EDGE_REPLACES = 5,
105 EDGE_PROVIDES = 7,
106 EDGE_CONFLICTS = 9,
107 EDGE_SUGGESTS = 11,
108 EDGE_RECOMMENDS = 13,
109 EDGE_ENHANCES = 15
110};
111enum operator_e {
112 VER_NULL = 0,
113 VER_EQUAL = 1,
114 VER_LESS = 2,
115 VER_LESS_EQUAL = 3,
116 VER_MORE = 4,
117 VER_MORE_EQUAL = 5,
118 VER_ANY = 6
119};
120
121enum dpkg_opt_e {
122 dpkg_opt_purge = 1,
123 dpkg_opt_remove = 2,
124 dpkg_opt_unpack = 4,
125 dpkg_opt_configure = 8,
126 dpkg_opt_install = 16,
127 dpkg_opt_package_name = 32,
128 dpkg_opt_filename = 64,
129 dpkg_opt_list_installed = 128,
130 dpkg_opt_force_ignore_depends = 256
131};
132
133typedef struct deb_file_s {
134 char *control_file;
135 char *filename;
136 unsigned int package:14;
137} deb_file_t;
138
139
140void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime)
141{
142 unsigned long int hash_num = key[0];
143 int len = strlen(key);
144 int i;
145
146 /* Maybe i should have uses a "proper" hashing algorithm here instead
147 * of making one up myself, seems to be working ok though. */
148 for(i = 1; i < len; i++) {
149 /* shifts the ascii based value and adds it to previous value
150 * shift amount is mod 24 because long int is 32 bit and data
151 * to be shifted is 8, don't want to shift data to where it has
152 * no effect*/
153 hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24));
154 }
155 *start = (unsigned int) hash_num % hash_prime;
156 *decrement = (unsigned int) 1 + (hash_num % (hash_prime - 1));
157}
158
159/* this adds the key to the hash table */
160int search_name_hashtable(const char *key)
161{
162 unsigned int probe_address = 0;
163 unsigned int probe_decrement = 0;
164// char *temp;
165
166 make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);
167 while(name_hashtable[probe_address] != NULL) {
168 if (strcmp(name_hashtable[probe_address], key) == 0) {
169 return(probe_address);
170 } else {
171 probe_address -= probe_decrement;
172 if ((int)probe_address < 0) {
173 probe_address += NAME_HASH_PRIME;
174 }
175 }
176 }
177 name_hashtable[probe_address] = bb_xstrdup(key);
178 return(probe_address);
179}
180
181/* this DOESNT add the key to the hashtable
182 * TODO make it consistent with search_name_hashtable
183 */
184unsigned int search_status_hashtable(const char *key)
185{
186 unsigned int probe_address = 0;
187 unsigned int probe_decrement = 0;
188
189 make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);
190 while(status_hashtable[probe_address] != NULL) {
191 if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) {
192 break;
193 } else {
194 probe_address -= probe_decrement;
195 if ((int)probe_address < 0) {
196 probe_address += STATUS_HASH_PRIME;
197 }
198 }
199 }
200 return(probe_address);
201}
202
203/* Need to rethink version comparison, maybe the official dpkg has something i can use ? */
204int version_compare_part(const char *version1, const char *version2)
205{
206 int upstream_len1 = 0;
207 int upstream_len2 = 0;
208 char *name1_char;
209 char *name2_char;
210 int len1 = 0;
211 int len2 = 0;
212 int tmp_int;
213 int ver_num1;
214 int ver_num2;
215 int ret;
216
217 if (version1 == NULL) {
218 version1 = bb_xstrdup("");
219 }
220 if (version2 == NULL) {
221 version2 = bb_xstrdup("");
222 }
223 upstream_len1 = strlen(version1);
224 upstream_len2 = strlen(version2);
225
226 while ((len1 < upstream_len1) || (len2 < upstream_len2)) {
227 /* Compare non-digit section */
228 tmp_int = strcspn(&version1[len1], "0123456789");
229 name1_char = bb_xstrndup(&version1[len1], tmp_int);
230 len1 += tmp_int;
231 tmp_int = strcspn(&version2[len2], "0123456789");
232 name2_char = bb_xstrndup(&version2[len2], tmp_int);
233 len2 += tmp_int;
234 tmp_int = strcmp(name1_char, name2_char);
235 free(name1_char);
236 free(name2_char);
237 if (tmp_int != 0) {
238 ret = tmp_int;
239 goto cleanup_version_compare_part;
240 }
241
242 /* Compare digits */
243 tmp_int = strspn(&version1[len1], "0123456789");
244 name1_char = bb_xstrndup(&version1[len1], tmp_int);
245 len1 += tmp_int;
246 tmp_int = strspn(&version2[len2], "0123456789");
247 name2_char = bb_xstrndup(&version2[len2], tmp_int);
248 len2 += tmp_int;
249 ver_num1 = atoi(name1_char);
250 ver_num2 = atoi(name2_char);
251 free(name1_char);
252 free(name2_char);
253 if (ver_num1 < ver_num2) {
254 ret = -1;
255 goto cleanup_version_compare_part;
256 }
257 else if (ver_num1 > ver_num2) {
258 ret = 1;
259 goto cleanup_version_compare_part;
260 }
261 }
262 ret = 0;
263cleanup_version_compare_part:
264 return(ret);
265}
266
267/* if ver1 < ver2 return -1,
268 * if ver1 = ver2 return 0,
269 * if ver1 > ver2 return 1,
270 */
271int version_compare(const unsigned int ver1, const unsigned int ver2)
272{
273 char *ch_ver1 = name_hashtable[ver1];
274 char *ch_ver2 = name_hashtable[ver2];
275
276 char epoch1, epoch2;
277 char *deb_ver1, *deb_ver2;
278 char *ver1_ptr, *ver2_ptr;
279 char *upstream_ver1;
280 char *upstream_ver2;
281 int result;
282
283 /* Compare epoch */
284 if (ch_ver1[1] == ':') {
285 epoch1 = ch_ver1[0];
286 ver1_ptr = strchr(ch_ver1, ':') + 1;
287 } else {
288 epoch1 = '0';
289 ver1_ptr = ch_ver1;
290 }
291 if (ch_ver2[1] == ':') {
292 epoch2 = ch_ver2[0];
293 ver2_ptr = strchr(ch_ver2, ':') + 1;
294 } else {
295 epoch2 = '0';
296 ver2_ptr = ch_ver2;
297 }
298 if (epoch1 < epoch2) {
299 return(-1);
300 }
301 else if (epoch1 > epoch2) {
302 return(1);
303 }
304
305 /* Compare upstream version */
306 upstream_ver1 = bb_xstrdup(ver1_ptr);
307 upstream_ver2 = bb_xstrdup(ver2_ptr);
308
309 /* Chop off debian version, and store for later use */
310 deb_ver1 = strrchr(upstream_ver1, '-');
311 deb_ver2 = strrchr(upstream_ver2, '-');
312 if (deb_ver1) {
313 deb_ver1[0] = '\0';
314 deb_ver1++;
315 }
316 if (deb_ver2) {
317 deb_ver2[0] = '\0';
318 deb_ver2++;
319 }
320 result = version_compare_part(upstream_ver1, upstream_ver2);
321
322 free(upstream_ver1);
323 free(upstream_ver2);
324
325 if (result != 0) {
326 return(result);
327 }
328
329 /* Compare debian versions */
330 return(version_compare_part(deb_ver1, deb_ver2));
331}
332
333int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator)
334{
335 const int version_result = version_compare(version1, version2);
336 switch(operator) {
337 case (VER_ANY):
338 return(TRUE);
339 case (VER_EQUAL):
340 if (version_result == 0) {
341 return(TRUE);
342 }
343 break;
344 case (VER_LESS):
345 if (version_result < 0) {
346 return(TRUE);
347 }
348 break;
349 case (VER_LESS_EQUAL):
350 if (version_result <= 0) {
351 return(TRUE);
352 }
353 break;
354 case (VER_MORE):
355 if (version_result > 0) {
356 return(TRUE);
357 }
358 break;
359 case (VER_MORE_EQUAL):
360 if (version_result >= 0) {
361 return(TRUE);
362 }
363 break;
364 }
365 return(FALSE);
366}
367
368
369int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator)
370{
371 unsigned int probe_address = 0;
372 unsigned int probe_decrement = 0;
373
374 make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME);
375 while(package_hashtable[probe_address] != NULL) {
376 if (package_hashtable[probe_address]->name == name) {
377 if (operator == VER_ANY) {
378 return(probe_address);
379 }
380 if (test_version(package_hashtable[probe_address]->version, version, operator)) {
381 return(probe_address);
382 }
383 }
384 probe_address -= probe_decrement;
385 if ((int)probe_address < 0) {
386 probe_address += PACKAGE_HASH_PRIME;
387 }
388 }
389 return(probe_address);
390}
391
392/*
393 * This function searches through the entire package_hashtable looking
394 * for a package which provides "needle". It returns the index into
395 * the package_hashtable for the providing package.
396 *
397 * needle is the index into name_hashtable of the package we are
398 * looking for.
399 *
400 * start_at is the index in the package_hashtable to start looking
401 * at. If start_at is -1 then start at the beginning. This is to allow
402 * for repeated searches since more than one package might provide
403 * needle.
404 *
405 * FIXME: I don't think this is very efficient, but I thought I'd keep
406 * it simple for now until it proves to be a problem.
407 */
408int search_for_provides(int needle, int start_at) {
409 int i, j;
410 common_node_t *p;
411 for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {
412 p = package_hashtable[i];
413 if ( p == NULL ) continue;
414 for(j = 0; j < p->num_of_edges; j++)
415 if ( p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle )
416 return i;
417 }
418 return -1;
419}
420
421/*
422 * Add an edge to a node
423 */
424void add_edge_to_node(common_node_t *node, edge_t *edge)
425{
426 node->num_of_edges++;
427 node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1));
428 node->edge[node->num_of_edges - 1] = edge;
429}
430
431/*
432 * Create one new node and one new edge for every dependency.
433 *
434 * Dependencies which contain multiple alternatives are represented as
435 * an EDGE_OR_PRE_DEPENDS or EDGE_OR_DEPENDS node, followed by a
436 * number of EDGE_PRE_DEPENDS or EDGE_DEPENDS nodes. The name field of
437 * the OR edge contains the full dependency string while the version
438 * field contains the number of EDGE nodes which follow as part of
439 * this alternative.
440 */
441void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type)
442{
443 char *line = bb_xstrdup(whole_line);
444 char *line2;
445 char *line_ptr1 = NULL;
446 char *line_ptr2 = NULL;
447 char *field;
448 char *field2;
449 char *version;
450 edge_t *edge;
451 edge_t *or_edge;
452 int offset_ch;
453
454 field = strtok_r(line, ",", &line_ptr1);
455 do {
456 /* skip leading spaces */
457 field += strspn(field, " ");
458 line2 = bb_xstrdup(field);
459 field2 = strtok_r(line2, "|", &line_ptr2);
460 if ( (edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) &&
461 (strcmp(field, field2) != 0)) {
462 or_edge = (edge_t *)xmalloc(sizeof(edge_t));
463 or_edge->type = edge_type + 1;
464 } else {
465 or_edge = NULL;
466 }
467
468 if ( or_edge ) {
469 or_edge->name = search_name_hashtable(field);
470 or_edge->version = 0; // tracks the number of altenatives
471
472 add_edge_to_node(parent_node, or_edge);
473 }
474
475 do {
476 edge = (edge_t *) xmalloc(sizeof(edge_t));
477 edge->type = edge_type;
478
479 /* Skip any extra leading spaces */
480 field2 += strspn(field2, " ");
481
482 /* Get dependency version info */
483 version = strchr(field2, '(');
484 if (version == NULL) {
485 edge->operator = VER_ANY;
486 /* Get the versions hash number, adding it if the number isnt already in there */
487 edge->version = search_name_hashtable("ANY");
488 } else {
489 /* Skip leading ' ' or '(' */
490 version += strspn(field2, " ");
491 version += strspn(version, "(");
492 /* Calculate length of any operator characters */
493 offset_ch = strspn(version, "<=>");
494 /* Determine operator */
495 if (offset_ch > 0) {
496 if (strncmp(version, "=", offset_ch) == 0) {
497 edge->operator = VER_EQUAL;
498 }
499 else if (strncmp(version, "<<", offset_ch) == 0) {
500 edge->operator = VER_LESS;
501 }
502 else if (strncmp(version, "<=", offset_ch) == 0) {
503 edge->operator = VER_LESS_EQUAL;
504 }
505 else if (strncmp(version, ">>", offset_ch) == 0) {
506 edge->operator = VER_MORE;
507 }
508 else if (strncmp(version, ">=", offset_ch) == 0) {
509 edge->operator = VER_MORE_EQUAL;
510 } else {
511 bb_error_msg_and_die("Illegal operator\n");
512 }
513 }
514 /* skip to start of version numbers */
515 version += offset_ch;
516 version += strspn(version, " ");
517
518 /* Truncate version at trailing ' ' or ')' */
519 version[strcspn(version, " )")] = '\0';
520 /* Get the versions hash number, adding it if the number isnt already in there */
521 edge->version = search_name_hashtable(version);
522 }
523
524 /* Get the dependency name */
525 field2[strcspn(field2, " (")] = '\0';
526 edge->name = search_name_hashtable(field2);
527
528 if ( or_edge )
529 or_edge->version++;
530
531 add_edge_to_node(parent_node, edge);
532 } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL);
533 free(line2);
534 } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL);
535 free(line);
536
537 return;
538}
539
540void free_package(common_node_t *node)
541{
542 unsigned short i;
543 if (node) {
544 for (i = 0; i < node->num_of_edges; i++) {
545 free(node->edge[i]);
546 }
547 if ( node->edge )
548 free(node->edge);
549 free(node);
550 }
551}
552
553unsigned int fill_package_struct(char *control_buffer)
554{
555 common_node_t *new_node = (common_node_t *) xcalloc(1, sizeof(common_node_t));
556 const char *field_names[] = { "Package", "Version", "Pre-Depends", "Depends",
557 "Replaces", "Provides", "Conflicts", "Suggests", "Recommends", "Enhances", 0};
558 char *field_name;
559 char *field_value;
560 int field_start = 0;
561 int num = -1;
562 int buffer_length = strlen(control_buffer);
563
564 new_node->version = search_name_hashtable("unknown");
565 while (field_start < buffer_length) {
566 unsigned short field_num;
567
568 field_start += read_package_field(&control_buffer[field_start],
569 &field_name, &field_value);
570
571 if (field_name == NULL) {
572 goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement ! */
573 }
574
575 field_num = compare_string_array(field_names, field_name);
576 switch(field_num) {
577 case 0: /* Package */
578 new_node->name = search_name_hashtable(field_value);
579 break;
580 case 1: /* Version */
581 new_node->version = search_name_hashtable(field_value);
582 break;
583 case 2: /* Pre-Depends */
584 add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS);
585 break;
586 case 3: /* Depends */
587 add_split_dependencies(new_node, field_value, EDGE_DEPENDS);
588 break;
589 case 4: /* Replaces */
590 add_split_dependencies(new_node, field_value, EDGE_REPLACES);
591 break;
592 case 5: /* Provides */
593 add_split_dependencies(new_node, field_value, EDGE_PROVIDES);
594 break;
595 case 6: /* Conflicts */
596 add_split_dependencies(new_node, field_value, EDGE_CONFLICTS);
597 break;
598 case 7: /* Suggests */
599 add_split_dependencies(new_node, field_value, EDGE_SUGGESTS);
600 break;
601 case 8: /* Recommends */
602 add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS);
603 break;
604 case 9: /* Enhances */
605 add_split_dependencies(new_node, field_value, EDGE_ENHANCES);
606 break;
607 }
608fill_package_struct_cleanup:
609 free(field_name);
610 free(field_value);
611 }
612
613 if (new_node->version == search_name_hashtable("unknown")) {
614 free_package(new_node);
615 return(-1);
616 }
617 num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL);
618 if (package_hashtable[num] == NULL) {
619 package_hashtable[num] = new_node;
620 } else {
621 free_package(new_node);
622 }
623 return(num);
624}
625
626/* if num = 1, it returns the want status, 2 returns flag, 3 returns status */
627unsigned int get_status(const unsigned int status_node, const int num)
628{
629 char *status_string = name_hashtable[status_hashtable[status_node]->status];
630 char *state_sub_string;
631 unsigned int state_sub_num;
632 int len;
633 int i;
634
635 /* set tmp_string to point to the start of the word number */
636 for (i = 1; i < num; i++) {
637 /* skip past a word */
638 status_string += strcspn(status_string, " ");
639 /* skip past the separating spaces */
640 status_string += strspn(status_string, " ");
641 }
642 len = strcspn(status_string, " \n\0");
643 state_sub_string = bb_xstrndup(status_string, len);
644 state_sub_num = search_name_hashtable(state_sub_string);
645 free(state_sub_string);
646 return(state_sub_num);
647}
648
649void set_status(const unsigned int status_node_num, const char *new_value, const int position)
650{
651 const unsigned int new_value_len = strlen(new_value);
652 const unsigned int new_value_num = search_name_hashtable(new_value);
653 unsigned int want = get_status(status_node_num, 1);
654 unsigned int flag = get_status(status_node_num, 2);
655 unsigned int status = get_status(status_node_num, 3);
656 int want_len = strlen(name_hashtable[want]);
657 int flag_len = strlen(name_hashtable[flag]);
658 int status_len = strlen(name_hashtable[status]);
659 char *new_status;
660
661 switch (position) {
662 case (1):
663 want = new_value_num;
664 want_len = new_value_len;
665 break;
666 case (2):
667 flag = new_value_num;
668 flag_len = new_value_len;
669 break;
670 case (3):
671 status = new_value_num;
672 status_len = new_value_len;
673 break;
674 default:
675 bb_error_msg_and_die("DEBUG ONLY: this shouldnt happen");
676 }
677
678 new_status = (char *) xmalloc(want_len + flag_len + status_len + 3);
679 sprintf(new_status, "%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
680 status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
681 free(new_status);
682 return;
683}
684
685const char *describe_status(int status_num) {
686 int status_want, status_state ;
687 if ( status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0 )
688 return "is not installed or flagged to be installed\n";
689
690 status_want = get_status(status_num, 1);
691 status_state = get_status(status_num, 3);
692
693 if ( status_state == search_name_hashtable("installed") ) {
694 if ( status_want == search_name_hashtable("install") )
695 return "is installed";
696 if ( status_want == search_name_hashtable("deinstall") )
697 return "is marked to be removed";
698 if ( status_want == search_name_hashtable("purge") )
699 return "is marked to be purged";
700 }
701 if ( status_want == search_name_hashtable("unknown") )
702 return "is in an indeterminate state";
703 if ( status_want == search_name_hashtable("install") )
704 return "is marked to be installed";
705
706 return "is not installed or flagged to be installed";
707}
708
709
710void index_status_file(const char *filename)
711{
712 FILE *status_file;
713 char *control_buffer;
714 char *status_line;
715 status_node_t *status_node = NULL;
716 unsigned int status_num;
717
718 status_file = bb_xfopen(filename, "r");
719 while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) {
720 const unsigned int package_num = fill_package_struct(control_buffer);
721 if (package_num != -1) {
722 status_node = xmalloc(sizeof(status_node_t));
723 /* fill_package_struct doesnt handle the status field */
724 status_line = strstr(control_buffer, "Status:");
725 if (status_line != NULL) {
726 status_line += 7;
727 status_line += strspn(status_line, " \n\t");
728 status_line = bb_xstrndup(status_line, strcspn(status_line, "\n\0"));
729 status_node->status = search_name_hashtable(status_line);
730 free(status_line);
731 }
732 status_node->package = package_num;
733 status_num = search_status_hashtable(name_hashtable[package_hashtable[status_node->package]->name]);
734 status_hashtable[status_num] = status_node;
735 }
736 free(control_buffer);
737 }
738 fclose(status_file);
739 return;
740}
741
742#if 0 /* this code is no longer used */
743char *get_depends_field(common_node_t *package, const int depends_type)
744{
745 char *depends = NULL;
746 char *old_sep = (char *)xcalloc(1, 3);
747 char *new_sep = (char *)xcalloc(1, 3);
748 int line_size = 0;
749 int depends_size;
750
751 int i;
752
753 for (i = 0; i < package->num_of_edges; i++) {
754 if ((package->edge[i]->type == EDGE_OR_PRE_DEPENDS) ||
755 (package->edge[i]->type == EDGE_OR_DEPENDS)) {
756 }
757
758 if ((package->edge[i]->type == depends_type) ||
759 (package->edge[i]->type == depends_type + 1)) {
760 /* Check if its the first time through */
761
762 depends_size = 8 + strlen(name_hashtable[package->edge[i]->name])
763 + strlen(name_hashtable[package->edge[i]->version]);
764 line_size += depends_size;
765 depends = (char *) xrealloc(depends, line_size + 1);
766
767 /* Check to see if this dependency is the type we are looking for
768 * +1 to check for 'extra' types, e.g. ored dependecies */
769 strcpy(old_sep, new_sep);
770 if (package->edge[i]->type == depends_type) {
771 strcpy(new_sep, ", ");
772 }
773 else if (package->edge[i]->type == depends_type + 1) {
774 strcpy(new_sep, "| ");
775 }
776
777 if (depends_size == line_size) {
778 strcpy(depends, "");
779 } else {
780 if ((strcmp(old_sep, "| ") == 0) && (strcmp(new_sep, "| ") == 0)) {
781 strcat(depends, " | ");
782 } else {
783 strcat(depends, ", ");
784 }
785 }
786
787 strcat(depends, name_hashtable[package->edge[i]->name]);
788 if (strcmp(name_hashtable[package->edge[i]->version], "NULL") != 0) {
789 if (package->edge[i]->operator == VER_EQUAL) {
790 strcat(depends, " (= ");
791 }
792 else if (package->edge[i]->operator == VER_LESS) {
793 strcat(depends, " (<< ");
794 }
795 else if (package->edge[i]->operator == VER_LESS_EQUAL) {
796 strcat(depends, " (<= ");
797 }
798 else if (package->edge[i]->operator == VER_MORE) {
799 strcat(depends, " (>> ");
800 }
801 else if (package->edge[i]->operator == VER_MORE_EQUAL) {
802 strcat(depends, " (>= ");
803 } else {
804 strcat(depends, " (");
805 }
806 strcat(depends, name_hashtable[package->edge[i]->version]);
807 strcat(depends, ")");
808 }
809 }
810 }
811 return(depends);
812}
813#endif
814
815void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)
816{
817 char *name;
818 char *value;
819 int start = 0;
820 while (1) {
821 start += read_package_field(&control_buffer[start], &name, &value);
822 if (name == NULL) {
823 break;
824 }
825 if (strcmp(name, "Status") != 0) {
826 fprintf(new_status_file, "%s: %s\n", name, value);
827 }
828 }
829 return;
830}
831
832/* This could do with a cleanup */
833void write_status_file(deb_file_t **deb_file)
834{
835 FILE *old_status_file = bb_xfopen("/var/lib/dpkg/status", "r");
836 FILE *new_status_file = bb_xfopen("/var/lib/dpkg/status.udeb", "w");
837 char *package_name;
838 char *status_from_file;
839 char *control_buffer = NULL;
840 char *tmp_string;
841 int status_num;
842 int field_start = 0;
843 int write_flag;
844 int i = 0;
845
846 /* Update previously known packages */
847 while ((control_buffer = fgets_str(old_status_file, "\n\n")) != NULL) {
848 if ((tmp_string = strstr(control_buffer, "Package:")) == NULL) {
849 continue;
850 }
851
852 tmp_string += 8;
853 tmp_string += strspn(tmp_string, " \n\t");
854 package_name = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n\0"));
855 write_flag = FALSE;
856 tmp_string = strstr(control_buffer, "Status:");
857 if (tmp_string != NULL) {
858 /* Seperate the status value from the control buffer */
859 tmp_string += 7;
860 tmp_string += strspn(tmp_string, " \n\t");
861 status_from_file = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n"));
862 } else {
863 status_from_file = NULL;
864 }
865
866 /* Find this package in the status hashtable */
867 status_num = search_status_hashtable(package_name);
868 if (status_hashtable[status_num] != NULL) {
869 const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status];
870 if (strcmp(status_from_file, status_from_hashtable) != 0) {
871 /* New status isnt exactly the same as old status */
872 const int state_status = get_status(status_num, 3);
873 if ((strcmp("installed", name_hashtable[state_status]) == 0) ||
874 (strcmp("unpacked", name_hashtable[state_status]) == 0)) {
875 /* We need to add the control file from the package */
876 i = 0;
877 while(deb_file[i] != NULL) {
878 if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) {
879 /* Write a status file entry with a modified status */
880 /* remove trailing \n's */
881 write_buffer_no_status(new_status_file, deb_file[i]->control_file);
882 set_status(status_num, "ok", 2);
883 fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]);
884 write_flag = TRUE;
885 break;
886 }
887 i++;
888 }
889 /* This is temperary, debugging only */
890 if (deb_file[i] == NULL) {
891 bb_error_msg_and_die("ALERT: Couldnt find a control file, your status file may be broken, status may be incorrect for %s", package_name);
892 }
893 }
894 else if (strcmp("not-installed", name_hashtable[state_status]) == 0) {
895 /* Only write the Package, Status, Priority and Section lines */
896 fprintf(new_status_file, "Package: %s\n", package_name);
897 fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
898
899 while (1) {
900 char *field_name;
901 char *field_value;
902 field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
903 if (field_name == NULL) {
904 break;
905 }
906 if ((strcmp(field_name, "Priority") == 0) ||
907 (strcmp(field_name, "Section") == 0)) {
908 fprintf(new_status_file, "%s: %s\n", field_name, field_value);
909 }
910 }
911 write_flag = TRUE;
912 fputs("\n", new_status_file);
913 }
914 else if (strcmp("config-files", name_hashtable[state_status]) == 0) {
915 /* only change the status line */
916 while (1) {
917 char *field_name;
918 char *field_value;
919 field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
920 if (field_name == NULL) {
921 break;
922 }
923 /* Setup start point for next field */
924 if (strcmp(field_name, "Status") == 0) {
925 fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
926 } else {
927 fprintf(new_status_file, "%s: %s\n", field_name, field_value);
928 }
929 }
930 write_flag = TRUE;
931 fputs("\n", new_status_file);
932 }
933 }
934 }
935 /* If the package from the status file wasnt handle above, do it now*/
936 if (! write_flag) {
937 fprintf(new_status_file, "%s\n\n", control_buffer);
938 }
939
940 free(status_from_file);
941 free(package_name);
942 free(control_buffer);
943 }
944
945 /* Write any new packages */
946 for(i = 0; deb_file[i] != NULL; i++) {
947 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]);
948 if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) {
949 write_buffer_no_status(new_status_file, deb_file[i]->control_file);
950 set_status(status_num, "ok", 2);
951 fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]);
952 }
953 }
954 fclose(old_status_file);
955 fclose(new_status_file);
956
957
958 /* Create a separate backfile to dpkg */
959 if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {
960 struct stat stat_buf;
961 if (stat("/var/lib/dpkg/status", &stat_buf) == 0) {
962 bb_error_msg_and_die("Couldnt create backup status file");
963 }
964 /* Its ok if renaming the status file fails because status
965 * file doesnt exist, maybe we are starting from scratch */
966 bb_error_msg("No status file found, creating new one");
967 }
968
969 if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) {
970 bb_error_msg_and_die("DANGER: Couldnt create status file, you need to manually repair your status file");
971 }
972}
973
974/* This function returns TRUE if the given package can satisfy a
975 * dependency of type depend_type.
976 *
977 * A pre-depends is satisfied only if a package is already installed,
978 * which a regular depends can be satisfied by a package which we want
979 * to install.
980 */
981int package_satisfies_dependency(int package, int depend_type)
982{
983 int status_num = search_status_hashtable(name_hashtable[package_hashtable[package]->name]);
984
985 /* status could be unknown if package is a pure virtual
986 * provides which cannot satisfy any dependency by itself.
987 */
988 if ( status_hashtable[status_num] == NULL )
989 return 0;
990
991 switch (depend_type) {
992 case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed");
993 case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install");
994 }
995 return 0;
996}
997
998int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
999{
1000 int *conflicts = NULL;
1001 int conflicts_num = 0;
1002 int i = deb_start;
1003 int j;
1004
1005 /* Check for conflicts
1006 * TODO: TEST if conflicts with other packages to be installed
1007 *
1008 * Add install packages and the packages they provide
1009 * to the list of files to check conflicts for
1010 */
1011
1012 /* Create array of package numbers to check against
1013 * installed package for conflicts*/
1014 while (deb_file[i] != NULL) {
1015 const unsigned int package_num = deb_file[i]->package;
1016 conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
1017 conflicts[conflicts_num] = package_num;
1018 conflicts_num++;
1019 /* add provides to conflicts list */
1020 for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) {
1021 if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) {
1022 const int conflicts_package_num = search_package_hashtable(
1023 package_hashtable[package_num]->edge[j]->name,
1024 package_hashtable[package_num]->edge[j]->version,
1025 package_hashtable[package_num]->edge[j]->operator);
1026 if (package_hashtable[conflicts_package_num] == NULL) {
1027 /* create a new package */
1028 common_node_t *new_node = (common_node_t *) xmalloc(sizeof(common_node_t));
1029 new_node->name = package_hashtable[package_num]->edge[j]->name;
1030 new_node->version = package_hashtable[package_num]->edge[j]->version;
1031 new_node->num_of_edges = 0;
1032 new_node->edge = NULL;
1033 package_hashtable[conflicts_package_num] = new_node;
1034 }
1035 conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
1036 conflicts[conflicts_num] = conflicts_package_num;
1037 conflicts_num++;
1038 }
1039 }
1040 i++;
1041 }
1042
1043 /* Check conflicts */
1044 i = 0;
1045 while (deb_file[i] != NULL) {
1046 const common_node_t *package_node = package_hashtable[deb_file[i]->package];
1047 int status_num = 0;
1048 status_num = search_status_hashtable(name_hashtable[package_node->name]);
1049
1050 if (get_status(status_num, 3) == search_name_hashtable("installed")) {
1051 i++;
1052 continue;
1053 }
1054
1055 for (j = 0; j < package_node->num_of_edges; j++) {
1056 const edge_t *package_edge = package_node->edge[j];
1057
1058 if (package_edge->type == EDGE_CONFLICTS) {
1059 const unsigned int package_num =
1060 search_package_hashtable(package_edge->name,
1061 package_edge->version,
1062 package_edge->operator);
1063 int result = 0;
1064 if (package_hashtable[package_num] != NULL) {
1065 status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
1066
1067 if (get_status(status_num, 1) == search_name_hashtable("install")) {
1068 result = test_version(package_hashtable[deb_file[i]->package]->version,
1069 package_edge->version, package_edge->operator);
1070 }
1071 }
1072
1073 if (result) {
1074 bb_error_msg_and_die("Package %s conflicts with %s",
1075 name_hashtable[package_node->name],
1076 name_hashtable[package_edge->name]);
1077 }
1078 }
1079 }
1080 i++;
1081 }
1082
1083
1084 /* Check dependendcies */
1085 for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1086 int status_num = 0;
1087 int number_of_alternatives = 0;
1088 const edge_t * root_of_alternatives = NULL;
1089 const common_node_t *package_node = package_hashtable[i];
1090
1091 /* If the package node does not exist then this
1092 * package is a virtual one. In which case there are
1093 * no dependencies to check.
1094 */
1095 if ( package_node == NULL ) continue;
1096
1097 status_num = search_status_hashtable(name_hashtable[package_node->name]);
1098
1099 /* If there is no status then this package is a
1100 * virtual one provided by something else. In which
1101 * case there are no dependencies to check.
1102 */
1103 if ( status_hashtable[status_num] == NULL ) continue;
1104
1105 /* If we don't want this package installed then we may
1106 * as well ignore it's dependencies.
1107 */
1108 if (get_status(status_num, 1) != search_name_hashtable("install")) {
1109 continue;
1110 }
1111
1112#if 0
1113 /* This might be needed so we don't complain about
1114 * things which are broken but unrelated to the
1115 * packages that are currently being installed
1116 */
1117 if (state_status == search_name_hashtable("installed"))
1118 continue;
1119#endif
1120
1121 /* This code is tested only for EDGE_DEPENDS, since I
1122 * have no suitable pre-depends available. There is no
1123 * reason that it shouldn't work though :-)
1124 */
1125 for (j = 0; j < package_node->num_of_edges; j++) {
1126 const edge_t *package_edge = package_node->edge[j];
1127 unsigned int package_num;
1128
1129 if ( package_edge->type == EDGE_OR_PRE_DEPENDS ||
1130 package_edge->type == EDGE_OR_DEPENDS ) { /* start an EDGE_OR_ list */
1131 number_of_alternatives = package_edge->version;
1132 root_of_alternatives = package_edge;
1133 continue;
1134 } else if ( number_of_alternatives == 0 ) { /* not in the middle of an EDGE_OR_ list */
1135 number_of_alternatives = 1;
1136 root_of_alternatives = NULL;
1137 }
1138
1139 package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator);
1140
1141 if (package_edge->type == EDGE_PRE_DEPENDS ||
1142 package_edge->type == EDGE_DEPENDS ) {
1143 int result=1;
1144 status_num = 0;
1145
1146 /* If we are inside an alternative then check
1147 * this edge is the right type.
1148 *
1149 * EDGE_DEPENDS == OR_DEPENDS -1
1150 * EDGE_PRE_DEPENDS == OR_PRE_DEPENDS -1
1151 */
1152 if ( root_of_alternatives && package_edge->type != root_of_alternatives->type - 1)
1153 bb_error_msg_and_die("Fatal error. Package dependencies corrupt: %d != %d - 1 \n",
1154 package_edge->type, root_of_alternatives->type);
1155
1156 if (package_hashtable[package_num] != NULL)
1157 result = !package_satisfies_dependency(package_num, package_edge->type);
1158
1159 if (result) { /* check for other package which provide what we are looking for */
1160 int provider = -1;
1161
1162 while ( (provider = search_for_provides(package_edge->name, provider) ) > -1 ) {
1163 if ( package_hashtable[provider] == NULL ) {
1164 printf("Have a provider but no package information for it\n");
1165 continue;
1166 }
1167 result = !package_satisfies_dependency(provider, package_edge->type);
1168
1169 if ( result == 0 )
1170 break;
1171 }
1172 }
1173
1174 /* It must be already installed, or to be installed */
1175 number_of_alternatives--;
1176 if (result && number_of_alternatives == 0) {
1177 if ( root_of_alternatives )
1178 bb_error_msg_and_die(
1179 "Package %s %sdepends on %s, "
1180 "which cannot be satisfied",
1181 name_hashtable[package_node->name],
1182 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
1183 name_hashtable[root_of_alternatives->name]);
1184 else
1185 bb_error_msg_and_die(
1186 "Package %s %sdepends on %s, which %s\n",
1187 name_hashtable[package_node->name],
1188 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
1189 name_hashtable[package_edge->name],
1190 describe_status(status_num));
1191 } else if ( result == 0 && number_of_alternatives ) {
1192 /* we've found a package which
1193 * satisfies the dependency,
1194 * so skip over the rest of
1195 * the alternatives.
1196 */
1197 j += number_of_alternatives;
1198 number_of_alternatives = 0;
1199 }
1200 }
1201 }
1202 }
1203 free(conflicts);
1204 return(TRUE);
1205}
1206
1207char **create_list(const char *filename)
1208{
1209 FILE *list_stream;
1210 char **file_list = NULL;
1211 char *line = NULL;
1212 int count = 0;
1213
1214 /* don't use [xw]fopen here, handle error ourself */
1215 list_stream = fopen(filename, "r");
1216 if (list_stream == NULL) {
1217 return(NULL);
1218 }
1219
1220 while ((line = bb_get_chomped_line_from_file(list_stream)) != NULL) {
1221 file_list = xrealloc(file_list, sizeof(char *) * (count + 2));
1222 file_list[count] = line;
1223 count++;
1224 }
1225 fclose(list_stream);
1226
1227 if (count == 0) {
1228 return(NULL);
1229 } else {
1230 file_list[count] = NULL;
1231 return(file_list);
1232 }
1233}
1234
1235/* maybe i should try and hook this into remove_file.c somehow */
1236int remove_file_array(char **remove_names, char **exclude_names)
1237{
1238 struct stat path_stat;
1239 int match_flag;
1240 int remove_flag = FALSE;
1241 int i,j;
1242
1243 if (remove_names == NULL) {
1244 return(FALSE);
1245 }
1246 for (i = 0; remove_names[i] != NULL; i++) {
1247 match_flag = FALSE;
1248 if (exclude_names != NULL) {
1249 for (j = 0; exclude_names[j] != 0; j++) {
1250 if (strcmp(remove_names[i], exclude_names[j]) == 0) {
1251 match_flag = TRUE;
1252 break;
1253 }
1254 }
1255 }
1256 if (!match_flag) {
1257 if (lstat(remove_names[i], &path_stat) < 0) {
1258 continue;
1259 }
1260 if (S_ISDIR(path_stat.st_mode)) {
1261 if (rmdir(remove_names[i]) != -1) {
1262 remove_flag = TRUE;
1263 }
1264 } else {
1265 if (unlink(remove_names[i]) != -1) {
1266 remove_flag = TRUE;
1267 }
1268 }
1269 }
1270 }
1271 return(remove_flag);
1272}
1273
1274int run_package_script(const char *package_name, const char *script_type)
1275{
1276 struct stat path_stat;
1277 char *script_path;
1278 int result;
1279
1280 script_path = xmalloc(strlen(package_name) + strlen(script_type) + 21);
1281 sprintf(script_path, "/var/lib/dpkg/info/%s.%s", package_name, script_type);
1282
1283 /* If the file doesnt exist is isnt a fatal */
1284 if (lstat(script_path, &path_stat) < 0) {
1285 result = EXIT_SUCCESS;
1286 } else {
1287 result = system(script_path);
1288 }
1289 free(script_path);
1290 return(result);
1291}
1292
1293const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm",
1294 "list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL };
1295
1296char **all_control_list(const char *package_name)
1297{
1298 unsigned short i = 0;
1299 char **remove_files;
1300
1301 /* Create a list of all /var/lib/dpkg/info/<package> files */
1302 remove_files = malloc(sizeof(all_control_files));
1303 while (all_control_files[i]) {
1304 remove_files[i] = xmalloc(strlen(package_name) + strlen(all_control_files[i]) + 21);
1305 sprintf(remove_files[i], "/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
1306 i++;
1307 }
1308 remove_files[sizeof(all_control_files)/sizeof(char*) - 1] = NULL;
1309
1310 return(remove_files);
1311}
1312
1313void free_array(char **array)
1314{
1315
1316 if (array) {
1317 unsigned short i = 0;
1318 while (array[i]) {
1319 free(array[i]);
1320 i++;
1321 }
1322 free(array);
1323 }
1324}
1325
1326/* This function lists information on the installed packages. It loops through
1327 * the status_hashtable to retrieve the info. This results in smaller code than
1328 * scanning the status file. The resulting list, however, is unsorted.
1329 */
1330void list_packages(void)
1331{
1332 int i;
1333
1334 printf(" Name Version\n");
1335 printf("+++-==============-==============\n");
1336
1337 /* go through status hash, dereference package hash and finally strings */
1338 for (i=0; i<STATUS_HASH_PRIME+1; i++) {
1339
1340 if (status_hashtable[i]) {
1341 const char *stat_str; /* status string */
1342 const char *name_str; /* package name */
1343 const char *vers_str; /* version */
1344 char s1, s2; /* status abbreviations */
1345 int spccnt; /* space count */
1346 int j;
1347
1348 stat_str = name_hashtable[status_hashtable[i]->status];
1349 name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
1350 vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
1351
1352 /* get abbreviation for status field 1 */
1353 s1 = stat_str[0] == 'i' ? 'i' : 'r';
1354
1355 /* get abbreviation for status field 2 */
1356 for (j=0, spccnt=0; stat_str[j] && spccnt<2; j++) {
1357 if (stat_str[j] == ' ') spccnt++;
1358 }
1359 s2 = stat_str[j];
1360
1361 /* print out the line formatted like Debian dpkg */
1362 printf("%c%c %-14s %s\n", s1, s2, name_str, vers_str);
1363 }
1364 }
1365}
1366
1367void remove_package(const unsigned int package_num, int noisy)
1368{
1369 const char *package_name = name_hashtable[package_hashtable[package_num]->name];
1370 const char *package_version = name_hashtable[package_hashtable[package_num]->version];
1371 const unsigned int status_num = search_status_hashtable(package_name);
1372 const int package_name_length = strlen(package_name);
1373 char **remove_files;
1374 char **exclude_files;
1375 char list_name[package_name_length + 25];
1376 char conffile_name[package_name_length + 30];
1377 int return_value;
1378
1379 if ( noisy )
1380 printf("Removing %s (%s) ...\n", package_name, package_version);
1381
1382 /* run prerm script */
1383 return_value = run_package_script(package_name, "prerm");
1384 if (return_value == -1) {
1385 bb_error_msg_and_die("script failed, prerm failure");
1386 }
1387
1388 /* Create a list of files to remove, and a separate list of those to keep */
1389 sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
1390 remove_files = create_list(list_name);
1391
1392 sprintf(conffile_name, "/var/lib/dpkg/info/%s.conffiles", package_name);
1393 exclude_files = create_list(conffile_name);
1394
1395 /* Some directories cant be removed straight away, so do multiple passes */
1396 while (remove_file_array(remove_files, exclude_files));
1397 free_array(exclude_files);
1398 free_array(remove_files);
1399
1400 /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep */
1401 exclude_files = xmalloc(sizeof(char*) * 3);
1402 exclude_files[0] = bb_xstrdup(conffile_name);
1403 exclude_files[1] = xmalloc(package_name_length + 27);
1404 sprintf(exclude_files[1], "/var/lib/dpkg/info/%s.postrm", package_name);
1405 exclude_files[2] = NULL;
1406
1407 /* Create a list of all /var/lib/dpkg/info/<package> files */
1408 remove_files = all_control_list(package_name);
1409
1410 remove_file_array(remove_files, exclude_files);
1411 free_array(remove_files);
1412 free_array(exclude_files);
1413
1414 /* rename <package>.conffile to <package>.list */
1415 rename(conffile_name, list_name);
1416
1417 /* Change package status */
1418 set_status(status_num, "config-files", 3);
1419}
1420
1421void purge_package(const unsigned int package_num)
1422{
1423 const char *package_name = name_hashtable[package_hashtable[package_num]->name];
1424 const char *package_version = name_hashtable[package_hashtable[package_num]->version];
1425 const unsigned int status_num = search_status_hashtable(package_name);
1426 char **remove_files;
1427 char **exclude_files;
1428 char list_name[strlen(package_name) + 25];
1429
1430 printf("Purging %s (%s) ...\n", package_name, package_version);
1431
1432 /* run prerm script */
1433 if (run_package_script(package_name, "prerm") != 0) {
1434 bb_error_msg_and_die("script failed, prerm failure");
1435 }
1436
1437 /* Create a list of files to remove */
1438 sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
1439 remove_files = create_list(list_name);
1440
1441 exclude_files = xmalloc(sizeof(char*));
1442 exclude_files[0] = NULL;
1443
1444 /* Some directories cant be removed straight away, so do multiple passes */
1445 while (remove_file_array(remove_files, exclude_files));
1446 free_array(remove_files);
1447
1448 /* Create a list of all /var/lib/dpkg/info/<package> files */
1449 remove_files = all_control_list(package_name);
1450 remove_file_array(remove_files, exclude_files);
1451 free_array(remove_files);
1452 free(exclude_files);
1453
1454 /* run postrm script */
1455 if (run_package_script(package_name, "postrm") == -1) {
1456 bb_error_msg_and_die("postrm fialure.. set status to what?");
1457 }
1458
1459 /* Change package status */
1460 set_status(status_num, "not-installed", 3);
1461}
1462
1463static archive_handle_t *init_archive_deb_ar(const char *filename)
1464{
1465 archive_handle_t *ar_handle;
1466
1467 /* Setup an ar archive handle that refers to the gzip sub archive */
1468 ar_handle = init_handle();
1469 ar_handle->filter = filter_accept_list_reassign;
1470 ar_handle->src_fd = bb_xopen(filename, O_RDONLY);
1471
1472 return(ar_handle);
1473}
1474
1475static void init_archive_deb_control(archive_handle_t *ar_handle)
1476{
1477 archive_handle_t *tar_handle;
1478
1479 /* Setup the tar archive handle */
1480 tar_handle = init_handle();
1481 tar_handle->src_fd = ar_handle->src_fd;
1482
1483 /* We don't care about data.tar.* or debian-binary, just control.tar.* */
1484#ifdef CONFIG_FEATURE_DEB_TAR_GZ
1485 ar_handle->accept = llist_add_to(NULL, "control.tar.gz");
1486#endif
1487#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
1488 ar_handle->accept = llist_add_to(ar_handle->accept, "control.tar.bz2");
1489#endif
1490
1491 /* Assign the tar handle as a subarchive of the ar handle */
1492 ar_handle->sub_archive = tar_handle;
1493
1494 return;
1495}
1496
1497static void init_archive_deb_data(archive_handle_t *ar_handle)
1498{
1499 archive_handle_t *tar_handle;
1500
1501 /* Setup the tar archive handle */
1502 tar_handle = init_handle();
1503 tar_handle->src_fd = ar_handle->src_fd;
1504
1505 /* We don't care about control.tar.* or debian-binary, just data.tar.* */
1506#ifdef CONFIG_FEATURE_DEB_TAR_GZ
1507 ar_handle->accept = llist_add_to(NULL, "data.tar.gz");
1508#endif
1509#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
1510 ar_handle->accept = llist_add_to(ar_handle->accept, "data.tar.bz2");
1511#endif
1512
1513 /* Assign the tar handle as a subarchive of the ar handle */
1514 ar_handle->sub_archive = tar_handle;
1515
1516 return;
1517}
1518
1519static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)
1520{
1521 ar_handle->sub_archive->action_data = data_extract_to_buffer;
1522 ar_handle->sub_archive->accept = myaccept;
1523
1524 unpack_ar_archive(ar_handle);
1525 close(ar_handle->src_fd);
1526
1527 return(ar_handle->sub_archive->buffer);
1528}
1529
1530static void data_extract_all_prefix(archive_handle_t *archive_handle)
1531{
1532 char *name_ptr = archive_handle->file_header->name;
1533
1534 name_ptr += strspn(name_ptr, "./");
1535 if (name_ptr[0] != '\0') {
1536 archive_handle->file_header->name = xmalloc(strlen(archive_handle->buffer) + 2 + strlen(name_ptr));
1537 strcpy(archive_handle->file_header->name, archive_handle->buffer);
1538 strcat(archive_handle->file_header->name, name_ptr);
1539 data_extract_all(archive_handle);
1540 }
1541 return;
1542}
1543
1544static void unpack_package(deb_file_t *deb_file)
1545{
1546 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
1547 const unsigned int status_num = search_status_hashtable(package_name);
1548 const unsigned int status_package_num = status_hashtable[status_num]->package;
1549 char *info_prefix;
1550 archive_handle_t *archive_handle;
1551 FILE *out_stream;
1552 llist_t *accept_list = NULL;
1553 int i = 0;
1554
1555 /* If existing version, remove it first */
1556 if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
1557 /* Package is already installed, remove old version first */
1558 printf("Preparing to replace %s %s (using %s) ...\n", package_name,
1559 name_hashtable[package_hashtable[status_package_num]->version],
1560 deb_file->filename);
1561 remove_package(status_package_num, 0);
1562 } else {
1563 printf("Unpacking %s (from %s) ...\n", package_name, deb_file->filename);
1564 }
1565
1566 /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
1567 info_prefix = (char *) xmalloc(strlen(package_name) + 20 + 4 + 2);
1568 sprintf(info_prefix, "/var/lib/dpkg/info/%s.", package_name);
1569 archive_handle = init_archive_deb_ar(deb_file->filename);
1570 init_archive_deb_control(archive_handle);
1571
1572 while(all_control_files[i]) {
1573 char *c = (char *) xmalloc(3 + bb_strlen(all_control_files[i]));
1574 sprintf(c, "./%s", all_control_files[i]);
1575 accept_list= llist_add_to(accept_list, c);
1576 i++;
1577 }
1578 archive_handle->sub_archive->accept = accept_list;
1579 archive_handle->sub_archive->filter = filter_accept_list;
1580 archive_handle->sub_archive->action_data = data_extract_all_prefix;
1581 archive_handle->sub_archive->buffer = info_prefix;
1582 archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
1583 unpack_ar_archive(archive_handle);
1584
1585 /* Run the preinst prior to extracting */
1586 if (run_package_script(package_name, "preinst") != 0) {
1587 /* when preinst returns exit code != 0 then quit installation process */
1588 bb_error_msg_and_die("subprocess pre-installation script returned error.");
1589 }
1590
1591 /* Extract data.tar.gz to the root directory */
1592 archive_handle = init_archive_deb_ar(deb_file->filename);
1593 init_archive_deb_data(archive_handle);
1594 archive_handle->sub_archive->action_data = data_extract_all_prefix;
1595 archive_handle->sub_archive->buffer = "/";
1596 archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
1597 unpack_ar_archive(archive_handle);
1598
1599 /* Create the list file */
1600 strcat(info_prefix, "list");
1601 out_stream = bb_xfopen(info_prefix, "w");
1602 while (archive_handle->sub_archive->passed) {
1603 /* the leading . has been stripped by data_extract_all_prefix already */
1604 fputs(archive_handle->sub_archive->passed->data, out_stream);
1605 fputc('\n', out_stream);
1606 archive_handle->sub_archive->passed = archive_handle->sub_archive->passed->link;
1607 }
1608 fclose(out_stream);
1609
1610 /* change status */
1611 set_status(status_num, "install", 1);
1612 set_status(status_num, "unpacked", 3);
1613
1614 free(info_prefix);
1615}
1616
1617void configure_package(deb_file_t *deb_file)
1618{
1619 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
1620 const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version];
1621 const int status_num = search_status_hashtable(package_name);
1622
1623 printf("Setting up %s (%s) ...\n", package_name, package_version);
1624
1625 /* Run the postinst script */
1626 if (run_package_script(package_name, "postinst") != 0) {
1627 /* TODO: handle failure gracefully */
1628 bb_error_msg_and_die("postrm failure.. set status to what?");
1629 }
1630 /* Change status to reflect success */
1631 set_status(status_num, "install", 1);
1632 set_status(status_num, "installed", 3);
1633}
1634
1635int dpkg_main(int argc, char **argv)
1636{
1637 deb_file_t **deb_file = NULL;
1638 status_node_t *status_node;
1639 int opt;
1640 int package_num;
1641 int dpkg_opt = 0;
1642 int deb_count = 0;
1643 int state_status;
1644 int status_num;
1645 int i;
1646
1647 while ((opt = getopt(argc, argv, "CF:ilPru")) != -1) {
1648 switch (opt) {
1649 case 'C': // equivalent to --configure in official dpkg
1650 dpkg_opt |= dpkg_opt_configure;
1651 dpkg_opt |= dpkg_opt_package_name;
1652 break;
1653 case 'F': // equivalent to --force in official dpkg
1654 if (strcmp(optarg, "depends") == 0) {
1655 dpkg_opt |= dpkg_opt_force_ignore_depends;
1656 }
1657 break;
1658 case 'i':
1659 dpkg_opt |= dpkg_opt_install;
1660 dpkg_opt |= dpkg_opt_filename;
1661 break;
1662 case 'l':
1663 dpkg_opt |= dpkg_opt_list_installed;
1664 break;
1665 case 'P':
1666 dpkg_opt |= dpkg_opt_purge;
1667 dpkg_opt |= dpkg_opt_package_name;
1668 break;
1669 case 'r':
1670 dpkg_opt |= dpkg_opt_remove;
1671 dpkg_opt |= dpkg_opt_package_name;
1672 break;
1673 case 'u': /* Equivalent to --unpack in official dpkg */
1674 dpkg_opt |= dpkg_opt_unpack;
1675 dpkg_opt |= dpkg_opt_filename;
1676 break;
1677 default:
1678 bb_show_usage();
1679 }
1680 }
1681 /* check for non-otion argument if expected */
1682 if ((dpkg_opt == 0) || ((argc == optind) && !(dpkg_opt && dpkg_opt_list_installed))) {
1683 bb_show_usage();
1684 }
1685
1686/* puts("(Reading database ... xxxxx files and directories installed.)"); */
1687 index_status_file("/var/lib/dpkg/status");
1688
1689 /* if the list action was given print the installed packages and exit */
1690 if (dpkg_opt & dpkg_opt_list_installed) {
1691 list_packages();
1692 return(EXIT_SUCCESS);
1693 }
1694
1695 /* Read arguments and store relevant info in structs */
1696 while (optind < argc) {
1697 /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */
1698 deb_file = xrealloc(deb_file, sizeof(deb_file_t *) * (deb_count + 2));
1699 deb_file[deb_count] = (deb_file_t *) xmalloc(sizeof(deb_file_t));
1700 if (dpkg_opt & dpkg_opt_filename) {
1701 archive_handle_t *archive_handle;
1702 llist_t *control_list = NULL;
1703
1704 /* Extract the control file */
1705 control_list = llist_add_to(NULL, "./control");
1706 archive_handle = init_archive_deb_ar(argv[optind]);
1707 init_archive_deb_control(archive_handle);
1708 deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
1709 if (deb_file[deb_count]->control_file == NULL) {
1710 bb_error_msg_and_die("Couldnt extract control file");
1711 }
1712 deb_file[deb_count]->filename = bb_xstrdup(argv[optind]);
1713 package_num = fill_package_struct(deb_file[deb_count]->control_file);
1714
1715 if (package_num == -1) {
1716 bb_error_msg("Invalid control file in %s", argv[optind]);
1717 continue;
1718 }
1719 deb_file[deb_count]->package = (unsigned int) package_num;
1720
1721 /* Add the package to the status hashtable */
1722 if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) {
1723 /* Try and find a currently installed version of this package */
1724 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
1725 /* If no previous entry was found initialise a new entry */
1726 if ((status_hashtable[status_num] == NULL) ||
1727 (status_hashtable[status_num]->status == 0)) {
1728 status_node = (status_node_t *) xmalloc(sizeof(status_node_t));
1729 status_node->package = deb_file[deb_count]->package;
1730 /* reinstreq isnt changed to "ok" until the package control info
1731 * is written to the status file*/
1732 status_node->status = search_name_hashtable("install reinstreq not-installed");
1733 status_hashtable[status_num] = status_node;
1734 } else {
1735 set_status(status_num, "install", 1);
1736 set_status(status_num, "reinstreq", 2);
1737 }
1738 }
1739 }
1740 else if (dpkg_opt & dpkg_opt_package_name) {
1741 deb_file[deb_count]->filename = NULL;
1742 deb_file[deb_count]->control_file = NULL;
1743 deb_file[deb_count]->package = search_package_hashtable(
1744 search_name_hashtable(argv[optind]),
1745 search_name_hashtable("ANY"), VER_ANY);
1746 if (package_hashtable[deb_file[deb_count]->package] == NULL) {
1747 bb_error_msg_and_die("Package %s is uninstalled or unknown\n", argv[optind]);
1748 }
1749 package_num = deb_file[deb_count]->package;
1750 status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
1751 state_status = get_status(status_num, 3);
1752
1753 /* check package status is "installed" */
1754 if (dpkg_opt & dpkg_opt_remove) {
1755 if ((strcmp(name_hashtable[state_status], "not-installed") == 0) ||
1756 (strcmp(name_hashtable[state_status], "config-files") == 0)) {
1757 bb_error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[package_num]->name]);
1758 }
1759 set_status(status_num, "deinstall", 1);
1760 }
1761 else if (dpkg_opt & dpkg_opt_purge) {
1762 /* if package status is "conf-files" then its ok */
1763 if (strcmp(name_hashtable[state_status], "not-installed") == 0) {
1764 bb_error_msg_and_die("%s is already purged.", name_hashtable[package_hashtable[package_num]->name]);
1765 }
1766 set_status(status_num, "purge", 1);
1767 }
1768 }
1769 deb_count++;
1770 optind++;
1771 }
1772 deb_file[deb_count] = NULL;
1773
1774 /* Check that the deb file arguments are installable */
1775 if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) {
1776 if (!check_deps(deb_file, 0, deb_count)) {
1777 bb_error_msg_and_die("Dependency check failed");
1778 }
1779 }
1780
1781 /* TODO: install or remove packages in the correct dependency order */
1782 for (i = 0; i < deb_count; i++) {
1783 /* Remove or purge packages */
1784 if (dpkg_opt & dpkg_opt_remove) {
1785 remove_package(deb_file[i]->package, 1);
1786 }
1787 else if (dpkg_opt & dpkg_opt_purge) {
1788 purge_package(deb_file[i]->package);
1789 }
1790 else if (dpkg_opt & dpkg_opt_unpack) {
1791 unpack_package(deb_file[i]);
1792 }
1793 else if (dpkg_opt & dpkg_opt_install) {
1794 unpack_package(deb_file[i]);
1795 /* package is configured in second pass below */
1796 }
1797 else if (dpkg_opt & dpkg_opt_configure) {
1798 configure_package(deb_file[i]);
1799 }
1800 }
1801 /* configure installed packages */
1802 if (dpkg_opt & dpkg_opt_install) {
1803 for (i = 0; i < deb_count; i++)
1804 configure_package(deb_file[i]);
1805 }
1806
1807 write_status_file(deb_file);
1808
1809 for (i = 0; i < deb_count; i++) {
1810 free(deb_file[i]->control_file);
1811 free(deb_file[i]->filename);
1812 free(deb_file[i]);
1813 }
1814
1815 free(deb_file);
1816
1817 for (i = 0; i < NAME_HASH_PRIME; i++) {
1818 free(name_hashtable[i]);
1819 }
1820
1821 for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1822 if (package_hashtable[i] != NULL) {
1823 free_package(package_hashtable[i]);
1824 }
1825 }
1826
1827 for (i = 0; i < STATUS_HASH_PRIME; i++) {
1828 free(status_hashtable[i]);
1829 }
1830
1831 return(EXIT_SUCCESS);
1832}
1833
diff --git a/busybox/archival/dpkg_deb.c b/busybox/archival/dpkg_deb.c
new file mode 100644
index 000000000..5aa9881d5
--- /dev/null
+++ b/busybox/archival/dpkg_deb.c
@@ -0,0 +1,112 @@
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 <fcntl.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <getopt.h>
22
23#include "unarchive.h"
24#include "busybox.h"
25
26#define DPKG_DEB_OPT_CONTENTS 1
27#define DPKG_DEB_OPT_CONTROL 2
28#define DPKG_DEB_OPT_FIELD 4
29#define DPKG_DEB_OPT_EXTRACT 8
30#define DPKG_DEB_OPT_EXTRACT_VERBOSE 16
31
32extern int dpkg_deb_main(int argc, char **argv)
33{
34 archive_handle_t *ar_archive;
35 archive_handle_t *tar_archive;
36 llist_t *control_tar_llist = NULL;
37 unsigned long opt;
38 char *extract_dir = NULL;
39 short argcount = 1;
40
41 /* Setup the tar archive handle */
42 tar_archive = init_handle();
43
44 /* Setup an ar archive handle that refers to the gzip sub archive */
45 ar_archive = init_handle();
46 ar_archive->sub_archive = tar_archive;
47 ar_archive->filter = filter_accept_list_reassign;
48
49#ifdef CONFIG_FEATURE_DEB_TAR_GZ
50 ar_archive->accept = llist_add_to(NULL, "data.tar.gz");
51 control_tar_llist = llist_add_to(NULL, "control.tar.gz");
52#endif
53
54#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
55 ar_archive->accept = llist_add_to(ar_archive->accept, "data.tar.bz2");
56 control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2");
57#endif
58
59 bb_opt_complementaly = "c~efXx:e~cfXx:f~ceXx:X~cefx:x~cefX";
60 opt = bb_getopt_ulflags(argc, argv, "cefXx");
61
62 if (opt & DPKG_DEB_OPT_CONTENTS) {
63 tar_archive->action_header = header_verbose_list;
64 }
65 if (opt & DPKG_DEB_OPT_CONTROL) {
66 ar_archive->accept = control_tar_llist;
67 tar_archive->action_data = data_extract_all;
68 if (optind + 1 == argc) {
69 extract_dir = "./DEBIAN";
70 } else {
71 argcount++;
72 }
73 }
74 if (opt & DPKG_DEB_OPT_FIELD) {
75 /* Print the entire control file
76 * it should accept a second argument which specifies a
77 * specific field to print */
78 ar_archive->accept = control_tar_llist;
79 tar_archive->accept = llist_add_to(NULL, "./control");;
80 tar_archive->filter = filter_accept_list;
81 tar_archive->action_data = data_extract_to_stdout;
82 }
83 if (opt & DPKG_DEB_OPT_EXTRACT) {
84 tar_archive->action_header = header_list;
85 }
86 if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) {
87 tar_archive->action_data = data_extract_all;
88 argcount = 2;
89 }
90
91 if ((optind + argcount != argc) || (opt & 0x80000000UL)) {
92 bb_show_usage();
93 }
94
95 tar_archive->src_fd = ar_archive->src_fd = bb_xopen(argv[optind++], O_RDONLY);
96
97 /* Workout where to extract the files */
98 /* 2nd argument is a dir name */
99 if (argv[optind]) {
100 extract_dir = argv[optind];
101 }
102 if (extract_dir) {
103 mkdir(extract_dir, 0777);
104 chdir(extract_dir);
105 }
106 unpack_ar_archive(ar_archive);
107
108 /* Cleanup */
109 close (ar_archive->src_fd);
110
111 return(EXIT_SUCCESS);
112}
diff --git a/busybox/archival/gunzip.c b/busybox/archival/gunzip.c
new file mode 100644
index 000000000..beb7bd12e
--- /dev/null
+++ b/busybox/archival/gunzip.c
@@ -0,0 +1,198 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Gzip implementation for busybox
4 *
5 * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
6 *
7 * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
8 * based on gzip sources
9 *
10 * Adjusted further by Erik Andersen <andersen@codepoet.org> to support files as
11 * well as stdin/stdout, and to generally behave itself wrt command line
12 * handling.
13 *
14 * General cleanup to better adhere to the style guide and make use of standard
15 * busybox functions by Glenn McGrath <bug1@iinet.net.au>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *
31 *
32 * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
33 * Copyright (C) 1992-1993 Jean-loup Gailly
34 * The unzip code was written and put in the public domain by Mark Adler.
35 * Portions of the lzw code are derived from the public domain 'compress'
36 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
37 * Ken Turkowski, Dave Mack and Peter Jannesen.
38 *
39 * See the license_msg below and the file COPYING for the software license.
40 * See the file algorithm.doc for the compression algorithms and file formats.
41 */
42
43#if 0
44static char *license_msg[] = {
45 " Copyright (C) 1992-1993 Jean-loup Gailly",
46 " This program is free software; you can redistribute it and/or modify",
47 " it under the terms of the GNU General Public License as published by",
48 " the Free Software Foundation; either version 2, or (at your option)",
49 " any later version.",
50 "",
51 " This program is distributed in the hope that it will be useful,",
52 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
53 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
54 " GNU General Public License for more details.",
55 "",
56 " You should have received a copy of the GNU General Public License",
57 " along with this program; if not, write to the Free Software",
58 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
59 0
60};
61#endif
62
63#include <stdlib.h>
64#include <string.h>
65#include <unistd.h>
66#include <getopt.h>
67#include <sys/types.h>
68#include <sys/stat.h>
69#include <fcntl.h>
70
71#include "busybox.h"
72#include "unarchive.h"
73
74#define GUNZIP_OPT_STDOUT 1
75#define GUNZIP_OPT_FORCE 2
76#define GUNZIP_OPT_TEST 4
77#define GUNZIP_OPT_DECOMPRESS 8
78
79extern int gunzip_main(int argc, char **argv)
80{
81 char status = EXIT_SUCCESS;
82 unsigned long opt;
83
84 opt = bb_getopt_ulflags(argc, argv, "cftd");
85 /* if called as zcat */
86 if (strcmp(bb_applet_name, "zcat") == 0) {
87 opt |= GUNZIP_OPT_STDOUT;
88 }
89
90 do {
91 struct stat stat_buf;
92 const char *old_path = argv[optind];
93 const char *delete_path = NULL;
94 char *new_path = NULL;
95 int src_fd;
96 int dst_fd;
97
98 optind++;
99
100 if (old_path == NULL || strcmp(old_path, "-") == 0) {
101 src_fd = STDIN_FILENO;
102 opt |= GUNZIP_OPT_STDOUT;
103 } else {
104 src_fd = bb_xopen(old_path, O_RDONLY);
105
106 /* Get the time stamp on the input file. */
107 if (stat(old_path, &stat_buf) < 0) {
108 bb_error_msg_and_die("Couldn't stat file %s", old_path);
109 }
110 }
111
112 /* Check that the input is sane. */
113 if (isatty(src_fd) && ((opt & GUNZIP_OPT_FORCE) == 0)) {
114 bb_error_msg_and_die
115 ("compressed data not read from terminal. Use -f to force it.");
116 }
117
118 /* Set output filename and number */
119 if (opt & GUNZIP_OPT_TEST) {
120 dst_fd = bb_xopen("/dev/null", O_WRONLY); /* why does test use filenum 2 ? */
121 } else if (opt & GUNZIP_OPT_STDOUT) {
122 dst_fd = STDOUT_FILENO;
123 } else {
124 char *extension;
125
126 new_path = bb_xstrdup(old_path);
127
128 extension = strrchr(new_path, '.');
129#ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS
130 if (extension && (strcmp(extension, ".Z") == 0)) {
131 *extension = '\0';
132 } else
133#endif
134 if (extension && (strcmp(extension, ".gz") == 0)) {
135 *extension = '\0';
136 } else if (extension && (strcmp(extension, ".tgz") == 0)) {
137 extension[2] = 'a';
138 extension[3] = 'r';
139 } else {
140 bb_error_msg_and_die("Invalid extension");
141 }
142
143 /* Open output file */
144 dst_fd = bb_xopen(new_path, O_WRONLY | O_CREAT);
145
146 /* Set permissions on the file */
147 chmod(new_path, stat_buf.st_mode);
148
149 /* If unzip succeeds remove the old file */
150 delete_path = old_path;
151 }
152
153 /* do the decompression, and cleanup */
154 if (bb_xread_char(src_fd) == 0x1f) {
155 unsigned char magic2;
156
157 magic2 = bb_xread_char(src_fd);
158#ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS
159 if (magic2 == 0x9d) {
160 status = uncompress(src_fd, dst_fd);
161 } else
162#endif
163 if (magic2 == 0x8b) {
164 check_header_gzip(src_fd);
165 status = inflate_gunzip(src_fd, dst_fd);
166 if (status != 0) {
167 bb_error_msg_and_die("Error inflating");
168 }
169 } else {
170 bb_error_msg_and_die("Invalid magic");
171 }
172 } else {
173 bb_error_msg_and_die("Invalid magic");
174 }
175
176 if ((status != EXIT_SUCCESS) && (new_path)) {
177 /* Unzip failed, remove new path instead of old path */
178 delete_path = new_path;
179 }
180
181 if (dst_fd != STDOUT_FILENO) {
182 close(dst_fd);
183 }
184 if (src_fd != STDIN_FILENO) {
185 close(src_fd);
186 }
187
188 /* delete_path will be NULL if in test mode or from stdin */
189 if (delete_path && (unlink(delete_path) == -1)) {
190 bb_error_msg_and_die("Couldn't remove %s", delete_path);
191 }
192
193 free(new_path);
194
195 } while (optind < argc);
196
197 return status;
198}
diff --git a/busybox/archival/gzip.c b/busybox/archival/gzip.c
new file mode 100644
index 000000000..d494aa30e
--- /dev/null
+++ b/busybox/archival/gzip.c
@@ -0,0 +1,2548 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Gzip implementation for busybox
4 *
5 * Based on GNU gzip Copyright (C) 1992-1993 Jean-loup Gailly.
6 *
7 * Originally adjusted for busybox by Charles P. Wright <cpw@unix.asb.com>
8 * "this is a stripped down version of gzip I put into busybox, it does
9 * only standard in to standard out with -9 compression. It also requires
10 * the zcat module for some important functions."
11 *
12 * Adjusted further by Erik Andersen <andersen@codepoet.org> to support
13 * files as well as stdin/stdout, and to generally behave itself wrt
14 * command line handling.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32/* These defines are very important for BusyBox. Without these,
33 * huge chunks of ram are pre-allocated making the BusyBox bss
34 * size Freaking Huge(tm), which is a bad thing.*/
35#define SMALL_MEM
36#define DYN_ALLOC
37
38#include <stdlib.h>
39#include <stdio.h>
40#include <string.h>
41#include <unistd.h>
42#include <errno.h>
43#include <sys/types.h>
44#include <signal.h>
45#include <utime.h>
46#include <ctype.h>
47#include <sys/types.h>
48#include <unistd.h>
49#include <dirent.h>
50#include <fcntl.h>
51#include <time.h>
52#include "busybox.h"
53
54#define memzero(s, n) memset ((void *)(s), 0, (n))
55
56#ifndef RETSIGTYPE
57# define RETSIGTYPE void
58#endif
59
60typedef unsigned char uch;
61typedef unsigned short ush;
62typedef unsigned long ulg;
63
64/* Return codes from gzip */
65#define OK 0
66#define ERROR 1
67#define WARNING 2
68
69/* Compression methods (see algorithm.doc) */
70/* Only STORED and DEFLATED are supported by this BusyBox module */
71#define STORED 0
72/* methods 4 to 7 reserved */
73#define DEFLATED 8
74
75/* To save memory for 16 bit systems, some arrays are overlaid between
76 * the various modules:
77 * deflate: prev+head window d_buf l_buf outbuf
78 * unlzw: tab_prefix tab_suffix stack inbuf outbuf
79 * For compression, input is done in window[]. For decompression, output
80 * is done in window except for unlzw.
81 */
82
83#ifndef INBUFSIZ
84# ifdef SMALL_MEM
85# define INBUFSIZ 0x2000 /* input buffer size */
86# else
87# define INBUFSIZ 0x8000 /* input buffer size */
88# endif
89#endif
90#define INBUF_EXTRA 64 /* required by unlzw() */
91
92#ifndef OUTBUFSIZ
93# ifdef SMALL_MEM
94# define OUTBUFSIZ 8192 /* output buffer size */
95# else
96# define OUTBUFSIZ 16384 /* output buffer size */
97# endif
98#endif
99#define OUTBUF_EXTRA 2048 /* required by unlzw() */
100
101#ifndef DIST_BUFSIZE
102# ifdef SMALL_MEM
103# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
104# else
105# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
106# endif
107#endif
108
109#ifdef DYN_ALLOC
110# define DECLARE(type, array, size) static type * array
111# define ALLOC(type, array, size) { \
112 array = (type*)xcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
113 }
114# define FREE(array) {free(array), array=NULL;}
115#else
116# define DECLARE(type, array, size) static type array[size]
117# define ALLOC(type, array, size)
118# define FREE(array)
119#endif
120
121#define tab_suffix window
122#define tab_prefix prev /* hash link (see deflate.c) */
123#define head (prev+WSIZE) /* hash head (see deflate.c) */
124
125static long bytes_in; /* number of input bytes */
126
127#define isize bytes_in
128/* for compatibility with old zip sources (to be cleaned) */
129
130typedef int file_t; /* Do not use stdio */
131
132#define NO_FILE (-1) /* in memory compression */
133
134
135#define PACK_MAGIC "\037\036" /* Magic header for packed files */
136#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
137#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
138#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files */
139#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */
140
141/* gzip flag byte */
142#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
143#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
144#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
145#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
146#define COMMENT 0x10 /* bit 4 set: file comment present */
147#define RESERVED 0xC0 /* bit 6,7: reserved */
148
149/* internal file attribute */
150#define UNKNOWN 0xffff
151#define BINARY 0
152#define ASCII 1
153
154#ifndef WSIZE
155# define WSIZE 0x8000 /* window size--must be a power of two, and */
156#endif /* at least 32K for zip's deflate method */
157
158#define MIN_MATCH 3
159#define MAX_MATCH 258
160/* The minimum and maximum match lengths */
161
162#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
163/* Minimum amount of lookahead, except at the end of the input file.
164 * See deflate.c for comments about the MIN_MATCH+1.
165 */
166
167#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
168/* In order to simplify the code, particularly on 16 bit machines, match
169 * distances are limited to MAX_DIST instead of WSIZE.
170 */
171
172/* put_byte is used for the compressed output */
173#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
174 flush_outbuf();}
175
176
177/* Output a 32 bit value to the bit stream, lsb first */
178#if 0
179#define put_long(n) { \
180 put_short((n) & 0xffff); \
181 put_short(((ulg)(n)) >> 16); \
182}
183#endif
184
185#define seekable() 0 /* force sequential output */
186#define translate_eol 0 /* no option -a yet */
187
188/* Diagnostic functions */
189#ifdef DEBUG
190# define Assert(cond,msg) {if(!(cond)) bb_error_msg(msg);}
191# define Trace(x) fprintf x
192# define Tracev(x) {if (verbose) fprintf x ;}
193# define Tracevv(x) {if (verbose>1) fprintf x ;}
194# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
195# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
196#else
197# define Assert(cond,msg)
198# define Trace(x)
199# define Tracev(x)
200# define Tracevv(x)
201# define Tracec(c,x)
202# define Tracecv(c,x)
203#endif
204
205#define WARN(msg) {if (!quiet) fprintf msg ; \
206 if (exit_code == OK) exit_code = WARNING;}
207
208#ifndef MAX_PATH_LEN
209# define MAX_PATH_LEN 1024 /* max pathname length */
210#endif
211
212
213 /* from zip.c: */
214static int zip(int in, int out);
215static int file_read(char *buf, unsigned size);
216
217 /* from gzip.c */
218static RETSIGTYPE abort_gzip(void);
219
220 /* from deflate.c */
221static void lm_init(ush * flags);
222static ulg deflate(void);
223
224 /* from trees.c */
225static void ct_init(ush * attr, int *methodp);
226static int ct_tally(int dist, int lc);
227static ulg flush_block(char *buf, ulg stored_len, int eof);
228
229 /* from bits.c */
230static void bi_init(file_t zipfile);
231static void send_bits(int value, int length);
232static unsigned bi_reverse(unsigned value, int length);
233static void bi_windup(void);
234static void copy_block(char *buf, unsigned len, int header);
235static int (*read_buf) (char *buf, unsigned size);
236
237 /* from util.c: */
238static void flush_outbuf(void);
239
240/* lzw.h -- define the lzw functions.
241 * Copyright (C) 1992-1993 Jean-loup Gailly.
242 * This is free software; you can redistribute it and/or modify it under the
243 * terms of the GNU General Public License, see the file COPYING.
244 */
245
246#if !defined(OF) && defined(lint)
247# include "gzip.h"
248#endif
249
250#ifndef BITS
251# define BITS 16
252#endif
253#define INIT_BITS 9 /* Initial number of bits per code */
254
255#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
256/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
257 * It's a pity that old uncompress does not check bit 0x20. That makes
258 * extension of the format actually undesirable because old compress
259 * would just crash on the new format instead of giving a meaningful
260 * error message. It does check the number of bits, but it's more
261 * helpful to say "unsupported format, get a new version" than
262 * "can only handle 16 bits".
263 */
264
265/* tailor.h -- target dependent definitions
266 * Copyright (C) 1992-1993 Jean-loup Gailly.
267 * This is free software; you can redistribute it and/or modify it under the
268 * terms of the GNU General Public License, see the file COPYING.
269 */
270
271/* The target dependent definitions should be defined here only.
272 * The target dependent functions should be defined in tailor.c.
273 */
274
275
276 /* Common defaults */
277
278#ifndef OS_CODE
279# define OS_CODE 0x03 /* assume Unix */
280#endif
281
282#ifndef PATH_SEP
283# define PATH_SEP '/'
284#endif
285
286#ifndef OPTIONS_VAR
287# define OPTIONS_VAR "GZIP"
288#endif
289
290#ifndef Z_SUFFIX
291# define Z_SUFFIX ".gz"
292#endif
293
294#ifdef MAX_EXT_CHARS
295# define MAX_SUFFIX MAX_EXT_CHARS
296#else
297# define MAX_SUFFIX 30
298#endif
299
300 /* global buffers */
301
302DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
303DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
304DECLARE(ush, d_buf, DIST_BUFSIZE);
305DECLARE(uch, window, 2L * WSIZE);
306DECLARE(ush, tab_prefix, 1L << BITS);
307
308static int foreground; /* set if program run in foreground */
309static int method = DEFLATED; /* compression method */
310static int exit_code = OK; /* program exit code */
311static int part_nb; /* number of parts in .gz file */
312static long time_stamp; /* original time stamp (modification time) */
313static long ifile_size; /* input file size, -1 for devices (debug only) */
314static char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */
315static int z_len; /* strlen(z_suffix) */
316
317static int ifd; /* input file descriptor */
318static int ofd; /* output file descriptor */
319static unsigned insize; /* valid bytes in inbuf */
320static unsigned outcnt; /* bytes in output buffer */
321
322
323/* Output a 16 bit value, lsb first */
324static void put_short(ush w)
325{
326 if (outcnt < OUTBUFSIZ - 2) {
327 outbuf[outcnt++] = (uch) ((w) & 0xff);
328 outbuf[outcnt++] = (uch) ((ush) (w) >> 8);
329 } else {
330 put_byte((uch) ((w) & 0xff));
331 put_byte((uch) ((ush) (w) >> 8));
332 }
333}
334
335/* ========================================================================
336 * Signal and error handler.
337 */
338static void abort_gzip()
339{
340 exit(ERROR);
341}
342
343/* ===========================================================================
344 * Clear input and output buffers
345 */
346static void clear_bufs(void)
347{
348 outcnt = 0;
349 insize = 0;
350 bytes_in = 0L;
351}
352
353static void write_bb_error_msg(void)
354{
355 fputc('\n', stderr);
356 bb_perror_nomsg();
357 abort_gzip();
358}
359
360/* ===========================================================================
361 * Does the same as write(), but also handles partial pipe writes and checks
362 * for error return.
363 */
364static void write_buf(int fd, void *buf, unsigned cnt)
365{
366 unsigned n;
367
368 while ((n = write(fd, buf, cnt)) != cnt) {
369 if (n == (unsigned) (-1)) {
370 write_bb_error_msg();
371 }
372 cnt -= n;
373 buf = (void *) ((char *) buf + n);
374 }
375}
376
377/* ===========================================================================
378 * Run a set of bytes through the crc shift register. If s is a NULL
379 * pointer, then initialize the crc shift register contents instead.
380 * Return the current crc in either case.
381 */
382static ulg updcrc(uch * s, unsigned n)
383{
384 static ulg crc = (ulg) 0xffffffffL; /* shift register contents */
385 register ulg c; /* temporary variable */
386 static unsigned long crc_32_tab[256];
387
388 if (crc_32_tab[1] == 0x00000000L) {
389 unsigned long csr; /* crc shift register */
390 const unsigned long e = 0xedb88320L; /* polynomial exclusive-or pattern */
391 int i; /* counter for all possible eight bit values */
392 int k; /* byte being shifted into crc apparatus */
393
394 /* Compute table of CRC's. */
395 for (i = 1; i < 256; i++) {
396 csr = i;
397 /* The idea to initialize the register with the byte instead of
398 * zero was stolen from Haruhiko Okumura's ar002
399 */
400 for (k = 8; k; k--)
401 csr = csr & 1 ? (csr >> 1) ^ e : csr >> 1;
402 crc_32_tab[i] = csr;
403 }
404 }
405
406 if (s == NULL) {
407 c = 0xffffffffL;
408 } else {
409 c = crc;
410 if (n)
411 do {
412 c = crc_32_tab[((int) c ^ (*s++)) & 0xff] ^ (c >> 8);
413 } while (--n);
414 }
415 crc = c;
416 return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
417}
418
419/* bits.c -- output variable-length bit strings
420 * Copyright (C) 1992-1993 Jean-loup Gailly
421 * This is free software; you can redistribute it and/or modify it under the
422 * terms of the GNU General Public License, see the file COPYING.
423 */
424
425
426/*
427 * PURPOSE
428 *
429 * Output variable-length bit strings. Compression can be done
430 * to a file or to memory. (The latter is not supported in this version.)
431 *
432 * DISCUSSION
433 *
434 * The PKZIP "deflate" file format interprets compressed file data
435 * as a sequence of bits. Multi-bit strings in the file may cross
436 * byte boundaries without restriction.
437 *
438 * The first bit of each byte is the low-order bit.
439 *
440 * The routines in this file allow a variable-length bit value to
441 * be output right-to-left (useful for literal values). For
442 * left-to-right output (useful for code strings from the tree routines),
443 * the bits must have been reversed first with bi_reverse().
444 *
445 * For in-memory compression, the compressed bit stream goes directly
446 * into the requested output buffer. The input data is read in blocks
447 * by the mem_read() function. The buffer is limited to 64K on 16 bit
448 * machines.
449 *
450 * INTERFACE
451 *
452 * void bi_init (FILE *zipfile)
453 * Initialize the bit string routines.
454 *
455 * void send_bits (int value, int length)
456 * Write out a bit string, taking the source bits right to
457 * left.
458 *
459 * int bi_reverse (int value, int length)
460 * Reverse the bits of a bit string, taking the source bits left to
461 * right and emitting them right to left.
462 *
463 * void bi_windup (void)
464 * Write out any remaining bits in an incomplete byte.
465 *
466 * void copy_block(char *buf, unsigned len, int header)
467 * Copy a stored block to the zip file, storing first the length and
468 * its one's complement if requested.
469 *
470 */
471
472/* ===========================================================================
473 * Local data used by the "bit string" routines.
474 */
475
476static file_t zfile; /* output gzip file */
477
478static unsigned short bi_buf;
479
480/* Output buffer. bits are inserted starting at the bottom (least significant
481 * bits).
482 */
483
484#define Buf_size (8 * 2*sizeof(char))
485/* Number of bits used within bi_buf. (bi_buf might be implemented on
486 * more than 16 bits on some systems.)
487 */
488
489static int bi_valid;
490
491/* Current input function. Set to mem_read for in-memory compression */
492
493#ifdef DEBUG
494ulg bits_sent; /* bit length of the compressed data */
495#endif
496
497/* ===========================================================================
498 * Initialize the bit string routines.
499 */
500static void bi_init(file_t zipfile)
501{
502 zfile = zipfile;
503 bi_buf = 0;
504 bi_valid = 0;
505#ifdef DEBUG
506 bits_sent = 0L;
507#endif
508
509 /* Set the defaults for file compression. They are set by memcompress
510 * for in-memory compression.
511 */
512 if (zfile != NO_FILE) {
513 read_buf = file_read;
514 }
515}
516
517/* ===========================================================================
518 * Send a value on a given number of bits.
519 * IN assertion: length <= 16 and value fits in length bits.
520 */
521static void send_bits(int value, int length)
522{
523#ifdef DEBUG
524 Tracev((stderr, " l %2d v %4x ", length, value));
525 Assert(length > 0 && length <= 15, "invalid length");
526 bits_sent += (ulg) length;
527#endif
528 /* If not enough room in bi_buf, use (valid) bits from bi_buf and
529 * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
530 * unused bits in value.
531 */
532 if (bi_valid > (int) Buf_size - length) {
533 bi_buf |= (value << bi_valid);
534 put_short(bi_buf);
535 bi_buf = (ush) value >> (Buf_size - bi_valid);
536 bi_valid += length - Buf_size;
537 } else {
538 bi_buf |= value << bi_valid;
539 bi_valid += length;
540 }
541}
542
543/* ===========================================================================
544 * Reverse the first len bits of a code, using straightforward code (a faster
545 * method would use a table)
546 * IN assertion: 1 <= len <= 15
547 */
548static unsigned bi_reverse(unsigned code, int len)
549{
550 register unsigned res = 0;
551
552 do {
553 res |= code & 1;
554 code >>= 1, res <<= 1;
555 } while (--len > 0);
556 return res >> 1;
557}
558
559/* ===========================================================================
560 * Write out any remaining bits in an incomplete byte.
561 */
562static void bi_windup()
563{
564 if (bi_valid > 8) {
565 put_short(bi_buf);
566 } else if (bi_valid > 0) {
567 put_byte(bi_buf);
568 }
569 bi_buf = 0;
570 bi_valid = 0;
571#ifdef DEBUG
572 bits_sent = (bits_sent + 7) & ~7;
573#endif
574}
575
576/* ===========================================================================
577 * Copy a stored block to the zip file, storing first the length and its
578 * one's complement if requested.
579 */
580static void copy_block(char *buf, unsigned len, int header)
581{
582 bi_windup(); /* align on byte boundary */
583
584 if (header) {
585 put_short((ush) len);
586 put_short((ush) ~ len);
587#ifdef DEBUG
588 bits_sent += 2 * 16;
589#endif
590 }
591#ifdef DEBUG
592 bits_sent += (ulg) len << 3;
593#endif
594 while (len--) {
595 put_byte(*buf++);
596 }
597}
598
599/* deflate.c -- compress data using the deflation algorithm
600 * Copyright (C) 1992-1993 Jean-loup Gailly
601 * This is free software; you can redistribute it and/or modify it under the
602 * terms of the GNU General Public License, see the file COPYING.
603 */
604
605/*
606 * PURPOSE
607 *
608 * Identify new text as repetitions of old text within a fixed-
609 * length sliding window trailing behind the new text.
610 *
611 * DISCUSSION
612 *
613 * The "deflation" process depends on being able to identify portions
614 * of the input text which are identical to earlier input (within a
615 * sliding window trailing behind the input currently being processed).
616 *
617 * The most straightforward technique turns out to be the fastest for
618 * most input files: try all possible matches and select the longest.
619 * The key feature of this algorithm is that insertions into the string
620 * dictionary are very simple and thus fast, and deletions are avoided
621 * completely. Insertions are performed at each input character, whereas
622 * string matches are performed only when the previous match ends. So it
623 * is preferable to spend more time in matches to allow very fast string
624 * insertions and avoid deletions. The matching algorithm for small
625 * strings is inspired from that of Rabin & Karp. A brute force approach
626 * is used to find longer strings when a small match has been found.
627 * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
628 * (by Leonid Broukhis).
629 * A previous version of this file used a more sophisticated algorithm
630 * (by Fiala and Greene) which is guaranteed to run in linear amortized
631 * time, but has a larger average cost, uses more memory and is patented.
632 * However the F&G algorithm may be faster for some highly redundant
633 * files if the parameter max_chain_length (described below) is too large.
634 *
635 * ACKNOWLEDGMENTS
636 *
637 * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
638 * I found it in 'freeze' written by Leonid Broukhis.
639 * Thanks to many info-zippers for bug reports and testing.
640 *
641 * REFERENCES
642 *
643 * APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
644 *
645 * A description of the Rabin and Karp algorithm is given in the book
646 * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
647 *
648 * Fiala,E.R., and Greene,D.H.
649 * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
650 *
651 * INTERFACE
652 *
653 * void lm_init (int pack_level, ush *flags)
654 * Initialize the "longest match" routines for a new file
655 *
656 * ulg deflate (void)
657 * Processes a new input file and return its compressed length. Sets
658 * the compressed length, crc, deflate flags and internal file
659 * attributes.
660 */
661
662
663/* ===========================================================================
664 * Configuration parameters
665 */
666
667/* Compile with MEDIUM_MEM to reduce the memory requirements or
668 * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
669 * entire input file can be held in memory (not possible on 16 bit systems).
670 * Warning: defining these symbols affects HASH_BITS (see below) and thus
671 * affects the compression ratio. The compressed output
672 * is still correct, and might even be smaller in some cases.
673 */
674
675#ifdef SMALL_MEM
676# define HASH_BITS 13 /* Number of bits used to hash strings */
677#endif
678#ifdef MEDIUM_MEM
679# define HASH_BITS 14
680#endif
681#ifndef HASH_BITS
682# define HASH_BITS 15
683 /* For portability to 16 bit machines, do not use values above 15. */
684#endif
685
686/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and
687 * window with tab_suffix. Check that we can do this:
688 */
689#if (WSIZE<<1) > (1<<BITS)
690# error cannot overlay window with tab_suffix and prev with tab_prefix0
691#endif
692#if HASH_BITS > BITS-1
693# error cannot overlay head with tab_prefix1
694#endif
695#define HASH_SIZE (unsigned)(1<<HASH_BITS)
696#define HASH_MASK (HASH_SIZE-1)
697#define WMASK (WSIZE-1)
698/* HASH_SIZE and WSIZE must be powers of two */
699#define NIL 0
700/* Tail of hash chains */
701#define FAST 4
702#define SLOW 2
703/* speed options for the general purpose bit flag */
704#ifndef TOO_FAR
705# define TOO_FAR 4096
706#endif
707/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
708/* ===========================================================================
709 * Local data used by the "longest match" routines.
710 */
711typedef ush Pos;
712typedef unsigned IPos;
713
714/* A Pos is an index in the character window. We use short instead of int to
715 * save space in the various tables. IPos is used only for parameter passing.
716 */
717
718/* DECLARE(uch, window, 2L*WSIZE); */
719/* Sliding window. Input bytes are read into the second half of the window,
720 * and move to the first half later to keep a dictionary of at least WSIZE
721 * bytes. With this organization, matches are limited to a distance of
722 * WSIZE-MAX_MATCH bytes, but this ensures that IO is always
723 * performed with a length multiple of the block size. Also, it limits
724 * the window size to 64K, which is quite useful on MSDOS.
725 * To do: limit the window size to WSIZE+BSZ if SMALL_MEM (the code would
726 * be less efficient).
727 */
728
729/* DECLARE(Pos, prev, WSIZE); */
730/* Link to older string with same hash index. To limit the size of this
731 * array to 64K, this link is maintained only for the last 32K strings.
732 * An index in this array is thus a window index modulo 32K.
733 */
734
735/* DECLARE(Pos, head, 1<<HASH_BITS); */
736/* Heads of the hash chains or NIL. */
737
738static const ulg window_size = (ulg) 2 * WSIZE;
739
740/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
741 * input file length plus MIN_LOOKAHEAD.
742 */
743
744static long block_start;
745
746/* window position at the beginning of the current output block. Gets
747 * negative when the window is moved backwards.
748 */
749
750static unsigned ins_h; /* hash index of string to be inserted */
751
752#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
753/* Number of bits by which ins_h and del_h must be shifted at each
754 * input step. It must be such that after MIN_MATCH steps, the oldest
755 * byte no longer takes part in the hash key, that is:
756 * H_SHIFT * MIN_MATCH >= HASH_BITS
757 */
758
759static unsigned int prev_length;
760
761/* Length of the best match at previous step. Matches not greater than this
762 * are discarded. This is used in the lazy match evaluation.
763 */
764
765static unsigned strstart; /* start of string to insert */
766static unsigned match_start; /* start of matching string */
767static int eofile; /* flag set at end of input file */
768static unsigned lookahead; /* number of valid bytes ahead in window */
769
770static const unsigned max_chain_length = 4096;
771
772/* To speed up deflation, hash chains are never searched beyond this length.
773 * A higher limit improves compression ratio but degrades the speed.
774 */
775
776static const unsigned int max_lazy_match = 258;
777
778/* Attempt to find a better match only when the current match is strictly
779 * smaller than this value. This mechanism is used only for compression
780 * levels >= 4.
781 */
782#define max_insert_length max_lazy_match
783/* Insert new strings in the hash table only if the match length
784 * is not greater than this length. This saves time but degrades compression.
785 * max_insert_length is used only for compression levels <= 3.
786 */
787
788static const unsigned good_match = 32;
789
790/* Use a faster search when the previous match is longer than this */
791
792
793/* Values for max_lazy_match, good_match and max_chain_length, depending on
794 * the desired pack level (0..9). The values given below have been tuned to
795 * exclude worst case performance for pathological files. Better values may be
796 * found for specific files.
797 */
798
799static const int nice_match = 258; /* Stop searching when current match exceeds this */
800
801/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
802 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
803 * meaning.
804 */
805
806#define EQUAL 0
807/* result of memcmp for equal strings */
808
809/* ===========================================================================
810 * Prototypes for local functions.
811 */
812static void fill_window(void);
813
814static int longest_match(IPos cur_match);
815
816#ifdef DEBUG
817static void check_match(IPos start, IPos match, int length);
818#endif
819
820/* ===========================================================================
821 * Update a hash value with the given input byte
822 * IN assertion: all calls to to UPDATE_HASH are made with consecutive
823 * input characters, so that a running hash key can be computed from the
824 * previous key instead of complete recalculation each time.
825 */
826#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
827
828/* ===========================================================================
829 * Insert string s in the dictionary and set match_head to the previous head
830 * of the hash chain (the most recent string with same hash key). Return
831 * the previous length of the hash chain.
832 * IN assertion: all calls to to INSERT_STRING are made with consecutive
833 * input characters and the first MIN_MATCH bytes of s are valid
834 * (except for the last MIN_MATCH-1 bytes of the input file).
835 */
836#define INSERT_STRING(s, match_head) \
837 (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
838 prev[(s) & WMASK] = match_head = head[ins_h], \
839 head[ins_h] = (s))
840
841/* ===========================================================================
842 * Initialize the "longest match" routines for a new file
843 */
844static void lm_init(ush * flags)
845{
846 register unsigned j;
847
848 /* Initialize the hash table. */
849 memzero((char *) head, HASH_SIZE * sizeof(*head));
850 /* prev will be initialized on the fly */
851
852 *flags |= SLOW;
853 /* ??? reduce max_chain_length for binary files */
854
855 strstart = 0;
856 block_start = 0L;
857
858 lookahead = read_buf((char *) window,
859 sizeof(int) <= 2 ? (unsigned) WSIZE : 2 * WSIZE);
860
861 if (lookahead == 0 || lookahead == (unsigned) EOF) {
862 eofile = 1, lookahead = 0;
863 return;
864 }
865 eofile = 0;
866 /* Make sure that we always have enough lookahead. This is important
867 * if input comes from a device such as a tty.
868 */
869 while (lookahead < MIN_LOOKAHEAD && !eofile)
870 fill_window();
871
872 ins_h = 0;
873 for (j = 0; j < MIN_MATCH - 1; j++)
874 UPDATE_HASH(ins_h, window[j]);
875 /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
876 * not important since only literal bytes will be emitted.
877 */
878}
879
880/* ===========================================================================
881 * Set match_start to the longest match starting at the given string and
882 * return its length. Matches shorter or equal to prev_length are discarded,
883 * in which case the result is equal to prev_length and match_start is
884 * garbage.
885 * IN assertions: cur_match is the head of the hash chain for the current
886 * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
887 */
888
889/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or
890 * match.s. The code is functionally equivalent, so you can use the C version
891 * if desired.
892 */
893static int longest_match(IPos cur_match)
894{
895 unsigned chain_length = max_chain_length; /* max hash chain length */
896 register uch *scan = window + strstart; /* current string */
897 register uch *match; /* matched string */
898 register int len; /* length of current match */
899 int best_len = prev_length; /* best match length so far */
900 IPos limit =
901 strstart > (IPos) MAX_DIST ? strstart - (IPos) MAX_DIST : NIL;
902 /* Stop when cur_match becomes <= limit. To simplify the code,
903 * we prevent matches with the string of window index 0.
904 */
905
906/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
907 * It is easy to get rid of this optimization if necessary.
908 */
909#if HASH_BITS < 8 || MAX_MATCH != 258
910# error Code too clever
911#endif
912 register uch *strend = window + strstart + MAX_MATCH;
913 register uch scan_end1 = scan[best_len - 1];
914 register uch scan_end = scan[best_len];
915
916 /* Do not waste too much time if we already have a good match: */
917 if (prev_length >= good_match) {
918 chain_length >>= 2;
919 }
920 Assert(strstart <= window_size - MIN_LOOKAHEAD, "insufficient lookahead");
921
922 do {
923 Assert(cur_match < strstart, "no future");
924 match = window + cur_match;
925
926 /* Skip to next match if the match length cannot increase
927 * or if the match length is less than 2:
928 */
929 if (match[best_len] != scan_end ||
930 match[best_len - 1] != scan_end1 ||
931 *match != *scan || *++match != scan[1])
932 continue;
933
934 /* The check at best_len-1 can be removed because it will be made
935 * again later. (This heuristic is not always a win.)
936 * It is not necessary to compare scan[2] and match[2] since they
937 * are always equal when the other bytes match, given that
938 * the hash keys are equal and that HASH_BITS >= 8.
939 */
940 scan += 2, match++;
941
942 /* We check for insufficient lookahead only every 8th comparison;
943 * the 256th check will be made at strstart+258.
944 */
945 do {
946 } while (*++scan == *++match && *++scan == *++match &&
947 *++scan == *++match && *++scan == *++match &&
948 *++scan == *++match && *++scan == *++match &&
949 *++scan == *++match && *++scan == *++match && scan < strend);
950
951 len = MAX_MATCH - (int) (strend - scan);
952 scan = strend - MAX_MATCH;
953
954 if (len > best_len) {
955 match_start = cur_match;
956 best_len = len;
957 if (len >= nice_match)
958 break;
959 scan_end1 = scan[best_len - 1];
960 scan_end = scan[best_len];
961 }
962 } while ((cur_match = prev[cur_match & WMASK]) > limit
963 && --chain_length != 0);
964
965 return best_len;
966}
967
968#ifdef DEBUG
969/* ===========================================================================
970 * Check that the match at match_start is indeed a match.
971 */
972static void check_match(IPos start, IPos match, int length)
973{
974 /* check that the match is indeed a match */
975 if (memcmp((char *) window + match,
976 (char *) window + start, length) != EQUAL) {
977 bb_error_msg(" start %d, match %d, length %d", start, match, length);
978 bb_error_msg("invalid match");
979 }
980 if (verbose > 1) {
981 bb_error_msg("\\[%d,%d]", start - match, length);
982 do {
983 putc(window[start++], stderr);
984 } while (--length != 0);
985 }
986}
987#else
988# define check_match(start, match, length)
989#endif
990
991/* ===========================================================================
992 * Fill the window when the lookahead becomes insufficient.
993 * Updates strstart and lookahead, and sets eofile if end of input file.
994 * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
995 * OUT assertions: at least one byte has been read, or eofile is set;
996 * file reads are performed for at least two bytes (required for the
997 * translate_eol option).
998 */
999static void fill_window()
1000{
1001 register unsigned n, m;
1002 unsigned more =
1003 (unsigned) (window_size - (ulg) lookahead - (ulg) strstart);
1004 /* Amount of free space at the end of the window. */
1005
1006 /* If the window is almost full and there is insufficient lookahead,
1007 * move the upper half to the lower one to make room in the upper half.
1008 */
1009 if (more == (unsigned) EOF) {
1010 /* Very unlikely, but possible on 16 bit machine if strstart == 0
1011 * and lookahead == 1 (input done one byte at time)
1012 */
1013 more--;
1014 } else if (strstart >= WSIZE + MAX_DIST) {
1015 /* By the IN assertion, the window is not empty so we can't confuse
1016 * more == 0 with more == 64K on a 16 bit machine.
1017 */
1018 Assert(window_size == (ulg) 2 * WSIZE, "no sliding with BIG_MEM");
1019
1020 memcpy((char *) window, (char *) window + WSIZE, (unsigned) WSIZE);
1021 match_start -= WSIZE;
1022 strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
1023
1024 block_start -= (long) WSIZE;
1025
1026 for (n = 0; n < HASH_SIZE; n++) {
1027 m = head[n];
1028 head[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
1029 }
1030 for (n = 0; n < WSIZE; n++) {
1031 m = prev[n];
1032 prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
1033 /* If n is not on any hash chain, prev[n] is garbage but
1034 * its value will never be used.
1035 */
1036 }
1037 more += WSIZE;
1038 }
1039 /* At this point, more >= 2 */
1040 if (!eofile) {
1041 n = read_buf((char *) window + strstart + lookahead, more);
1042 if (n == 0 || n == (unsigned) EOF) {
1043 eofile = 1;
1044 } else {
1045 lookahead += n;
1046 }
1047 }
1048}
1049
1050/* ===========================================================================
1051 * Flush the current block, with given end-of-file flag.
1052 * IN assertion: strstart is set to the end of the current match.
1053 */
1054#define FLUSH_BLOCK(eof) \
1055 flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
1056 (char*)NULL, (long)strstart - block_start, (eof))
1057
1058/* ===========================================================================
1059 * Same as above, but achieves better compression. We use a lazy
1060 * evaluation for matches: a match is finally adopted only if there is
1061 * no better match at the next window position.
1062 */
1063static ulg deflate()
1064{
1065 IPos hash_head; /* head of hash chain */
1066 IPos prev_match; /* previous match */
1067 int flush; /* set if current block must be flushed */
1068 int match_available = 0; /* set if previous match exists */
1069 register unsigned match_length = MIN_MATCH - 1; /* length of best match */
1070
1071 /* Process the input block. */
1072 while (lookahead != 0) {
1073 /* Insert the string window[strstart .. strstart+2] in the
1074 * dictionary, and set hash_head to the head of the hash chain:
1075 */
1076 INSERT_STRING(strstart, hash_head);
1077
1078 /* Find the longest match, discarding those <= prev_length.
1079 */
1080 prev_length = match_length, prev_match = match_start;
1081 match_length = MIN_MATCH - 1;
1082
1083 if (hash_head != NIL && prev_length < max_lazy_match &&
1084 strstart - hash_head <= MAX_DIST) {
1085 /* To simplify the code, we prevent matches with the string
1086 * of window index 0 (in particular we have to avoid a match
1087 * of the string with itself at the start of the input file).
1088 */
1089 match_length = longest_match(hash_head);
1090 /* longest_match() sets match_start */
1091 if (match_length > lookahead)
1092 match_length = lookahead;
1093
1094 /* Ignore a length 3 match if it is too distant: */
1095 if (match_length == MIN_MATCH && strstart - match_start > TOO_FAR) {
1096 /* If prev_match is also MIN_MATCH, match_start is garbage
1097 * but we will ignore the current match anyway.
1098 */
1099 match_length--;
1100 }
1101 }
1102 /* If there was a match at the previous step and the current
1103 * match is not better, output the previous match:
1104 */
1105 if (prev_length >= MIN_MATCH && match_length <= prev_length) {
1106
1107 check_match(strstart - 1, prev_match, prev_length);
1108
1109 flush =
1110 ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
1111
1112 /* Insert in hash table all strings up to the end of the match.
1113 * strstart-1 and strstart are already inserted.
1114 */
1115 lookahead -= prev_length - 1;
1116 prev_length -= 2;
1117 do {
1118 strstart++;
1119 INSERT_STRING(strstart, hash_head);
1120 /* strstart never exceeds WSIZE-MAX_MATCH, so there are
1121 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
1122 * these bytes are garbage, but it does not matter since the
1123 * next lookahead bytes will always be emitted as literals.
1124 */
1125 } while (--prev_length != 0);
1126 match_available = 0;
1127 match_length = MIN_MATCH - 1;
1128 strstart++;
1129 if (flush)
1130 FLUSH_BLOCK(0), block_start = strstart;
1131
1132 } else if (match_available) {
1133 /* If there was no match at the previous position, output a
1134 * single literal. If there was a match but the current match
1135 * is longer, truncate the previous match to a single literal.
1136 */
1137 Tracevv((stderr, "%c", window[strstart - 1]));
1138 if (ct_tally(0, window[strstart - 1])) {
1139 FLUSH_BLOCK(0), block_start = strstart;
1140 }
1141 strstart++;
1142 lookahead--;
1143 } else {
1144 /* There is no previous match to compare with, wait for
1145 * the next step to decide.
1146 */
1147 match_available = 1;
1148 strstart++;
1149 lookahead--;
1150 }
1151 Assert(strstart <= isize && lookahead <= isize, "a bit too far");
1152
1153 /* Make sure that we always have enough lookahead, except
1154 * at the end of the input file. We need MAX_MATCH bytes
1155 * for the next match, plus MIN_MATCH bytes to insert the
1156 * string following the next match.
1157 */
1158 while (lookahead < MIN_LOOKAHEAD && !eofile)
1159 fill_window();
1160 }
1161 if (match_available)
1162 ct_tally(0, window[strstart - 1]);
1163
1164 return FLUSH_BLOCK(1); /* eof */
1165}
1166
1167/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
1168 * Copyright (C) 1992-1993 Jean-loup Gailly
1169 * The unzip code was written and put in the public domain by Mark Adler.
1170 * Portions of the lzw code are derived from the public domain 'compress'
1171 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
1172 * Ken Turkowski, Dave Mack and Peter Jannesen.
1173 *
1174 * See the license_msg below and the file COPYING for the software license.
1175 * See the file algorithm.doc for the compression algorithms and file formats.
1176 */
1177
1178/* Compress files with zip algorithm and 'compress' interface.
1179 * See usage() and help() functions below for all options.
1180 * Outputs:
1181 * file.gz: compressed file with same mode, owner, and utimes
1182 * or stdout with -c option or if stdin used as input.
1183 * If the output file name had to be truncated, the original name is kept
1184 * in the compressed file.
1185 */
1186
1187 /* configuration */
1188
1189typedef struct dirent dir_type;
1190
1191typedef RETSIGTYPE(*sig_type) (int);
1192
1193/* ======================================================================== */
1194int gzip_main(int argc, char **argv)
1195{
1196 int result;
1197 int inFileNum;
1198 int outFileNum;
1199 struct stat statBuf;
1200 char *delFileName;
1201 int tostdout = 0;
1202 int force = 0;
1203 int opt;
1204
1205 while ((opt = getopt(argc, argv, "cf123456789dq")) != -1) {
1206 switch (opt) {
1207 case 'c':
1208 tostdout = 1;
1209 break;
1210 case 'f':
1211 force = 1;
1212 break;
1213 /* Ignore 1-9 (compression level) options */
1214 case '1':
1215 case '2':
1216 case '3':
1217 case '4':
1218 case '5':
1219 case '6':
1220 case '7':
1221 case '8':
1222 case '9':
1223 break;
1224 case 'q':
1225 break;
1226#ifdef CONFIG_GUNZIP
1227 case 'd':
1228 optind = 1;
1229 return gunzip_main(argc, argv);
1230#endif
1231 default:
1232 bb_show_usage();
1233 }
1234 }
1235
1236 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
1237 if (foreground) {
1238 (void) signal(SIGINT, (sig_type) abort_gzip);
1239 }
1240#ifdef SIGTERM
1241 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
1242 (void) signal(SIGTERM, (sig_type) abort_gzip);
1243 }
1244#endif
1245#ifdef SIGHUP
1246 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
1247 (void) signal(SIGHUP, (sig_type) abort_gzip);
1248 }
1249#endif
1250
1251 strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1);
1252 z_len = strlen(z_suffix);
1253
1254 /* Allocate all global buffers (for DYN_ALLOC option) */
1255 ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
1256 ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
1257 ALLOC(ush, d_buf, DIST_BUFSIZE);
1258 ALLOC(uch, window, 2L * WSIZE);
1259 ALLOC(ush, tab_prefix, 1L << BITS);
1260
1261 clear_bufs();
1262 part_nb = 0;
1263
1264 if (optind == argc) {
1265 time_stamp = 0;
1266 ifile_size = -1L;
1267 zip(STDIN_FILENO, STDOUT_FILENO);
1268 } else {
1269 int i;
1270
1271 for (i = optind; i < argc; i++) {
1272 char *path = NULL;
1273
1274 if (strcmp(argv[i], "-") == 0) {
1275 time_stamp = 0;
1276 ifile_size = -1L;
1277 inFileNum = STDIN_FILENO;
1278 outFileNum = STDOUT_FILENO;
1279 } else {
1280 inFileNum = open(argv[i], O_RDONLY);
1281 if (inFileNum < 0 || fstat(inFileNum, &statBuf) < 0)
1282 bb_perror_msg_and_die("%s", argv[i]);
1283 time_stamp = statBuf.st_ctime;
1284 ifile_size = statBuf.st_size;
1285
1286 if (!tostdout) {
1287 path = xmalloc(strlen(argv[i]) + 4);
1288 strcpy(path, argv[i]);
1289 strcat(path, ".gz");
1290
1291 /* Open output file */
1292#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
1293 outFileNum =
1294 open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW);
1295#else
1296 outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL);
1297#endif
1298 if (outFileNum < 0) {
1299 bb_perror_msg("%s", path);
1300 free(path);
1301 continue;
1302 }
1303
1304 /* Set permissions on the file */
1305 fchmod(outFileNum, statBuf.st_mode);
1306 } else
1307 outFileNum = STDOUT_FILENO;
1308 }
1309
1310 if (path == NULL && isatty(outFileNum) && force == 0) {
1311 bb_error_msg
1312 ("compressed data not written to a terminal. Use -f to force compression.");
1313 free(path);
1314 continue;
1315 }
1316
1317 result = zip(inFileNum, outFileNum);
1318
1319 if (path != NULL) {
1320 close(inFileNum);
1321 close(outFileNum);
1322
1323 /* Delete the original file */
1324 if (result == OK)
1325 delFileName = argv[i];
1326 else
1327 delFileName = path;
1328
1329 if (unlink(delFileName) < 0)
1330 bb_perror_msg("%s", delFileName);
1331 }
1332
1333 free(path);
1334 }
1335 }
1336
1337 return (exit_code);
1338}
1339
1340/* trees.c -- output deflated data using Huffman coding
1341 * Copyright (C) 1992-1993 Jean-loup Gailly
1342 * This is free software; you can redistribute it and/or modify it under the
1343 * terms of the GNU General Public License, see the file COPYING.
1344 */
1345
1346/*
1347 * PURPOSE
1348 *
1349 * Encode various sets of source values using variable-length
1350 * binary code trees.
1351 *
1352 * DISCUSSION
1353 *
1354 * The PKZIP "deflation" process uses several Huffman trees. The more
1355 * common source values are represented by shorter bit sequences.
1356 *
1357 * Each code tree is stored in the ZIP file in a compressed form
1358 * which is itself a Huffman encoding of the lengths of
1359 * all the code strings (in ascending order by source values).
1360 * The actual code strings are reconstructed from the lengths in
1361 * the UNZIP process, as described in the "application note"
1362 * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
1363 *
1364 * REFERENCES
1365 *
1366 * Lynch, Thomas J.
1367 * Data Compression: Techniques and Applications, pp. 53-55.
1368 * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7.
1369 *
1370 * Storer, James A.
1371 * Data Compression: Methods and Theory, pp. 49-50.
1372 * Computer Science Press, 1988. ISBN 0-7167-8156-5.
1373 *
1374 * Sedgewick, R.
1375 * Algorithms, p290.
1376 * Addison-Wesley, 1983. ISBN 0-201-06672-6.
1377 *
1378 * INTERFACE
1379 *
1380 * void ct_init (ush *attr, int *methodp)
1381 * Allocate the match buffer, initialize the various tables and save
1382 * the location of the internal file attribute (ascii/binary) and
1383 * method (DEFLATE/STORE)
1384 *
1385 * void ct_tally (int dist, int lc);
1386 * Save the match info and tally the frequency counts.
1387 *
1388 * long flush_block (char *buf, ulg stored_len, int eof)
1389 * Determine the best encoding for the current block: dynamic trees,
1390 * static trees or store, and output the encoded block to the zip
1391 * file. Returns the total compressed length for the file so far.
1392 *
1393 */
1394
1395/* ===========================================================================
1396 * Constants
1397 */
1398
1399#define MAX_BITS 15
1400/* All codes must not exceed MAX_BITS bits */
1401
1402#define MAX_BL_BITS 7
1403/* Bit length codes must not exceed MAX_BL_BITS bits */
1404
1405#define LENGTH_CODES 29
1406/* number of length codes, not counting the special END_BLOCK code */
1407
1408#define LITERALS 256
1409/* number of literal bytes 0..255 */
1410
1411#define END_BLOCK 256
1412/* end of block literal code */
1413
1414#define L_CODES (LITERALS+1+LENGTH_CODES)
1415/* number of Literal or Length codes, including the END_BLOCK code */
1416
1417#define D_CODES 30
1418/* number of distance codes */
1419
1420#define BL_CODES 19
1421/* number of codes used to transfer the bit lengths */
1422
1423typedef uch extra_bits_t;
1424
1425/* extra bits for each length code */
1426static const extra_bits_t extra_lbits[LENGTH_CODES]
1427 = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
1428 4, 4, 5, 5, 5, 5, 0
1429};
1430
1431/* extra bits for each distance code */
1432static const extra_bits_t extra_dbits[D_CODES]
1433 = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
1434 10, 10, 11, 11, 12, 12, 13, 13
1435};
1436
1437/* extra bits for each bit length code */
1438static const extra_bits_t extra_blbits[BL_CODES]
1439= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
1440
1441#define STORED_BLOCK 0
1442#define STATIC_TREES 1
1443#define DYN_TREES 2
1444/* The three kinds of block type */
1445
1446#ifndef LIT_BUFSIZE
1447# ifdef SMALL_MEM
1448# define LIT_BUFSIZE 0x2000
1449# else
1450# ifdef MEDIUM_MEM
1451# define LIT_BUFSIZE 0x4000
1452# else
1453# define LIT_BUFSIZE 0x8000
1454# endif
1455# endif
1456#endif
1457#ifndef DIST_BUFSIZE
1458# define DIST_BUFSIZE LIT_BUFSIZE
1459#endif
1460/* Sizes of match buffers for literals/lengths and distances. There are
1461 * 4 reasons for limiting LIT_BUFSIZE to 64K:
1462 * - frequencies can be kept in 16 bit counters
1463 * - if compression is not successful for the first block, all input data is
1464 * still in the window so we can still emit a stored block even when input
1465 * comes from standard input. (This can also be done for all blocks if
1466 * LIT_BUFSIZE is not greater than 32K.)
1467 * - if compression is not successful for a file smaller than 64K, we can
1468 * even emit a stored file instead of a stored block (saving 5 bytes).
1469 * - creating new Huffman trees less frequently may not provide fast
1470 * adaptation to changes in the input data statistics. (Take for
1471 * example a binary file with poorly compressible code followed by
1472 * a highly compressible string table.) Smaller buffer sizes give
1473 * fast adaptation but have of course the overhead of transmitting trees
1474 * more frequently.
1475 * - I can't count above 4
1476 * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
1477 * memory at the expense of compression). Some optimizations would be possible
1478 * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
1479 */
1480#if LIT_BUFSIZE > INBUFSIZ
1481#error cannot overlay l_buf and inbuf
1482#endif
1483#define REP_3_6 16
1484/* repeat previous bit length 3-6 times (2 bits of repeat count) */
1485#define REPZ_3_10 17
1486/* repeat a zero length 3-10 times (3 bits of repeat count) */
1487#define REPZ_11_138 18
1488/* repeat a zero length 11-138 times (7 bits of repeat count) */
1489
1490/* ===========================================================================
1491 * Local data
1492 */
1493
1494/* Data structure describing a single value and its code string. */
1495typedef struct ct_data {
1496 union {
1497 ush freq; /* frequency count */
1498 ush code; /* bit string */
1499 } fc;
1500 union {
1501 ush dad; /* father node in Huffman tree */
1502 ush len; /* length of bit string */
1503 } dl;
1504} ct_data;
1505
1506#define Freq fc.freq
1507#define Code fc.code
1508#define Dad dl.dad
1509#define Len dl.len
1510
1511#define HEAP_SIZE (2*L_CODES+1)
1512/* maximum heap size */
1513
1514static ct_data dyn_ltree[HEAP_SIZE]; /* literal and length tree */
1515static ct_data dyn_dtree[2 * D_CODES + 1]; /* distance tree */
1516
1517static ct_data static_ltree[L_CODES + 2];
1518
1519/* The static literal tree. Since the bit lengths are imposed, there is no
1520 * need for the L_CODES extra codes used during heap construction. However
1521 * The codes 286 and 287 are needed to build a canonical tree (see ct_init
1522 * below).
1523 */
1524
1525static ct_data static_dtree[D_CODES];
1526
1527/* The static distance tree. (Actually a trivial tree since all codes use
1528 * 5 bits.)
1529 */
1530
1531static ct_data bl_tree[2 * BL_CODES + 1];
1532
1533/* Huffman tree for the bit lengths */
1534
1535typedef struct tree_desc {
1536 ct_data *dyn_tree; /* the dynamic tree */
1537 ct_data *static_tree; /* corresponding static tree or NULL */
1538 const extra_bits_t *extra_bits; /* extra bits for each code or NULL */
1539 int extra_base; /* base index for extra_bits */
1540 int elems; /* max number of elements in the tree */
1541 int max_length; /* max bit length for the codes */
1542 int max_code; /* largest code with non zero frequency */
1543} tree_desc;
1544
1545static tree_desc l_desc =
1546 { dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES,
1547 MAX_BITS, 0
1548};
1549
1550static tree_desc d_desc =
1551 { dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0 };
1552
1553static tree_desc bl_desc =
1554 { bl_tree, (ct_data *) 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS,
1555 0
1556};
1557
1558
1559static ush bl_count[MAX_BITS + 1];
1560
1561/* number of codes at each bit length for an optimal tree */
1562
1563static const uch bl_order[BL_CODES]
1564= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
1565
1566/* The lengths of the bit length codes are sent in order of decreasing
1567 * probability, to avoid transmitting the lengths for unused bit length codes.
1568 */
1569
1570static int heap[2 * L_CODES + 1]; /* heap used to build the Huffman trees */
1571static int heap_len; /* number of elements in the heap */
1572static int heap_max; /* element of largest frequency */
1573
1574/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
1575 * The same heap array is used to build all trees.
1576 */
1577
1578static uch depth[2 * L_CODES + 1];
1579
1580/* Depth of each subtree used as tie breaker for trees of equal frequency */
1581
1582static uch length_code[MAX_MATCH - MIN_MATCH + 1];
1583
1584/* length code for each normalized match length (0 == MIN_MATCH) */
1585
1586static uch dist_code[512];
1587
1588/* distance codes. The first 256 values correspond to the distances
1589 * 3 .. 258, the last 256 values correspond to the top 8 bits of
1590 * the 15 bit distances.
1591 */
1592
1593static int base_length[LENGTH_CODES];
1594
1595/* First normalized length for each code (0 = MIN_MATCH) */
1596
1597static int base_dist[D_CODES];
1598
1599/* First normalized distance for each code (0 = distance of 1) */
1600
1601#define l_buf inbuf
1602/* DECLARE(uch, l_buf, LIT_BUFSIZE); buffer for literals or lengths */
1603
1604/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */
1605
1606static uch flag_buf[(LIT_BUFSIZE / 8)];
1607
1608/* flag_buf is a bit array distinguishing literals from lengths in
1609 * l_buf, thus indicating the presence or absence of a distance.
1610 */
1611
1612static unsigned last_lit; /* running index in l_buf */
1613static unsigned last_dist; /* running index in d_buf */
1614static unsigned last_flags; /* running index in flag_buf */
1615static uch flags; /* current flags not yet saved in flag_buf */
1616static uch flag_bit; /* current bit used in flags */
1617
1618/* bits are filled in flags starting at bit 0 (least significant).
1619 * Note: these flags are overkill in the current code since we don't
1620 * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
1621 */
1622
1623static ulg opt_len; /* bit length of current block with optimal trees */
1624static ulg static_len; /* bit length of current block with static trees */
1625
1626static ulg compressed_len; /* total bit length of compressed file */
1627
1628
1629static ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */
1630static int *file_method; /* pointer to DEFLATE or STORE */
1631
1632/* ===========================================================================
1633 * Local (static) routines in this file.
1634 */
1635
1636static void init_block(void);
1637static void pqdownheap(ct_data * tree, int k);
1638static void gen_bitlen(tree_desc * desc);
1639static void gen_codes(ct_data * tree, int max_code);
1640static void build_tree(tree_desc * desc);
1641static void scan_tree(ct_data * tree, int max_code);
1642static void send_tree(ct_data * tree, int max_code);
1643static int build_bl_tree(void);
1644static void send_all_trees(int lcodes, int dcodes, int blcodes);
1645static void compress_block(ct_data * ltree, ct_data * dtree);
1646static void set_file_type(void);
1647
1648
1649#ifndef DEBUG
1650# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
1651 /* Send a code of the given tree. c and tree must not have side effects */
1652
1653#else /* DEBUG */
1654# define send_code(c, tree) \
1655 { if (verbose>1) bb_error_msg("\ncd %3d ",(c)); \
1656 send_bits(tree[c].Code, tree[c].Len); }
1657#endif
1658
1659#define d_code(dist) \
1660 ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
1661/* Mapping from a distance to a distance code. dist is the distance - 1 and
1662 * must not have side effects. dist_code[256] and dist_code[257] are never
1663 * used.
1664 */
1665
1666/* the arguments must not have side effects */
1667
1668/* ===========================================================================
1669 * Allocate the match buffer, initialize the various tables and save the
1670 * location of the internal file attribute (ascii/binary) and method
1671 * (DEFLATE/STORE).
1672 */
1673static void ct_init(ush * attr, int *methodp)
1674{
1675 int n; /* iterates over tree elements */
1676 int bits; /* bit counter */
1677 int length; /* length value */
1678 int code; /* code value */
1679 int dist; /* distance index */
1680
1681 file_type = attr;
1682 file_method = methodp;
1683 compressed_len = 0L;
1684
1685 if (static_dtree[0].Len != 0)
1686 return; /* ct_init already called */
1687
1688 /* Initialize the mapping length (0..255) -> length code (0..28) */
1689 length = 0;
1690 for (code = 0; code < LENGTH_CODES - 1; code++) {
1691 base_length[code] = length;
1692 for (n = 0; n < (1 << extra_lbits[code]); n++) {
1693 length_code[length++] = (uch) code;
1694 }
1695 }
1696 Assert(length == 256, "ct_init: length != 256");
1697 /* Note that the length 255 (match length 258) can be represented
1698 * in two different ways: code 284 + 5 bits or code 285, so we
1699 * overwrite length_code[255] to use the best encoding:
1700 */
1701 length_code[length - 1] = (uch) code;
1702
1703 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
1704 dist = 0;
1705 for (code = 0; code < 16; code++) {
1706 base_dist[code] = dist;
1707 for (n = 0; n < (1 << extra_dbits[code]); n++) {
1708 dist_code[dist++] = (uch) code;
1709 }
1710 }
1711 Assert(dist == 256, "ct_init: dist != 256");
1712 dist >>= 7; /* from now on, all distances are divided by 128 */
1713 for (; code < D_CODES; code++) {
1714 base_dist[code] = dist << 7;
1715 for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
1716 dist_code[256 + dist++] = (uch) code;
1717 }
1718 }
1719 Assert(dist == 256, "ct_init: 256+dist != 512");
1720
1721 /* Construct the codes of the static literal tree */
1722 for (bits = 0; bits <= MAX_BITS; bits++)
1723 bl_count[bits] = 0;
1724 n = 0;
1725 while (n <= 143)
1726 static_ltree[n++].Len = 8, bl_count[8]++;
1727 while (n <= 255)
1728 static_ltree[n++].Len = 9, bl_count[9]++;
1729 while (n <= 279)
1730 static_ltree[n++].Len = 7, bl_count[7]++;
1731 while (n <= 287)
1732 static_ltree[n++].Len = 8, bl_count[8]++;
1733 /* Codes 286 and 287 do not exist, but we must include them in the
1734 * tree construction to get a canonical Huffman tree (longest code
1735 * all ones)
1736 */
1737 gen_codes((ct_data *) static_ltree, L_CODES + 1);
1738
1739 /* The static distance tree is trivial: */
1740 for (n = 0; n < D_CODES; n++) {
1741 static_dtree[n].Len = 5;
1742 static_dtree[n].Code = bi_reverse(n, 5);
1743 }
1744
1745 /* Initialize the first block of the first file: */
1746 init_block();
1747}
1748
1749/* ===========================================================================
1750 * Initialize a new block.
1751 */
1752static void init_block()
1753{
1754 int n; /* iterates over tree elements */
1755
1756 /* Initialize the trees. */
1757 for (n = 0; n < L_CODES; n++)
1758 dyn_ltree[n].Freq = 0;
1759 for (n = 0; n < D_CODES; n++)
1760 dyn_dtree[n].Freq = 0;
1761 for (n = 0; n < BL_CODES; n++)
1762 bl_tree[n].Freq = 0;
1763
1764 dyn_ltree[END_BLOCK].Freq = 1;
1765 opt_len = static_len = 0L;
1766 last_lit = last_dist = last_flags = 0;
1767 flags = 0;
1768 flag_bit = 1;
1769}
1770
1771#define SMALLEST 1
1772/* Index within the heap array of least frequent node in the Huffman tree */
1773
1774
1775/* ===========================================================================
1776 * Remove the smallest element from the heap and recreate the heap with
1777 * one less element. Updates heap and heap_len.
1778 */
1779#define pqremove(tree, top) \
1780{\
1781 top = heap[SMALLEST]; \
1782 heap[SMALLEST] = heap[heap_len--]; \
1783 pqdownheap(tree, SMALLEST); \
1784}
1785
1786/* ===========================================================================
1787 * Compares to subtrees, using the tree depth as tie breaker when
1788 * the subtrees have equal frequency. This minimizes the worst case length.
1789 */
1790#define smaller(tree, n, m) \
1791 (tree[n].Freq < tree[m].Freq || \
1792 (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
1793
1794/* ===========================================================================
1795 * Restore the heap property by moving down the tree starting at node k,
1796 * exchanging a node with the smallest of its two sons if necessary, stopping
1797 * when the heap property is re-established (each father smaller than its
1798 * two sons).
1799 */
1800static void pqdownheap(ct_data * tree, int k)
1801{
1802 int v = heap[k];
1803 int j = k << 1; /* left son of k */
1804
1805 while (j <= heap_len) {
1806 /* Set j to the smallest of the two sons: */
1807 if (j < heap_len && smaller(tree, heap[j + 1], heap[j]))
1808 j++;
1809
1810 /* Exit if v is smaller than both sons */
1811 if (smaller(tree, v, heap[j]))
1812 break;
1813
1814 /* Exchange v with the smallest son */
1815 heap[k] = heap[j];
1816 k = j;
1817
1818 /* And continue down the tree, setting j to the left son of k */
1819 j <<= 1;
1820 }
1821 heap[k] = v;
1822}
1823
1824/* ===========================================================================
1825 * Compute the optimal bit lengths for a tree and update the total bit length
1826 * for the current block.
1827 * IN assertion: the fields freq and dad are set, heap[heap_max] and
1828 * above are the tree nodes sorted by increasing frequency.
1829 * OUT assertions: the field len is set to the optimal bit length, the
1830 * array bl_count contains the frequencies for each bit length.
1831 * The length opt_len is updated; static_len is also updated if stree is
1832 * not null.
1833 */
1834static void gen_bitlen(tree_desc * desc)
1835{
1836 ct_data *tree = desc->dyn_tree;
1837 const extra_bits_t *extra = desc->extra_bits;
1838 int base = desc->extra_base;
1839 int max_code = desc->max_code;
1840 int max_length = desc->max_length;
1841 ct_data *stree = desc->static_tree;
1842 int h; /* heap index */
1843 int n, m; /* iterate over the tree elements */
1844 int bits; /* bit length */
1845 int xbits; /* extra bits */
1846 ush f; /* frequency */
1847 int overflow = 0; /* number of elements with bit length too large */
1848
1849 for (bits = 0; bits <= MAX_BITS; bits++)
1850 bl_count[bits] = 0;
1851
1852 /* In a first pass, compute the optimal bit lengths (which may
1853 * overflow in the case of the bit length tree).
1854 */
1855 tree[heap[heap_max]].Len = 0; /* root of the heap */
1856
1857 for (h = heap_max + 1; h < HEAP_SIZE; h++) {
1858 n = heap[h];
1859 bits = tree[tree[n].Dad].Len + 1;
1860 if (bits > max_length)
1861 bits = max_length, overflow++;
1862 tree[n].Len = (ush) bits;
1863 /* We overwrite tree[n].Dad which is no longer needed */
1864
1865 if (n > max_code)
1866 continue; /* not a leaf node */
1867
1868 bl_count[bits]++;
1869 xbits = 0;
1870 if (n >= base)
1871 xbits = extra[n - base];
1872 f = tree[n].Freq;
1873 opt_len += (ulg) f *(bits + xbits);
1874
1875 if (stree)
1876 static_len += (ulg) f *(stree[n].Len + xbits);
1877 }
1878 if (overflow == 0)
1879 return;
1880
1881 Trace((stderr, "\nbit length overflow\n"));
1882 /* This happens for example on obj2 and pic of the Calgary corpus */
1883
1884 /* Find the first bit length which could increase: */
1885 do {
1886 bits = max_length - 1;
1887 while (bl_count[bits] == 0)
1888 bits--;
1889 bl_count[bits]--; /* move one leaf down the tree */
1890 bl_count[bits + 1] += 2; /* move one overflow item as its brother */
1891 bl_count[max_length]--;
1892 /* The brother of the overflow item also moves one step up,
1893 * but this does not affect bl_count[max_length]
1894 */
1895 overflow -= 2;
1896 } while (overflow > 0);
1897
1898 /* Now recompute all bit lengths, scanning in increasing frequency.
1899 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
1900 * lengths instead of fixing only the wrong ones. This idea is taken
1901 * from 'ar' written by Haruhiko Okumura.)
1902 */
1903 for (bits = max_length; bits != 0; bits--) {
1904 n = bl_count[bits];
1905 while (n != 0) {
1906 m = heap[--h];
1907 if (m > max_code)
1908 continue;
1909 if (tree[m].Len != (unsigned) bits) {
1910 Trace((stderr, "code %d bits %d->%d\n", m, tree[m].Len,
1911 bits));
1912 opt_len +=
1913 ((long) bits - (long) tree[m].Len) * (long) tree[m].Freq;
1914 tree[m].Len = (ush) bits;
1915 }
1916 n--;
1917 }
1918 }
1919}
1920
1921/* ===========================================================================
1922 * Generate the codes for a given tree and bit counts (which need not be
1923 * optimal).
1924 * IN assertion: the array bl_count contains the bit length statistics for
1925 * the given tree and the field len is set for all tree elements.
1926 * OUT assertion: the field code is set for all tree elements of non
1927 * zero code length.
1928 */
1929static void gen_codes(ct_data * tree, int max_code)
1930{
1931 ush next_code[MAX_BITS + 1]; /* next code value for each bit length */
1932 ush code = 0; /* running code value */
1933 int bits; /* bit index */
1934 int n; /* code index */
1935
1936 /* The distribution counts are first used to generate the code values
1937 * without bit reversal.
1938 */
1939 for (bits = 1; bits <= MAX_BITS; bits++) {
1940 next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
1941 }
1942 /* Check that the bit counts in bl_count are consistent. The last code
1943 * must be all ones.
1944 */
1945 Assert(code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
1946 "inconsistent bit counts");
1947 Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
1948
1949 for (n = 0; n <= max_code; n++) {
1950 int len = tree[n].Len;
1951
1952 if (len == 0)
1953 continue;
1954 /* Now reverse the bits */
1955 tree[n].Code = bi_reverse(next_code[len]++, len);
1956
1957 Tracec(tree != static_ltree,
1958 (stderr, "\nn %3d %c l %2d c %4x (%x) ", n,
1959 (isgraph(n) ? n : ' '), len, tree[n].Code,
1960 next_code[len] - 1));
1961 }
1962}
1963
1964/* ===========================================================================
1965 * Construct one Huffman tree and assigns the code bit strings and lengths.
1966 * Update the total bit length for the current block.
1967 * IN assertion: the field freq is set for all tree elements.
1968 * OUT assertions: the fields len and code are set to the optimal bit length
1969 * and corresponding code. The length opt_len is updated; static_len is
1970 * also updated if stree is not null. The field max_code is set.
1971 */
1972static void build_tree(tree_desc * desc)
1973{
1974 ct_data *tree = desc->dyn_tree;
1975 ct_data *stree = desc->static_tree;
1976 int elems = desc->elems;
1977 int n, m; /* iterate over heap elements */
1978 int max_code = -1; /* largest code with non zero frequency */
1979 int node = elems; /* next internal node of the tree */
1980
1981 /* Construct the initial heap, with least frequent element in
1982 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
1983 * heap[0] is not used.
1984 */
1985 heap_len = 0, heap_max = HEAP_SIZE;
1986
1987 for (n = 0; n < elems; n++) {
1988 if (tree[n].Freq != 0) {
1989 heap[++heap_len] = max_code = n;
1990 depth[n] = 0;
1991 } else {
1992 tree[n].Len = 0;
1993 }
1994 }
1995
1996 /* The pkzip format requires that at least one distance code exists,
1997 * and that at least one bit should be sent even if there is only one
1998 * possible code. So to avoid special checks later on we force at least
1999 * two codes of non zero frequency.
2000 */
2001 while (heap_len < 2) {
2002 int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
2003
2004 tree[new].Freq = 1;
2005 depth[new] = 0;
2006 opt_len--;
2007 if (stree)
2008 static_len -= stree[new].Len;
2009 /* new is 0 or 1 so it does not have extra bits */
2010 }
2011 desc->max_code = max_code;
2012
2013 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
2014 * establish sub-heaps of increasing lengths:
2015 */
2016 for (n = heap_len / 2; n >= 1; n--)
2017 pqdownheap(tree, n);
2018
2019 /* Construct the Huffman tree by repeatedly combining the least two
2020 * frequent nodes.
2021 */
2022 do {
2023 pqremove(tree, n); /* n = node of least frequency */
2024 m = heap[SMALLEST]; /* m = node of next least frequency */
2025
2026 heap[--heap_max] = n; /* keep the nodes sorted by frequency */
2027 heap[--heap_max] = m;
2028
2029 /* Create a new node father of n and m */
2030 tree[node].Freq = tree[n].Freq + tree[m].Freq;
2031 depth[node] = (uch) (MAX(depth[n], depth[m]) + 1);
2032 tree[n].Dad = tree[m].Dad = (ush) node;
2033#ifdef DUMP_BL_TREE
2034 if (tree == bl_tree) {
2035 bb_error_msg("\nnode %d(%d), sons %d(%d) %d(%d)",
2036 node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
2037 }
2038#endif
2039 /* and insert the new node in the heap */
2040 heap[SMALLEST] = node++;
2041 pqdownheap(tree, SMALLEST);
2042
2043 } while (heap_len >= 2);
2044
2045 heap[--heap_max] = heap[SMALLEST];
2046
2047 /* At this point, the fields freq and dad are set. We can now
2048 * generate the bit lengths.
2049 */
2050 gen_bitlen((tree_desc *) desc);
2051
2052 /* The field len is now set, we can generate the bit codes */
2053 gen_codes((ct_data *) tree, max_code);
2054}
2055
2056/* ===========================================================================
2057 * Scan a literal or distance tree to determine the frequencies of the codes
2058 * in the bit length tree. Updates opt_len to take into account the repeat
2059 * counts. (The contribution of the bit length codes will be added later
2060 * during the construction of bl_tree.)
2061 */
2062static void scan_tree(ct_data * tree, int max_code)
2063{
2064 int n; /* iterates over all tree elements */
2065 int prevlen = -1; /* last emitted length */
2066 int curlen; /* length of current code */
2067 int nextlen = tree[0].Len; /* length of next code */
2068 int count = 0; /* repeat count of the current code */
2069 int max_count = 7; /* max repeat count */
2070 int min_count = 4; /* min repeat count */
2071
2072 if (nextlen == 0)
2073 max_count = 138, min_count = 3;
2074 tree[max_code + 1].Len = (ush) 0xffff; /* guard */
2075
2076 for (n = 0; n <= max_code; n++) {
2077 curlen = nextlen;
2078 nextlen = tree[n + 1].Len;
2079 if (++count < max_count && curlen == nextlen) {
2080 continue;
2081 } else if (count < min_count) {
2082 bl_tree[curlen].Freq += count;
2083 } else if (curlen != 0) {
2084 if (curlen != prevlen)
2085 bl_tree[curlen].Freq++;
2086 bl_tree[REP_3_6].Freq++;
2087 } else if (count <= 10) {
2088 bl_tree[REPZ_3_10].Freq++;
2089 } else {
2090 bl_tree[REPZ_11_138].Freq++;
2091 }
2092 count = 0;
2093 prevlen = curlen;
2094 if (nextlen == 0) {
2095 max_count = 138, min_count = 3;
2096 } else if (curlen == nextlen) {
2097 max_count = 6, min_count = 3;
2098 } else {
2099 max_count = 7, min_count = 4;
2100 }
2101 }
2102}
2103
2104/* ===========================================================================
2105 * Send a literal or distance tree in compressed form, using the codes in
2106 * bl_tree.
2107 */
2108static void send_tree(ct_data * tree, int max_code)
2109{
2110 int n; /* iterates over all tree elements */
2111 int prevlen = -1; /* last emitted length */
2112 int curlen; /* length of current code */
2113 int nextlen = tree[0].Len; /* length of next code */
2114 int count = 0; /* repeat count of the current code */
2115 int max_count = 7; /* max repeat count */
2116 int min_count = 4; /* min repeat count */
2117
2118/* tree[max_code+1].Len = -1; *//* guard already set */
2119 if (nextlen == 0)
2120 max_count = 138, min_count = 3;
2121
2122 for (n = 0; n <= max_code; n++) {
2123 curlen = nextlen;
2124 nextlen = tree[n + 1].Len;
2125 if (++count < max_count && curlen == nextlen) {
2126 continue;
2127 } else if (count < min_count) {
2128 do {
2129 send_code(curlen, bl_tree);
2130 } while (--count != 0);
2131
2132 } else if (curlen != 0) {
2133 if (curlen != prevlen) {
2134 send_code(curlen, bl_tree);
2135 count--;
2136 }
2137 Assert(count >= 3 && count <= 6, " 3_6?");
2138 send_code(REP_3_6, bl_tree);
2139 send_bits(count - 3, 2);
2140
2141 } else if (count <= 10) {
2142 send_code(REPZ_3_10, bl_tree);
2143 send_bits(count - 3, 3);
2144
2145 } else {
2146 send_code(REPZ_11_138, bl_tree);
2147 send_bits(count - 11, 7);
2148 }
2149 count = 0;
2150 prevlen = curlen;
2151 if (nextlen == 0) {
2152 max_count = 138, min_count = 3;
2153 } else if (curlen == nextlen) {
2154 max_count = 6, min_count = 3;
2155 } else {
2156 max_count = 7, min_count = 4;
2157 }
2158 }
2159}
2160
2161/* ===========================================================================
2162 * Construct the Huffman tree for the bit lengths and return the index in
2163 * bl_order of the last bit length code to send.
2164 */
2165static const int build_bl_tree()
2166{
2167 int max_blindex; /* index of last bit length code of non zero freq */
2168
2169 /* Determine the bit length frequencies for literal and distance trees */
2170 scan_tree((ct_data *) dyn_ltree, l_desc.max_code);
2171 scan_tree((ct_data *) dyn_dtree, d_desc.max_code);
2172
2173 /* Build the bit length tree: */
2174 build_tree((tree_desc *) (&bl_desc));
2175 /* opt_len now includes the length of the tree representations, except
2176 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
2177 */
2178
2179 /* Determine the number of bit length codes to send. The pkzip format
2180 * requires that at least 4 bit length codes be sent. (appnote.txt says
2181 * 3 but the actual value used is 4.)
2182 */
2183 for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
2184 if (bl_tree[bl_order[max_blindex]].Len != 0)
2185 break;
2186 }
2187 /* Update opt_len to include the bit length tree and counts */
2188 opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
2189 Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));
2190
2191 return max_blindex;
2192}
2193
2194/* ===========================================================================
2195 * Send the header for a block using dynamic Huffman trees: the counts, the
2196 * lengths of the bit length codes, the literal tree and the distance tree.
2197 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
2198 */
2199static void send_all_trees(int lcodes, int dcodes, int blcodes)
2200{
2201 int rank; /* index in bl_order */
2202
2203 Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
2204 Assert(lcodes <= L_CODES && dcodes <= D_CODES
2205 && blcodes <= BL_CODES, "too many codes");
2206 Tracev((stderr, "\nbl counts: "));
2207 send_bits(lcodes - 257, 5); /* not +255 as stated in appnote.txt */
2208 send_bits(dcodes - 1, 5);
2209 send_bits(blcodes - 4, 4); /* not -3 as stated in appnote.txt */
2210 for (rank = 0; rank < blcodes; rank++) {
2211 Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
2212 send_bits(bl_tree[bl_order[rank]].Len, 3);
2213 }
2214 Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
2215
2216 send_tree((ct_data *) dyn_ltree, lcodes - 1); /* send the literal tree */
2217 Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
2218
2219 send_tree((ct_data *) dyn_dtree, dcodes - 1); /* send the distance tree */
2220 Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
2221}
2222
2223/* ===========================================================================
2224 * Determine the best encoding for the current block: dynamic trees, static
2225 * trees or store, and output the encoded block to the zip file. This function
2226 * returns the total compressed length for the file so far.
2227 */
2228static ulg flush_block(char *buf, ulg stored_len, int eof)
2229{
2230 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
2231 int max_blindex; /* index of last bit length code of non zero freq */
2232
2233 flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */
2234
2235 /* Check if the file is ascii or binary */
2236 if (*file_type == (ush) UNKNOWN)
2237 set_file_type();
2238
2239 /* Construct the literal and distance trees */
2240 build_tree((tree_desc *) (&l_desc));
2241 Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
2242
2243 build_tree((tree_desc *) (&d_desc));
2244 Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
2245 /* At this point, opt_len and static_len are the total bit lengths of
2246 * the compressed block data, excluding the tree representations.
2247 */
2248
2249 /* Build the bit length tree for the above two trees, and get the index
2250 * in bl_order of the last bit length code to send.
2251 */
2252 max_blindex = build_bl_tree();
2253
2254 /* Determine the best encoding. Compute first the block length in bytes */
2255 opt_lenb = (opt_len + 3 + 7) >> 3;
2256 static_lenb = (static_len + 3 + 7) >> 3;
2257
2258 Trace((stderr,
2259 "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
2260 opt_lenb, opt_len, static_lenb, static_len, stored_len,
2261 last_lit, last_dist));
2262
2263 if (static_lenb <= opt_lenb)
2264 opt_lenb = static_lenb;
2265
2266 /* If compression failed and this is the first and last block,
2267 * and if the zip file can be seeked (to rewrite the local header),
2268 * the whole file is transformed into a stored file:
2269 */
2270 if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
2271 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
2272 if (buf == (char *) 0)
2273 bb_error_msg("block vanished");
2274
2275 copy_block(buf, (unsigned) stored_len, 0); /* without header */
2276 compressed_len = stored_len << 3;
2277 *file_method = STORED;
2278
2279 } else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) {
2280 /* 4: two words for the lengths */
2281 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
2282 * Otherwise we can't have processed more than WSIZE input bytes since
2283 * the last block flush, because compression would have been
2284 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
2285 * transform a block into a stored block.
2286 */
2287 send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */
2288 compressed_len = (compressed_len + 3 + 7) & ~7L;
2289 compressed_len += (stored_len + 4) << 3;
2290
2291 copy_block(buf, (unsigned) stored_len, 1); /* with header */
2292
2293 } else if (static_lenb == opt_lenb) {
2294 send_bits((STATIC_TREES << 1) + eof, 3);
2295 compress_block((ct_data *) static_ltree, (ct_data *) static_dtree);
2296 compressed_len += 3 + static_len;
2297 } else {
2298 send_bits((DYN_TREES << 1) + eof, 3);
2299 send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1,
2300 max_blindex + 1);
2301 compress_block((ct_data *) dyn_ltree, (ct_data *) dyn_dtree);
2302 compressed_len += 3 + opt_len;
2303 }
2304 Assert(compressed_len == bits_sent, "bad compressed size");
2305 init_block();
2306
2307 if (eof) {
2308 bi_windup();
2309 compressed_len += 7; /* align on byte boundary */
2310 }
2311 Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3,
2312 compressed_len - 7 * eof));
2313
2314 return compressed_len >> 3;
2315}
2316
2317/* ===========================================================================
2318 * Save the match info and tally the frequency counts. Return true if
2319 * the current block must be flushed.
2320 */
2321static int ct_tally(int dist, int lc)
2322{
2323 l_buf[last_lit++] = (uch) lc;
2324 if (dist == 0) {
2325 /* lc is the unmatched char */
2326 dyn_ltree[lc].Freq++;
2327 } else {
2328 /* Here, lc is the match length - MIN_MATCH */
2329 dist--; /* dist = match distance - 1 */
2330 Assert((ush) dist < (ush) MAX_DIST &&
2331 (ush) lc <= (ush) (MAX_MATCH - MIN_MATCH) &&
2332 (ush) d_code(dist) < (ush) D_CODES, "ct_tally: bad match");
2333
2334 dyn_ltree[length_code[lc] + LITERALS + 1].Freq++;
2335 dyn_dtree[d_code(dist)].Freq++;
2336
2337 d_buf[last_dist++] = (ush) dist;
2338 flags |= flag_bit;
2339 }
2340 flag_bit <<= 1;
2341
2342 /* Output the flags if they fill a byte: */
2343 if ((last_lit & 7) == 0) {
2344 flag_buf[last_flags++] = flags;
2345 flags = 0, flag_bit = 1;
2346 }
2347 /* Try to guess if it is profitable to stop the current block here */
2348 if ((last_lit & 0xfff) == 0) {
2349 /* Compute an upper bound for the compressed length */
2350 ulg out_length = (ulg) last_lit * 8L;
2351 ulg in_length = (ulg) strstart - block_start;
2352 int dcode;
2353
2354 for (dcode = 0; dcode < D_CODES; dcode++) {
2355 out_length +=
2356 (ulg) dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]);
2357 }
2358 out_length >>= 3;
2359 Trace((stderr,
2360 "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
2361 last_lit, last_dist, in_length, out_length,
2362 100L - out_length * 100L / in_length));
2363 if (last_dist < last_lit / 2 && out_length < in_length / 2)
2364 return 1;
2365 }
2366 return (last_lit == LIT_BUFSIZE - 1 || last_dist == DIST_BUFSIZE);
2367 /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
2368 * on 16 bit machines and because stored blocks are restricted to
2369 * 64K-1 bytes.
2370 */
2371}
2372
2373/* ===========================================================================
2374 * Send the block data compressed using the given Huffman trees
2375 */
2376static void compress_block(ct_data * ltree, ct_data * dtree)
2377{
2378 unsigned dist; /* distance of matched string */
2379 int lc; /* match length or unmatched char (if dist == 0) */
2380 unsigned lx = 0; /* running index in l_buf */
2381 unsigned dx = 0; /* running index in d_buf */
2382 unsigned fx = 0; /* running index in flag_buf */
2383 uch flag = 0; /* current flags */
2384 unsigned code; /* the code to send */
2385 int extra; /* number of extra bits to send */
2386
2387 if (last_lit != 0)
2388 do {
2389 if ((lx & 7) == 0)
2390 flag = flag_buf[fx++];
2391 lc = l_buf[lx++];
2392 if ((flag & 1) == 0) {
2393 send_code(lc, ltree); /* send a literal byte */
2394 Tracecv(isgraph(lc), (stderr, " '%c' ", lc));
2395 } else {
2396 /* Here, lc is the match length - MIN_MATCH */
2397 code = length_code[lc];
2398 send_code(code + LITERALS + 1, ltree); /* send the length code */
2399 extra = extra_lbits[code];
2400 if (extra != 0) {
2401 lc -= base_length[code];
2402 send_bits(lc, extra); /* send the extra length bits */
2403 }
2404 dist = d_buf[dx++];
2405 /* Here, dist is the match distance - 1 */
2406 code = d_code(dist);
2407 Assert(code < D_CODES, "bad d_code");
2408
2409 send_code(code, dtree); /* send the distance code */
2410 extra = extra_dbits[code];
2411 if (extra != 0) {
2412 dist -= base_dist[code];
2413 send_bits(dist, extra); /* send the extra distance bits */
2414 }
2415 } /* literal or match pair ? */
2416 flag >>= 1;
2417 } while (lx < last_lit);
2418
2419 send_code(END_BLOCK, ltree);
2420}
2421
2422/* ===========================================================================
2423 * Set the file type to ASCII or BINARY, using a crude approximation:
2424 * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
2425 * IN assertion: the fields freq of dyn_ltree are set and the total of all
2426 * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
2427 */
2428static void set_file_type()
2429{
2430 int n = 0;
2431 unsigned ascii_freq = 0;
2432 unsigned bin_freq = 0;
2433
2434 while (n < 7)
2435 bin_freq += dyn_ltree[n++].Freq;
2436 while (n < 128)
2437 ascii_freq += dyn_ltree[n++].Freq;
2438 while (n < LITERALS)
2439 bin_freq += dyn_ltree[n++].Freq;
2440 *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
2441 if (*file_type == BINARY && translate_eol) {
2442 bb_error_msg("-l used on binary file");
2443 }
2444}
2445
2446/* zip.c -- compress files to the gzip or pkzip format
2447 * Copyright (C) 1992-1993 Jean-loup Gailly
2448 * This is free software; you can redistribute it and/or modify it under the
2449 * terms of the GNU General Public License, see the file COPYING.
2450 */
2451
2452
2453static ulg crc; /* crc on uncompressed file data */
2454static long header_bytes; /* number of bytes in gzip header */
2455
2456static void put_long(ulg n)
2457{
2458 put_short((n) & 0xffff);
2459 put_short(((ulg) (n)) >> 16);
2460}
2461
2462/* put_header_byte is used for the compressed output
2463 * - for the initial 4 bytes that can't overflow the buffer.
2464 */
2465#define put_header_byte(c) {outbuf[outcnt++]=(uch)(c);}
2466
2467/* ===========================================================================
2468 * Deflate in to out.
2469 * IN assertions: the input and output buffers are cleared.
2470 * The variables time_stamp and save_orig_name are initialized.
2471 */
2472static int zip(int in, int out)
2473{
2474 uch my_flags = 0; /* general purpose bit flags */
2475 ush attr = 0; /* ascii/binary flag */
2476 ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
2477
2478 ifd = in;
2479 ofd = out;
2480 outcnt = 0;
2481
2482 /* Write the header to the gzip file. See algorithm.doc for the format */
2483
2484
2485 method = DEFLATED;
2486 put_header_byte(GZIP_MAGIC[0]); /* magic header */
2487 put_header_byte(GZIP_MAGIC[1]);
2488 put_header_byte(DEFLATED); /* compression method */
2489
2490 put_header_byte(my_flags); /* general flags */
2491 put_long(time_stamp);
2492
2493 /* Write deflated file to zip file */
2494 crc = updcrc(0, 0);
2495
2496 bi_init(out);
2497 ct_init(&attr, &method);
2498 lm_init(&deflate_flags);
2499
2500 put_byte((uch) deflate_flags); /* extra flags */
2501 put_byte(OS_CODE); /* OS identifier */
2502
2503 header_bytes = (long) outcnt;
2504
2505 (void) deflate();
2506
2507 /* Write the crc and uncompressed size */
2508 put_long(crc);
2509 put_long(isize);
2510 header_bytes += 2 * sizeof(long);
2511
2512 flush_outbuf();
2513 return OK;
2514}
2515
2516
2517/* ===========================================================================
2518 * Read a new buffer from the current input file, perform end-of-line
2519 * translation, and update the crc and input file size.
2520 * IN assertion: size >= 2 (for end-of-line translation)
2521 */
2522static int file_read(char *buf, unsigned size)
2523{
2524 unsigned len;
2525
2526 Assert(insize == 0, "inbuf not empty");
2527
2528 len = read(ifd, buf, size);
2529 if (len == (unsigned) (-1) || len == 0)
2530 return (int) len;
2531
2532 crc = updcrc((uch *) buf, len);
2533 isize += (ulg) len;
2534 return (int) len;
2535}
2536
2537/* ===========================================================================
2538 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
2539 * (used for the compressed data only)
2540 */
2541static void flush_outbuf()
2542{
2543 if (outcnt == 0)
2544 return;
2545
2546 write_buf(ofd, (char *) outbuf, outcnt);
2547 outcnt = 0;
2548}
diff --git a/busybox/archival/libunarchive/Makefile b/busybox/archival/libunarchive/Makefile
new file mode 100644
index 000000000..e985fa49f
--- /dev/null
+++ b/busybox/archival/libunarchive/Makefile
@@ -0,0 +1,32 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20top_srcdir=../..
21top_builddir=../..
22srcdir=$(top_srcdir)/archival/libunarchive
23LIBUNARCHIVE_DIR:=./
24include $(top_builddir)/Rules.mak
25include $(top_builddir)/.config
26include $(srcdir)/Makefile.in
27all: $(libraries-y)
28-include $(top_builddir)/.depend
29
30clean:
31 rm -f *.o *.a $(AR_TARGET)
32
diff --git a/busybox/archival/libunarchive/Makefile.in b/busybox/archival/libunarchive/Makefile.in
new file mode 100644
index 000000000..809b0e10e
--- /dev/null
+++ b/busybox/archival/libunarchive/Makefile.in
@@ -0,0 +1,84 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20LIBUNARCHIVE_AR:=libunarchive.a
21ifndef $(LIBUNARCHIVE_DIR)
22LIBUNARCHIVE_DIR:=$(top_builddir)/archival/libunarchive/
23endif
24srcdir=$(top_srcdir)/archvial/libunarchive
25
26LIBUNARCHIVE-y:= \
27\
28 data_skip.o \
29 data_extract_all.o \
30 data_extract_to_stdout.o \
31 data_extract_to_buffer.o \
32\
33 filter_accept_all.o \
34 filter_accept_list.o \
35 filter_accept_reject_list.o \
36\
37 header_skip.o \
38 header_list.o \
39 header_verbose_list.o \
40\
41 archive_xread_all.o \
42 archive_xread_all_eof.o \
43\
44 seek_by_char.o \
45 seek_by_jump.o \
46\
47 data_align.o \
48 find_list_entry.o \
49 open_transformer.o \
50 init_handle.o
51
52GUNZIP_FILES:= check_header_gzip.o decompress_unzip.o
53DPKG_FILES:= \
54 get_header_ar.o \
55 unpack_ar_archive.o \
56 get_header_tar.o \
57 filter_accept_list_reassign.o
58
59LIBUNARCHIVE-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
60LIBUNARCHIVE-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
61LIBUNARCHIVE-$(CONFIG_CPIO) += get_header_cpio.o
62LIBUNARCHIVE-$(CONFIG_DPKG) += $(DPKG_FILES)
63LIBUNARCHIVE-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
64LIBUNARCHIVE-$(CONFIG_FEATURE_DEB_TAR_GZ) += $(GUNZIP_FILES) get_header_tar_gz.o
65LIBUNARCHIVE-$(CONFIG_FEATURE_DEB_TAR_BZ2) += decompress_bunzip2.o get_header_tar_bz2.o
66LIBUNARCHIVE-$(CONFIG_GUNZIP) += $(GUNZIP_FILES)
67LIBUNARCHIVE-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
68LIBUNARCHIVE-$(CONFIG_RPM2CPIO) += $(GUNZIP_FILES) get_header_cpio.o
69LIBUNARCHIVE-$(CONFIG_RPM) += $(GUNZIP_FILES) get_header_cpio.o
70LIBUNARCHIVE-$(CONFIG_TAR) += get_header_tar.o
71LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_BZIP2) += decompress_bunzip2.o get_header_tar_bz2.o
72LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_GZIP) += $(GUNZIP_FILES) get_header_tar_gz.o
73LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_COMPRESS) += decompress_uncompress.o
74LIBUNARCHIVE-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
75LIBUNARCHIVE-$(CONFIG_UNZIP) += $(GUNZIP_FILES)
76
77libraries-y+=$(LIBUNARCHIVE_DIR)$(LIBUNARCHIVE_AR)
78
79$(LIBUNARCHIVE_DIR)$(LIBUNARCHIVE_AR): $(patsubst %,$(LIBUNARCHIVE_DIR)%, $(LIBUNARCHIVE-y))
80 $(AR) -ro $@ $(patsubst %,$(LIBUNARCHIVE_DIR)%, $(LIBUNARCHIVE-y))
81
82$(LIBUNARCHIVA_DIR)%.o: $(srcdir)/%.c
83 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
84
diff --git a/busybox/archival/libunarchive/archive_xread_all.c b/busybox/archival/libunarchive/archive_xread_all.c
new file mode 100644
index 000000000..ba9ade2d5
--- /dev/null
+++ b/busybox/archival/libunarchive/archive_xread_all.c
@@ -0,0 +1,32 @@
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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include "unarchive.h"
21#include "libbb.h"
22
23extern void archive_xread_all(const archive_handle_t *archive_handle, void *buf, const size_t count)
24{
25 ssize_t size;
26
27 size = bb_full_read(archive_handle->src_fd, buf, count);
28 if (size != count) {
29 bb_error_msg_and_die("Short read");
30 }
31 return;
32}
diff --git a/busybox/archival/libunarchive/archive_xread_all_eof.c b/busybox/archival/libunarchive/archive_xread_all_eof.c
new file mode 100644
index 000000000..8084e3524
--- /dev/null
+++ b/busybox/archival/libunarchive/archive_xread_all_eof.c
@@ -0,0 +1,32 @@
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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include "unarchive.h"
21#include "libbb.h"
22
23extern ssize_t archive_xread_all_eof(archive_handle_t *archive_handle, unsigned char *buf, size_t count)
24{
25 ssize_t size;
26
27 size = bb_full_read(archive_handle->src_fd, buf, count);
28 if ((size != 0) && (size != count)) {
29 bb_perror_msg_and_die("Short read, read %d of %d", size, count);
30 }
31 return(size);
32}
diff --git a/busybox/archival/libunarchive/check_header_gzip.c b/busybox/archival/libunarchive/check_header_gzip.c
new file mode 100644
index 000000000..13832c240
--- /dev/null
+++ b/busybox/archival/libunarchive/check_header_gzip.c
@@ -0,0 +1,57 @@
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[8];
9 struct {
10 unsigned char method;
11 unsigned char flags;
12 unsigned int mtime;
13 unsigned char xtra_flags;
14 unsigned char os_flags;
15 } formated;
16 } header;
17
18 bb_xread_all(src_fd, header.raw, 8);
19
20 /* Check the compression method */
21 if (header.formated.method != 8) {
22 bb_error_msg_and_die("Unknown compression method %d",
23 header.formated.method);
24 }
25
26 if (header.formated.flags & 0x04) {
27 /* bit 2 set: extra field present */
28 unsigned char extra_short;
29
30 extra_short = bb_xread_char(src_fd) + (bb_xread_char(src_fd) << 8);
31 while (extra_short > 0) {
32 /* Ignore extra field */
33 bb_xread_char(src_fd);
34 extra_short--;
35 }
36 }
37
38 /* Discard original name if any */
39 if (header.formated.flags & 0x08) {
40 /* bit 3 set: original file name present */
41 while(bb_xread_char(src_fd) != 0);
42 }
43
44 /* Discard file comment if any */
45 if (header.formated.flags & 0x10) {
46 /* bit 4 set: file comment present */
47 while(bb_xread_char(src_fd) != 0);
48 }
49
50 /* Read the header checksum */
51 if (header.formated.flags & 0x02) {
52 bb_xread_char(src_fd);
53 bb_xread_char(src_fd);
54 }
55
56 return;
57}
diff --git a/busybox/archival/libunarchive/data_align.c b/busybox/archival/libunarchive/data_align.c
new file mode 100644
index 000000000..1d433957d
--- /dev/null
+++ b/busybox/archival/libunarchive/data_align.c
@@ -0,0 +1,33 @@
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
19#include <errno.h>
20#include <unistd.h>
21
22#include "libbb.h"
23#include "unarchive.h"
24
25extern void data_align(archive_handle_t *archive_handle, const unsigned short boundary)
26{
27 const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary;
28
29 archive_handle->seek(archive_handle, skip_amount);
30 archive_handle->offset += skip_amount;
31
32 return;
33}
diff --git a/busybox/archival/libunarchive/data_extract_all.c b/busybox/archival/libunarchive/data_extract_all.c
new file mode 100644
index 000000000..d10d665f6
--- /dev/null
+++ b/busybox/archival/libunarchive/data_extract_all.c
@@ -0,0 +1,124 @@
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
19#include <errno.h>
20#include <fcntl.h>
21#include <stdlib.h>
22#include <string.h>
23#include <utime.h>
24#include <unistd.h>
25#include <stdlib.h>
26
27#include "libbb.h"
28#include "unarchive.h"
29
30extern void data_extract_all(archive_handle_t *archive_handle)
31{
32 file_header_t *file_header = archive_handle->file_header;
33 int dst_fd;
34 int res;
35
36 if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
37 char *name = bb_xstrdup(file_header->name);
38 bb_make_directory (dirname(name), -1, FILEUTILS_RECUR);
39 free(name);
40 }
41
42 /* Check if the file already exists */
43 if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) {
44 /* Remove the existing entry if it exists */
45 if (((file_header->mode & S_IFMT) != S_IFDIR) && (unlink(file_header->name) == -1) && (errno != ENOENT)) {
46 bb_perror_msg_and_die("Couldnt remove old file");
47 }
48 }
49 else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) {
50 /* Remove the existing entry if its older than the extracted entry */
51 struct stat statbuf;
52 if (lstat(file_header->name, &statbuf) == -1) {
53 if (errno != ENOENT) {
54 bb_perror_msg_and_die("Couldnt stat old file");
55 }
56 }
57 else if (statbuf.st_mtime <= file_header->mtime) {
58 if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
59 bb_error_msg("%s not created: newer or same age file exists", file_header->name);
60 }
61 data_skip(archive_handle);
62 return;
63 }
64 else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
65 bb_perror_msg_and_die("Couldnt remove old file %s", file_header->name);
66 }
67 }
68
69 /* Handle hard links separately
70 * We identified hard links as regular files of size 0 with a symlink */
71 if (S_ISREG(file_header->mode) && (file_header->link_name) && (file_header->size == 0)) {
72 /* hard link */
73 res = link(file_header->link_name, file_header->name);
74 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
75 bb_perror_msg("Couldnt create hard link");
76 }
77 } else {
78 /* Create the filesystem entry */
79 switch(file_header->mode & S_IFMT) {
80 case S_IFREG: {
81 /* Regular file */
82 dst_fd = bb_xopen(file_header->name, O_WRONLY | O_CREAT | O_EXCL);
83 bb_copyfd_size(archive_handle->src_fd, dst_fd, file_header->size);
84 close(dst_fd);
85 break;
86 }
87 case S_IFDIR:
88 res = mkdir(file_header->name, file_header->mode);
89 if ((errno != EISDIR) && (res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
90 bb_perror_msg("extract_archive: %s", file_header->name);
91 }
92 break;
93 case S_IFLNK:
94 /* Symlink */
95 res = symlink(file_header->link_name, file_header->name);
96 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
97 bb_perror_msg("Cannot create symlink from %s to '%s'", file_header->name, file_header->link_name);
98 }
99 break;
100 case S_IFSOCK:
101 case S_IFBLK:
102 case S_IFCHR:
103 case S_IFIFO:
104 res = mknod(file_header->name, file_header->mode, file_header->device);
105 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
106 bb_perror_msg("Cannot create node %s", file_header->name);
107 }
108 break;
109 default:
110 bb_error_msg_and_die("Unrecognised file type");
111 }
112 }
113
114 lchown(file_header->name, file_header->uid, file_header->gid);
115 if ((file_header->mode & S_IFMT) != S_IFLNK) {
116 chmod(file_header->name, file_header->mode);
117 }
118
119 if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
120 struct utimbuf t;
121 t.actime = t.modtime = file_header->mtime;
122 utime(file_header->name, &t);
123 }
124}
diff --git a/busybox/archival/libunarchive/data_extract_to_buffer.c b/busybox/archival/libunarchive/data_extract_to_buffer.c
new file mode 100644
index 000000000..db5521bcb
--- /dev/null
+++ b/busybox/archival/libunarchive/data_extract_to_buffer.c
@@ -0,0 +1,28 @@
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 "libbb.h"
18#include "unarchive.h"
19
20extern void data_extract_to_buffer(archive_handle_t *archive_handle)
21{
22 const unsigned int size = archive_handle->file_header->size;
23
24 archive_handle->buffer = xmalloc(size + 1);
25
26 archive_xread_all(archive_handle, archive_handle->buffer, size);
27 archive_handle->buffer[size] = '\0';
28}
diff --git a/busybox/archival/libunarchive/data_extract_to_stdout.c b/busybox/archival/libunarchive/data_extract_to_stdout.c
new file mode 100644
index 000000000..df2bca6ef
--- /dev/null
+++ b/busybox/archival/libunarchive/data_extract_to_stdout.c
@@ -0,0 +1,23 @@
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 "unarchive.h"
18#include <unistd.h>
19
20extern void data_extract_to_stdout(archive_handle_t *archive_handle)
21{
22 bb_copyfd_size(archive_handle->src_fd, STDOUT_FILENO, archive_handle->file_header->size);
23}
diff --git a/busybox/archival/libunarchive/data_skip.c b/busybox/archival/libunarchive/data_skip.c
new file mode 100644
index 000000000..b82c9065b
--- /dev/null
+++ b/busybox/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 archive_handle->seek(archive_handle, archive_handle->file_header->size);
27}
diff --git a/busybox/archival/libunarchive/decompress_bunzip2.c b/busybox/archival/libunarchive/decompress_bunzip2.c
new file mode 100644
index 000000000..259a47776
--- /dev/null
+++ b/busybox/archival/libunarchive/decompress_bunzip2.c
@@ -0,0 +1,611 @@
1/* vi: set sw=4 ts=4: */
2/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
3
4 Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
5 which also acknowledges contributions by Mike Burrows, David Wheeler,
6 Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
7 Robert Sedgewick, and Jon L. Bentley.
8
9 This code is licensed under the LGPLv2:
10 LGPL (http://www.gnu.org/copyleft/lgpl.html
11*/
12
13/*
14 Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org).
15
16 More efficient reading of Huffman codes, a streamlined read_bunzip()
17 function, and various other tweaks. In (limited) tests, approximately
18 20% faster than bzcat on x86 and about 10% faster on arm.
19
20 Note that about 2/3 of the time is spent in read_unzip() reversing
21 the Burrows-Wheeler transformation. Much of that time is delay
22 resulting from cache misses.
23
24 I would ask that anyone benefiting from this work, especially those
25 using it in commercial products, consider making a donation to my local
26 non-profit hospice organization in the name of the woman I loved, who
27 passed away Feb. 12, 2003.
28
29 In memory of Toni W. Hagan
30
31 Hospice of Acadiana, Inc.
32 2600 Johnston St., Suite 200
33 Lafayette, LA 70503-3240
34
35 Phone (337) 232-1234 or 1-800-738-2226
36 Fax (337) 232-1297
37
38 http://www.hospiceacadiana.com/
39
40 Manuel
41 */
42
43#include <setjmp.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48#include <limits.h>
49
50#include "libbb.h"
51
52/* Constants for Huffman coding */
53#define MAX_GROUPS 6
54#define GROUP_SIZE 50 /* 64 would have been more efficient */
55#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */
56#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */
57#define SYMBOL_RUNA 0
58#define SYMBOL_RUNB 1
59
60/* Status return values */
61#define RETVAL_OK 0
62#define RETVAL_LAST_BLOCK (-1)
63#define RETVAL_NOT_BZIP_DATA (-2)
64#define RETVAL_UNEXPECTED_INPUT_EOF (-3)
65#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4)
66#define RETVAL_DATA_ERROR (-5)
67#define RETVAL_OUT_OF_MEMORY (-6)
68#define RETVAL_OBSOLETE_INPUT (-7)
69
70/* Other housekeeping constants */
71#define IOBUF_SIZE 4096
72
73/* This is what we know about each Huffman coding group */
74struct group_data {
75 /* We have an extra slot at the end of limit[] for a sentinal value. */
76 int limit[MAX_HUFCODE_BITS+1],base[MAX_HUFCODE_BITS],permute[MAX_SYMBOLS];
77 int minLen, maxLen;
78};
79
80/* Structure holding all the housekeeping data, including IO buffers and
81 memory that persists between calls to bunzip */
82typedef struct {
83 /* State for interrupting output loop */
84 int writeCopies,writePos,writeRunCountdown,writeCount,writeCurrent;
85 /* I/O tracking data (file handles, buffers, positions, etc.) */
86 int in_fd,out_fd,inbufCount,inbufPos /*,outbufPos*/;
87 unsigned char *inbuf /*,*outbuf*/;
88 unsigned int inbufBitCount, inbufBits;
89 /* The CRC values stored in the block header and calculated from the data */
90 unsigned int crc32Table[256],headerCRC, totalCRC, writeCRC;
91 /* Intermediate buffer and its size (in bytes) */
92 unsigned int *dbuf, dbufSize;
93 /* These things are a bit too big to go on the stack */
94 unsigned char selectors[32768]; /* nSelectors=15 bits */
95 struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
96 /* For I/O error handling */
97 jmp_buf jmpbuf;
98} bunzip_data;
99
100/* Return the next nnn bits of input. All reads from the compressed input
101 are done through this function. All reads are big endian */
102static unsigned int get_bits(bunzip_data *bd, char bits_wanted)
103{
104 unsigned int bits=0;
105
106 /* If we need to get more data from the byte buffer, do so. (Loop getting
107 one byte at a time to enforce endianness and avoid unaligned access.) */
108 while (bd->inbufBitCount<bits_wanted) {
109 /* If we need to read more data from file into byte buffer, do so */
110 if(bd->inbufPos==bd->inbufCount) {
111 if((bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE)) <= 0)
112 longjmp(bd->jmpbuf,RETVAL_UNEXPECTED_INPUT_EOF);
113 bd->inbufPos=0;
114 }
115 /* Avoid 32-bit overflow (dump bit buffer to top of output) */
116 if(bd->inbufBitCount>=24) {
117 bits=bd->inbufBits&((1<<bd->inbufBitCount)-1);
118 bits_wanted-=bd->inbufBitCount;
119 bits<<=bits_wanted;
120 bd->inbufBitCount=0;
121 }
122 /* Grab next 8 bits of input from buffer. */
123 bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++];
124 bd->inbufBitCount+=8;
125 }
126 /* Calculate result */
127 bd->inbufBitCount-=bits_wanted;
128 bits|=(bd->inbufBits>>bd->inbufBitCount)&((1<<bits_wanted)-1);
129
130 return bits;
131}
132
133/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */
134
135static int get_next_block(bunzip_data *bd)
136{
137 /* Note: Ignore the warning about hufGroup, base and limit being used uninitialized.
138 * They will be initialized on the fist pass of the loop. */
139 struct group_data *hufGroup;
140 int dbufCount,nextSym,dbufSize,groupCount,*base,*limit,selector,
141 i,j,k,t,runPos,symCount,symTotal,nSelectors,byteCount[256];
142 unsigned char uc, symToByte[256], mtfSymbol[256], *selectors;
143 unsigned int *dbuf,origPtr;
144
145 dbuf=bd->dbuf;
146 dbufSize=bd->dbufSize;
147 selectors=bd->selectors;
148 /* Reset longjmp I/O error handling */
149 i=setjmp(bd->jmpbuf);
150 if(i) return i;
151 /* Read in header signature and CRC, then validate signature.
152 (last block signature means CRC is for whole file, return now) */
153 i = get_bits(bd,24);
154 j = get_bits(bd,24);
155 bd->headerCRC=get_bits(bd,32);
156 if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK;
157 if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA;
158 /* We can add support for blockRandomised if anybody complains. There was
159 some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
160 it didn't actually work. */
161 if(get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT;
162 if((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR;
163 /* mapping table: if some byte values are never used (encoding things
164 like ascii text), the compression code removes the gaps to have fewer
165 symbols to deal with, and writes a sparse bitfield indicating which
166 values were present. We make a translation table to convert the symbols
167 back to the corresponding bytes. */
168 t=get_bits(bd, 16);
169 symTotal=0;
170 for (i=0;i<16;i++) {
171 if(t&(1<<(15-i))) {
172 k=get_bits(bd,16);
173 for(j=0;j<16;j++)
174 if(k&(1<<(15-j))) symToByte[symTotal++]=(16*i)+j;
175 }
176 }
177 /* How many different Huffman coding groups does this block use? */
178 groupCount=get_bits(bd,3);
179 if (groupCount<2 || groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR;
180 /* nSelectors: Every GROUP_SIZE many symbols we select a new Huffman coding
181 group. Read in the group selector list, which is stored as MTF encoded
182 bit runs. (MTF=Move To Front, as each value is used it's moved to the
183 start of the list.) */
184 if(!(nSelectors=get_bits(bd, 15))) return RETVAL_DATA_ERROR;
185 for(i=0; i<groupCount; i++) mtfSymbol[i] = i;
186 for(i=0; i<nSelectors; i++) {
187 /* Get next value */
188 for(j=0;get_bits(bd,1);j++) if (j>=groupCount) return RETVAL_DATA_ERROR;
189 /* Decode MTF to get the next selector */
190 uc = mtfSymbol[j];
191 for(;j;j--) mtfSymbol[j] = mtfSymbol[j-1];
192 mtfSymbol[0]=selectors[i]=uc;
193 }
194 /* Read the Huffman coding tables for each group, which code for symTotal
195 literal symbols, plus two run symbols (RUNA, RUNB) */
196 symCount=symTotal+2;
197 for (j=0; j<groupCount; j++) {
198 unsigned char length[MAX_SYMBOLS],temp[MAX_HUFCODE_BITS+1];
199 int minLen, maxLen, pp;
200 /* Read Huffman code lengths for each symbol. They're stored in
201 a way similar to mtf; record a starting value for the first symbol,
202 and an offset from the previous value for everys symbol after that.
203 (Subtracting 1 before the loop and then adding it back at the end is
204 an optimization that makes the test inside the loop simpler: symbol
205 length 0 becomes negative, so an unsigned inequality catches it.) */
206 t=get_bits(bd, 5)-1;
207 for (i = 0; i < symCount; i++) {
208 for(;;) {
209 if (((unsigned)t) > (MAX_HUFCODE_BITS-1))
210 return RETVAL_DATA_ERROR;
211 /* If first bit is 0, stop. Else second bit indicates whether
212 to increment or decrement the value. Optimization: grab 2
213 bits and unget the second if the first was 0. */
214 k = get_bits(bd,2);
215 if (k < 2) {
216 bd->inbufBitCount++;
217 break;
218 }
219 /* Add one if second bit 1, else subtract 1. Avoids if/else */
220 t+=(((k+1)&2)-1);
221 }
222 /* Correct for the initial -1, to get the final symbol length */
223 length[i]=t+1;
224 }
225 /* Find largest and smallest lengths in this group */
226 minLen=maxLen=length[0];
227 for(i = 1; i < symCount; i++) {
228 if(length[i] > maxLen) maxLen = length[i];
229 else if(length[i] < minLen) minLen = length[i];
230 }
231 /* Calculate permute[], base[], and limit[] tables from length[].
232 *
233 * permute[] is the lookup table for converting Huffman coded symbols
234 * into decoded symbols. base[] is the amount to subtract from the
235 * value of a Huffman symbol of a given length when using permute[].
236 *
237 * limit[] indicates the largest numerical value a symbol with a given
238 * number of bits can have. This is how the Huffman codes can vary in
239 * length: each code with a value>limit[length] needs another bit.
240 */
241 hufGroup=bd->groups+j;
242 hufGroup->minLen = minLen;
243 hufGroup->maxLen = maxLen;
244 /* Note that minLen can't be smaller than 1, so we adjust the base
245 and limit array pointers so we're not always wasting the first
246 entry. We do this again when using them (during symbol decoding).*/
247 base=hufGroup->base-1;
248 limit=hufGroup->limit-1;
249 /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */
250 pp=0;
251 for(i=minLen;i<=maxLen;i++) {
252 temp[i]=limit[i]=0;
253 for(t=0;t<symCount;t++)
254 if(length[t]==i) hufGroup->permute[pp++] = t;
255 }
256 /* Count symbols coded for at each bit length */
257 for (i=0;i<symCount;i++) temp[length[i]]++;
258 /* Calculate limit[] (the largest symbol-coding value at each bit
259 * length, which is (previous limit<<1)+symbols at this level), and
260 * base[] (number of symbols to ignore at each bit length, which is
261 * limit minus the cumulative count of symbols coded for already). */
262 pp=t=0;
263 for (i=minLen; i<maxLen; i++) {
264 pp+=temp[i];
265 /* We read the largest possible symbol size and then unget bits
266 after determining how many we need, and those extra bits could
267 be set to anything. (They're noise from future symbols.) At
268 each level we're really only interested in the first few bits,
269 so here we set all the trailing to-be-ignored bits to 1 so they
270 don't affect the value>limit[length] comparison. */
271 limit[i]= (pp << (maxLen - i)) - 1;
272 pp<<=1;
273 base[i+1]=pp-(t+=temp[i]);
274 }
275 limit[maxLen+1] = INT_MAX; /* Sentinal value for reading next sym. */
276 limit[maxLen]=pp+temp[maxLen]-1;
277 base[minLen]=0;
278 }
279 /* We've finished reading and digesting the block header. Now read this
280 block's Huffman coded symbols from the file and undo the Huffman coding
281 and run length encoding, saving the result into dbuf[dbufCount++]=uc */
282
283 /* Initialize symbol occurrence counters and symbol Move To Front table */
284 for(i=0;i<256;i++) {
285 byteCount[i] = 0;
286 mtfSymbol[i]=(unsigned char)i;
287 }
288 /* Loop through compressed symbols. */
289 runPos=dbufCount=symCount=selector=0;
290 for(;;) {
291 /* Determine which Huffman coding group to use. */
292 if(!(symCount--)) {
293 symCount=GROUP_SIZE-1;
294 if(selector>=nSelectors) return RETVAL_DATA_ERROR;
295 hufGroup=bd->groups+selectors[selector++];
296 base=hufGroup->base-1;
297 limit=hufGroup->limit-1;
298 }
299 /* Read next Huffman-coded symbol. */
300 /* Note: It is far cheaper to read maxLen bits and back up than it is
301 to read minLen bits and then an additional bit at a time, testing
302 as we go. Because there is a trailing last block (with file CRC),
303 there is no danger of the overread causing an unexpected EOF for a
304 valid compressed file. As a further optimization, we do the read
305 inline (falling back to a call to get_bits if the buffer runs
306 dry). The following (up to got_huff_bits:) is equivalent to
307 j=get_bits(bd,hufGroup->maxLen);
308 */
309 while (bd->inbufBitCount<hufGroup->maxLen) {
310 if(bd->inbufPos==bd->inbufCount) {
311 j = get_bits(bd,hufGroup->maxLen);
312 goto got_huff_bits;
313 }
314 bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++];
315 bd->inbufBitCount+=8;
316 };
317 bd->inbufBitCount-=hufGroup->maxLen;
318 j = (bd->inbufBits>>bd->inbufBitCount)&((1<<hufGroup->maxLen)-1);
319got_huff_bits:
320 /* Figure how how many bits are in next symbol and unget extras */
321 i=hufGroup->minLen;
322 while(j>limit[i]) ++i;
323 bd->inbufBitCount += (hufGroup->maxLen - i);
324 /* Huffman decode value to get nextSym (with bounds checking) */
325 if ((i > hufGroup->maxLen)
326 || (((unsigned)(j=(j>>(hufGroup->maxLen-i))-base[i]))
327 >= MAX_SYMBOLS))
328 return RETVAL_DATA_ERROR;
329 nextSym = hufGroup->permute[j];
330 /* We have now decoded the symbol, which indicates either a new literal
331 byte, or a repeated run of the most recent literal byte. First,
332 check if nextSym indicates a repeated run, and if so loop collecting
333 how many times to repeat the last literal. */
334 if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */
335 /* If this is the start of a new run, zero out counter */
336 if(!runPos) {
337 runPos = 1;
338 t = 0;
339 }
340 /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at
341 each bit position, add 1 or 2 instead. For example,
342 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2.
343 You can make any bit pattern that way using 1 less symbol than
344 the basic or 0/1 method (except all bits 0, which would use no
345 symbols, but a run of length 0 doesn't mean anything in this
346 context). Thus space is saved. */
347 t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
348 runPos <<= 1;
349 continue;
350 }
351 /* When we hit the first non-run symbol after a run, we now know
352 how many times to repeat the last literal, so append that many
353 copies to our buffer of decoded symbols (dbuf) now. (The last
354 literal used is the one at the head of the mtfSymbol array.) */
355 if(runPos) {
356 runPos=0;
357 if(dbufCount+t>=dbufSize) return RETVAL_DATA_ERROR;
358
359 uc = symToByte[mtfSymbol[0]];
360 byteCount[uc] += t;
361 while(t--) dbuf[dbufCount++]=uc;
362 }
363 /* Is this the terminating symbol? */
364 if(nextSym>symTotal) break;
365 /* At this point, nextSym indicates a new literal character. Subtract
366 one to get the position in the MTF array at which this literal is
367 currently to be found. (Note that the result can't be -1 or 0,
368 because 0 and 1 are RUNA and RUNB. But another instance of the
369 first symbol in the mtf array, position 0, would have been handled
370 as part of a run above. Therefore 1 unused mtf position minus
371 2 non-literal nextSym values equals -1.) */
372 if(dbufCount>=dbufSize) return RETVAL_DATA_ERROR;
373 i = nextSym - 1;
374 uc = mtfSymbol[i];
375 /* Adjust the MTF array. Since we typically expect to move only a
376 * small number of symbols, and are bound by 256 in any case, using
377 * memmove here would typically be bigger and slower due to function
378 * call overhead and other assorted setup costs. */
379 do {
380 mtfSymbol[i] = mtfSymbol[i-1];
381 } while (--i);
382 mtfSymbol[0] = uc;
383 uc=symToByte[uc];
384 /* We have our literal byte. Save it into dbuf. */
385 byteCount[uc]++;
386 dbuf[dbufCount++] = (unsigned int)uc;
387 }
388 /* At this point, we've read all the Huffman-coded symbols (and repeated
389 runs) for this block from the input stream, and decoded them into the
390 intermediate buffer. There are dbufCount many decoded bytes in dbuf[].
391 Now undo the Burrows-Wheeler transform on dbuf.
392 See http://dogma.net/markn/articles/bwt/bwt.htm
393 */
394 /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
395 j=0;
396 for(i=0;i<256;i++) {
397 k=j+byteCount[i];
398 byteCount[i] = j;
399 j=k;
400 }
401 /* Figure out what order dbuf would be in if we sorted it. */
402 for (i=0;i<dbufCount;i++) {
403 uc=(unsigned char)(dbuf[i] & 0xff);
404 dbuf[byteCount[uc]] |= (i << 8);
405 byteCount[uc]++;
406 }
407 /* Decode first byte by hand to initialize "previous" byte. Note that it
408 doesn't get output, and if the first three characters are identical
409 it doesn't qualify as a run (hence writeRunCountdown=5). */
410 if(dbufCount) {
411 if(origPtr>=dbufCount) return RETVAL_DATA_ERROR;
412 bd->writePos=dbuf[origPtr];
413 bd->writeCurrent=(unsigned char)(bd->writePos&0xff);
414 bd->writePos>>=8;
415 bd->writeRunCountdown=5;
416 }
417 bd->writeCount=dbufCount;
418
419 return RETVAL_OK;
420}
421
422/* Undo burrows-wheeler transform on intermediate buffer to produce output.
423 If start_bunzip was initialized with out_fd=-1, then up to len bytes of
424 data are written to outbuf. Return value is number of bytes written or
425 error (all errors are negative numbers). If out_fd!=-1, outbuf and len
426 are ignored, data is written to out_fd and return is RETVAL_OK or error.
427*/
428
429static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
430{
431 const unsigned int *dbuf;
432 int pos,current,previous,gotcount;
433
434 /* If last read was short due to end of file, return last block now */
435 if(bd->writeCount<0) return bd->writeCount;
436
437 gotcount = 0;
438 dbuf=bd->dbuf;
439 pos=bd->writePos;
440 current=bd->writeCurrent;
441
442 /* We will always have pending decoded data to write into the output
443 buffer unless this is the very first call (in which case we haven't
444 Huffman-decoded a block into the intermediate buffer yet). */
445
446 if (bd->writeCopies) {
447 /* Inside the loop, writeCopies means extra copies (beyond 1) */
448 --bd->writeCopies;
449 /* Loop outputting bytes */
450 for(;;) {
451 /* If the output buffer is full, snapshot state and return */
452 if(gotcount >= len) {
453 bd->writePos=pos;
454 bd->writeCurrent=current;
455 bd->writeCopies++;
456 return len;
457 }
458 /* Write next byte into output buffer, updating CRC */
459 outbuf[gotcount++] = current;
460 bd->writeCRC=(((bd->writeCRC)<<8)
461 ^bd->crc32Table[((bd->writeCRC)>>24)^current]);
462 /* Loop now if we're outputting multiple copies of this byte */
463 if (bd->writeCopies) {
464 --bd->writeCopies;
465 continue;
466 }
467decode_next_byte:
468 if (!bd->writeCount--) break;
469 /* Follow sequence vector to undo Burrows-Wheeler transform */
470 previous=current;
471 pos=dbuf[pos];
472 current=pos&0xff;
473 pos>>=8;
474 /* After 3 consecutive copies of the same byte, the 4th is a repeat
475 count. We count down from 4 instead
476 * of counting up because testing for non-zero is faster */
477 if(--bd->writeRunCountdown) {
478 if(current!=previous) bd->writeRunCountdown=4;
479 } else {
480 /* We have a repeated run, this byte indicates the count */
481 bd->writeCopies=current;
482 current=previous;
483 bd->writeRunCountdown=5;
484 /* Sometimes there are just 3 bytes (run length 0) */
485 if(!bd->writeCopies) goto decode_next_byte;
486 /* Subtract the 1 copy we'd output anyway to get extras */
487 --bd->writeCopies;
488 }
489 }
490 /* Decompression of this block completed successfully */
491 bd->writeCRC=~bd->writeCRC;
492 bd->totalCRC=((bd->totalCRC<<1) | (bd->totalCRC>>31)) ^ bd->writeCRC;
493 /* If this block had a CRC error, force file level CRC error. */
494 if(bd->writeCRC!=bd->headerCRC) {
495 bd->totalCRC=bd->headerCRC+1;
496 return RETVAL_LAST_BLOCK;
497 }
498 }
499
500 /* Refill the intermediate buffer by Huffman-decoding next block of input */
501 /* (previous is just a convenient unused temp variable here) */
502 previous=get_next_block(bd);
503 if(previous) {
504 bd->writeCount=previous;
505 return (previous!=RETVAL_LAST_BLOCK) ? previous : gotcount;
506 }
507 bd->writeCRC=0xffffffffUL;
508 pos=bd->writePos;
509 current=bd->writeCurrent;
510 goto decode_next_byte;
511}
512
513/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain
514 a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
515 ignored, and data is read from file handle into temporary buffer. */
516static int start_bunzip(bunzip_data **bdp, int in_fd, char *inbuf, int len)
517{
518 bunzip_data *bd;
519 unsigned int i,j,c;
520 const unsigned int BZh0=(((unsigned int)'B')<<24)+(((unsigned int)'Z')<<16)
521 +(((unsigned int)'h')<<8)+(unsigned int)'0';
522
523 /* Figure out how much data to allocate */
524 i=sizeof(bunzip_data);
525 if(in_fd!=-1) i+=IOBUF_SIZE;
526 /* Allocate bunzip_data. Most fields initialize to zero. */
527 bd=*bdp=xmalloc(i);
528 memset(bd,0,sizeof(bunzip_data));
529 /* Setup input buffer */
530 if(-1==(bd->in_fd=in_fd)) {
531 bd->inbuf=inbuf;
532 bd->inbufCount=len;
533 } else bd->inbuf=(unsigned char *)(bd+1);
534 /* Init the CRC32 table (big endian) */
535 for(i=0;i<256;i++) {
536 c=i<<24;
537 for(j=8;j;j--)
538 c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1);
539 bd->crc32Table[i]=c;
540 }
541 /* Setup for I/O error handling via longjmp */
542 i=setjmp(bd->jmpbuf);
543 if(i) return i;
544
545 /* Ensure that file starts with "BZh['1'-'9']." */
546 i = get_bits(bd,32);
547 if (((unsigned int)(i-BZh0-1)) >= 9) return RETVAL_NOT_BZIP_DATA;
548
549 /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
550 uncompressed data. Allocate intermediate buffer for block. */
551 bd->dbufSize=100000*(i-BZh0);
552
553 bd->dbuf=xmalloc(bd->dbufSize * sizeof(int));
554 return RETVAL_OK;
555}
556
557/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data,
558 not end of file.) */
559extern int uncompressStream(int src_fd, int dst_fd)
560{
561 char *outbuf;
562 bunzip_data *bd;
563 int i;
564
565 outbuf=xmalloc(IOBUF_SIZE);
566 if(!(i=start_bunzip(&bd,src_fd,0,0))) {
567 for(;;) {
568 if((i=read_bunzip(bd,outbuf,IOBUF_SIZE)) <= 0) break;
569 if(i!=write(dst_fd,outbuf,i)) {
570 i=RETVAL_UNEXPECTED_OUTPUT_EOF;
571 break;
572 }
573 }
574 }
575 /* Check CRC and release memory */
576 if(i==RETVAL_LAST_BLOCK) {
577 if (bd->headerCRC!=bd->totalCRC) {
578 bb_error_msg("Data integrity error when decompressing.");
579 } else {
580 i=RETVAL_OK;
581 }
582 }
583 else if (i==RETVAL_UNEXPECTED_OUTPUT_EOF) {
584 bb_error_msg("Compressed file ends unexpectedly");
585 } else {
586 bb_error_msg("Decompression failed");
587 }
588 if(bd->dbuf) free(bd->dbuf);
589 free(bd);
590 free(outbuf);
591
592 return i;
593}
594
595#ifdef TESTING
596
597static char * const bunzip_errors[]={NULL,"Bad file checksum","Not bzip data",
598 "Unexpected input EOF","Unexpected output EOF","Data error",
599 "Out of memory","Obsolete (pre 0.9.5) bzip format not supported."};
600
601/* Dumb little test thing, decompress stdin to stdout */
602int main(int argc, char *argv[])
603{
604 int i=uncompressStream(0,1);
605 char c;
606
607 if(i) fprintf(stderr,"%s\n", bunzip_errors[-i]);
608 else if(read(0,&c,1)) fprintf(stderr,"Trailing garbage ignored\n");
609 return -i;
610}
611#endif
diff --git a/busybox/archival/libunarchive/decompress_uncompress.c b/busybox/archival/libunarchive/decompress_uncompress.c
new file mode 100644
index 000000000..e39872cbe
--- /dev/null
+++ b/busybox/archival/libunarchive/decompress_uncompress.c
@@ -0,0 +1,293 @@
1#include "config.h"
2#include "libbb.h"
3
4/* uncompress for busybox -- (c) 2002 Robert Griebl
5 *
6 * based on the original compress42.c source
7 * (see disclaimer below)
8 */
9
10
11/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
12 *
13 * Authors:
14 * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
15 * Jim McKie (decvax!mcvax!jim)
16 * Steve Davies (decvax!vax135!petsd!peora!srd)
17 * Ken Turkowski (decvax!decwrl!turtlevax!ken)
18 * James A. Woods (decvax!ihnp4!ames!jaw)
19 * Joe Orost (decvax!vax135!petsd!joe)
20 * Dave Mack (csu@alembic.acs.com)
21 * Peter Jannesen, Network Communication Systems
22 * (peter@ncs.nl)
23 *
24 * marc@suse.de : a small security fix for a buffer overflow
25 *
26 * [... History snipped ...]
27 *
28 */
29#include <stdio.h>
30#include <string.h>
31#include <unistd.h>
32
33/* Default input buffer size */
34#define IBUFSIZ 2048
35
36/* Default output buffer size */
37#define OBUFSIZ 2048
38
39/* Defines for third byte of header */
40#define MAGIC_1 (char_type)'\037' /* First byte of compressed file */
41#define MAGIC_2 (char_type)'\235' /* Second byte of compressed file */
42#define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */
43 /* Masks 0x20 and 0x40 are free. */
44 /* I think 0x20 should mean that there is */
45 /* a fourth header byte (for expansion). */
46#define BLOCK_MODE 0x80 /* Block compresssion if table is full and */
47 /* compression rate is dropping flush tables */
48 /* the next two codes should not be changed lightly, as they must not */
49 /* lie within the contiguous general code space. */
50#define FIRST 257 /* first free entry */
51#define CLEAR 256 /* table clear output code */
52
53#define INIT_BITS 9 /* initial number of bits/code */
54
55
56/* machine variants which require cc -Dmachine: pdp11, z8000, DOS */
57#define FAST
58
59#define HBITS 17 /* 50% occupancy */
60#define HSIZE (1<<HBITS)
61#define HMASK (HSIZE-1)
62#define HPRIME 9941
63#define BITS 16
64#undef MAXSEG_64K
65#define MAXCODE(n) (1L << (n))
66
67/* Block compress mode -C compatible with 2.0 */
68int block_mode = BLOCK_MODE;
69
70/* user settable max # bits/code */
71int maxbits = BITS;
72
73/* Exitcode of compress (-1 no file compressed) */
74int exit_code = -1;
75
76/* Input buffer */
77unsigned char inbuf[IBUFSIZ + 64];
78
79/* Output buffer */
80unsigned char outbuf[OBUFSIZ + 2048];
81
82
83long int htab[HSIZE];
84unsigned short codetab[HSIZE];
85
86#define htabof(i) htab[i]
87#define codetabof(i) codetab[i]
88#define tab_prefixof(i) codetabof(i)
89#define tab_suffixof(i) ((unsigned char *)(htab))[i]
90#define de_stack ((unsigned char *)&(htab[HSIZE-1]))
91#define clear_htab() memset(htab, -1, sizeof(htab))
92#define clear_tab_prefixof() memset(codetab, 0, 256);
93
94
95/*
96 * Decompress stdin to stdout. This routine adapts to the codes in the
97 * file building the "string" table on-the-fly; requiring no table to
98 * be stored in the compressed file. The tables used herein are shared
99 * with those of the compress() routine. See the definitions above.
100 */
101
102extern int uncompress(int fd_in, int fd_out)
103{
104 unsigned char *stackp;
105 long int code;
106 int finchar;
107 long int oldcode;
108 long int incode;
109 int inbits;
110 int posbits;
111 int outpos;
112 int insize;
113 int bitmask;
114 long int free_ent;
115 long int maxcode;
116 long int maxmaxcode;
117 int n_bits;
118 int rsize = 0;
119
120 insize = 0;
121
122 inbuf[0] = bb_xread_char(fd_in);
123
124 maxbits = inbuf[0] & BIT_MASK;
125 block_mode = inbuf[0] & BLOCK_MODE;
126 maxmaxcode = MAXCODE(maxbits);
127
128 if (maxbits > BITS) {
129 bb_error_msg("compressed with %d bits, can only handle %d bits", maxbits,
130 BITS);
131 return -1;
132 }
133
134 maxcode = MAXCODE(n_bits = INIT_BITS) - 1;
135 bitmask = (1 << n_bits) - 1;
136 oldcode = -1;
137 finchar = 0;
138 outpos = 0;
139 posbits = 0 << 3;
140
141 free_ent = ((block_mode) ? FIRST : 256);
142
143 /* As above, initialize the first 256 entries in the table. */
144 clear_tab_prefixof();
145
146 for (code = 255; code >= 0; --code) {
147 tab_suffixof(code) = (unsigned char) code;
148 }
149
150 do {
151 resetbuf:;
152 {
153 int i;
154 int e;
155 int o;
156
157 e = insize - (o = (posbits >> 3));
158
159 for (i = 0; i < e; ++i)
160 inbuf[i] = inbuf[i + o];
161
162 insize = e;
163 posbits = 0;
164 }
165
166 if (insize < (int) sizeof(inbuf) - IBUFSIZ) {
167 rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ);
168 insize += rsize;
169 }
170
171 inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 :
172 (insize << 3) - (n_bits - 1));
173
174 while (inbits > posbits) {
175 if (free_ent > maxcode) {
176 posbits =
177 ((posbits - 1) +
178 ((n_bits << 3) -
179 (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
180 ++n_bits;
181 if (n_bits == maxbits) {
182 maxcode = maxmaxcode;
183 } else {
184 maxcode = MAXCODE(n_bits) - 1;
185 }
186 bitmask = (1 << n_bits) - 1;
187 goto resetbuf;
188 }
189 {
190 unsigned char *p = &inbuf[posbits >> 3];
191
192 code =
193 ((((long) (p[0])) | ((long) (p[1]) << 8) |
194 ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask;
195 }
196 posbits += n_bits;
197
198
199 if (oldcode == -1) {
200 outbuf[outpos++] = (unsigned char) (finchar =
201 (int) (oldcode = code));
202 continue;
203 }
204
205 if (code == CLEAR && block_mode) {
206 clear_tab_prefixof();
207 free_ent = FIRST - 1;
208 posbits =
209 ((posbits - 1) +
210 ((n_bits << 3) -
211 (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
212 maxcode = MAXCODE(n_bits = INIT_BITS) - 1;
213 bitmask = (1 << n_bits) - 1;
214 goto resetbuf;
215 }
216
217 incode = code;
218 stackp = de_stack;
219
220 /* Special case for KwKwK string. */
221 if (code >= free_ent) {
222 if (code > free_ent) {
223 unsigned char *p;
224
225 posbits -= n_bits;
226 p = &inbuf[posbits >> 3];
227
228 bb_error_msg
229 ("insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)",
230 insize, posbits, p[-1], p[0], p[1], p[2], p[3],
231 (posbits & 07));
232 bb_error_msg("uncompress: corrupt input");
233 return -1;
234 }
235
236 *--stackp = (unsigned char) finchar;
237 code = oldcode;
238 }
239
240 /* Generate output characters in reverse order */
241 while ((long int) code >= (long int) 256) {
242 *--stackp = tab_suffixof(code);
243 code = tab_prefixof(code);
244 }
245
246 *--stackp = (unsigned char) (finchar = tab_suffixof(code));
247
248 /* And put them out in forward order */
249 {
250 int i;
251
252 if (outpos + (i = (de_stack - stackp)) >= OBUFSIZ) {
253 do {
254 if (i > OBUFSIZ - outpos) {
255 i = OBUFSIZ - outpos;
256 }
257
258 if (i > 0) {
259 memcpy(outbuf + outpos, stackp, i);
260 outpos += i;
261 }
262
263 if (outpos >= OBUFSIZ) {
264 write(fd_out, outbuf, outpos);
265 outpos = 0;
266 }
267 stackp += i;
268 } while ((i = (de_stack - stackp)) > 0);
269 } else {
270 memcpy(outbuf + outpos, stackp, i);
271 outpos += i;
272 }
273 }
274
275 /* Generate the new entry. */
276 if ((code = free_ent) < maxmaxcode) {
277 tab_prefixof(code) = (unsigned short) oldcode;
278 tab_suffixof(code) = (unsigned char) finchar;
279 free_ent = code + 1;
280 }
281
282 /* Remember previous code. */
283 oldcode = incode;
284 }
285
286 } while (rsize > 0);
287
288 if (outpos > 0) {
289 write(fd_out, outbuf, outpos);
290 }
291
292 return 0;
293}
diff --git a/busybox/archival/libunarchive/decompress_unzip.c b/busybox/archival/libunarchive/decompress_unzip.c
new file mode 100644
index 000000000..e8cf54bff
--- /dev/null
+++ b/busybox/archival/libunarchive/decompress_unzip.c
@@ -0,0 +1,982 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * gunzip implementation for busybox
4 *
5 * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
6 *
7 * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
8 * based on gzip sources
9 *
10 * Adjusted further by Erik Andersen <andersen@codepoet.org> to support
11 * files as well as stdin/stdout, and to generally behave itself wrt
12 * command line handling.
13 *
14 * General cleanup to better adhere to the style guide and make use of standard
15 * busybox functions by Glenn McGrath <bug1@iinet.net.au>
16 *
17 * read_gz interface + associated hacking by Laurence Anderson
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 *
33 *
34 * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
35 * Copyright (C) 1992-1993 Jean-loup Gailly
36 * The unzip code was written and put in the public domain by Mark Adler.
37 * Portions of the lzw code are derived from the public domain 'compress'
38 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
39 * Ken Turkowski, Dave Mack and Peter Jannesen.
40 *
41 * See the license_msg below and the file COPYING for the software license.
42 * See the file algorithm.doc for the compression algorithms and file formats.
43 */
44
45#if 0
46static char *license_msg[] = {
47 " Copyright (C) 1992-1993 Jean-loup Gailly",
48 " This program is free software; you can redistribute it and/or modify",
49 " it under the terms of the GNU General Public License as published by",
50 " the Free Software Foundation; either version 2, or (at your option)",
51 " any later version.",
52 "",
53 " This program is distributed in the hope that it will be useful,",
54 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
55 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
56 " GNU General Public License for more details.",
57 "",
58 " You should have received a copy of the GNU General Public License",
59 " along with this program; if not, write to the Free Software",
60 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
61 0
62};
63#endif
64
65#include <sys/types.h>
66#include <sys/wait.h>
67#include <signal.h>
68#include <stdlib.h>
69#include <string.h>
70#include <unistd.h>
71#include <fcntl.h>
72#include "config.h"
73#include "busybox.h"
74#include "unarchive.h"
75
76typedef struct huft_s {
77 unsigned char e; /* number of extra bits or operation */
78 unsigned char b; /* number of bits in this code or subcode */
79 union {
80 unsigned short n; /* literal, length base, or distance base */
81 struct huft_s *t; /* pointer to next level of table */
82 } v;
83} huft_t;
84
85static int gunzip_src_fd;
86unsigned int gunzip_bytes_out; /* number of output bytes */
87static unsigned int gunzip_outbuf_count; /* bytes in output buffer */
88
89/* gunzip_window size--must be a power of two, and
90 * at least 32K for zip's deflate method */
91static const int gunzip_wsize = 0x8000;
92static unsigned char *gunzip_window;
93
94static unsigned int *gunzip_crc_table;
95unsigned int gunzip_crc;
96
97/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
98#define BMAX 16 /* maximum bit length of any code (16 for explode) */
99#define N_MAX 288 /* maximum number of codes in any set */
100
101/* bitbuffer */
102static unsigned int gunzip_bb; /* bit buffer */
103static unsigned char gunzip_bk; /* bits in bit buffer */
104
105/* These control the size of the bytebuffer */
106static unsigned int bytebuffer_max = 0x8000;
107static unsigned char *bytebuffer = NULL;
108static unsigned int bytebuffer_offset = 0;
109static unsigned int bytebuffer_size = 0;
110
111static const unsigned short mask_bits[] = {
112 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
113 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
114};
115
116/* Copy lengths for literal codes 257..285 */
117static const unsigned short cplens[] = {
118 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
119 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
120};
121
122/* note: see note #13 above about the 258 in this list. */
123/* Extra bits for literal codes 257..285 */
124static const unsigned char cplext[] = {
125 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,
126 5, 5, 5, 0, 99, 99
127}; /* 99==invalid */
128
129/* Copy offsets for distance codes 0..29 */
130static const unsigned short cpdist[] = {
131 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
132 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
133};
134
135/* Extra bits for distance codes */
136static const unsigned char cpdext[] = {
137 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
138 11, 11, 12, 12, 13, 13
139};
140
141/* Tables for deflate from PKZIP's appnote.txt. */
142/* Order of the bit length code lengths */
143static const unsigned char border[] = {
144 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
145};
146
147static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
148{
149 while (*current < required) {
150 if (bytebuffer_offset >= bytebuffer_size) {
151 /* Leave the first 4 bytes empty so we can always unwind the bitbuffer
152 * to the front of the bytebuffer, leave 4 bytes free at end of tail
153 * so we can easily top up buffer in check_trailer_gzip() */
154 bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8);
155 bytebuffer_offset = 4;
156 }
157 bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current;
158 bytebuffer_offset++;
159 *current += 8;
160 }
161 return(bitbuffer);
162}
163
164static void make_gunzip_crc_table(void)
165{
166 const unsigned int poly = 0xedb88320; /* polynomial exclusive-or pattern */
167 unsigned short i; /* counter for all possible eight bit values */
168
169 /* initial shift register value */
170 gunzip_crc = 0xffffffffL;
171 gunzip_crc_table = (unsigned int *) malloc(256 * sizeof(unsigned int));
172
173 /* Compute and print table of CRC's, five per line */
174 for (i = 0; i < 256; i++) {
175 unsigned int table_entry; /* crc shift register */
176 unsigned char k; /* byte being shifted into crc apparatus */
177
178 table_entry = i;
179 /* The idea to initialize the register with the byte instead of
180 * zero was stolen from Haruhiko Okumura's ar002
181 */
182 for (k = 8; k; k--) {
183 if (table_entry & 1) {
184 table_entry = (table_entry >> 1) ^ poly;
185 } else {
186 table_entry >>= 1;
187 }
188 }
189 gunzip_crc_table[i] = table_entry;
190 }
191}
192
193/*
194 * Free the malloc'ed tables built by huft_build(), which makes a linked
195 * list of the tables it made, with the links in a dummy first entry of
196 * each table.
197 * t: table to free
198 */
199static int huft_free(huft_t * t)
200{
201 huft_t *p;
202 huft_t *q;
203
204 /* Go through linked list, freeing from the malloced (t[-1]) address. */
205 p = t;
206 while (p != (huft_t *) NULL) {
207 q = (--p)->v.t;
208 free((char *) p);
209 p = q;
210 }
211 return 0;
212}
213
214/* Given a list of code lengths and a maximum table size, make a set of
215 * tables to decode that set of codes. Return zero on success, one if
216 * the given code set is incomplete (the tables are still built in this
217 * case), two if the input is invalid (all zero length codes or an
218 * oversubscribed set of lengths), and three if not enough memory.
219 *
220 * b: code lengths in bits (all assumed <= BMAX)
221 * n: number of codes (assumed <= N_MAX)
222 * s: number of simple-valued codes (0..s-1)
223 * d: list of base values for non-simple codes
224 * e: list of extra bits for non-simple codes
225 * t: result: starting table
226 * m: maximum lookup bits, returns actual
227 */
228static int huft_build(unsigned int *b, const unsigned int n,
229 const unsigned int s, const unsigned short *d,
230 const unsigned char *e, huft_t ** t, int *m)
231{
232 unsigned a; /* counter for codes of length k */
233 unsigned c[BMAX + 1]; /* bit length count table */
234 unsigned f; /* i repeats in table every f entries */
235 int g; /* maximum code length */
236 int h; /* table level */
237 register unsigned i; /* counter, current code */
238 register unsigned j; /* counter */
239 register int k; /* number of bits in current code */
240 int l; /* bits per table (returned in m) */
241 register unsigned *p; /* pointer into c[], b[], or v[] */
242 register huft_t *q; /* points to current table */
243 huft_t r; /* table entry for structure assignment */
244 huft_t *u[BMAX]; /* table stack */
245 unsigned v[N_MAX]; /* values in order of bit length */
246 register int w; /* bits before this table == (l * h) */
247 unsigned x[BMAX + 1]; /* bit offsets, then code stack */
248 unsigned *xp; /* pointer into x */
249 int y; /* number of dummy codes added */
250 unsigned z; /* number of entries in current table */
251
252 /* Generate counts for each bit length */
253 memset((void *) (c), 0, sizeof(c));
254 p = b;
255 i = n;
256 do {
257 c[*p]++; /* assume all entries <= BMAX */
258 p++; /* Can't combine with above line (Solaris bug) */
259 } while (--i);
260 if (c[0] == n) { /* null input--all zero length codes */
261 *t = (huft_t *) NULL;
262 *m = 0;
263 return 0;
264 }
265
266 /* Find minimum and maximum length, bound *m by those */
267 l = *m;
268 for (j = 1; j <= BMAX; j++) {
269 if (c[j]) {
270 break;
271 }
272 }
273 k = j; /* minimum code length */
274 if ((unsigned) l < j) {
275 l = j;
276 }
277 for (i = BMAX; i; i--) {
278 if (c[i]) {
279 break;
280 }
281 }
282 g = i; /* maximum code length */
283 if ((unsigned) l > i) {
284 l = i;
285 }
286 *m = l;
287
288 /* Adjust last length count to fill out codes, if needed */
289 for (y = 1 << j; j < i; j++, y <<= 1) {
290 if ((y -= c[j]) < 0) {
291 return 2; /* bad input: more codes than bits */
292 }
293 }
294 if ((y -= c[i]) < 0) {
295 return 2;
296 }
297 c[i] += y;
298
299 /* Generate starting offsets into the value table for each length */
300 x[1] = j = 0;
301 p = c + 1;
302 xp = x + 2;
303 while (--i) { /* note that i == g from above */
304 *xp++ = (j += *p++);
305 }
306
307 /* Make a table of values in order of bit lengths */
308 p = b;
309 i = 0;
310 do {
311 if ((j = *p++) != 0) {
312 v[x[j]++] = i;
313 }
314 } while (++i < n);
315
316 /* Generate the Huffman codes and for each, make the table entries */
317 x[0] = i = 0; /* first Huffman code is zero */
318 p = v; /* grab values in bit order */
319 h = -1; /* no tables yet--level -1 */
320 w = -l; /* bits decoded == (l * h) */
321 u[0] = (huft_t *) NULL; /* just to keep compilers happy */
322 q = (huft_t *) NULL; /* ditto */
323 z = 0; /* ditto */
324
325 /* go through the bit lengths (k already is bits in shortest code) */
326 for (; k <= g; k++) {
327 a = c[k];
328 while (a--) {
329 /* here i is the Huffman code of length k bits for value *p */
330 /* make tables up to required level */
331 while (k > w + l) {
332 h++;
333 w += l; /* previous table always l bits */
334
335 /* compute minimum size table less than or equal to l bits */
336 z = (z = g - w) > (unsigned) l ? l : z; /* upper limit on table size */
337 if ((f = 1 << (j = k - w)) > a + 1) { /* try a k-w bit table *//* too few codes for k-w bit table */
338 f -= a + 1; /* deduct codes from patterns left */
339 xp = c + k;
340 while (++j < z) { /* try smaller tables up to z bits */
341 if ((f <<= 1) <= *++xp) {
342 break; /* enough codes to use up j bits */
343 }
344 f -= *xp; /* else deduct codes from patterns */
345 }
346 }
347 z = 1 << j; /* table entries for j-bit table */
348
349 /* allocate and link in new table */
350 q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t));
351
352 *t = q + 1; /* link to list for huft_free() */
353 *(t = &(q->v.t)) = NULL;
354 u[h] = ++q; /* table starts after link */
355
356 /* connect to last table, if there is one */
357 if (h) {
358 x[h] = i; /* save pattern for backing up */
359 r.b = (unsigned char) l; /* bits to dump before this table */
360 r.e = (unsigned char) (16 + j); /* bits in this table */
361 r.v.t = q; /* pointer to this table */
362 j = i >> (w - l); /* (get around Turbo C bug) */
363 u[h - 1][j] = r; /* connect to last table */
364 }
365 }
366
367 /* set up table entry in r */
368 r.b = (unsigned char) (k - w);
369 if (p >= v + n) {
370 r.e = 99; /* out of values--invalid code */
371 } else if (*p < s) {
372 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
373 r.v.n = (unsigned short) (*p); /* simple code is just the value */
374 p++; /* one compiler does not like *p++ */
375 } else {
376 r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */
377 r.v.n = d[*p++ - s];
378 }
379
380 /* fill code-like entries with r */
381 f = 1 << (k - w);
382 for (j = i >> w; j < z; j += f) {
383 q[j] = r;
384 }
385
386 /* backwards increment the k-bit code i */
387 for (j = 1 << (k - 1); i & j; j >>= 1) {
388 i ^= j;
389 }
390 i ^= j;
391
392 /* backup over finished tables */
393 while ((i & ((1 << w) - 1)) != x[h]) {
394 h--; /* don't need to update q */
395 w -= l;
396 }
397 }
398 }
399 /* Return true (1) if we were given an incomplete table */
400 return y != 0 && g != 1;
401}
402
403/*
404 * inflate (decompress) the codes in a deflated (compressed) block.
405 * Return an error code or zero if it all goes ok.
406 *
407 * tl, td: literal/length and distance decoder tables
408 * bl, bd: number of bits decoded by tl[] and td[]
409 */
410static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_bl, const unsigned int my_bd, int setup)
411{
412 static unsigned int e; /* table entry flag/number of extra bits */
413 static unsigned int n, d; /* length and index for copy */
414 static unsigned int w; /* current gunzip_window position */
415 static huft_t *t; /* pointer to table entry */
416 static unsigned int ml, md; /* masks for bl and bd bits */
417 static unsigned int b; /* bit buffer */
418 static unsigned int k; /* number of bits in bit buffer */
419 static huft_t *tl, *td;
420 static unsigned int bl, bd;
421 static int resumeCopy = 0;
422
423 if (setup) { // 1st time we are called, copy in variables
424 tl = my_tl;
425 td = my_td;
426 bl = my_bl;
427 bd = my_bd;
428 /* make local copies of globals */
429 b = gunzip_bb; /* initialize bit buffer */
430 k = gunzip_bk;
431 w = gunzip_outbuf_count; /* initialize gunzip_window position */
432
433 /* inflate the coded data */
434 ml = mask_bits[bl]; /* precompute masks for speed */
435 md = mask_bits[bd];
436 return 0; // Don't actually do anything the first time
437 }
438
439 if (resumeCopy) goto do_copy;
440
441 while (1) { /* do until end of block */
442 b = fill_bitbuffer(b, &k, bl);
443 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
444 do {
445 if (e == 99) {
446 bb_error_msg_and_die("inflate_codes error 1");;
447 }
448 b >>= t->b;
449 k -= t->b;
450 e -= 16;
451 b = fill_bitbuffer(b, &k, e);
452 } while ((e =
453 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
454 b >>= t->b;
455 k -= t->b;
456 if (e == 16) { /* then it's a literal */
457 gunzip_window[w++] = (unsigned char) t->v.n;
458 if (w == gunzip_wsize) {
459 gunzip_outbuf_count = (w);
460 //flush_gunzip_window();
461 w = 0;
462 return 1; // We have a block to read
463 }
464 } else { /* it's an EOB or a length */
465
466 /* exit if end of block */
467 if (e == 15) {
468 break;
469 }
470
471 /* get length of block to copy */
472 b = fill_bitbuffer(b, &k, e);
473 n = t->v.n + ((unsigned) b & mask_bits[e]);
474 b >>= e;
475 k -= e;
476
477 /* decode distance of block to copy */
478 b = fill_bitbuffer(b, &k, bd);
479 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
480 do {
481 if (e == 99)
482 bb_error_msg_and_die("inflate_codes error 2");;
483 b >>= t->b;
484 k -= t->b;
485 e -= 16;
486 b = fill_bitbuffer(b, &k, e);
487 } while ((e =
488 (t =
489 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
490 b >>= t->b;
491 k -= t->b;
492 b = fill_bitbuffer(b, &k, e);
493 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
494 b >>= e;
495 k -= e;
496
497 /* do the copy */
498do_copy: do {
499 n -= (e =
500 (e =
501 gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
502 /* copy to new buffer to prevent possible overwrite */
503 if (w - d >= e) { /* (this test assumes unsigned comparison) */
504 memcpy(gunzip_window + w, gunzip_window + d, e);
505 w += e;
506 d += e;
507 } else {
508 /* do it slow to avoid memcpy() overlap */
509 /* !NOMEMCPY */
510 do {
511 gunzip_window[w++] = gunzip_window[d++];
512 } while (--e);
513 }
514 if (w == gunzip_wsize) {
515 gunzip_outbuf_count = (w);
516 if (n) resumeCopy = 1;
517 else resumeCopy = 0;
518 //flush_gunzip_window();
519 w = 0;
520 return 1;
521 }
522 } while (n);
523 resumeCopy = 0;
524 }
525 }
526
527 /* restore the globals from the locals */
528 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
529 gunzip_bb = b; /* restore global bit buffer */
530 gunzip_bk = k;
531
532 /* normally just after call to inflate_codes, but save code by putting it here */
533 /* free the decoding tables, return */
534 huft_free(tl);
535 huft_free(td);
536
537 /* done */
538 return 0;
539}
540
541static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
542{
543 static int n, b_stored, k_stored, w;
544 if (setup) {
545 n = my_n;
546 b_stored = my_b_stored;
547 k_stored = my_k_stored;
548 w = gunzip_outbuf_count; /* initialize gunzip_window position */
549 return 0; // Don't do anything first time
550 }
551
552 /* read and output the compressed data */
553 while (n--) {
554 b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
555 gunzip_window[w++] = (unsigned char) b_stored;
556 if (w == (unsigned int) gunzip_wsize) {
557 gunzip_outbuf_count = (w);
558 //flush_gunzip_window();
559 w = 0;
560 b_stored >>= 8;
561 k_stored -= 8;
562 return 1; // We have a block
563 }
564 b_stored >>= 8;
565 k_stored -= 8;
566 }
567
568 /* restore the globals from the locals */
569 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
570 gunzip_bb = b_stored; /* restore global bit buffer */
571 gunzip_bk = k_stored;
572 return 0; // Finished
573}
574
575/*
576 * decompress an inflated block
577 * e: last block flag
578 *
579 * GLOBAL VARIABLES: bb, kk,
580 */
581 // Return values: -1 = inflate_stored, -2 = inflate_codes
582static int inflate_block(int *e)
583{
584 unsigned t; /* block type */
585 register unsigned int b; /* bit buffer */
586 unsigned int k; /* number of bits in bit buffer */
587
588 /* make local bit buffer */
589
590 b = gunzip_bb;
591 k = gunzip_bk;
592
593 /* read in last block bit */
594 b = fill_bitbuffer(b, &k, 1);
595 *e = (int) b & 1;
596 b >>= 1;
597 k -= 1;
598
599 /* read in block type */
600 b = fill_bitbuffer(b, &k, 2);
601 t = (unsigned) b & 3;
602 b >>= 2;
603 k -= 2;
604
605 /* restore the global bit buffer */
606 gunzip_bb = b;
607 gunzip_bk = k;
608
609 /* inflate that block type */
610 switch (t) {
611 case 0: /* Inflate stored */
612 {
613 unsigned int n; /* number of bytes in block */
614 unsigned int b_stored; /* bit buffer */
615 unsigned int k_stored; /* number of bits in bit buffer */
616
617 /* make local copies of globals */
618 b_stored = gunzip_bb; /* initialize bit buffer */
619 k_stored = gunzip_bk;
620
621 /* go to byte boundary */
622 n = k_stored & 7;
623 b_stored >>= n;
624 k_stored -= n;
625
626 /* get the length and its complement */
627 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
628 n = ((unsigned) b_stored & 0xffff);
629 b_stored >>= 16;
630 k_stored -= 16;
631
632 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
633 if (n != (unsigned) ((~b_stored) & 0xffff)) {
634 return 1; /* error in compressed data */
635 }
636 b_stored >>= 16;
637 k_stored -= 16;
638
639 inflate_stored(n, b_stored, k_stored, 1); // Setup inflate_stored
640 return -1;
641 }
642 case 1: /* Inflate fixed
643 * decompress an inflated type 1 (fixed Huffman codes) block. We should
644 * either replace this with a custom decoder, or at least precompute the
645 * Huffman tables.
646 */
647 {
648 int i; /* temporary variable */
649 huft_t *tl; /* literal/length code table */
650 huft_t *td; /* distance code table */
651 unsigned int bl; /* lookup bits for tl */
652 unsigned int bd; /* lookup bits for td */
653 unsigned int l[288]; /* length list for huft_build */
654
655 /* set up literal table */
656 for (i = 0; i < 144; i++) {
657 l[i] = 8;
658 }
659 for (; i < 256; i++) {
660 l[i] = 9;
661 }
662 for (; i < 280; i++) {
663 l[i] = 7;
664 }
665 for (; i < 288; i++) { /* make a complete, but wrong code set */
666 l[i] = 8;
667 }
668 bl = 7;
669 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) {
670 return i;
671 }
672
673 /* set up distance table */
674 for (i = 0; i < 30; i++) { /* make an incomplete code set */
675 l[i] = 5;
676 }
677 bd = 5;
678 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) {
679 huft_free(tl);
680 return i;
681 }
682
683 /* decompress until an end-of-block code */
684 inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes
685
686 /* huft_free code moved into inflate_codes */
687
688 return -2;
689 }
690 case 2: /* Inflate dynamic */
691 {
692 const int dbits = 6; /* bits in base distance lookup table */
693 const int lbits = 9; /* bits in base literal/length lookup table */
694
695 huft_t *tl; /* literal/length code table */
696 huft_t *td; /* distance code table */
697 unsigned int i; /* temporary variables */
698 unsigned int j;
699 unsigned int l; /* last length */
700 unsigned int m; /* mask for bit lengths table */
701 unsigned int n; /* number of lengths to get */
702 unsigned int bl; /* lookup bits for tl */
703 unsigned int bd; /* lookup bits for td */
704 unsigned int nb; /* number of bit length codes */
705 unsigned int nl; /* number of literal/length codes */
706 unsigned int nd; /* number of distance codes */
707
708 unsigned int ll[286 + 30]; /* literal/length and distance code lengths */
709 unsigned int b_dynamic; /* bit buffer */
710 unsigned int k_dynamic; /* number of bits in bit buffer */
711
712 /* make local bit buffer */
713 b_dynamic = gunzip_bb;
714 k_dynamic = gunzip_bk;
715
716 /* read in table lengths */
717 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
718 nl = 257 + ((unsigned int) b_dynamic & 0x1f); /* number of literal/length codes */
719
720 b_dynamic >>= 5;
721 k_dynamic -= 5;
722 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
723 nd = 1 + ((unsigned int) b_dynamic & 0x1f); /* number of distance codes */
724
725 b_dynamic >>= 5;
726 k_dynamic -= 5;
727 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 4);
728 nb = 4 + ((unsigned int) b_dynamic & 0xf); /* number of bit length codes */
729
730 b_dynamic >>= 4;
731 k_dynamic -= 4;
732 if (nl > 286 || nd > 30) {
733 return 1; /* bad lengths */
734 }
735
736 /* read in bit-length-code lengths */
737 for (j = 0; j < nb; j++) {
738 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
739 ll[border[j]] = (unsigned int) b_dynamic & 7;
740 b_dynamic >>= 3;
741 k_dynamic -= 3;
742 }
743 for (; j < 19; j++) {
744 ll[border[j]] = 0;
745 }
746
747 /* build decoding table for trees--single level, 7 bit lookup */
748 bl = 7;
749 i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl);
750 if (i != 0) {
751 if (i == 1) {
752 huft_free(tl);
753 }
754 return i; /* incomplete code set */
755 }
756
757 /* read in literal and distance code lengths */
758 n = nl + nd;
759 m = mask_bits[bl];
760 i = l = 0;
761 while ((unsigned int) i < n) {
762 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, (unsigned int)bl);
763 j = (td = tl + ((unsigned int) b_dynamic & m))->b;
764 b_dynamic >>= j;
765 k_dynamic -= j;
766 j = td->v.n;
767 if (j < 16) { /* length of code in bits (0..15) */
768 ll[i++] = l = j; /* save last length in l */
769 } else if (j == 16) { /* repeat last length 3 to 6 times */
770 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 2);
771 j = 3 + ((unsigned int) b_dynamic & 3);
772 b_dynamic >>= 2;
773 k_dynamic -= 2;
774 if ((unsigned int) i + j > n) {
775 return 1;
776 }
777 while (j--) {
778 ll[i++] = l;
779 }
780 } else if (j == 17) { /* 3 to 10 zero length codes */
781 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
782 j = 3 + ((unsigned int) b_dynamic & 7);
783 b_dynamic >>= 3;
784 k_dynamic -= 3;
785 if ((unsigned int) i + j > n) {
786 return 1;
787 }
788 while (j--) {
789 ll[i++] = 0;
790 }
791 l = 0;
792 } else { /* j == 18: 11 to 138 zero length codes */
793 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 7);
794 j = 11 + ((unsigned int) b_dynamic & 0x7f);
795 b_dynamic >>= 7;
796 k_dynamic -= 7;
797 if ((unsigned int) i + j > n) {
798 return 1;
799 }
800 while (j--) {
801 ll[i++] = 0;
802 }
803 l = 0;
804 }
805 }
806
807 /* free decoding table for trees */
808 huft_free(tl);
809
810 /* restore the global bit buffer */
811 gunzip_bb = b_dynamic;
812 gunzip_bk = k_dynamic;
813
814 /* build the decoding tables for literal/length and distance codes */
815 bl = lbits;
816
817 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
818 if (i == 1) {
819 bb_error_msg_and_die("Incomplete literal tree");
820 huft_free(tl);
821 }
822 return i; /* incomplete code set */
823 }
824
825 bd = dbits;
826 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
827 if (i == 1) {
828 bb_error_msg_and_die("incomplete distance tree");
829 huft_free(td);
830 }
831 huft_free(tl);
832 return i; /* incomplete code set */
833 }
834
835 /* decompress until an end-of-block code */
836 inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes
837
838 /* huft_free code moved into inflate_codes */
839
840 return -2;
841 }
842 default:
843 /* bad block type */
844 bb_error_msg_and_die("bad block type %d\n", t);
845 }
846}
847
848static void calculate_gunzip_crc(void)
849{
850 int n;
851 for (n = 0; n < gunzip_outbuf_count; n++) {
852 gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
853 }
854 gunzip_bytes_out += gunzip_outbuf_count;
855}
856
857static int inflate_get_next_window(void)
858{
859 static int method = -1; // Method == -1 for stored, -2 for codes
860 static int e = 0;
861 static int needAnotherBlock = 1;
862
863 gunzip_outbuf_count = 0;
864
865 while(1) {
866 int ret;
867
868 if (needAnotherBlock) {
869 if(e) {
870 calculate_gunzip_crc();
871 e = 0;
872 needAnotherBlock = 1;
873 return 0;
874 } // Last block
875 method = inflate_block(&e);
876 needAnotherBlock = 0;
877 }
878
879 switch (method) {
880 case -1: ret = inflate_stored(0,0,0,0);
881 break;
882 case -2: ret = inflate_codes(0,0,0,0,0);
883 break;
884 default: bb_error_msg_and_die("inflate error %d", method);
885 }
886
887 if (ret == 1) {
888 calculate_gunzip_crc();
889 return 1; // More data left
890 } else needAnotherBlock = 1; // End of that block
891 }
892 /* Doesnt get here */
893}
894
895/* Initialise bytebuffer, be careful not to overfill the buffer */
896extern void inflate_init(unsigned int bufsize)
897{
898 /* Set the bytebuffer size, default is same as gunzip_wsize */
899 bytebuffer_max = bufsize + 8;
900 bytebuffer_offset = 4;
901 bytebuffer_size = 0;
902}
903
904extern int inflate_unzip(int in, int out)
905{
906 ssize_t nwrote;
907 typedef void (*sig_type) (int);
908
909 /* Allocate all global buffers (for DYN_ALLOC option) */
910 gunzip_window = xmalloc(gunzip_wsize);
911 gunzip_outbuf_count = 0;
912 gunzip_bytes_out = 0;
913 gunzip_src_fd = in;
914
915 /* initialize gunzip_window, bit buffer */
916 gunzip_bk = 0;
917 gunzip_bb = 0;
918
919 /* Create the crc table */
920 make_gunzip_crc_table();
921
922 /* Allocate space for buffer */
923 bytebuffer = xmalloc(bytebuffer_max);
924
925 while(1) {
926 int ret = inflate_get_next_window();
927 nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count);
928 if (nwrote == -1) {
929 bb_perror_msg("write");
930 return -1;
931 }
932 if (ret == 0) break;
933 }
934
935 /* Cleanup */
936 free(gunzip_window);
937 free(gunzip_crc_table);
938
939 /* Store unused bytes in a global buffer so calling applets can access it */
940 if (gunzip_bk >= 8) {
941 /* Undo too much lookahead. The next read will be byte aligned
942 * so we can discard unused bits in the last meaningful byte. */
943 bytebuffer_offset--;
944 bytebuffer[bytebuffer_offset] = gunzip_bb & 0xff;
945 gunzip_bb >>= 8;
946 gunzip_bk -= 8;
947 }
948 return 0;
949}
950
951extern int inflate_gunzip(int in, int out)
952{
953 unsigned int stored_crc = 0;
954 unsigned char count;
955
956 inflate_unzip(in, out);
957
958 /* top up the input buffer with the rest of the trailer */
959 count = bytebuffer_size - bytebuffer_offset;
960 if (count < 8) {
961 bb_xread_all(in, &bytebuffer[bytebuffer_size], 8 - count);
962 bytebuffer_size += 8 - count;
963 }
964 for (count = 0; count != 4; count++) {
965 stored_crc |= (bytebuffer[bytebuffer_offset] << (count * 8));
966 bytebuffer_offset++;
967 }
968
969 /* Validate decompression - crc */
970 if (stored_crc != (gunzip_crc ^ 0xffffffffL)) {
971 bb_error_msg("crc error");
972 }
973
974 /* Validate decompression - size */
975 if (gunzip_bytes_out !=
976 (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) |
977 (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) {
978 bb_error_msg("Incorrect length");
979 }
980
981 return 0;
982}
diff --git a/busybox/archival/libunarchive/filter_accept_all.c b/busybox/archival/libunarchive/filter_accept_all.c
new file mode 100644
index 000000000..baf9e4b71
--- /dev/null
+++ b/busybox/archival/libunarchive/filter_accept_all.c
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2002 by Glenn McGrath
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <fnmatch.h>
20#include <stdlib.h>
21
22#include "unarchive.h"
23
24/* Accept any non-null name, its not really a filter at all */
25extern char filter_accept_all(archive_handle_t *archive_handle)
26{
27 if (archive_handle->file_header->name) {
28 return(EXIT_SUCCESS);
29 } else {
30 return(EXIT_FAILURE);
31 }
32}
diff --git a/busybox/archival/libunarchive/filter_accept_list.c b/busybox/archival/libunarchive/filter_accept_list.c
new file mode 100644
index 000000000..e1c4827bf
--- /dev/null
+++ b/busybox/archival/libunarchive/filter_accept_list.c
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2002 by Glenn McGrath
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <fnmatch.h>
20#include <stdlib.h>
21
22#include "unarchive.h"
23
24/*
25 * Accept names that are in the accept list, ignoring reject list.
26 */
27extern char filter_accept_list(archive_handle_t *archive_handle)
28{
29 if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) {
30 return(EXIT_SUCCESS);
31 } else {
32 return(EXIT_FAILURE);
33 }
34}
diff --git a/busybox/archival/libunarchive/filter_accept_list_reassign.c b/busybox/archival/libunarchive/filter_accept_list_reassign.c
new file mode 100644
index 000000000..d0436549b
--- /dev/null
+++ b/busybox/archival/libunarchive/filter_accept_list_reassign.c
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2002 by Glenn McGrath
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22
23#include "libbb.h"
24#include "unarchive.h"
25
26/*
27 * Reassign the subarchive metadata parser based on the filename extension
28 * e.g. if its a .tar.gz modify archive_handle->sub_archive to process a .tar.gz
29 * or if its a .tar.bz2 make archive_handle->sub_archive handle that
30 */
31extern char filter_accept_list_reassign(archive_handle_t *archive_handle)
32{
33 /* Check the file entry is in the accept list */
34 if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) {
35 const char *name_ptr;
36
37 /* Extract the last 2 extensions */
38 name_ptr = strrchr(archive_handle->file_header->name, '.');
39
40 /* Modify the subarchive handler based on the extension */
41#ifdef CONFIG_FEATURE_DEB_TAR_GZ
42 if (strcmp(name_ptr, ".gz") == 0) {
43 archive_handle->action_data_subarchive = get_header_tar_gz;
44 return(EXIT_SUCCESS);
45 }
46#endif
47#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
48 if (strcmp(name_ptr, ".bz2") == 0) {
49 archive_handle->action_data_subarchive = get_header_tar_bz2;
50 return(EXIT_SUCCESS);
51 }
52#endif
53 }
54 return(EXIT_FAILURE);
55}
diff --git a/busybox/archival/libunarchive/filter_accept_reject_list.c b/busybox/archival/libunarchive/filter_accept_reject_list.c
new file mode 100644
index 000000000..657f7a0bd
--- /dev/null
+++ b/busybox/archival/libunarchive/filter_accept_reject_list.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright (C) 2002 by Glenn McGrath
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <fnmatch.h>
20#include <stdlib.h>
21
22#include "unarchive.h"
23
24/*
25 * Accept names that are in the accept list and not in the reject list
26 */
27extern char filter_accept_reject_list(archive_handle_t *archive_handle)
28{
29 const char *key = archive_handle->file_header->name;
30 const llist_t *accept_entry = find_list_entry(archive_handle->accept, key);
31 const llist_t *reject_entry = find_list_entry(archive_handle->reject, key);
32
33 /* If the key is in a reject list fail */
34 if (reject_entry) {
35 return(EXIT_FAILURE);
36 }
37
38 /* Fail if an accept list was specified and the key wasnt in there */
39 if (archive_handle->accept && (accept_entry == NULL)) {
40 return(EXIT_FAILURE);
41 }
42
43 /* Accepted */
44 return(EXIT_SUCCESS);
45}
diff --git a/busybox/archival/libunarchive/find_list_entry.c b/busybox/archival/libunarchive/find_list_entry.c
new file mode 100644
index 000000000..7ed9e332f
--- /dev/null
+++ b/busybox/archival/libunarchive/find_list_entry.c
@@ -0,0 +1,30 @@
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 <fnmatch.h>
18#include <stdlib.h>
19#include "unarchive.h"
20
21extern const llist_t *find_list_entry(const llist_t *list, const char *filename)
22{
23 while (list) {
24 if (fnmatch(list->data, filename, 0) == 0) {
25 return(list);
26 }
27 list = list->link;
28 }
29 return(NULL);
30}
diff --git a/busybox/archival/libunarchive/get_header_ar.c b/busybox/archival/libunarchive/get_header_ar.c
new file mode 100644
index 000000000..ebb6f8cbe
--- /dev/null
+++ b/busybox/archival/libunarchive/get_header_ar.c
@@ -0,0 +1,126 @@
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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include "unarchive.h"
22#include "libbb.h"
23
24extern char get_header_ar(archive_handle_t *archive_handle)
25{
26 file_header_t *typed = archive_handle->file_header;
27 union {
28 char raw[60];
29 struct {
30 char name[16];
31 char date[12];
32 char uid[6];
33 char gid[6];
34 char mode[8];
35 char size[10];
36 char magic[2];
37 } formated;
38 } ar;
39#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
40 static char *ar_long_names;
41 static unsigned int ar_long_name_size;
42#endif
43
44 /* dont use bb_xread as we want to handle the error ourself */
45 if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
46 /* End Of File */
47 return(EXIT_FAILURE);
48 }
49
50 /* ar header starts on an even byte (2 byte aligned)
51 * '\n' is used for padding
52 */
53 if (ar.raw[0] == '\n') {
54 /* fix up the header, we started reading 1 byte too early */
55 memmove(ar.raw, &ar.raw[1], 59);
56 ar.raw[59] = bb_xread_char(archive_handle->src_fd);
57 archive_handle->offset++;
58 }
59 archive_handle->offset += 60;
60
61 /* align the headers based on the header magic */
62 if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
63 bb_error_msg_and_die("Invalid ar header");
64 }
65
66 typed->mode = strtol(ar.formated.mode, NULL, 8);
67 typed->mtime = atoi(ar.formated.date);
68 typed->uid = atoi(ar.formated.uid);
69 typed->gid = atoi(ar.formated.gid);
70 typed->size = atoi(ar.formated.size);
71
72 /* long filenames have '/' as the first character */
73 if (ar.formated.name[0] == '/') {
74#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
75 if (ar.formated.name[1] == '/') {
76 /* If the second char is a '/' then this entries data section
77 * stores long filename for multiple entries, they are stored
78 * in static variable long_names for use in future entries */
79 ar_long_name_size = typed->size;
80 ar_long_names = xmalloc(ar_long_name_size);
81 bb_xread_all(archive_handle->src_fd, ar_long_names, ar_long_name_size);
82 archive_handle->offset += ar_long_name_size;
83 /* This ar entries data section only contained filenames for other records
84 * they are stored in the static ar_long_names for future reference */
85 return (get_header_ar(archive_handle)); /* Return next header */
86 } else if (ar.formated.name[1] == ' ') {
87 /* This is the index of symbols in the file for compilers */
88 data_skip(archive_handle);
89 archive_handle->offset += typed->size;
90 return (get_header_ar(archive_handle)); /* Return next header */
91 } else {
92 /* The number after the '/' indicates the offset in the ar data section
93 (saved in variable long_name) that conatains the real filename */
94 const unsigned int long_offset = atoi(&ar.formated.name[1]);
95 if (long_offset >= ar_long_name_size) {
96 bb_error_msg_and_die("Cant resolve long filename");
97 }
98 typed->name = bb_xstrdup(ar_long_names + long_offset);
99 }
100#else
101 bb_error_msg_and_die("long filenames not supported");
102#endif
103 } else {
104 /* short filenames */
105 typed->name = bb_xstrndup(ar.formated.name, 16);
106 }
107
108 typed->name[strcspn(typed->name, " /")] = '\0';
109
110 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
111 archive_handle->action_header(typed);
112 if (archive_handle->sub_archive) {
113 while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS);
114 } else {
115 archive_handle->action_data(archive_handle);
116 }
117 } else {
118 data_skip(archive_handle);
119 }
120
121 archive_handle->offset += typed->size;
122 /* Set the file pointer to the correct spot, we may have been reading a compressed file */
123 lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET);
124
125 return(EXIT_SUCCESS);
126}
diff --git a/busybox/archival/libunarchive/get_header_cpio.c b/busybox/archival/libunarchive/get_header_cpio.c
new file mode 100644
index 000000000..11925c4e3
--- /dev/null
+++ b/busybox/archival/libunarchive/get_header_cpio.c
@@ -0,0 +1,161 @@
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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <sys/sysmacros.h> /* major() and minor() */
22#include "unarchive.h"
23#include "libbb.h"
24
25typedef struct hardlinks_s {
26 file_header_t *entry;
27 int inode;
28 struct hardlinks_s *next;
29} hardlinks_t;
30
31extern char get_header_cpio(archive_handle_t *archive_handle)
32{
33 static hardlinks_t *saved_hardlinks = NULL;
34 static unsigned short pending_hardlinks = 0;
35 file_header_t *file_header = archive_handle->file_header;
36 char cpio_header[110];
37 int namesize;
38 char dummy[16];
39 int major, minor, nlink, inode;
40
41 if (pending_hardlinks) { /* Deal with any pending hardlinks */
42 hardlinks_t *tmp;
43 hardlinks_t *oldtmp;
44
45 tmp = saved_hardlinks;
46 oldtmp = NULL;
47
48 while (tmp) {
49 bb_error_msg_and_die("need to fix this\n");
50 if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */
51 file_header = tmp->entry;
52 if (oldtmp) {
53 oldtmp->next = tmp->next; /* Remove item from linked list */
54 } else {
55 saved_hardlinks = tmp->next;
56 }
57 free(tmp);
58 continue;
59 }
60 oldtmp = tmp;
61 tmp = tmp->next;
62 }
63 pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */
64 }
65
66 /* There can be padding before archive header */
67 data_align(archive_handle, 4);
68
69 if (archive_xread_all_eof(archive_handle, cpio_header, 110) == 0) {
70 return(EXIT_FAILURE);
71 }
72 archive_handle->offset += 110;
73
74 if ((strncmp(&cpio_header[0], "07070", 5) != 0) || ((cpio_header[5] != '1') && (cpio_header[5] != '2'))) {
75 bb_error_msg_and_die("Unsupported cpio format, use newc or crc");
76 }
77
78 {
79 unsigned long tmpsize;
80 sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
81 dummy, &inode, (unsigned int*)&file_header->mode,
82 (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
83 &nlink, &file_header->mtime, &tmpsize,
84 dummy, &major, &minor, &namesize, dummy);
85 file_header->size = tmpsize;
86 }
87
88 file_header->name = (char *) xmalloc(namesize + 1);
89 archive_xread_all(archive_handle, file_header->name, namesize); /* Read in filename */
90 file_header->name[namesize] = '\0';
91 archive_handle->offset += namesize;
92
93 /* Update offset amount and skip padding before file contents */
94 data_align(archive_handle, 4);
95
96 if (strcmp(file_header->name, "TRAILER!!!") == 0) {
97 printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */
98 if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
99 hardlinks_t *tmp = saved_hardlinks;
100 hardlinks_t *oldtmp = NULL;
101 while (tmp) {
102 bb_error_msg("%s not created: cannot resolve hardlink", tmp->entry->name);
103 oldtmp = tmp;
104 tmp = tmp->next;
105 free (oldtmp->entry->name);
106 free (oldtmp->entry);
107 free (oldtmp);
108 }
109 saved_hardlinks = NULL;
110 pending_hardlinks = 0;
111 }
112 return(EXIT_FAILURE);
113 }
114
115 if (S_ISLNK(file_header->mode)) {
116 file_header->link_name = (char *) xmalloc(file_header->size + 1);
117 archive_xread_all(archive_handle, file_header->link_name, file_header->size);
118 file_header->link_name[file_header->size] = '\0';
119 archive_handle->offset += file_header->size;
120 file_header->size = 0; /* Stop possible seeks in future */
121 } else {
122 file_header->link_name = NULL;
123 }
124 if (nlink > 1 && !S_ISDIR(file_header->mode)) {
125 if (file_header->size == 0) { /* Put file on a linked list for later */
126 hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
127 new->next = saved_hardlinks;
128 new->inode = inode;
129 new->entry = file_header;
130 saved_hardlinks = new;
131 return(EXIT_SUCCESS); // Skip this one
132 } else { /* Found the file with data in */
133 hardlinks_t *tmp = saved_hardlinks;
134 pending_hardlinks = 1;
135 while (tmp) {
136 if (tmp->inode == inode) {
137 tmp->entry->link_name = bb_xstrdup(file_header->name);
138 nlink--;
139 }
140 tmp = tmp->next;
141 }
142 if (nlink > 1) {
143 bb_error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
144 }
145 }
146 }
147 file_header->device = makedev(major, minor);
148
149 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
150 archive_handle->action_data(archive_handle);
151 archive_handle->action_header(archive_handle->file_header);
152 } else {
153 data_skip(archive_handle);
154 }
155
156 archive_handle->offset += file_header->size;
157
158 free(file_header->link_name);
159
160 return (EXIT_SUCCESS);
161}
diff --git a/busybox/archival/libunarchive/get_header_tar.c b/busybox/archival/libunarchive/get_header_tar.c
new file mode 100644
index 000000000..1ad9ac5e5
--- /dev/null
+++ b/busybox/archival/libunarchive/get_header_tar.c
@@ -0,0 +1,215 @@
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 * FIXME:
17 * In privileged mode if uname and gname map to a uid and gid then use the
18 * mapped value instead of the uid/gid values in tar header
19 *
20 * References:
21 * GNU tar and star man pages,
22 * Opengroup's ustar interchange format,
23 * http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include "unarchive.h"
30#include "libbb.h"
31
32#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
33static char *longname = NULL;
34static char *linkname = NULL;
35#endif
36
37extern char get_header_tar(archive_handle_t *archive_handle)
38{
39 file_header_t *file_header = archive_handle->file_header;
40 union {
41 /* ustar header, Posix 1003.1 */
42 unsigned char raw[512];
43 struct {
44 char name[100]; /* 0-99 */
45 char mode[8]; /* 100-107 */
46 char uid[8]; /* 108-115 */
47 char gid[8]; /* 116-123 */
48 char size[12]; /* 124-135 */
49 char mtime[12]; /* 136-147 */
50 char chksum[8]; /* 148-155 */
51 char typeflag; /* 156-156 */
52 char linkname[100]; /* 157-256 */
53 char magic[6]; /* 257-262 */
54 char version[2]; /* 263-264 */
55 char uname[32]; /* 265-296 */
56 char gname[32]; /* 297-328 */
57 char devmajor[8]; /* 329-336 */
58 char devminor[8]; /* 337-344 */
59 char prefix[155]; /* 345-499 */
60 char padding[12]; /* 500-512 */
61 } formated;
62 } tar;
63 long sum = 0;
64 long i;
65
66 /* Align header */
67 data_align(archive_handle, 512);
68
69 if (bb_full_read(archive_handle->src_fd, tar.raw, 512) != 512) {
70 /* Assume end of file */
71 return(EXIT_FAILURE);
72 }
73 archive_handle->offset += 512;
74
75 /* If there is no filename its an empty header */
76 if (tar.formated.name[0] == 0) {
77 return(EXIT_SUCCESS);
78 }
79
80 /* Check header has valid magic, "ustar" is for the proper tar
81 * 0's are for the old tar format
82 */
83 if (strncmp(tar.formated.magic, "ustar", 5) != 0) {
84#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
85 if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0)
86#endif
87 bb_error_msg_and_die("Invalid tar magic");
88 }
89 /* Do checksum on headers */
90 for (i = 0; i < 148 ; i++) {
91 sum += tar.raw[i];
92 }
93 sum += ' ' * 8;
94 for (i = 156; i < 512 ; i++) {
95 sum += tar.raw[i];
96 }
97 if (sum != strtol(tar.formated.chksum, NULL, 8)) {
98 bb_error_msg("Invalid tar header checksum");
99 return(EXIT_FAILURE);
100 }
101
102#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
103 if (longname) {
104 file_header->name = longname;
105 longname = NULL;
106 }
107 else if (linkname) {
108 file_header->name = linkname;
109 linkname = NULL;
110 } else
111#endif
112 if (tar.formated.prefix[0] == 0) {
113 file_header->name = strdup(tar.formated.name);
114 } else {
115 file_header->name = concat_path_file(tar.formated.prefix, tar.formated.name);
116 }
117
118 file_header->uid = strtol(tar.formated.uid, NULL, 8);
119 file_header->gid = strtol(tar.formated.gid, NULL, 8);
120 file_header->size = strtol(tar.formated.size, NULL, 8);
121 file_header->mtime = strtol(tar.formated.mtime, NULL, 8);
122 file_header->link_name = (tar.formated.linkname[0] != '\0') ?
123 bb_xstrdup(tar.formated.linkname) : NULL;
124 file_header->device = makedev(strtol(tar.formated.devmajor, NULL, 8),
125 strtol(tar.formated.devminor, NULL, 8));
126
127 /* Set bits 0-11 of the files mode */
128 file_header->mode = 07777 & strtol(tar.formated.mode, NULL, 8);
129
130 /* Set bits 12-15 of the files mode */
131 switch (tar.formated.typeflag) {
132 /* busybox identifies hard links as being regular files with 0 size and a link name */
133 case '1':
134 file_header->mode |= S_IFREG;
135 break;
136 case 'x':
137 case 'g':
138 bb_error_msg_and_die("pax is not tar");
139 break;
140 case '7':
141 /* Reserved for high performance files, treat as normal file */
142 case 0:
143 case '0':
144#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
145 if (last_char_is(file_header->name, '/')) {
146 file_header->mode |= S_IFDIR;
147 } else
148#endif
149 file_header->mode |= S_IFREG;
150 break;
151 case '2':
152 file_header->mode |= S_IFLNK;
153 break;
154 case '3':
155 file_header->mode |= S_IFCHR;
156 break;
157 case '4':
158 file_header->mode |= S_IFBLK;
159 break;
160 case '5':
161 file_header->mode |= S_IFDIR;
162 break;
163 case '6':
164 file_header->mode |= S_IFIFO;
165 break;
166#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
167 case 'L': {
168 longname = xmalloc(file_header->size + 1);
169 archive_xread_all(archive_handle, longname, file_header->size);
170 longname[file_header->size] = '\0';
171 archive_handle->offset += file_header->size;
172
173 return(get_header_tar(archive_handle));
174 }
175 case 'K': {
176 linkname = xmalloc(file_header->size + 1);
177 archive_xread_all(archive_handle, linkname, file_header->size);
178 linkname[file_header->size] = '\0';
179 archive_handle->offset += file_header->size;
180
181 file_header->name = linkname;
182 return(get_header_tar(archive_handle));
183 }
184 case 'D': /* GNU dump dir */
185 case 'M': /* Continuation of multi volume archive*/
186 case 'N': /* Old GNU for names > 100 characters */
187 case 'S': /* Sparse file */
188 case 'V': /* Volume header */
189 bb_error_msg("Ignoring GNU extension type %c", tar.formated.typeflag);
190#endif
191 default:
192 bb_error_msg("Unknown typeflag: 0x%x", tar.formated.typeflag);
193 }
194 { /* Strip trailing '/' in directories */
195 /* Must be done after mode is set as '/' is used to check if its a directory */
196 char *tmp = last_char_is(file_header->name, '/');
197 if (tmp) {
198 *tmp = '\0';
199 }
200 }
201
202 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
203 archive_handle->action_header(archive_handle->file_header);
204 archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
205 archive_handle->action_data(archive_handle);
206 archive_handle->passed = llist_add_to(archive_handle->passed, file_header->name);
207 } else {
208 data_skip(archive_handle);
209 }
210 archive_handle->offset += file_header->size;
211
212 free(file_header->link_name);
213
214 return(EXIT_SUCCESS);
215}
diff --git a/busybox/archival/libunarchive/get_header_tar_bz2.c b/busybox/archival/libunarchive/get_header_tar_bz2.c
new file mode 100644
index 000000000..d49d6b96a
--- /dev/null
+++ b/busybox/archival/libunarchive/get_header_tar_bz2.c
@@ -0,0 +1,38 @@
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 <sys/wait.h>
19#include <signal.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24#include "libbb.h"
25#include "unarchive.h"
26
27extern char get_header_tar_bz2(archive_handle_t *archive_handle)
28{
29 /* Cant lseek over pipe's */
30 archive_handle->seek = seek_by_char;
31
32 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompressStream);
33 archive_handle->offset = 0;
34 while (get_header_tar(archive_handle) == EXIT_SUCCESS);
35
36 /* Can only do one file at a time */
37 return(EXIT_FAILURE);
38}
diff --git a/busybox/archival/libunarchive/get_header_tar_gz.c b/busybox/archival/libunarchive/get_header_tar_gz.c
new file mode 100644
index 000000000..9c708a951
--- /dev/null
+++ b/busybox/archival/libunarchive/get_header_tar_gz.c
@@ -0,0 +1,42 @@
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 <stdlib.h>
18
19#include "libbb.h"
20#include "unarchive.h"
21
22extern char get_header_tar_gz(archive_handle_t *archive_handle)
23{
24 unsigned char magic[2];
25
26 /* Cant lseek over pipe's */
27 archive_handle->seek = seek_by_char;
28
29 archive_xread_all(archive_handle, &magic, 2);
30 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
31 bb_error_msg_and_die("Invalid gzip magic");
32 }
33
34 check_header_gzip(archive_handle->src_fd);
35
36 archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
37 archive_handle->offset = 0;
38 while (get_header_tar(archive_handle) == EXIT_SUCCESS);
39
40 /* Can only do one file at a time */
41 return(EXIT_FAILURE);
42}
diff --git a/busybox/archival/libunarchive/header_list.c b/busybox/archival/libunarchive/header_list.c
new file mode 100644
index 000000000..5849a762e
--- /dev/null
+++ b/busybox/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/busybox/archival/libunarchive/header_skip.c b/busybox/archival/libunarchive/header_skip.c
new file mode 100644
index 000000000..4430178f8
--- /dev/null
+++ b/busybox/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/busybox/archival/libunarchive/header_verbose_list.c b/busybox/archival/libunarchive/header_verbose_list.c
new file mode 100644
index 000000000..6739dd393
--- /dev/null
+++ b/busybox/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 bb_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/busybox/archival/libunarchive/init_handle.c b/busybox/archival/libunarchive/init_handle.c
new file mode 100644
index 000000000..3cee84f67
--- /dev/null
+++ b/busybox/archival/libunarchive/init_handle.c
@@ -0,0 +1,36 @@
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 <unistd.h>
18#include <string.h>
19#include "libbb.h"
20#include "unarchive.h"
21
22archive_handle_t *init_handle(void)
23{
24 archive_handle_t *archive_handle;
25
26 /* Initialise default values */
27 archive_handle = xmalloc(sizeof(archive_handle_t));
28 memset(archive_handle, 0, sizeof(archive_handle_t));
29 archive_handle->file_header = xmalloc(sizeof(file_header_t));
30 archive_handle->action_header = header_skip;
31 archive_handle->action_data = data_skip;
32 archive_handle->filter = filter_accept_all;
33 archive_handle->seek = seek_by_jump;
34
35 return(archive_handle);
36}
diff --git a/busybox/archival/libunarchive/open_transformer.c b/busybox/archival/libunarchive/open_transformer.c
new file mode 100644
index 000000000..fb149fc0b
--- /dev/null
+++ b/busybox/archival/libunarchive/open_transformer.c
@@ -0,0 +1,51 @@
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 <stdlib.h>
18#include <unistd.h>
19
20#include "libbb.h"
21
22/* transformer(), more than meets the eye */
23extern int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd))
24{
25 int fd_pipe[2];
26 int pid;
27
28 if (pipe(fd_pipe) != 0) {
29 bb_perror_msg_and_die("Can't create pipe");
30 }
31
32 pid = fork();
33 if (pid == -1) {
34 bb_perror_msg_and_die("Fork failed");
35 }
36
37 if (pid == 0) {
38 /* child process */
39 close(fd_pipe[0]); /* We don't wan't to read from the parent */
40 transformer(src_fd, fd_pipe[1]);
41 close(fd_pipe[1]); /* Send EOF */
42 close(src_fd);
43 exit(0);
44 /* notreached */
45 }
46
47 /* parent process */
48 close(fd_pipe[1]); /* Don't want to write to the child */
49
50 return(fd_pipe[0]);
51}
diff --git a/busybox/archival/libunarchive/seek_by_char.c b/busybox/archival/libunarchive/seek_by_char.c
new file mode 100644
index 000000000..a50d566f5
--- /dev/null
+++ b/busybox/archival/libunarchive/seek_by_char.c
@@ -0,0 +1,32 @@
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 <stdlib.h>
18
19#include "unarchive.h"
20#include "busybox.h"
21
22/* If we are reading through a pipe(), or from stdin then we cant lseek,
23 * we must read and discard the data to skip over it.
24 *
25 * TODO: rename to seek_by_read
26 */
27extern void seek_by_char(const archive_handle_t *archive_handle, const unsigned int jump_size)
28{
29 if (jump_size) {
30 bb_copyfd_size(archive_handle->src_fd, -1, jump_size);
31 }
32}
diff --git a/busybox/archival/libunarchive/seek_by_jump.c b/busybox/archival/libunarchive/seek_by_jump.c
new file mode 100644
index 000000000..578870d9b
--- /dev/null
+++ b/busybox/archival/libunarchive/seek_by_jump.c
@@ -0,0 +1,35 @@
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 <errno.h>
19#include <unistd.h>
20#include <stdlib.h>
21
22#include "libbb.h"
23#include "unarchive.h"
24
25extern void seek_by_jump(const archive_handle_t *archive_handle, const unsigned int amount)
26{
27 if (lseek(archive_handle->src_fd, (off_t) amount, SEEK_CUR) == (off_t) -1) {
28#ifdef CONFIG_FEATURE_UNARCHIVE_TAPE
29 if (errno == ESPIPE) {
30 seek_by_char(archive_handle, amount);
31 } else
32#endif
33 bb_perror_msg_and_die("Seek failure");
34 }
35}
diff --git a/busybox/archival/libunarchive/unpack_ar_archive.c b/busybox/archival/libunarchive/unpack_ar_archive.c
new file mode 100644
index 000000000..e8f113bcf
--- /dev/null
+++ b/busybox/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 archive_xread_all(ar_archive, magic, 7);
28 if (strncmp(magic, "!<arch>", 7) != 0) {
29 bb_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/busybox/archival/rpm.c b/busybox/archival/rpm.c
new file mode 100644
index 000000000..30cdc93fb
--- /dev/null
+++ b/busybox/archival/rpm.c
@@ -0,0 +1,349 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini rpm applet for busybox
4 *
5 * Copyright (C) 2001,2002 by Laurence Anderson
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
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
20 */
21
22#include <stdio.h>
23#include <unistd.h>
24#include <signal.h>
25#include <stdlib.h>
26#include <fcntl.h>
27#include <netinet/in.h> /* For ntohl & htonl function */
28#include <string.h> /* For strncmp */
29#include <sys/mman.h> /* For mmap */
30#include <time.h> /* For ctime */
31
32#include "busybox.h"
33#include "unarchive.h"
34
35#define RPM_HEADER_MAGIC "\216\255\350"
36#define RPM_CHAR_TYPE 1
37#define RPM_INT8_TYPE 2
38#define RPM_INT16_TYPE 3
39#define RPM_INT32_TYPE 4
40/* #define RPM_INT64_TYPE 5 ---- These aren't supported (yet) */
41#define RPM_STRING_TYPE 6
42#define RPM_BIN_TYPE 7
43#define RPM_STRING_ARRAY_TYPE 8
44#define RPM_I18NSTRING_TYPE 9
45
46#define RPMTAG_NAME 1000
47#define RPMTAG_VERSION 1001
48#define RPMTAG_RELEASE 1002
49#define RPMTAG_SUMMARY 1004
50#define RPMTAG_DESCRIPTION 1005
51#define RPMTAG_BUILDTIME 1006
52#define RPMTAG_BUILDHOST 1007
53#define RPMTAG_SIZE 1009
54#define RPMTAG_VENDOR 1011
55#define RPMTAG_LICENSE 1014
56#define RPMTAG_PACKAGER 1015
57#define RPMTAG_GROUP 1016
58#define RPMTAG_URL 1020
59#define RPMTAG_PREIN 1023
60#define RPMTAG_POSTIN 1024
61#define RPMTAG_FILEFLAGS 1037
62#define RPMTAG_FILEUSERNAME 1039
63#define RPMTAG_FILEGROUPNAME 1040
64#define RPMTAG_SOURCERPM 1044
65#define RPMTAG_PREINPROG 1085
66#define RPMTAG_POSTINPROG 1086
67#define RPMTAG_PREFIXS 1098
68#define RPMTAG_DIRINDEXES 1116
69#define RPMTAG_BASENAMES 1117
70#define RPMTAG_DIRNAMES 1118
71#define RPMFILE_CONFIG (1 << 0)
72#define RPMFILE_DOC (1 << 1)
73
74enum rpm_functions_e {
75 rpm_query = 1,
76 rpm_install = 2,
77 rpm_query_info = 4,
78 rpm_query_package = 8,
79 rpm_query_list = 16,
80 rpm_query_list_doc = 32,
81 rpm_query_list_config = 64
82};
83
84typedef struct {
85 uint32_t tag; /* 4 byte tag */
86 uint32_t type; /* 4 byte type */
87 uint32_t offset; /* 4 byte offset */
88 uint32_t count; /* 4 byte count */
89} rpm_index;
90
91static void *map;
92static rpm_index **mytags;
93static int tagcount;
94
95void extract_cpio_gz(int fd);
96rpm_index **rpm_gettags(int fd, int *num_tags);
97int bsearch_rpmtag(const void *key, const void *item);
98char *rpm_getstring(int tag, int itemindex);
99int rpm_getint(int tag, int itemindex);
100int rpm_getcount(int tag);
101void exec_script(int progtag, int datatag, char *prefix);
102void fileaction_dobackup(char *filename, int fileref);
103void fileaction_setowngrp(char *filename, int fileref);
104void fileaction_list(char *filename, int itemno);
105void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref));
106
107int rpm_main(int argc, char **argv)
108{
109 int opt = 0, func = 0, rpm_fd, offset;
110
111 while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
112 switch (opt) {
113 case 'i': // First arg: Install mode, with q: Information
114 if (!func) func |= rpm_install;
115 else func |= rpm_query_info;
116 break;
117 case 'q': // First arg: Query mode
118 if (!func) func |= rpm_query;
119 else bb_show_usage();
120 break;
121 case 'p': // Query a package
122 func |= rpm_query_package;
123 break;
124 case 'l': // List files in a package
125 func |= rpm_query_list;
126 break;
127 case 'd': // List doc files in a package (implies list)
128 func |= rpm_query_list;
129 func |= rpm_query_list_doc;
130 break;
131 case 'c': // List config files in a package (implies list)
132 func |= rpm_query_list;
133 func |= rpm_query_list_config;
134 break;
135 default:
136 bb_show_usage();
137 }
138 }
139
140 if (optind == argc) bb_show_usage();
141 while (optind < argc) {
142 rpm_fd = bb_xopen(argv[optind], O_RDONLY);
143 mytags = rpm_gettags(rpm_fd, (int *) &tagcount);
144 offset = lseek(rpm_fd, 0, SEEK_CUR);
145 if (!mytags) { printf("Error reading rpm header\n"); exit(-1); }
146 map = mmap(0, offset > getpagesize() ? (offset + offset % getpagesize()) : getpagesize(), PROT_READ, MAP_SHARED, rpm_fd, 0); // Mimimum is one page
147 if (func & rpm_install) {
148 loop_through_files(RPMTAG_BASENAMES, fileaction_dobackup); /* Backup any config files */
149 extract_cpio_gz(rpm_fd); // Extact the archive
150 loop_through_files(RPMTAG_BASENAMES, fileaction_setowngrp); /* Set the correct file uid/gid's */
151 } else if (func & rpm_query && func & rpm_query_package) {
152 if (!((func & rpm_query_info) || (func & rpm_query_list))) { // If just a straight query, just give package name
153 printf("%s-%s-%s\n", rpm_getstring(RPMTAG_NAME, 0), rpm_getstring(RPMTAG_VERSION, 0), rpm_getstring(RPMTAG_RELEASE, 0));
154 }
155 if (func & rpm_query_info) {
156 /* Do the nice printout */
157 time_t bdate_time;
158 struct tm *bdate;
159 char bdatestring[50];
160 printf("Name : %-29sRelocations: %s\n", rpm_getstring(RPMTAG_NAME, 0), rpm_getstring(RPMTAG_PREFIXS, 0) ? rpm_getstring(RPMTAG_PREFIXS, 0) : "(not relocateable)");
161 printf("Version : %-34sVendor: %s\n", rpm_getstring(RPMTAG_VERSION, 0), rpm_getstring(RPMTAG_VENDOR, 0) ? rpm_getstring(RPMTAG_VENDOR, 0) : "(none)");
162 bdate_time = rpm_getint(RPMTAG_BUILDTIME, 0);
163 bdate = localtime((time_t *) &bdate_time);
164 strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate);
165 printf("Release : %-30sBuild Date: %s\n", rpm_getstring(RPMTAG_RELEASE, 0), bdatestring);
166 printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstring(RPMTAG_BUILDHOST, 0));
167 printf("Group : %-30sSource RPM: %s\n", rpm_getstring(RPMTAG_GROUP, 0), rpm_getstring(RPMTAG_SOURCERPM, 0));
168 printf("Size : %-33dLicense: %s\n", rpm_getint(RPMTAG_SIZE, 0), rpm_getstring(RPMTAG_LICENSE, 0));
169 printf("URL : %s\n", rpm_getstring(RPMTAG_URL, 0));
170 printf("Summary : %s\n", rpm_getstring(RPMTAG_SUMMARY, 0));
171 printf("Description :\n%s\n", rpm_getstring(RPMTAG_DESCRIPTION, 0));
172 }
173 if (func & rpm_query_list) {
174 int count, it, flags;
175 count = rpm_getcount(RPMTAG_BASENAMES);
176 for (it = 0; it < count; it++) {
177 flags = rpm_getint(RPMTAG_FILEFLAGS, it);
178 switch ((func & rpm_query_list_doc) + (func & rpm_query_list_config))
179 {
180 case rpm_query_list_doc: if (!(flags & RPMFILE_DOC)) continue; break;
181 case rpm_query_list_config: if (!(flags & RPMFILE_CONFIG)) continue; break;
182 case rpm_query_list_doc + rpm_query_list_config: if (!((flags & RPMFILE_CONFIG) || (flags & RPMFILE_DOC))) continue; break;
183 }
184 printf("%s%s\n", rpm_getstring(RPMTAG_DIRNAMES, rpm_getint(RPMTAG_DIRINDEXES, it)), rpm_getstring(RPMTAG_BASENAMES, it));
185 }
186 }
187 }
188 optind++;
189 free (mytags);
190 }
191 return 0;
192}
193
194void extract_cpio_gz(int fd) {
195 archive_handle_t *archive_handle;
196 unsigned char magic[2];
197
198 /* Initialise */
199 archive_handle = init_handle();
200 archive_handle->seek = seek_by_char;
201 //archive_handle->action_header = header_list;
202 archive_handle->action_data = data_extract_all;
203 archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
204 archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS;
205 archive_handle->src_fd = fd;
206 archive_handle->offset = 0;
207
208 bb_xread_all(archive_handle->src_fd, &magic, 2);
209 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
210 bb_error_msg_and_die("Invalid gzip magic");
211 }
212 check_header_gzip(archive_handle->src_fd);
213 chdir("/"); // Install RPM's to root
214
215 archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
216 archive_handle->offset = 0;
217 while (get_header_cpio(archive_handle) == EXIT_SUCCESS);
218}
219
220
221rpm_index **rpm_gettags(int fd, int *num_tags)
222{
223 rpm_index **tags = calloc(200, sizeof(struct rpmtag *)); /* We should never need mode than 200, and realloc later */
224 int pass, tagindex = 0;
225 lseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */
226
227 for (pass = 0; pass < 2; pass++) { /* 1st pass is the signature headers, 2nd is the main stuff */
228 struct {
229 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
230 uint8_t version; /* 1 byte version number */
231 uint32_t reserved; /* 4 bytes reserved */
232 uint32_t entries; /* Number of entries in header (4 bytes) */
233 uint32_t size; /* Size of store (4 bytes) */
234 } header;
235 rpm_index *tmpindex;
236 int storepos;
237
238 read(fd, &header, sizeof(header));
239 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) return NULL; /* Invalid magic */
240 if (header.version != 1) return NULL; /* This program only supports v1 headers */
241 header.size = ntohl(header.size);
242 header.entries = ntohl(header.entries);
243 storepos = lseek(fd,0,SEEK_CUR) + header.entries * 16;
244
245 while (header.entries--) {
246 tmpindex = tags[tagindex++] = malloc(sizeof(rpm_index));
247 read(fd, tmpindex, sizeof(rpm_index));
248 tmpindex->tag = ntohl(tmpindex->tag); tmpindex->type = ntohl(tmpindex->type); tmpindex->count = ntohl(tmpindex->count);
249 tmpindex->offset = storepos + ntohl(tmpindex->offset);
250 if (pass==0) tmpindex->tag -= 743;
251 }
252 lseek(fd, header.size, SEEK_CUR); /* Seek past store */
253 if (pass==0) lseek(fd, (8 - (lseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); /* Skip padding to 8 byte boundary after reading signature headers */
254 }
255 tags = realloc(tags, tagindex * sizeof(struct rpmtag *)); /* realloc tags to save space */
256 *num_tags = tagindex;
257 return tags; /* All done, leave the file at the start of the gzipped cpio archive */
258}
259
260int bsearch_rpmtag(const void *key, const void *item)
261{
262 rpm_index **tmp = (rpm_index **) item;
263 return ((int) key - tmp[0]->tag);
264}
265
266int rpm_getcount(int tag)
267{
268 rpm_index **found;
269 found = bsearch((void *) tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
270 if (!found) return 0;
271 else return found[0]->count;
272}
273
274char *rpm_getstring(int tag, int itemindex)
275{
276 rpm_index **found;
277 found = bsearch((void *) tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
278 if (!found || itemindex >= found[0]->count) return NULL;
279 if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) {
280 int n;
281 char *tmpstr = (char *) (map + found[0]->offset);
282 for (n=0; n < itemindex; n++) tmpstr = tmpstr + strlen(tmpstr) + 1;
283 return tmpstr;
284 } else return NULL;
285}
286
287int rpm_getint(int tag, int itemindex)
288{
289 rpm_index **found;
290 int n, *tmpint;
291 found = bsearch((void *) tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
292 if (!found || itemindex >= found[0]->count) return -1;
293 tmpint = (int *) (map + found[0]->offset);
294 if (found[0]->type == RPM_INT32_TYPE) {
295 for (n=0; n<itemindex; n++) tmpint = (int *) ((void *) tmpint + 4);
296 return ntohl(*tmpint);
297 } else if (found[0]->type == RPM_INT16_TYPE) {
298 for (n=0; n<itemindex; n++) tmpint = (int *) ((void *) tmpint + 2);
299 return ntohs(*tmpint);
300 } else if (found[0]->type == RPM_INT8_TYPE) {
301 for (n=0; n<itemindex; n++) tmpint = (int *) ((void *) tmpint + 1);
302 return ntohs(*tmpint);
303 } else return -1;
304}
305
306void fileaction_dobackup(char *filename, int fileref)
307{
308 struct stat oldfile;
309 int stat_res;
310 char *newname;
311 if (rpm_getint(RPMTAG_FILEFLAGS, fileref) & RPMFILE_CONFIG) { /* Only need to backup config files */
312 stat_res = lstat (filename, &oldfile);
313 if (stat_res == 0 && S_ISREG(oldfile.st_mode)) { /* File already exists - really should check MD5's etc to see if different */
314 newname = bb_xstrdup(filename);
315 newname = strcat(newname, ".rpmorig");
316 copy_file(filename, newname, FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS);
317 remove_file(filename, FILEUTILS_RECUR | FILEUTILS_FORCE);
318 free(newname);
319 }
320 }
321}
322
323void fileaction_setowngrp(char *filename, int fileref)
324{
325 int uid, gid;
326 uid = my_getpwnam(rpm_getstring(RPMTAG_FILEUSERNAME, fileref));
327 gid = my_getgrnam(rpm_getstring(RPMTAG_FILEGROUPNAME, fileref));
328 chown (filename, uid, gid);
329}
330
331void fileaction_list(char *filename, int fileref)
332{
333 printf("%s\n", filename);
334}
335
336void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref))
337{
338 int count = 0;
339 char *filename, *tmp_dirname, *tmp_basename;
340 while (rpm_getstring(filetag, count)) {
341 tmp_dirname = rpm_getstring(RPMTAG_DIRNAMES, rpm_getint(RPMTAG_DIRINDEXES, count)); /* 1st put on the directory */
342 tmp_basename = rpm_getstring(RPMTAG_BASENAMES, count);
343 filename = xmalloc(strlen(tmp_basename) + strlen(tmp_dirname) + 1);
344 strcpy(filename, tmp_dirname); /* First the directory name */
345 strcat(filename, tmp_basename); /* then the filename */
346 fileaction(filename, count++);
347 free(filename);
348 }
349}
diff --git a/busybox/archival/rpm2cpio.c b/busybox/archival/rpm2cpio.c
new file mode 100644
index 000000000..5314e5300
--- /dev/null
+++ b/busybox/archival/rpm2cpio.c
@@ -0,0 +1,106 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini rpm2cpio implementation for busybox
4 *
5 * Copyright (C) 2001 by Laurence Anderson
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
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
20 */
21#include <sys/types.h>
22#include <netinet/in.h> /* For ntohl & htonl function */
23#include <fcntl.h>
24#include <unistd.h>
25#include <string.h>
26#include "busybox.h"
27#include "unarchive.h"
28
29#define RPM_MAGIC "\355\253\356\333"
30#define RPM_HEADER_MAGIC "\216\255\350"
31
32struct rpm_lead {
33 unsigned char magic[4];
34 uint8_t major, minor;
35 uint16_t type;
36 uint16_t archnum;
37 char name[66];
38 uint16_t osnum;
39 uint16_t signature_type;
40 char reserved[16];
41};
42
43struct rpm_header {
44 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
45 uint8_t version; /* 1 byte version number */
46 uint32_t reserved; /* 4 bytes reserved */
47 uint32_t entries; /* Number of entries in header (4 bytes) */
48 uint32_t size; /* Size of store (4 bytes) */
49};
50
51void skip_header(int rpm_fd)
52{
53 struct rpm_header header;
54
55 bb_xread_all(rpm_fd, &header, sizeof(struct rpm_header));
56 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) {
57 bb_error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */
58 }
59 if (header.version != 1) {
60 bb_error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */
61 }
62 header.entries = ntohl(header.entries);
63 header.size = ntohl(header.size);
64 lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */
65 lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */
66}
67
68/* No getopt required */
69extern int rpm2cpio_main(int argc, char **argv)
70{
71 struct rpm_lead lead;
72 int rpm_fd;
73 unsigned char magic[2];
74
75 if (argc == 1) {
76 rpm_fd = STDIN_FILENO;
77 } else {
78 rpm_fd = bb_xopen(argv[1], O_RDONLY);
79 }
80
81 bb_xread_all(rpm_fd, &lead, sizeof(struct rpm_lead));
82 if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) {
83 bb_error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */
84 }
85
86 /* Skip the signature header */
87 skip_header(rpm_fd);
88 lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR);
89
90 /* Skip the main header */
91 skip_header(rpm_fd);
92
93 bb_xread_all(rpm_fd, &magic, 2);
94 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
95 bb_error_msg_and_die("Invalid gzip magic");
96 }
97
98 check_header_gzip(rpm_fd);
99 if (inflate_gunzip(rpm_fd, STDOUT_FILENO) != 0) {
100 bb_error_msg("Error inflating");
101 }
102
103 close(rpm_fd);
104
105 return 0;
106}
diff --git a/busybox/archival/tar.c b/busybox/archival/tar.c
new file mode 100644
index 000000000..950e21dd3
--- /dev/null
+++ b/busybox/archival/tar.c
@@ -0,0 +1,891 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini tar implementation for busybox
4 *
5 * Modified to use common extraction code used by ar, cpio, dpkg-deb, dpkg
6 * Glenn McGrath <bug1@iinet.net.au>
7 *
8 * Note, that as of BusyBox-0.43, tar has been completely rewritten from the
9 * ground up. It still has remnants of the old code lying about, but it is
10 * very different now (i.e., cleaner, less global variables, etc.)
11 *
12 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
13 *
14 * Based in part in the tar implementation in sash
15 * Copyright (c) 1999 by David I. Bell
16 * Permission is granted to use, distribute, or modify this source,
17 * provided that this copyright notice remains intact.
18 * Permission to distribute sash derived code under the GPL has been granted.
19 *
20 * Based in part on the tar implementation from busybox-0.28
21 * Copyright (C) 1995 Bruce Perens
22 * This is free software under the GNU General Public License.
23 *
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 * General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 *
38 */
39
40#include <fcntl.h>
41#include <getopt.h>
42#include <search.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <unistd.h>
46#include <fnmatch.h>
47#include <string.h>
48#include <errno.h>
49#include <signal.h>
50#include <sys/wait.h>
51#include <sys/socket.h>
52#include <sys/sysmacros.h> /* major() and minor() */
53#include "unarchive.h"
54#include "busybox.h"
55
56#ifdef CONFIG_FEATURE_TAR_CREATE
57
58/* Tar file constants */
59# define TAR_MAGIC "ustar" /* ustar and a null */
60# define TAR_VERSION " " /* Be compatable with GNU tar format */
61
62static const int TAR_BLOCK_SIZE = 512;
63static const int TAR_MAGIC_LEN = 6;
64static const int TAR_VERSION_LEN = 2;
65
66/* POSIX tar Header Block, from POSIX 1003.1-1990 */
67enum { NAME_SIZE = 100 }; /* because gcc won't let me use 'static const int' */
68struct TarHeader { /* byte offset */
69 char name[NAME_SIZE]; /* 0-99 */
70 char mode[8]; /* 100-107 */
71 char uid[8]; /* 108-115 */
72 char gid[8]; /* 116-123 */
73 char size[12]; /* 124-135 */
74 char mtime[12]; /* 136-147 */
75 char chksum[8]; /* 148-155 */
76 char typeflag; /* 156-156 */
77 char linkname[NAME_SIZE]; /* 157-256 */
78 char magic[6]; /* 257-262 */
79 char version[2]; /* 263-264 */
80 char uname[32]; /* 265-296 */
81 char gname[32]; /* 297-328 */
82 char devmajor[8]; /* 329-336 */
83 char devminor[8]; /* 337-344 */
84 char prefix[155]; /* 345-499 */
85 char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */
86};
87typedef struct TarHeader TarHeader;
88
89/*
90** writeTarFile(), writeFileToTarball(), and writeTarHeader() are
91** the only functions that deal with the HardLinkInfo structure.
92** Even these functions use the xxxHardLinkInfo() functions.
93*/
94typedef struct HardLinkInfo HardLinkInfo;
95struct HardLinkInfo {
96 HardLinkInfo *next; /* Next entry in list */
97 dev_t dev; /* Device number */
98 ino_t ino; /* Inode number */
99 short linkCount; /* (Hard) Link Count */
100 char name[1]; /* Start of filename (must be last) */
101};
102
103/* Some info to be carried along when creating a new tarball */
104struct TarBallInfo {
105 char *fileName; /* File name of the tarball */
106 int tarFd; /* Open-for-write file descriptor
107 for the tarball */
108 struct stat statBuf; /* Stat info for the tarball, letting
109 us know the inode and device that the
110 tarball lives, so we can avoid trying
111 to include the tarball into itself */
112 int verboseFlag; /* Whether to print extra stuff or not */
113 const llist_t *excludeList; /* List of files to not include */
114 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
115 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
116};
117typedef struct TarBallInfo TarBallInfo;
118
119/* A nice enum with all the possible tar file content types */
120enum TarFileType {
121 REGTYPE = '0', /* regular file */
122 REGTYPE0 = '\0', /* regular file (ancient bug compat) */
123 LNKTYPE = '1', /* hard link */
124 SYMTYPE = '2', /* symbolic link */
125 CHRTYPE = '3', /* character special */
126 BLKTYPE = '4', /* block special */
127 DIRTYPE = '5', /* directory */
128 FIFOTYPE = '6', /* FIFO special */
129 CONTTYPE = '7', /* reserved */
130 GNULONGLINK = 'K', /* GNU long (>100 chars) link name */
131 GNULONGNAME = 'L', /* GNU long (>100 chars) file name */
132};
133typedef enum TarFileType TarFileType;
134
135/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
136static inline void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr,
137 struct stat *statbuf,
138 const char *name)
139{
140 /* Note: hlInfoHeadPtr can never be NULL! */
141 HardLinkInfo *hlInfo;
142
143 hlInfo = (HardLinkInfo *) xmalloc(sizeof(HardLinkInfo) + strlen(name));
144 hlInfo->next = *hlInfoHeadPtr;
145 *hlInfoHeadPtr = hlInfo;
146 hlInfo->dev = statbuf->st_dev;
147 hlInfo->ino = statbuf->st_ino;
148 hlInfo->linkCount = statbuf->st_nlink;
149 strcpy(hlInfo->name, name);
150}
151
152static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr)
153{
154 HardLinkInfo *hlInfo = NULL;
155 HardLinkInfo *hlInfoNext = NULL;
156
157 if (hlInfoHeadPtr) {
158 hlInfo = *hlInfoHeadPtr;
159 while (hlInfo) {
160 hlInfoNext = hlInfo->next;
161 free(hlInfo);
162 hlInfo = hlInfoNext;
163 }
164 *hlInfoHeadPtr = NULL;
165 }
166 return;
167}
168
169/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
170static inline HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf)
171{
172 while (hlInfo) {
173 if ((statbuf->st_ino == hlInfo->ino) && (statbuf->st_dev == hlInfo->dev))
174 break;
175 hlInfo = hlInfo->next;
176 }
177 return (hlInfo);
178}
179
180/* Put an octal string into the specified buffer.
181 * The number is zero and space padded and possibly null padded.
182 * Returns TRUE if successful. */
183static int putOctal(char *cp, int len, long value)
184{
185 int tempLength;
186 char tempBuffer[32];
187 char *tempString = tempBuffer;
188
189 /* Create a string of the specified length with an initial space,
190 * leading zeroes and the octal number, and a trailing null. */
191 sprintf(tempString, "%0*lo", len - 1, value);
192
193 /* If the string is too large, suppress the leading space. */
194 tempLength = strlen(tempString) + 1;
195 if (tempLength > len) {
196 tempLength--;
197 tempString++;
198 }
199
200 /* If the string is still too large, suppress the trailing null. */
201 if (tempLength > len)
202 tempLength--;
203
204 /* If the string is still too large, fail. */
205 if (tempLength > len)
206 return FALSE;
207
208 /* Copy the string to the field. */
209 memcpy(cp, tempString, len);
210
211 return TRUE;
212}
213
214/* Write out a tar header for the specified file/directory/whatever */
215static inline int writeTarHeader(struct TarBallInfo *tbInfo,
216 const char *header_name,
217 const char *real_name, struct stat *statbuf)
218{
219 long chksum = 0;
220 struct TarHeader header;
221 const unsigned char *cp = (const unsigned char *) &header;
222 ssize_t size = sizeof(struct TarHeader);
223
224 memset(&header, 0, size);
225
226 strncpy(header.name, header_name, sizeof(header.name));
227
228 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
229 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
230 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
231 putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
232 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
233 strncpy(header.magic, TAR_MAGIC TAR_VERSION,
234 TAR_MAGIC_LEN + TAR_VERSION_LEN);
235
236 /* Enter the user and group names (default to root if it fails) */
237 if (my_getpwuid(header.uname, statbuf->st_uid, sizeof(header.uname)) == NULL)
238 strcpy(header.uname, "root");
239 if (my_getgrgid(header.gname, statbuf->st_gid, sizeof(header.gname)) == NULL)
240 strcpy(header.gname, "root");
241
242 if (tbInfo->hlInfo) {
243 /* This is a hard link */
244 header.typeflag = LNKTYPE;
245 strncpy(header.linkname, tbInfo->hlInfo->name,
246 sizeof(header.linkname));
247 } else if (S_ISLNK(statbuf->st_mode)) {
248 char *lpath = xreadlink(real_name);
249
250 if (!lpath) /* Already printed err msg inside xreadlink() */
251 return (FALSE);
252 header.typeflag = SYMTYPE;
253 strncpy(header.linkname, lpath, sizeof(header.linkname));
254 free(lpath);
255 } else if (S_ISDIR(statbuf->st_mode)) {
256 header.typeflag = DIRTYPE;
257 strncat(header.name, "/", sizeof(header.name));
258 } else if (S_ISCHR(statbuf->st_mode)) {
259 header.typeflag = CHRTYPE;
260 putOctal(header.devmajor, sizeof(header.devmajor),
261 major(statbuf->st_rdev));
262 putOctal(header.devminor, sizeof(header.devminor),
263 minor(statbuf->st_rdev));
264 } else if (S_ISBLK(statbuf->st_mode)) {
265 header.typeflag = BLKTYPE;
266 putOctal(header.devmajor, sizeof(header.devmajor),
267 major(statbuf->st_rdev));
268 putOctal(header.devminor, sizeof(header.devminor),
269 minor(statbuf->st_rdev));
270 } else if (S_ISFIFO(statbuf->st_mode)) {
271 header.typeflag = FIFOTYPE;
272 } else if (S_ISREG(statbuf->st_mode)) {
273 header.typeflag = REGTYPE;
274 putOctal(header.size, sizeof(header.size), statbuf->st_size);
275 } else {
276 bb_error_msg("%s: Unknown file type", real_name);
277 return (FALSE);
278 }
279
280 /* Calculate and store the checksum (i.e., the sum of all of the bytes of
281 * the header). The checksum field must be filled with blanks for the
282 * calculation. The checksum field is formatted differently from the
283 * other fields: it has [6] digits, a null, then a space -- rather than
284 * digits, followed by a null like the other fields... */
285 memset(header.chksum, ' ', sizeof(header.chksum));
286 cp = (const unsigned char *) &header;
287 while (size-- > 0)
288 chksum += *cp++;
289 putOctal(header.chksum, 7, chksum);
290
291 /* Now write the header out to disk */
292 if ((size =
293 bb_full_write(tbInfo->tarFd, (char *) &header,
294 sizeof(struct TarHeader))) < 0) {
295 bb_error_msg(bb_msg_io_error, real_name);
296 return (FALSE);
297 }
298 /* Pad the header up to the tar block size */
299 for (; size < TAR_BLOCK_SIZE; size++) {
300 write(tbInfo->tarFd, "\0", 1);
301 }
302 /* Now do the verbose thing (or not) */
303
304 if (tbInfo->verboseFlag) {
305 FILE *vbFd = stdout;
306
307 if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */
308 vbFd = stderr;
309
310 fprintf(vbFd, "%s\n", header.name);
311 }
312
313 return (TRUE);
314}
315
316# ifdef CONFIG_FEATURE_TAR_FROM
317static inline int exclude_file(const llist_t *excluded_files, const char *file)
318{
319 while (excluded_files) {
320 if (excluded_files->data[0] == '/') {
321 if (fnmatch(excluded_files->data, file,
322 FNM_PATHNAME | FNM_LEADING_DIR) == 0)
323 return 1;
324 } else {
325 const char *p;
326
327 for (p = file; p[0] != '\0'; p++) {
328 if ((p == file || p[-1] == '/') && p[0] != '/' &&
329 fnmatch(excluded_files->data, p,
330 FNM_PATHNAME | FNM_LEADING_DIR) == 0)
331 return 1;
332 }
333 }
334 excluded_files = excluded_files->link;
335 }
336
337 return 0;
338}
339# endif
340
341static int writeFileToTarball(const char *fileName, struct stat *statbuf,
342 void *userData)
343{
344 struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
345 const char *header_name;
346
347 /*
348 ** Check to see if we are dealing with a hard link.
349 ** If so -
350 ** Treat the first occurance of a given dev/inode as a file while
351 ** treating any additional occurances as hard links. This is done
352 ** by adding the file information to the HardLinkInfo linked list.
353 */
354 tbInfo->hlInfo = NULL;
355 if (statbuf->st_nlink > 1) {
356 tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf);
357 if (tbInfo->hlInfo == NULL)
358 addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, fileName);
359 }
360
361 /* It is against the rules to archive a socket */
362 if (S_ISSOCK(statbuf->st_mode)) {
363 bb_error_msg("%s: socket ignored", fileName);
364 return (TRUE);
365 }
366
367 /* It is a bad idea to store the archive we are in the process of creating,
368 * so check the device and inode to be sure that this particular file isn't
369 * the new tarball */
370 if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
371 tbInfo->statBuf.st_ino == statbuf->st_ino) {
372 bb_error_msg("%s: file is the archive; skipping", fileName);
373 return (TRUE);
374 }
375
376 header_name = fileName;
377 while (header_name[0] == '/') {
378 static int alreadyWarned = FALSE;
379
380 if (alreadyWarned == FALSE) {
381 bb_error_msg("Removing leading '/' from member names");
382 alreadyWarned = TRUE;
383 }
384 header_name++;
385 }
386
387 if (strlen(fileName) >= NAME_SIZE) {
388 bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE);
389 return (TRUE);
390 }
391
392 if (header_name[0] == '\0')
393 return TRUE;
394
395# ifdef CONFIG_FEATURE_TAR_FROM
396 if (exclude_file(tbInfo->excludeList, header_name)) {
397 return SKIP;
398 }
399# endif /* CONFIG_FEATURE_TAR_FROM */
400
401 if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) {
402 return (FALSE);
403 }
404
405 /* Now, if the file is a regular file, copy it out to the tarball */
406 if ((tbInfo->hlInfo == NULL)
407 && (S_ISREG(statbuf->st_mode))) {
408 int inputFileFd;
409 ssize_t readSize = 0;
410
411 /* open the file we want to archive, and make sure all is well */
412 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
413 bb_perror_msg("%s: Cannot open", fileName);
414 return (FALSE);
415 }
416
417 /* write the file to the archive */
418 readSize = bb_copyfd_eof(inputFileFd, tbInfo->tarFd);
419
420 /* Pad the file up to the tar block size */
421 for (; (readSize % TAR_BLOCK_SIZE) != 0; readSize++) {
422 write(tbInfo->tarFd, "\0", 1);
423 }
424 close(inputFileFd);
425 }
426
427 return (TRUE);
428}
429
430static inline int writeTarFile(const int tar_fd, const int verboseFlag,
431 const unsigned long dereferenceFlag, const llist_t *include,
432 const llist_t *exclude, const int gzip)
433{
434#ifdef CONFIG_FEATURE_TAR_GZIP
435 int gzipDataPipe[2] = { -1, -1 };
436 int gzipStatusPipe[2] = { -1, -1 };
437 pid_t gzipPid = 0;
438 volatile int vfork_exec_errno = 0;
439#endif
440
441 int errorFlag = FALSE;
442 ssize_t size;
443 struct TarBallInfo tbInfo;
444
445 tbInfo.hlInfoHead = NULL;
446
447 fchmod(tar_fd, 0644);
448 tbInfo.tarFd = tar_fd;
449 tbInfo.verboseFlag = verboseFlag;
450
451 /* Store the stat info for the tarball's file, so
452 * can avoid including the tarball into itself.... */
453 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
454 bb_perror_msg_and_die("Couldnt stat tar file");
455
456#ifdef CONFIG_FEATURE_TAR_GZIP
457 if (gzip) {
458 if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) {
459 bb_perror_msg_and_die("Failed to create gzip pipe");
460 }
461
462 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
463
464# if __GNUC__
465 /* Avoid vfork clobbering */
466 (void) &include;
467 (void) &errorFlag;
468# endif
469
470 gzipPid = vfork();
471
472 if (gzipPid == 0) {
473 dup2(gzipDataPipe[0], 0);
474 close(gzipDataPipe[1]);
475
476 if (tbInfo.tarFd != 1)
477 dup2(tbInfo.tarFd, 1);
478
479 close(gzipStatusPipe[0]);
480 fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows sucess */
481
482 execl("/bin/gzip", "gzip", "-f", 0);
483 vfork_exec_errno = errno;
484
485 close(gzipStatusPipe[1]);
486 exit(-1);
487 } else if (gzipPid > 0) {
488 close(gzipDataPipe[0]);
489 close(gzipStatusPipe[1]);
490
491 while (1) {
492 char buf;
493
494 int n = bb_full_read(gzipStatusPipe[0], &buf, 1);
495
496 if (n == 0 && vfork_exec_errno != 0) {
497 errno = vfork_exec_errno;
498 bb_perror_msg_and_die("Could not exec gzip process");
499 } else if ((n < 0) && (errno == EAGAIN || errno == EINTR))
500 continue; /* try it again */
501 break;
502 }
503 close(gzipStatusPipe[0]);
504
505 tbInfo.tarFd = gzipDataPipe[1];
506 } else {
507 bb_perror_msg_and_die("Failed to vfork gzip process");
508 }
509 }
510#endif
511
512 tbInfo.excludeList = exclude;
513
514 /* Read the directory/files and iterate over them one at a time */
515 while (include) {
516 if (!recursive_action(include->data, TRUE, dereferenceFlag, FALSE,
517 writeFileToTarball, writeFileToTarball,
518 (void *) &tbInfo)) {
519 errorFlag = TRUE;
520 }
521 include = include->link;
522 }
523 /* Write two empty blocks to the end of the archive */
524 for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++) {
525 write(tbInfo.tarFd, "\0", 1);
526 }
527
528 /* To be pedantically correct, we would check if the tarball
529 * is smaller than 20 tar blocks, and pad it if it was smaller,
530 * but that isn't necessary for GNU tar interoperability, and
531 * so is considered a waste of space */
532
533 /* Hang up the tools, close up shop, head home */
534 close(tbInfo.tarFd);
535 if (errorFlag)
536 bb_error_msg("Error exit delayed from previous errors");
537
538 freeHardLinkInfo(&tbInfo.hlInfoHead);
539
540#ifdef CONFIG_FEATURE_TAR_GZIP
541 if (gzip && gzipPid) {
542 if (waitpid(gzipPid, NULL, 0) == -1)
543 printf("Couldnt wait ?");
544 }
545#endif
546
547 return !errorFlag;
548}
549#endif /* tar_create */
550
551#ifdef CONFIG_FEATURE_TAR_FROM
552static llist_t *append_file_list_to_list(llist_t *list)
553{
554 FILE *src_stream;
555 llist_t *cur = list;
556 llist_t *tmp;
557 char *line;
558 llist_t *newlist = NULL;
559
560 while(cur) {
561 src_stream = bb_xfopen(cur->data, "r");
562 tmp = cur;
563 cur = cur->link;
564 free(tmp);
565 while((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
566 newlist = llist_add_to(newlist, line);
567 }
568 fclose(src_stream);
569 }
570 return newlist;
571}
572#endif
573
574#ifdef CONFIG_FEATURE_TAR_COMPRESS
575static char get_header_tar_Z(archive_handle_t *archive_handle)
576{
577 /* Cant lseek over pipe's */
578 archive_handle->seek = seek_by_char;
579
580 /* do the decompression, and cleanup */
581 if ((bb_xread_char(archive_handle->src_fd) != 0x1f) || (bb_xread_char(archive_handle->src_fd) != 0x9d)) {
582 bb_error_msg_and_die("Invalid magic");
583 }
584
585 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress);
586 archive_handle->offset = 0;
587 while (get_header_tar(archive_handle) == EXIT_SUCCESS);
588
589 /* Can only do one file at a time */
590 return(EXIT_FAILURE);
591}
592#endif
593
594#define CTX_TEST (1 << 0)
595#define CTX_EXTRACT (1 << 1)
596#define TAR_OPT_BASEDIR (1 << 2)
597#define TAR_OPT_TARNAME (1 << 3)
598#define TAR_OPT_2STDOUT (1 << 4)
599#define TAR_OPT_P (1 << 5)
600#define TAR_OPT_VERBOSE (1 << 6)
601#define TAR_OPT_KEEP_OLD (1 << 7)
602
603#ifdef CONFIG_FEATURE_TAR_CREATE
604# define CTX_CREATE (1 << 8)
605# define TAR_OPT_DEREFERNCE (1 << 9)
606# define TAR_OPT_STR_CREATE "ch"
607# define TAR_OPT_FLAG_CREATE 2
608#else
609//# define CTX_CREATE 0
610# define TAR_OPT_STR_CREATE ""
611# define TAR_OPT_FLAG_CREATE 0
612#endif
613
614#ifdef CONFIG_FEATURE_TAR_BZIP2
615# define TAR_OPT_BZIP2 (1 << (8 + TAR_OPT_FLAG_CREATE))
616# define TAR_OPT_STR_BZIP2 "j"
617# define TAR_OPT_FLAG_BZIP2 1
618#else
619# define TAR_OPT_STR_BZIP2 ""
620# define TAR_OPT_FLAG_BZIP2 0
621#endif
622
623#ifdef CONFIG_FEATURE_TAR_FROM
624# define TAR_OPT_INCLUDE_FROM (1 << (8 + TAR_OPT_FLAG_CREATE + TAR_OPT_FLAG_BZIP2))
625# define TAR_OPT_EXCLUDE_FROM (1 << (8 + TAR_OPT_FLAG_CREATE + TAR_OPT_FLAG_BZIP2 + 1))
626# define TAR_OPT_STR_FROM "T:X:"
627# define TAR_OPT_FLAG_FROM 2
628#else
629# define TAR_OPT_STR_FROM ""
630# define TAR_OPT_FLAG_FROM 0
631#endif
632
633#ifdef CONFIG_FEATURE_TAR_GZIP
634# define TAR_OPT_GZIP (1 << (8 + TAR_OPT_FLAG_CREATE + TAR_OPT_FLAG_BZIP2 + TAR_OPT_FLAG_FROM))
635# define TAR_OPT_STR_GZIP "z"
636# define TAR_OPT_FLAG_GZIP 1
637#else
638# define TAR_OPT_STR_GZIP ""
639# define TAR_OPT_FLAG_GZIP 0
640#endif
641
642#ifdef CONFIG_FEATURE_TAR_COMPRESS
643# define TAR_OPT_UNCOMPRESS (1 << (8 + TAR_OPT_FLAG_CREATE + TAR_OPT_FLAG_BZIP2 + TAR_OPT_FLAG_FROM + TAR_OPT_FLAG_GZIP))
644# define TAR_OPT_STR_COMPRESS "Z"
645#else
646# define TAR_OPT_STR_COMPRESS ""
647#endif
648
649static const char tar_options[]="txC:f:Opvk" \
650 TAR_OPT_STR_CREATE \
651 TAR_OPT_STR_BZIP2 \
652 TAR_OPT_STR_FROM \
653 TAR_OPT_STR_GZIP \
654 TAR_OPT_STR_COMPRESS;
655
656#ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS
657static const struct option tar_long_options[] = {
658 { "list", 0, NULL, 't' },
659 { "extract", 0, NULL, 'x' },
660 { "directory", 1, NULL, 'C' },
661 { "file", 1, NULL, 'f' },
662 { "to-stdout", 0, NULL, 'O' },
663 { "same-permissions", 0, NULL, 'p' },
664 { "verbose", 0, NULL, 'v' },
665 { "keep-old", 0, NULL, 'k' },
666# ifdef CONFIG_FEATURE_TAR_CREATE
667 { "create", 0, NULL, 'c' },
668 { "dereference", 0, NULL, 'h' },
669# endif
670# ifdef CONFIG_FEATURE_TAR_BZIP2
671 { "bzip2", 0, NULL, 'j' },
672# endif
673# ifdef CONFIG_FEATURE_TAR_FROM
674 { "files-from", 1, NULL, 'T' },
675 { "exclude-from", 1, NULL, 'X' },
676# endif
677# ifdef CONFIG_FEATURE_TAR_GZIP
678 { "gzip", 0, NULL, 'z' },
679# endif
680# ifdef CONFIG_FEATURE_TAR_COMPRESS
681 { "compress", 0, NULL, 'Z' },
682# endif
683 { 0, 0, 0, 0 }
684};
685#endif
686
687int tar_main(int argc, char **argv)
688{
689 char (*get_header_ptr)(archive_handle_t *) = get_header_tar;
690 archive_handle_t *tar_handle;
691 char *base_dir = NULL;
692 const char *tar_filename = "-";
693 unsigned long opt;
694 unsigned long ctx_flag = 0;
695
696 if (argc < 2) {
697 bb_show_usage();
698 }
699
700 /* Prepend '-' to the first argument if required */
701 if (argv[1][0] != '-') {
702 char *tmp;
703
704 bb_xasprintf(&tmp, "-%s", argv[1]);
705 argv[1] = tmp;
706 }
707
708 /* Initialise default values */
709 tar_handle = init_handle();
710 tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
711
712 bb_opt_complementaly = "c~tx:t~cx:x~ct:X*:T*";
713#ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS
714 bb_applet_long_options = tar_long_options;
715#endif
716
717 opt = bb_getopt_ulflags(argc, argv, tar_options,
718 &base_dir, /* Change to dir <optarg> */
719 &tar_filename /* archive filename */
720#ifdef CONFIG_FEATURE_TAR_FROM
721 , &(tar_handle->accept),
722 &(tar_handle->reject)
723#endif
724 );
725
726 /* Check one and only one context option was given */
727 if(opt & 0x80000000UL) {
728 bb_show_usage();
729 }
730#ifdef CONFIG_FEATURE_TAR_CREATE
731 ctx_flag = opt & (CTX_CREATE | CTX_TEST | CTX_EXTRACT);
732#else
733 ctx_flag = opt & (CTX_TEST | CTX_EXTRACT);
734#endif
735 if (ctx_flag == 0) {
736 bb_show_usage();
737 }
738 if(ctx_flag & CTX_TEST) {
739 if ((tar_handle->action_header == header_list) ||
740 (tar_handle->action_header == header_verbose_list)) {
741 tar_handle->action_header = header_verbose_list;
742 } else {
743 tar_handle->action_header = header_list;
744 }
745 }
746 if(ctx_flag & CTX_EXTRACT) {
747 if (tar_handle->action_data != data_extract_to_stdout)
748 tar_handle->action_data = data_extract_all;
749 }
750 if(opt & TAR_OPT_2STDOUT) {
751 /* To stdout */
752 tar_handle->action_data = data_extract_to_stdout;
753 }
754 if(opt & TAR_OPT_VERBOSE) {
755 if ((tar_handle->action_header == header_list) ||
756 (tar_handle->action_header == header_verbose_list))
757 {
758 tar_handle->action_header = header_verbose_list;
759 } else {
760 tar_handle->action_header = header_list;
761 }
762 }
763 if (opt & TAR_OPT_KEEP_OLD) {
764 tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;
765 }
766
767#ifdef CONFIG_FEATURE_TAR_GZIP
768 if(opt & TAR_OPT_GZIP) {
769 get_header_ptr = get_header_tar_gz;
770 }
771#endif
772#ifdef CONFIG_FEATURE_TAR_BZIP2
773 if(opt & TAR_OPT_BZIP2) {
774 get_header_ptr = get_header_tar_bz2;
775 }
776#endif
777#ifdef CONFIG_FEATURE_TAR_COMPRESS
778 if(opt & TAR_OPT_UNCOMPRESS) {
779 get_header_ptr = get_header_tar_Z;
780 }
781#endif
782#ifdef CONFIG_FEATURE_TAR_FROM
783 if(opt & TAR_OPT_EXCLUDE_FROM) {
784 tar_handle->reject = append_file_list_to_list(tar_handle->reject);
785 }
786 if(opt & TAR_OPT_INCLUDE_FROM) {
787 tar_handle->accept = append_file_list_to_list(tar_handle->accept);
788 }
789#endif
790
791 /* Check if we are reading from stdin */
792 if ((argv[optind]) && (*argv[optind] == '-')) {
793 /* Default is to read from stdin, so just skip to next arg */
794 optind++;
795 }
796
797 /* Setup an array of filenames to work with */
798 /* TODO: This is the same as in ar, separate function ? */
799 while (optind < argc) {
800 char *filename_ptr = last_char_is(argv[optind], '/');
801 if (filename_ptr) {
802 *filename_ptr = '\0';
803 }
804 tar_handle->accept = llist_add_to(tar_handle->accept, argv[optind]);
805 optind++;
806 }
807
808 if ((tar_handle->accept) || (tar_handle->reject)) {
809 tar_handle->filter = filter_accept_reject_list;
810 }
811
812 /* Open the tar file */
813 {
814 FILE *tar_stream;
815 int flags;
816
817#ifdef CONFIG_FEATURE_TAR_CREATE
818 if (opt & CTX_CREATE) {
819 /* Make sure there is at least one file to tar up. */
820 if (tar_handle->accept == NULL) {
821 bb_error_msg_and_die("Cowardly refusing to create an empty archive");
822 }
823 tar_stream = stdout;
824 flags = O_WRONLY | O_CREAT | O_EXCL;
825 unlink(tar_filename);
826 } else
827#endif
828 {
829 tar_stream = stdin;
830 flags = O_RDONLY;
831 }
832
833 if ((tar_filename[0] == '-') && (tar_filename[1] == '\0')) {
834 tar_handle->src_fd = fileno(tar_stream);
835 tar_handle->seek = seek_by_char;
836 } else {
837 tar_handle->src_fd = bb_xopen(tar_filename, flags);
838 }
839 }
840
841 if ((base_dir) && (chdir(base_dir))) {
842 bb_perror_msg_and_die("Couldnt chdir to %s", base_dir);
843 }
844
845#ifdef CONFIG_FEATURE_TAR_CREATE
846 /* create an archive */
847 if (opt & CTX_CREATE) {
848 int verboseFlag = FALSE;
849 int gzipFlag = FALSE;
850
851# ifdef CONFIG_FEATURE_TAR_GZIP
852 if (get_header_ptr == get_header_tar_gz) {
853 gzipFlag = TRUE;
854 }
855# endif /* CONFIG_FEATURE_TAR_GZIP */
856# ifdef CONFIG_FEATURE_TAR_BZIP2
857 if (get_header_ptr == get_header_tar_bz2) {
858 bb_error_msg_and_die("Creating bzip2 compressed archives is not currently supported.");
859 }
860# endif /* CONFIG_FEATURE_TAR_BZIP2 */
861
862 if ((tar_handle->action_header == header_list) ||
863 (tar_handle->action_header == header_verbose_list)) {
864 verboseFlag = TRUE;
865 }
866 writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERNCE, tar_handle->accept,
867 tar_handle->reject, gzipFlag);
868 } else
869#endif /* CONFIG_FEATURE_TAR_CREATE */
870 {
871 while (get_header_ptr(tar_handle) == EXIT_SUCCESS);
872
873 /* Ckeck that every file that should have been extracted was */
874 while (tar_handle->accept) {
875 if (find_list_entry(tar_handle->reject, tar_handle->accept->data) == NULL) {
876 if (find_list_entry(tar_handle->passed, tar_handle->accept->data) == NULL) {
877 bb_error_msg_and_die("%s: Not found in archive\n", tar_handle->accept->data);
878 }
879 }
880 tar_handle->accept = tar_handle->accept->link;
881 }
882 }
883
884#ifdef CONFIG_FEATURE_CLEAN_UP
885 if (tar_handle->src_fd != STDIN_FILENO) {
886 close(tar_handle->src_fd);
887 }
888#endif /* CONFIG_FEATURE_CLEAN_UP */
889
890 return(EXIT_SUCCESS);
891}
diff --git a/busybox/archival/uncompress.c b/busybox/archival/uncompress.c
new file mode 100644
index 000000000..48b4e2cad
--- /dev/null
+++ b/busybox/archival/uncompress.c
@@ -0,0 +1,115 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Uncompress applet for busybox (c) 2002 Glenn McGrath
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <getopt.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27
28#include "libbb.h"
29#include "unarchive.h"
30
31#define GUNZIP_TO_STDOUT 1
32#define GUNZIP_FORCE 2
33
34extern int uncompress_main(int argc, char **argv)
35{
36 int status = EXIT_SUCCESS;
37 unsigned long flags;
38
39 flags = bb_getopt_ulflags(argc, argv, "cf");
40
41 while (optind < argc) {
42 const char *compressed_file = argv[optind++];
43 const char *delete_path = NULL;
44 char *uncompressed_file = NULL;
45 int src_fd;
46 int dst_fd;
47
48 if (strcmp(compressed_file, "-") == 0) {
49 src_fd = STDIN_FILENO;
50 flags |= GUNZIP_TO_STDOUT;
51 } else {
52 src_fd = bb_xopen(compressed_file, O_RDONLY);
53 }
54
55 /* Check that the input is sane. */
56 if (isatty(src_fd) && ((flags & GUNZIP_FORCE) == 0)) {
57 bb_error_msg_and_die
58 ("compressed data not read from terminal. Use -f to force it.");
59 }
60
61 /* Set output filename and number */
62 if (flags & GUNZIP_TO_STDOUT) {
63 dst_fd = STDOUT_FILENO;
64 } else {
65 struct stat stat_buf;
66 char *extension;
67
68 uncompressed_file = bb_xstrdup(compressed_file);
69
70 extension = strrchr(uncompressed_file, '.');
71 if (!extension || (strcmp(extension, ".Z") != 0)) {
72 bb_error_msg_and_die("Invalid extension");
73 }
74 *extension = '\0';
75
76 /* Open output file */
77 dst_fd = bb_xopen(uncompressed_file, O_WRONLY | O_CREAT);
78
79 /* Set permissions on the file */
80 stat(compressed_file, &stat_buf);
81 chmod(uncompressed_file, stat_buf.st_mode);
82
83 /* If unzip succeeds remove the old file */
84 delete_path = compressed_file;
85 }
86
87 /* do the decompression, and cleanup */
88 if ((bb_xread_char(src_fd) != 0x1f) || (bb_xread_char(src_fd) != 0x9d)) {
89 bb_error_msg_and_die("Invalid magic");
90 }
91
92 status = uncompress(src_fd, dst_fd);
93
94 if ((status != EXIT_SUCCESS) && (uncompressed_file)) {
95 /* Unzip failed, remove the uncomressed file instead of compressed file */
96 delete_path = uncompressed_file;
97 }
98
99 if (dst_fd != STDOUT_FILENO) {
100 close(dst_fd);
101 }
102 if (src_fd != STDIN_FILENO) {
103 close(src_fd);
104 }
105
106 /* delete_path will be NULL if in test mode or from stdin */
107 if (delete_path && (unlink(delete_path) == -1)) {
108 bb_error_msg_and_die("Couldn't remove %s", delete_path);
109 }
110
111 free(uncompressed_file);
112 }
113
114 return status;
115}
diff --git a/busybox/archival/unzip.c b/busybox/archival/unzip.c
new file mode 100644
index 000000000..eea2f5438
--- /dev/null
+++ b/busybox/archival/unzip.c
@@ -0,0 +1,247 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini unzip implementation for busybox
4 *
5 * Copyright (C) 2001 by Laurence Anderson
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
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
20 *
21 */
22
23/* For reference see
24 * http://www.pkware.com/products/enterprise/white_papers/appnote.txt
25 * http://www.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip
26 */
27
28/* TODO Endian issues, exclude, should we accept input from stdin ? */
29
30#include <fcntl.h>
31#include <getopt.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35#include "unarchive.h"
36#include "busybox.h"
37
38#define ZIP_FILEHEADER_MAGIC 0x04034b50
39#define ZIP_CDS_MAGIC 0x02014b50
40#define ZIP_CDS_END_MAGIC 0x06054b50
41#define ZIP_DD_MAGIC 0x08074b50
42
43extern unsigned int gunzip_crc;
44extern unsigned int gunzip_bytes_out;
45
46static void header_list_unzip(const file_header_t *file_header)
47{
48 printf(" inflating: %s\n", file_header->name);
49}
50
51static void header_verbose_list_unzip(const file_header_t *file_header)
52{
53 unsigned int dostime = (unsigned int) file_header->mtime;
54
55 /* can printf arguments cut of the decade component ? */
56 unsigned short year = 1980 + ((dostime & 0xfe000000) >> 25);
57 while (year >= 100) {
58 year -= 100;
59 }
60
61 printf("%9u %02u-%02u-%02u %02u:%02u %s\n",
62 (unsigned int) file_header->size,
63 (dostime & 0x01e00000) >> 21,
64 (dostime & 0x001f0000) >> 16,
65 year,
66 (dostime & 0x0000f800) >> 11,
67 (dostime & 0x000007e0) >> 5,
68 file_header->name);
69}
70
71extern int unzip_main(int argc, char **argv)
72{
73 union {
74 unsigned char raw[26];
75 struct {
76 unsigned short version; /* 0-1 */
77 unsigned short flags; /* 2-3 */
78 unsigned short method; /* 4-5 */
79 unsigned short modtime; /* 6-7 */
80 unsigned short moddate; /* 8-9 */
81 unsigned int crc32 __attribute__ ((packed)); /* 10-13 */
82 unsigned int cmpsize __attribute__ ((packed));; /* 14-17 */
83 unsigned int ucmpsize __attribute__ ((packed));; /* 18-21 */
84 unsigned short filename_len; /* 22-23 */
85 unsigned short extra_len; /* 24-25 */
86 } formated __attribute__ ((packed));
87 } zip_header;
88
89 archive_handle_t *archive_handle;
90 unsigned int total_size = 0;
91 unsigned int total_entries = 0;
92 char *base_dir = NULL;
93 int opt = 0;
94
95 /* Initialise */
96 archive_handle = init_handle();
97 archive_handle->action_data = NULL;
98 archive_handle->action_header = header_list_unzip;
99
100 while ((opt = getopt(argc, argv, "lnopqd:")) != -1) {
101 switch (opt) {
102 case 'l': /* list */
103 archive_handle->action_header = header_verbose_list_unzip;
104 archive_handle->action_data = data_skip;
105 break;
106 case 'n': /* never overwright existing files */
107 break;
108 case 'o':
109 archive_handle->flags = ARCHIVE_EXTRACT_UNCONDITIONAL;
110 break;
111 case 'p': /* extract files to stdout */
112 archive_handle->action_data = data_extract_to_stdout;
113 break;
114 case 'q': /* Extract files quietly */
115 archive_handle->action_header = header_skip;
116 break;
117 case 'd': /* Extract files to specified base directory*/
118 base_dir = optarg;
119 break;
120#if 0
121 case 'x': /* Exclude the specified files */
122 archive_handle->filter = filter_accept_reject_list;
123 break;
124#endif
125 default:
126 bb_show_usage();
127 }
128 }
129
130 if (argc == optind) {
131 bb_show_usage();
132 }
133
134 printf("Archive: %s\n", argv[optind]);
135 if (archive_handle->action_header == header_verbose_list_unzip) {
136 printf(" Length Date Time Name\n");
137 printf(" -------- ---- ---- ----\n");
138 }
139
140 if (*argv[optind] == '-') {
141 archive_handle->src_fd = STDIN_FILENO;
142 archive_handle->seek = seek_by_char;
143 } else {
144 archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY);
145 }
146
147 if ((base_dir) && (chdir(base_dir))) {
148 bb_perror_msg_and_die("Couldnt chdir");
149 }
150
151 while (optind < argc) {
152 archive_handle->filter = filter_accept_list;
153 archive_handle->accept = llist_add_to(archive_handle->accept, argv[optind]);
154 optind++;
155 }
156
157 while (1) {
158 unsigned int magic;
159 int dst_fd;
160
161 /* TODO Endian issues */
162 archive_xread_all(archive_handle, &magic, 4);
163 archive_handle->offset += 4;
164
165 if (magic == ZIP_CDS_MAGIC) {
166 break;
167 }
168 else if (magic != ZIP_FILEHEADER_MAGIC) {
169 bb_error_msg_and_die("Invlaide zip magic");
170 }
171
172 /* Read the file header */
173 archive_xread_all(archive_handle, zip_header.raw, 26);
174 archive_handle->offset += 26;
175 archive_handle->file_header->mode = S_IFREG | 0777;
176
177 if (zip_header.formated.method != 8) {
178 bb_error_msg_and_die("Unsupported compression method %d\n", zip_header.formated.method);
179 }
180
181 /* Read filename */
182 archive_handle->file_header->name = xmalloc(zip_header.formated.filename_len + 1);
183 archive_xread_all(archive_handle, archive_handle->file_header->name, zip_header.formated.filename_len);
184 archive_handle->offset += zip_header.formated.filename_len;
185 archive_handle->file_header->name[zip_header.formated.filename_len] = '\0';
186
187 /* Skip extra header bits */
188 archive_handle->file_header->size = zip_header.formated.extra_len;
189 data_skip(archive_handle);
190 archive_handle->offset += zip_header.formated.extra_len;
191
192 /* Handle directories */
193 archive_handle->file_header->mode = S_IFREG | 0777;
194 if (last_char_is(archive_handle->file_header->name, '/')) {
195 archive_handle->file_header->mode ^= S_IFREG;
196 archive_handle->file_header->mode |= S_IFDIR;
197 }
198
199 /* Data section */
200 archive_handle->file_header->size = zip_header.formated.cmpsize;
201 if (archive_handle->action_data) {
202 archive_handle->action_data(archive_handle);
203 } else {
204 dst_fd = bb_xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT);
205 inflate_init(zip_header.formated.cmpsize);
206 inflate_unzip(archive_handle->src_fd, dst_fd);
207 close(dst_fd);
208 chmod(archive_handle->file_header->name, archive_handle->file_header->mode);
209
210 /* Validate decompression - crc */
211 if (zip_header.formated.crc32 != (gunzip_crc ^ 0xffffffffL)) {
212 bb_error_msg("Invalid compressed data--crc error");
213 }
214
215 /* Validate decompression - size */
216 if (gunzip_bytes_out != zip_header.formated.ucmpsize) {
217 bb_error_msg("Invalid compressed data--length error");
218 }
219 }
220
221 /* local file descriptor section */
222 archive_handle->offset += zip_header.formated.cmpsize;
223 /* This ISNT unix time */
224 archive_handle->file_header->mtime = zip_header.formated.modtime | (zip_header.formated.moddate << 16);
225 archive_handle->file_header->size = zip_header.formated.ucmpsize;
226 total_size += archive_handle->file_header->size;
227 total_entries++;
228
229 archive_handle->action_header(archive_handle->file_header);
230
231 /* Data descriptor section */
232 if (zip_header.formated.flags & 4) {
233 /* skip over duplicate crc, compressed size and uncompressed size */
234 unsigned char data_description[12];
235 archive_xread_all(archive_handle, data_description, 12);
236 archive_handle->offset += 12;
237 }
238 }
239 /* Central directory section */
240
241 if (archive_handle->action_header == header_verbose_list_unzip) {
242 printf(" -------- -------\n");
243 printf("%9d %d files\n", total_size, total_entries);
244 }
245
246 return(EXIT_SUCCESS);
247}