handle UTF16 UDF label

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-12-10 18:34:46 +01:00
parent f22c12e852
commit f8e2e451e6

View file

@ -789,6 +789,43 @@ fail:
return 0; return 0;
} }
static char *
read_string (grub_uint8_t *raw, grub_size_t sz)
{
grub_uint16_t *utf16;
char *ret;
grub_size_t utf16len = 0;
if (raw[0] != 8 && raw[0] != 16)
return NULL;
if (raw[0] == 8)
{
unsigned i;
utf16len = sz - 1;
utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
if (!utf16)
return NULL;
for (i = 0; i < utf16len; i++)
utf16[i] = raw[i + 1];
}
if (raw[0] == 16)
{
unsigned i;
utf16len = (sz - 1) / 2;
utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
if (!utf16)
return NULL;
for (i = 0; i < utf16len; i++)
utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
}
ret = grub_malloc (utf16len * 3 + 1);
if (ret)
*grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0';
grub_free (utf16);
return ret;
}
static int static int
grub_udf_iterate_dir (grub_fshelp_node_t dir, grub_udf_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR int NESTED_FUNC_ATTR
@ -842,10 +879,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
else else
{ {
enum grub_fshelp_filetype type; enum grub_fshelp_filetype type;
char *filename;
grub_uint8_t raw[dirent.file_ident_length]; grub_uint8_t raw[dirent.file_ident_length];
grub_uint16_t utf16[dirent.file_ident_length - 1];
grub_uint8_t filename[dirent.file_ident_length * 2];
grub_size_t utf16len = 0;
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
@ -856,27 +891,14 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
!= dirent.file_ident_length) != dirent.file_ident_length)
return 0; return 0;
if (raw[0] == 8) filename = read_string (raw, dirent.file_ident_length);
{
unsigned i;
utf16len = dirent.file_ident_length - 1;
for (i = 0; i < utf16len; i++)
utf16[i] = raw[i + 1];
}
if (raw[0] == 16)
{
unsigned i;
utf16len = (dirent.file_ident_length - 1) / 2;
for (i = 0; i < utf16len; i++)
utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
}
if (raw[0] == 8 || raw[0] == 16)
{
*grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0';
if (hook ((char *) filename, type, child)) if (filename && hook (filename, type, child))
return 1; {
grub_free (filename);
return 1;
} }
grub_free (filename);
} }
} }
@ -1033,7 +1055,7 @@ grub_udf_label (grub_device_t device, char **label)
if (data) if (data)
{ {
*label = grub_strdup ((char *) &data->lvd.ident[1]); *label = read_string (data->lvd.ident, sizeof (data->lvd.ident));
grub_free (data); grub_free (data);
} }
else else