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