#include "image.h" #include /* write to b the result of decompressing c with the algorithm described in image(6), using w as scratch space with sliding window size NMEM */ int decompress(Biobuf *b, uchar *c, int clen) { uchar w[2*NMEM]; uchar *u, *we, *ce, *p, *pe; int n, o; u = w; we = w + 2*NMEM; ce = c + clen; while(c < ce) { if(*c & 0x80) { n = (*c & 0x7F) + 1; if(c + n > ce) { werrstr("truncated cdata"); return -1; } /* flush and slide the window if necessary */ if(u + n > we) { if(Bwrite(b, w, NMEM) < NMEM) sysfatal("write: %r"); memmove(w, w+NMEM, u - (w+NMEM)); u -= NMEM; } memmove(u, c+1, n); u += n; c += 1 + n; } else { if(c + 1 > ce) { werrstr("truncated code word"); return -1; } n = ((*c & 0x7C) >> 2) + 3; o = ((*c & 0x3) << 8 | *(c+1)) + 1; if(u - o < w) { werrstr("invalid offset"); return -1; } /* flush and slide the window if necessary */ if(u + n > we) { if(Bwrite(b, w, NMEM) < NMEM) sysfatal("write: %r"); memmove(w, w+NMEM, u - (w+NMEM)); u -= NMEM; } p = u-o; pe = p + n; while(p < pe) *u++ = *p++; c += 2; } } if(Bwrite(b, w, u-w) != u-w) sysfatal("write: %r"); return 0; } void usage(void) { fprint(2, "usage: %s hdr.r.max.y) sysfatal("line %d: out of sequence next y: %d", y, nexty); csz = atoi((char *)cbuf + 12); if(csz > ncblock || csz < 0) sysfatal("line %d: unusual cblock size: %d/%d", y, csz, ncblock); if((n = Bread(&bin, cbuf, csz)) != csz) { if(n < 0) sysfatal("line %d: cblock: %r", y); sysfatal("line %d: cblock: short read: %d/%d", y, n, csz); } if(decompress(&bout, cbuf, csz) < 0) sysfatal("line %d: %r", y); } exits(nil); } /* image(6) /sys/src/libmemdraw/cread.c /sys/src/libdraw/computil.c /sys/src/libmemdraw/cload.c */