duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

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:
Mfs/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; +}