code: plan9front

Download patch

ref: 1473e5d437e12c7312a859bcdfc167284ca99a4e
parent: f92057cc3928015d676e77e846104741d8e43b05
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Jun 13 08:43:15 EDT 2015

lib9p: fix lib9p wstat qid.type/mode checks (fixes lock(1) for ramfs/hjfs)

--- a/sys/src/cmd/ramfs.c
+++ b/sys/src/cmd/ramfs.c
@@ -335,14 +335,8 @@
 	}
 
 	if(r->d.mode != ~0){
-		f->mode = (r->d.mode & ~DMDIR) | (f->mode & DMDIR);
-		f->qid.type = 0;
-		if(f->mode & DMDIR)
-			f->qid.type |= QTDIR;
-		if(f->mode & DMAPPEND)
-			f->qid.type |= QTAPPEND;
-		if(f->mode & DMEXCL)
-			f->qid.type |= QTEXCL;
+		f->mode = r->d.mode;
+		f->qid.type = f->mode >> 24;
 	}
 	if(r->d.name[0] != '\0'){
 		free(f->name);
--- a/sys/src/lib9p/srv.c
+++ b/sys/src/lib9p/srv.c
@@ -682,25 +682,32 @@
 		respond(r, Ebaddir);
 		return;
 	}
-	if(r->d.type != (ushort)~0){
-		respond(r, "wstat -- attempt to change type");
+	if(r->d.qid.path != ~0 && r->d.qid.path != r->fid->qid.path){
+		respond(r, "wstat -- attempt to change qid.path");
 		return;
 	}
-	if(r->d.dev != ~0){
-		respond(r, "wstat -- attempt to change dev");
+	if(r->d.qid.vers != ~0 && r->d.qid.vers != r->fid->qid.vers){
+		respond(r, "wstat -- attempt to change qid.vers");
 		return;
 	}
-	if(r->d.qid.type != (uchar)~0 || r->d.qid.vers != ~0 || r->d.qid.path != ~0){
-		respond(r, "wstat -- attempt to change qid");
-		return;
-	}
-	if(r->d.muid && r->d.muid[0]){
-		respond(r, "wstat -- attempt to change muid");
-		return;
-	}
-	if(r->d.mode != ~0 && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){
-		respond(r, "wstat -- attempt to change DMDIR bit");
-		return;
+	if(r->d.mode != ~0){
+		if(r->d.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
+			respond(r, "wstat -- unknown bits in mode");
+			return;
+		}
+		if(r->d.qid.type != (uchar)~0 && r->d.qid.type != ((r->d.mode>>24)&0xFF)){
+			respond(r, "wstat -- qid.type/mode mismatch");
+			return;
+		}
+		if(((r->d.mode>>24) ^ r->fid->qid.type) & ~(QTAPPEND|QTEXCL|QTTMP)){
+			respond(r, "wstat -- attempt to change qid.type");
+			return;
+		}
+	} else {
+		if(r->d.qid.type != (uchar)~0 && r->d.qid.type != r->fid->qid.type){
+			respond(r, "wstat -- attempt to change qid.type");
+			return;
+		}
 	}
 	srv->wstat(r);
 }