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:
parent
ec51877698
commit
0e09795831
4 changed files with 42 additions and 31 deletions
|
@ -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{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue