shithub: gefs

Download patch

ref: 7fa15946915dfffc3856c9075b20f591d1b00195
parent: 5bdac7aa918b452953323093051c758938e381fe
author: Ori Bernstein <ori@eigenstate.org>
date: Sun May 7 21:21:05 EDT 2023

fs: give correct errors on rename and create

return Efsrch instead of Eexist when something doesn't
exist, and check if we're clobbering a file with wstat

--- a/dat.h
+++ b/dat.h
@@ -129,6 +129,8 @@
 extern char Efid[];
 extern char Etype[];
 extern char Edscan[];
+extern char Esrch[];
+extern char Efsrch[];
 extern char Eexist[];
 extern char Emode[];
 extern char Efull[];
@@ -551,6 +553,7 @@
 	Key;
 	Xdir;
 	Dent	*next;
+	vlong	up;
 	long	ref;
 	char	gone;
 
--- a/error.c
+++ b/error.c
@@ -11,6 +11,8 @@
 char Efid[]	= "fid in use";
 char Etype[]	= "invalid fid type";
 char Edscan[]	= "invalid dir scan offset";
+char Esrch[]	= "key not found";
+char Efsrch[]	= "directory entry not found";
 char Eexist[]	= "create/wstat -- file exists";
 char Emode[]	= "open/create -- unknown mode";
 char Efull[]	= "file system full";
--- a/fs.c
+++ b/fs.c
@@ -320,7 +320,7 @@
 
 	e = lookup(f->mnt, &k, &kv, kvbuf, sizeof(kvbuf));
 	if(e != nil){
-		if(e != Eexist){
+		if(e != Esrch){
 			werrstr(e);
 			return -1;
 		}
@@ -369,7 +369,7 @@
 			memcpy(b->buf, t->buf, Blksz);
 			freeblk(f->mnt->root, t);
 			dropblk(t);
-		}else if(e != Eexist){
+		}else if(e != Esrch){
 			werrstr("%s", e);
 			return -1;
 		}
@@ -411,6 +411,7 @@
 		goto Out;
 	de->Xdir = *d;
 	de->ref = 1;
+	de->up = pqid;
 	de->qid = d->qid;
 	de->length = d->length;
 
@@ -528,13 +529,13 @@
 	Conn *c;
 
 	for(c = fs->conns; c != nil; c = c->next){
-		fprint(fd, "fids:%d\n", c->rfd);
+		fprint(fd, "fids:\n");
 		for(i = 0; i < Nfidtab; i++){
 			lock(&c->fidtablk[i]);
 			for(f = c->fidtab[i]; f != nil; f = f->next){
 				rlock(f->dent);
-				fprint(fd, "\tfid[%d]: %d [refs=%ld, k=%K, qid=%Q]\n",
-					i, f->fid, f->dent->ref, &f->dent->Key, f->dent->qid);
+				fprint(fd, "\tfid[%d] from %#zx: %d [refs=%ld, k=%K, qid=%Q]\n",
+					i, getmalloctag(f), f->fid, f->dent->ref, &f->dent->Key, f->dent->qid);
 				runlock(f->dent);
 			}
 			unlock(&c->fidtablk[i]);
@@ -603,6 +604,7 @@
 	if(n->mnt != nil)
 		ainc(&n->mnt->ref);
 	ainc(&n->dent->ref);
+	setmalloctag(n, getcallerpc(&c));
 	return n;
 }
 
@@ -1078,7 +1080,7 @@
 		name = m->wname[i];
 		if(d.qid.path == Qdump){
 			if((mnt = getmount(m->wname[i])) == nil){
-				rerror(m, Eexist);
+				rerror(m, Efsrch);
 				putfid(o);
 				return;
 			}
@@ -1202,6 +1204,8 @@
 	char rnbuf[Kvmax], opbuf[Kvmax], upbuf[Upksz];
 	char *p, *e, strs[65535];
 	int op, nm, rename;
+	vlong oldlen;
+	Qid old;
 	Fcall r;
 	Dent *de;
 	Msg mb[3];
@@ -1254,6 +1258,10 @@
 				rerror(m, Ename);
 				goto Out;
 			}
+			if(walk1(f->mnt->root, f->dent->up, d.name, &old, &oldlen) == 0){
+				rerror(m, Eexist);
+				goto Out;
+			}
 			n.name = d.name;
 		}
 	}
@@ -1433,9 +1441,8 @@
 		free(f->scan);
 		f->scan = nil;
 	}
-	unlock(f);
-
 	clunkfid(m->conn, f);
+	unlock(f);
 	r.type = Rclunk;
 	respond(m, &r);
 	putfid(f);
@@ -1470,7 +1477,7 @@
 	de = f->dent;
 
 	if(walk1(f->mnt->root, f->qpath, m->name, &old, &oldlen) == 0){
-		rerror(m, Emode);
+		rerror(m, Eexist);
 		putfid(f);
 		return;
 	}
@@ -1477,8 +1484,8 @@
 
 	rlock(de);
 	if(fsaccess(f, de->mode, de->uid, de->gid, DMWRITE) == -1){
+		rerror(m, Eperm);
 		runlock(de);
-		rerror(m, Eexist);
 		putfid(f);
 		return;
 	}
@@ -1677,15 +1684,17 @@
 	wlock(f->dent);
 	if(f->dent->gone){
 		rerror(m, Ephase);
-		wunlock(f->dent);
+Disallow:	wunlock(f->dent);
 		putfid(f);
 		return;
 	}
+	if(f->dent->mode & DMEXCL){
+		rerror(m, Elocked);
+		goto Disallow;
+	}
 	if(fsaccess(f, d.mode, d.uid, d.gid, mbits) == -1){
 		rerror(m, Eperm);
-		wunlock(f->dent);
-		putfid(f);
-		return;
+		goto Disallow;
 	}
 	f->dent->length = d.length;
 	wunlock(f->dent);
--- a/tree.c
+++ b/tree.c
@@ -1320,7 +1320,7 @@
 		dropblk(b);
 		return Enomem;
 	}
-	err = Eexist;
+	err = Esrch;
 	ok = 0;
 	p[0] = holdblk(b);
 	for(i = 1; i < h; i++){