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.
This commit is contained in:
cinap_lenrek 2015-10-05 04:31:31 +02:00
parent ec51877698
commit 0e09795831
4 changed files with 42 additions and 31 deletions

View file

@ -142,7 +142,8 @@ enum
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{

View file

@ -305,7 +305,7 @@ mk8dot3name(Xfile *f, Dosptr *ndp, char *name, char *sname)
* 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 @@ mkdentry(Xfs *xf, Dosptr *ndp, char *name, char *sname, int longtype, int nattr,
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 @@ rread(void)
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 @@ rwstat(void)
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);

View file

@ -674,7 +674,7 @@ emptydir(Xfile *f)
}
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 @@ error:
}
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,7 +930,12 @@ readfile(Xfile *f, void *vbuf, long offset, long count)
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);
@ -961,17 +966,24 @@ readfile(Xfile *f, void *vbuf, long offset, long count)
}
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 @@ writefile(Xfile *f, void *vbuf, long offset, long count)
rcnt += c;
o = 0;
}
if(rcnt <= 0 && addr < 0)
if(addr < 0)
return -1;
length = 0;
dlen = GLONG(d->length);
@ -1016,13 +1028,17 @@ writefile(Xfile *f, void *vbuf, long offset, long count)
}
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);
@ -1093,7 +1109,7 @@ getdir(Xfs *xfs, Dir *dp, Dosdir *d, int addr, int offset)
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 @@ dirdump(void *vdbuf)
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);
}

View file

@ -46,8 +46,8 @@ void rauth(void);
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 rwstat(void);
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);