code: 9ferno

Download patch

ref: b222ebff6f05d02834c26d5dae0f96c8fd03d573
parent: 20533acd96fd7a8e154d8b550ba7d9615d3963b3
author: joe9 <joe9mail@gmail.com>
date: Thu Jul 22 05:38:38 EDT 2021

fix bug in direntry mode conversion

Dir.mode is a u32
Sys_dir.mode is a WORD

When converting a ~0 value from Dir.mode to Sys_dir.mode, it is not
sign extended.

The default value for Dir.mode (specified by nulldir) is ~0.

When checking for mode's default value in Sys_dir, it should be checked
for 16rFFFFFFFF along with ~0.

--- a/appl/cmd/disk/kfs.b
+++ b/appl/cmd/disk/kfs.b
@@ -1787,8 +1787,10 @@
 	# 'type' or'ed with the old directory mode;
 	# else neither are defaults, use the new mode but check
 	# it agrees with 'type'.
-
-	if(dir.qid.qtype == 16rFF && dir.mode == ~0){
+	# checking for the default value of 16rFFFFFFFF also as the
+	# conversion from Dir.mode (u32) to Sys_Dir.mode(intptr)
+	# loses the top 4 bytes and ~0 will not match in those circumstances
+	if(dir.qid.qtype == 16rFF && (dir.mode == ~0||big dir.mode == big 16rFFFFFFFF)){
 		dir.mode = d.mode & 8r777;
 		if(d.mode & DLOCK)
 			dir.mode |= DMEXCL;
@@ -1800,8 +1802,9 @@
 	else if(dir.qid.qtype == 16rFF){
 		# nothing to do
 	}
-	else if(dir.mode == ~0)
+	else if(dir.mode == ~0||big dir.mode == big 16rFFFFFFFF){
 		dir.mode = (dir.qid.qtype<<24)|(d.mode & 8r777);
+	}
 	else if(dir.qid.qtype != ((dir.mode>>24) & 16rFF)){
 		d.put();
 		return ferr(f, Eqidmode, file, p1);
--- a/os/port/inferno.c
+++ b/os/port/inferno.c
@@ -385,6 +385,13 @@
 	sd->qid.path = d->qid.path;
 	sd->qid.vers = d->qid.vers;
 	sd->qid.qtype = d->qid.type;
+	/* this is not proper. I should not
+		be checking just for ~0 but also for 16rffffffff
+		while checking for the default value of ~0 */
+	/*if(d->mode == ~0)
+		sd->mode = ~0;
+	else
+		sd->mode = d->mode;*/
 	sd->mode = d->mode;
 	sd->atime = d->atime;
 	sd->mtime = d->mtime;