git: 9front

Download patch

ref: db3f78629fffa47aa537b3128ae4c25e8cc8bb33
parent: 96b8ccceae687c6653470f6690ff2eeca6f47d33
author: Jacob Moody <moody@posixcafe.org>
date: Sat Jul 29 15:20:04 EDT 2023

kernel: make walk/open errors more consistent with userspace

As is the error for an open would be in the form:
	'filename' does not exist
This changes it to be of the form:
	file does not exist: 'filename'

This brings it more in line with what could
be expected from a userspace filesystem.
Existing code, perhaps due to this discrepancy,
all uses strstr to check for this error. They can
now instead check for explicitly the error as a prefix.
This would avoid issues with potentially maliciously
named files such as "does not exist".

Likewise this also helps filesystems such as exportfs,
which spit back the errstr from open(2) directly as Rerror
to their clients.

--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -950,7 +950,6 @@
  * Either walks all the way or not at all.  No partial results in *cp.
  * *nerror is the number of names to display in an error message.
  */
-static char Edoesnotexist[] = "does not exist";
 int
 walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 {
@@ -1066,7 +1065,7 @@
 					if(wq->nqid == 0 || (wq->qid[wq->nqid-1].type&QTDIR) != 0){
 						if(nerror)
 							*nerror = nhave+wq->nqid+1;
-						kstrcpy(up->errstr, Edoesnotexist, ERRMAX);
+						kstrcpy(up->errstr, Enonexist, ERRMAX);
 					}else{
 						if(nerror)
 							*nerror = nhave+wq->nqid;
@@ -1204,7 +1203,7 @@
 	}
 }
 
-static void
+void
 namelenerror(char *aname, int len, char *err)
 {
 	char *ename, *name, *next;
@@ -1247,14 +1246,8 @@
 		snprint(up->genbuf, sizeof up->genbuf, "...%.*s",
 			utfnlen(name, ename-name), name);
 	}				
-	snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, err);
+	snprint(up->errstr, ERRMAX, "%s: %#q", err, up->genbuf);
 	nexterror();
-}
-
-void
-nameerror(char *name, char *err)
-{
-	namelenerror(name, strlen(name), err);
 }
 
 /*
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -206,7 +206,7 @@
 void		mul64fract(uvlong*, uvlong, uvlong);
 void		muxclose(Mnt*);
 Chan*		namec(char*, int, int, ulong);
-void		nameerror(char*, char*);
+void		namelenerror(char*, int, char*);
 int		needpages(void*);
 Chan*		newchan(void);
 int		newfd(Chan*, int);
--- a/sys/src/9/port/sysfile.c
+++ b/sys/src/9/port/sysfile.c
@@ -1233,6 +1233,7 @@
 {
 	long l;
 	int namelen;
+	char *p;
 
 	if(waserror()){
 		cclose(c);
@@ -1244,8 +1245,10 @@
 		 * (which should be renamed? the mount point or the mounted Chan?).
 		 */
 		dirname(d, &namelen);
-		if(namelen)
-			nameerror(chanpath(c), Eismtpt);
+		if(namelen){
+			p = chanpath(c);
+			namelenerror(p, strlen(p), Eismtpt);
+		}
 	}
 	l = devtab[c->type]->wstat(c, d, nd);
 	poperror();
--