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

📄 dossubs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	bp = xf->ptr;	first = 1;	len = utftorunes(longname, name, DOSNAMELEN);	if(chatty){		chat("utftorunes %s =", name);		for(i=0; i<len; i++)			chat(" %.4X", longname[i]);		chat("\n");	}	for(nds = (len + DOSRUNE-1) / DOSRUNE; nds > 0; nds--){		putnamesect(&ndp->p->iobuf[ndp->offset], longname, nds, first, sum);		first = 0;		ndp->offset += 32;		if(ndp->offset == bp->sectsize){			chat("long name moving over sector boundary\n");			ndp->p->flags |= BMOD;			putsect(ndp->p);			ndp->p = nil;			/*			 * switch to the next cluster for a long entry			 * naddr should be set up correctly by searchdir			 */			ndp->prevaddr = ndp->addr;			ndp->addr = ndp->naddr;			ndp->naddr = -1;			if(ndp->addr == -1)				return -1;			ndp->p = getsect(xf, ndp->addr);			if(ndp->p == nil)				return -1;			ndp->offset = 0;			ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset];		}	}	return 0;}longgetfat(Xfs *xf, int n){	Dosbpb *bp = xf->ptr;	Iosect *p;	ulong k, sect;	int o, fb;	if(n < FATRESRV || n >= bp->fatclusters)		return -1;	fb = bp->fatbits;	k = (fb * n) >> 3;	if(k >= bp->fatsize*bp->sectsize)		panic("getfat");	sect = k/bp->sectsize + bp->fataddr;	o = k%bp->sectsize;	p = getsect(xf, sect);	if(p == nil)		return -1;	k = p->iobuf[o++];	if(o >= bp->sectsize){		putsect(p);		p = getsect(xf, sect+1);		if(p == nil)			return -1;		o = 0;	}	k |= p->iobuf[o++]<<8;	if(fb == 32){		/* fat32 is really fat28 */		k |= p->iobuf[o++] << 16;		k |= (p->iobuf[o] & 0x0f) << 24;		fb = 28;	}	putsect(p);	if(fb == 12){		if(n&1)			k >>= 4;		else			k &= 0xfff;	}	if(chatty > 1)		chat("fat(%#x)=%#lx...", n, k);	/*	 * This is a very strange check for out of range.	 * As a concrete example, for a 16-bit FAT,	 * FFF8 through FFFF all signify ``end of cluster chain.''	 * This generalizes to other-sized FATs.	 */	if(k >= (1 << fb) - 8)		return -1;	return k;}voidputfat(Xfs *xf, int n, ulong val){	Fatinfo *fi;	Dosbpb *bp;	Iosect *p;	ulong k, sect, esect;	int o;	bp = xf->ptr;	if(n < FATRESRV || n >= bp->fatclusters)		panic("putfat n=%d", n);	k = (bp->fatbits * n) >> 3;	if(k >= bp->fatsize*bp->sectsize)		panic("putfat");	sect = k/bp->sectsize + bp->fataddr;	esect = sect + bp->nfats * bp->fatsize;	for(; sect<esect; sect+=bp->fatsize){		o = k%bp->sectsize;		p = getsect(xf, sect);		if(p == nil)			continue;		switch(bp->fatbits){		case 12:			if(n&1){				p->iobuf[o] &= 0x0f;				p->iobuf[o++] |= val<<4;				if(o >= bp->sectsize){					p->flags |= BMOD;					putsect(p);					p = getsect(xf, sect+1);					if(p == nil)						continue;					o = 0;				}				p->iobuf[o] = val>>4;			}else{				p->iobuf[o++] = val;				if(o >= bp->sectsize){					p->flags |= BMOD;					putsect(p);					p = getsect(xf, sect+1);					if(p == nil)						continue;					o = 0;				}				p->iobuf[o] &= 0xf0;				p->iobuf[o] |= (val>>8) & 0x0f;			}			break;		case 16:			p->iobuf[o++] = val;			p->iobuf[o] = val>>8;			break;		case 32:	/* fat32 is really fat28 */			p->iobuf[o++] = val;			p->iobuf[o++] = val>>8;			p->iobuf[o++] = val>>16;			p->iobuf[o] = (p->iobuf[o] & 0xf0) | ((val>>24) & 0x0f);			break;		default:			panic("putfat fatbits");		}		p->flags |= BMOD;		putsect(p);	}	if(val == 0)		bp->freeclusters++;	else		bp->freeclusters--;	if(bp->fatinfo){		p = getsect(xf, bp->fatinfo);		if(p != nil){			fi = (Fatinfo*)p->iobuf;			PLONG(fi->nextfree, bp->freeptr);			PLONG(fi->freeclust, bp->freeclusters);			p->flags |= BMOD;			putsect(p);		}	}}/* * Contiguous falloc; if we can, use lastclust+1. * Otherwise, move the file to get some space. * If there just isn't enough contiguous space * anywhere on disk, fail. */intcfalloc(Xfile *f){	int l;	if((l=makecontig(f, 8)) >= 0)		return l;	return makecontig(f, 1);}/* * Check whether a file is contiguous. */intiscontig(Xfs *xf, Dosdir *d){	long clust, next;	clust = getstart(xf, d);	if(clust <= 0)		return 1;	for(;;) {		next = getfat(xf, clust);		if(next < 0)			return 1;		if(next != clust+1)			return 0;		clust = next;	}}/* * Make a file contiguous, with nextra clusters of  * free space after it for later expansion. * Return the number of the first new cluster. */intmakecontig(Xfile *f, int nextra){	Dosbpb *bp;	Dosdir *d;	Dosptr *dp;	Xfs *xf;	Iosect *wp, *rp;	long clust, next, last, start, rclust, wclust, eclust, ostart;	int isok, i, n, nclust, nrun, rs, ws;	xf = f->xf;	bp = xf->ptr;	dp = f->ptr;	d = dp->d;	isok = 1;	nclust = 0;	clust = fileclust(f, 0, 0);	chat("clust %#lux", clust);	if(clust != -1) {		for(;;) {			nclust++;			chat(".");			next = getfat(xf, clust);			if(next <= 0)				break;			if(next != clust+1)				isok = 0;			clust = next;		}	}	chat("nclust %d\n", nclust);	if(isok && clust != -1) {		eclust = clust+1;	/* eclust = first cluster past file */		assert(eclust == fileclust(f, 0, 0)+nclust);		for(i=0; i<nextra; i++)			if(getfat(xf, eclust+i) != 0)				break;		if(i == nextra) {	/* they were all free */			chat("eclust=%#lx, getfat eclust-1 = %#lux\n", eclust, getfat(xf, eclust-1));			assert(getfat(xf, eclust-1) == 0xffffffff);			putfat(xf, eclust-1, eclust);			putfat(xf, eclust, 0xffffffff);			bp->freeptr = clust+1;	/* to help keep the blocks free */			return eclust;		}	}	/* need to search for nclust+nextra contiguous free blocks */	last = -1;	n = bp->freeptr;	nrun = 0;	for(;;){		if(getfat(xf, n) == 0) {			if(last+1 == n)				nrun++;			else				nrun = 1;			if(nrun >= nclust+nextra)				break;			last = n;		}		if(++n >= bp->fatclusters)			n = FATRESRV;		if(n == bp->freeptr) {			errno = Econtig;			return -1;		}	}	bp->freeptr = n+1;	/* copy old data over */	start = n+1 - nrun;	/* sanity check */	for(i=0; i<nclust+nextra; i++)		assert(getfat(xf, start+i) == 0);	chat("relocate chain %lux -> 0x%lux len %d\n", fileclust(f, 0, 0), start, nclust);	wclust = start;	for(rclust = fileclust(f, 0, 0); rclust > 0; rclust = next){		rs = clust2sect(bp, rclust);		ws = clust2sect(bp, wclust);		for(i=0; i<bp->clustsize; i++, rs++, ws++){			rp = getsect(xf, rs);			if(rp == nil)				return -1;			wp = getosect(xf, ws);			assert(wp != nil);			memmove(wp->iobuf, rp->iobuf, bp->sectsize);			wp->flags = BMOD;			putsect(rp);			putsect(wp);		}		chat("move cluster %#lx -> %#lx...", rclust, wclust);		next = getfat(xf, rclust);		putfat(xf, wclust, wclust+1);		wclust++;	}	/* now wclust points at the first new cluster; chain it in */	chat("wclust 0x%lux start 0x%lux (fat->0x%lux) nclust %d\n", wclust, start, getfat(xf, start), nclust);	assert(wclust == start+nclust);	putfat(xf, wclust, 0xffffffff);	/* end of file */	/* update directory entry to point at new start */	ostart = fileclust(f, 0, 0);	putstart(xf, d, start);	/* check our work */	i = 0;	clust = fileclust(f, 0, 0);	if(clust != -1) {		for(;;) {			i++;			next = getfat(xf, clust);			if(next <= 0)				break;			assert(next == clust+1);			clust = next;		}	}	chat("chain check: len %d\n", i);	assert(i == nclust+1);	/* succeeded; remove old chain. */	for(rclust = ostart; rclust > 0; rclust = next){		next = getfat(xf, rclust);		putfat(xf, rclust, 0);	/* free cluster */	}	return start+nclust;}	intfalloc(Xfs *xf){	Dosbpb *bp = xf->ptr;	Iosect *p;	int n, i, k;	n = bp->freeptr;	for(;;){		if(getfat(xf, n) == 0)			break;		if(++n >= bp->fatclusters)			n = FATRESRV;		if(n == bp->freeptr)			return -1;	}	bp->freeptr = n+1;	if(bp->freeptr >= bp->fatclusters)		bp->freeptr = FATRESRV;	putfat(xf, n, 0xffffffff);	k = clust2sect(bp, n);	for(i=0; i<bp->clustsize; i++){		p = getosect(xf, k+i);		memset(p->iobuf, 0, bp->sectsize);		p->flags = BMOD;		putsect(p);	}	return n;}voidffree(Xfs *xf, long start){	putfat(xf, start, 0);}longclust2sect(Dosbpb *bp, long clust){	return bp->dataaddr + (clust - FATRESRV) * bp->clustsize;}longsect2clust(Dosbpb *bp, long sect){	long c;	c = (sect - bp->dataaddr) / bp->clustsize + FATRESRV;	assert(sect == clust2sect(bp, c));	return c;}voidputtime(Dosdir *d, long s){	Tm *t;	ushort x;	if(s == 0)		s = time(0);	t = localtime(s);	x = (t->hour<<11) | (t->min<<5) | (t->sec>>1);	PSHORT(d->time, x);	x = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday;	PSHORT(d->date, x);}longgtime(Dosdir *dp){	Tm tm;	int i;	i = GSHORT(dp->time);	tm.hour = i >> 11;	tm.min = (i >> 5) & 63;	tm.sec = (i & 31) << 1;	i = GSHORT(dp->date);	tm.year = 80 + (i >> 9);	tm.mon = ((i >> 5) & 15) - 1;	tm.mday = i & 31;	tm.zone[0] = '\0';	tm.tzoff = 0;	tm.yday = 0;	return tm2sec(&tm);}/* * structure dumps for debugging */voidbootdump(int fd, Dosboot *b){	Biobuf bp;	Binit(&bp, fd, OWRITE);	Bprint(&bp, "magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",		b->magic[0], b->magic[1], b->magic[2]);	Bprint(&bp, "version: \"%8.8s\"\n", (char*)b->version);	Bprint(&bp, "sectsize: %d\n", GSHORT(b->sectsize));	Bprint(&bp, "clustsize: %d\n", b->clustsize);	Bprint(&bp, "nresrv: %d\n", GSHORT(b->nresrv));	Bprint(&bp, "nfats: %d\n", b->nfats);	Bprint(&bp, "rootsize: %d\n", GSHORT(b->rootsize));	Bprint(&bp, "volsize: %d\n", GSHORT(b->volsize));	Bprint(&bp, "mediadesc: 0x%2.2x\n", b->mediadesc);	Bprint(&bp, "fatsize: %d\n", GSHORT(b->fatsize));	Bprint(&bp, "trksize: %d\n", GSHORT(b->trksize));	Bprint(&bp, "nheads: %d\n", GSHORT(b->nheads));	Bprint(&bp, "nhidden: %ld\n", GLONG(b->nhidden));	Bprint(&bp, "bigvolsize: %ld\n", GLONG(b->bigvolsize));	Bprint(&bp, "driveno: %d\n", b->driveno);	Bprint(&bp, "reserved0: 0x%2.2x\n", b->reserved0);	Bprint(&bp, "bootsig: 0x%2.2x\n", b->bootsig);	Bprint(&bp, "volid: 0x%8.8lux\n", GLONG(b->volid));	Bprint(&bp, "label: \"%11.11s\"\n", (char*)b->label);	Bterm(&bp);}voidbootdump32(int fd, Dosboot32 *b){	Biobuf bp;	Binit(&bp, fd, OWRITE);	Bprint(&bp, "magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",		b->magic[0], b->magic[1], b->magic[2]);	Bprint(&bp, "version: \"%8.8s\"\n", (char*)b->version);	Bprint(&bp, "sectsize: %d\n", GSHORT(b->sectsize));	Bprint(&bp, "clustsize: %d\n", b->clustsize);	Bprint(&bp, "nresrv: %d\n", GSHORT(b->nresrv));	Bprint(&bp, "nfats: %d\n", b->nfats);	Bprint(&bp, "rootsize: %d\n", GSHORT(b->rootsize));	Bprint(&bp, "volsize: %d\n", GSHORT(b->volsize));	Bprint(&bp, "mediadesc: 0x%2.2x\n", b->mediadesc);	Bprint(&bp, "fatsize: %d\n", GSHORT(b->fatsize));	Bprint(&bp, "trksize: %d\n", GSHORT(b->trksize));	Bprint(&bp, "nheads: %d\n", GSHORT(b->nheads));	Bprint(&bp, "nhidden: %ld\n", GLONG(b->nhidden));	Bprint(&bp, "bigvolsize: %ld\n", GLONG(b->bigvolsize));	Bprint(&bp, "fatsize32: %ld\n", GLONG(b->fatsize32));	Bprint(&bp, "extflags: %d\n", GSHORT(b->extflags));	Bprint(&bp, "version: %d\n", GSHORT(b->version1));	Bprint(&bp, "rootstart: %ld\n", GLONG(b->rootstart));	Bprint(&bp, "infospec: %d\n", GSHORT(b->infospec));	Bprint(&bp, "backupboot: %d\n", GSHORT(b->backupboot));	Bprint(&bp, "reserved: %d %d %d %d %d %d %d %d %d %d %d %d\n",		b->reserved[0], b->reserved[1], b->reserved[2], b->reserved[3],		b->reserved[4], b->reserved[5], b->reserved[6], b->reserved[7],		b->reserved[8], b->reserved[9], b->reserved[10], b->reserved[11]);	Bterm(&bp);}voidbootsecdump32(int fd, Xfs *xf, Dosboot32 *b32){	Fatinfo *fi;	Iosect *p1;	int fisec, bsec, res;	fprint(fd, "\nfat32\n");	bootdump32(fd, b32);	res = GSHORT(b32->nresrv);	bsec = GSHORT(b32->backupboot);	if(bsec < res && bsec != 0){		p1 = getsect(xf, bsec);		if(p1 == nil)			fprint(fd, "\ncouldn't get backup boot sector: %r\n");		else{			fprint(fd, "\nbackup boot\n");			bootdump32(fd, (Dosboot32*)p1->iobuf);			putsect(p1);		}	}else if(bsec != 0xffff)		fprint(fd, "bad backup boot sector: %d reserved %d\n", bsec, res);	fisec = GSHORT(b32->infospec);	if(fisec < res && fisec != 0){		p1 = getsect(xf, fisec);		if(p1 == nil)			fprint(fd, "\ncouldn't get fat info sector: %r\n");		else{			fprint(fd, "\nfat info %d\n", fisec);			fi = (Fatinfo*)p1->iobuf;			fprint(fd, "sig1: 0x%lux sb 0x%lux\n", GLONG(fi->sig1), FATINFOSIG1);			fprint(fd, "sig: 0x%lux sb 0x%lux\n", GLONG(fi->sig), FATINFOSIG);			fprint(fd, "freeclust: %lud\n", GLONG(fi->freeclust));			fprint(fd, "nextfree: %lud\n", GLONG(fi->nextfree));			fprint(fd, "reserved: %lud %lud %lud\n", GLONG(fi->resrv), GLONG(fi->resrv+4), GLONG(fi->resrv+8));			putsect(p1);		}	}else if(fisec != 0xffff)		fprint(2, "bad fat info sector: %d reserved %d\n", bsec, res);}voiddirdump(void *vdbuf){	static char attrchar[] = "rhsvda67";	Dosdir *d;	char *name, namebuf[DOSNAMELEN];	char buf[128], *s, *ebuf;	uchar *dbuf;	int i;	if(!chatty)		return;	d = vdbuf;	ebuf = buf + sizeof(buf);	if(d->attr == 0xf){		dbuf = vdbuf;		name = namebuf + DOSNAMELEN;		*--name = '\0';		name = getnamerunes(name, dbuf, 1);		seprint(buf, ebuf, "\"%s\" %2.2x %2.2ux %2.2ux %d", name, dbuf[0], dbuf[12], dbuf[13], GSHORT(d->start));	}else{		s = seprint(buf, ebuf, "\"%.8s.%.3s\" ", (char*)d->name, (char*)d->ext);		for(i=7; i>=0; i--)			*s++ = d->attr&(1<<i) ? attrchar[i] : '-';			i = GSHORT(d->time);		s = seprint(s, ebuf, " %2.2d:%2.2d:%2.2d", i>>11, (i>>5)&63, (i&31)<<1);		i = GSHORT(d->date);		s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);			i = GSHORT(d->ctime);		s = seprint(s, ebuf, " %2.2d:%2.2d:%2.2d", i>>11, (i>>5)&63, (i&31)<<1);		i = GSHORT(d->cdate);		s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);			i = GSHORT(d->adate);		s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);		seprint(s, ebuf, " %d %d", GSHORT(d->start), GSHORT(d->length));	}	chat("%s\n", buf);}intcistrcmp(char *s1, char *s2){	int c1, c2;	while(*s1){		c1 = *s1++;		c2 = *s2++;		if(c1 >= 'A' && c1 <= 'Z')			c1 -= 'A' - 'a';		if(c2 >= 'A' && c2 <= 'Z')			c2 -= 'A' - 'a';		if(c1 != c2)			return c1 - c2;	}	return -*s2;}intutftorunes(Rune *rr, char *s, int n){	Rune *r, *re;	int c;	r = rr;	re = r + n - 1;	while(c = (uchar)*s){		if(c < Runeself){			*r = c;			s++;		}else			s += chartorune(r, s);		r++;		if(r >= re)			break;	}	*r = 0;	return r - rr;}

⌨️ 快捷键说明

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