diff --git a/sys/src/cmd/hjfs/auth.c b/sys/src/cmd/hjfs/auth.c index fc2e41dca..a72b0e397 100644 --- a/sys/src/cmd/hjfs/auth.c +++ b/sys/src/cmd/hjfs/auth.c @@ -366,54 +366,14 @@ static void createuserdir(Fs *fs, char *name, short uid) { Chan *ch; - Buf *b, *c; - Dentry *d; - FLoc f; - ch = chanattach(fs, 0); + ch = chanattach(fs, CHFNOPERM); if(ch == nil) return; - ch->uid = -1; - if(chanwalk(ch, "usr") <= 0 || (ch->loc->type & QTDIR) == 0){ - direrr: - chanclunk(ch); - return; - } - chbegin(ch); - if(willmodify(ch->fs, ch->loc, 0) < 0){ - direrr1: - chend(ch); - goto direrr; - } - b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); - if(b == nil) - goto direrr1; - if(newentry(ch->fs, ch->loc, b, name, &f) <= 0){ - direrr2: - putbuf(b); - goto direrr1; - } - modified(ch, &b->de[ch->loc->deind]); - c = getbuf(ch->fs->d, f.blk, TDENTRY, 0); - if(c == nil) - goto direrr2; - c->op |= BDELWRI; - d = &c->de[f.deind]; - memset(d, 0, sizeof(*d)); - if(newqid(fs, &d->path) < 0){ - direrr3: - putbuf(c); - goto direrr2; - } - strncpy(d->name, name, NAMELEN - 1); - d->uid = uid; - d->muid = uid; - d->gid = uid; - d->mode = DALLOC | 0775; - d->type = QTDIR; - d->atime = time(0); - d->mtime = d->atime; - goto direrr3; + ch->uid = uid; + if(chanwalk(ch, "usr") > 0) + chancreat(ch, name, DMDIR | 0775, OREAD); + chanclunk(ch); } int diff --git a/sys/src/cmd/hjfs/buf.c b/sys/src/cmd/hjfs/buf.c index 51fdff162..46faa0991 100644 --- a/sys/src/cmd/hjfs/buf.c +++ b/sys/src/cmd/hjfs/buf.c @@ -266,6 +266,11 @@ getbuf(Dev *d, uvlong off, int type, int nodata) req.nodata = nodata; send(getb, &req); recv(th->resp, &b); + if(b->error != nil){ + werrstr("%s", b->error); + putbuf(b); + return nil; + } if(nodata) b->type = type; if(b->type != type && type != -1){ @@ -275,11 +280,6 @@ getbuf(Dev *d, uvlong off, int type, int nodata) putbuf(b); return nil; } - if(b->error != nil){ - werrstr("%s", b->error); - putbuf(b); - return nil; - } b->callerpc = getcallerpc(&d); return b; } diff --git a/sys/src/cmd/hjfs/conv.c b/sys/src/cmd/hjfs/conv.c index 21333e222..abedbe47a 100644 --- a/sys/src/cmd/hjfs/conv.c +++ b/sys/src/cmd/hjfs/conv.c @@ -53,7 +53,7 @@ unpack(Buf *b, uchar *p) GET64(b->sb.qidpath); break; case TDENTRY: - for(d = b->de; d < b->de + nelem(b->de); d++){ + for(d = b->de; d < &b->de[DEPERBLK]; d++){ GETS(d->name, NAMELEN); GET16(d->uid); GET16(d->muid); diff --git a/sys/src/cmd/hjfs/dat.h b/sys/src/cmd/hjfs/dat.h index 014eba424..83359d48f 100644 --- a/sys/src/cmd/hjfs/dat.h +++ b/sys/src/cmd/hjfs/dat.h @@ -185,8 +185,10 @@ enum { CHWRITE = 2, CHRCLOSE = 4, CHFDUMP = 1, + CHFNOLOCK = 2, CHFRO = 4, + CHFNOPERM = 8, CHWBUSY = 1, CHWCLUNK = 2, diff --git a/sys/src/cmd/hjfs/dump.c b/sys/src/cmd/hjfs/dump.c index 210e57964..4a9982693 100644 --- a/sys/src/cmd/hjfs/dump.c +++ b/sys/src/cmd/hjfs/dump.c @@ -24,7 +24,7 @@ copydentry(Fs *fs, FLoc *a, Loc *b, char *nname) putbuf(ba); return -1; } - rc = newentry(fs, b, bb, nname, &c); + rc = newentry(fs, b, bb, nname, &c, 1); if(rc < 0){ err1: putbuf(bb); @@ -35,7 +35,7 @@ copydentry(Fs *fs, FLoc *a, Loc *b, char *nname) if(bc == nil) goto err1; d = &bc->de[c.deind]; - memcpy(d, &ba->de[a->deind], sizeof(Dentry)); + memcpy(d, &ba->de[a->deind], sizeof(*d)); strcpy(d->name, nname); for(i = 0; i < NDIRECT; i++) if(d->db[i] != 0) @@ -116,6 +116,7 @@ int willmodify(Fs *fs, Loc *l, int nolock) { Buf *p; + Loc *m; uvlong i, r; Dentry *d; int rc; @@ -150,7 +151,7 @@ again: continue; if(r == l->blk) goto found; - } + } phase: werrstr("willmodify -- phase error"); putbuf(p); @@ -164,7 +165,19 @@ found: if(rc == 0) goto phase; putbuf(p); - l->blk = r; + + if(r != l->blk){ + /* + * block got dumped, update the loctree so locs + * point to the new block. + */ + qlock(&fs->loctree); + for(m = l->cnext; m != l; m = m->cnext) + if(m->blk == l->blk) + m->blk = r; + l->blk = r; + qunlock(&fs->loctree); + } done: l->flags |= LDUMPED; if(!nolock){ diff --git a/sys/src/cmd/hjfs/fns.h b/sys/src/cmd/hjfs/fns.h index 0a917191e..26e525e27 100644 --- a/sys/src/cmd/hjfs/fns.h +++ b/sys/src/cmd/hjfs/fns.h @@ -44,7 +44,7 @@ int trunc(Fs *, FLoc *, Buf *, uvlong); int dprint(char *fmt, ...); int delete(Fs *, FLoc *, Buf *); int chref(Fs *, uvlong, int); -int newentry(Fs *, Loc *, Buf *, char *, FLoc *); +int newentry(Fs *, Loc *, Buf *, char *, FLoc *, int); int namevalid(char *); int usersload(Fs *, Chan *); int userssave(Fs *, Chan *); diff --git a/sys/src/cmd/hjfs/fs1.c b/sys/src/cmd/hjfs/fs1.c index 6f914f911..1d463f2db 100644 --- a/sys/src/cmd/hjfs/fs1.c +++ b/sys/src/cmd/hjfs/fs1.c @@ -34,8 +34,12 @@ qidcmp(Qid *a, Qid *b) { if(a->type != b->type) return 1; - if(a->path != b->path) + if(a->path != b->path){ + /* special case for dump, this is ok */ + if(a->path==ROOTQID && b->path==DUMPROOTQID) + return 0; return 1; + } return 0; } @@ -46,12 +50,14 @@ getdent(FLoc *l, Buf *b) d = &b->de[l->deind]; if((d->mode & (DGONE | DALLOC)) == 0){ - dprint("hjfs: getdent: file gone, callerpc %#p\n", getcallerpc(&l)); + dprint("hjfs: getdent: file gone, d=%llux, l=%llud/%d %llux, callerpc %#p\n", + d->path, l->blk, l->deind, l->path, getcallerpc(&l)); werrstr("phase error -- getdent"); return nil; } if(qidcmp(d, l) != 0){ - dprint("hjfs: getdent: wrong qid, callerpc %#p\n", getcallerpc(&l)); + dprint("hjfs: getdent: wrong qid d=%llux != l=%llud/%d %llux, callerpc %#p\n", + d->path, l->blk, l->deind, l->path, getcallerpc(&l)); werrstr("phase error -- getdent"); return nil; } @@ -950,66 +956,70 @@ delete(Fs *fs, FLoc *l, Buf *b) return 0; } +/* + * newentry() looks for a free slot in the directory + * and returns FLoc pointing to the slot. if no free + * slot is available a new block is allocated. if + * dump == 0, then the resulting blk from the FLoc + * *is not* dumped, so to finally allocate the Dentry, + * one has to call willmodify() on res before modyfing it. + */ int -newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res) +newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res, int dump) { Dentry *d, *dd; uvlong i, si, r; - int j, sj, rc; + int j, sj; Buf *c; - FLoc f; si = sj = -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) - continue; - if(rc == 0 && si != -1) - continue; - c = getbuf(fs->d, r, TDENTRY, rc == 0); - if(c == nil) - continue; - if(rc == 0){ - memset(c->de, 0, sizeof(c->de)); - if(i >= d->size){ - d->size = i+1; - b->op |= BDELWRI; - } - c->op |= BDELWRI; - } - for(j = 0; j < DEPERBLK; j++){ - dd = &c->de[j]; - if((dd->mode & DALLOC) != 0){ - if(strcmp(dd->name, name) == 0){ - werrstr(Eexists); - putbuf(c); - return 0; - } + if(d != nil){ + for(i = 0; i < d->size; i++){ + if(getblk(fs, l, b, i, &r, GBREAD) <= 0) continue; - } - if(si != -1 || haveloc(fs, r, j, l)) + c = getbuf(fs->d, r, TDENTRY, 0); + if(c == nil) continue; - if((dd->mode & DGONE) != 0){ - memset(&f, 0, sizeof(f)); - f.blk = r; - f.deind = j; - f.Qid = dd->Qid; - if(delete(fs, &f, c) < 0) + for(j = 0; j < DEPERBLK; j++){ + dd = &c->de[j]; + if((dd->mode & DGONE) != 0) continue; + if((dd->mode & DALLOC) != 0){ + if(strcmp(dd->name, name) == 0){ + werrstr(Eexists); + putbuf(c); + return 0; + } + continue; + } + if(si != -1 || haveloc(fs, r, j, l)) + continue; + si = i; + sj = j; + } + putbuf(c); + } + if(si == -1 && i == d->size){ + if(getblk(fs, l, b, i, &r, GBCREATE) >= 0){ + c = getbuf(fs->d, r, TDENTRY, 1); + if(c != nil){ + si = i; + sj = 0; + d->size = i+1; + b->op |= BDELWRI; + memset(c->de, 0, sizeof(c->de)); + c->op |= BDELWRI; + putbuf(c); + } } - si = i; - sj = j; } - putbuf(c); } if(si == -1 || sj == -1){ werrstr("phase error -- create"); return -1; } - if(getblk(fs, l, b, si, &res->blk, GBWRITE) <= 0) + if(getblk(fs, l, b, si, &res->blk, dump != 0 ? GBWRITE : GBREAD) <= 0) return -1; res->deind = sj; res->Qid = (Qid){0, 0, 0}; diff --git a/sys/src/cmd/hjfs/fs2.c b/sys/src/cmd/hjfs/fs2.c index d2a4a8830..d2fd918a4 100644 --- a/sys/src/cmd/hjfs/fs2.c +++ b/sys/src/cmd/hjfs/fs2.c @@ -104,11 +104,12 @@ namevalid(char *name) int chancreat(Chan *ch, char *name, int perm, int mode) { - Buf *b, *c; + Buf *b; Dentry *d; int isdir; + Loc *l; FLoc f; - + if((ch->flags & CHFRO) != 0){ werrstr(Einval); return -1; @@ -134,6 +135,7 @@ chancreat(Chan *ch, char *name, int perm, int mode) chend(ch); return -1; } + l = nil; d = getdent(ch->loc, b); if(d == nil) goto error; @@ -141,44 +143,49 @@ chancreat(Chan *ch, char *name, int perm, int mode) werrstr(Enotadir); goto error; } - if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ - werrstr(Eperm); + if((ch->flags & CHFNOPERM) == 0) /* for console */ + if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ + werrstr(Eperm); + goto error; + } + if(newentry(ch->fs, ch->loc, b, name, &f, 0) <= 0) goto error; - } - if(newentry(ch->fs, ch->loc, b, name, &f) <= 0) - goto error; - c = getbuf(ch->fs->d, f.blk, TDENTRY, 0); - if(c == nil) - goto error; - modified(ch, d); - b->op |= BDELWRI; - c->op |= BDELWRI; if(isdir) perm &= ~0777 | d->mode & 0777; else perm &= ~0666 | d->mode & 0666; - d = &c->de[f.deind]; - memset(d, 0, sizeof(*d)); - if(newqid(ch->fs, &d->path) < 0){ - putbuf(c); + f.type = perm >> 24; + if(newqid(ch->fs, &f.path) < 0) goto error; - } - d->type = perm >> 24; + l = getloc(ch->fs, f, ch->loc); + modified(ch, d); + b->op |= BDELWRI; + putbuf(b); + b = nil; + + if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0) + goto error; + b = getbuf(ch->fs->d, l->blk, TDENTRY, 0); + if(b == nil) + goto error; + ch->loc = l; + d = &b->de[l->deind]; + memset(d, 0, sizeof(*d)); + d->Qid = l->Qid; strcpy(d->name, name); d->mtime = time(0); d->atime = d->mtime; d->gid = d->uid = d->muid = ch->uid; d->mode = DALLOC | perm & 0777; - f.Qid = d->Qid; - ch->loc = getloc(ch->fs, f, ch->loc); if((d->type & QTEXCL) != 0){ qlock(&ch->loc->ex); ch->loc->exlock = ch; ch->loc->lwrite = d->atime; qunlock(&ch->loc->ex); } - putbuf(c); + b->op |= BDELWRI; putbuf(b); + switch(mode & OEXEC){ case ORDWR: ch->open |= CHREAD; @@ -194,7 +201,10 @@ chancreat(Chan *ch, char *name, int perm, int mode) return 1; error: - putbuf(b); + if(l != nil) + putloc(ch->fs, l, 0); + if(b != nil) + putbuf(b); chend(ch); return -1; } @@ -212,6 +222,11 @@ chanopen(Chan *ch, int mode) chend(ch); return -1; } + if((mode & OTRUNC) != 0) + if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){ + chend(ch); + return -1; + } b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); if(b == nil){ chend(ch);