summaryrefslogtreecommitdiffstats
path: root/sys/fs/udf
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2009-02-26 12:33:12 +0000
committeravg <avg@FreeBSD.org>2009-02-26 12:33:12 +0000
commit66df72ab44aeb22c0b0a299866db8ed39d1ecbb7 (patch)
tree91241a3c43d850745f37013ebb8ba1c475f69c74 /sys/fs/udf
parent3f68170c35dc93a2bdb94dbd32673d239c3be3ac (diff)
downloadFreeBSD-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/fs/udf')
-rw-r--r--sys/fs/udf/udf_vnops.c26
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 {
OpenPOWER on IntegriCloud