shithub: riscv

Download patch

ref: b36a5dfc910b36a587f505420e6e082bd69d8b08
parent: ac2e6cf02063ca9f9769b669ef53ce5c1a764f4e
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Thu May 12 08:07:03 EDT 2011

cwfs: +t

--- a/sys/src/cmd/cwfs/9p2.c
+++ b/sys/src/cmd/cwfs/9p2.c
@@ -18,6 +18,8 @@
 		mode |= DAPND;
 	if(mode9p2 & DMDIR)
 		mode |= DDIR;
+	if(mode9p2 & DMTMP)
+		mode |= DTMP;
 
 	return mode;
 }
@@ -45,6 +47,8 @@
 		type |= QTAPPEND;
 	if(mode9p1 & DDIR)
 		type |= QTDIR;
+	if(mode9p1 & DTMP)
+		type |= QTTMP;
 
 	return type;
 }
@@ -61,6 +65,8 @@
 		mode |= DMAPPEND;
 	if(mode9p1 & DDIR)
 		mode |= DMDIR;
+	if(mode9p1 & DTMP)
+		mode |= DMTMP;
 
 	return mode;
 }
@@ -1488,7 +1494,7 @@
 		error = Ewstatq;
 		goto out;
 	}
-	if(dir.mode & ~(DMDIR|DMAPPEND|DMEXCL|0777)){
+	if(dir.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
 		error = Ewstatb;
 		goto out;
 	}
--- a/sys/src/cmd/cwfs/cw.c
+++ b/sys/src/cmd/cwfs/cw.c
@@ -1233,6 +1233,7 @@
 		putbuf(p);
 		p = 0;
 	}
+
 	state = cwio(cw->dev, addr, 0, Onone);	/* read the state (twice?) */
 	switch(state) {
 	default:
@@ -1249,7 +1250,7 @@
 		/*
 		 * botch.. could be done by relabeling
 		 */
-		if(!p) {
+		if(!p){
 			p = getbuf(cw->dev, addr, Brd);
 			if(p == nil) {
 				fprint(2, "split: null getbuf\n");
@@ -1256,6 +1257,7 @@
 				break;
 			}
 		}
+
 		na = cw->fsize;
 		cw->fsize = na+1;
 		cwio(cw->dev, na, 0, Ogrow);
@@ -1293,8 +1295,9 @@
 Off
 cwrecur(Cw *cw, Off addr, int tag, int tag1, long qp)
 {
-	Iobuf *p;
+	Iobuf *p, *b;
 	Dentry *d;
+	long qp1;
 	int i, j, shouldstop;
 	Off na;
 	char *np;
@@ -1323,6 +1326,7 @@
 	}
 	cw->depth++;
 
+	b = nil;
 	switch(tag) {
 	default:
 		fprint(2, "cwrecur: unknown tag %d %s\n", tag, cw->name);
@@ -1334,9 +1338,12 @@
 	case Tdir:
 		if(!p) {
 			p = getbuf(cw->dev, addr, Brd);
-			if(p == nil) {
-				fprint(2, "cwrecur: Tdir p null %s\n",
-					cw->name);
+			if(!p || checktag(p, tag, qp)) {
+				fprint(2, "cwrecur: Tdir p null %s\n", cw->name);
+				if(p){
+					putbuf(p);
+					p = nil;
+				}
 				break;
 			}
 		}
@@ -1353,11 +1360,12 @@
 			d = getdir(p, i);
 			if(!(d->mode & DALLOC))
 				continue;
-			qp = d->qid.path & ~QPDIR;
+			if(d->mode & DTMP)
+				continue;
+			qp1 = d->qid.path & ~QPDIR;
 			if(tag == Tdir)
 				strncpy(np, d->name, NAMELEN);
-			else
-			if(i > 0)
+			else if(i > 0)
 				fprint(2, "cwrecur: root with >1 directory\n");
 			tag1 = Tfile;
 			if(d->mode & DDIR)
@@ -1365,7 +1373,7 @@
 			for(j=0; j<NDBLOCK; j++) {
 				na = d->dblock[j];
 				if(na) {
-					na = cwrecur(cw, na, tag1, 0, qp);
+					na = cwrecur(cw, na, tag1, 0, qp1);
 					if(na) {
 						d->dblock[j] = na;
 						p->flags |= Bmod;
@@ -1375,7 +1383,7 @@
 			for (j = 0; j < NIBLOCK; j++) {
 				na = d->iblocks[j];
 				if(na) {
-					na = cwrecur(cw, na, Tind1+j, tag1, qp);
+					na = cwrecur(cw, na, Tind1+j, tag1, qp1);
 					if(na) {
 						d->iblocks[j] = na;
 						p->flags |= Bmod;
@@ -1383,6 +1391,20 @@
 				}
 			}
 		}
+
+		for(i=0; i<DIRPERBUF; i++){
+			d = getdir(p, i);
+			if(!(d->mode & DALLOC))
+				continue;
+			if(d->mode & DTMP){
+				if(!b){
+					b = getbuf(devnone, Cwtmp, 0);
+					memmove(b->iobuf, p->iobuf, RBUFSIZE);
+				}
+				memset(d, 0, sizeof(Dentry));
+				p->flags |= Bmod;
+			}
+		}
 		break;
 
 	case Tind1:
@@ -1400,8 +1422,12 @@
 	tind:
 		if(!p) {
 			p = getbuf(cw->dev, addr, Brd);
-			if(p == nil) {
+			if(!p || checktag(p, tag, qp)) {
 				fprint(2, "cwrecur: Tind p null %s\n", cw->name);
+				if(p){
+					putbuf(p);
+					p = nil;
+				}
 				break;
 			}
 		}
@@ -1417,15 +1443,35 @@
 		}
 		break;
 	}
+
 	na = split(cw, p, addr);
+
 	cw->depth--;
-	if(na && shouldstop) {
-		if(cw->falsehits < 10)
-			fprint(2, "shouldstop %lld %lld t=%s %s\n",
-				(Wideoff)addr, (Wideoff)na,
-				tagnames[tag], cw->name);
-		cw->falsehits++;
+
+	if(na){
+		if(b){
+			p = getbuf(cw->dev, na, Brd);
+			if(!p || checktag(p, tag, qp)){
+				fprint(2, "cwrecur: b/p null %s\n", cw->name);
+				na = 0;
+			} else {
+				memmove(p->iobuf, b->iobuf, RBUFSIZE);
+				p->flags |= Bmod|Bimm;
+			}
+			if(p)
+				putbuf(p);
+		}
+		if(shouldstop){
+			if(cw->falsehits < 10)
+				fprint(2, "shouldstop %lld %lld t=%s %s\n",
+					(Wideoff)addr, (Wideoff)na,
+					tagnames[tag], cw->name);
+			cw->falsehits++;
+		}
 	}
+	if(b)
+		putbuf(b);
+
 	return na;
 }
 
--- a/sys/src/cmd/cwfs/portdat.h
+++ b/sys/src/cmd/cwfs/portdat.h
@@ -126,6 +126,7 @@
 		#define	DDIR	0x4000
 		#define	DAPND	0x2000
 		#define	DLOCK	0x1000
+		#define DTMP	0x0800
 		#define	DREAD	0x4
 		#define	DWRITE	0x2
 		#define	DEXEC	0x1
@@ -621,6 +622,7 @@
 	Cwdump2,
 	Cuidbuf,
 	Cckbuf,
+	Cwtmp,
 };
 
 /*