diff options
author | bp <bp@FreeBSD.org> | 2000-01-02 03:30:42 +0000 |
---|---|---|
committer | bp <bp@FreeBSD.org> | 2000-01-02 03:30:42 +0000 |
commit | 11b5b4872ea97ba1acf882fc84bf885c607b0980 (patch) | |
tree | d1a17b02550eeb8d138561c88cf1746ba2cab8d2 /sys/msdosfs | |
parent | 034f4c18839b7e3aba2de93e8676d439a367f35e (diff) | |
download | FreeBSD-src-11b5b4872ea97ba1acf882fc84bf885c607b0980.zip FreeBSD-src-11b5b4872ea97ba1acf882fc84bf885c607b0980.tar.gz |
Fix the mess with signed/unsigned longs and ints (inspired by bde).
Fix potential bug with directory reading.
Explicitly limit file size to 4GB (msdos can't handle larger files).
Slightly reorganize msdosfs_read() to reduce number of 'if's.
Diffstat (limited to 'sys/msdosfs')
-rw-r--r-- | sys/msdosfs/msdosfs_vnops.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index d72a4cd..15e8578 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -74,6 +74,8 @@ #include <msdosfs/msdosfsmount.h> #include <msdosfs/fat.h> +#define DOS_FILESIZE_MAX 0xffffffff + /* * Prototypes for MSDOSFS vnode operations */ @@ -545,12 +547,12 @@ msdosfs_read(ap) } */ *ap; { int error = 0; - off_t diff; int blsize; int isadir; int orig_resid; - long n; - long on; + u_int n; + u_long diff; + u_long on; daddr_t lbn; daddr_t rablock; int rasize; @@ -564,6 +566,8 @@ msdosfs_read(ap) if (uio->uio_offset < 0) return (EINVAL); + if (uio->uio_offset > DOS_FILESIZE_MAX) + return (EFBIG); /* * If they didn't ask for any data, then we are done. */ @@ -578,41 +582,42 @@ msdosfs_read(ap) if (uio->uio_offset >= dep->de_FileSize) break; lbn = de_cluster(pmp, uio->uio_offset); - on = uio->uio_offset & pmp->pm_crbomask; - n = min((u_long) (pmp->pm_bpcluster - on), uio->uio_resid); - diff = dep->de_FileSize - uio->uio_offset; - if (diff < n) - n = diff; - /* convert cluster # to block # if a directory */ - if (isadir) { - error = pcbmap(dep, lbn, &lbn, 0, &blsize); - if (error) - break; - } /* * If we are operating on a directory file then be sure to * do i/o with the vnode for the filesystem instead of the * vnode for the directory. */ if (isadir) { + /* convert cluster # to block # */ + error = pcbmap(dep, lbn, &lbn, 0, &blsize); + if (error) + break; error = bread(pmp->pm_devvp, lbn, blsize, NOCRED, &bp); } else { + blsize = pmp->pm_bpcluster; rablock = lbn + 1; if (seqcount > 1 && de_cn2off(pmp, rablock) < dep->de_FileSize) { rasize = pmp->pm_bpcluster; - error = breadn(vp, lbn, pmp->pm_bpcluster, + error = breadn(vp, lbn, blsize, &rablock, &rasize, 1, NOCRED, &bp); } else { - error = bread(vp, lbn, pmp->pm_bpcluster, - NOCRED, &bp); + error = bread(vp, lbn, blsize, NOCRED, &bp); } } - n = min(n, pmp->pm_bpcluster - bp->b_resid); if (error) { brelse(bp); break; } + on = uio->uio_offset & pmp->pm_crbomask; + diff = pmp->pm_bpcluster - on; + n = diff > uio->uio_resid ? uio->uio_resid : diff; + diff = dep->de_FileSize - uio->uio_offset; + if (diff < n) + n = diff; + diff = blsize - bp->b_resid; + if (diff < n) + n = diff; error = uiomove(bp->b_data + on, (int) n, uio); brelse(bp); } while (error == 0 && uio->uio_resid > 0 && n != 0); @@ -676,6 +681,9 @@ msdosfs_write(ap) if (uio->uio_resid == 0) return (0); + if (uio->uio_offset + uio->uio_resid > DOS_FILESIZE_MAX) + return (EFBIG); + /* * If they've exceeded their filesize limit, tell them about it. */ |