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

📄 dossubs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <auth.h>#include <fcall.h>#include "iotrack.h"#include "dat.h"#include "fns.h"static uchar	isdos[256];intisdosfs(uchar *buf){	/*	 * When dynamic disc managers move the disc partition, 	 * they make it start with 0xE9.	 */	if(buf[0] == 0xE9)		return 1;	/*	 * Check if the jump displacement (magic[1]) is too short for a FAT.	 */	if(buf[0] == 0xEB && buf[2] == 0x90 && buf[1] >= 0x30)		return 1;	return 0;}intdosfs(Xfs *xf){	Iosect *p, *p1;	Dosboot *b;	Fatinfo *fi;	Dosboot32 *b32;	Dosbpb *bp;	long fisec, extflags;	int i;	if(!isdos['a']){		for(i = 'a'; i <= 'z'; i++)			isdos[i] = 1;		for(i = 'A'; i <= 'Z'; i++)			isdos[i] = 1;		for(i = '0'; i <= '9'; i++)			isdos[i] = 1;		isdos['$'] = 1;		isdos['%'] = 1;		isdos['''] = 1;		isdos['-'] = 1;		isdos['_'] = 1;		isdos['@'] = 1;		isdos['~'] = 1;		isdos['`'] = 1;		isdos['!'] = 1;		isdos['('] = 1;		isdos[')'] = 1;		isdos['{'] = 1;		isdos['}'] = 1;		isdos['^'] = 1;		isdos['#'] = 1;		isdos['&'] = 1;	}	p = getsect(xf, 0);	if(p == 0)		return -1;	b = (Dosboot*)p->iobuf;	if(b->clustsize == 0 || isdosfs(p->iobuf) == 0){		putsect(p);		return -1;	}	bp = malloc(sizeof(Dosbpb));	memset(bp, 0, sizeof(Dosbpb));	/* clear lock */	xf->ptr = bp;	xf->fmt = 1;	bp->sectsize = GSHORT(b->sectsize);	bp->clustsize = b->clustsize;	bp->nresrv = GSHORT(b->nresrv);	bp->nfats = b->nfats;	bp->rootsize = GSHORT(b->rootsize);	bp->volsize = GSHORT(b->volsize);	if(bp->volsize == 0)		bp->volsize = GLONG(b->bigvolsize);	bp->mediadesc = b->mediadesc;	bp->fatsize = GSHORT(b->fatsize);	bp->fataddr = GSHORT(b->nresrv);	bp->fatinfo = 0;	if(bp->fatsize == 0){	/* is FAT32 */		if(chatty)			bootsecdump32(2, xf, (Dosboot32*)b);		xf->isfat32 = 1;		b32 = (Dosboot32*)b;		bp->fatsize = GLONG(b32->fatsize32);		if(bp->fatsize == 0){			putsect(p);			return -1;		}		bp->dataaddr = bp->fataddr + bp->nfats*bp->fatsize;		bp->rootaddr = 0;		bp->rootstart = GLONG(b32->rootstart);		/*		 * disable fat mirroring?		 */		extflags = GSHORT(b32->extflags);		if(extflags & 0x0080){			for(i = 0; i < 4; i++){				if(extflags & (1 << i)){					bp->fataddr += i * bp->fatsize;					bp->nfats = 1;					break;				}			}		}		/*		 * fat free list info		 */		bp->freeptr = FATRESRV;		fisec = GSHORT(b32->infospec);		if(fisec != 0 && fisec < GSHORT(b32->nresrv)){			p1 = getsect(xf, fisec);			if(p1 != nil){				fi = (Fatinfo*)p1->iobuf;				if(GLONG(fi->sig1) == FATINFOSIG1 && GLONG(fi->sig) == FATINFOSIG){					bp->fatinfo = fisec;					bp->freeptr = GLONG(fi->nextfree);					bp->freeclusters = GLONG(fi->freeclust);					chat("fat info: %ld free clusters, next free %ld\n", bp->freeclusters, bp->freeptr);				}				putsect(p1);			}		}	}else{		if(chatty)			bootdump(2, b);		bp->rootaddr = bp->fataddr + bp->nfats*bp->fatsize;		bp->rootstart = 0;		i = bp->rootsize*DOSDIRSIZE + bp->sectsize-1;		i /= bp->sectsize;		bp->dataaddr = bp->rootaddr + i;		bp->freeptr = FATRESRV;	}	bp->fatclusters = FATRESRV+(bp->volsize - bp->dataaddr)/bp->clustsize;	if(xf->isfat32)		bp->fatbits = 32;	else if(bp->fatclusters < 4087)		bp->fatbits = 12;	else		bp->fatbits = 16;	chat("fatbits=%d (%d clusters)...", bp->fatbits, bp->fatclusters);	for(i=0; i<b->nfats; i++)		chat("fat %d: %ld...", i, bp->fataddr+i*bp->fatsize);	chat("root: %ld...", bp->rootaddr);	chat("data: %ld...", bp->dataaddr);	putsect(p);	return 0;}/* * initialize f to the root directory * this file has no Dosdir entry, * so we special case it all over. */voidrootfile(Xfile *f){	Dosptr *dp;	dp = f->ptr;	memset(dp, 0, sizeof(Dosptr));	dp->prevaddr = -1;}intisroot(ulong addr){	return addr == 0;}intgetfile(Xfile *f){	Dosptr *dp;	Iosect *p;	dp = f->ptr;	if(dp->p)		panic("getfile");	p = getsect(f->xf, dp->addr);	if(p == nil)		return -1;	/*	 * we could also make up a Dosdir for the root	 */	dp->d = nil;	if(!isroot(dp->addr)){		if(f->qid.path != QIDPATH(dp)){			chat("qid mismatch f=%#llux d=%#lux...", f->qid.path, QIDPATH(dp));			putsect(p);			errno = Enonexist;			return -1;		}		dp->d = (Dosdir *)&p->iobuf[dp->offset];	}	dp->p = p;	return 0;}voidputfile(Xfile *f){	Dosptr *dp;	dp = f->ptr;	if(!dp->p)		panic("putfile");	putsect(dp->p);	dp->p = nil;	dp->d = nil;}longgetstart(Xfs *xf, Dosdir *d){	long start;	start = GSHORT(d->start);	if(xf->isfat32)		start |= GSHORT(d->hstart)<<16;	return start;}voidputstart(Xfs *xf, Dosdir *d, long start){	PSHORT(d->start, start);	if(xf->isfat32)		PSHORT(d->hstart, start>>16);}/* * return the disk cluster for the iclust cluster in f */longfileclust(Xfile *f, long iclust, int cflag){	Dosbpb *bp;	Dosptr *dp;	Dosdir *d;	long start, clust, nskip, next;	bp = f->xf->ptr;	dp = f->ptr;	d = dp->d;	next = 0;	/* 	 * asking for the cluster of the root directory	 * is not a well-formed question, since the root directory	 * does not begin on a cluster boundary.	 */	if(!f->xf->isfat32 && isroot(dp->addr))		return -1;	if(f->xf->isfat32 && isroot(dp->addr)){		start = bp->rootstart;	}else{		start = getstart(f->xf, d);		if(start == 0){			if(!cflag)				return -1;			mlock(bp);			start = falloc(f->xf);			unmlock(bp);			if(start <= 0)				return -1;			puttime(d, 0);			putstart(f->xf, d, start);			dp->p->flags |= BMOD;			dp->clust = 0;		}	}	if(dp->clust == 0 || iclust < dp->iclust){		clust = start;		nskip = iclust;	}else{		clust = dp->clust;		nskip = iclust - dp->iclust;	}	if(chatty > 1 && nskip > 0)		chat("clust %#lx, skip %ld...", clust, nskip);	if(clust <= 0)		return -1;	if(nskip > 0){		mlock(bp);		while(--nskip >= 0){			next = getfat(f->xf, clust);			if(chatty > 1)				chat("->%#lx", next);			if(next > 0){				clust = next;				continue;			}else if(!cflag)				break;			if(d && (d->attr&DSYSTEM)){				next = cfalloc(f);				if(next < 0)					break;				/* cfalloc will call putfat for us, since clust may change */			} else {				next = falloc(f->xf);				if(next < 0)					break;				putfat(f->xf, clust, next);			}			clust = next;		}		unmlock(bp);		if(next <= 0)			return -1;		dp->clust = clust;		dp->iclust = iclust;	}	if(chatty > 1)		chat(" clust(%#lx)=%#lx...", iclust, clust);	return clust;}/* * return the disk sector for the isect disk sector in f  */longfileaddr(Xfile *f, long isect, int cflag){	Dosbpb *bp;	Dosptr *dp;	long clust;	bp = f->xf->ptr;	dp = f->ptr;	if(!f->xf->isfat32 && isroot(dp->addr)){		if(isect*bp->sectsize >= bp->rootsize*DOSDIRSIZE)			return -1;		return bp->rootaddr + isect;	}	clust = fileclust(f, isect/bp->clustsize, cflag);	if(clust < 0)		return -1;	return clust2sect(bp, clust) + isect%bp->clustsize;}/* * translate names */voidfixname(char *buf){	int c;	char *p;	p = buf;	while(c = *p){		if(c == ':' && trspaces)			*p = ' ';		p++;	}}/* * classify the file name as one of  *	Invalid - contains a bad character *	Short - short valid 8.3 name, no lowercase letters *	ShortLower - short valid 8.3 name except for lowercase letters *	Long - long name  */intclassifyname(char *buf){	char *p, *dot;	int c, isextended, is8dot3, islower, ndot;	p = buf;	isextended = 0;	islower = 0;	dot = nil;	ndot = 0;	while(c = (uchar)*p){		if(c&0x80)	/* UTF8 */			isextended = 1;		else if(c == '.'){			dot = p;			ndot++;		}else if(strchr("+,:;=[] ", c))			isextended = 1;		else if(!isdos[c])			return Invalid;		if('a' <= c && c <= 'z')			islower = 1;		p++;	}	is8dot3 = (ndot==0 && p-buf <= 8) || (ndot==1 && dot-buf <= 8 && p-(dot+1) <= 3);		if(!isextended && is8dot3){		if(islower)			return ShortLower;		return Short;	}	return Long;}		/* * make an alias for a valid long file name */voidmkalias(char *name, char *sname, int id){	Rune r;	char *s, *e, sid[10];	int i, esuf, v;	e = strrchr(name, '.');	if(e == nil)		e = strchr(name, '\0');	s = name;	i = 0;	while(s < e && i < 6){		if(isdos[(uchar)*s])			sname[i++] = *s++;		else			s += chartorune(&r, s);	}	v = snprint(sid, 10, "%d", id);	if(i + 1 + v > 8)		i = 8 - 1 - v;	sname[i++] = '~';	strcpy(&sname[i], sid);	i += v;	sname[i++] = '.';	esuf = i + 3;	if(esuf > 12)		panic("bad mkalias");	while(*e && i < esuf){		if(isdos[(uchar)*e])			sname[i++] = *e++;		else			e += chartorune(&r, e);	}	if(sname[i-1] == '.')		i--;	sname[i] = '\0';}/* * check for valid plan 9 names, * rewrite ' ' to ':' */char isfrog[256]={	/*NUL*/	1, 1, 1, 1, 1, 1, 1, 1,	/*BKS*/	1, 1, 1, 1, 1, 1, 1, 1,	/*DLE*/	1, 1, 1, 1, 1, 1, 1, 1,	/*CAN*/	1, 1, 1, 1, 1, 1, 1, 1,/*	[' ']	1,	let's try this -rsc */	['/']	1,	[0x7f]	1,};intnameok(char *elem){	while(*elem) {		if(*elem == ' ' && trspaces)			*elem = ':';		if(isfrog[*(uchar*)elem])			return 0;		elem++;	}	return 1;}/* * look for a directory entry matching name * always searches for long names which match a short name */intsearchdir(Xfile *f, char *name, Dosptr *dp, int cflag, int longtype){	Xfs *xf;	Iosect *p;	Dosbpb *bp;	Dosdir *d;	char buf[261], *bname;	int isect, addr, o, addr1, addr2, prevaddr, prevaddr1, o1, islong, have, need, sum;	xf = f->xf;	bp = xf->ptr;	addr1 = -1;	addr2 = -1;	prevaddr1 = -1;	o1 = 0;	islong = 0;	sum = -1;	need = 1;	if(longtype!=Short && cflag)		need += (utflen(name) + DOSRUNE-1) / DOSRUNE;	memset(dp, 0, sizeof(Dosptr));	dp->prevaddr = -1;	dp->naddr = -1;	dp->paddr = ((Dosptr *)f->ptr)->addr;	dp->poffset = ((Dosptr *)f->ptr)->offset;	have = 0;	addr = -1;	bname = nil;	for(isect=0;; isect++){		prevaddr = addr;		addr = fileaddr(f, isect, cflag);		if(addr < 0)			break;		p = getsect(xf, addr);		if(p == 0)			break;		for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){			d = (Dosdir *)&p->iobuf[o];			if(d->name[0] == 0x00){				chat("end dir(0)...");				putsect(p);				if(!cflag)					return -1;				/*				 * addr1 & o1 are the start of the dirs				 * addr2 is the optional second cluster used if the long name				 * entry does not fit within the addr1 cluster				 *				 * have tells us the number of contiguous free dirs				 * starting at addr1.o1; need are necessary to hold the long name.				 */				if(addr1 < 0){					addr1 = addr;					prevaddr1 = prevaddr;					o1 = o;				}				if(addr2 < 0 && (bp->sectsize-o)/DOSDIRSIZE + have < need){					addr2 = fileaddr(f, isect+1, cflag);					if(addr2 < 0)						goto breakout;				}else if(addr2 < 0)					addr2 = addr;				if(addr2 == addr1)					addr2 = -1;				dp->addr = addr1;				dp->offset = o1;				dp->prevaddr = prevaddr1;				dp->naddr = addr2;				return 0;			}			if(d->name[0] == DOSEMPTY){				if(chatty)					fprint(2, "empty dir\n");				have++;				if(addr1 == -1){					addr1 = addr;					o1 = o;					prevaddr1 = prevaddr;				}				if(addr2 == -1 && have >= need)					addr2 = addr;				continue;			}			have = 0;			if(addr2 == -1)				addr1 = -1;			dirdump(d);			if((d->attr & 0xf) == 0xf){				bname = getnamesect(buf, bname, p->iobuf + o, &islong, &sum, 1);				continue;			}			if(d->attr & DVLABEL){				islong = 0;				continue;			}			if(islong != 1 || sum != aliassum(d) || cistrcmp(bname, name) != 0){				bname = buf;				getname(buf, d);			}			islong = 0;			if(cistrcmp(bname, name) != 0)				continue;			if(chatty)				fprint(2, "found\n");			if(cflag){				putsect(p);				return -1;			}			dp->addr = addr;			dp->prevaddr = prevaddr;			dp->offset = o;			dp->p = p;			dp->d = d;			return 0;		}		putsect(p);	}breakout:	chat("end dir(1)...");	return -1;}intemptydir(Xfile *f){	Xfs *xf = f->xf;	Dosbpb *bp = xf->ptr;	int isect, addr, o;	Iosect *p;	Dosdir *d;	for(isect=0;; isect++){		addr = fileaddr(f, isect, 0);		if(addr < 0)			break;		p = getsect(xf, addr);		if(p == 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -