diff options
author | Pali Rohár | 2017-07-05 13:50:52 +0200 |
---|---|---|
committer | Pali Rohár | 2017-07-05 13:50:52 +0200 |
commit | db316767434c2c451ec1732861256d5729143e89 (patch) | |
tree | 254926b5a5b0d4cb1fd0a7c8483a0b600f289d47 /libblkid | |
parent | libblkid: udf: Fix types (diff) | |
download | kernel-qcow2-util-linux-db316767434c2c451ec1732861256d5729143e89.tar.gz kernel-qcow2-util-linux-db316767434c2c451ec1732861256d5729143e89.tar.xz kernel-qcow2-util-linux-db316767434c2c451ec1732861256d5729143e89.zip |
libblkid: udf: Add support for ID_FS_VERSION
Set ID_FS_VERSION to Minimum UDF Read Revision.
Diffstat (limited to 'libblkid')
-rw-r--r-- | libblkid/src/superblocks/udf.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/libblkid/src/superblocks/udf.c b/libblkid/src/superblocks/udf.c index 0169d720c..836008a8e 100644 --- a/libblkid/src/superblocks/udf.c +++ b/libblkid/src/superblocks/udf.c @@ -67,6 +67,15 @@ struct volume_descriptor { uint32_t seq_num; uint8_t desc_charset[64]; struct dstring128 logvol_id; + uint32_t logical_blocksize; + uint8_t domain_id[32]; + uint8_t logical_contents_use[16]; + uint32_t map_table_length; + uint32_t num_partition_maps; + uint8_t imp_id[32]; + uint8_t imp_use[128]; + uint32_t lvid_length; + uint32_t lvid_location; } __attribute__((packed)) logical; } __attribute__((packed)) type; @@ -80,6 +89,18 @@ struct volume_structure_descriptor { #define UDF_VSD_OFFSET 0x8000LL +struct logical_vol_integ_descriptor_imp_use +{ + uint8_t imp_id[32]; + uint32_t num_files; + uint32_t num_dirs; + uint16_t min_udf_read_rev; + uint16_t min_udf_write_rev; + uint16_t max_udf_write_rev; +} __attribute__ ((packed)); + +#define UDF_LVIDIU_OFFSET(num_partition_maps) (80 + 2 * 4 * num_partition_maps) + static inline int gen_uuid_from_volset_id(unsigned char uuid[17], struct dstring128 *volset_id) { int enc; @@ -136,6 +157,10 @@ 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 num_partition_maps = 0; + uint32_t lvid_count = 0; + uint32_t lvid_loc = 0; uint32_t bs; uint32_t pbs[5]; uint32_t b; @@ -148,6 +173,7 @@ 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, @@ -281,6 +307,11 @@ real_blksz: vd->type.primary.volset_id.c, clen, enc); } } else if (type == 6) { /* TAG_ID_LVD */ + if (!num_partition_maps || !lvid_count || !lvid_loc) { + num_partition_maps = le32_to_cpu(vd->type.logical.num_partition_maps); + lvid_count = le32_to_cpu(vd->type.logical.lvid_length) / bs; + lvid_loc = le32_to_cpu(vd->type.logical.lvid_location); + } if (!have_logvolid || !have_label) { /* LogicalVolumeIdentifier in UDF 2.01 specification: * =============================================================== @@ -324,10 +355,44 @@ real_blksz: } } } - if (have_logvolid && have_volid && have_volsetid) + if (have_volid && have_uuid && have_volsetid && have_logvolid && have_label && num_partition_maps && lvid_count && lvid_loc) break; } + /* pick the logical volume integrity descriptor from the list and read UDF revision */ + if (lvid_count && lvid_loc && num_partition_maps) { + for (b = 0; b < lvid_count; b++) { + vd = (struct volume_descriptor *) + blkid_probe_get_buffer(pr, + (uint64_t) (lvid_loc + b) * bs, + sizeof(*vd)); + if (!vd) + 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 == 9) { /* TAG_ID_LVID */ + 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(num_partition_maps), + 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; + } + } + return 0; } |