* 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.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-12-12 22:40:43 +01:00
parent 48d6e45653
commit 1bc8f60db7
3 changed files with 43 additions and 61 deletions

View file

@ -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.

View 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]);
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;
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_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;
/* 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);
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);
}
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);

View 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))