📄 zipfs.c
字号:
#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);voidpopulate(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 ;}voiddotrunc(Ram *r){ USED(r);}voiddocreate(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;}voidpopdir(Ram *r){ USED(r);}voiddowrite(Ram *r, char *buf, long off, long cnt){ USED(r); USED(buf); USED(off); USED(cnt);}intdopermw(Ram *r){ USED(r); return 0;}/*************************************************/static intfindCDir(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 intheader(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 intcheader(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 intblwrite(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 voidtrailer(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 ulongget4(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 intget2(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 intget1(Biobuf *b){ int c; c = Bgetc(b); if(c < 0) sysfatal("unexpected eof"); return c;}static longmsdos2time(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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -