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