123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <flate.h>
- #include <auth.h>
- #include <fcall.h>
- #include <ctype.h>
- #include "tapefs.h"
- #include "zip.h"
- #define FORCE_LOWER 1 /* force filenames to lower case */
- #define MUNGE_CR 1 /* replace '\r\n' with ' \n' */
- #define High64 (1LL<<63)
- /*
- * File system for zip archives (read-only)
- */
- enum {
- IS_MSDOS = 0, /* creator OS (interpretation of external flags) */
- IS_RDONLY = 1, /* file was readonly (external flags) */
- IS_TEXT = 1, /* file was text (internal flags) */
- };
- typedef struct Block Block;
- struct Block{
- uchar *pos;
- uchar *limit;
- };
- static Biobuf *bin;
- static ulong *crctab;
- static ulong crc;
- static int findCDir(Biobuf *);
- static int header(Biobuf *, ZipHead *);
- static int cheader(Biobuf *, ZipHead *);
- static void trailer(Biobuf *, ZipHead *);
- static char *getname(Biobuf *, int);
- static int blwrite(void *, void *, int);
- static ulong get4(Biobuf *);
- static int get2(Biobuf *);
- static int get1(Biobuf *);
- static long msdos2time(int, int);
- void
- populate(char *name)
- {
- char *p;
- Fileinf f;
- ZipHead zh;
- int ok, entries;
- crctab = mkcrctab(ZCrcPoly);
- ok = inflateinit();
- if(ok != FlateOk)
- sysfatal("inflateinit failed: %s", flateerr(ok));
- bin = Bopen(name, OREAD);
- if (bin == nil)
- error("Can't open argument file");
- entries = findCDir(bin);
- if(entries < 0)
- sysfatal("empty file");
- while(entries-- > 0){
- memset(&zh, 0, sizeof(zh));
- if(!cheader(bin, &zh))
- break;
- f.addr = zh.off;
- if(zh.iattr & IS_TEXT)
- f.addr |= High64;
- f.mode = (zh.madevers == IS_MSDOS && zh.eattr & IS_RDONLY)? 0444: 0644;
- if (zh.meth == 0 && zh.uncsize == 0){
- p = strchr(zh.file, '\0');
- if(p > zh.file && p[-1] == '/')
- f.mode |= (DMDIR | 0111);
- }
- f.uid = 0;
- f.gid = 0;
- f.size = zh.uncsize;
- f.mdate = msdos2time(zh.modtime, zh.moddate);
- f.name = zh.file + ((zh.file[0] == '/')? 1: 0);
- poppath(f, 1);
- free(zh.file);
- }
- return ;
- }
- void
- dotrunc(Ram *r)
- {
- USED(r);
- }
- void
- docreate(Ram *r)
- {
- USED(r);
- }
- char *
- doread(Ram *r, vlong off, long cnt)
- {
- int i, err;
- Block bs;
- ZipHead zh;
- static Qid oqid;
- static char buf[Maxbuf];
- static uchar *cache = nil;
- if (cnt > Maxbuf)
- sysfatal("file too big (>%d)", Maxbuf);
- if (Bseek(bin, r->addr & 0x7FFFFFFFFFFFFFFFLL, 0) < 0)
- sysfatal("seek failed");
- memset(&zh, 0, sizeof(zh));
- if (!header(bin, &zh))
- sysfatal("cannot get local header");
- switch(zh.meth){
- case 0:
- if (Bseek(bin, off, 1) < 0)
- sysfatal("seek failed");
- if (Bread(bin, buf, cnt) != cnt)
- sysfatal("read failed");
- break;
- case 8:
- if (r->qid.path != oqid.path){
- oqid = r->qid;
- if (cache)
- free(cache);
- cache = emalloc(r->ndata);
- bs.pos = cache;
- bs.limit = cache+r->ndata;
- if ((err = inflate(&bs, blwrite, bin, (int(*)(void*))Bgetc)) != FlateOk)
- sysfatal("inflate failed - %s", flateerr(err));
- if (blockcrc(crctab, crc, cache, r->ndata) != zh.crc)
- fprint(2, "%s - crc failed", r->name);
- if ((r->addr & High64) && MUNGE_CR){
- for (i = 0; i < r->ndata -1; i++)
- if (cache[i] == '\r' && cache[i +1] == '\n')
- cache[i] = ' ';
- }
- }
- memcpy(buf, cache+off, cnt);
- break;
- default:
- sysfatal("%d - unsupported compression method", zh.meth);
- break;
- }
-
- return buf;
- }
- void
- popdir(Ram *r)
- {
- USED(r);
- }
- void
- dowrite(Ram *r, char *buf, long off, long cnt)
- {
- USED(r); USED(buf); USED(off); USED(cnt);
- }
- int
- dopermw(Ram *r)
- {
- USED(r);
- return 0;
- }
- /*************************************************/
- static int
- findCDir(Biobuf *bin)
- {
- vlong ecoff;
- long off;
- int entries, zclen;
- ecoff = Bseek(bin, -ZECHeadSize, 2);
- if(ecoff < 0)
- sysfatal("can't seek to header");
- if(get4(bin) != ZECHeader)
- sysfatal("bad magic number on directory");
- get2(bin);
- get2(bin);
- get2(bin);
- entries = get2(bin);
- get4(bin);
- off = get4(bin);
- zclen = get2(bin);
- while(zclen-- > 0)
- get1(bin);
- if(Bseek(bin, off, 0) != off)
- sysfatal("can't seek to contents");
- return entries;
- }
- static int
- header(Biobuf *bin, ZipHead *zh)
- {
- ulong v;
- int flen, xlen;
- v = get4(bin);
- if(v != ZHeader){
- if(v == ZCHeader)
- return 0;
- sysfatal("bad magic on local header");
- }
- zh->extvers = get1(bin);
- zh->extos = get1(bin);
- zh->flags = get2(bin);
- zh->meth = get2(bin);
- zh->modtime = get2(bin);
- zh->moddate = get2(bin);
- zh->crc = get4(bin);
- zh->csize = get4(bin);
- zh->uncsize = get4(bin);
- flen = get2(bin);
- xlen = get2(bin);
- zh->file = getname(bin, flen);
- while(xlen-- > 0)
- get1(bin);
- return 1;
- }
- static int
- cheader(Biobuf *bin, ZipHead *zh)
- {
- ulong v;
- int flen, xlen, fclen;
- v = get4(bin);
- if(v != ZCHeader){
- if(v == ZECHeader)
- return 0;
- sysfatal("bad magic number in file");
- }
- zh->madevers = get1(bin);
- zh->madeos = get1(bin);
- zh->extvers = get1(bin);
- zh->extos = get1(bin);
- zh->flags = get2(bin);
- zh->meth = get2(bin);
- zh->modtime = get2(bin);
- zh->moddate = get2(bin);
- zh->crc = get4(bin);
- zh->csize = get4(bin);
- zh->uncsize = get4(bin);
- flen = get2(bin);
- xlen = get2(bin);
- fclen = get2(bin);
- get2(bin); /* disk number start */
- zh->iattr = get2(bin); /* 1 == is-text-file */
- zh->eattr = get4(bin); /* 1 == readonly-file */
- zh->off = get4(bin);
- zh->file = getname(bin, flen);
- while(xlen-- > 0)
- get1(bin);
- while(fclen-- > 0)
- get1(bin);
- return 1;
- }
- static int
- blwrite(void *vb, void *buf, int n)
- {
- Block *b = vb;
- if(n > b->limit - b->pos)
- n = b->limit - b->pos;
- memmove(b->pos, buf, n);
- b->pos += n;
- return n;
- }
- static void
- trailer(Biobuf *bin, ZipHead *zh)
- {
- if(zh->flags & ZTrailInfo){
- zh->crc = get4(bin);
- zh->csize = get4(bin);
- zh->uncsize = get4(bin);
- }
- }
- static char*
- getname(Biobuf *bin, int len)
- {
- char *s;
- int i, c;
- s = emalloc(len + 1);
- for(i = 0; i < len; i++){
- c = get1(bin);
- if(FORCE_LOWER)
- c = tolower(c);
- s[i] = c;
- }
- s[i] = '\0';
- return s;
- }
- static ulong
- get4(Biobuf *b)
- {
- ulong v;
- int i, c;
- v = 0;
- for(i = 0; i < 4; i++){
- c = Bgetc(b);
- if(c < 0)
- sysfatal("unexpected eof");
- v |= c << (i * 8);
- }
- return v;
- }
- static int
- get2(Biobuf *b)
- {
- int i, c, v;
- v = 0;
- for(i = 0; i < 2; i++){
- c = Bgetc(b);
- if(c < 0)
- sysfatal("unexpected eof");
- v |= c << (i * 8);
- }
- return v;
- }
- static int
- get1(Biobuf *b)
- {
- int c;
- c = Bgetc(b);
- if(c < 0)
- sysfatal("unexpected eof");
- return c;
- }
- static long
- msdos2time(int time, int date)
- {
- Tm tm;
- tm.hour = time >> 11;
- tm.min = (time >> 5) & 63;
- tm.sec = (time & 31) << 1;
- tm.year = 80 + (date >> 9);
- tm.mon = ((date >> 5) & 15) - 1;
- tm.mday = date & 31;
- tm.zone[0] = '\0';
- tm.yday = 0;
- return tm2sec(&tm);
- }
|