diff --git a/sys/src/cmd/hjfs/buf.c b/sys/src/cmd/hjfs/buf.c index 23f533520..51fdff162 100644 --- a/sys/src/cmd/hjfs/buf.c +++ b/sys/src/cmd/hjfs/buf.c @@ -269,7 +269,8 @@ getbuf(Dev *d, uvlong off, int type, int nodata) if(nodata) b->type = type; if(b->type != type && type != -1){ - dprint("hjfs: type mismatch, dev %s, block %lld, got %T, want %T, caller %#p\n", d->name, off, b->type, type, getcallerpc(&d)); + dprint("hjfs: type mismatch, dev %s, block %lld, got %T, want %T, caller %#p\n", + d->name, off, b->type, type, getcallerpc(&d)); werrstr("phase error -- type mismatch"); putbuf(b); return nil; diff --git a/sys/src/cmd/hjfs/dump.c b/sys/src/cmd/hjfs/dump.c index ba6dd5fc0..210e57964 100644 --- a/sys/src/cmd/hjfs/dump.c +++ b/sys/src/cmd/hjfs/dump.c @@ -143,8 +143,8 @@ again: p = getbuf(fs->d, l->next->blk, TDENTRY, 0); if(p == nil) goto err; - d = &p->de[l->next->deind]; - for(i = 0; i < d->size; i++){ + d = getdent(l->next, p); + if(d != nil) for(i = 0; i < d->size; i++){ rc = getblk(fs, l->next, p, i, &r, GBREAD); if(rc <= 0) continue; diff --git a/sys/src/cmd/hjfs/fns.h b/sys/src/cmd/hjfs/fns.h index 510392bc6..0a917191e 100644 --- a/sys/src/cmd/hjfs/fns.h +++ b/sys/src/cmd/hjfs/fns.h @@ -8,6 +8,7 @@ void unpack(Buf *, uchar *); Dev* newdev(char *); ThrData* getthrdata(void); Fs* initfs(Dev *, int, int); +Dentry* getdent(FLoc *, Buf *); int getfree(Fs *, uvlong *); int putfree(Fs *, uvlong); Chan* chanattach(Fs *, int); diff --git a/sys/src/cmd/hjfs/fs1.c b/sys/src/cmd/hjfs/fs1.c index 472e8852d..b059a39ff 100644 --- a/sys/src/cmd/hjfs/fs1.c +++ b/sys/src/cmd/hjfs/fs1.c @@ -29,6 +29,35 @@ chref(Fs *fs, uvlong r, int stat) return rc; } +static int +qidcmp(Qid *a, Qid *b) +{ + if(a->type != b->type) + return 1; + if(a->path != b->path) + return 1; + return 0; +} + +Dentry* +getdent(FLoc *l, Buf *b) +{ + Dentry *d; + + d = &b->de[l->deind]; + if((d->mode & (DGONE | DALLOC)) == 0){ + dprint("hjfs: getdent: file gone, callerpc %#p\n", getcallerpc(&l)); + werrstr("phase error -- getdent"); + return nil; + } + if(qidcmp(d, l) != 0){ + dprint("hjfs: getdent: wrong qid, callerpc %#p\n", getcallerpc(&l)); + werrstr("phase error -- getdent"); + return nil; + } + return d; +} + int getfree(Fs *fs, uvlong *r) { @@ -364,13 +393,13 @@ haveloc(Fs *fs, uvlong blk, int deind, Loc *next) qlock(&fs->loctree); l = next->child; - do{ + if(l != nil) do{ if(l->blk == blk && l->deind == deind){ qunlock(&fs->loctree); return 1; } l = l->cnext; - }while(l != next->child); + } while(l != next->child); qunlock(&fs->loctree); return 0; } @@ -511,7 +540,11 @@ getblk(Fs *fs, FLoc *L, Buf *bd, uvlong blk, uvlong *r, int mode) Dentry *d; b = bd; - d = &bd->de[L->deind]; + d = getdent(L, b); + if(d == nil){ + dprint("hjfs: getblk: dirent gone\n"); + return -1; + } if(blk < NDIRECT){ loc = &d->db[blk]; goto found; @@ -696,7 +729,9 @@ trunc(Fs *fs, FLoc *ll, Buf *bd, uvlong size) uvlong l; int i, j; - d = &bd->de[ll->deind]; + d = getdent(ll, bd); + if(d == nil) + return -1; if(size >= d->size) goto done; blk = HOWMANY(size, RBLOCK); @@ -758,7 +793,9 @@ findentry(Fs *fs, FLoc *l, Buf *b, char *name, FLoc *rl, int dump) uvlong r; Buf *c; - d = &b->de[l->deind]; + d = getdent(l, b); + if(d == nil) + return -1; for(i = 0; i < d->size; i++){ if(getblk(fs, l, b, i, &r, GBREAD) <= 0) continue; @@ -816,7 +853,10 @@ deltraverse(Fs *fs, Del *p, Buf *b, Del **last) if(b == nil) return -1; } - s = b->de[p->deind].size; + d = getdent(p, b); + if(d == nil) + return -1; + s = d->size; for(i = 0; i < s; i++){ rc = getblk(fs, p, b, i, &r, GBREAD); if(rc <= 0) @@ -835,6 +875,7 @@ deltraverse(Fs *fs, Del *p, Buf *b, Del **last) dd = emalloc(sizeof(Del)); dd->blk = i; dd->deind = j; + dd->Qid = d->Qid; dd->prev = *last; (*last)->next = dd; *last = dd; @@ -854,8 +895,10 @@ delete(Fs *fs, FLoc *l, Buf *b) Dentry *d; Buf *c; Del *first, *last, *p, *q; - - d = &b->de[l->deind]; + + d = getdent(l, b); + if(d == nil) + return -1; if((d->type & QTDIR) == 0){ trunc(fs, l, b, 0); memset(d, 0, sizeof(*d)); @@ -873,9 +916,12 @@ delete(Fs *fs, FLoc *l, Buf *b) c = getbuf(fs->d, p->blk, TDENTRY, 0); if(c == nil) continue; - trunc(fs, p, c, 0); - memset(&c->de[p->deind], 0, sizeof(Dentry)); - c->op |= BDELWRI; + d = getdent(p, c); + if(d != nil){ + trunc(fs, p, c, 0); + memset(d, 0, sizeof(*d)); + c->op |= BDELWRI; + } if(p != first) putbuf(c); } @@ -885,16 +931,16 @@ delete(Fs *fs, FLoc *l, Buf *b) int newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res) { - Dentry *d; + Dentry *d, *dd; uvlong i, si, r; int j, sj, rc; Buf *c; FLoc f; si = sj = -1; - d = &b->de[l->deind]; - for(i = 0; i <= d->size; i++){ - if(i == d->size && si != -1) + d = getdent(l, b); + if(d != nil) for(i = 0; i <= d->size; i++){ + if(i >= d->size && si != -1) break; rc = getblk(fs, l, b, i, &r, si == -1 ? GBCREATE : GBREAD); if(rc < 0) @@ -906,32 +952,34 @@ newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res) continue; if(rc == 0){ memset(c->de, 0, sizeof(c->de)); - if(i == d->size){ - d->size++; + if(i >= d->size){ + d->size = i+1; b->op |= BDELWRI; } c->op |= BDELWRI; } for(j = 0; j < DEPERBLK; j++){ - if(si == -1 && (c->de[j].mode & DALLOC) == 0){ - si = i; - sj = j; + dd = &c->de[j]; + if((dd->mode & DALLOC) != 0){ + if(strcmp(dd->name, name) == 0){ + werrstr(Eexists); + putbuf(c); + return 0; + } + continue; } - if(si == -1 && (c->de[j].mode & DGONE) != 0 && !haveloc(fs, r, j, l)){ + if(si != -1 || haveloc(fs, r, j, l)) + continue; + if((dd->mode & DGONE) != 0){ memset(&f, 0, sizeof(f)); f.blk = r; f.deind = j; - if(delete(fs, &f, c) >= 0){ - si = i; - sj = j; - } - } - if((c->de[j].mode & DALLOC) != 0 && - strcmp(c->de[j].name, name) == 0){ - werrstr(Eexists); - putbuf(c); - return 0; + f.Qid = dd->Qid; + if(delete(fs, &f, c) < 0) + continue; } + si = i; + sj = j; } putbuf(c); } @@ -942,5 +990,6 @@ newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res) if(getblk(fs, l, b, si, &res->blk, GBWRITE) <= 0) return -1; res->deind = sj; + res->Qid = (Qid){0, 0, 0}; return 1; } diff --git a/sys/src/cmd/hjfs/fs2.c b/sys/src/cmd/hjfs/fs2.c index cdc7a6cd6..d2a4a8830 100644 --- a/sys/src/cmd/hjfs/fs2.c +++ b/sys/src/cmd/hjfs/fs2.c @@ -53,7 +53,9 @@ chanwalk(Chan *ch, char *name) chend(ch); return -1; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil) + goto error; if((d->type & QTDIR) == 0){ werrstr(Enotadir); goto error; @@ -132,7 +134,9 @@ chancreat(Chan *ch, char *name, int perm, int mode) chend(ch); return -1; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil) + goto error; if((d->type & QTDIR) == 0){ werrstr(Enotadir); goto error; @@ -146,9 +150,9 @@ chancreat(Chan *ch, char *name, int perm, int mode) c = getbuf(ch->fs->d, f.blk, TDENTRY, 0); if(c == nil) goto error; - c->op |= BDELWRI; - b->op |= BDELWRI; modified(ch, d); + b->op |= BDELWRI; + c->op |= BDELWRI; if(isdir) perm &= ~0777 | d->mode & 0777; else @@ -213,7 +217,9 @@ chanopen(Chan *ch, int mode) chend(ch); return -1; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil) + goto err; if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){ permerr: werrstr(Eperm); @@ -325,7 +331,12 @@ chanwrite(Chan *ch, void *buf, ulong n, uvlong off) chend(ch); return -1; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil){ + putbuf(b); + chend(ch); + return -1; + } if((d->type & QTAPPEND) != 0) off = d->size; e = off + n; @@ -392,7 +403,12 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off) chend(ch); return -1; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil){ + putbuf(b); + chend(ch); + return -1; + } if(off >= d->size) n = 0; else if(off + n > d->size) @@ -465,6 +481,7 @@ int chanstat(Chan *ch, Dir *di) { Buf *b; + Dentry *d; chbegin(ch); b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); @@ -472,7 +489,13 @@ chanstat(Chan *ch, Dir *di) chend(ch); return -1; } - statbuf(ch->fs, &b->de[ch->loc->deind], di, nil); + d = getdent(ch->loc, b); + if(d == nil){ + putbuf(b); + chend(ch); + return -1; + } + statbuf(ch->fs, d, di, nil); putbuf(b); chend(ch); return 0; @@ -504,7 +527,12 @@ chandirread(Chan *ch, void *buf, ulong n, uvlong off) chend(ch); return -1; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil){ + putbuf(b); + chend(ch); + return -1; + } if(ch->dwblk >= d->size){ putbuf(b); chend(ch); @@ -590,11 +618,16 @@ chanclunk(Chan *ch) b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); if(b == nil) goto err; - if(!permcheck(ch->fs, &p->de[ch->loc->next->deind], ch->uid, OWRITE)){ + d = getdent(ch->loc->next, p); + if(d == nil) + goto err; + if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ werrstr(Eperm); goto err; } - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil) + goto err; if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0) goto inval; if((d->mode & DGONE) != 0) @@ -653,7 +686,10 @@ chanwstat(Chan *ch, Dir *di) pb = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0); if(pb == nil) goto error; - if(!permcheck(ch->fs, &pb->de[ch->loc->next->deind], ch->uid, OWRITE)) + d = getdent(ch->loc->next, pb); + if(d == nil) + goto error; + if(!permcheck(ch->fs, d, ch->uid, OWRITE)) goto perm; rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP); if(rc > 0) @@ -664,7 +700,9 @@ chanwstat(Chan *ch, Dir *di) b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); if(b == nil) goto error; - d = &b->de[ch->loc->deind]; + d = getdent(ch->loc, b); + if(d == nil) + goto error; isdir = (d->type & QTDIR) != 0; owner = ch->uid == d->uid || ingroup(ch->fs, ch->uid, d->gid, 1) || (ch->fs->flags & FSNOPERM) != 0; if((uvlong)~di->length){