summaryrefslogtreecommitdiff
path: root/i/pc104/initrd/conf/busybox/archival/libunarchive
diff options
context:
space:
mode:
Diffstat (limited to 'i/pc104/initrd/conf/busybox/archival/libunarchive')
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/Kbuild59
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/archive_xread_all_eof.c20
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/check_header_gzip.c59
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/data_align.c17
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_all.c127
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_buffer.c17
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_stdout.c13
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/data_skip.c16
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_bunzip2.c731
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_uncompress.c308
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unlzma.c497
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unzip.c1104
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_all.c17
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list.c19
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list_reassign.c44
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_reject_list.c33
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/find_list_entry.c54
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_ar.c126
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_cpio.c160
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar.c284
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_bz2.c20
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_gz.c31
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_lzma.c22
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/header_list.c11
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/header_skip.c10
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/header_verbose_list.c31
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/init_handle.c22
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/open_transformer.c44
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_jump.c24
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_read.c18
-rw-r--r--i/pc104/initrd/conf/busybox/archival/libunarchive/unpack_ar_archive.c22
31 files changed, 3960 insertions, 0 deletions
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/Kbuild b/i/pc104/initrd/conf/busybox/archival/libunarchive/Kbuild
new file mode 100644
index 0000000..4e14541
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/Kbuild
@@ -0,0 +1,59 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+#
+# Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+
+lib-y:= \
+\
+ data_skip.o \
+ data_extract_all.o \
+ data_extract_to_stdout.o \
+ data_extract_to_buffer.o \
+\
+ filter_accept_all.o \
+ filter_accept_list.o \
+ filter_accept_reject_list.o \
+\
+ header_skip.o \
+ header_list.o \
+ header_verbose_list.o \
+\
+ archive_xread_all_eof.o \
+\
+ seek_by_read.o \
+ seek_by_jump.o \
+\
+ data_align.o \
+ find_list_entry.o \
+ open_transformer.o \
+ init_handle.o
+
+GUNZIP_FILES:= check_header_gzip.o decompress_unzip.o
+DPKG_FILES:= \
+ get_header_ar.o \
+ unpack_ar_archive.o \
+ get_header_tar.o \
+ filter_accept_list_reassign.o
+
+lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
+lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
+lib-$(CONFIG_UNLZMA) += decompress_unlzma.o
+lib-$(CONFIG_CPIO) += get_header_cpio.o
+lib-$(CONFIG_DPKG) += $(DPKG_FILES)
+lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
+lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += $(GUNZIP_FILES) get_header_tar_gz.o
+lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += decompress_bunzip2.o get_header_tar_bz2.o
+lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
+lib-$(CONFIG_GUNZIP) += $(GUNZIP_FILES)
+lib-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
+lib-$(CONFIG_RPM2CPIO) += $(GUNZIP_FILES) get_header_cpio.o
+lib-$(CONFIG_RPM) += $(GUNZIP_FILES) get_header_cpio.o
+lib-$(CONFIG_TAR) += get_header_tar.o
+lib-$(CONFIG_FEATURE_TAR_BZIP2) += decompress_bunzip2.o get_header_tar_bz2.o
+lib-$(CONFIG_FEATURE_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
+lib-$(CONFIG_FEATURE_TAR_GZIP) += $(GUNZIP_FILES) get_header_tar_gz.o
+lib-$(CONFIG_FEATURE_TAR_COMPRESS) += decompress_uncompress.o
+lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
+lib-$(CONFIG_UNZIP) += $(GUNZIP_FILES)
+lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/archive_xread_all_eof.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/archive_xread_all_eof.c
new file mode 100644
index 0000000..007f68c
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/archive_xread_all_eof.c
@@ -0,0 +1,20 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "unarchive.h"
+#include "libbb.h"
+
+ssize_t archive_xread_all_eof(archive_handle_t *archive_handle,
+ unsigned char *buf, size_t count)
+{
+ ssize_t size;
+
+ size = full_read(archive_handle->src_fd, buf, count);
+ if (size != 0 && size != count) {
+ bb_error_msg_and_die("short read: %u of %u",
+ (unsigned)size, (unsigned)count);
+ }
+ return size;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/check_header_gzip.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/check_header_gzip.c
new file mode 100644
index 0000000..66aa574
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/check_header_gzip.c
@@ -0,0 +1,59 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h" /* for external decl of check_header_gzip_or_die */
+
+void check_header_gzip_or_die(int src_fd)
+{
+ union {
+ unsigned char raw[8];
+ struct {
+ unsigned char method;
+ unsigned char flags;
+ unsigned int mtime;
+ unsigned char xtra_flags;
+ unsigned char os_flags;
+ } formatted;
+ } header;
+
+ xread(src_fd, header.raw, 8);
+
+ /* Check the compression method */
+ if (header.formatted.method != 8) {
+ bb_error_msg_and_die("unknown compression method %d",
+ header.formatted.method);
+ }
+
+ if (header.formatted.flags & 0x04) {
+ /* bit 2 set: extra field present */
+ unsigned extra_short;
+
+ extra_short = xread_char(src_fd) + (xread_char(src_fd) << 8);
+ while (extra_short > 0) {
+ /* Ignore extra field */
+ xread_char(src_fd);
+ extra_short--;
+ }
+ }
+
+ /* Discard original name if any */
+ if (header.formatted.flags & 0x08) {
+ /* bit 3 set: original file name present */
+ while (xread_char(src_fd) != 0);
+ }
+
+ /* Discard file comment if any */
+ if (header.formatted.flags & 0x10) {
+ /* bit 4 set: file comment present */
+ while (xread_char(src_fd) != 0);
+ }
+
+ /* Read the header checksum */
+ if (header.formatted.flags & 0x02) {
+ xread_char(src_fd);
+ xread_char(src_fd);
+ }
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/data_align.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_align.c
new file mode 100644
index 0000000..946c94d
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_align.c
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void data_align(archive_handle_t *archive_handle, const unsigned short boundary)
+{
+ const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary;
+
+ archive_handle->seek(archive_handle, skip_amount);
+ archive_handle->offset += skip_amount;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_all.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_all.c
new file mode 100644
index 0000000..0bb5bfe
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_all.c
@@ -0,0 +1,127 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void data_extract_all(archive_handle_t *archive_handle)
+{
+ file_header_t *file_header = archive_handle->file_header;
+ int dst_fd;
+ int res;
+
+ if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
+ char *name = xstrdup(file_header->name);
+ bb_make_directory(dirname(name), -1, FILEUTILS_RECUR);
+ free(name);
+ }
+
+ /* Check if the file already exists */
+ if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) {
+ /* Remove the existing entry if it exists */
+ if (((file_header->mode & S_IFMT) != S_IFDIR)
+ && (unlink(file_header->name) == -1)
+ && (errno != ENOENT)
+ ) {
+ bb_perror_msg_and_die("cannot remove old file");
+ }
+ }
+ else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) {
+ /* Remove the existing entry if its older than the extracted entry */
+ struct stat statbuf;
+ if (lstat(file_header->name, &statbuf) == -1) {
+ if (errno != ENOENT) {
+ bb_perror_msg_and_die("cannot stat old file");
+ }
+ }
+ else if (statbuf.st_mtime <= file_header->mtime) {
+ if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+ bb_error_msg("%s not created: newer or "
+ "same age file exists", file_header->name);
+ }
+ data_skip(archive_handle);
+ return;
+ }
+ else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
+ bb_perror_msg_and_die("cannot remove old file %s",
+ file_header->name);
+ }
+ }
+
+ /* Handle hard links separately
+ * We identified hard links as regular files of size 0 with a symlink */
+ if (S_ISREG(file_header->mode) && (file_header->link_name)
+ && (file_header->size == 0)
+ ) {
+ /* hard link */
+ res = link(file_header->link_name, file_header->name);
+ if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+ bb_perror_msg("cannot create hard link");
+ }
+ } else {
+ /* Create the filesystem entry */
+ switch (file_header->mode & S_IFMT) {
+ case S_IFREG: {
+ /* Regular file */
+ dst_fd = xopen3(file_header->name, O_WRONLY | O_CREAT | O_EXCL,
+ file_header->mode);
+ bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
+ close(dst_fd);
+ break;
+ }
+ case S_IFDIR:
+ res = mkdir(file_header->name, file_header->mode);
+ if ((errno != EISDIR) && (res == -1)
+ && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("extract_archive: %s", file_header->name);
+ }
+ break;
+ case S_IFLNK:
+ /* Symlink */
+ res = symlink(file_header->link_name, file_header->name);
+ if ((res == -1)
+ && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("cannot create symlink "
+ "from %s to '%s'",
+ file_header->name,
+ file_header->link_name);
+ }
+ break;
+ case S_IFSOCK:
+ case S_IFBLK:
+ case S_IFCHR:
+ case S_IFIFO:
+ res = mknod(file_header->name, file_header->mode, file_header->device);
+ if ((res == -1)
+ && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("cannot create node %s", file_header->name);
+ }
+ break;
+ default:
+ bb_error_msg_and_die("unrecognized file type");
+ }
+ }
+
+ if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_OWN)) {
+ lchown(file_header->name, file_header->uid, file_header->gid);
+ }
+ /* uclibc has no lchmod, glibc is even stranger -
+ * it has lchmod which seems to do nothing!
+ * so we use chmod... */
+ if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_PERM)
+ && (file_header->mode & S_IFMT) != S_IFLNK
+ ) {
+ chmod(file_header->name, file_header->mode);
+ }
+
+ if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
+ struct utimbuf t;
+ t.actime = t.modtime = file_header->mtime;
+ utime(file_header->name, &t);
+ }
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_buffer.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_buffer.c
new file mode 100644
index 0000000..d8fcdf3
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_buffer.c
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 2002 Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void data_extract_to_buffer(archive_handle_t *archive_handle)
+{
+ unsigned int size = archive_handle->file_header->size;
+
+ archive_handle->buffer = xzalloc(size + 1);
+ xread(archive_handle->src_fd, archive_handle->buffer, size);
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_stdout.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_stdout.c
new file mode 100644
index 0000000..d87a4a5
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_extract_to_stdout.c
@@ -0,0 +1,13 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "unarchive.h"
+
+void data_extract_to_stdout(archive_handle_t *archive_handle)
+{
+ bb_copyfd_exact_size(archive_handle->src_fd,
+ STDOUT_FILENO,
+ archive_handle->file_header->size);
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/data_skip.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_skip.c
new file mode 100644
index 0000000..dc3505a
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/data_skip.c
@@ -0,0 +1,16 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+void data_skip(archive_handle_t *archive_handle)
+{
+ archive_handle->seek(archive_handle, archive_handle->file_header->size);
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_bunzip2.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_bunzip2.c
new file mode 100644
index 0000000..ff7d64d
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_bunzip2.c
@@ -0,0 +1,731 @@
+/* vi: set sw=4 ts=4: */
+/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
+
+ Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
+ which also acknowledges contributions by Mike Burrows, David Wheeler,
+ Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
+ Robert Sedgewick, and Jon L. Bentley.
+
+ Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+
+/*
+ Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org).
+
+ More efficient reading of Huffman codes, a streamlined read_bunzip()
+ function, and various other tweaks. In (limited) tests, approximately
+ 20% faster than bzcat on x86 and about 10% faster on arm.
+
+ Note that about 2/3 of the time is spent in read_unzip() reversing
+ the Burrows-Wheeler transformation. Much of that time is delay
+ resulting from cache misses.
+
+ I would ask that anyone benefiting from this work, especially those
+ using it in commercial products, consider making a donation to my local
+ non-profit hospice organization (www.hospiceacadiana.com) in the name of
+ the woman I loved, Toni W. Hagan, who passed away Feb. 12, 2003.
+
+ Manuel
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+/* Constants for Huffman coding */
+#define MAX_GROUPS 6
+#define GROUP_SIZE 50 /* 64 would have been more efficient */
+#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */
+#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */
+#define SYMBOL_RUNA 0
+#define SYMBOL_RUNB 1
+
+/* Status return values */
+#define RETVAL_OK 0
+#define RETVAL_LAST_BLOCK (-1)
+#define RETVAL_NOT_BZIP_DATA (-2)
+#define RETVAL_UNEXPECTED_INPUT_EOF (-3)
+#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4)
+#define RETVAL_DATA_ERROR (-5)
+#define RETVAL_OUT_OF_MEMORY (-6)
+#define RETVAL_OBSOLETE_INPUT (-7)
+
+/* Other housekeeping constants */
+#define IOBUF_SIZE 4096
+
+/* This is what we know about each Huffman coding group */
+struct group_data {
+ /* We have an extra slot at the end of limit[] for a sentinal value. */
+ int limit[MAX_HUFCODE_BITS+1],base[MAX_HUFCODE_BITS],permute[MAX_SYMBOLS];
+ int minLen, maxLen;
+};
+
+/* Structure holding all the housekeeping data, including IO buffers and
+ memory that persists between calls to bunzip */
+
+typedef struct {
+ /* State for interrupting output loop */
+
+ int writeCopies,writePos,writeRunCountdown,writeCount,writeCurrent;
+
+ /* I/O tracking data (file handles, buffers, positions, etc.) */
+
+ int in_fd,out_fd,inbufCount,inbufPos /*,outbufPos*/;
+ unsigned char *inbuf /*,*outbuf*/;
+ unsigned int inbufBitCount, inbufBits;
+
+ /* The CRC values stored in the block header and calculated from the data */
+
+ uint32_t headerCRC, totalCRC, writeCRC;
+ uint32_t *crc32Table;
+ /* Intermediate buffer and its size (in bytes) */
+
+ unsigned int *dbuf, dbufSize;
+
+ /* These things are a bit too big to go on the stack */
+
+ unsigned char selectors[32768]; /* nSelectors=15 bits */
+ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
+
+ /* For I/O error handling */
+
+ jmp_buf jmpbuf;
+} bunzip_data;
+
+/* Return the next nnn bits of input. All reads from the compressed input
+ are done through this function. All reads are big endian */
+
+static unsigned int get_bits(bunzip_data *bd, char bits_wanted)
+{
+ unsigned int bits=0;
+
+ /* If we need to get more data from the byte buffer, do so. (Loop getting
+ one byte at a time to enforce endianness and avoid unaligned access.) */
+
+ while (bd->inbufBitCount<bits_wanted) {
+
+ /* If we need to read more data from file into byte buffer, do so */
+
+ if(bd->inbufPos==bd->inbufCount) {
+ if((bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE)) <= 0)
+ longjmp(bd->jmpbuf,RETVAL_UNEXPECTED_INPUT_EOF);
+ bd->inbufPos=0;
+ }
+
+ /* Avoid 32-bit overflow (dump bit buffer to top of output) */
+
+ if(bd->inbufBitCount>=24) {
+ bits=bd->inbufBits&((1<<bd->inbufBitCount)-1);
+ bits_wanted-=bd->inbufBitCount;
+ bits<<=bits_wanted;
+ bd->inbufBitCount=0;
+ }
+
+ /* Grab next 8 bits of input from buffer. */
+
+ bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++];
+ bd->inbufBitCount+=8;
+ }
+
+ /* Calculate result */
+
+ bd->inbufBitCount-=bits_wanted;
+ bits|=(bd->inbufBits>>bd->inbufBitCount)&((1<<bits_wanted)-1);
+
+ return bits;
+}
+
+/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */
+
+static int get_next_block(bunzip_data *bd)
+{
+ struct group_data *hufGroup;
+ int dbufCount,nextSym,dbufSize,groupCount,*base,*limit,selector,
+ i,j,k,t,runPos,symCount,symTotal,nSelectors,byteCount[256];
+ unsigned char uc, symToByte[256], mtfSymbol[256], *selectors;
+ unsigned int *dbuf,origPtr;
+
+ dbuf=bd->dbuf;
+ dbufSize=bd->dbufSize;
+ selectors=bd->selectors;
+
+ /* Reset longjmp I/O error handling */
+
+ i=setjmp(bd->jmpbuf);
+ if (i) return i;
+
+ /* Read in header signature and CRC, then validate signature.
+ (last block signature means CRC is for whole file, return now) */
+
+ i = get_bits(bd,24);
+ j = get_bits(bd,24);
+ bd->headerCRC=get_bits(bd,32);
+ if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK;
+ if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA;
+
+ /* We can add support for blockRandomised if anybody complains. There was
+ some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
+ it didn't actually work. */
+
+ if (get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT;
+ if ((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR;
+
+ /* mapping table: if some byte values are never used (encoding things
+ like ascii text), the compression code removes the gaps to have fewer
+ symbols to deal with, and writes a sparse bitfield indicating which
+ values were present. We make a translation table to convert the symbols
+ back to the corresponding bytes. */
+
+ t=get_bits(bd, 16);
+ symTotal=0;
+ for (i=0;i<16;i++) {
+ if(t&(1<<(15-i))) {
+ k=get_bits(bd,16);
+ for (j=0;j<16;j++)
+ if(k&(1<<(15-j))) symToByte[symTotal++]=(16*i)+j;
+ }
+ }
+
+ /* How many different Huffman coding groups does this block use? */
+
+ groupCount=get_bits(bd,3);
+ if (groupCount<2 || groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR;
+
+ /* nSelectors: Every GROUP_SIZE many symbols we select a new Huffman coding
+ group. Read in the group selector list, which is stored as MTF encoded
+ bit runs. (MTF=Move To Front, as each value is used it's moved to the
+ start of the list.) */
+
+ if(!(nSelectors=get_bits(bd, 15))) return RETVAL_DATA_ERROR;
+ for (i=0; i<groupCount; i++) mtfSymbol[i] = i;
+ for (i=0; i<nSelectors; i++) {
+
+ /* Get next value */
+
+ for (j=0;get_bits(bd,1);j++) if (j>=groupCount) return RETVAL_DATA_ERROR;
+
+ /* Decode MTF to get the next selector */
+
+ uc = mtfSymbol[j];
+ for (;j;j--) mtfSymbol[j] = mtfSymbol[j-1];
+ mtfSymbol[0]=selectors[i]=uc;
+ }
+
+ /* Read the Huffman coding tables for each group, which code for symTotal
+ literal symbols, plus two run symbols (RUNA, RUNB) */
+
+ symCount=symTotal+2;
+ for (j=0; j<groupCount; j++) {
+ unsigned char length[MAX_SYMBOLS],temp[MAX_HUFCODE_BITS+1];
+ int minLen, maxLen, pp;
+
+ /* Read Huffman code lengths for each symbol. They're stored in
+ a way similar to mtf; record a starting value for the first symbol,
+ and an offset from the previous value for everys symbol after that.
+ (Subtracting 1 before the loop and then adding it back at the end is
+ an optimization that makes the test inside the loop simpler: symbol
+ length 0 becomes negative, so an unsigned inequality catches it.) */
+
+ t=get_bits(bd, 5)-1;
+ for (i = 0; i < symCount; i++) {
+ for (;;) {
+ if (((unsigned)t) > (MAX_HUFCODE_BITS-1))
+ return RETVAL_DATA_ERROR;
+
+ /* If first bit is 0, stop. Else second bit indicates whether
+ to increment or decrement the value. Optimization: grab 2
+ bits and unget the second if the first was 0. */
+
+ k = get_bits(bd,2);
+ if (k < 2) {
+ bd->inbufBitCount++;
+ break;
+ }
+
+ /* Add one if second bit 1, else subtract 1. Avoids if/else */
+
+ t+=(((k+1)&2)-1);
+ }
+
+ /* Correct for the initial -1, to get the final symbol length */
+
+ length[i]=t+1;
+ }
+
+ /* Find largest and smallest lengths in this group */
+
+ minLen=maxLen=length[0];
+ for (i = 1; i < symCount; i++) {
+ if(length[i] > maxLen) maxLen = length[i];
+ else if(length[i] < minLen) minLen = length[i];
+ }
+
+ /* Calculate permute[], base[], and limit[] tables from length[].
+ *
+ * permute[] is the lookup table for converting Huffman coded symbols
+ * into decoded symbols. base[] is the amount to subtract from the
+ * value of a Huffman symbol of a given length when using permute[].
+ *
+ * limit[] indicates the largest numerical value a symbol with a given
+ * number of bits can have. This is how the Huffman codes can vary in
+ * length: each code with a value>limit[length] needs another bit.
+ */
+
+ hufGroup=bd->groups+j;
+ hufGroup->minLen = minLen;
+ hufGroup->maxLen = maxLen;
+
+ /* Note that minLen can't be smaller than 1, so we adjust the base
+ and limit array pointers so we're not always wasting the first
+ entry. We do this again when using them (during symbol decoding).*/
+
+ base=hufGroup->base-1;
+ limit=hufGroup->limit-1;
+
+ /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */
+
+ pp=0;
+ for (i=minLen;i<=maxLen;i++) {
+ temp[i]=limit[i]=0;
+ for (t=0;t<symCount;t++)
+ if(length[t]==i) hufGroup->permute[pp++] = t;
+ }
+
+ /* Count symbols coded for at each bit length */
+
+ for (i=0;i<symCount;i++) temp[length[i]]++;
+
+ /* Calculate limit[] (the largest symbol-coding value at each bit
+ * length, which is (previous limit<<1)+symbols at this level), and
+ * base[] (number of symbols to ignore at each bit length, which is
+ * limit minus the cumulative count of symbols coded for already). */
+
+ pp=t=0;
+ for (i=minLen; i<maxLen; i++) {
+ pp+=temp[i];
+
+ /* We read the largest possible symbol size and then unget bits
+ after determining how many we need, and those extra bits could
+ be set to anything. (They're noise from future symbols.) At
+ each level we're really only interested in the first few bits,
+ so here we set all the trailing to-be-ignored bits to 1 so they
+ don't affect the value>limit[length] comparison. */
+
+ limit[i]= (pp << (maxLen - i)) - 1;
+ pp<<=1;
+ base[i+1]=pp-(t+=temp[i]);
+ }
+ limit[maxLen+1] = INT_MAX; /* Sentinal value for reading next sym. */
+ limit[maxLen]=pp+temp[maxLen]-1;
+ base[minLen]=0;
+ }
+
+ /* We've finished reading and digesting the block header. Now read this
+ block's Huffman coded symbols from the file and undo the Huffman coding
+ and run length encoding, saving the result into dbuf[dbufCount++]=uc */
+
+ /* Initialize symbol occurrence counters and symbol Move To Front table */
+
+ for (i=0;i<256;i++) {
+ byteCount[i] = 0;
+ mtfSymbol[i]=(unsigned char)i;
+ }
+
+ /* Loop through compressed symbols. */
+
+ runPos=dbufCount=selector=0;
+ for (;;) {
+
+ /* fetch next Huffman coding group from list. */
+
+ symCount=GROUP_SIZE-1;
+ if(selector>=nSelectors) return RETVAL_DATA_ERROR;
+ hufGroup=bd->groups+selectors[selector++];
+ base=hufGroup->base-1;
+ limit=hufGroup->limit-1;
+continue_this_group:
+
+ /* Read next Huffman-coded symbol. */
+
+ /* Note: It is far cheaper to read maxLen bits and back up than it is
+ to read minLen bits and then an additional bit at a time, testing
+ as we go. Because there is a trailing last block (with file CRC),
+ there is no danger of the overread causing an unexpected EOF for a
+ valid compressed file. As a further optimization, we do the read
+ inline (falling back to a call to get_bits if the buffer runs
+ dry). The following (up to got_huff_bits:) is equivalent to
+ j=get_bits(bd,hufGroup->maxLen);
+ */
+
+ while (bd->inbufBitCount<hufGroup->maxLen) {
+ if(bd->inbufPos==bd->inbufCount) {
+ j = get_bits(bd,hufGroup->maxLen);
+ goto got_huff_bits;
+ }
+ bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++];
+ bd->inbufBitCount+=8;
+ };
+ bd->inbufBitCount-=hufGroup->maxLen;
+ j = (bd->inbufBits>>bd->inbufBitCount)&((1<<hufGroup->maxLen)-1);
+
+got_huff_bits:
+
+ /* Figure how how many bits are in next symbol and unget extras */
+
+ i=hufGroup->minLen;
+ while (j>limit[i]) ++i;
+ bd->inbufBitCount += (hufGroup->maxLen - i);
+
+ /* Huffman decode value to get nextSym (with bounds checking) */
+
+ if ((i > hufGroup->maxLen)
+ || (((unsigned)(j=(j>>(hufGroup->maxLen-i))-base[i]))
+ >= MAX_SYMBOLS))
+ return RETVAL_DATA_ERROR;
+ nextSym = hufGroup->permute[j];
+
+ /* We have now decoded the symbol, which indicates either a new literal
+ byte, or a repeated run of the most recent literal byte. First,
+ check if nextSym indicates a repeated run, and if so loop collecting
+ how many times to repeat the last literal. */
+
+ if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */
+
+ /* If this is the start of a new run, zero out counter */
+
+ if(!runPos) {
+ runPos = 1;
+ t = 0;
+ }
+
+ /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at
+ each bit position, add 1 or 2 instead. For example,
+ 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2.
+ You can make any bit pattern that way using 1 less symbol than
+ the basic or 0/1 method (except all bits 0, which would use no
+ symbols, but a run of length 0 doesn't mean anything in this
+ context). Thus space is saved. */
+
+ t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
+ if(runPos < dbufSize) runPos <<= 1;
+ goto end_of_huffman_loop;
+ }
+
+ /* When we hit the first non-run symbol after a run, we now know
+ how many times to repeat the last literal, so append that many
+ copies to our buffer of decoded symbols (dbuf) now. (The last
+ literal used is the one at the head of the mtfSymbol array.) */
+
+ if(runPos) {
+ runPos=0;
+ if(dbufCount+t>=dbufSize) return RETVAL_DATA_ERROR;
+
+ uc = symToByte[mtfSymbol[0]];
+ byteCount[uc] += t;
+ while (t--) dbuf[dbufCount++]=uc;
+ }
+
+ /* Is this the terminating symbol? */
+
+ if(nextSym>symTotal) break;
+
+ /* At this point, nextSym indicates a new literal character. Subtract
+ one to get the position in the MTF array at which this literal is
+ currently to be found. (Note that the result can't be -1 or 0,
+ because 0 and 1 are RUNA and RUNB. But another instance of the
+ first symbol in the mtf array, position 0, would have been handled
+ as part of a run above. Therefore 1 unused mtf position minus
+ 2 non-literal nextSym values equals -1.) */
+
+ if(dbufCount>=dbufSize) return RETVAL_DATA_ERROR;
+ i = nextSym - 1;
+ uc = mtfSymbol[i];
+
+ /* Adjust the MTF array. Since we typically expect to move only a
+ * small number of symbols, and are bound by 256 in any case, using
+ * memmove here would typically be bigger and slower due to function
+ * call overhead and other assorted setup costs. */
+
+ do {
+ mtfSymbol[i] = mtfSymbol[i-1];
+ } while (--i);
+ mtfSymbol[0] = uc;
+ uc=symToByte[uc];
+
+ /* We have our literal byte. Save it into dbuf. */
+
+ byteCount[uc]++;
+ dbuf[dbufCount++] = (unsigned int)uc;
+
+ /* Skip group initialization if we're not done with this group. Done
+ * this way to avoid compiler warning. */
+
+end_of_huffman_loop:
+ if(symCount--) goto continue_this_group;
+ }
+
+ /* At this point, we've read all the Huffman-coded symbols (and repeated
+ runs) for this block from the input stream, and decoded them into the
+ intermediate buffer. There are dbufCount many decoded bytes in dbuf[].
+ Now undo the Burrows-Wheeler transform on dbuf.
+ See http://dogma.net/markn/articles/bwt/bwt.htm
+ */
+
+ /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
+
+ j=0;
+ for (i=0;i<256;i++) {
+ k=j+byteCount[i];
+ byteCount[i] = j;
+ j=k;
+ }
+
+ /* Figure out what order dbuf would be in if we sorted it. */
+
+ for (i=0;i<dbufCount;i++) {
+ uc=(unsigned char)(dbuf[i] & 0xff);
+ dbuf[byteCount[uc]] |= (i << 8);
+ byteCount[uc]++;
+ }
+
+ /* Decode first byte by hand to initialize "previous" byte. Note that it
+ doesn't get output, and if the first three characters are identical
+ it doesn't qualify as a run (hence writeRunCountdown=5). */
+
+ if(dbufCount) {
+ if(origPtr>=dbufCount) return RETVAL_DATA_ERROR;
+ bd->writePos=dbuf[origPtr];
+ bd->writeCurrent=(unsigned char)(bd->writePos&0xff);
+ bd->writePos>>=8;
+ bd->writeRunCountdown=5;
+ }
+ bd->writeCount=dbufCount;
+
+ return RETVAL_OK;
+}
+
+/* Undo burrows-wheeler transform on intermediate buffer to produce output.
+ If start_bunzip was initialized with out_fd=-1, then up to len bytes of
+ data are written to outbuf. Return value is number of bytes written or
+ error (all errors are negative numbers). If out_fd!=-1, outbuf and len
+ are ignored, data is written to out_fd and return is RETVAL_OK or error.
+*/
+
+static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
+{
+ const unsigned int *dbuf;
+ int pos,current,previous,gotcount;
+
+ /* If last read was short due to end of file, return last block now */
+ if(bd->writeCount<0) return bd->writeCount;
+
+ gotcount = 0;
+ dbuf=bd->dbuf;
+ pos=bd->writePos;
+ current=bd->writeCurrent;
+
+ /* We will always have pending decoded data to write into the output
+ buffer unless this is the very first call (in which case we haven't
+ Huffman-decoded a block into the intermediate buffer yet). */
+
+ if (bd->writeCopies) {
+
+ /* Inside the loop, writeCopies means extra copies (beyond 1) */
+
+ --bd->writeCopies;
+
+ /* Loop outputting bytes */
+
+ for (;;) {
+
+ /* If the output buffer is full, snapshot state and return */
+
+ if(gotcount >= len) {
+ bd->writePos=pos;
+ bd->writeCurrent=current;
+ bd->writeCopies++;
+ return len;
+ }
+
+ /* Write next byte into output buffer, updating CRC */
+
+ outbuf[gotcount++] = current;
+ bd->writeCRC=(((bd->writeCRC)<<8)
+ ^bd->crc32Table[((bd->writeCRC)>>24)^current]);
+
+ /* Loop now if we're outputting multiple copies of this byte */
+
+ if (bd->writeCopies) {
+ --bd->writeCopies;
+ continue;
+ }
+decode_next_byte:
+ if (!bd->writeCount--) break;
+ /* Follow sequence vector to undo Burrows-Wheeler transform */
+ previous=current;
+ pos=dbuf[pos];
+ current=pos&0xff;
+ pos>>=8;
+
+ /* After 3 consecutive copies of the same byte, the 4th is a repeat
+ count. We count down from 4 instead
+ * of counting up because testing for non-zero is faster */
+
+ if(--bd->writeRunCountdown) {
+ if(current!=previous) bd->writeRunCountdown=4;
+ } else {
+
+ /* We have a repeated run, this byte indicates the count */
+
+ bd->writeCopies=current;
+ current=previous;
+ bd->writeRunCountdown=5;
+
+ /* Sometimes there are just 3 bytes (run length 0) */
+
+ if(!bd->writeCopies) goto decode_next_byte;
+
+ /* Subtract the 1 copy we'd output anyway to get extras */
+
+ --bd->writeCopies;
+ }
+ }
+
+ /* Decompression of this block completed successfully */
+
+ bd->writeCRC=~bd->writeCRC;
+ bd->totalCRC=((bd->totalCRC<<1) | (bd->totalCRC>>31)) ^ bd->writeCRC;
+
+ /* If this block had a CRC error, force file level CRC error. */
+
+ if(bd->writeCRC!=bd->headerCRC) {
+ bd->totalCRC=bd->headerCRC+1;
+ return RETVAL_LAST_BLOCK;
+ }
+ }
+
+ /* Refill the intermediate buffer by Huffman-decoding next block of input */
+ /* (previous is just a convenient unused temp variable here) */
+
+ previous=get_next_block(bd);
+ if(previous) {
+ bd->writeCount=previous;
+ return (previous!=RETVAL_LAST_BLOCK) ? previous : gotcount;
+ }
+ bd->writeCRC=~0;
+ pos=bd->writePos;
+ current=bd->writeCurrent;
+ goto decode_next_byte;
+}
+
+/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain
+ a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
+ ignored, and data is read from file handle into temporary buffer. */
+
+static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
+ int len)
+{
+ bunzip_data *bd;
+ unsigned int i;
+ const unsigned int BZh0=(((unsigned int)'B')<<24)+(((unsigned int)'Z')<<16)
+ +(((unsigned int)'h')<<8)+(unsigned int)'0';
+
+ /* Figure out how much data to allocate */
+
+ i=sizeof(bunzip_data);
+ if(in_fd!=-1) i+=IOBUF_SIZE;
+
+ /* Allocate bunzip_data. Most fields initialize to zero. */
+
+ bd=*bdp=xzalloc(i);
+
+ /* Setup input buffer */
+
+ if(-1==(bd->in_fd=in_fd)) {
+ bd->inbuf=inbuf;
+ bd->inbufCount=len;
+ } else bd->inbuf=(unsigned char *)(bd+1);
+
+ /* Init the CRC32 table (big endian) */
+
+ bd->crc32Table = crc32_filltable(1);
+
+ /* Setup for I/O error handling via longjmp */
+
+ i=setjmp(bd->jmpbuf);
+ if(i) return i;
+
+ /* Ensure that file starts with "BZh['1'-'9']." */
+
+ i = get_bits(bd,32);
+ if (((unsigned int)(i-BZh0-1)) >= 9) return RETVAL_NOT_BZIP_DATA;
+
+ /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
+ uncompressed data. Allocate intermediate buffer for block. */
+
+ bd->dbufSize=100000*(i-BZh0);
+
+ bd->dbuf=xmalloc(bd->dbufSize * sizeof(int));
+ return RETVAL_OK;
+}
+
+/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data,
+ not end of file.) */
+
+USE_DESKTOP(long long) int
+uncompressStream(int src_fd, int dst_fd)
+{
+ USE_DESKTOP(long long total_written = 0;)
+ char *outbuf;
+ bunzip_data *bd;
+ int i;
+
+ outbuf=xmalloc(IOBUF_SIZE);
+ i=start_bunzip(&bd,src_fd,0,0);
+ if(!i) {
+ for (;;) {
+ if((i=read_bunzip(bd,outbuf,IOBUF_SIZE)) <= 0) break;
+ if(i!=write(dst_fd,outbuf,i)) {
+ i=RETVAL_UNEXPECTED_OUTPUT_EOF;
+ break;
+ }
+ USE_DESKTOP(total_written += i;)
+ }
+ }
+
+ /* Check CRC and release memory */
+
+ if(i==RETVAL_LAST_BLOCK) {
+ if (bd->headerCRC!=bd->totalCRC) {
+ bb_error_msg("data integrity error when decompressing");
+ } else {
+ i=RETVAL_OK;
+ }
+ } else if (i==RETVAL_UNEXPECTED_OUTPUT_EOF) {
+ bb_error_msg("compressed file ends unexpectedly");
+ } else {
+ bb_error_msg("decompression failed");
+ }
+ free(bd->dbuf);
+ free(bd);
+ free(outbuf);
+
+ return i ? i : USE_DESKTOP(total_written) + 0;
+}
+
+#ifdef TESTING
+
+static char * const bunzip_errors[]={NULL,"Bad file checksum","Not bzip data",
+ "Unexpected input EOF","Unexpected output EOF","Data error",
+ "Out of memory","Obsolete (pre 0.9.5) bzip format not supported."};
+
+/* Dumb little test thing, decompress stdin to stdout */
+int main(int argc, char *argv[])
+{
+ int i=uncompressStream(0,1);
+ char c;
+
+ if(i<0) fprintf(stderr,"%s\n", bunzip_errors[-i]);
+ else if(read(0,&c,1)) fprintf(stderr,"Trailing garbage ignored\n");
+ return -i;
+}
+#endif
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_uncompress.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_uncompress.c
new file mode 100644
index 0000000..8ce3cba
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_uncompress.c
@@ -0,0 +1,308 @@
+/* vi: set sw=4 ts=4: */
+#include "libbb.h"
+
+/* uncompress for busybox -- (c) 2002 Robert Griebl
+ *
+ * based on the original compress42.c source
+ * (see disclaimer below)
+ */
+
+
+/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
+ *
+ * Authors:
+ * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ * Dave Mack (csu@alembic.acs.com)
+ * Peter Jannesen, Network Communication Systems
+ * (peter@ncs.nl)
+ *
+ * marc@suse.de : a small security fix for a buffer overflow
+ *
+ * [... History snipped ...]
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Default input buffer size */
+#define IBUFSIZ 2048
+
+/* Default output buffer size */
+#define OBUFSIZ 2048
+
+/* Defines for third byte of header */
+#define MAGIC_1 (char_type)'\037' /* First byte of compressed file */
+#define MAGIC_2 (char_type)'\235' /* Second byte of compressed file */
+#define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */
+ /* Masks 0x20 and 0x40 are free. */
+ /* I think 0x20 should mean that there is */
+ /* a fourth header byte (for expansion). */
+#define BLOCK_MODE 0x80 /* Block compresssion if table is full and */
+ /* compression rate is dropping flush tables */
+ /* the next two codes should not be changed lightly, as they must not */
+ /* lie within the contiguous general code space. */
+#define FIRST 257 /* first free entry */
+#define CLEAR 256 /* table clear output code */
+
+#define INIT_BITS 9 /* initial number of bits/code */
+
+
+/* machine variants which require cc -Dmachine: pdp11, z8000, DOS */
+#define FAST
+
+#define HBITS 17 /* 50% occupancy */
+#define HSIZE (1<<HBITS)
+#define HMASK (HSIZE-1)
+#define HPRIME 9941
+#define BITS 16
+#undef MAXSEG_64K
+#define MAXCODE(n) (1L << (n))
+
+#define htabof(i) htab[i]
+#define codetabof(i) codetab[i]
+#define tab_prefixof(i) codetabof(i)
+#define tab_suffixof(i) ((unsigned char *)(htab))[i]
+#define de_stack ((unsigned char *)&(htab[HSIZE-1]))
+#define clear_htab() memset(htab, -1, HSIZE)
+#define clear_tab_prefixof() memset(codetab, 0, 256);
+
+
+/*
+ * Decompress stdin to stdout. This routine adapts to the codes in the
+ * file building the "string" table on-the-fly; requiring no table to
+ * be stored in the compressed file. The tables used herein are shared
+ * with those of the compress() routine. See the definitions above.
+ */
+
+USE_DESKTOP(long long) int
+uncompress(int fd_in, int fd_out)
+{
+ USE_DESKTOP(long long total_written = 0;)
+ unsigned char *stackp;
+ long int code;
+ int finchar;
+ long int oldcode;
+ long int incode;
+ int inbits;
+ int posbits;
+ int outpos;
+ int insize;
+ int bitmask;
+ long int free_ent;
+ long int maxcode;
+ long int maxmaxcode;
+ int n_bits;
+ int rsize = 0;
+ RESERVE_CONFIG_UBUFFER(inbuf, IBUFSIZ + 64);
+ RESERVE_CONFIG_UBUFFER(outbuf, OBUFSIZ + 2048);
+ unsigned char htab[HSIZE];
+ unsigned short codetab[HSIZE];
+
+ /* Hmm, these were statics - why?! */
+ /* user settable max # bits/code */
+ int maxbits; /* = BITS; */
+ /* block compress mode -C compatible with 2.0 */
+ int block_mode; /* = BLOCK_MODE; */
+
+ memset(inbuf, 0, IBUFSIZ + 64);
+ memset(outbuf, 0, OBUFSIZ + 2048);
+
+ insize = 0;
+
+ /* xread isn't good here, we have to return - caller may want
+ * to do some cleanup (e.g. delete incomplete unpacked file etc) */
+ if (full_read(fd_in, inbuf, 1) != 1) {
+ bb_error_msg("short read");
+ return -1;
+ }
+
+ maxbits = inbuf[0] & BIT_MASK;
+ block_mode = inbuf[0] & BLOCK_MODE;
+ maxmaxcode = MAXCODE(maxbits);
+
+ if (maxbits > BITS) {
+ bb_error_msg("compressed with %d bits, can only handle "
+ "%d bits", maxbits, BITS);
+ return -1;
+ }
+
+ n_bits = INIT_BITS;
+ maxcode = MAXCODE(INIT_BITS) - 1;
+ bitmask = (1 << INIT_BITS) - 1;
+ oldcode = -1;
+ finchar = 0;
+ outpos = 0;
+ posbits = 0 << 3;
+
+ free_ent = ((block_mode) ? FIRST : 256);
+
+ /* As above, initialize the first 256 entries in the table. */
+ clear_tab_prefixof();
+
+ for (code = 255; code >= 0; --code) {
+ tab_suffixof(code) = (unsigned char) code;
+ }
+
+ do {
+ resetbuf:
+ {
+ int i;
+ int e;
+ int o;
+
+ o = posbits >> 3;
+ e = insize - o;
+
+ for (i = 0; i < e; ++i)
+ inbuf[i] = inbuf[i + o];
+
+ insize = e;
+ posbits = 0;
+ }
+
+ if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
+ rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ);
+//error check??
+ insize += rsize;
+ }
+
+ inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 :
+ (insize << 3) - (n_bits - 1));
+
+ while (inbits > posbits) {
+ if (free_ent > maxcode) {
+ posbits =
+ ((posbits - 1) +
+ ((n_bits << 3) -
+ (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
+ ++n_bits;
+ if (n_bits == maxbits) {
+ maxcode = maxmaxcode;
+ } else {
+ maxcode = MAXCODE(n_bits) - 1;
+ }
+ bitmask = (1 << n_bits) - 1;
+ goto resetbuf;
+ }
+ {
+ unsigned char *p = &inbuf[posbits >> 3];
+
+ code = ((((long) (p[0])) | ((long) (p[1]) << 8) |
+ ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask;
+ }
+ posbits += n_bits;
+
+
+ if (oldcode == -1) {
+ oldcode = code;
+ finchar = (int) oldcode;
+ outbuf[outpos++] = (unsigned char) finchar;
+ continue;
+ }
+
+ if (code == CLEAR && block_mode) {
+ clear_tab_prefixof();
+ free_ent = FIRST - 1;
+ posbits =
+ ((posbits - 1) +
+ ((n_bits << 3) -
+ (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
+ n_bits = INIT_BITS;
+ maxcode = MAXCODE(INIT_BITS) - 1;
+ bitmask = (1 << INIT_BITS) - 1;
+ goto resetbuf;
+ }
+
+ incode = code;
+ stackp = de_stack;
+
+ /* Special case for KwKwK string. */
+ if (code >= free_ent) {
+ if (code > free_ent) {
+ unsigned char *p;
+
+ posbits -= n_bits;
+ p = &inbuf[posbits >> 3];
+
+ bb_error_msg
+ ("insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)",
+ insize, posbits, p[-1], p[0], p[1], p[2], p[3],
+ (posbits & 07));
+ bb_error_msg("uncompress: corrupt input");
+ return -1;
+ }
+
+ *--stackp = (unsigned char) finchar;
+ code = oldcode;
+ }
+
+ /* Generate output characters in reverse order */
+ while ((long int) code >= (long int) 256) {
+ *--stackp = tab_suffixof(code);
+ code = tab_prefixof(code);
+ }
+
+ finchar = tab_suffixof(code);
+ *--stackp = (unsigned char) finchar;
+
+ /* And put them out in forward order */
+ {
+ int i;
+
+ i = de_stack - stackp;
+ if (outpos + i >= OBUFSIZ) {
+ do {
+ if (i > OBUFSIZ - outpos) {
+ i = OBUFSIZ - outpos;
+ }
+
+ if (i > 0) {
+ memcpy(outbuf + outpos, stackp, i);
+ outpos += i;
+ }
+
+ if (outpos >= OBUFSIZ) {
+ full_write(fd_out, outbuf, outpos);
+//error check??
+ USE_DESKTOP(total_written += outpos;)
+ outpos = 0;
+ }
+ stackp += i;
+ i = de_stack - stackp;
+ } while (i > 0);
+ } else {
+ memcpy(outbuf + outpos, stackp, i);
+ outpos += i;
+ }
+ }
+
+ /* Generate the new entry. */
+ code = free_ent;
+ if (code < maxmaxcode) {
+ tab_prefixof(code) = (unsigned short) oldcode;
+ tab_suffixof(code) = (unsigned char) finchar;
+ free_ent = code + 1;
+ }
+
+ /* Remember previous code. */
+ oldcode = incode;
+ }
+
+ } while (rsize > 0);
+
+ if (outpos > 0) {
+ full_write(fd_out, outbuf, outpos);
+//error check??
+ USE_DESKTOP(total_written += outpos;)
+ }
+
+ RELEASE_CONFIG_BUFFER(inbuf);
+ RELEASE_CONFIG_BUFFER(outbuf);
+ return USE_DESKTOP(total_written) + 0;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unlzma.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unlzma.c
new file mode 100644
index 0000000..15a0275
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unlzma.c
@@ -0,0 +1,497 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Small lzma deflate implementation.
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
+ *
+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
+ * Copyright (C) 1999-2005 Igor Pavlov
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+#ifdef CONFIG_FEATURE_LZMA_FAST
+# define speed_inline ATTRIBUTE_ALWAYS_INLINE
+#else
+# define speed_inline
+#endif
+
+
+typedef struct {
+ int fd;
+ uint8_t *ptr;
+
+/* Was keeping rc on stack in unlzma and separately allocating buffer,
+ * but with "buffer 'attached to' allocated rc" code is smaller: */
+ /* uint8_t *buffer; */
+#define RC_BUFFER ((uint8_t*)(rc+1))
+
+ uint8_t *buffer_end;
+
+/* Had provisions for variable buffer, but we don't need it here */
+ /* int buffer_size; */
+#define RC_BUFFER_SIZE 0x10000
+
+ uint32_t code;
+ uint32_t range;
+ uint32_t bound;
+} rc_t;
+
+#define RC_TOP_BITS 24
+#define RC_MOVE_BITS 5
+#define RC_MODEL_TOTAL_BITS 11
+
+
+/* Called twice: once at startup and once in rc_normalize() */
+static void rc_read(rc_t * rc)
+{
+ int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE);
+ if (buffer_size <= 0)
+ bb_error_msg_and_die("unexpected EOF");
+ rc->ptr = RC_BUFFER;
+ rc->buffer_end = RC_BUFFER + buffer_size;
+}
+
+/* Called once */
+static rc_t* rc_init(int fd) /*, int buffer_size) */
+{
+ int i;
+ rc_t* rc;
+
+ rc = xmalloc(sizeof(rc_t) + RC_BUFFER_SIZE);
+
+ rc->fd = fd;
+ /* rc->buffer_size = buffer_size; */
+ rc->buffer_end = RC_BUFFER + RC_BUFFER_SIZE;
+ rc->ptr = rc->buffer_end;
+
+ rc->code = 0;
+ rc->range = 0xFFFFFFFF;
+ for (i = 0; i < 5; i++) {
+ if (rc->ptr >= rc->buffer_end)
+ rc_read(rc);
+ rc->code = (rc->code << 8) | *rc->ptr++;
+ }
+ return rc;
+}
+
+/* Called once */
+static ATTRIBUTE_ALWAYS_INLINE void rc_free(rc_t * rc)
+{
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(rc);
+}
+
+/* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */
+static void rc_do_normalize(rc_t * rc)
+{
+ if (rc->ptr >= rc->buffer_end)
+ rc_read(rc);
+ rc->range <<= 8;
+ rc->code = (rc->code << 8) | *rc->ptr++;
+}
+static ATTRIBUTE_ALWAYS_INLINE void rc_normalize(rc_t * rc)
+{
+ if (rc->range < (1 << RC_TOP_BITS)) {
+ rc_do_normalize(rc);
+ }
+}
+
+/* Called 9 times */
+/* Why rc_is_bit_0_helper exists?
+ * Because we want to always expose (rc->code < rc->bound) to optimizer
+ */
+static speed_inline uint32_t rc_is_bit_0_helper(rc_t * rc, uint16_t * p)
+{
+ rc_normalize(rc);
+ rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
+ return rc->bound;
+}
+static ATTRIBUTE_ALWAYS_INLINE int rc_is_bit_0(rc_t * rc, uint16_t * p)
+{
+ uint32_t t = rc_is_bit_0_helper(rc, p);
+ return rc->code < t;
+}
+
+/* Called ~10 times, but very small, thus inlined */
+static speed_inline void rc_update_bit_0(rc_t * rc, uint16_t * p)
+{
+ rc->range = rc->bound;
+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
+}
+static speed_inline void rc_update_bit_1(rc_t * rc, uint16_t * p)
+{
+ rc->range -= rc->bound;
+ rc->code -= rc->bound;
+ *p -= *p >> RC_MOVE_BITS;
+}
+
+/* Called 4 times in unlzma loop */
+static int rc_get_bit(rc_t * rc, uint16_t * p, int *symbol)
+{
+ if (rc_is_bit_0(rc, p)) {
+ rc_update_bit_0(rc, p);
+ *symbol *= 2;
+ return 0;
+ } else {
+ rc_update_bit_1(rc, p);
+ *symbol = *symbol * 2 + 1;
+ return 1;
+ }
+}
+
+/* Called once */
+static ATTRIBUTE_ALWAYS_INLINE int rc_direct_bit(rc_t * rc)
+{
+ rc_normalize(rc);
+ rc->range >>= 1;
+ if (rc->code >= rc->range) {
+ rc->code -= rc->range;
+ return 1;
+ }
+ return 0;
+}
+
+/* Called twice */
+static speed_inline void
+rc_bit_tree_decode(rc_t * rc, uint16_t * p, int num_levels, int *symbol)
+{
+ int i = num_levels;
+
+ *symbol = 1;
+ while (i--)
+ rc_get_bit(rc, p + *symbol, symbol);
+ *symbol -= 1 << num_levels;
+}
+
+
+typedef struct {
+ uint8_t pos;
+ uint32_t dict_size;
+ uint64_t dst_size;
+} __attribute__ ((packed)) lzma_header_t;
+
+
+/* #defines will force compiler to compute/optimize each one with each usage.
+ * Have heart and use enum instead. */
+enum {
+ LZMA_BASE_SIZE = 1846,
+ LZMA_LIT_SIZE = 768,
+
+ LZMA_NUM_POS_BITS_MAX = 4,
+
+ LZMA_LEN_NUM_LOW_BITS = 3,
+ LZMA_LEN_NUM_MID_BITS = 3,
+ LZMA_LEN_NUM_HIGH_BITS = 8,
+
+ LZMA_LEN_CHOICE = 0,
+ LZMA_LEN_CHOICE_2 = (LZMA_LEN_CHOICE + 1),
+ LZMA_LEN_LOW = (LZMA_LEN_CHOICE_2 + 1),
+ LZMA_LEN_MID = (LZMA_LEN_LOW \
+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))),
+ LZMA_LEN_HIGH = (LZMA_LEN_MID \
+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))),
+ LZMA_NUM_LEN_PROBS = (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)),
+
+ LZMA_NUM_STATES = 12,
+ LZMA_NUM_LIT_STATES = 7,
+
+ LZMA_START_POS_MODEL_INDEX = 4,
+ LZMA_END_POS_MODEL_INDEX = 14,
+ LZMA_NUM_FULL_DISTANCES = (1 << (LZMA_END_POS_MODEL_INDEX >> 1)),
+
+ LZMA_NUM_POS_SLOT_BITS = 6,
+ LZMA_NUM_LEN_TO_POS_STATES = 4,
+
+ LZMA_NUM_ALIGN_BITS = 4,
+
+ LZMA_MATCH_MIN_LEN = 2,
+
+ LZMA_IS_MATCH = 0,
+ LZMA_IS_REP = (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
+ LZMA_IS_REP_G0 = (LZMA_IS_REP + LZMA_NUM_STATES),
+ LZMA_IS_REP_G1 = (LZMA_IS_REP_G0 + LZMA_NUM_STATES),
+ LZMA_IS_REP_G2 = (LZMA_IS_REP_G1 + LZMA_NUM_STATES),
+ LZMA_IS_REP_0_LONG = (LZMA_IS_REP_G2 + LZMA_NUM_STATES),
+ LZMA_POS_SLOT = (LZMA_IS_REP_0_LONG \
+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
+ LZMA_SPEC_POS = (LZMA_POS_SLOT \
+ + (LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)),
+ LZMA_ALIGN = (LZMA_SPEC_POS \
+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX),
+ LZMA_LEN_CODER = (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)),
+ LZMA_REP_LEN_CODER = (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS),
+ LZMA_LITERAL = (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS),
+};
+
+
+USE_DESKTOP(long long) int
+unlzma(int src_fd, int dst_fd)
+{
+ USE_DESKTOP(long long total_written = 0;)
+ lzma_header_t header;
+ int lc, pb, lp;
+ uint32_t pos_state_mask;
+ uint32_t literal_pos_mask;
+ uint32_t pos;
+ uint16_t *p;
+ uint16_t *prob;
+ uint16_t *prob_lit;
+ int num_bits;
+ int num_probs;
+ rc_t *rc;
+ int i, mi;
+ uint8_t *buffer;
+ uint8_t previous_byte = 0;
+ size_t buffer_pos = 0, global_pos = 0;
+ int len = 0;
+ int state = 0;
+ uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+
+ xread(src_fd, &header, sizeof(header));
+
+ if (header.pos >= (9 * 5 * 5))
+ bb_error_msg_and_die("bad header");
+ mi = header.pos / 9;
+ lc = header.pos % 9;
+ pb = mi / 5;
+ lp = mi % 5;
+ pos_state_mask = (1 << pb) - 1;
+ literal_pos_mask = (1 << lp) - 1;
+
+ header.dict_size = SWAP_LE32(header.dict_size);
+ header.dst_size = SWAP_LE64(header.dst_size);
+
+ if (header.dict_size == 0)
+ header.dict_size = 1;
+
+ buffer = xmalloc(MIN(header.dst_size, header.dict_size));
+
+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
+ p = xmalloc(num_probs * sizeof(*p));
+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp));
+ for (i = 0; i < num_probs; i++)
+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
+
+ rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */
+
+ while (global_pos + buffer_pos < header.dst_size) {
+ int pos_state = (buffer_pos + global_pos) & pos_state_mask;
+
+ prob =
+ p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
+ if (rc_is_bit_0(rc, prob)) {
+ mi = 1;
+ rc_update_bit_0(rc, prob);
+ prob = (p + LZMA_LITERAL + (LZMA_LIT_SIZE
+ * ((((buffer_pos + global_pos) & literal_pos_mask) << lc)
+ + (previous_byte >> (8 - lc)))));
+
+ if (state >= LZMA_NUM_LIT_STATES) {
+ int match_byte;
+
+ pos = buffer_pos - rep0;
+ while (pos >= header.dict_size)
+ pos += header.dict_size;
+ match_byte = buffer[pos];
+ do {
+ int bit;
+
+ match_byte <<= 1;
+ bit = match_byte & 0x100;
+ prob_lit = prob + 0x100 + bit + mi;
+ if (rc_get_bit(rc, prob_lit, &mi)) {
+ if (!bit)
+ break;
+ } else {
+ if (bit)
+ break;
+ }
+ } while (mi < 0x100);
+ }
+ while (mi < 0x100) {
+ prob_lit = prob + mi;
+ rc_get_bit(rc, prob_lit, &mi);
+ }
+ previous_byte = (uint8_t) mi;
+
+ buffer[buffer_pos++] = previous_byte;
+ if (buffer_pos == header.dict_size) {
+ buffer_pos = 0;
+ global_pos += header.dict_size;
+ if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size)
+ goto bad;
+ USE_DESKTOP(total_written += header.dict_size;)
+ }
+ if (state < 4)
+ state = 0;
+ else if (state < 10)
+ state -= 3;
+ else
+ state -= 6;
+ } else {
+ int offset;
+ uint16_t *prob_len;
+
+ rc_update_bit_1(rc, prob);
+ prob = p + LZMA_IS_REP + state;
+ if (rc_is_bit_0(rc, prob)) {
+ rc_update_bit_0(rc, prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < LZMA_NUM_LIT_STATES ? 0 : 3;
+ prob = p + LZMA_LEN_CODER;
+ } else {
+ rc_update_bit_1(rc, prob);
+ prob = p + LZMA_IS_REP_G0 + state;
+ if (rc_is_bit_0(rc, prob)) {
+ rc_update_bit_0(rc, prob);
+ prob = (p + LZMA_IS_REP_0_LONG
+ + (state << LZMA_NUM_POS_BITS_MAX) + pos_state);
+ if (rc_is_bit_0(rc, prob)) {
+ rc_update_bit_0(rc, prob);
+
+ state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
+ pos = buffer_pos - rep0;
+ while (pos >= header.dict_size)
+ pos += header.dict_size;
+ previous_byte = buffer[pos];
+ buffer[buffer_pos++] = previous_byte;
+ if (buffer_pos == header.dict_size) {
+ buffer_pos = 0;
+ global_pos += header.dict_size;
+ if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size)
+ goto bad;
+ USE_DESKTOP(total_written += header.dict_size;)
+ }
+ continue;
+ } else {
+ rc_update_bit_1(rc, prob);
+ }
+ } else {
+ uint32_t distance;
+
+ rc_update_bit_1(rc, prob);
+ prob = p + LZMA_IS_REP_G1 + state;
+ if (rc_is_bit_0(rc, prob)) {
+ rc_update_bit_0(rc, prob);
+ distance = rep1;
+ } else {
+ rc_update_bit_1(rc, prob);
+ prob = p + LZMA_IS_REP_G2 + state;
+ if (rc_is_bit_0(rc, prob)) {
+ rc_update_bit_0(rc, prob);
+ distance = rep2;
+ } else {
+ rc_update_bit_1(rc, prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < LZMA_NUM_LIT_STATES ? 8 : 11;
+ prob = p + LZMA_REP_LEN_CODER;
+ }
+
+ prob_len = prob + LZMA_LEN_CHOICE;
+ if (rc_is_bit_0(rc, prob_len)) {
+ rc_update_bit_0(rc, prob_len);
+ prob_len = (prob + LZMA_LEN_LOW
+ + (pos_state << LZMA_LEN_NUM_LOW_BITS));
+ offset = 0;
+ num_bits = LZMA_LEN_NUM_LOW_BITS;
+ } else {
+ rc_update_bit_1(rc, prob_len);
+ prob_len = prob + LZMA_LEN_CHOICE_2;
+ if (rc_is_bit_0(rc, prob_len)) {
+ rc_update_bit_0(rc, prob_len);
+ prob_len = (prob + LZMA_LEN_MID
+ + (pos_state << LZMA_LEN_NUM_MID_BITS));
+ offset = 1 << LZMA_LEN_NUM_LOW_BITS;
+ num_bits = LZMA_LEN_NUM_MID_BITS;
+ } else {
+ rc_update_bit_1(rc, prob_len);
+ prob_len = prob + LZMA_LEN_HIGH;
+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
+ + (1 << LZMA_LEN_NUM_MID_BITS));
+ num_bits = LZMA_LEN_NUM_HIGH_BITS;
+ }
+ }
+ rc_bit_tree_decode(rc, prob_len, num_bits, &len);
+ len += offset;
+
+ if (state < 4) {
+ int pos_slot;
+
+ state += LZMA_NUM_LIT_STATES;
+ prob =
+ p + LZMA_POS_SLOT +
+ ((len <
+ LZMA_NUM_LEN_TO_POS_STATES ? len :
+ LZMA_NUM_LEN_TO_POS_STATES - 1)
+ << LZMA_NUM_POS_SLOT_BITS);
+ rc_bit_tree_decode(rc, prob, LZMA_NUM_POS_SLOT_BITS,
+ &pos_slot);
+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
+ num_bits = (pos_slot >> 1) - 1;
+ rep0 = 2 | (pos_slot & 1);
+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
+ rep0 <<= num_bits;
+ prob = p + LZMA_SPEC_POS + rep0 - pos_slot - 1;
+ } else {
+ num_bits -= LZMA_NUM_ALIGN_BITS;
+ while (num_bits--)
+ rep0 = (rep0 << 1) | rc_direct_bit(rc);
+ prob = p + LZMA_ALIGN;
+ rep0 <<= LZMA_NUM_ALIGN_BITS;
+ num_bits = LZMA_NUM_ALIGN_BITS;
+ }
+ i = 1;
+ mi = 1;
+ while (num_bits--) {
+ if (rc_get_bit(rc, prob + mi, &mi))
+ rep0 |= i;
+ i <<= 1;
+ }
+ } else
+ rep0 = pos_slot;
+ if (++rep0 == 0)
+ break;
+ }
+
+ len += LZMA_MATCH_MIN_LEN;
+
+ do {
+ pos = buffer_pos - rep0;
+ while (pos >= header.dict_size)
+ pos += header.dict_size;
+ previous_byte = buffer[pos];
+ buffer[buffer_pos++] = previous_byte;
+ if (buffer_pos == header.dict_size) {
+ buffer_pos = 0;
+ global_pos += header.dict_size;
+ if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size)
+ goto bad;
+ USE_DESKTOP(total_written += header.dict_size;)
+ }
+ len--;
+ } while (len != 0 && buffer_pos < header.dst_size);
+ }
+ }
+
+
+ if (full_write(dst_fd, buffer, buffer_pos) != buffer_pos) {
+ bad:
+ rc_free(rc);
+ return -1;
+ }
+ rc_free(rc);
+ USE_DESKTOP(total_written += buffer_pos;)
+ return USE_DESKTOP(total_written) + 0;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unzip.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unzip.c
new file mode 100644
index 0000000..331fe34
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/decompress_unzip.c
@@ -0,0 +1,1104 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * gunzip implementation for busybox
+ *
+ * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
+ *
+ * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
+ * based on gzip sources
+ *
+ * Adjusted further by Erik Andersen <andersen@codepoet.org> to support
+ * files as well as stdin/stdout, and to generally behave itself wrt
+ * command line handling.
+ *
+ * General cleanup to better adhere to the style guide and make use of standard
+ * busybox functions by Glenn McGrath <bug1@iinet.net.au>
+ *
+ * read_gz interface + associated hacking by Laurence Anderson
+ *
+ * Fixed huft_build() so decoding end-of-block code does not grab more bits
+ * than necessary (this is required by unzip applet), added inflate_cleanup()
+ * to free leaked bytebuffer memory (used in unzip.c), and some minor style
+ * guide cleanups by Ed Clark
+ *
+ * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * The unzip code was written and put in the public domain by Mark Adler.
+ * Portions of the lzw code are derived from the public domain 'compress'
+ * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
+ * Ken Turkowski, Dave Mack and Peter Jannesen.
+ *
+ * See the file algorithm.doc for the compression algorithms and file formats.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+typedef struct huft_s {
+ unsigned char e; /* number of extra bits or operation */
+ unsigned char b; /* number of bits in this code or subcode */
+ union {
+ unsigned short n; /* literal, length base, or distance base */
+ struct huft_s *t; /* pointer to next level of table */
+ } v;
+} huft_t;
+
+enum {
+ /* gunzip_window size--must be a power of two, and
+ * at least 32K for zip's deflate method */
+ GUNZIP_WSIZE = 0x8000,
+ /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+ BMAX = 16, /* maximum bit length of any code (16 for explode) */
+ N_MAX = 288, /* maximum number of codes in any set */
+};
+
+
+/* This is somewhat complex-looking arrangement, but it allows
+ * to place decompressor state either in bss or in
+ * malloc'ed space simply by changing #defines below.
+ * Sizes on i386:
+ * text data bss dec hex
+ * 5256 0 108 5364 14f4 - bss
+ * 4915 0 0 4915 1333 - malloc
+ */
+#define STATE_IN_BSS 0
+#define STATE_IN_MALLOC 1
+
+
+typedef struct state_t {
+ off_t gunzip_bytes_out; /* number of output bytes */
+ uint32_t gunzip_crc;
+
+ int gunzip_src_fd;
+ unsigned gunzip_outbuf_count; /* bytes in output buffer */
+
+ unsigned char *gunzip_window;
+
+ uint32_t *gunzip_crc_table;
+
+ /* bitbuffer */
+ unsigned gunzip_bb; /* bit buffer */
+ unsigned char gunzip_bk; /* bits in bit buffer */
+
+ /* These control the size of the STATE()bytebuffer */
+ unsigned bytebuffer_max;
+ unsigned char *bytebuffer;
+ unsigned bytebuffer_offset;
+ unsigned bytebuffer_size;
+
+ /* private data of inflate_codes() */
+ unsigned inflate_codes_ml; /* masks for bl and bd bits */
+ unsigned inflate_codes_md; /* masks for bl and bd bits */
+ unsigned inflate_codes_bb; /* bit buffer */
+ unsigned inflate_codes_k; /* number of bits in bit buffer */
+ unsigned inflate_codes_w; /* current gunzip_window position */
+ huft_t *inflate_codes_tl;
+ huft_t *inflate_codes_td;
+ unsigned inflate_codes_bl;
+ unsigned inflate_codes_bd;
+ unsigned inflate_codes_nn; /* length and index for copy */
+ unsigned inflate_codes_dd;
+ smallint resume_copy;
+
+ /* private data of inflate_get_next_window() */
+ smallint method; /* Method == -1 for stored, -2 for codes */
+ smallint need_another_block;
+ smallint end_reached;
+
+ /* private data of inflate_stored() */
+ unsigned inflate_stored_n;
+ unsigned inflate_stored_b;
+ unsigned inflate_stored_k;
+ unsigned inflate_stored_w;
+} state_t;
+#define gunzip_bytes_out (S()gunzip_bytes_out )
+#define gunzip_crc (S()gunzip_crc )
+#define gunzip_src_fd (S()gunzip_src_fd )
+#define gunzip_outbuf_count (S()gunzip_outbuf_count)
+#define gunzip_window (S()gunzip_window )
+#define gunzip_crc_table (S()gunzip_crc_table )
+#define gunzip_bb (S()gunzip_bb )
+#define gunzip_bk (S()gunzip_bk )
+#define bytebuffer_max (S()bytebuffer_max )
+#define bytebuffer (S()bytebuffer )
+#define bytebuffer_offset (S()bytebuffer_offset )
+#define bytebuffer_size (S()bytebuffer_size )
+#define inflate_codes_ml (S()inflate_codes_ml )
+#define inflate_codes_md (S()inflate_codes_md )
+#define inflate_codes_bb (S()inflate_codes_bb )
+#define inflate_codes_k (S()inflate_codes_k )
+#define inflate_codes_w (S()inflate_codes_w )
+#define inflate_codes_tl (S()inflate_codes_tl )
+#define inflate_codes_td (S()inflate_codes_td )
+#define inflate_codes_bl (S()inflate_codes_bl )
+#define inflate_codes_bd (S()inflate_codes_bd )
+#define inflate_codes_nn (S()inflate_codes_nn )
+#define inflate_codes_dd (S()inflate_codes_dd )
+#define resume_copy (S()resume_copy )
+#define method (S()method )
+#define need_another_block (S()need_another_block )
+#define end_reached (S()end_reached )
+#define inflate_stored_n (S()inflate_stored_n )
+#define inflate_stored_b (S()inflate_stored_b )
+#define inflate_stored_k (S()inflate_stored_k )
+#define inflate_stored_w (S()inflate_stored_w )
+#define INIT_STATE ({ bytebuffer_size = 0; method = -1; need_another_block = 1; })
+
+
+/* This is generic part */
+#if STATE_IN_BSS /* Use global data segment */
+#define DECLARE_STATE /*nothing*/
+#define ALLOC_STATE (init_state())
+#define DEALLOC_STATE ((void)0)
+#define S() state.
+#define PASS_STATE /*nothing*/
+#define PASS_STATE_ONLY /*nothing*/
+#define STATE_PARAM /*nothing*/
+#define STATE_PARAM_ONLY void
+static state_t state;
+static void init_state(void)
+{
+ INIT_STATE;
+}
+#endif
+
+#if STATE_IN_MALLOC /* Use malloc space */
+#define DECLARE_STATE state_t *state
+#define ALLOC_STATE (state = alloc_state())
+#define DEALLOC_STATE free(state)
+#define S() state->
+#define PASS_STATE state,
+#define PASS_STATE_ONLY state
+#define STATE_PARAM state_t *state,
+#define STATE_PARAM_ONLY state_t *state
+static state_t* alloc_state(void)
+{
+ state_t* state = xzalloc(sizeof(*state));
+ INIT_STATE;
+ return state;
+}
+#endif
+
+
+static const unsigned short mask_bits[] = {
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* Copy lengths for literal codes 257..285 */
+static const unsigned short cplens[] = {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
+ 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+};
+
+/* note: see note #13 above about the 258 in this list. */
+/* Extra bits for literal codes 257..285 */
+static const unsigned char cplext[] = {
+ 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,
+ 5, 5, 5, 0, 99, 99
+}; /* 99 == invalid */
+
+/* Copy offsets for distance codes 0..29 */
+static const unsigned short cpdist[] = {
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
+ 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
+};
+
+/* Extra bits for distance codes */
+static const unsigned char cpdext[] = {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
+ 11, 11, 12, 12, 13, 13
+};
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+/* Order of the bit length code lengths */
+static const unsigned char border[] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current, const unsigned required)
+{
+ while (*current < required) {
+ if (bytebuffer_offset >= bytebuffer_size) {
+ /* Leave the first 4 bytes empty so we can always unwind the bitbuffer
+ * to the front of the bytebuffer, leave 4 bytes free at end of tail
+ * so we can easily top up buffer in check_trailer_gzip() */
+ bytebuffer_size = safe_read(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8);
+ if (1 > bytebuffer_size)
+//shouldn't we propagate error?
+ bb_error_msg_and_die("unexpected end of file");
+ bytebuffer_size += 4;
+ bytebuffer_offset = 4;
+ }
+ bitbuffer |= ((unsigned) bytebuffer[bytebuffer_offset]) << *current;
+ bytebuffer_offset++;
+ *current += 8;
+ }
+ return bitbuffer;
+}
+
+/*
+ * Free the malloc'ed tables built by huft_build(), which makes a linked
+ * list of the tables it made, with the links in a dummy first entry of
+ * each table.
+ * t: table to free
+ */
+static void huft_free(huft_t * p)
+{
+ huft_t *q;
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ while (p) {
+ q = (--p)->v.t;
+ free(p);
+ p = q;
+ }
+}
+
+/* Given a list of code lengths and a maximum table size, make a set of
+ * tables to decode that set of codes. Return zero on success, one if
+ * the given code set is incomplete (the tables are still built in this
+ * case), two if the input is invalid (all zero length codes or an
+ * oversubscribed set of lengths), and three if not enough memory.
+ *
+ * b: code lengths in bits (all assumed <= BMAX)
+ * n: number of codes (assumed <= N_MAX)
+ * s: number of simple-valued codes (0..s-1)
+ * d: list of base values for non-simple codes
+ * e: list of extra bits for non-simple codes
+ * t: result: starting table
+ * m: maximum lookup bits, returns actual
+ */
+static int huft_build(unsigned *b, const unsigned n,
+ const unsigned s, const unsigned short *d,
+ const unsigned char *e, huft_t ** t, unsigned *m)
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX + 1]; /* bit length count table */
+ unsigned eob_len; /* length of end-of-block code (value 256) */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int htl; /* table level */
+ unsigned i; /* counter, current code */
+ unsigned j; /* counter */
+ int k; /* number of bits in current code */
+ unsigned *p; /* pointer into c[], b[], or v[] */
+ huft_t *q; /* points to current table */
+ huft_t r; /* table entry for structure assignment */
+ huft_t *u[BMAX]; /* table stack */
+ unsigned v[N_MAX]; /* values in order of bit length */
+ int ws[BMAX+1]; /* bits decoded stack */
+ int w; /* bits decoded */
+ unsigned x[BMAX + 1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+ /* Length of EOB code, if any */
+ eob_len = n > 256 ? b[256] : BMAX;
+
+ /* Generate counts for each bit length */
+ memset(c, 0, sizeof(c));
+ p = b;
+ i = n;
+ do {
+ c[*p]++; /* assume all entries <= BMAX */
+ p++; /* Can't combine with above line (Solaris bug) */
+ } while (--i);
+ if (c[0] == n) { /* null input--all zero length codes */
+ *t = NULL;
+ *m = 0;
+ return 2;
+ }
+
+ /* Find minimum and maximum length, bound *m by those */
+ for (j = 1; (c[j] == 0) && (j <= BMAX); j++);
+ k = j; /* minimum code length */
+ for (i = BMAX; (c[i] == 0) && i; i--);
+ g = i; /* maximum code length */
+ *m = (*m < j) ? j : ((*m > i) ? i : *m);
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1) {
+ y -= c[j];
+ if (y < 0) {
+ return 2; /* bad input: more codes than bits */
+ }
+ }
+ y -= c[i];
+ if (y < 0) {
+ return 2;
+ }
+ c[i] += y;
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1;
+ xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ j += *p++;
+ *xp++ = j;
+ }
+
+ /* Make a table of values in order of bit lengths */
+ p = b;
+ i = 0;
+ do {
+ j = *p++;
+ if (j != 0) {
+ v[x[j]++] = i;
+ }
+ } while (++i < n);
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ htl = -1; /* no tables yet--level -1 */
+ w = ws[0] = 0; /* bits decoded */
+ u[0] = NULL; /* just to keep compilers happy */
+ q = NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++) {
+ a = c[k];
+ while (a--) {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > ws[htl + 1]) {
+ w = ws[++htl];
+
+ /* compute minimum size table less than or equal to *m bits */
+ z = g - w;
+ z = z > *m ? *m : z; /* upper limit on table size */
+ j = k - w;
+ f = 1 << j;
+ if (f > a + 1) { /* try a k-w bit table */
+ /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) { /* try smaller tables up to z bits */
+ f <<= 1;
+ if (f <= *++xp) {
+ break; /* enough codes to use up j bits */
+ }
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ j = (w + j > eob_len && w < eob_len) ? eob_len - w : j; /* make EOB code end at table */
+ z = 1 << j; /* table entries for j-bit table */
+ ws[htl+1] = w + j; /* set bits decoded in stack */
+
+ /* allocate and link in new table */
+ q = xzalloc((z + 1) * sizeof(huft_t));
+ *t = q + 1; /* link to list for huft_free() */
+ t = &(q->v.t);
+ u[htl] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (htl) {
+ x[htl] = i; /* save pattern for backing up */
+ r.b = (unsigned char) (w - ws[htl - 1]); /* bits to dump before this table */
+ r.e = (unsigned char) (16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = (i & ((1 << w) - 1)) >> ws[htl - 1];
+ u[htl - 1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (unsigned char) (k - w);
+ if (p >= v + n) {
+ r.e = 99; /* out of values--invalid code */
+ } else if (*p < s) {
+ r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is EOB code */
+ r.v.n = (unsigned short) (*p++); /* simple code is just the value */
+ } else {
+ r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f) {
+ q[j] = r;
+ }
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1) {
+ i ^= j;
+ }
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[htl]) {
+ w = ws[--htl];
+ }
+ }
+ }
+
+ /* return actual size of base table */
+ *m = ws[1];
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+/*
+ * inflate (decompress) the codes in a deflated (compressed) block.
+ * Return an error code or zero if it all goes ok.
+ *
+ * tl, td: literal/length and distance decoder tables
+ * bl, bd: number of bits decoded by tl[] and td[]
+ */
+/* called once from inflate_block */
+
+/* map formerly local static variables to globals */
+#define ml inflate_codes_ml
+#define md inflate_codes_md
+#define bb inflate_codes_bb
+#define k inflate_codes_k
+#define w inflate_codes_w
+#define tl inflate_codes_tl
+#define td inflate_codes_td
+#define bl inflate_codes_bl
+#define bd inflate_codes_bd
+#define nn inflate_codes_nn
+#define dd inflate_codes_dd
+static void inflate_codes_setup(STATE_PARAM huft_t * my_tl, huft_t * my_td, const unsigned my_bl, const unsigned my_bd)
+{
+ tl = my_tl;
+ td = my_td;
+ bl = my_bl;
+ bd = my_bd;
+ /* make local copies of globals */
+ bb = gunzip_bb; /* initialize bit buffer */
+ k = gunzip_bk;
+ w = gunzip_outbuf_count; /* initialize gunzip_window position */
+ /* inflate the coded data */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+}
+/* called once from inflate_get_next_window */
+static int inflate_codes(STATE_PARAM_ONLY)
+{
+ unsigned e; /* table entry flag/number of extra bits */
+ huft_t *t; /* pointer to table entry */
+
+ if (resume_copy) goto do_copy;
+
+ while (1) { /* do until end of block */
+ bb = fill_bitbuffer(PASS_STATE bb, &k, bl);
+ t = tl + ((unsigned) bb & ml);
+ e = t->e;
+ if (e > 16)
+ do {
+ if (e == 99) {
+//shouldn't we propagate error?
+ bb_error_msg_and_die("inflate_codes error 1");
+ }
+ bb >>= t->b;
+ k -= t->b;
+ e -= 16;
+ bb = fill_bitbuffer(PASS_STATE bb, &k, e);
+ t = t->v.t + ((unsigned) bb & mask_bits[e]);
+ e = t->e;
+ } while (e > 16);
+ bb >>= t->b;
+ k -= t->b;
+ if (e == 16) { /* then it's a literal */
+ gunzip_window[w++] = (unsigned char) t->v.n;
+ if (w == GUNZIP_WSIZE) {
+ gunzip_outbuf_count = w;
+ //flush_gunzip_window();
+ w = 0;
+ return 1; // We have a block to read
+ }
+ } else { /* it's an EOB or a length */
+ /* exit if end of block */
+ if (e == 15) {
+ break;
+ }
+
+ /* get length of block to copy */
+ bb = fill_bitbuffer(PASS_STATE bb, &k, e);
+ nn = t->v.n + ((unsigned) bb & mask_bits[e]);
+ bb >>= e;
+ k -= e;
+
+ /* decode distance of block to copy */
+ bb = fill_bitbuffer(PASS_STATE bb, &k, bd);
+ t = td + ((unsigned) bb & md);
+ e = t->e;
+ if (e > 16)
+ do {
+ if (e == 99)
+//shouldn't we propagate error?
+ bb_error_msg_and_die("inflate_codes error 2");
+ bb >>= t->b;
+ k -= t->b;
+ e -= 16;
+ bb = fill_bitbuffer(PASS_STATE bb, &k, e);
+ t = t->v.t + ((unsigned) bb & mask_bits[e]);
+ e = t->e;
+ } while (e > 16);
+ bb >>= t->b;
+ k -= t->b;
+ bb = fill_bitbuffer(PASS_STATE bb, &k, e);
+ dd = w - t->v.n - ((unsigned) bb & mask_bits[e]);
+ bb >>= e;
+ k -= e;
+
+ /* do the copy */
+ do_copy:
+ do {
+ /* Was: nn -= (e = (e = GUNZIP_WSIZE - ((dd &= GUNZIP_WSIZE - 1) > w ? dd : w)) > nn ? nn : e); */
+ /* Who wrote THAT?? rewritten as: */
+ dd &= GUNZIP_WSIZE - 1;
+ e = GUNZIP_WSIZE - (dd > w ? dd : w);
+ if (e > nn) e = nn;
+ nn -= e;
+
+ /* copy to new buffer to prevent possible overwrite */
+ if (w - dd >= e) { /* (this test assumes unsigned comparison) */
+ memcpy(gunzip_window + w, gunzip_window + dd, e);
+ w += e;
+ dd += e;
+ } else {
+ /* do it slow to avoid memcpy() overlap */
+ /* !NOMEMCPY */
+ do {
+ gunzip_window[w++] = gunzip_window[dd++];
+ } while (--e);
+ }
+ if (w == GUNZIP_WSIZE) {
+ gunzip_outbuf_count = w;
+ resume_copy = (nn != 0);
+ //flush_gunzip_window();
+ w = 0;
+ return 1;
+ }
+ } while (nn);
+ resume_copy = 0;
+ }
+ }
+
+ /* restore the globals from the locals */
+ gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
+ gunzip_bb = bb; /* restore global bit buffer */
+ gunzip_bk = k;
+
+ /* normally just after call to inflate_codes, but save code by putting it here */
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+
+ /* done */
+ return 0;
+}
+#undef ml
+#undef md
+#undef bb
+#undef k
+#undef w
+#undef tl
+#undef td
+#undef bl
+#undef bd
+#undef nn
+#undef dd
+
+
+/* called once from inflate_block */
+static void inflate_stored_setup(STATE_PARAM int my_n, int my_b, int my_k)
+{
+ inflate_stored_n = my_n;
+ inflate_stored_b = my_b;
+ inflate_stored_k = my_k;
+ /* initialize gunzip_window position */
+ inflate_stored_w = gunzip_outbuf_count;
+}
+/* called once from inflate_get_next_window */
+static int inflate_stored(STATE_PARAM_ONLY)
+{
+ /* read and output the compressed data */
+ while (inflate_stored_n--) {
+ inflate_stored_b = fill_bitbuffer(PASS_STATE inflate_stored_b, &inflate_stored_k, 8);
+ gunzip_window[inflate_stored_w++] = (unsigned char) inflate_stored_b;
+ if (inflate_stored_w == GUNZIP_WSIZE) {
+ gunzip_outbuf_count = inflate_stored_w;
+ //flush_gunzip_window();
+ inflate_stored_w = 0;
+ inflate_stored_b >>= 8;
+ inflate_stored_k -= 8;
+ return 1; // We have a block
+ }
+ inflate_stored_b >>= 8;
+ inflate_stored_k -= 8;
+ }
+
+ /* restore the globals from the locals */
+ gunzip_outbuf_count = inflate_stored_w; /* restore global gunzip_window pointer */
+ gunzip_bb = inflate_stored_b; /* restore global bit buffer */
+ gunzip_bk = inflate_stored_k;
+ return 0; // Finished
+}
+
+
+/*
+ * decompress an inflated block
+ * e: last block flag
+ *
+ * GLOBAL VARIABLES: bb, kk,
+ */
+/* Return values: -1 = inflate_stored, -2 = inflate_codes */
+/* One callsite in inflate_get_next_window */
+static int inflate_block(STATE_PARAM smallint *e)
+{
+ unsigned t; /* block type */
+ unsigned b; /* bit buffer */
+ unsigned k; /* number of bits in bit buffer */
+
+ /* make local bit buffer */
+
+ b = gunzip_bb;
+ k = gunzip_bk;
+
+ /* read in last block bit */
+ b = fill_bitbuffer(PASS_STATE b, &k, 1);
+ *e = b & 1;
+ b >>= 1;
+ k -= 1;
+
+ /* read in block type */
+ b = fill_bitbuffer(PASS_STATE b, &k, 2);
+ t = (unsigned) b & 3;
+ b >>= 2;
+ k -= 2;
+
+ /* restore the global bit buffer */
+ gunzip_bb = b;
+ gunzip_bk = k;
+
+ /* inflate that block type */
+ switch (t) {
+ case 0: /* Inflate stored */
+ {
+ unsigned n; /* number of bytes in block */
+ unsigned b_stored; /* bit buffer */
+ unsigned k_stored; /* number of bits in bit buffer */
+
+ /* make local copies of globals */
+ b_stored = gunzip_bb; /* initialize bit buffer */
+ k_stored = gunzip_bk;
+
+ /* go to byte boundary */
+ n = k_stored & 7;
+ b_stored >>= n;
+ k_stored -= n;
+
+ /* get the length and its complement */
+ b_stored = fill_bitbuffer(PASS_STATE b_stored, &k_stored, 16);
+ n = ((unsigned) b_stored & 0xffff);
+ b_stored >>= 16;
+ k_stored -= 16;
+
+ b_stored = fill_bitbuffer(PASS_STATE b_stored, &k_stored, 16);
+ if (n != (unsigned) ((~b_stored) & 0xffff)) {
+ return 1; /* error in compressed data */
+ }
+ b_stored >>= 16;
+ k_stored -= 16;
+
+ inflate_stored_setup(PASS_STATE n, b_stored, k_stored); // Setup inflate_stored
+
+ return -1;
+ }
+ case 1:
+ /* Inflate fixed
+ * decompress an inflated type 1 (fixed Huffman codes) block. We should
+ * either replace this with a custom decoder, or at least precompute the
+ * Huffman tables. */
+ {
+ int i; /* temporary variable */
+ huft_t *tl; /* literal/length code table */
+ huft_t *td; /* distance code table */
+ unsigned bl; /* lookup bits for tl */
+ unsigned bd; /* lookup bits for td */
+ unsigned l[288]; /* length list for huft_build */
+
+ /* set up literal table */
+ for (i = 0; i < 144; i++) {
+ l[i] = 8;
+ }
+ for (; i < 256; i++) {
+ l[i] = 9;
+ }
+ for (; i < 280; i++) {
+ l[i] = 7;
+ }
+ for (; i < 288; i++) { /* make a complete, but wrong code set */
+ l[i] = 8;
+ }
+ bl = 7;
+ i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl);
+ if (i != 0) {
+ return i;
+ }
+
+ /* set up distance table */
+ for (i = 0; i < 30; i++) { /* make an incomplete code set */
+ l[i] = 5;
+ }
+ bd = 5;
+ i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd);
+ if (i > 1) {
+ huft_free(tl);
+ return i;
+ }
+
+ /* decompress until an end-of-block code */
+ inflate_codes_setup(PASS_STATE tl, td, bl, bd); // Setup inflate_codes
+
+ /* huft_free code moved into inflate_codes */
+
+ return -2;
+ }
+ case 2: /* Inflate dynamic */
+ {
+ const int dbits = 6; /* bits in base distance lookup table */
+ const int lbits = 9; /* bits in base literal/length lookup table */
+
+ huft_t *tl; /* literal/length code table */
+ huft_t *td; /* distance code table */
+ unsigned i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ unsigned bl; /* lookup bits for tl */
+ unsigned bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+
+ unsigned ll[286 + 30]; /* literal/length and distance code lengths */
+ unsigned b_dynamic; /* bit buffer */
+ unsigned k_dynamic; /* number of bits in bit buffer */
+
+ /* make local bit buffer */
+ b_dynamic = gunzip_bb;
+ k_dynamic = gunzip_bk;
+
+ /* read in table lengths */
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 5);
+ nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */
+
+ b_dynamic >>= 5;
+ k_dynamic -= 5;
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 5);
+ nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */
+
+ b_dynamic >>= 5;
+ k_dynamic -= 5;
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 4);
+ nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */
+
+ b_dynamic >>= 4;
+ k_dynamic -= 4;
+ if (nl > 286 || nd > 30) {
+ return 1; /* bad lengths */
+ }
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++) {
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 3);
+ ll[border[j]] = (unsigned) b_dynamic & 7;
+ b_dynamic >>= 3;
+ k_dynamic -= 3;
+ }
+ for (; j < 19; j++) {
+ ll[border[j]] = 0;
+ }
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl);
+ if (i != 0) {
+ if (i == 1) {
+ huft_free(tl);
+ }
+ return i; /* incomplete code set */
+ }
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask_bits[bl];
+ i = l = 0;
+ while ((unsigned) i < n) {
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, (unsigned)bl);
+ j = (td = tl + ((unsigned) b_dynamic & m))->b;
+ b_dynamic >>= j;
+ k_dynamic -= j;
+ j = td->v.n;
+ if (j < 16) { /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ } else if (j == 16) { /* repeat last length 3 to 6 times */
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 2);
+ j = 3 + ((unsigned) b_dynamic & 3);
+ b_dynamic >>= 2;
+ k_dynamic -= 2;
+ if ((unsigned) i + j > n) {
+ return 1;
+ }
+ while (j--) {
+ ll[i++] = l;
+ }
+ } else if (j == 17) { /* 3 to 10 zero length codes */
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 3);
+ j = 3 + ((unsigned) b_dynamic & 7);
+ b_dynamic >>= 3;
+ k_dynamic -= 3;
+ if ((unsigned) i + j > n) {
+ return 1;
+ }
+ while (j--) {
+ ll[i++] = 0;
+ }
+ l = 0;
+ } else { /* j == 18: 11 to 138 zero length codes */
+ b_dynamic = fill_bitbuffer(PASS_STATE b_dynamic, &k_dynamic, 7);
+ j = 11 + ((unsigned) b_dynamic & 0x7f);
+ b_dynamic >>= 7;
+ k_dynamic -= 7;
+ if ((unsigned) i + j > n) {
+ return 1;
+ }
+ while (j--) {
+ ll[i++] = 0;
+ }
+ l = 0;
+ }
+ }
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+ /* restore the global bit buffer */
+ gunzip_bb = b_dynamic;
+ gunzip_bk = k_dynamic;
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+
+ i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl);
+ if (i != 0) {
+ if (i == 1) {
+//shouldn't we propagate error?
+ bb_error_msg_and_die("incomplete literal tree");
+ /* huft_free(tl); */
+ }
+ return i; /* incomplete code set */
+ }
+
+ bd = dbits;
+ i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd);
+ if (i != 0) {
+ if (i == 1) {
+//shouldn't we propagate error?
+ bb_error_msg_and_die("incomplete distance tree");
+ /* huft_free(td); */
+ }
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+ /* decompress until an end-of-block code */
+ inflate_codes_setup(PASS_STATE tl, td, bl, bd); // Setup inflate_codes
+
+ /* huft_free code moved into inflate_codes */
+
+ return -2;
+ }
+ default:
+ /* bad block type */
+//shouldn't we propagate error?
+ bb_error_msg_and_die("bad block type %d", t);
+ }
+}
+
+/* Two callsites, both in inflate_get_next_window */
+static void calculate_gunzip_crc(STATE_PARAM_ONLY)
+{
+ int n;
+ for (n = 0; n < gunzip_outbuf_count; n++) {
+ gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
+ }
+ gunzip_bytes_out += gunzip_outbuf_count;
+}
+
+/* One callsite in inflate_unzip_internal */
+static int inflate_get_next_window(STATE_PARAM_ONLY)
+{
+ gunzip_outbuf_count = 0;
+
+ while (1) {
+ int ret;
+
+ if (need_another_block) {
+ if (end_reached) {
+ calculate_gunzip_crc(PASS_STATE_ONLY);
+ end_reached = 0;
+ need_another_block = 1;
+ return 0; /* Last block */
+ }
+ method = inflate_block(PASS_STATE &end_reached);
+ need_another_block = 0;
+ }
+
+ switch (method) {
+ case -1:
+ ret = inflate_stored(PASS_STATE_ONLY);
+ break;
+ case -2:
+ ret = inflate_codes(PASS_STATE_ONLY);
+ break;
+ default:
+//shouldn't we propagate error?
+ bb_error_msg_and_die("inflate error %d", method);
+ }
+
+ if (ret == 1) {
+ calculate_gunzip_crc(PASS_STATE_ONLY);
+ return 1; // More data left
+ }
+ need_another_block = 1; // End of that block
+ }
+ /* Doesnt get here */
+}
+
+
+/* Called from inflate_gunzip() and inflate_unzip() */
+/* NB: bytebuffer is allocated here but freeing it is left to the caller! */
+static USE_DESKTOP(long long) int
+inflate_unzip_internal(STATE_PARAM int in, int out)
+{
+ USE_DESKTOP(long long) int n = 0;
+ ssize_t nwrote;
+
+ /* Allocate all global buffers (for DYN_ALLOC option) */
+ gunzip_window = xmalloc(GUNZIP_WSIZE);
+ gunzip_outbuf_count = 0;
+ gunzip_bytes_out = 0;
+ gunzip_src_fd = in;
+
+ /* initialize gunzip_window, bit buffer */
+ gunzip_bk = 0;
+ gunzip_bb = 0;
+
+ /* Create the crc table */
+ gunzip_crc_table = crc32_filltable(0);
+ gunzip_crc = ~0;
+
+ /* Allocate space for buffer */
+ bytebuffer = xmalloc(bytebuffer_max);
+
+ while (1) {
+ int r = inflate_get_next_window(PASS_STATE_ONLY);
+ nwrote = full_write(out, gunzip_window, gunzip_outbuf_count);
+ if (nwrote != gunzip_outbuf_count) {
+ bb_perror_msg("write");
+ n = -1;
+ goto ret;
+ }
+ USE_DESKTOP(n += nwrote;)
+ if (r == 0) break;
+ }
+
+ /* Store unused bytes in a global buffer so calling applets can access it */
+ if (gunzip_bk >= 8) {
+ /* Undo too much lookahead. The next read will be byte aligned
+ * so we can discard unused bits in the last meaningful byte. */
+ bytebuffer_offset--;
+ bytebuffer[bytebuffer_offset] = gunzip_bb & 0xff;
+ gunzip_bb >>= 8;
+ gunzip_bk -= 8;
+ }
+ ret:
+ /* Cleanup */
+ free(gunzip_window);
+ free(gunzip_crc_table);
+ return n;
+}
+
+
+USE_DESKTOP(long long) int
+inflate_unzip(inflate_unzip_result *res, unsigned bufsize, int in, int out)
+{
+ USE_DESKTOP(long long) int n;
+ DECLARE_STATE;
+
+ ALLOC_STATE;
+
+ bytebuffer_max = bufsize + 8;
+ bytebuffer_offset = 4;
+ n = inflate_unzip_internal(PASS_STATE in, out);
+
+ res->crc = gunzip_crc;
+ res->bytes_out = gunzip_bytes_out;
+ free(bytebuffer);
+ DEALLOC_STATE;
+ return n;
+}
+
+
+USE_DESKTOP(long long) int
+inflate_gunzip(int in, int out)
+{
+ uint32_t stored_crc = 0;
+ unsigned count;
+ USE_DESKTOP(long long) int n;
+ DECLARE_STATE;
+
+ ALLOC_STATE;
+
+ bytebuffer_max = 0x8000;
+ n = inflate_unzip_internal(PASS_STATE in, out);
+
+ if (n < 0) goto ret;
+
+ /* top up the input buffer with the rest of the trailer */
+ count = bytebuffer_size - bytebuffer_offset;
+ if (count < 8) {
+ xread(in, &bytebuffer[bytebuffer_size], 8 - count);
+//shouldn't we propagate error?
+ bytebuffer_size += 8 - count;
+ }
+ for (count = 0; count != 4; count++) {
+ stored_crc |= (bytebuffer[bytebuffer_offset] << (count * 8));
+ bytebuffer_offset++;
+ }
+
+ /* Validate decompression - crc */
+ if (stored_crc != (~gunzip_crc)) {
+ bb_error_msg("crc error");
+ n = -1;
+ goto ret;
+ }
+
+ /* Validate decompression - size */
+ if (gunzip_bytes_out !=
+ (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) |
+ (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))
+ ) {
+ bb_error_msg("incorrect length");
+ n = -1;
+ }
+ ret:
+ free(bytebuffer);
+ DEALLOC_STATE;
+ return n;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_all.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_all.c
new file mode 100644
index 0000000..5c991ca
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_all.c
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include "unarchive.h"
+
+/* Accept any non-null name, its not really a filter at all */
+char filter_accept_all(archive_handle_t *archive_handle)
+{
+ if (archive_handle->file_header->name)
+ return EXIT_SUCCESS;
+ return EXIT_FAILURE;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list.c
new file mode 100644
index 0000000..cfc1b0c
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list.c
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include "unarchive.h"
+
+/*
+ * Accept names that are in the accept list, ignoring reject list.
+ */
+char filter_accept_list(archive_handle_t *archive_handle)
+{
+ if (find_list_entry(archive_handle->accept, archive_handle->file_header->name))
+ return EXIT_SUCCESS;
+ return EXIT_FAILURE;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list_reassign.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list_reassign.c
new file mode 100644
index 0000000..0fb536f
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_list_reassign.c
@@ -0,0 +1,44 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+/*
+ * Reassign the subarchive metadata parser based on the filename extension
+ * e.g. if its a .tar.gz modify archive_handle->sub_archive to process a .tar.gz
+ * or if its a .tar.bz2 make archive_handle->sub_archive handle that
+ */
+char filter_accept_list_reassign(archive_handle_t *archive_handle)
+{
+ /* Check the file entry is in the accept list */
+ if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) {
+ const char *name_ptr;
+
+ /* Extract the last 2 extensions */
+ name_ptr = strrchr(archive_handle->file_header->name, '.');
+
+ /* Modify the subarchive handler based on the extension */
+#ifdef CONFIG_FEATURE_DEB_TAR_GZ
+ if (strcmp(name_ptr, ".gz") == 0) {
+ archive_handle->action_data_subarchive = get_header_tar_gz;
+ return EXIT_SUCCESS;
+ }
+#endif
+#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
+ if (strcmp(name_ptr, ".bz2") == 0) {
+ archive_handle->action_data_subarchive = get_header_tar_bz2;
+ return EXIT_SUCCESS;
+ }
+#endif
+ if (ENABLE_FEATURE_DEB_TAR_LZMA && !strcmp(name_ptr, ".lzma")) {
+ archive_handle->action_data_subarchive = get_header_tar_lzma;
+ return EXIT_SUCCESS;
+ }
+ }
+ return EXIT_FAILURE;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_reject_list.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_reject_list.c
new file mode 100644
index 0000000..79da350
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/filter_accept_reject_list.c
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include "unarchive.h"
+
+/*
+ * Accept names that are in the accept list and not in the reject list
+ */
+char filter_accept_reject_list(archive_handle_t *archive_handle)
+{
+ const char *key = archive_handle->file_header->name;
+ const llist_t *reject_entry = find_list_entry2(archive_handle->reject, key);
+ const llist_t *accept_entry;
+
+ /* If the key is in a reject list fail */
+ if (reject_entry) {
+ return EXIT_FAILURE;
+ }
+ accept_entry = find_list_entry2(archive_handle->accept, key);
+
+ /* Fail if an accept list was specified and the key wasnt in there */
+ if ((accept_entry == NULL) && archive_handle->accept) {
+ return EXIT_FAILURE;
+ }
+
+ /* Accepted */
+ return EXIT_SUCCESS;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/find_list_entry.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/find_list_entry.c
new file mode 100644
index 0000000..d1afc72
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/find_list_entry.c
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fnmatch.h>
+#include <stdlib.h>
+#include "unarchive.h"
+
+/* Find a string in a shell pattern list */
+const llist_t *find_list_entry(const llist_t *list, const char *filename)
+{
+ while (list) {
+ if (fnmatch(list->data, filename, 0) == 0) {
+ return list;
+ }
+ list = list->link;
+ }
+ return NULL;
+}
+
+/* Same, but compares only path components present in pattern
+ * (extra trailing path components in filename are assumed to match)
+ */
+const llist_t *find_list_entry2(const llist_t *list, const char *filename)
+{
+ char buf[PATH_MAX];
+ int pattern_slash_cnt;
+ const char *c;
+ char *d;
+
+ while (list) {
+ c = list->data;
+ pattern_slash_cnt = 0;
+ while (*c)
+ if (*c++ == '/') pattern_slash_cnt++;
+ c = filename;
+ d = buf;
+ /* paranoia is better that buffer overflows */
+ while (*c && d != buf + sizeof(buf)-1) {
+ if (*c == '/' && --pattern_slash_cnt < 0)
+ break;
+ *d++ = *c++;
+ }
+ *d = '\0';
+ if (fnmatch(list->data, buf, 0) == 0) {
+ return list;
+ }
+ list = list->link;
+ }
+ return NULL;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_ar.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_ar.c
new file mode 100644
index 0000000..c691f1b
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_ar.c
@@ -0,0 +1,126 @@
+/* vi: set sw=4 ts=4: */
+/* Copyright 2001 Glenn McGrath.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+char get_header_ar(archive_handle_t *archive_handle)
+{
+ int err;
+ file_header_t *typed = archive_handle->file_header;
+ union {
+ char raw[60];
+ struct {
+ char name[16];
+ char date[12];
+ char uid[6];
+ char gid[6];
+ char mode[8];
+ char size[10];
+ char magic[2];
+ } formatted;
+ } ar;
+#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
+ static char *ar_long_names;
+ static unsigned int ar_long_name_size;
+#endif
+
+ /* dont use xread as we want to handle the error ourself */
+ if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
+ /* End Of File */
+ return EXIT_FAILURE;
+ }
+
+ /* ar header starts on an even byte (2 byte aligned)
+ * '\n' is used for padding
+ */
+ if (ar.raw[0] == '\n') {
+ /* fix up the header, we started reading 1 byte too early */
+ memmove(ar.raw, &ar.raw[1], 59);
+ ar.raw[59] = xread_char(archive_handle->src_fd);
+ archive_handle->offset++;
+ }
+ archive_handle->offset += 60;
+
+ /* align the headers based on the header magic */
+ if (ar.formatted.magic[0] != '`' || ar.formatted.magic[1] != '\n')
+ bb_error_msg_and_die("invalid ar header");
+
+ /* FIXME: more thorough routine would be in order here */
+ /* (we have something like that in tar) */
+ /* but for now we are lax. This code works because */
+ /* on misformatted numbers bb_strtou returns all-ones */
+ typed->mode = err = bb_strtou(ar.formatted.mode, NULL, 8);
+ if (err == -1) bb_error_msg_and_die("invalid ar header");
+ typed->mtime = err = bb_strtou(ar.formatted.date, NULL, 10);
+ if (err == -1) bb_error_msg_and_die("invalid ar header");
+ typed->uid = err = bb_strtou(ar.formatted.uid, NULL, 10);
+ if (err == -1) bb_error_msg_and_die("invalid ar header");
+ typed->gid = err = bb_strtou(ar.formatted.gid, NULL, 10);
+ if (err == -1) bb_error_msg_and_die("invalid ar header");
+ typed->size = err = bb_strtou(ar.formatted.size, NULL, 10);
+ if (err == -1) bb_error_msg_and_die("invalid ar header");
+
+ /* long filenames have '/' as the first character */
+ if (ar.formatted.name[0] == '/') {
+#if ENABLE_FEATURE_AR_LONG_FILENAMES
+ unsigned long_offset;
+
+ if (ar.formatted.name[1] == '/') {
+ /* If the second char is a '/' then this entries data section
+ * stores long filename for multiple entries, they are stored
+ * in static variable long_names for use in future entries */
+ ar_long_name_size = typed->size;
+ ar_long_names = xmalloc(ar_long_name_size);
+ xread(archive_handle->src_fd, ar_long_names, ar_long_name_size);
+ archive_handle->offset += ar_long_name_size;
+ /* This ar entries data section only contained filenames for other records
+ * they are stored in the static ar_long_names for future reference */
+ return get_header_ar(archive_handle); /* Return next header */
+ }
+
+ if (ar.formatted.name[1] == ' ') {
+ /* This is the index of symbols in the file for compilers */
+ data_skip(archive_handle);
+ archive_handle->offset += typed->size;
+ return get_header_ar(archive_handle); /* Return next header */
+ }
+
+ /* The number after the '/' indicates the offset in the ar data section
+ * (saved in variable long_name) that conatains the real filename */
+ long_offset = atoi(&ar.formatted.name[1]);
+ if (long_offset >= ar_long_name_size) {
+ bb_error_msg_and_die("can't resolve long filename");
+ }
+ typed->name = xstrdup(ar_long_names + long_offset);
+#else
+ bb_error_msg_and_die("long filenames not supported");
+#endif
+ } else {
+ /* short filenames */
+ typed->name = xstrndup(ar.formatted.name, 16);
+ }
+
+ typed->name[strcspn(typed->name, " /")] = '\0';
+
+ if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+ archive_handle->action_header(typed);
+ if (archive_handle->sub_archive) {
+ while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS)
+ /* repeat */;
+ } else {
+ archive_handle->action_data(archive_handle);
+ }
+ } else {
+ data_skip(archive_handle);
+ }
+
+ archive_handle->offset += typed->size;
+ /* Set the file pointer to the correct spot, we may have been reading a compressed file */
+ lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET);
+
+ return EXIT_SUCCESS;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_cpio.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_cpio.c
new file mode 100644
index 0000000..6fd1340
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_cpio.c
@@ -0,0 +1,160 @@
+/* vi: set sw=4 ts=4: */
+/* Copyright 2002 Laurence Anderson
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+typedef struct hardlinks_s {
+ char *name;
+ int inode;
+ struct hardlinks_s *next;
+} hardlinks_t;
+
+char get_header_cpio(archive_handle_t *archive_handle)
+{
+ static hardlinks_t *saved_hardlinks = NULL;
+ static unsigned short pending_hardlinks = 0;
+ static int inode;
+ file_header_t *file_header = archive_handle->file_header;
+ char cpio_header[110];
+ int namesize;
+ char dummy[16];
+ int major, minor, nlink;
+
+ if (pending_hardlinks) { /* Deal with any pending hardlinks */
+ hardlinks_t *tmp, *oldtmp;
+
+ tmp = saved_hardlinks;
+ oldtmp = NULL;
+
+ file_header->link_name = file_header->name;
+ file_header->size = 0;
+
+ while (tmp) {
+ if (tmp->inode != inode) {
+ tmp = tmp->next;
+ continue;
+ }
+
+ file_header->name = tmp->name;
+
+ if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+ archive_handle->action_data(archive_handle);
+ archive_handle->action_header(archive_handle->file_header);
+ }
+
+ pending_hardlinks--;
+
+ oldtmp = tmp;
+ tmp = tmp->next;
+ free(oldtmp->name);
+ free(oldtmp);
+ if (oldtmp == saved_hardlinks)
+ saved_hardlinks = tmp;
+ }
+
+ file_header->name = file_header->link_name;
+
+ if (pending_hardlinks > 1) {
+ bb_error_msg("error resolving hardlink: archive made by GNU cpio 2.0-2.2?");
+ }
+
+ /* No more pending hardlinks, read next file entry */
+ pending_hardlinks = 0;
+ }
+
+ /* There can be padding before archive header */
+ data_align(archive_handle, 4);
+
+ if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) {
+ return EXIT_FAILURE;
+ }
+ archive_handle->offset += 110;
+
+ if (strncmp(&cpio_header[0], "07070", 5) != 0
+ || (cpio_header[5] != '1' && cpio_header[5] != '2')
+ ) {
+ bb_error_msg_and_die("unsupported cpio format, use newc or crc");
+ }
+
+ {
+ unsigned long tmpsize;
+ sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
+ dummy, &inode, (unsigned int*)&file_header->mode,
+ (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
+ &nlink, &file_header->mtime, &tmpsize,
+ dummy, &major, &minor, &namesize, dummy);
+ file_header->size = tmpsize;
+ }
+
+ free(file_header->name);
+ file_header->name = xzalloc(namesize + 1);
+ /* Read in filename */
+ xread(archive_handle->src_fd, file_header->name, namesize);
+ archive_handle->offset += namesize;
+
+ /* Update offset amount and skip padding before file contents */
+ data_align(archive_handle, 4);
+
+ if (strcmp(file_header->name, "TRAILER!!!") == 0) {
+ /* Always round up */
+ printf("%d blocks\n", (int) (archive_handle->offset % 512 ?
+ archive_handle->offset / 512 + 1 :
+ archive_handle->offset / 512
+ ));
+ if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
+ hardlinks_t *tmp = saved_hardlinks;
+ hardlinks_t *oldtmp = NULL;
+ while (tmp) {
+ bb_error_msg("%s not created: cannot resolve hardlink", tmp->name);
+ oldtmp = tmp;
+ tmp = tmp->next;
+ free(oldtmp->name);
+ free(oldtmp);
+ }
+ saved_hardlinks = NULL;
+ pending_hardlinks = 0;
+ }
+ return EXIT_FAILURE;
+ }
+
+ if (S_ISLNK(file_header->mode)) {
+ file_header->link_name = xzalloc(file_header->size + 1);
+ xread(archive_handle->src_fd, file_header->link_name, file_header->size);
+ archive_handle->offset += file_header->size;
+ file_header->size = 0; /* Stop possible seeks in future */
+ } else {
+ file_header->link_name = NULL;
+ }
+ if (nlink > 1 && !S_ISDIR(file_header->mode)) {
+ if (file_header->size == 0) { /* Put file on a linked list for later */
+ hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
+ new->next = saved_hardlinks;
+ new->inode = inode;
+ /* name current allocated, freed later */
+ new->name = file_header->name;
+ file_header->name = NULL;
+ saved_hardlinks = new;
+ return EXIT_SUCCESS; /* Skip this one */
+ }
+ /* Found the file with data in */
+ pending_hardlinks = nlink;
+ }
+ file_header->device = makedev(major, minor);
+
+ if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+ archive_handle->action_data(archive_handle);
+ archive_handle->action_header(archive_handle->file_header);
+ } else {
+ data_skip(archive_handle);
+ }
+
+ archive_handle->offset += file_header->size;
+
+ free(file_header->link_name);
+
+ return EXIT_SUCCESS;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar.c
new file mode 100644
index 0000000..b3efdec
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar.c
@@ -0,0 +1,284 @@
+/* vi: set sw=4 ts=4: */
+/* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * FIXME:
+ * In privileged mode if uname and gname map to a uid and gid then use the
+ * mapped value instead of the uid/gid values in tar header
+ *
+ * References:
+ * GNU tar and star man pages,
+ * Opengroup's ustar interchange format,
+ * http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+static char *longname;
+static char *linkname;
+#else
+enum {
+ longname = 0,
+ linkname = 0,
+};
+#endif
+
+/* NB: _DESTROYS_ str[len] character! */
+static unsigned long long getOctal(char *str, int len)
+{
+ unsigned long long v;
+ /* Actually, tar header allows leading spaces also.
+ * Oh well, we will be liberal and skip this...
+ * The only downside probably is that we allow "-123" too :)
+ if (*str < '0' || *str > '7')
+ bb_error_msg_and_die("corrupted octal value in tar header");
+ */
+ str[len] = '\0';
+ v = strtoull(str, &str, 8);
+ if (*str)
+ bb_error_msg_and_die("corrupted octal value in tar header");
+ return v;
+}
+#define GET_OCTAL(a) getOctal((a), sizeof(a))
+
+void BUG_tar_header_size(void);
+char get_header_tar(archive_handle_t *archive_handle)
+{
+ static int end;
+
+ file_header_t *file_header = archive_handle->file_header;
+ struct {
+ /* ustar header, Posix 1003.1 */
+ char name[100]; /* 0-99 */
+ char mode[8]; /* 100-107 */
+ char uid[8]; /* 108-115 */
+ char gid[8]; /* 116-123 */
+ char size[12]; /* 124-135 */
+ char mtime[12]; /* 136-147 */
+ char chksum[8]; /* 148-155 */
+ char typeflag; /* 156-156 */
+ char linkname[100]; /* 157-256 */
+ char magic[6]; /* 257-262 */
+ char version[2]; /* 263-264 */
+ char uname[32]; /* 265-296 */
+ char gname[32]; /* 297-328 */
+ char devmajor[8]; /* 329-336 */
+ char devminor[8]; /* 337-344 */
+ char prefix[155]; /* 345-499 */
+ char padding[12]; /* 500-512 */
+ } tar;
+ char *cp;
+ int i, sum_u, sum_s, sum;
+ int parse_names;
+
+ if (sizeof(tar) != 512)
+ BUG_tar_header_size();
+
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ again:
+#endif
+ /* Align header */
+ data_align(archive_handle, 512);
+
+ again_after_align:
+
+ xread(archive_handle->src_fd, &tar, 512);
+ archive_handle->offset += 512;
+
+ /* If there is no filename its an empty header */
+ if (tar.name[0] == 0) {
+ if (end) {
+ /* This is the second consecutive empty header! End of archive!
+ * Read until the end to empty the pipe from gz or bz2
+ */
+ while (full_read(archive_handle->src_fd, &tar, 512) == 512)
+ /* repeat */;
+ return EXIT_FAILURE;
+ }
+ end = 1;
+ return EXIT_SUCCESS;
+ }
+ end = 0;
+
+ /* Check header has valid magic, "ustar" is for the proper tar
+ * 0's are for the old tar format
+ */
+ if (strncmp(tar.magic, "ustar", 5) != 0) {
+#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
+ if (memcmp(tar.magic, "\0\0\0\0", 5) != 0)
+#endif
+ bb_error_msg_and_die("invalid tar magic");
+ }
+
+ /* Do checksum on headers.
+ * POSIX says that checksum is done on unsigned bytes, but
+ * Sun and HP-UX gets it wrong... more details in
+ * GNU tar source. */
+ sum_s = sum_u = ' ' * sizeof(tar.chksum);
+ for (i = 0; i < 148 ; i++) {
+ sum_u += ((unsigned char*)&tar)[i];
+ sum_s += ((signed char*)&tar)[i];
+ }
+ for (i = 156; i < 512 ; i++) {
+ sum_u += ((unsigned char*)&tar)[i];
+ sum_s += ((signed char*)&tar)[i];
+ }
+ /* This field does not need special treatment (getOctal) */
+ sum = xstrtoul(tar.chksum, 8);
+ if (sum_u != sum && sum_s != sum) {
+ bb_error_msg_and_die("invalid tar header checksum");
+ }
+
+ /* 0 is reserved for high perf file, treat as normal file */
+ if (!tar.typeflag) tar.typeflag = '0';
+ parse_names = (tar.typeflag >= '0' && tar.typeflag <= '7');
+
+ /* getOctal trashes subsequent field, therefore we call it
+ * on fields in reverse order */
+ if (tar.devmajor[0]) {
+ unsigned minor = GET_OCTAL(tar.devminor);
+ unsigned major = GET_OCTAL(tar.devmajor);
+ file_header->device = makedev(major, minor);
+ }
+ file_header->link_name = NULL;
+ if (!linkname && parse_names && tar.linkname[0]) {
+ /* we trash magic[0] here, it's ok */
+ tar.linkname[sizeof(tar.linkname)] = '\0';
+ file_header->link_name = xstrdup(tar.linkname);
+ /* FIXME: what if we have non-link object with link_name? */
+ /* Will link_name be free()ed? */
+ }
+ file_header->mtime = GET_OCTAL(tar.mtime);
+ file_header->size = GET_OCTAL(tar.size);
+ file_header->gid = GET_OCTAL(tar.gid);
+ file_header->uid = GET_OCTAL(tar.uid);
+ /* Set bits 0-11 of the files mode */
+ file_header->mode = 07777 & GET_OCTAL(tar.mode);
+
+ file_header->name = NULL;
+ if (!longname && parse_names) {
+ /* we trash mode[0] here, it's ok */
+ tar.name[sizeof(tar.name)] = '\0';
+ if (tar.prefix[0]) {
+ /* and padding[0] */
+ tar.prefix[sizeof(tar.prefix)] = '\0';
+ file_header->name = concat_path_file(tar.prefix, tar.name);
+ } else
+ file_header->name = xstrdup(tar.name);
+ }
+
+ /* Set bits 12-15 of the files mode */
+ /* (typeflag was not trashed because chksum does not use getOctal) */
+ switch (tar.typeflag) {
+ /* busybox identifies hard links as being regular files with 0 size and a link name */
+ case '1':
+ file_header->mode |= S_IFREG;
+ break;
+ case '7':
+ /* case 0: */
+ case '0':
+#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
+ if (last_char_is(file_header->name, '/')) {
+ file_header->mode |= S_IFDIR;
+ } else
+#endif
+ file_header->mode |= S_IFREG;
+ break;
+ case '2':
+ file_header->mode |= S_IFLNK;
+ break;
+ case '3':
+ file_header->mode |= S_IFCHR;
+ break;
+ case '4':
+ file_header->mode |= S_IFBLK;
+ break;
+ case '5':
+ file_header->mode |= S_IFDIR;
+ break;
+ case '6':
+ file_header->mode |= S_IFIFO;
+ break;
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ case 'L':
+ /* free: paranoia: tar with several consecutive longnames */
+ free(longname);
+ /* For paranoia reasons we allocate extra NUL char */
+ longname = xzalloc(file_header->size + 1);
+ /* We read ASCIZ string, including NUL */
+ xread(archive_handle->src_fd, longname, file_header->size);
+ archive_handle->offset += file_header->size;
+ /* return get_header_tar(archive_handle); */
+ /* gcc 4.1.1 didn't optimize it into jump */
+ /* so we will do it ourself, this also saves stack */
+ goto again;
+ case 'K':
+ free(linkname);
+ linkname = xzalloc(file_header->size + 1);
+ xread(archive_handle->src_fd, linkname, file_header->size);
+ archive_handle->offset += file_header->size;
+ /* return get_header_tar(archive_handle); */
+ goto again;
+ case 'D': /* GNU dump dir */
+ case 'M': /* Continuation of multi volume archive */
+ case 'N': /* Old GNU for names > 100 characters */
+ case 'S': /* Sparse file */
+ case 'V': /* Volume header */
+#endif
+ case 'g': /* pax global header */
+ case 'x': { /* pax extended header */
+ off_t sz;
+ bb_error_msg("warning: skipping header '%c'", tar.typeflag);
+ sz = (file_header->size + 511) & ~(off_t)511;
+ archive_handle->offset += sz;
+ sz >>= 9; /* sz /= 512 but w/o contortions for signed div */
+ while (sz--)
+ xread(archive_handle->src_fd, &tar, 512);
+ /* return get_header_tar(archive_handle); */
+ goto again_after_align;
+ }
+ default:
+ bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
+ }
+
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ if (longname) {
+ file_header->name = longname;
+ longname = NULL;
+ }
+ if (linkname) {
+ file_header->link_name = linkname;
+ linkname = NULL;
+ }
+#endif
+ if (!strncmp(file_header->name, "/../"+1, 3)
+ || strstr(file_header->name, "/../")
+ ) {
+ bb_error_msg_and_die("name with '..' encountered: '%s'",
+ file_header->name);
+ }
+
+ /* Strip trailing '/' in directories */
+ /* Must be done after mode is set as '/' is used to check if it's a directory */
+ cp = last_char_is(file_header->name, '/');
+
+ if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+ archive_handle->action_header(archive_handle->file_header);
+ /* Note that we kill the '/' only after action_header() */
+ /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */
+ if (cp) *cp = '\0';
+ archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
+ archive_handle->action_data(archive_handle);
+ llist_add_to(&(archive_handle->passed), file_header->name);
+ } else {
+ data_skip(archive_handle);
+ free(file_header->name);
+ }
+ archive_handle->offset += file_header->size;
+
+ free(file_header->link_name);
+ /* Do not free(file_header->name)! */
+
+ return EXIT_SUCCESS;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_bz2.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_bz2.c
new file mode 100644
index 0000000..d8715c0
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_bz2.c
@@ -0,0 +1,20 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+char get_header_tar_bz2(archive_handle_t *archive_handle)
+{
+ /* Can't lseek over pipes */
+ archive_handle->seek = seek_by_read;
+
+ archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompressStream);
+ archive_handle->offset = 0;
+ while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;
+
+ /* Can only do one file at a time */
+ return EXIT_FAILURE;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_gz.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_gz.c
new file mode 100644
index 0000000..1f07e4e
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_gz.c
@@ -0,0 +1,31 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+char get_header_tar_gz(archive_handle_t *archive_handle)
+{
+ unsigned char magic[2];
+
+ /* Can't lseek over pipes */
+ archive_handle->seek = seek_by_read;
+
+ xread(archive_handle->src_fd, &magic, 2);
+ if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
+ bb_error_msg_and_die("invalid gzip magic");
+ }
+
+ check_header_gzip_or_die(archive_handle->src_fd);
+
+ archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
+ archive_handle->offset = 0;
+ while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;
+
+ /* Can only do one file at a time */
+ return EXIT_FAILURE;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_lzma.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_lzma.c
new file mode 100644
index 0000000..06b8daa
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/get_header_tar_lzma.c
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Small lzma deflate implementation.
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
+ *
+ * Licensed under GPL v2, see file LICENSE in this tarball for details.
+ */
+
+#include "unarchive.h"
+
+char get_header_tar_lzma(archive_handle_t * archive_handle)
+{
+ /* Can't lseek over pipes */
+ archive_handle->seek = seek_by_read;
+
+ archive_handle->src_fd = open_transformer(archive_handle->src_fd, unlzma);
+ archive_handle->offset = 0;
+ while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;
+
+ /* Can only do one file at a time */
+ return EXIT_FAILURE;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/header_list.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/header_list.c
new file mode 100644
index 0000000..fb461a6
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/header_list.c
@@ -0,0 +1,11 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <stdio.h>
+#include "unarchive.h"
+
+void header_list(const file_header_t *file_header)
+{
+ puts(file_header->name);
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/header_skip.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/header_skip.c
new file mode 100644
index 0000000..53242e0
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/header_skip.c
@@ -0,0 +1,10 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <stdio.h>
+#include "unarchive.h"
+
+void header_skip(const file_header_t *file_header ATTRIBUTE_UNUSED)
+{
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/header_verbose_list.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/header_verbose_list.c
new file mode 100644
index 0000000..7b97e52
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/header_verbose_list.c
@@ -0,0 +1,31 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void header_verbose_list(const file_header_t *file_header)
+{
+ struct tm *mtime = localtime(&(file_header->mtime));
+
+ printf("%s %d/%d %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
+ bb_mode_string(file_header->mode),
+ file_header->uid,
+ file_header->gid,
+ file_header->size,
+ 1900 + mtime->tm_year,
+ 1 + mtime->tm_mon,
+ mtime->tm_mday,
+ mtime->tm_hour,
+ mtime->tm_min,
+ mtime->tm_sec,
+ file_header->name);
+
+ if (file_header->link_name) {
+ printf(" -> %s", file_header->link_name);
+ }
+ /* putchar isnt used anywhere else i dont think */
+ puts("");
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/init_handle.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/init_handle.c
new file mode 100644
index 0000000..309d329
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/init_handle.c
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+archive_handle_t *init_handle(void)
+{
+ archive_handle_t *archive_handle;
+
+ /* Initialize default values */
+ archive_handle = xzalloc(sizeof(archive_handle_t));
+ archive_handle->file_header = xzalloc(sizeof(file_header_t));
+ archive_handle->action_header = header_skip;
+ archive_handle->action_data = data_skip;
+ archive_handle->filter = filter_accept_all;
+ archive_handle->seek = seek_by_jump;
+
+ return archive_handle;
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/open_transformer.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/open_transformer.c
new file mode 100644
index 0000000..456d3e9
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/open_transformer.c
@@ -0,0 +1,44 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "libbb.h"
+
+#include "unarchive.h"
+
+/* transformer(), more than meets the eye */
+int open_transformer(int src_fd,
+ USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd))
+{
+ int fd_pipe[2];
+ int pid;
+
+ if (pipe(fd_pipe) != 0) {
+ bb_perror_msg_and_die("can't create pipe");
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ bb_perror_msg_and_die("fork failed");
+ }
+
+ if (pid == 0) {
+ /* child process */
+ close(fd_pipe[0]); /* We don't wan't to read from the parent */
+ // FIXME: error check?
+ transformer(src_fd, fd_pipe[1]);
+ close(fd_pipe[1]); /* Send EOF */
+ close(src_fd);
+ exit(0);
+ /* notreached */
+ }
+
+ /* parent process */
+ close(fd_pipe[1]); /* Don't want to write to the child */
+
+ return fd_pipe[0];
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_jump.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_jump.c
new file mode 100644
index 0000000..d605f61
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_jump.c
@@ -0,0 +1,24 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void seek_by_jump(const archive_handle_t *archive_handle, const unsigned int amount)
+{
+ if (lseek(archive_handle->src_fd, (off_t) amount, SEEK_CUR) == (off_t) -1) {
+#ifdef CONFIG_FEATURE_UNARCHIVE_TAPE
+ if (errno == ESPIPE) {
+ seek_by_read(archive_handle, amount);
+ } else
+#endif
+ bb_perror_msg_and_die("seek failure");
+ }
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_read.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_read.c
new file mode 100644
index 0000000..e46af48
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/seek_by_read.c
@@ -0,0 +1,18 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+
+#include "unarchive.h"
+#include "libbb.h"
+
+/* If we are reading through a pipe(), or from stdin then we can't lseek,
+ * we must read and discard the data to skip over it.
+ */
+void seek_by_read(const archive_handle_t *archive_handle, const unsigned int jump_size)
+{
+ if (jump_size)
+ bb_copyfd_exact_size(archive_handle->src_fd, -1, jump_size);
+}
diff --git a/i/pc104/initrd/conf/busybox/archival/libunarchive/unpack_ar_archive.c b/i/pc104/initrd/conf/busybox/archival/libunarchive/unpack_ar_archive.c
new file mode 100644
index 0000000..6a84ae8
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/archival/libunarchive/unpack_ar_archive.c
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+void unpack_ar_archive(archive_handle_t *ar_archive)
+{
+ char magic[7];
+
+ xread(ar_archive->src_fd, magic, 7);
+ if (strncmp(magic, "!<arch>", 7) != 0) {
+ bb_error_msg_and_die("invalid ar magic");
+ }
+ ar_archive->offset += 7;
+
+ while (get_header_ar(ar_archive) == EXIT_SUCCESS);
+}