grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] * grub-core/fs/udf.c: Add support for UUID


From: Pali Rohár
Subject: [PATCH] * grub-core/fs/udf.c: Add support for UUID
Date: Mon, 10 Apr 2017 20:35:30 +0200

Use same algorithm as in libblkid from util-linux.
---
 grub-core/fs/udf.c |  136 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 131 insertions(+), 5 deletions(-)

diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index 839bff8..a4baa4c 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)
            {
@@ -821,7 +858,7 @@ grub_udf_get_cluster_sector (grub_disk_t disk, 
grub_uint64_t *sec_per_lcn)
 #endif
 
 static char *
-read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
+read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf, int 
normalize_utf8)
 {
   grub_uint16_t *utf16 = NULL;
   grub_size_t utf16len = 0;
@@ -832,6 +869,15 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char 
*outbuf)
   if (raw[0] != 8 && raw[0] != 16)
     return NULL;
 
+  if (raw[0] == 8 && !normalize_utf8)
+    {
+      if (!outbuf)
+        outbuf = grub_strndup ((char *)raw + 1, sz - 1);
+      else
+        grub_memcpy (outbuf, raw + 1, sz - 1);
+      return outbuf;
+    }
+
   if (raw[0] == 8)
     {
       unsigned i;
@@ -923,7 +969,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
                  != dirent.file_ident_length)
                return 0;
 
-             filename = read_string (raw, dirent.file_ident_length, 0);
+             filename = read_string (raw, dirent.file_ident_length, 0, 1);
              if (!filename)
                grub_print_error ();
 
@@ -1009,7 +1055,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
          /* in 4 + n bytes. out, at most: 1 + 2 * n bytes.  */
          if (optr != out)
            *optr++ = '/';
-         if (!read_string (ptr + 4, s - 4, optr))
+         if (!read_string (ptr + 4, s - 4, optr, 1))
            goto fail;
          optr += grub_strlen (optr);
          break;
@@ -1197,7 +1243,7 @@ grub_udf_label (grub_device_t device, char **label)
 
   if (data)
     {
-      *label = read_string (data->lvd.ident, sizeof (data->lvd.ident), 0);
+      *label = read_string (data->lvd.ident, sizeof (data->lvd.ident), 0, 1);
       grub_free (data);
     }
   else
@@ -1206,6 +1252,85 @@ 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 binpos;
+  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);
+
+  binpos = 16;
+  for (i = 0; i < len; ++i)
+    {
+      if (!grub_isalnum (buf[i]))
+        {
+          binpos = i;
+          break;
+        }
+    }
+
+  if (binpos < 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 (binpos < 16)
+    {
+      grub_memcpy (uuid, buf, 8);
+      grub_snprintf (uuid+8, 9, "%02x%02x%02x%02x",
+                    buf[8], buf[9], buf[10], buf[11]);
+    }
+  else
+    {
+      grub_memcpy (uuid, buf, 16);
+      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_string (data->pvd.volset_ident, sizeof 
(data->pvd.volset_ident), 0, 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,
@@ -1213,6 +1338,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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]