diff --git a/ChangeLog b/ChangeLog index 6809db62d..c1216c833 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-25 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Mention SFS as Latin1 filesystem. + * grub-core/fs/sfs.c (grub_sfs_mount): Fix a memory leak while on it. + (grub_sfs_iterate_dir): Convert Latin1 to UTF8. Stylistic and + performance fixes while on it. + (grub_sfs_close): Fix memory leak while on it. + (grub_sfs_label): Convert Latin1 to UTF-8. + 2011-12-25 Vladimir Serbinenko * grub-core/fs/hfs.c (grub_hfs_dir): Cap keylen to actually available diff --git a/docs/grub.texi b/docs/grub.texi index 0ebdcf4c4..88c21bc2e 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3940,14 +3940,14 @@ ISO9660 (plain and RockRidge), nilfs2, UFS1, UFS2 and ZFS are assumed to be UTF-8. This might be false on systems configured with legacy charset but as long as the charset used is superset of ASCII you should be able to access ASCII-named files. And it's recommended to configure your system to use -UTF-8 to access the filesystem, convmv may help with migration. AFFS and HFS -never use unicode and GRUB assumes them to be in Latin1 and MacRoman -respectively. GRUB handles filesystem case-insensitivity however no attempt -is performed at case conversion of international characters so e.g. a file -named lowercase greek alpha is treated as different from the one named -as uppercase alpha. The filesystems in questions are NTFS (except POSIX -namespace), HFS+ (by default), FAT, exFAT -and ZFS (configurable on per-subvolume basis by property ``casesensitivity'', +UTF-8 to access the filesystem, convmv may help with migration. AFFS, SFS +and HFS never use unicode and GRUB assumes them to be in Latin1, Latin1 +and MacRoman respectively. GRUB handles filesystem case-insensitivity however +no attempt is performed at case conversion of international characters +so e.g. a file named lowercase greek alpha is treated as different from +the one named as uppercase alpha. The filesystems in questions are +NTFS (except POSIX namespace), HFS+ (by default), FAT, exFAT and +ZFS (configurable on per-subvolume basis by property ``casesensitivity'', default sensitive). On ZFS subvolumes marked as case insensitive files containing lowercase international characters are inaccessible. Also like all supported filesystems except HFS+ and ZFS (configurable on diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index f1e09ccbd..bc7258963 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -303,6 +304,7 @@ grub_sfs_mount (grub_disk_t disk) data->disk = disk; data->label = grub_strdup ((char *) (rootobjc->objects[0].filename)); + grub_free (rootobjc_data); return data; fail: @@ -357,24 +359,39 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, unsigned int next = dir->block; int pos; - auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, + auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, + int block, int size, int type, grub_uint32_t mtime); - int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, + int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, + int block, int size, int type, grub_uint32_t mtime) { + grub_size_t len = grub_strlen (name); + grub_uint8_t *name_u8; + int ret; node = grub_malloc (sizeof (*node)); if (!node) return 1; + name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + if (!name_u8) + { + grub_free (node); + return 1; + } node->data = data; node->size = size; node->block = block; node->mtime = mtime; - return hook (name, type, node); + *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0'; + + ret = hook ((char *) name_u8, type, node); + grub_free (name_u8); + return ret; } objc_data = grub_malloc (data->blocksize); @@ -398,7 +415,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, { struct grub_sfs_obj *obj; obj = (struct grub_sfs_obj *) ((char *) objc + pos); - char *filename = (char *) (obj->filename); + const char *filename = (const char *) obj->filename; int len; enum grub_fshelp_filetype type; unsigned int block; @@ -412,7 +429,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, /* Round up to a multiple of two bytes. */ pos = ((pos + 1) >> 1) << 1; - if (grub_strlen (filename) == 0) + if (filename[0] == 0) continue; /* First check if the file was not deleted. */ @@ -491,7 +508,10 @@ grub_sfs_open (struct grub_file *file, const char *name) static grub_err_t grub_sfs_close (grub_file_t file) { - grub_free (file->data); + struct grub_sfs_data *data = (struct grub_sfs_data *) file->data; + + grub_free (data->label); + grub_free (data); grub_dl_unref (my_mod); @@ -571,8 +591,15 @@ grub_sfs_label (grub_device_t device, char **label) data = grub_sfs_mount (disk); if (data) - *label = data->label; - + { + grub_size_t len = grub_strlen (data->label); + *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + if (*label) + *grub_latin1_to_utf8 ((grub_uint8_t *) *label, + (const grub_uint8_t *) data->label, + len) = '\0'; + grub_free (data->label); + } grub_free (data); return grub_errno;