📄 format.c
字号:
} 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 + -