Committed with few fixes. Thanks Le Thu, Jun 22, 2017 à 2:42 PM, Pali Rohár <pali.ro...@gmail.com> a écrit :
> Use same algorithm as in libblkid from util-linux v2.30. > > 1. Take first 16 bytes from UTF-8 encoded string of VolumeSetIdentifier > 2. If all bytes are hexadecimal digits, convert to lowercase and use as > UUID > 3. If first 8 bytes are not all hexadecimal digits, convert those 8 bytes > to their hexadecimal representation, resulting in 16 bytes for UUID > 4. Otherwise, compose UUID from two parts: > 1. part: converted first 8 bytes (which are hexadecimal digits) to > lowercase > 2. part: encoded following 4 bytes to their hexadecimal representation > (16 bytes) > > So UUID would always have 16 hexadecimal digits in lowercase variant. > > According to UDF specification, first 16 Unicode characters of > VolumeSetIdentifier should be unique value and first 8 should be > hexadecimal characters. > > In most cases all 16 characters are hexadecimal, but e.g. MS Windows > format.exe set only first 8 as hexadecimal and remaining as fixed > (non-unique) which violates specification. > --- > Changes since v1: > * Fixed handling strings in 8 bit OSTA compressed Unicode format > * Use xdigit instead of alnum > * Compatibility with blkid from util-linux v2.30 > --- > grub-core/fs/udf.c | 121 > +++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 120 insertions(+), 1 deletion(-) > > diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c > index e7a4d4e..ce12a49 100644 > --- a/grub-core/fs/udf.c > +++ b/grub-core/fs/udf.c > @@ -321,6 +321,32 @@ struct grub_udf_partmap > }; > } GRUB_PACKED; > > +struct grub_udf_pvd > +{ > + struct grub_udf_tag tag; > + grub_uint32_t seq_num; > + grub_uint32_t pvd_num; > + grub_uint8_t ident[32]; > + grub_uint16_t vol_seq_num; > + grub_uint16_t max_vol_seq_num; > + grub_uint16_t interchange_level; > + grub_uint16_t max_interchange_level; > + grub_uint32_t charset_list; > + grub_uint32_t max_charset_list; > + grub_uint8_t volset_ident[128]; > + struct grub_udf_charspec desc_charset; > + struct grub_udf_charspec expl_charset; > + struct grub_udf_extent_ad vol_abstract; > + struct grub_udf_extent_ad vol_copyright; > + struct grub_udf_regid app_ident; > + struct grub_udf_timestamp recording_time; > + struct grub_udf_regid imp_ident; > + grub_uint8_t imp_use[64]; > + grub_uint32_t pred_vds_loc; > + grub_uint16_t flags; > + grub_uint8_t reserved[22]; > +} GRUB_PACKED; > + > struct grub_udf_lvd > { > struct grub_udf_tag tag; > @@ -348,6 +374,7 @@ struct grub_udf_aed > struct grub_udf_data > { > grub_disk_t disk; > + struct grub_udf_pvd pvd; > struct grub_udf_lvd lvd; > struct grub_udf_pd pds[GRUB_UDF_MAX_PDS]; > struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS]; > @@ -692,7 +719,17 @@ grub_udf_mount (grub_disk_t disk) > } > > tag.tag_ident = U16 (tag.tag_ident); > - if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD) > + if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PVD) > + { > + if (grub_disk_read (disk, block << lbshift, 0, > + sizeof (struct grub_udf_pvd), > + &data->pvd)) > + { > + grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); > + goto fail; > + } > + } > + else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD) > { > if (data->npd >= GRUB_UDF_MAX_PDS) > { > @@ -1225,6 +1262,87 @@ grub_udf_label (grub_device_t device, char **label) > return grub_errno; > } > > +static char * > +gen_uuid_from_volset (char *volset_ident) > +{ > + grub_size_t i; > + grub_size_t len; > + grub_size_t nonhexpos; > + grub_uint8_t buf[17]; > + char *uuid; > + > + len = grub_strlen (volset_ident); > + if (len < 8) > + return NULL; > + > + uuid = grub_malloc (17); > + if (!uuid) > + return NULL; > + > + if (len > 16) > + len = 16; > + > + grub_memset (buf, 0, sizeof (buf)); > + grub_memcpy (buf, volset_ident, len); > + > + nonhexpos = 16; > + for (i = 0; i < 16; ++i) > + { > + if (!grub_isxdigit (buf[i])) > + { > + nonhexpos = i; > + break; > + } > + } > + > + if (nonhexpos < 8) > + { > + grub_snprintf (uuid, 17, "%02x%02x%02x%02x%02x%02x%02x%02x", > + buf[0], buf[1], buf[2], buf[3], > + buf[4], buf[5], buf[6], buf[7]); > + } > + else if (nonhexpos < 16) > + { > + for (i = 0; i < 8; ++i) > + uuid[i] = grub_tolower (buf[i]); > + grub_snprintf (uuid+8, 9, "%02x%02x%02x%02x", > + buf[8], buf[9], buf[10], buf[11]); > + } > + else > + { > + for (i = 0; i < 16; ++i) > + uuid[i] = grub_tolower (buf[i]); > + uuid[16] = 0; > + } > + > + return uuid; > +} > + > +static grub_err_t > +grub_udf_uuid (grub_device_t device, char **uuid) > +{ > + char *volset_ident; > + struct grub_udf_data *data; > + data = grub_udf_mount (device->disk); > + > + if (data) > + { > + volset_ident = read_dstring (data->pvd.volset_ident, sizeof > (data->pvd.volset_ident), 0); > + if (volset_ident) > + { > + *uuid = gen_uuid_from_volset (volset_ident); > + grub_free (volset_ident); > + } > + else > + *uuid = 0; > + grub_free (data); > + } > + else > + *uuid = 0; > + > + return grub_errno; > +} > + > static struct grub_fs grub_udf_fs = { > .name = "udf", > .dir = grub_udf_dir, > @@ -1232,6 +1350,7 @@ static struct grub_fs grub_udf_fs = { > .read = grub_udf_read, > .close = grub_udf_close, > .label = grub_udf_label, > + .uuid = grub_udf_uuid, > #ifdef GRUB_UTIL > .reserved_first_sector = 1, > .blocklist_install = 1, > -- > 1.7.9.5 > >
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel