Read label on HFS+.

* grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey_id): New function.
	(grub_hfsplus_btree_search): Fix types.
	(grub_hfsplus_label): Implement.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-10-26 00:32:17 +02:00
parent e9cc6b7b0e
commit 67e2bd718e
2 changed files with 88 additions and 7 deletions

View File

@ -1,3 +1,11 @@
2011-10-25 Vladimir Serbinenko <phcoder@gmail.com>
Read label on HFS+.
* grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey_id): New function.
(grub_hfsplus_btree_search): Fix types.
(grub_hfsplus_label): Implement.
2011-10-25 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/fs/ntfs.c (grub_ntfs_uuid): Fix a memory leak.

View File

@ -553,6 +553,25 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
return diff;
}
/* Compare the on disk catalog key KEYA with the catalog key we are
looking for (KEYB). */
static int
grub_hfsplus_cmp_catkey_id (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb)
{
struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
/* Safe unsigned comparison */
grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent);
if (aparent > catkey_b->parent)
return 1;
if (aparent < catkey_b->parent)
return -1;
return 0;
}
/* Compare the on disk extent overflow key KEYA with the extent
overflow key we are looking for (KEYB). */
static int
@ -662,7 +681,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
/* Read a node. */
if (grub_hfsplus_read_file (&btree->file, 0,
(long)currnode * (long)btree->nodesize,
(grub_disk_addr_t) currnode
* (grub_disk_addr_t) btree->nodesize,
btree->nodesize, (char *) node) <= 0)
{
grub_free (node);
@ -961,13 +981,66 @@ grub_hfsplus_dir (grub_device_t device, const char *path,
static grub_err_t
grub_hfsplus_label (grub_device_t device __attribute__((unused))
, char **label __attribute__((unused)))
grub_hfsplus_label (grub_device_t device, char **label)
{
/* XXX: It's not documented how to read a label. */
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"reading the label of a HFS+ "
"partition is not implemented");
struct grub_hfsplus_data *data;
grub_disk_t disk = device->disk;
struct grub_hfsplus_catkey *catkey;
int i, label_len;
struct grub_hfsplus_key_internal intern;
struct grub_hfsplus_btnode *node;
grub_disk_addr_t ptr;
*label = 0;
data = grub_hfsplus_mount (disk);
if (!data)
return grub_errno;
/* Create a key that points to the label. */
intern.catkey.parent = 1;
intern.catkey.name = "";
/* First lookup the first entry. */
if (grub_hfsplus_btree_search (&data->catalog_tree, &intern,
grub_hfsplus_cmp_catkey_id, &node, &ptr))
{
grub_free (data);
return 0;
}
catkey = (struct grub_hfsplus_catkey *)
grub_hfsplus_btree_recptr (&data->catalog_tree, node, 0);
label_len = grub_be_to_cpu16 (catkey->namelen);
for (i = 0; i < label_len; i++)
{
catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
/* If the name is obviously invalid, skip this node. */
if (catkey->name[i] == 0)
return 0;
}
*label = grub_malloc (label_len + 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_free (node);
grub_free (data);
return GRUB_ERR_NONE;
}
/* Get mtime. */