shithub: riscv

Download patch

ref: 0e09795831f37b86206e4dc9b3a0ac8bcd90401e
parent: ec518776982d6d1173683a1108e7537fc329ed43
author: cinap_lenrek <[email protected]>
date: Mon Oct 5 00:31:31 EDT 2015

dossrv: handle file offsets > 2^31

maximum file size is 4GB-1 as the file length is stored in
a 32 bit long. make sure it doesnt overflow on write or
or truncate. interpret the file length as unsigned. pass
vlong to readfile()/writefile()/truncfile() so we can
handle overflows and not just ignore the upper bits.

--- a/sys/src/cmd/dossrv/dat.h
+++ b/sys/src/cmd/dossrv/dat.h
@@ -142,7 +142,8 @@
 	DOSDIRSIZE	= 32,
 	DOSEMPTY	= 0xe5,			/* first char in name if entry is unused */
 	DOSRUNE		= 13,			/* runes per dosdir in a long file name */
-	DOSNAMELEN	= 261			/* max dos file name length */
+	DOSNAMELEN	= 261,			/* max dos file name length */
+	MAXFILELEN	= 0xFFFFFFFFUL,
 };
 
 struct Dosdir{
--- a/sys/src/cmd/dossrv/dosfs.c
+++ b/sys/src/cmd/dossrv/dosfs.c
@@ -305,7 +305,7 @@
  * fill in a directory entry for a new file
  */
 static int
-mkdentry(Xfs *xf, Dosptr *ndp, char *name, char *sname, int longtype, int nattr, long start, long length)
+mkdentry(Xfs *xf, Dosptr *ndp, char *name, char *sname, int longtype, int nattr, long start, ulong length)
 {
 	Dosdir *nd;
 
@@ -333,10 +333,7 @@
 	PSHORT(nd->ctime, GSHORT(nd->time));
 	nd->ctimetenth = 0;
 	putstart(xf, nd, start);
-	nd->length[0] = length;
-	nd->length[1] = length>>8;
-	nd->length[2] = length>>16;
-	nd->length[3] = length>>24;
+	PLONG(nd->length, length);
 
 	ndp->p->flags |= BMOD;
 
@@ -506,16 +503,13 @@
 	if (!(f=xfile(req->fid, Asis)) || !(f->flags&Oread))
 		goto error;
 	if(req->count > sizeof repdata)
-		req->count = sizeof repdata;
-	if(f->qid.type & QTDIR){
-		if(getfile(f) < 0)
-			goto error;
+		req->count = sizeof repdata;		
+	if(getfile(f) < 0)
+		goto error;
+	if(f->qid.type & QTDIR)
 		r = readdir(f, repdata, req->offset, req->count);
-	}else{
-		if(getfile(f) < 0)
-			goto error;
+	else
 		r = readfile(f, repdata, req->offset, req->count);
-	}
 	putfile(f);
 	if(r < 0){
 error:
@@ -711,8 +705,8 @@
 	Iosect *parp;
 	Dosdir *pard, *d, od;
 	char sname[13];
-	ulong oaddr, ooffset;
-	long start, length;
+	ulong oaddr, ooffset, length;
+	long start;
 	int i, longtype, changes, attr;
 
 	f = xfile(req->fid, Asis);
--- a/sys/src/cmd/dossrv/dossubs.c
+++ b/sys/src/cmd/dossrv/dossubs.c
@@ -674,7 +674,7 @@
 }
 
 long
-readdir(Xfile *f, void *vbuf, long offset, long count)
+readdir(Xfile *f, void *vbuf, vlong offset, long count)
 {
 	Xfs *xf;
 	Dosbpb *bp;
@@ -921,7 +921,7 @@
 }
 
 long
-readfile(Xfile *f, void *vbuf, long offset, long count)
+readfile(Xfile *f, void *vbuf, vlong offset, long count)
 {
 	Xfs *xf = f->xf;
 	Dosbpb *bp = xf->ptr;
@@ -930,8 +930,13 @@
 	int isect, addr, o, c;
 	Iosect *p;
 	uchar *buf;
-	long length, rcnt;
+	ulong length, rcnt;
 
+	if(offset >= MAXFILELEN)
+		return 0;
+	if(offset+count > MAXFILELEN)
+		count = MAXFILELEN - offset;
+
 	rcnt = 0;
 	length = GLONG(d->length);
 	buf = vbuf;
@@ -961,17 +966,24 @@
 }
 
 long
-writefile(Xfile *f, void *vbuf, long offset, long count)
+writefile(Xfile *f, void *vbuf, vlong offset, long count)
 {
 	Xfs *xf = f->xf;
 	Dosbpb *bp = xf->ptr;
 	Dosptr *dp = f->ptr;
 	Dosdir *d = dp->d;
-	int isect, addr = 0, o, c;
+	int isect, addr, o, c;
 	Iosect *p;
 	uchar *buf;
-	long length, rcnt = 0, dlen;
+	ulong length, rcnt, dlen;
 
+	if(offset >= MAXFILELEN)
+		return 0;
+	if(offset+count > MAXFILELEN)
+		count = MAXFILELEN - offset;
+
+	rcnt = 0;
+	addr = 0;
 	buf = vbuf;
 	isect = offset/bp->sectsize;
 	o = offset%bp->sectsize;
@@ -997,7 +1009,7 @@
 		rcnt += c;
 		o = 0;
 	}
-	if(rcnt <= 0 && addr < 0)
+	if(addr < 0)
 		return -1;
 	length = 0;
 	dlen = GLONG(d->length);
@@ -1016,14 +1028,18 @@
 }
 
 int
-truncfile(Xfile *f, long length)
+truncfile(Xfile *f, vlong length)
 {
 	Xfs *xf = f->xf;
 	Dosbpb *bp = xf->ptr;
 	Dosptr *dp = f->ptr;
 	Dosdir *d = dp->d;
-	long clust, next, n;
+	long clust, next;
+	vlong n;
 
+	if(length > MAXFILELEN)
+		return -1;
+
 	mlock(bp);
 	clust = getstart(f->xf, d);
 	n = length;
@@ -1093,7 +1109,7 @@
 		dp->mode |= DMDIR|0111;
 		dp->length = 0;
 	}else
-		dp->length = GLONG(d->length);
+		dp->length = (ulong)GLONG(d->length);
 	if(d->attr & DSYSTEM){
 		dp->mode |= DMEXCL;
 		if(iscontig(xfs, d))
@@ -1898,7 +1914,7 @@
 		i = GSHORT(d->adate);
 		s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);
 
-		seprint(s, ebuf, " %d %d", GSHORT(d->start), GSHORT(d->length));
+		seprint(s, ebuf, " %d %lud", GSHORT(d->start), (ulong)GLONG(d->length));
 	}
 	chat("%s\n", buf);
 }
--- a/sys/src/cmd/dossrv/fns.h
+++ b/sys/src/cmd/dossrv/fns.h
@@ -46,8 +46,8 @@
 void	rclone(void);
 void	rclunk(void);
 void	rcreate(void);
-long	readdir(Xfile*, void*, long, long);
-long	readfile(Xfile*, void*, long, long);
+long	readdir(Xfile*, void*, vlong, long);
+long	readfile(Xfile*, void*, vlong, long);
 void	refxfs(Xfs*, int);
 void	rflush(void);
 void	rootfile(Xfile*);
@@ -61,10 +61,10 @@
 void	rversion(void);
 int	searchdir(Xfile*, char*, Dosptr*, int, int);
 long	sect2clust(Dosbpb*, long);
-int	truncfile(Xfile*, long length);
+int	truncfile(Xfile*, vlong length);
 int	utftorunes(Rune*, char*, int);
 int	walkup(Xfile*, Dosptr*);
-long	writefile(Xfile*, void*, long, long);
+long	writefile(Xfile*, void*, vlong, long);
 char	*xerrstr(int);
 Xfile	*xfile(int, int);
 int	xfspurge(void);