Let tar extract files > 8G
Ian Wienand
ianw at vmware.com
Thu Dec 11 21:04:53 UTC 2008
Hi,
The 12 octal digits for size give each file a maximum size 8G. GNU
tar encodes sizes larger than this with a base-256 encoding, and marks
the top bit of the size set to indicate this.
I cribbed the base 256 converter from gnu tar sources
Testing - extract a big file
$ ls -l
-rw-r--r-- 1 wienandi mts 10737428480 2008-12-11 12:42 bigfile.tar
wienandi at coopers:/tmp/big$ ./busybox tar xvf bigfile.tar
./bigfile
wienandi at coopers:/tmp/big$ ls -l
-rw-r--r-- 1 wienandi mts 10737418240 2008-12-11 12:33 bigfile
-rw-r--r-- 1 wienandi mts 10737428480 2008-12-11 12:42 bigfile.tar
Thanks,
-i
Index: archival/libunarchive/get_header_tar.c
===================================================================
--- archival/libunarchive/get_header_tar.c (revision 24386)
+++ archival/libunarchive/get_header_tar.c (working copy)
@@ -14,6 +14,37 @@
#include "libbb.h"
#include "unarchive.h"
+/* Extract a number encoded in base-256 */
+static unsigned long long getBase256(char *str, int len)
+{
+#define LG_256 8
+
+ uintmax_t value;
+ char *lim = str + len;
+ /* Parse base-256 output. A nonnegative number N is
+ represented as (256**DIGS)/2 + N; a negative number -N is
+ represented as (256**DIGS) - N, i.e. as two's complement.
+ The representation guarantees that the leading bit is
+ always on, so that we don't confuse this format with the
+ others (assuming ASCII bytes of 8 bits or more). */
+ int signbit = *str & (1 << (LG_256 - 2));
+ uintmax_t topbits = (((uintmax_t) - signbit)
+ << (CHAR_BIT * sizeof (uintmax_t)
+ - LG_256 - (LG_256 - 2)));
+ value = (*str++ & ((1 << (LG_256 - 2)) - 1)) - signbit;
+ for (;;)
+ {
+ value = (value << LG_256) + (unsigned char) *str++;
+ if (str == lim)
+ break;
+ if (((value << LG_256 >> LG_256) | topbits) != value)
+ {
+ bb_error_msg_and_die("Archive base-256 value is out of range");
+ }
+ }
+ return value;
+}
+
/* NB: _DESTROYS_ str[len] character! */
static unsigned long long getOctal(char *str, int len)
{
@@ -234,7 +265,11 @@
file_header->gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL;
#endif
file_header->mtime = GET_OCTAL(tar.mtime);
- file_header->size = GET_OCTAL(tar.size);
+
+ /* Really big (> 8 gig) files have the size encoded in base
+ * 256. The top bit being set tells us this ... */
+ file_header->size = (*tar.size == '\200') ?
+ getBase256(tar.size, sizeof(tar.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 */
More information about the busybox
mailing list