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);