]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 12 Dec 2011 21:40:43 +0000 (22:40 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 12 Dec 2011 21:40:43 +0000 (22:40 +0100)
* grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Change to
UTF-16-BE. All users updated.
(grub_hfsplus_cmp_catkey): Fix unicode handling.
(grub_hfsplus_iterate_dir): Likewise.
(grub_hfsplus_label): Likewise.

ChangeLog
grub-core/fs/hfsplus.c
include/grub/charset.h

index 492c45b725f9e5a180010dfdacf0d3e43b6ac051..485d37f30f5450357e5473a6e3f7fb423ae7e65b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2011-12-12  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const.
+       * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Change to
+       UTF-16-BE. All users updated.
+       (grub_hfsplus_cmp_catkey): Fix unicode handling.
+       (grub_hfsplus_iterate_dir): Likewise.
+       (grub_hfsplus_label): Likewise.
+
 2011-12-12  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix compat condition.
index 00b2366bf17be23527e63a56ca34388b9df1a62c..9d5f20181e60e00b3e6802620f5862bc77f95e1d 100644 (file)
@@ -181,7 +181,8 @@ enum grub_hfsplus_filetype
 struct grub_hfsplus_catkey_internal
 {
   grub_uint32_t parent;
-  const char *name;
+  const grub_uint16_t *name;
+  grub_size_t namelen;
 };
 
 /* Internal representation of an extent overflow key.  */
@@ -519,8 +520,6 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
 {
   struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
   struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
-  char *filename;
-  int i;
   int diff;
 
   /* Safe unsigned comparison */
@@ -530,26 +529,13 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
   if (aparent < catkey_b->parent)
     return -1;
 
-  /* Change the filename in keya so the endianness is correct.  */
-  for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
-    catkey_a->name[i] = grub_be_to_cpu16 (catkey_a->name[i]);
-
-  filename = grub_malloc (grub_be_to_cpu16 (catkey_a->namelen) + 1);
-
-  if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey_a->name,
-                           grub_be_to_cpu16 (catkey_a->namelen)))
-    return -1; /* XXX: This error never occurs, but in case it happens
-                 just skip this entry.  */
+  diff = grub_memcmp (catkey_a->name, catkey_b->name,
+                     grub_min (grub_be_to_cpu16 (catkey_a->namelen),
+                               catkey_b->namelen)
+                     * sizeof (catkey_a->name[0]));
+  if (diff == 0)
+    diff = grub_be_to_cpu16 (catkey_a->namelen) - catkey_b->namelen;
 
-  diff = grub_strncmp (filename, catkey_b->name,
-                      grub_be_to_cpu16 (catkey_a->namelen));
-
-  grub_free (filename);
-
-  /* The endianness was changed to host format, change it back to
-     whatever it was.  */
-  for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
-    catkey_a->name[i] = grub_cpu_to_be16 (catkey_a->name[i]);
   return diff;
 }
 
@@ -792,6 +778,11 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
       if (type == GRUB_FSHELP_UNKNOWN)
        return 0;
 
+      filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
+                             * GRUB_MAX_UTF8_PER_UTF16 + 1);
+      if (! filename)
+       return 0;
+
       /* Make sure the byte order of the UTF16 string is correct.  */
       for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
        {
@@ -802,18 +793,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
            return 0;
        }
 
-      filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + 1);
-      if (! filename)
-       return 0;
-
-      if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
-                               grub_be_to_cpu16 (catkey->namelen)))
-       {
-         grub_free (filename);
-         return 0;
-       }
-
-      filename[grub_be_to_cpu16 (catkey->namelen)] = '\0';
+      *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
+                          grub_be_to_cpu16 (catkey->namelen)) = '\0';
 
       /* Restore the byte order to what it was previously.  */
       for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
@@ -823,22 +804,18 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
       if (! dir->data->case_sensitive)
        type |= GRUB_FSHELP_CASE_INSENSITIVE;
 
-      /* Only accept valid nodes.  */
-      if (grub_strlen (filename) == grub_be_to_cpu16 (catkey->namelen))
-       {
-         /* A valid node is found; setup the node and call the
-            callback function.  */
-         node = grub_malloc (sizeof (*node));
-         node->data = dir->data;
-
-         grub_memcpy (node->extents, fileinfo->data.extents,
-                      sizeof (node->extents));
-         node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800;
-         node->size = grub_be_to_cpu64 (fileinfo->data.size);
-         node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
-
-         ret = hook (filename, type, node);
-       }
+      /* A valid node is found; setup the node and call the
+        callback function.  */
+      node = grub_malloc (sizeof (*node));
+      node->data = dir->data;
+
+      grub_memcpy (node->extents, fileinfo->data.extents,
+                  sizeof (node->extents));
+      node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800;
+      node->size = grub_be_to_cpu64 (fileinfo->data.size);
+      node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
+
+      ret = hook (filename, type, node);
 
       grub_free (filename);
 
@@ -851,7 +828,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
 
   /* Create a key that points to the first entry in the directory.  */
   intern.catkey.parent = dir->fileid;
-  intern.catkey.name = "";
+  intern.catkey.name = 0;
+  intern.catkey.namelen = 0;
 
   /* First lookup the first entry.  */
   if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern,
@@ -999,7 +977,8 @@ grub_hfsplus_label (grub_device_t device, char **label)
 
   /* Create a key that points to the label.  */
   intern.catkey.parent = 1;
-  intern.catkey.name = "";
+  intern.catkey.name = 0;
+  intern.catkey.namelen = 0;
 
   /* First lookup the first entry.  */
   if (grub_hfsplus_btree_search (&data->catalog_tree, &intern,
@@ -1022,20 +1001,12 @@ grub_hfsplus_label (grub_device_t device, char **label)
        return 0;
     }
 
-  *label = grub_malloc (label_len + 1);
+  *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1);
   if (! *label)
     return grub_errno;
 
-  if (! grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name,
-                           label_len))
-    {
-      grub_free (node);
-      grub_free (*label);
-      grub_free (data);
-      *label = 0;
-      return grub_errno;
-    }
-  (*label)[label_len] = '\0';
+  *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name,
+                      label_len) = '\0';
 
   grub_free (node);
   grub_free (data);
index c8247f78a0b67181bd71a0068495b87913edced1..13443dad226e97b146ba78a23938cdb91d48ec1a 100644 (file)
@@ -36,6 +36,8 @@
 #define GRUB_UINT8_5_TRAILINGBITS 0x1f
 #define GRUB_UINT8_6_TRAILINGBITS 0x3f
 
+#define GRUB_MAX_UTF8_PER_UTF16 4
+
 #define GRUB_UCS2_LIMIT 0x10000
 #define GRUB_UTF16_UPPER_SURROGATE(code) \
   (0xD800 + ((((code) - GRUB_UCS2_LIMIT) >> 12) & 0xfff))