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;