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

📄 dossubs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
			return -1;		for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){			d = (Dosdir *)&p->iobuf[o];			if(d->name[0] == 0x00){				putsect(p);				return 0;			}			if(d->name[0] == DOSEMPTY)				continue;			if(d->name[0] == '.')				continue;			if(d->attr&DVLABEL)				continue;			putsect(p);			return -1;		}		putsect(p);	}	return 0;}longreaddir(Xfile *f, void *vbuf, long offset, long count){	Xfs *xf;	Dosbpb *bp;	Dir dir;	int isect, addr, o, islong, sum;	Iosect *p;	Dosdir *d;	long rcnt, n;	char *name, snamebuf[8+1+3+1], namebuf[DOSNAMELEN];	uchar *buf;	buf = vbuf;	rcnt = 0;	xf = f->xf;	bp = xf->ptr;	if(count <= 0)		return 0;	islong = 0;	sum = -1;	name = nil;	for(isect=0;; isect++){		addr = fileaddr(f, isect, 0);		if(addr < 0)			break;		p = getsect(xf, addr);		if(p == 0)			return -1;		for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){			d = (Dosdir *)&p->iobuf[o];			if(d->name[0] == 0x00){				putsect(p);				return rcnt;			}			if(d->name[0] == DOSEMPTY)				continue;			dirdump(d);			if(d->name[0] == '.'){				if(d->name[1] == ' ' || d->name[1] == 0)					continue;				if(d->name[1] == '.' &&				  (d->name[2] == ' ' || d->name[2] == 0))					continue;			}			if((d->attr & 0xf) == 0xf){				name = getnamesect(namebuf, name, p->iobuf+o, &islong, &sum, 1);				continue;			}			if(d->attr & DVLABEL){				islong = 0;				continue;			}			dir.name = snamebuf;			getdir(xf, &dir, d, addr, o);			if(islong == 1 && nameok(name) && sum == aliassum(d))				dir.name = name;			islong = 0;			n = convD2M(&dir, &buf[rcnt], count - rcnt);			name = nil;			if(n <= BIT16SZ){	/* no room for next entry */				putsect(p);				return rcnt;			}			rcnt += n;			if(offset > 0){				offset -= rcnt;				rcnt = 0;				islong = 0;				continue;			}			if(rcnt == count){				putsect(p);				return rcnt;			}		}		putsect(p);	}	return rcnt;}/* * set up ndp for a directory's parent * the hardest part is setting up paddr */intwalkup(Xfile *f, Dosptr *ndp){	Dosbpb *bp;	Dosptr *dp;	Dosdir *xd;	Iosect *p;	long k, o, so, start, pstart, ppstart, st, ppclust;	bp = f->xf->ptr;	dp = f->ptr;	memset(ndp, 0, sizeof(Dosptr));	ndp->prevaddr = -1;	ndp->naddr = -1;	ndp->addr = dp->paddr;	ndp->offset = dp->poffset;	chat("walkup: paddr=%#lx...", dp->paddr);	/*	 * root's paddr is always itself	 */	if(isroot(dp->paddr))		return 0;	/*	 * find the start of our parent's directory	 */	p = getsect(f->xf, dp->paddr);	if(p == nil)		goto error;	xd = (Dosdir *)&p->iobuf[dp->poffset];	dirdump(xd);	start = getstart(f->xf, xd);	chat("start=%#lx...", start);	if(start == 0)		goto error;	putsect(p);	/*	 * verify that parent's . points to itself	 */	p = getsect(f->xf, clust2sect(bp, start));	if(p == nil)		goto error;	xd = (Dosdir *)p->iobuf;	dirdump(xd);	st = getstart(f->xf, xd);	if(xd->name[0]!='.' || xd->name[1]!=' ' || start!=st)		goto error;	/*	 * parent's .. is the next entry, and has start of parent's parent	 */	xd++;	dirdump(xd);	if(xd->name[0] != '.' || xd->name[1] != '.')		goto error;	pstart = getstart(f->xf, xd);	putsect(p);	/*	 * we're done if parent is root	 */	if(pstart == 0 || f->xf->isfat32 && pstart == bp->rootstart)		return 0;	/*	 * verify that parent's . points to itself	 */	p = getsect(f->xf, clust2sect(bp, pstart));	if(p == 0){		chat("getsect %ld failed\n", pstart);		goto error;	}	xd = (Dosdir *)p->iobuf;	dirdump(xd);	st = getstart(f->xf, xd);	if(xd->name[0]!='.' || xd->name[1]!=' ' || pstart!=st)		goto error;	/*	 * parent's parent's .. is the next entry, and has start of parent's parent's parent	 */	xd++;	dirdump(xd);	if(xd->name[0] != '.' || xd->name[1] != '.')		goto error;	ppstart = getstart(f->xf, xd);	putsect(p);	/*	 * open parent's parent's parent, and walk through it until parent's parent is found	 * need this to find parent's parent's addr and offset	 */	ppclust = ppstart;	if(f->xf->isfat32 && ppclust == 0){		ppclust = bp->rootstart;		chat("ppclust 0, resetting to rootstart\n");	}	k = ppclust ? clust2sect(bp, ppclust) : bp->rootaddr;	p = getsect(f->xf, k);	if(p == nil){		chat("getsect %ld failed\n", k);		goto error;	}	xd = (Dosdir *)p->iobuf;	dirdump(xd);	if(ppstart){		st = getstart(f->xf, xd);		if(xd->name[0]!='.' || xd->name[1]!=' ' || ppstart!=st)			goto error;	}	for(so=1;; so++){		for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){			xd = (Dosdir *)&p->iobuf[o];			if(xd->name[0] == 0x00){				chat("end dir\n");				goto error;			}			if(xd->name[0] == DOSEMPTY)				continue;			st = getstart(f->xf, xd);			if(st == pstart)				goto out;		}		if(ppclust){			if(so%bp->clustsize == 0){				mlock(bp);				ppclust = getfat(f->xf, ppclust);				unmlock(bp);				if(ppclust < 0){					chat("getfat %ld failed\n", ppclust);					goto error;				}			}			k = clust2sect(bp, ppclust) + 				so%bp->clustsize;		}else{			if(so*bp->sectsize >= bp->rootsize*DOSDIRSIZE)				goto error;			k = bp->rootaddr + so;		}		putsect(p);		p = getsect(f->xf, k);		if(p == 0){			chat("getsect %ld failed\n", k);			goto error;		}	}out:	putsect(p);	ndp->paddr = k;	ndp->poffset = o;	return 0;error:	if(p)		putsect(p);	return -1;}longreadfile(Xfile *f, void *vbuf, long offset, long count){	Xfs *xf = f->xf;	Dosbpb *bp = xf->ptr;	Dosptr *dp = f->ptr;	Dosdir *d = dp->d;	int isect, addr, o, c;	Iosect *p;	uchar *buf;	long length, rcnt;	rcnt = 0;	length = GLONG(d->length);	buf = vbuf;	if(offset >= length)		return 0;	if(offset+count >= length)		count = length - offset;	isect = offset/bp->sectsize;	o = offset%bp->sectsize;	while(count > 0){		addr = fileaddr(f, isect++, 0);		if(addr < 0)			break;		c = bp->sectsize - o;		if(c > count)			c = count;		p = getsect(xf, addr);		if(p == 0)			return -1;		memmove(&buf[rcnt], &p->iobuf[o], c);		putsect(p);		count -= c;		rcnt += c;		o = 0;	}	return rcnt;}longwritefile(Xfile *f, void *vbuf, long offset, long count){	Xfs *xf = f->xf;	Dosbpb *bp = xf->ptr;	Dosptr *dp = f->ptr;	Dosdir *d = dp->d;	int isect, addr = 0, o, c;	Iosect *p;	uchar *buf;	long length, rcnt = 0, dlen;	buf = vbuf;	isect = offset/bp->sectsize;	o = offset%bp->sectsize;	while(count > 0){		addr = fileaddr(f, isect++, 1);		if(addr < 0)			break;		c = bp->sectsize - o;		if(c > count)			c = count;		if(c == bp->sectsize){			p = getosect(xf, addr);			p->flags = 0;		}else{			p = getsect(xf, addr);			if(p == nil)				return -1;		}		memmove(&p->iobuf[o], &buf[rcnt], c);		p->flags |= BMOD;		putsect(p);		count -= c;		rcnt += c;		o = 0;	}	if(rcnt <= 0 && addr < 0)		return -1;	length = 0;	dlen = GLONG(d->length);	if(rcnt > 0)		length = offset+rcnt;	else if(dp->addr && dp->clust){		c = bp->clustsize*bp->sectsize;		if(dp->iclust > (dlen+c-1)/c)			length = c*dp->iclust;	}	if(length > dlen)		PLONG(d->length, length);	puttime(d, 0);	dp->p->flags |= BMOD;	return rcnt;}inttruncfile(Xfile *f, long length){	Xfs *xf = f->xf;	Dosbpb *bp = xf->ptr;	Dosptr *dp = f->ptr;	Dosdir *d = dp->d;	long clust, next, n;	mlock(bp);	clust = getstart(f->xf, d);	n = length;	if(n <= 0)		putstart(f->xf, d, 0);	else		n -= bp->sectsize;	while(clust > 0){		next = getfat(xf, clust);		if(n <= 0)			putfat(xf, clust, 0);		else			n -= bp->clustsize*bp->sectsize;		clust = next;	}	unmlock(bp);	PLONG(d->length, length);	dp->iclust = 0;	dp->clust = 0;	dp->p->flags |= BMOD;	return 0;}voidputdir(Dosdir *d, Dir *dp){	if(dp->mode != ~0){		if(dp->mode & 2)			d->attr &= ~DRONLY;		else			d->attr |= DRONLY;		if(dp->mode & DMEXCL)			d->attr |= DSYSTEM;		else			d->attr &= ~DSYSTEM;	}	if(dp->mtime != ~0)		puttime(d, dp->mtime);}/* * should extend this to deal with * creation and access dates */voidgetdir(Xfs *xfs, Dir *dp, Dosdir *d, int addr, int offset){	if(d == nil || addr == 0)		panic("getdir on root");	dp->type = 0;	dp->dev = 0;	getname(dp->name, d);	dp->qid.path = addr*(Sectorsize/DOSDIRSIZE) +			offset/DOSDIRSIZE;	dp->qid.vers = 0;	if(d->attr & DRONLY)		dp->mode = 0444;	else		dp->mode = 0666;	dp->atime = gtime(d);	dp->mtime = dp->atime;	dp->qid.type = QTFILE;	if(d->attr & DDIR){		dp->qid.type = QTDIR;		dp->mode |= DMDIR|0111;		dp->length = 0;	}else		dp->length = GLONG(d->length);	if(d->attr & DSYSTEM){		dp->mode |= DMEXCL;		if(iscontig(xfs, d))			dp->mode |= DMAPPEND;	}	dp->uid = "bill";	dp->muid = "bill";	dp->gid = "trog";}voidgetname(char *p, Dosdir *d){	int c, i;	for(i=0; i<8; i++){		c = d->name[i];		if(c == '\0' || c == ' ')			break;		if(i == 0 && c == 0x05)			c = 0xe5;		*p++ = c;	}	for(i=0; i<3; i++){		c = d->ext[i];		if(c == '\0' || c == ' ')			break;		if(i == 0)			*p++ = '.';		*p++ = c;	}	*p = 0;}static char*getnamerunes(char *dst, uchar *buf, int step){	int i;	Rune r;	char dbuf[DOSRUNE * UTFmax + 1], *d;	d = dbuf;	r = 1;	for(i = 1; r && i < 11; i += 2){		r = buf[i] | (buf[i+1] << 8);		d += runetochar(d, &r);	}	for(i = 14; r && i < 26; i += 2){		r = buf[i] | (buf[i+1] << 8);		d += runetochar(d, &r);	}	for(i = 28; r && i < 32; i += 2){		r = buf[i] | (buf[i+1] << 8);		d += runetochar(d, &r);	}	if(step == 1)		dst -= d - dbuf;	memmove(dst, dbuf, d - dbuf);	if(step == -1){		dst += d - dbuf;		*dst = '\0';	}	return dst;}char*getnamesect(char *dbuf, char *d, uchar *buf, int *islong, int *sum, int step){	/*	 * validation checks to make sure we're	 * making up a consistent name	 */	if(buf[11] != 0xf || buf[12] != 0){		*islong = 0;		return nil;	}	if(step == 1){		if((buf[0] & 0xc0) == 0x40){			*islong = buf[0] & 0x3f;			*sum = buf[13];			d = dbuf + DOSNAMELEN;			*--d = '\0';		}else if(*islong && *islong == buf[0] + 1 && *sum == buf[13]){			*islong = buf[0];		}else{			*islong = 0;			return nil;		}	}else{		if(*islong + 1 == (buf[0] & 0xbf) && *sum == buf[13]){			*islong = buf[0] & 0x3f;			if(buf[0] & 0x40)				*sum = -1;		}else{			*islong = 0;			*sum = -1;			return nil;		}	}	if(*islong > 20){		*islong = 0;		*sum = -1;		return nil;	}	return getnamerunes(d, buf, step);}voidputname(char *p, Dosdir *d){	int i;	memset(d->name, ' ', sizeof d->name+sizeof d->ext);	for(i=0; i<sizeof d->name; i++){		if(*p == 0 || *p == '.')			break;		d->name[i] = toupper(*p++);	}	p = strrchr(p, '.');	if(p){		for(i=0; i<sizeof d->ext; i++){			if(*++p == 0)				break;			d->ext[i] = toupper(*p);		}	}}static voidputnamesect(uchar *slot, Rune *longname, int curslot, int first, int sum){	Rune r;	Dosdir ds;	int i, j;	memset(&ds, 0xff, sizeof ds);	ds.attr = 0xf;	ds.reserved[0] = 0;	ds.reserved[1] = sum;	ds.start[0] = 0;	ds.start[1] = 0;	if(first)		ds.name[0] = 0x40 | curslot;	else 		ds.name[0] = curslot;	memmove(slot, &ds, sizeof ds);	j = (curslot-1) * DOSRUNE;	for(i = 1; i < 11; i += 2){		r = longname[j++];		slot[i] = r;		slot[i+1] = r >> 8;		if(r == 0)			return;	}	for(i = 14; i < 26; i += 2){		r = longname[j++];		slot[i] = r;		slot[i+1] = r >> 8;		if(r == 0)			return;	}	for(i = 28; i < 32; i += 2){		r = longname[j++];		slot[i] = r;		slot[i+1] = r >> 8;		if(r == 0)			return;	}}intaliassum(Dosdir *d){	int i, sum;	if(d == nil)		return -1;	sum = 0;	for(i = 0; i < 11; i++)		sum = (((sum&1)<<7) | ((sum&0xfe)>>1)) + d->name[i];	return sum & 0xff;}intputlongname(Xfs *xf, Dosptr *ndp, char *name, char sname[13]){	Dosbpb *bp;	Dosdir tmpd;	Rune longname[DOSNAMELEN+1];	int i, first, sum, nds, len;	/* calculate checksum */	putname(sname, &tmpd);	sum = aliassum(&tmpd);

⌨️ 快捷键说明

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