summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2002-04-30 05:05:05 +0000
committerscottl <scottl@FreeBSD.org>2002-04-30 05:05:05 +0000
commit4a9b6b4afde72ce76ed1dacfcf1e1f286e537842 (patch)
tree96e0f953b4d0534a76c7f111a730a358dce1ce51 /sys
parent06a56984b5d6914defdf297800b55556596749a4 (diff)
downloadFreeBSD-src-4a9b6b4afde72ce76ed1dacfcf1e1f286e537842.zip
FreeBSD-src-4a9b6b4afde72ce76ed1dacfcf1e1f286e537842.tar.gz
Fix udf_read(). Honor the uio_resid when determining the size of
the block to read and copy out. This removes the hack in udf_readatoffset() for only reading one block at a time. WooHoo! Remove a redundant test for fragmented fids in both udf_readdir() and udf_lookup(). Add comment to both as to why the test is written the way it is. Add a few more safety checks for brelse(). Thanks to Timothy Shimmin <tes@boing.melbourne.sgi.com> for pointing out these problems.
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/udf/udf_vnops.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c
index 74d5896..d75c11b 100644
--- a/sys/fs/udf/udf_vnops.c
+++ b/sys/fs/udf/udf_vnops.c
@@ -397,23 +397,22 @@ udf_read(struct vop_read_args *a)
struct buf *bp;
uint8_t *data;
int error = 0;
- int size, n, fsize, offset;
+ int size, fsize, offset;
if (uio->uio_offset < 0)
return (EINVAL);
fsize = node->fentry->inf_len;
- size = 0;
+
while (uio->uio_offset < fsize && uio->uio_resid > 0) {
offset = uio->uio_offset;
+ size = uio->uio_resid;
error = udf_readatoffset(node, &size, offset, &bp, &data);
if (error)
return (error);
- n = min(size, size - bp->b_resid);
- error = uiomove((caddr_t)data, n, uio);
+ error = uiomove((caddr_t)data, size, uio);
if (bp != NULL)
brelse(bp);
- size -= n;
if (error)
break;
};
@@ -606,8 +605,12 @@ udf_readdir(struct vop_readdir_args *a)
fid = (struct fileid_desc*)&data[off];
- /* Check to see if the fid is fragmented */
- if (off >= size || off + fid_size > size ||
+ /*
+ * Check to see if the fid is fragmented. The first test
+ * ensures that we don't wander off the end of the buffer
+ * looking for the l_iu and l_fi fields.
+ */
+ if (off + fid_size > size ||
off + fid->l_iu + fid->l_fi + fid_size > size) {
struct fileid_desc *fid_buf;
uint8_t *buf;
@@ -653,7 +656,8 @@ udf_readdir(struct vop_readdir_args *a)
MALLOC(fid, struct fileid_desc *, total_fid_size,
M_UDFFID, M_NOWAIT | M_ZERO);
if (fid == NULL) {
- brelse(bp);
+ if (bp != NULL)
+ brelse(bp);
error = ENOMEM;
break;
}
@@ -886,8 +890,12 @@ lookloop:
while (offset + off < fsize) {
fid = (struct fileid_desc*)&data[off];
- /* Check to see if the fid is fragmented */
- if (off >= size || off + fid_size > size ||
+ /*
+ * Check to see if the fid is fragmented. The first test
+ * ensures that we don't wander off the end of the buffer
+ * looking for the l_iu and l_fi fields.
+ */
+ if (off + fid_size > size ||
off + fid_size + fid->l_iu + fid->l_fi > size) {
struct fileid_desc *fid_buf;
uint8_t *buf;
@@ -934,7 +942,8 @@ lookloop:
MALLOC(fid, struct fileid_desc *, total_fid_size,
M_UDFFID, M_NOWAIT | M_ZERO);
if (fid == NULL) {
- brelse(bp);
+ if (bp != NULL)
+ brelse(bp);
return (ENOMEM);
}
bcopy(fid_buf, fid, frag_size);
@@ -1094,13 +1103,10 @@ udf_readatoffset(struct udf_node *node, int *size, int offset, struct buf **bp,
return (error);
}
+ /* Adjust the size so that it is within range */
if (*size == 0 || *size > max_size)
*size = max_size;
-
- /* XXX Read only one block at a time? Could read-ahead help? */
- *size = min(*size, udfmp->bsize);
- if (*size == 0)
- return (EIO);
+ *size = min(*size, MAXBSIZE);
if ((error = udf_readlblks(udfmp, sector, *size, bp))) {
printf("udf_readlblks returned %d\n", error);
OpenPOWER on IntegriCloud