summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/cmd/hjfs/buf.c3
-rw-r--r--sys/src/cmd/hjfs/dump.c4
-rw-r--r--sys/src/cmd/hjfs/fns.h1
-rw-r--r--sys/src/cmd/hjfs/fs1.c111
-rw-r--r--sys/src/cmd/hjfs/fs2.c64
5 files changed, 136 insertions, 47 deletions
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){