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

📄 dosfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "all.h"#include "io.h"#include "mem.h"#include "dosfs.h"#define	GSHORT(p) (((p)[1]<<8)|(p)[0])#define	GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))#define	GLSHORT(p) (((p)[0]<<8)|(p)[1])#define	GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))/* *  debugging */#define chatty	0#define	chat	if(chatty)print/* *  block io buffers */typedef struct Clustbuf	Clustbuf;struct Clustbuf{	int	flags;	int	age;	Devsize	sector;	uchar *	iobuf;	Dos *	dos;	int	size;	int	bufsize;};enum{	Nbio=	16,	LOCKED=	1,	MOD=	2,	IMMED=	4,};static void	puttime(Dosdir*);static Clustbuf	bio[Nbio];/* *  write an io buffer and update its flags */static voidwriteclust(Clustbuf *p){	Dos *dos;	Off addr;	dos = p->dos;	addr = (p->sector+dos->start)*dos->sectbytes;	chat("writeclust @ %lld addr %lld...", (Wideoff)p->sector,		(Wideoff)addr);	if((*dos->seek)(dos->dev, addr) < 0)		panic("writeclust: seek");	if((*dos->write)(dos->dev, p->iobuf, p->size) != p->size)		panic("writeclust: write");	p->flags &= ~(MOD|IMMED);	chat("OK\n");}/* *  write any dirty buffers */static voidsyncclust(void){	Clustbuf *p;	for(p = bio; p < &bio[Nbio]; p++){		if(p->flags & LOCKED)			panic("syncclust");		if(p->flags & MOD)			writeclust(p);	}}/* *  get an io buffer, possibly with valid data */static Clustbuf*getclust0(Dos *dos, Off sector){	Clustbuf *p, *oldest;	chat("getclust0 @ %lld\n", (Wideoff)sector);	/*	 *  if we have it, just return it	 *  otherwise, reuse the oldest unlocked entry	 */	oldest = 0;	for(p = bio; p < &bio[Nbio]; p++){		if(sector == p->sector && dos == p->dos){			if(p->flags & LOCKED)				panic("getclust0 locked");			chat("getclust0 %lld in cache\n", (Wideoff)sector);			p->flags |= LOCKED;			return p;		}		if(p->flags & LOCKED)			continue;		if(oldest == 0 || p->age <= oldest->age)			oldest = p;	}	p = oldest;	if(p == 0)		panic("getclust0 all locked");	p->flags |= LOCKED;	if(p->flags & MOD)		writeclust(p);	/*	 *  make sure the buffer is big enough	 */	if(p->iobuf==0 || p->bufsize < dos->clustbytes){		p->bufsize = dos->clustbytes;		p->iobuf = ialloc(p->bufsize, 0);	}	if(sector >= dos->dataaddr)		p->size = dos->clustbytes;	else		p->size = dos->sectbytes;	p->dos = 0;	/* make it invalid */	return p;}/* *  get an io block from an io buffer */static Clustbuf*getclust(Dos *dos, Off sector){	Clustbuf *p;	Off addr;	p = getclust0(dos, sector);	if(p->dos){		p->age = MACHP(0)->ticks;		return p;	}	addr = (sector+dos->start)*dos->sectbytes;	chat("getclust seek addr %lld\n", (Wideoff)addr);	if((*dos->seek)(dos->dev, addr) < 0){		chat("can't seek block\n");		return 0;	}	chat("getclust read addr %lld\n", (Wideoff)addr);	if((*dos->read)(dos->dev, p->iobuf, p->size) != p->size){		chat("can't read block\n");		return 0;	}	p->age = MACHP(0)->ticks;	p->dos = dos;	p->sector = sector;	chat("getclust %lld read\n", (Wideoff)sector);	return p;}/* *  get an io block from an io buffer; *  any current data is discarded. */static Clustbuf*getclustz(Dos *dos, Off sector){	Clustbuf *p;	p = getclust0(dos, sector);	p->age = MACHP(0)->ticks;	p->dos = dos;	p->sector = sector;	memset(p->iobuf, 0, p->size);	p->flags |= MOD;	chat("getclustz %lld\n", (Wideoff)sector);	return p;}/* *  release an io buffer */static voidputclust(Clustbuf *p){	if(!(p->flags & LOCKED))		panic("putclust lock");	if((p->flags & (MOD|IMMED)) == (MOD|IMMED))		writeclust(p);	p->flags &= ~LOCKED;	chat("putclust @ sector %lld...", (Wideoff)p->sector);}/* *  walk the fat one level ( n is a current cluster number ). *  return the new cluster number or -1 if no more. */static longfatwalk(Dos *dos, int n){	ulong k, sect;	Clustbuf *p;	int o;	chat("fatwalk %d\n", n);	if(n < 2 || n >= dos->fatclusters)		return -1;	switch(dos->fatbits){	case 12:		k = (3*n)/2; break;	case 16:		k = 2*n; break;	default:		return -1;	}	if(k >= dos->fatbytes)		panic("getfat");	sect = k/dos->sectbytes + dos->fataddr;	o = k%dos->sectbytes;	p = getclust(dos, sect);	k = p->iobuf[o++];	if(o >= dos->sectbytes){		putclust(p);		p = getclust(dos, sect+1);		o = 0;	}	k |= p->iobuf[o]<<8;	putclust(p);	if(dos->fatbits == 12){		if(n&1)			k >>= 4;		else			k &= 0xfff;		if(k >= 0xff8)			k |= 0xf000;	}	k = k < 0xfff8 ? k : -1;	chat("fatwalk %d -> %lud\n", n, k);	return k;}/* *  write a value into each copy of the fat. */static voidfatwrite(Dos *dos, int n, int val){	Off k, sect;	Clustbuf *p;	int i, o;	chat("fatwrite %d %d...", n, val);	if(n < 2 || n >= dos->fatclusters)		panic("fatwrite n");	switch(dos->fatbits){	case 12:		k = (3*n)/2; break;	case 16:		k = 2*n; break;	default:		panic("fatwrite fatbits");		return;	}	if(k >= dos->fatbytes)		panic("fatwrite k");	for(i=0; i<dos->nfats; i++, k+=dos->fatbytes){		sect = k/dos->sectbytes + dos->fataddr;		o = k%dos->sectbytes;		p = getclust(dos, sect);		if(p == 0)			panic("fatwrite getclust");		switch(dos->fatbits){		case 12:			if(n&1){				p->iobuf[o] &= 0x0f;				p->iobuf[o++] |= val<<4;			}else				p->iobuf[o++] = val;			if(o >= dos->sectbytes){				p->flags |= MOD;				putclust(p);				p = getclust(dos, sect+1);				if(p == 0)					panic("fatwrite getclust");				o = 0;			}			if(n&1)				p->iobuf[o] = val>>4;			else{				p->iobuf[o] &= 0xf0;				p->iobuf[o] |= (val>>8)&0x0f;			}			break;		case 16:			p->iobuf[o++] = val;			p->iobuf[o] = val>>8;			break;		}		p->flags |= MOD;		putclust(p);	}	chat("OK\n");}/* *  allocate a free cluster from the fat. */static intfatalloc(Dos *dos){	Clustbuf *p;	int n;	n = dos->freeptr;	for(;;){		if(fatwalk(dos, n) == 0)			break;		if(++n >= dos->fatclusters)			n = 2;		if(n == dos->freeptr)			return -1;	}	dos->freeptr = n+1;	if(dos->freeptr >= dos->fatclusters)		dos->freeptr = 2;	fatwrite(dos, n, 0xffff);	p = getclustz(dos, dos->dataaddr + (n-2)*dos->clustsize);	putclust(p);	return n;}/* *  map a file's logical sector address to a physical sector address */static longfileaddr(Dosfile *fp, Off ltarget, Clustbuf *pdir){	Dos *dos = fp->dos;	Dosdir *dp;	Off p;	chat("fileaddr %8.8s %lld\n", fp->name, (Wideoff)ltarget);	/*	 *  root directory is contiguous and easy	 */	if(fp->pdir == 0){		if(ltarget*dos->sectbytes >= dos->rootsize*sizeof(Dosdir))			return -1;		p = dos->rootaddr + ltarget;		chat("fileaddr %lld -> %lld\n", (Wideoff)ltarget, (Wideoff)p);		return p;	}	if(fp->pstart == 0){	/* empty file */		if(!pdir)			return -1;		p = fatalloc(dos);		if(p <= 0)			return -1;		chat("fileaddr initial alloc %lld\n", (Wideoff)p);		dp = (Dosdir *)(pdir->iobuf + fp->odir);		puttime(dp);		dp->start[0] = p;		dp->start[1] = p>>8;		pdir->flags |= MOD;		fp->pstart = p;		fp->pcurrent = p;		fp->lcurrent = 0;	}	/*	 *  anything else requires a walk through the fat	 *  [lp]current will point to the last cluster if we run off the end	 */	ltarget /= dos->clustsize;	if(fp->pcurrent == 0 || fp->lcurrent > ltarget){		/* go back to the beginning */		fp->lcurrent = 0;		fp->pcurrent = fp->pstart;	}	while(fp->lcurrent < ltarget){		/* walk the fat */		p = fatwalk(dos, fp->pcurrent);		if(p < 0){			if(!pdir)				return -1;			p = fatalloc(dos);			if(p < 0){				print("file system full\n");				return -1;			}			fatwrite(dos, fp->pcurrent, p);		}		fp->pcurrent = p;		++fp->lcurrent;	}	/*	 *  clusters start at 2 instead of 0 (why? - presotto)	 */	p = dos->dataaddr + (fp->pcurrent-2)*dos->clustsize;	chat("fileaddr %lld -> %lld\n", (Wideoff)ltarget, (Wideoff)p);	return p;}/* *  set up a dos file name */static voidsetname(char *name, char *ext, char *from){	char *to;	memset(name, ' ', 8);	memset(ext, ' ', 3);	to = name;	for(; *from && to-name < 8; from++, to++){		if(*from == '.'){			from++;			break;

⌨️ 快捷键说明

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