From 74bbf0dbae0564c1cd7dfd13185e71ea60337f81 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 24 Dec 2011 20:20:41 +0100 Subject: [PATCH] Make HFS implementation use MacRoman. * grub-core/fs/hfs.c (MAX_UTF8_PER_MAC_ROMAN): New define. (macroman): New const array. (macroman_to_utf8): New function. (utf8_to_macroman): Likewise. (grub_hfs_find_dir): Use utf8_to_macroman. (grub_hfs_dir): Use macroman_to_utf8. Set case_insensitive. --- ChangeLog | 12 +++ grub-core/fs/hfs.c | 200 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 208 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index dea64e198..ccfe212e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-12-24 Vladimir Serbinenko + + Make HFS implementation to use MacRoman. + + * grub-core/fs/hfs.c (MAX_UTF8_PER_MAC_ROMAN): New define. + (macroman): New const array. + (macroman_to_utf8): New function. + (utf8_to_macroman): Likewise. + (grub_hfs_find_dir): Use utf8_to_macroman. + (grub_hfs_dir): Use macroman_to_utf8. + Set case_insensitive. + 2011-12-24 Vladimir Serbinenko * docs/grub.texi (Filesystems): Add IEEE1275 full-path example. diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 6c5c4da3e..4474ebef7 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -862,6 +862,190 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, 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. @@ -896,6 +1080,7 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, 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"); @@ -913,8 +1098,13 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, 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, @@ -955,14 +1145,16 @@ grub_hfs_dir (grub_device_t device, const char *path, 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) {