From 5a45eb2d2c70dc7ea2ff4c7b56ab8dba2780f033 Mon Sep 17 00:00:00 2001 From: Zachary Catlin Date: Fri, 1 Mar 2013 21:34:25 -0500 Subject: libblkid: use correct block size for UDF probe In UDF, Volume Structure Descriptors are always 2048 bytes long (ECMA-167, 3rd ed., §2/9.1), while filesystem sectors are the same size as the sectors of the underlying media (e.g., UDF 2.01 §1.3.2). Before this commit, the block size was estimated from VSD offsets, which gives incorrect answers for non-optical media. Now, the UDF probe uses the device block size by default, falling back to 2048-byte sectors for the case of optical-disk images. Signed-off-by: Zachary Catlin --- AUTHORS | 1 + libblkid/src/superblocks/udf.c | 45 ++++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/AUTHORS b/AUTHORS index f29f9a3a2..54fe7cec2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -385,5 +385,6 @@ CONTRIBUTORS: Yoshihiro Takahashi Yuri Chornoivan Yu Zhiguo + Zachary Catlin Zdenek Behan Zhi Li diff --git a/libblkid/src/superblocks/udf.c b/libblkid/src/superblocks/udf.c index 2cb471df2..c9fb02285 100644 --- a/libblkid/src/superblocks/udf.c +++ b/libblkid/src/superblocks/udf.c @@ -64,17 +64,25 @@ static int probe_udf(blkid_probe pr, struct volume_descriptor *vd; struct volume_structure_descriptor *vsd; unsigned int bs; + unsigned int pbs[2]; unsigned int b; unsigned int type; unsigned int count; unsigned int loc; + unsigned int i; - /* search Volume Sequence Descriptor (VSD) to get the logical - * block size of the volume */ - for (bs = 0x800; bs < 0x8000; bs += 0x800) { + /* The block size of a UDF filesystem is that of the underlying + * storage; we check later on for the special case of image files, + * which may have the 2048-byte block size of optical media. */ + pbs[0] = blkid_probe_get_sectorsize(pr); + pbs[1] = 0x800; + + /* check for a Volume Structure Descriptor (VSD); each is + * 2048 bytes long */ + for (b = 0; b < 0x8000; b += 0x800) { vsd = (struct volume_structure_descriptor *) blkid_probe_get_buffer(pr, - UDF_VSD_OFFSET + bs, + UDF_VSD_OFFSET + b, sizeof(*vsd)); if (!vsd) return 1; @@ -88,7 +96,7 @@ nsr: for (b = 0; b < 64; b++) { vsd = (struct volume_structure_descriptor *) blkid_probe_get_buffer(pr, - UDF_VSD_OFFSET + ((blkid_loff_t) b * bs), + UDF_VSD_OFFSET + ((blkid_loff_t) b * 0x800), sizeof(*vsd)); if (!vsd) return -1; @@ -102,17 +110,24 @@ nsr: return -1; anchor: - /* read Anchor Volume Descriptor (AVDP) */ - vd = (struct volume_descriptor *) - blkid_probe_get_buffer(pr, 256 * bs, sizeof(*vd)); - if (!vd) - return -1; - - type = le16_to_cpu(vd->tag.id); - if (type != 2) /* TAG_ID_AVDP */ - return 0; + /* read Anchor Volume Descriptor (AVDP), checking block size */ + for (i = 0; i < 2; i++) { + vd = (struct volume_descriptor *) + blkid_probe_get_buffer(pr, 256 * pbs[i], sizeof(*vd)); + if (!vd) + return -1; + + type = le16_to_cpu(vd->tag.id); + if (type == 2) /* TAG_ID_AVDP */ + goto real_blksz; + } + return 0; + +real_blksz: + /* Use the actual block size from here on out */ + bs = pbs[i]; - /* get desriptor list address and block count */ + /* get descriptor list address and block count */ count = le32_to_cpu(vd->type.anchor.length) / bs; loc = le32_to_cpu(vd->type.anchor.location); -- cgit v1.2.3-55-g7522