Mercurial > hvf > hvf-old
changeset 588:59c264b5fef0
cp/fs: don't read past end of file & deal with blocks spanning block boundary
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sat, 26 Nov 2011 16:34:43 -0500 |
parents | 643aebd957cb |
children | f74b95352a4e |
files | cp/fs/edf.c |
diffstat | 1 files changed, 40 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/cp/fs/edf.c Sat Nov 26 15:13:45 2011 -0500 +++ b/cp/fs/edf.c Sat Nov 26 16:34:43 2011 -0500 @@ -205,25 +205,57 @@ mutex_lock(&file->lock); + /* check for unsupported geometry */ if (file->FST.NLVL != 0 || file->FST.PTRSZ != 4 || file->FST.LRECL > fs->ADT.DBSIZ || file->FST.RECFM != FSTDFIX) goto out; + /* reading past the end of file? */ + if (recno >= file->FST.AIC) + goto out; + blk = (recno * file->FST.LRECL) / fs->ADT.DBSIZ; off = (recno * file->FST.LRECL) % fs->ADT.DBSIZ; - dbuf = bcache_read(file, 0, blk); - if (IS_ERR(dbuf)) { - ret = PTR_ERR(dbuf); - goto out; + if ((off + file->FST.LRECL) > fs->ADT.DBSIZ) { + int flen = fs->ADT.DBSIZ - off; + int slen = file->FST.LRECL - flen; + + assert(flen < file->FST.LRECL); + assert(slen < file->FST.LRECL); + + /* the first part of the record */ + dbuf = bcache_read(file, 0, blk); + if (IS_ERR(dbuf)) { + ret = PTR_ERR(dbuf); + goto out; + } + + memcpy(buf, dbuf + off, flen); + + /* the second part of the record */ + blk++; + + dbuf = bcache_read(file, 0, blk); + if (IS_ERR(dbuf)) { + ret = PTR_ERR(dbuf); + goto out; + } + + memcpy(buf + flen, dbuf, slen); + } else { + /* the whole record */ + dbuf = bcache_read(file, 0, blk); + if (IS_ERR(dbuf)) { + ret = PTR_ERR(dbuf); + goto out; + } + + memcpy(buf, dbuf + off, file->FST.LRECL); } - BUG_ON((off + file->FST.LRECL) > fs->ADT.DBSIZ); - - memcpy(buf, dbuf + off, file->FST.LRECL); - ret = 0; out: