diff options
author | avg <avg@FreeBSD.org> | 2009-02-26 12:33:12 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2009-02-26 12:33:12 +0000 |
commit | 66df72ab44aeb22c0b0a299866db8ed39d1ecbb7 (patch) | |
tree | 91241a3c43d850745f37013ebb8ba1c475f69c74 /sys | |
parent | 3f68170c35dc93a2bdb94dbd32673d239c3be3ac (diff) | |
download | FreeBSD-src-66df72ab44aeb22c0b0a299866db8ed39d1ecbb7.zip FreeBSD-src-66df72ab44aeb22c0b0a299866db8ed39d1ecbb7.tar.gz |
udf_read: correctly read data from files with data embedded into fentry,
... as opposed to files with data in extents.
Some UDF authoring tools produce this type of file for sufficiently small
data files.
Approved by: jhb (mentor)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/fs/udf/udf_vnops.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c index 5570808..bde9215 100644 --- a/sys/fs/udf/udf_vnops.c +++ b/sys/fs/udf/udf_vnops.c @@ -419,6 +419,14 @@ udf_print(struct vop_print_args *ap) #define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask) #define lblktosize(udfmp, blk) ((blk) << (udfmp)->bshift) +static inline int +is_data_in_fentry(const struct udf_node *node) +{ + const struct file_entry *fentry = node->fentry; + + return ((le16toh(fentry->icbtag.flags) & 0x7) == 3); +} + static int udf_read(struct vop_read_args *ap) { @@ -426,7 +434,9 @@ udf_read(struct vop_read_args *ap) struct uio *uio = ap->a_uio; struct udf_node *node = VTON(vp); struct udf_mnt *udfmp; + struct file_entry *fentry; struct buf *bp; + uint8_t *data; daddr_t lbn, rablock; off_t diff, fsize; int error = 0; @@ -436,6 +446,22 @@ udf_read(struct vop_read_args *ap) return (0); if (uio->uio_offset < 0) return (EINVAL); + + if (is_data_in_fentry(node)) { + fentry = node->fentry; + data = &fentry->data[le32toh(fentry->l_ea)]; + fsize = le32toh(fentry->l_ad); + + n = uio->uio_resid; + diff = fsize - uio->uio_offset; + if (diff <= 0) + return (0); + if (diff < n) + n = diff; + error = uiomove(data + uio->uio_offset, (int)n, uio); + return (error); + } + fsize = le64toh(node->fentry->inf_len); udfmp = node->udfmp; do { |