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

Reply via email to