summaryrefslogtreecommitdiffstats
path: root/libblkid
diff options
context:
space:
mode:
authorKarel Zak2017-11-13 12:32:03 +0100
committerKarel Zak2017-11-13 12:32:03 +0100
commitcfcbf7526aedb4e85ec8fa87d829f295644f96fb (patch)
tree566812142b2739a38e552fc623f7f5b629f2779a /libblkid
parentMerge branch 'master' of https://github.com/pali/util-linux (diff)
parenttest: Add UDF hdd image with final block size 4096 created by Linux mkudffs 1.3 (diff)
downloadkernel-qcow2-util-linux-cfcbf7526aedb4e85ec8fa87d829f295644f96fb.tar.gz
kernel-qcow2-util-linux-cfcbf7526aedb4e85ec8fa87d829f295644f96fb.tar.xz
kernel-qcow2-util-linux-cfcbf7526aedb4e85ec8fa87d829f295644f96fb.zip
Merge branch 'udf' of https://github.com/pali/util-linux
* 'udf' of https://github.com/pali/util-linux: test: Add UDF hdd image with final block size 4096 created by Linux mkudffs 1.3 libblkid: udf: Optimize and fix probing when block size > 2048 bytes
Diffstat (limited to 'libblkid')
-rw-r--r--libblkid/src/superblocks/udf.c101
1 files changed, 64 insertions, 37 deletions
diff --git a/libblkid/src/superblocks/udf.c b/libblkid/src/superblocks/udf.c
index 0c4bca12a..73bf9a8af 100644
--- a/libblkid/src/superblocks/udf.c
+++ b/libblkid/src/superblocks/udf.c
@@ -167,12 +167,13 @@ static int probe_udf(blkid_probe pr,
uint32_t lvid_count = 0;
uint32_t lvid_loc = 0;
uint32_t bs;
- uint32_t pbs[5];
uint32_t b;
uint16_t type;
uint32_t count;
uint32_t loc;
size_t i;
+ uint32_t vsd_len;
+ int vsd_2048_valid = -1;
int have_label = 0;
int have_uuid = 0;
int have_logvolid = 0;
@@ -183,55 +184,81 @@ static int probe_udf(blkid_probe pr,
/* 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 any block size valid for UDF filesystem */
+ uint32_t pbs[] = { 0, 512, 1024, 2048, 4096 };
pbs[0] = blkid_probe_get_sectorsize(pr);
- pbs[1] = 512;
- pbs[2] = 1024;
- pbs[3] = 2048;
- pbs[4] = 4096;
-
- /* 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 + b,
- sizeof(*vsd));
- if (!vsd)
- return errno ? -errno : 1;
- if (vsd->id[0] != '\0')
- goto nsr;
- }
- return 1;
-nsr:
- /* search the list of VSDs for a NSR descriptor */
- for (b = 0; b < 64; b++) {
- vsd = (struct volume_structure_descriptor *)
- blkid_probe_get_buffer(pr,
- UDF_VSD_OFFSET + ((uint64_t) b * 0x800),
- sizeof(*vsd));
- if (!vsd)
- return errno ? -errno : 1;
- if (memcmp(vsd->id, "NSR02", 5) == 0)
- goto anchor;
- if (memcmp(vsd->id, "NSR03", 5) == 0)
- goto anchor;
- }
- return 1;
+ for (i = 0; i < ARRAY_SIZE(pbs); i++) {
+ /* Do not try with block size same as sector size two times */
+ if (i != 0 && pbs[0] == pbs[i])
+ continue;
+
+ /* ECMA-167 2/8.4, 2/9.1: Each VSD is either 2048 bytes long or
+ * its size is same as blocksize (for blocksize > 2048 bytes)
+ * plus padded with zeros */
+ vsd_len = pbs[i] > 2048 ? pbs[i] : 2048;
+
+ /* Process 2048 bytes long VSD only once */
+ if (vsd_len == 2048) {
+ if (vsd_2048_valid == 0)
+ continue;
+ else if (vsd_2048_valid == 1)
+ goto anchor;
+ }
+
+ /* Check for a Volume Structure Descriptor (VSD) */
+ for (b = 0; b < 64; b++) {
+ vsd = (struct volume_structure_descriptor *)
+ blkid_probe_get_buffer(pr,
+ UDF_VSD_OFFSET + b * vsd_len,
+ sizeof(*vsd));
+ if (!vsd)
+ return errno ? -errno : 1;
+ if (vsd->id[0] == '\0')
+ break;
+ if (memcmp(vsd->id, "NSR02", 5) == 0 ||
+ memcmp(vsd->id, "NSR03", 5) == 0)
+ goto anchor;
+ else if (memcmp(vsd->id, "BEA01", 5) != 0 &&
+ memcmp(vsd->id, "BOOT2", 5) != 0 &&
+ memcmp(vsd->id, "CD001", 5) != 0 &&
+ memcmp(vsd->id, "CDW02", 5) != 0 &&
+ memcmp(vsd->id, "TEA01", 5) != 0)
+ /* ECMA-167 2/8.3.1: The volume recognition sequence is
+ * terminated by the first sector which is not a valid
+ * descriptor.
+ * UDF-2.60 2.1.7: UDF 2.00 and lower revisions do not
+ * have requirement that NSR descritor is in Extended Area
+ * (between BEA01 and TEA01) and that there is only one
+ * Extended Area. So do not stop scanning after TEA01. */
+ break;
+ }
+
+ if (vsd_len == 2048)
+ vsd_2048_valid = 0;
+
+ /* NSR was not found, try with next block size */
+ continue;
anchor:
- /* read Anchor Volume Descriptor (AVDP), checking block size */
- for (i = 0; i < ARRAY_SIZE(pbs); i++) {
+ if (vsd_len == 2048)
+ vsd_2048_valid = 1;
+
+ /* Read Anchor Volume Descriptor (AVDP), detect block size */
vd = (struct volume_descriptor *)
blkid_probe_get_buffer(pr, 256 * pbs[i], sizeof(*vd));
if (!vd)
return errno ? -errno : 1;
+ /* Check that we read correct sector and detected correct block size */
+ if (le32_to_cpu(vd->tag.location) != 256)
+ continue;
+
type = le16_to_cpu(vd->tag.id);
if (type == TAG_ID_AVDP)
goto real_blksz;
+
}
- return 0;
+ return 1;
real_blksz:
/* Use the actual block size from here on out */