📄 unpack.c
字号:
/* unpack.c: * This code provides the monitor with huffman decompression used * primarily by TFS, but also available as a command in the monitor. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "genlib.h"#if INCLUDE_UNPACK#include "stddefs.h"#include "cli.h"#define NAMELEN 80#define SUF0 '.'#define SUF1 'z'#define US 037#define RS 036#define BUFSIZ 1024#define BLKSIZE BUFSIZ/* variables associated with i/o */static char outbuff[BUFSIZ];/* the dictionary */static short intnodes[25];static char *tree[25];static char characters[256];static int UnpackError;static char *lastwrite;static char *decode();static char *getdict();/* getdict(): * Read in the dictionary portion and build decoding structures * return decode() if successful, 0 otherwise */static char *getdict(char *readptr, char *writeptr){ int c, i, nchildren; int maxlev, inleft; char *inp, *eof; long origsize; /* * check two-byte header * get size of original file, * get number of levels in maxlev, * get number of leaves on level i in intnodes[i], * set tree[i] to point to leaves for level i */ eof = &characters[0]; inleft = BUFSIZ; if (readptr[0] != US) { UnpackError = 1; return(0); } if (readptr[1] == US) { /* does not support old style packing */ UnpackError = 2; return(0); } if (readptr[1] != RS) { UnpackError = 3; return(0); } inp = (char *)&readptr[2]; origsize = 0; for (i=0; i<4; i++) origsize = origsize*256 + ((*inp++) & 0xff); maxlev = *inp++ & 0xff; if (maxlev > 24) { UnpackError = 4; return(0); } for (i=1; i<=maxlev; i++) intnodes[i] = *inp++ & 0377; for (i=1; i<=maxlev; i++) { tree[i] = eof; for (c=intnodes[i]; c>0; c--) { if (eof >= &characters[255]) { UnpackError = 5; return(0); } *eof++ = *inp++; } } *eof++ = *inp++; intnodes[maxlev] += 2; inleft -= inp - (char *)&readptr[0]; if (inleft < 0) { UnpackError = 6; return(0); } /* * convert intnodes[i] to be number of * internal nodes possessed by level i */ nchildren = 0; for (i=maxlev; i>=1; i--) { c = intnodes[i]; intnodes[i] = nchildren /= 2; nchildren += c; } readptr += BUFSIZ; return(decode(readptr,writeptr,inleft,inp,eof,origsize));}/* decode(): * unpack the file * return (readptr-inleft) if successful, 0 otherwise */static char *decode(uchar *rdptr,uchar *wrptr,int inleft,char *inp,char *eof,long origsize){ int bitsleft, c, i, j, k, lev; char *p, *outp; outp = &outbuff[0]; lev = 1; i = 0; while (1) { if (inleft <= 0) { inleft = BUFSIZ; inp = (char *)rdptr; rdptr += BUFSIZ; } if (--inleft < 0) { if(origsize == 0) { lastwrite = (char *)wrptr; return((char *)(rdptr-inleft)); } UnpackError = 7; return(0); } c = *inp++; bitsleft = 8; while (--bitsleft >= 0) { i *= 2; if (c & 0x80) i++; c <<= 1; if ((j = i - intnodes[lev]) >= 0) { p = &tree[lev][j]; if (p == eof) { c = outp - &outbuff[0]; for(k=0;k<c;k++) { *wrptr++ = outbuff[k]; } origsize -= c; if (origsize != 0) { UnpackError = 8; return(0); } lastwrite = (char *)wrptr; return((char *)(rdptr-inleft)); } *outp++ = *p; if (outp == &outbuff[BUFSIZ]) { outp = &outbuff[0]; for(k=0;k<BUFSIZ;k++) { *wrptr++ = outbuff[k]; } origsize -= BUFSIZ; } lev = 1; i = 0; } else lev++; } }}char *UnpackHelp[] = { "Huffman decompressor", "{src} {dest}", 0,};intUnpack(int argc,char *argv[]){ char *src, *dest; char *ret; if (argc != 3) return(CMD_PARAM_ERROR); src = (char *)strtol(argv[1],(char **)0,0); dest = (char *)strtol(argv[2],(char **)0,0); UnpackError = 0; ret = getdict(src,dest); if (UnpackError) printf("Error = %d\n",UnpackError); printf("in size = %d\n",ret-src); if (UnpackError) return(CMD_FAILURE); return(CMD_SUCCESS);}intunpacker(char *src,char *dest,int *insize,int *outsize,int verbose){ char *ret; UnpackError = 0; ret = getdict(src,dest); if (UnpackError && verbose) printf("Unpack error = %d\n",UnpackError); if (UnpackError) return(-1); if (insize) *insize = (int)(ret - src); if (outsize) *outsize = (int)(lastwrite - dest); if (verbose) printf("Insize = %d, outsize = %d\n", (int)(ret-src),(int)(lastwrite-dest)); return(0);}/* Front end to the rest of the unpack() stuff... * Return the size of the decompressed data or -1 if failure. * The same front end API is available if unzip is used instead of unpack. * Note that for the unpacker, srcsize is not needed; but, since it is * needed for unzip, we make the interface the same by having it here. */intdecompress(char *src,int srcsize, char *dest){ int newsize, ret; ret = unpacker(src,dest,0,&newsize,0); if (ret == 0) return(newsize); return(-1);}#endif#if !INCLUDE_DECOMPRESSintdecompress(char *src,int srcsize, char *dest){ printf("ERROR: decompression utilities not installed.\n"); return(-1);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -