shithub: drawterm

Download patch

ref: 2d15857c35ea4aa8cea1d32600bfdbf776411e4c
parent: 2c1e851527d9803cc586d129613fb052d932eda4
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Oct 23 09:54:40 EDT 2021

add dirchanstat() from 9front to handle seek bug

--- a/kern/chan.c
+++ b/kern/chan.c
@@ -1600,3 +1600,42 @@
 		return;
 	error(Enotdir);
 }
+
+
+enum
+{
+	DIRSIZE	= STATFIXLEN + 16 * 4		/* enough for encoded stat buf + some reasonable strings */
+};
+
+Dir*
+dirchanstat(Chan *c)
+{
+	Dir *d;
+	uchar *buf;
+	int n, nd, i;
+
+	nd = DIRSIZE;
+	for(i=0; i<2; i++){	/* should work by the second try */
+		d = smalloc(sizeof(Dir) + BIT16SZ + nd);
+		if(waserror()){
+			free(d);
+			nexterror();
+		}
+		buf = (uchar*)&d[1];
+		n = devtab[c->type]->stat(c, buf, BIT16SZ+nd);
+		if(n < BIT16SZ)
+			error(Eshortstat);
+		nd = GBIT16(buf);	/* upper bound on size of Dir + strings */
+		if(nd <= n){
+			if(convM2D(buf, n, d, (char*)&d[1]) == 0)
+				error(Eshortstat);
+			poperror();
+			return d;
+		}
+		/* else sizeof(Dir)+BIT16SZ+nd is plenty */
+		free(d);
+		poperror();
+	}
+	error(Eshortstat);
+	return nil;
+}
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -50,6 +50,7 @@
 int		devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
 Walkqid*	devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
 int		devwstat(Chan*, uchar*, int);
+Dir*		dirchanstat(Chan*);
 void		drawcmap(void);
 Fgrp*		dupfgrp(Fgrp*);
 int		emptystr(char*);
--- a/kern/sysfile.c
+++ b/kern/sysfile.c
@@ -503,9 +503,7 @@
 _sysseek(int fd, vlong off, int whence)
 {
 	Chan *c;
-	uchar buf[sizeof(Dir)+100];
-	Dir dir;
-	int n;
+	Dir *d;
 
 	c = fdtochan(fd, -1, 1, 1);
 	if(waserror()){
@@ -538,10 +536,9 @@
 	case 2:
 		if(c->qid.type & QTDIR)
 			error(Eisdir);
-		n = devtab[c->type]->stat(c, buf, sizeof buf);
-		if(convM2D(buf, n, &dir, nil) == 0)
-			error("internal error: stat error in seek");
-		off = dir.length + off;
+		d = dirchanstat(c);
+		off = d->length + off;
+		free(d);
 		if(off < 0)
 			error(Enegoff);
 		c->offset = off;