summaryrefslogtreecommitdiff
path: root/sys/src/cmd/dossrv/dossubs.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-10-05 04:31:31 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2015-10-05 04:31:31 +0200
commit0e09795831f37b86206e4dc9b3a0ac8bcd90401e (patch)
tree22e593360937f5d58497f3aa46ee3791520ac767 /sys/src/cmd/dossrv/dossubs.c
parentec518776982d6d1173683a1108e7537fc329ed43 (diff)
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.
Diffstat (limited to 'sys/src/cmd/dossrv/dossubs.c')
-rw-r--r--sys/src/cmd/dossrv/dossubs.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/sys/src/cmd/dossrv/dossubs.c b/sys/src/cmd/dossrv/dossubs.c
index 8c4af3701..a48f735fb 100644
--- a/sys/src/cmd/dossrv/dossubs.c
+++ b/sys/src/cmd/dossrv/dossubs.c
@@ -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);
}