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, DOSDIRSIZE = 32,
DOSEMPTY = 0xe5, /* first char in name if entry is unused */ DOSEMPTY = 0xe5, /* first char in name if entry is unused */
DOSRUNE = 13, /* runes per dosdir in a long file name */ 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{ 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 * fill in a directory entry for a new file
*/ */
static int 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; 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)); PSHORT(nd->ctime, GSHORT(nd->time));
nd->ctimetenth = 0; nd->ctimetenth = 0;
putstart(xf, nd, start); putstart(xf, nd, start);
nd->length[0] = length; PLONG(nd->length, length);
nd->length[1] = length>>8;
nd->length[2] = length>>16;
nd->length[3] = length>>24;
ndp->p->flags |= BMOD; ndp->p->flags |= BMOD;
@ -506,16 +503,13 @@ rread(void)
if (!(f=xfile(req->fid, Asis)) || !(f->flags&Oread)) if (!(f=xfile(req->fid, Asis)) || !(f->flags&Oread))
goto error; goto error;
if(req->count > sizeof repdata) if(req->count > sizeof repdata)
req->count = sizeof repdata; req->count = sizeof repdata;
if(f->qid.type & QTDIR){ if(getfile(f) < 0)
if(getfile(f) < 0) goto error;
goto error; if(f->qid.type & QTDIR)
r = readdir(f, repdata, req->offset, req->count); r = readdir(f, repdata, req->offset, req->count);
}else{ else
if(getfile(f) < 0)
goto error;
r = readfile(f, repdata, req->offset, req->count); r = readfile(f, repdata, req->offset, req->count);
}
putfile(f); putfile(f);
if(r < 0){ if(r < 0){
error: error:
@ -711,8 +705,8 @@ rwstat(void)
Iosect *parp; Iosect *parp;
Dosdir *pard, *d, od; Dosdir *pard, *d, od;
char sname[13]; char sname[13];
ulong oaddr, ooffset; ulong oaddr, ooffset, length;
long start, length; long start;
int i, longtype, changes, attr; int i, longtype, changes, attr;
f = xfile(req->fid, Asis); f = xfile(req->fid, Asis);

View file

@ -674,7 +674,7 @@ emptydir(Xfile *f)
} }
long long
readdir(Xfile *f, void *vbuf, long offset, long count) readdir(Xfile *f, void *vbuf, vlong offset, long count)
{ {
Xfs *xf; Xfs *xf;
Dosbpb *bp; Dosbpb *bp;
@ -921,7 +921,7 @@ error:
} }
long long
readfile(Xfile *f, void *vbuf, long offset, long count) readfile(Xfile *f, void *vbuf, vlong offset, long count)
{ {
Xfs *xf = f->xf; Xfs *xf = f->xf;
Dosbpb *bp = xf->ptr; Dosbpb *bp = xf->ptr;
@ -930,7 +930,12 @@ readfile(Xfile *f, void *vbuf, long offset, long count)
int isect, addr, o, c; int isect, addr, o, c;
Iosect *p; Iosect *p;
uchar *buf; uchar *buf;
long length, rcnt; ulong length, rcnt;
if(offset >= MAXFILELEN)
return 0;
if(offset+count > MAXFILELEN)
count = MAXFILELEN - offset;
rcnt = 0; rcnt = 0;
length = GLONG(d->length); length = GLONG(d->length);
@ -961,17 +966,24 @@ readfile(Xfile *f, void *vbuf, long offset, long count)
} }
long long
writefile(Xfile *f, void *vbuf, long offset, long count) writefile(Xfile *f, void *vbuf, vlong offset, long count)
{ {
Xfs *xf = f->xf; Xfs *xf = f->xf;
Dosbpb *bp = xf->ptr; Dosbpb *bp = xf->ptr;
Dosptr *dp = f->ptr; Dosptr *dp = f->ptr;
Dosdir *d = dp->d; Dosdir *d = dp->d;
int isect, addr = 0, o, c; int isect, addr, o, c;
Iosect *p; Iosect *p;
uchar *buf; 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; buf = vbuf;
isect = offset/bp->sectsize; isect = offset/bp->sectsize;
o = offset%bp->sectsize; o = offset%bp->sectsize;
@ -997,7 +1009,7 @@ writefile(Xfile *f, void *vbuf, long offset, long count)
rcnt += c; rcnt += c;
o = 0; o = 0;
} }
if(rcnt <= 0 && addr < 0) if(addr < 0)
return -1; return -1;
length = 0; length = 0;
dlen = GLONG(d->length); dlen = GLONG(d->length);
@ -1016,13 +1028,17 @@ writefile(Xfile *f, void *vbuf, long offset, long count)
} }
int int
truncfile(Xfile *f, long length) truncfile(Xfile *f, vlong length)
{ {
Xfs *xf = f->xf; Xfs *xf = f->xf;
Dosbpb *bp = xf->ptr; Dosbpb *bp = xf->ptr;
Dosptr *dp = f->ptr; Dosptr *dp = f->ptr;
Dosdir *d = dp->d; Dosdir *d = dp->d;
long clust, next, n; long clust, next;
vlong n;
if(length > MAXFILELEN)
return -1;
mlock(bp); mlock(bp);
clust = getstart(f->xf, d); 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->mode |= DMDIR|0111;
dp->length = 0; dp->length = 0;
}else }else
dp->length = GLONG(d->length); dp->length = (ulong)GLONG(d->length);
if(d->attr & DSYSTEM){ if(d->attr & DSYSTEM){
dp->mode |= DMEXCL; dp->mode |= DMEXCL;
if(iscontig(xfs, d)) if(iscontig(xfs, d))
@ -1898,7 +1914,7 @@ dirdump(void *vdbuf)
i = GSHORT(d->adate); i = GSHORT(d->adate);
s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31); 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); chat("%s\n", buf);
} }

View file

@ -46,8 +46,8 @@ void rauth(void);
void rclone(void); void rclone(void);
void rclunk(void); void rclunk(void);
void rcreate(void); void rcreate(void);
long readdir(Xfile*, void*, long, long); long readdir(Xfile*, void*, vlong, long);
long readfile(Xfile*, void*, long, long); long readfile(Xfile*, void*, vlong, long);
void refxfs(Xfs*, int); void refxfs(Xfs*, int);
void rflush(void); void rflush(void);
void rootfile(Xfile*); void rootfile(Xfile*);
@ -61,10 +61,10 @@ void rwstat(void);
void rversion(void); void rversion(void);
int searchdir(Xfile*, char*, Dosptr*, int, int); int searchdir(Xfile*, char*, Dosptr*, int, int);
long sect2clust(Dosbpb*, long); long sect2clust(Dosbpb*, long);
int truncfile(Xfile*, long length); int truncfile(Xfile*, vlong length);
int utftorunes(Rune*, char*, int); int utftorunes(Rune*, char*, int);
int walkup(Xfile*, Dosptr*); int walkup(Xfile*, Dosptr*);
long writefile(Xfile*, void*, long, long); long writefile(Xfile*, void*, vlong, long);
char *xerrstr(int); char *xerrstr(int);
Xfile *xfile(int, int); Xfile *xfile(int, int);
int xfspurge(void); int xfspurge(void);