return grub_errno;
}
+#define MAX_UTF8_PER_MAC_ROMAN 3
+
+static const char macroman[0x80][MAX_UTF8_PER_MAC_ROMAN + 1] =
+ {
+ /* 80 */ "\xc3\x84",
+ /* 81 */ "\xc3\x85",
+ /* 82 */ "\xc3\x87",
+ /* 83 */ "\xc3\x89",
+ /* 84 */ "\xc3\x91",
+ /* 85 */ "\xc3\x96",
+ /* 86 */ "\xc3\x9c",
+ /* 87 */ "\xc3\xa1",
+ /* 88 */ "\xc3\xa0",
+ /* 89 */ "\xc3\xa2",
+ /* 8A */ "\xc3\xa4",
+ /* 8B */ "\xc3\xa3",
+ /* 8C */ "\xc3\xa5",
+ /* 8D */ "\xc3\xa7",
+ /* 8E */ "\xc3\xa9",
+ /* 8F */ "\xc3\xa8",
+ /* 90 */ "\xc3\xaa",
+ /* 91 */ "\xc3\xab",
+ /* 92 */ "\xc3\xad",
+ /* 93 */ "\xc3\xac",
+ /* 94 */ "\xc3\xae",
+ /* 95 */ "\xc3\xaf",
+ /* 96 */ "\xc3\xb1",
+ /* 97 */ "\xc3\xb3",
+ /* 98 */ "\xc3\xb2",
+ /* 99 */ "\xc3\xb4",
+ /* 9A */ "\xc3\xb6",
+ /* 9B */ "\xc3\xb5",
+ /* 9C */ "\xc3\xba",
+ /* 9D */ "\xc3\xb9",
+ /* 9E */ "\xc3\xbb",
+ /* 9F */ "\xc3\xbc",
+ /* A0 */ "\xe2\x80\xa0",
+ /* A1 */ "\xc2\xb0",
+ /* A2 */ "\xc2\xa2",
+ /* A3 */ "\xc2\xa3",
+ /* A4 */ "\xc2\xa7",
+ /* A5 */ "\xe2\x80\xa2",
+ /* A6 */ "\xc2\xb6",
+ /* A7 */ "\xc3\x9f",
+ /* A8 */ "\xc2\xae",
+ /* A9 */ "\xc2\xa9",
+ /* AA */ "\xe2\x84\xa2",
+ /* AB */ "\xc2\xb4",
+ /* AC */ "\xc2\xa8",
+ /* AD */ "\xe2\x89\xa0",
+ /* AE */ "\xc3\x86",
+ /* AF */ "\xc3\x98",
+ /* B0 */ "\xe2\x88\x9e",
+ /* B1 */ "\xc2\xb1",
+ /* B2 */ "\xe2\x89\xa4",
+ /* B3 */ "\xe2\x89\xa5",
+ /* B4 */ "\xc2\xa5",
+ /* B5 */ "\xc2\xb5",
+ /* B6 */ "\xe2\x88\x82",
+ /* B7 */ "\xe2\x88\x91",
+ /* B8 */ "\xe2\x88\x8f",
+ /* B9 */ "\xcf\x80",
+ /* BA */ "\xe2\x88\xab",
+ /* BB */ "\xc2\xaa",
+ /* BC */ "\xc2\xba",
+ /* BD */ "\xce\xa9",
+ /* BE */ "\xc3\xa6",
+ /* BF */ "\xc3\xb8",
+ /* C0 */ "\xc2\xbf",
+ /* C1 */ "\xc2\xa1",
+ /* C2 */ "\xc2\xac",
+ /* C3 */ "\xe2\x88\x9a",
+ /* C4 */ "\xc6\x92",
+ /* C5 */ "\xe2\x89\x88",
+ /* C6 */ "\xe2\x88\x86",
+ /* C7 */ "\xc2\xab",
+ /* C8 */ "\xc2\xbb",
+ /* C9 */ "\xe2\x80\xa6",
+ /* CA */ "\xc2\xa0",
+ /* CB */ "\xc3\x80",
+ /* CC */ "\xc3\x83",
+ /* CD */ "\xc3\x95",
+ /* CE */ "\xc5\x92",
+ /* CF */ "\xc5\x93",
+ /* D0 */ "\xe2\x80\x93",
+ /* D1 */ "\xe2\x80\x94",
+ /* D2 */ "\xe2\x80\x9c",
+ /* D3 */ "\xe2\x80\x9d",
+ /* D4 */ "\xe2\x80\x98",
+ /* D5 */ "\xe2\x80\x99",
+ /* D6 */ "\xc3\xb7",
+ /* D7 */ "\xe2\x97\x8a",
+ /* D8 */ "\xc3\xbf",
+ /* D9 */ "\xc5\xb8",
+ /* DA */ "\xe2\x81\x84",
+ /* DB */ "\xe2\x82\xac",
+ /* DC */ "\xe2\x80\xb9",
+ /* DD */ "\xe2\x80\xba",
+ /* DE */ "\xef\xac\x81",
+ /* DF */ "\xef\xac\x82",
+ /* E0 */ "\xe2\x80\xa1",
+ /* E1 */ "\xc2\xb7",
+ /* E2 */ "\xe2\x80\x9a",
+ /* E3 */ "\xe2\x80\x9e",
+ /* E4 */ "\xe2\x80\xb0",
+ /* E5 */ "\xc3\x82",
+ /* E6 */ "\xc3\x8a",
+ /* E7 */ "\xc3\x81",
+ /* E8 */ "\xc3\x8b",
+ /* E9 */ "\xc3\x88",
+ /* EA */ "\xc3\x8d",
+ /* EB */ "\xc3\x8e",
+ /* EC */ "\xc3\x8f",
+ /* ED */ "\xc3\x8c",
+ /* EE */ "\xc3\x93",
+ /* EF */ "\xc3\x94",
+ /* F0 */ "\xef\xa3\xbf",
+ /* F1 */ "\xc3\x92",
+ /* F2 */ "\xc3\x9a",
+ /* F3 */ "\xc3\x9b",
+ /* F4 */ "\xc3\x99",
+ /* F5 */ "\xc4\xb1",
+ /* F6 */ "\xcb\x86",
+ /* F7 */ "\xcb\x9c",
+ /* F8 */ "\xc2\xaf",
+ /* F9 */ "\xcb\x98",
+ /* FA */ "\xcb\x99",
+ /* FB */ "\xcb\x9a",
+ /* FC */ "\xc2\xb8",
+ /* FD */ "\xcb\x9d",
+ /* FE */ "\xcb\x9b",
+ /* FF */ "\xcb\x87",
+ };
+
+static void
+macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len)
+{
+ char *optr = to;
+ const grub_uint8_t *iptr;
+
+ for (iptr = from; iptr < from + len && *iptr; iptr++)
+ {
+ if (!(*iptr & 0x80))
+ {
+ *optr++ = *iptr;
+ continue;
+ }
+ optr = grub_stpcpy (optr, macroman[*iptr & 0x7f]);
+ }
+ *optr = 0;
+}
+
+static grub_ssize_t
+utf8_to_macroman (grub_uint8_t *to, const char *from)
+{
+ grub_uint8_t *end = to + 31;
+ grub_uint8_t *optr = to;
+ const char *iptr = from;
+
+ while (*iptr && optr < end)
+ {
+ int i, clen;
+ if (!(*iptr & 0x80))
+ {
+ *optr++ = *iptr++;
+ continue;
+ }
+ clen = 2;
+ if ((*iptr & 0xf0) == 0xe0)
+ clen++;
+ for (i = 0; i < 0x80; i++)
+ if (grub_memcmp (macroman[i], iptr, clen) == 0)
+ break;
+ if (i == 0x80)
+ break;
+ *optr++ = i | 0x80;
+ iptr += clen;
+ }
+ /* Too long or not encodable. */
+ if (*iptr)
+ return -1;
+ return optr - to;
+}
+
/* Find a file or directory with the pathname PATH in the filesystem
DATA. Return the file record in RETDATA when it is non-zero.
while (path && grub_strlen (path))
{
+ grub_ssize_t slen;
if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
struct grub_hfs_catalog_key key;
key.parent_dir = grub_cpu_to_be32 (inode);
- key.strlen = grub_strlen (path);
- grub_strcpy ((char *) (key.str), path);
+ slen = utf8_to_macroman (key.str, path);
+ if (slen < 0)
+ {
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
+ goto fail;
+ }
+ key.strlen = slen;
/* Lookup this node. */
if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
int dir_hook (struct grub_hfs_record *rec)
{
- char fname[32] = { 0 };
+ char fname[32 * MAX_UTF8_PER_MAC_ROMAN] = { 0 };
struct grub_hfs_dirrec *drec = rec->data;
struct grub_hfs_filerec *frec = rec->data;
struct grub_hfs_catalog_key *ckey = rec->key;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
- grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
+ macroman_to_utf8 (fname, ckey->str, ckey->strlen);
+
+ info.case_insensitive = 1;
if (drec->type == GRUB_HFS_FILETYPE_DIR)
{