shithub: riscv

Download patch

ref: f286eda5878116e4bc8dc08266a5ca499c8378f6
parent: cb8d49e3c2026324252377e601550758dfa30b83
parent: 9a3942718357a83c534ee5a37ae9bd3bc85a2f50
author: cinap_lenrek <[email protected]>
date: Sat Nov 17 20:12:27 EST 2012

merge

--- a/sys/src/cmd/hjfs/auth.c
+++ b/sys/src/cmd/hjfs/auth.c
@@ -366,54 +366,14 @@
 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
--- a/sys/src/cmd/hjfs/buf.c
+++ b/sys/src/cmd/hjfs/buf.c
@@ -266,6 +266,11 @@
 	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){
@@ -272,11 +277,6 @@
 		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;
-	}
-	if(b->error != nil){
-		werrstr("%s", b->error);
 		putbuf(b);
 		return nil;
 	}
--- a/sys/src/cmd/hjfs/conv.c
+++ b/sys/src/cmd/hjfs/conv.c
@@ -53,7 +53,7 @@
 		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);
--- a/sys/src/cmd/hjfs/dat.h
+++ b/sys/src/cmd/hjfs/dat.h
@@ -185,8 +185,10 @@
 	CHWRITE = 2,
 	CHRCLOSE = 4,
 	CHFDUMP = 1,
+
 	CHFNOLOCK = 2,
 	CHFRO = 4,
+	CHFNOPERM = 8,
 	
 	CHWBUSY = 1,
 	CHWCLUNK = 2,
--- a/sys/src/cmd/hjfs/dump.c
+++ b/sys/src/cmd/hjfs/dump.c
@@ -24,7 +24,7 @@
 		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 @@
 	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 @@
 willmodify(Fs *fs, Loc *l, int nolock)
 {
 	Buf *p;
+	Loc *m;
 	uvlong i, r;
 	Dentry *d;
 	int rc;
@@ -150,7 +151,7 @@
 			continue;
 		if(r == l->blk)
 			goto found;
-	}
+	}	
 phase:
 	werrstr("willmodify -- phase error");
 	putbuf(p);
@@ -164,7 +165,19 @@
 	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){
--- a/sys/src/cmd/hjfs/fns.h
+++ b/sys/src/cmd/hjfs/fns.h
@@ -44,7 +44,7 @@
 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 *);
--- a/sys/src/cmd/hjfs/fs1.c
+++ b/sys/src/cmd/hjfs/fs1.c
@@ -34,8 +34,12 @@
 {
 	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 @@
 
 	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 @@
 	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;
+	if(d != nil){
+		for(i = 0; i < d->size; i++){
+			if(getblk(fs, l, b, i, &r, GBREAD) <= 0)
+				continue;
+			c = getbuf(fs->d, r, TDENTRY, 0);
+			if(c == nil)
+				continue;
+			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;
 			}
-			c->op |= BDELWRI;
+			putbuf(c);
 		}
-		for(j = 0; j < DEPERBLK; j++){
-			dd = &c->de[j];
-			if((dd->mode & DALLOC) != 0){
-				if(strcmp(dd->name, name) == 0){
-					werrstr(Eexists);
+		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);
-					return 0;
 				}
-				continue;
 			}
-			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;
-				f.Qid = dd->Qid;
-				if(delete(fs, &f, c) < 0)
-					continue;
-			}
-			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};
--- a/sys/src/cmd/hjfs/fs2.c
+++ b/sys/src/cmd/hjfs/fs2.c
@@ -104,11 +104,12 @@
 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 @@
 		chend(ch);
 		return -1;
 	}
+	l = nil;
 	d = getdent(ch->loc, b);
 	if(d == nil)
 		goto error;
@@ -141,36 +143,40 @@
 		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;
@@ -177,8 +183,9 @@
 		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 @@
 	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 @@
 		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);