summaryrefslogtreecommitdiff
path: root/sys/src/cmd/hjfs
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-11-16 13:42:45 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2012-11-16 13:42:45 +0100
commitb9bf9f1d547fe819d87d7dbb2ec58bd0b53d711a (patch)
treed907e23196cc187295dd99b16e3e94293e7ddb62 /sys/src/cmd/hjfs
parentffa6f9c6ea8ce11c7ed895d5efb1458f256106fd (diff)
hjfs: dentry qid checking, prevent newentry() from allocating already in use slot
always check if the directory entry qid from the loc still matches the one on disk before doing anything. helps catching bugs and is basically equivalent to what cwfs does with its checktag. make a haveloc() check in newentry() to make sure we dont allocate a file slot thats still in use, but deleted. this seems to fix the NPROC>1 build problems.
Diffstat (limited to 'sys/src/cmd/hjfs')
-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){