⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zipfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 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 + -