diff options
author | Pali Rohár | 2017-11-15 18:05:52 +0100 |
---|---|---|
committer | Pali Rohár | 2017-11-15 18:05:52 +0100 |
commit | d0ecd5e98437f41a8e025b4311e029e7baf35237 (patch) | |
tree | a95273d6310c0a5e891f311e78f18cf1db76bcf5 /libblkid | |
parent | tests: GPT device resize test (diff) | |
download | kernel-qcow2-util-linux-d0ecd5e98437f41a8e025b4311e029e7baf35237.tar.gz kernel-qcow2-util-linux-d0ecd5e98437f41a8e025b4311e029e7baf35237.tar.xz kernel-qcow2-util-linux-d0ecd5e98437f41a8e025b4311e029e7baf35237.zip |
libblkid: udf: Really try to read only first LVID
We do not want to scan whole LVID sequence.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Diffstat (limited to 'libblkid')
-rw-r--r-- | libblkid/src/superblocks/udf.c | 71 |
1 files changed, 32 insertions, 39 deletions
diff --git a/libblkid/src/superblocks/udf.c b/libblkid/src/superblocks/udf.c index a6af43e13..bc7273ca5 100644 --- a/libblkid/src/superblocks/udf.c +++ b/libblkid/src/superblocks/udf.c @@ -174,7 +174,7 @@ static int probe_udf(blkid_probe pr, struct volume_descriptor *vd; struct volume_structure_descriptor *vsd; struct logical_vol_integ_descriptor_imp_use *lvidiu; - uint32_t lvid_count = 0; + uint32_t lvid_len = 0; uint32_t lvid_loc = 0; uint32_t bs; uint32_t b; @@ -189,7 +189,6 @@ static int probe_udf(blkid_probe pr, int have_logvolid = 0; int have_volid = 0; int have_volsetid = 0; - int have_udf_rev = 0; /* The block size of a UDF filesystem is that of the underlying * storage; we check later on for the special case of image files, @@ -349,11 +348,11 @@ real_blksz: vd->type.primary.volset_id.c, clen, enc); } } else if (type == TAG_ID_LVD) { - if (!lvid_count || !lvid_loc) { + if (!lvid_len || !lvid_loc) { uint32_t num_partition_maps = le32_to_cpu(vd->type.logical.num_partition_maps); /* ECMA-167 3/10.6.12: If num_partition_maps is 0, then no LVID is specified */ if (num_partition_maps) { - lvid_count = le32_to_cpu(vd->type.logical.lvid_length) / bs; + lvid_len = le32_to_cpu(vd->type.logical.lvid_length); lvid_loc = le32_to_cpu(vd->type.logical.lvid_location); } } @@ -400,46 +399,40 @@ real_blksz: } } } - if (have_volid && have_uuid && have_volsetid && have_logvolid && have_label && lvid_count && lvid_loc) + if (have_volid && have_uuid && have_volsetid && have_logvolid && have_label && lvid_len && lvid_loc) break; } - /* pick the logical volume integrity descriptor from the list and read UDF revision */ - if (lvid_count && lvid_loc) { - for (b = 0; b < lvid_count; b++) { - vd = (struct volume_descriptor *) + /* Pick the first logical volume integrity descriptor and read UDF revision */ + if (lvid_loc && lvid_len >= sizeof(*vd)) { + vd = (struct volume_descriptor *) + blkid_probe_get_buffer(pr, + (uint64_t) lvid_loc * bs, + sizeof(*vd)); + if (!vd) + return errno ? -errno : 1; + type = le16_to_cpu(vd->tag.id); + if (type == TAG_ID_LVID && + le32_to_cpu(vd->tag.location) == lvid_loc && + UDF_LVIDIU_LENGTH(*vd) >= sizeof(*lvidiu)) { + /* ECMA-167 3/8.8.2: There is stored sequence of LVIDs and valid is just last + * one. So correctly we should jump to next_lvid_location and read next LVID + * until we find last one. This could be time consuming process and could + * lead to scanning lot of disk blocks. Because we use LVID only for UDF + * version, in the worst case we would report only wrong ID_FS_VERSION. */ + uint16_t udf_rev; + lvidiu = (struct logical_vol_integ_descriptor_imp_use *) blkid_probe_get_buffer(pr, - (uint64_t) (lvid_loc + b) * bs, - sizeof(*vd)); - if (!vd) + (uint64_t) lvid_loc * bs + UDF_LVIDIU_OFFSET(*vd), + sizeof(*lvidiu)); + if (!lvidiu) return errno ? -errno : 1; - type = le16_to_cpu(vd->tag.id); - if (type == 0) - break; - if (le32_to_cpu(vd->tag.location) != lvid_loc + b) - break; - if (type == TAG_ID_LVID && UDF_LVIDIU_LENGTH(*vd) >= sizeof(*lvidiu)) { - /* ECMA-167 3/8.8.2: There is stored sequence of LVIDs and valid is just last - * one. So correctly we should jump to next_lvid_location and read next LVID - * until we find last one. This could be time consuming process and could - * lead to scanning lot of disk blocks. Because we use LVID only for UDF - * version, in the worst case we would report only wrong ID_FS_VERSION. */ - uint16_t udf_rev; - lvidiu = (struct logical_vol_integ_descriptor_imp_use *) - blkid_probe_get_buffer(pr, - (uint64_t) (lvid_loc + b) * bs + UDF_LVIDIU_OFFSET(*vd), - sizeof(*lvidiu)); - if (!lvidiu) - return errno ? -errno : 1; - /* Use Minimum UDF Read Revision as ID_FS_VERSION */ - udf_rev = le16_to_cpu(lvidiu->min_udf_read_rev); - if (udf_rev) - have_udf_rev = !blkid_probe_sprintf_version(pr, "%d.%02d", - (int)(udf_rev >> 8), - (int)(udf_rev & 0xFF)); - } - if (have_udf_rev) - break; + /* Use Minimum UDF Read Revision as ID_FS_VERSION */ + udf_rev = le16_to_cpu(lvidiu->min_udf_read_rev); + if (udf_rev) + blkid_probe_sprintf_version(pr, "%d.%02d", + (int)(udf_rev >> 8), + (int)(udf_rev & 0xFF)); } } |