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

📄 format.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	secsize = disk->secsize;	length = disk->size;	buf = malloc(secsize);	if(buf == 0)		fatal("out of memory");	/*	 * Make disk full size if a file.	 */	if(fflag && disk->type == Tfile){		if((d = dirfstat(disk->wfd)) == nil)			fatal("fstat disk: %r");		if(commit && d->length < disk->size) {			if(seek(disk->wfd, disk->size-1, 0) < 0)				fatal("seek to 9: %r");			if(write(disk->wfd, "9", 1) < 0)				fatal("writing 9: @%lld %r", seek(disk->wfd, 0LL, 1));		}		free(d);	}	/*	 * Start with initial sector from disk	 */	if(seek(disk->fd, 0, 0) < 0)		fatal("seek to boot sector: %r\n");	if(commit && read(disk->fd, buf, secsize) != secsize)		fatal("reading boot sector: %r");	if(dofat)		memset(buf, 0, sizeof(Dosboot));	/*	 * Jump instruction and OEM name.	 */	b = (Dosboot*)buf;	b->magic[0] = 0xEB;	b->magic[1] = 0x3C;	b->magic[2] = 0x90;	memmove(b->version, "Plan9.00", sizeof(b->version));		/*	 * Add bootstrapping code; assume it starts 	 * at 0x3E (the destination of the jump we just	 * wrote to b->magic).	 */	if(dopbs) {		pbsbuf = malloc(secsize);		if(pbsbuf == 0)			fatal("out of memory");		if(pbs){			if((sysfd = open(pbs, OREAD)) < 0)				fatal("open %s: %r", pbs);			if((npbs = read(sysfd, pbsbuf, secsize)) < 0)				fatal("read %s: %r", pbs);			if(npbs > secsize-2)				fatal("boot block too large");			close(sysfd);		}		else {			memmove(pbsbuf, bootprog, sizeof(bootprog));			npbs = nbootprog;		}		if(npbs <= 0x3E)			fprint(2, "warning: pbs too small\n");		else			memmove(buf+0x3E, pbsbuf+0x3E, npbs-0x3E);		free(pbsbuf);	}	/*	 * Add FAT BIOS parameter block.	 */	if(dofat) {		if(commit) {			print("Initializing FAT file system\n");			print("type %s, %d tracks, %d heads, %d sectors/track, %lld bytes/sec\n",				t->name, t->tracks, t->heads, t->sectors, secsize);		}		if(clustersize == 0)			clustersize = t->cluster;		/*		 * the number of fat bits depends on how much disk is left		 * over after you subtract out the space taken up by the fat tables. 		 * try both.  what a crock.		 */		fatbits = 12;Tryagain:		volsecs = length/secsize;		/*		 * here's a crock inside a crock.  even having fixed fatbits,		 * the number of fat sectors depends on the number of clusters,		 * but of course we don't know yet.  maybe iterating will get us there.		 * or maybe it will cycle.		 */		clusters = 0;		for(i=0;; i++){			fatsecs = (fatbits*clusters + 8*secsize - 1)/(8*secsize);			rootsecs = volsecs/200;			rootfiles = rootsecs * (secsize/sizeof(Dosdir));			if(rootfiles > 512){				rootfiles = 512;				rootsecs = rootfiles/(secsize/sizeof(Dosdir));			}			data = nresrv + 2*fatsecs + (rootfiles*sizeof(Dosdir) + secsize-1)/secsize;			newclusters = 2 + (volsecs - data)/clustersize;			if(newclusters == clusters)				break;			clusters = newclusters;			if(i > 10)				fatal("can't decide how many clusters to use (%d? %d?)", clusters, newclusters);if(chatty) print("clusters %d\n", clusters);		}				if(chatty) print("try %d fatbits => %d clusters of %d\n", fatbits, clusters, clustersize);		switch(fatbits){		case 12:			if(clusters >= 4087){				fatbits = 16;				goto Tryagain;			}			break;		case 16:			if(clusters >= 65527)				fatal("disk too big; implement fat32");			break;		}		PUTSHORT(b->sectsize, secsize);		b->clustsize = clustersize;		PUTSHORT(b->nresrv, nresrv);		b->nfats = 2;		PUTSHORT(b->rootsize, rootfiles);		if(volsecs < (1<<16))			PUTSHORT(b->volsize, volsecs);		b->mediadesc = t->media;		PUTSHORT(b->fatsize, fatsecs);		PUTSHORT(b->trksize, t->sectors);		PUTSHORT(b->nheads, t->heads);		PUTLONG(b->nhidden, disk->offset);		PUTLONG(b->bigvolsize, volsecs);			/*		 * Extended BIOS Parameter Block.		 */		if(t->media == 0xF8)			b->driveno = getdriveno(disk);		else			b->driveno = 0;if(chatty) print("driveno = %ux\n", b->driveno);			b->bootsig = 0x29;		x = disk->offset + b->nfats*fatsecs + nresrv;		PUTLONG(b->volid, x);if(chatty) print("volid = %lux %lux\n", x, GETLONG(b->volid));		memmove(b->label, label, sizeof(b->label));		sprint(r, "FAT%d    ", fatbits);		memmove(b->type, r, sizeof(b->type));	}	buf[secsize-2] = 0x55;	buf[secsize-1] = 0xAA;	if(commit) {		if(seek(disk->wfd, 0, 0) < 0)			fatal("seek to boot sector: %r\n");		if(write(disk->wfd, buf, secsize) != secsize)			fatal("writing boot sector: %r");	}	free(buf);	/*	 * If we were only called to write the PBS, leave now.	 */	if(dofat == 0)		return;	/*	 *  allocate an in memory fat	 */	if(seek(disk->wfd, nresrv*secsize, 0) < 0)		fatal("seek to fat: %r\n");if(chatty) print("fat @%lluX\n", seek(disk->wfd, 0, 1));	fat = malloc(fatsecs*secsize);	if(fat == 0)		fatal("out of memory");	memset(fat, 0, fatsecs*secsize);	fat[0] = t->media;	fat[1] = 0xff;	fat[2] = 0xff;	if(fatbits == 16)		fat[3] = 0xff;	fatlast = 1;	if(seek(disk->wfd, 2*fatsecs*secsize, 1) < 0)	/* 2 fats */		fatal("seek to root: %r");if(chatty) print("root @%lluX\n", seek(disk->wfd, 0LL, 1));	/*	 *  allocate an in memory root	 */	root = malloc(rootsecs*secsize);	if(root == 0)		fatal("out of memory");	memset(root, 0, rootsecs*secsize);	if(seek(disk->wfd, rootsecs*secsize, 1) < 0)	/* rootsecs */		fatal("seek to files: %r");if(chatty) print("files @%lluX\n", seek(disk->wfd, 0LL, 1));	/*	 * Now positioned at the Files Area.	 * If we have any arguments, process 	 * them and write out.	 */	for(p = root; argc > 0; argc--, argv++, p += sizeof(Dosdir)){		if(p >= (root+(rootsecs*secsize)))			fatal("too many files in root");		/*		 * Open the file and get its length.		 */		if((sysfd = open(*argv, OREAD)) < 0)			fatal("open %s: %r", *argv);		if((d = dirfstat(sysfd)) == nil)			fatal("stat %s: %r", *argv);		if(d->length > 0xFFFFFFFFU)			fatal("file %s too big\n", *argv, d->length);		if(commit)			print("Adding file %s, length %lld\n", *argv, d->length);		length = d->length;		if(length){			/*			 * Allocate a buffer to read the entire file into.			 * This must be rounded up to a cluster boundary.			 *			 * Read the file and write it out to the Files Area.			 */			length += secsize*clustersize - 1;			length /= secsize*clustersize;			length *= secsize*clustersize;			if((buf = malloc(length)) == 0)				fatal("out of memory");				if(readn(sysfd, buf, d->length) != d->length)				fatal("read %s: %r", *argv);			memset(buf+d->length, 0, length-d->length);if(chatty) print("%s @%lluX\n", d->name, seek(disk->wfd, 0LL, 1));			if(commit && writen(disk->wfd, buf, length) != length)				fatal("write %s: %r", *argv);			free(buf);			close(sysfd);				/*			 * Allocate the FAT clusters.			 * We're assuming here that where we			 * wrote the file is in sync with			 * the cluster allocation.			 * Save the starting cluster.			 */			length /= secsize*clustersize;			x = clustalloc(Sof);			for(n = 0; n < length-1; n++)				clustalloc(0);			clustalloc(Eof);		}		else			x = 0;		/*		 * Add the filename to the root.		 */fprint(2, "add %s at clust %lux\n", d->name, x);		addrname(p, d, *argv, x);		free(d);	}	/*	 *  write the fats and root	 */	if(commit) {		if(seek(disk->wfd, nresrv*secsize, 0) < 0)			fatal("seek to fat #1: %r");		if(write(disk->wfd, fat, fatsecs*secsize) < 0)			fatal("writing fat #1: %r");		if(write(disk->wfd, fat, fatsecs*secsize) < 0)			fatal("writing fat #2: %r");		if(write(disk->wfd, root, rootsecs*secsize) < 0)			fatal("writing root: %r");	}	free(fat);	free(root);}/* *  allocate a cluster */ulongclustalloc(int flag){	ulong o, x;	if(flag != Sof){		x = (flag == Eof) ? 0xffff : (fatlast+1);		if(fatbits == 12){			x &= 0xfff;			o = (3*fatlast)/2;			if(fatlast & 1){				fat[o] = (fat[o]&0x0f) | (x<<4);				fat[o+1] = (x>>4);			} else {				fat[o] = x;				fat[o+1] = (fat[o+1]&0xf0) | ((x>>8) & 0x0F);			}		} else {			o = 2*fatlast;			fat[o] = x;			fat[o+1] = x>>8;		}	}			if(flag == Eof)		return 0;	else{		++fatlast;		if(fatlast >= clusters)			sysfatal("data does not fit on disk (%d %d)", fatlast, clusters);		return fatlast;	}}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);		}	}}voidputtime(Dosdir *d){	Tm *t = localtime(time(0));	ushort x;	x = (t->hour<<11) | (t->min<<5) | (t->sec>>1);	d->time[0] = x;	d->time[1] = x>>8;	x = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday;	d->date[0] = x;	d->date[1] = x>>8;}voidaddrname(uchar *entry, Dir *dir, char *name, ulong start){	char *s;	Dosdir *d;	s = strrchr(name, '/');	if(s)		s++;	else		s = name;	d = (Dosdir*)entry;	putname(s, d);	if(strcmp(s, "9load") == 0)		d->attr = DSYSTEM;	else		d->attr = 0;	puttime(d);	d->start[0] = start;	d->start[1] = start>>8;	d->length[0] = dir->length;	d->length[1] = dir->length>>8;	d->length[2] = dir->length>>16;	d->length[3] = dir->length>>24;}

⌨️ 快捷键说明

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