commit 1bfe2f94456c9d9f816b11019a7b200aabb800f6
parent cd8b8d31d8b51f443d691af3339d86841055b8b6
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Mon, 28 Nov 2022 14:38:31 -0500
ar/ungz: finished porting the code
it compiles, but it doesn't work yet. there's probably a few CC bugs lurking in
there.
Diffstat:
M | fs/ar/ungz.c | | | 166 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
1 file changed, 152 insertions(+), 14 deletions(-)
diff --git a/fs/ar/ungz.c b/fs/ar/ungz.c
@@ -3,7 +3,7 @@
*/
typedef unsigned int size_t;
-typedef unsigned int long;
+typedef int long;
/*
* Maximums for allocations and loops. It is not useful to change these --
@@ -417,7 +417,7 @@ int fixed(state *s)
symbol = symbol + 1;
}
- construct(lencode, lengths, FIXLCODES);
+ construct(&lencode, lengths, FIXLCODES);
/* distance table */
for (symbol = 0; symbol < MAXDCODES; symbol = symbol + 1)
@@ -425,10 +425,10 @@ int fixed(state *s)
lengths[symbol] = 5;
}
- construct(distcode, lengths, MAXDCODES);
+ construct(&distcode, lengths, MAXDCODES);
/* decode data until end-of-block code */
- hold = codes(s, lencode, distcode);
+ hold = codes(s, &lencode, &distcode);
return hold;
}
@@ -560,14 +560,14 @@ static int dynamic(state *s)
}
/* build huffman table for code lengths codes (use lencode temporarily) */
- err = construct(lencode, lengths, 19);
+ err = construct(&lencode, lengths, 19);
if (err != 0) return -4; /* require complete code set here */
/* read length/literal and distance code length tables */
index = 0;
while (index < (nlen + ndist))
{
- symbol = decode(s, lencode);
+ symbol = decode(s, &lencode);
if (symbol < 0) return symbol; /* invalid symbol */
if (symbol < 16) /* length in 0..15 */
@@ -602,26 +602,144 @@ static int dynamic(state *s)
if (lengths[256] == 0) return -9;
/* build huffman table for literal/length codes */
- err = construct(lencode, lengths, nlen);
+ err = construct(&lencode, lengths, nlen);
/* incomplete code ok only for single length 1 code */
if (err < 0) return -7;
- // TODO: compile error from here!
- // if((0 != err) && (nlen != (lencode->count[0] + lencode->count[1]))) return -7;
+ if((0 != err) && (nlen != (lencode.count[0] + lencode.count[1]))) return -7;
/* build huffman table for distance codes */
- //set = lengths + nlen;
- //err = construct(distcode, set, ndist);
+ set = lengths + nlen;
+ err = construct(&distcode, set, ndist);
/* incomplete code ok only for single length 1 code */
- //if (err < 0) return -8;
- //if((0 != err) && (ndist != (distcode->count[0] + distcode->count[1]))) return -8;
+ if (err < 0) return -8;
+ if((0 != err) && (ndist != (distcode.count[0] + distcode.count[1]))) return -8;
/* decode data until end-of-block code */
- //hold = codes(s, lencode, distcode);
+ hold = codes(s, &lencode, &distcode);
return hold;
}
+/*
+ * Inflate source to dest. On return, destlen and sourcelen are updated to the
+ * size of the uncompressed data and the size of the deflate data respectively.
+ * On success, the return value of puff() is zero. If there is an error in the
+ * source data, i.e. it is not in the deflate format, then a negative value is
+ * returned. If there is not enough input available or there is not enough
+ * output space, then a positive error is returned. In that case, destlen and
+ * sourcelen are not updated to facilitate retrying from the beginning with the
+ * provision of more input data or more output space. In the case of invalid
+ * inflate data (a negative error), the dest and source pointers are updated to
+ * facilitate the debugging of deflators.
+ *
+ * puff() also has a mode to determine the size of the uncompressed output with
+ * no output written. For this dest must be (unsigned char *)0. In this case,
+ * the input value of *destlen is ignored, and on return *destlen is set to the
+ * size of the uncompressed output.
+ *
+ * The return codes are:
+ *
+ * 2: available inflate data did not terminate
+ * 1: output space exhausted before completing inflate
+ * 0: successful inflate
+ * -1: invalid block type (type == 3)
+ * -2: stored block length did not match one's complement
+ * -3: dynamic block code description: too many length or distance codes
+ * -4: dynamic block code description: code lengths codes incomplete
+ * -5: dynamic block code description: repeat lengths with no first length
+ * -6: dynamic block code description: repeat more than specified lengths
+ * -7: dynamic block code description: invalid literal/length code lengths
+ * -8: dynamic block code description: invalid distance code lengths
+ * -9: dynamic block code description: missing end-of-block code
+ * -10: invalid literal/length or distance code in fixed or dynamic block
+ * -11: distance is too far back in fixed or dynamic block
+ *
+ * Format notes:
+ *
+ * - Three bits are read for each block to determine the kind of block and
+ * whether or not it is the last block. Then the block is decoded and the
+ * process repeated if it was not the last block.
+ *
+ * - The leftover bits in the last byte of the deflate data after the last
+ * block (if it was a fixed or dynamic block) are undefined and have no
+ * expected values to check.
+ */
+
+struct puffer
+{
+ int error;
+ size_t destlen;
+ size_t sourcelen;
+};
+
+static puffer _puffer;
+
+puffer* puff(char* dest, size_t destlen, char* source, size_t sourcelen)
+{
+ state s; /* input/output state */
+ int last;
+ int type; /* block information */
+ int err; /* return value */
+
+ /* initialize output state */
+ s.out = dest;
+ s.outlen = destlen; /* ignored if dest is NIL */
+ s.outcnt = 0;
+
+ /* initialize input state */
+ s.in = source;
+ s.inlen = sourcelen;
+ s.incnt = 0;
+ s.bitbuf = 0;
+ s.bitcnt = 0;
+
+ /* process blocks until last block or error */
+ do
+ {
+ last = bits(&s, 1); /* one if last block */
+ type = bits(&s, 2); /* block type 0..3 */
+
+ if(0 == type)
+ {
+ err = stored(&s);
+ }
+ else if(1 == type)
+ {
+ err = fixed(&s);
+ }
+ else if(2 == type)
+ {
+ err = dynamic(&s);
+ }
+ else err = -1;
+
+ if (err != 0) break; /* return with error */
+ } while (!last);
+
+ /* update the lengths and return */
+ _puffer.error = err;
+ _puffer.destlen = s.outcnt;
+ _puffer.sourcelen = s.incnt;
+ return &_puffer;
+}
+
+void write_blob(char* s, int start, int len, File *f)
+{
+ char* table = "0123456789ABCDEF";
+ int i = s[start] & $FF;
+
+ if(start > len) return;
+
+ fputc(table[(i >> 4)], f);
+ fputc(table[(i & $F)], f);
+ fputc(' ', f);
+
+ if(start == len) fputc($0a, f);
+ else fputc(' ', f);
+ write_blob(s, start + 1, len, f);
+}
+
#define FTEXT $01
#define FHCRC $02
#define FEXTRA $04
@@ -793,3 +911,23 @@ gz* loadgz(char* name)
fclose(f);
return r;
}
+
+int ungz(char *fname)
+{
+ puffer* ret;
+ char* name;
+ char* buffer;
+ gz* in;
+ File *out;
+
+ in = loadgz(name);
+
+ if (in == NULL)
+ {
+ fputs("memory allocation failure\nDidn't read file\n", ConsoleOut());
+ abort();
+ }
+
+ ret = puff(0, 0, in->block, in->ISIZE);
+ return 0;
+}