Support BFS (befs) UUID.

* grub-core/fs/afs.c (grub_afs_inode): Make small_data zero-size.
	(grub_afs_small_data_element_header): New struct.
	(grub_afs_read_inode): Read complete inode. Fix ino type while on it.
	(grub_afs_read_attribute) [MODE_BFS]: New function.
	(grub_afs_iterate_dir): Allocate for complete inode.
	(grub_afs_mount): Likewise.
	(grub_afs_uuid) [MODE_BFS]: New function.
	(grub_afs_fs) [MODE_BFS]: Add .uuid.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-10-27 20:58:52 +02:00
parent f8d82408d9
commit 5b1ae25f06
2 changed files with 162 additions and 14 deletions

View file

@ -1,3 +1,16 @@
2011-10-27 Vladimir Serbinenko <phcoder@gmail.com>
Support BFS (befs) UUID.
* grub-core/fs/afs.c (grub_afs_inode): Make small_data zero-size.
(grub_afs_small_data_element_header): New struct.
(grub_afs_read_inode): Read complete inode. Fix ino type while on it.
(grub_afs_read_attribute) [MODE_BFS]: New function.
(grub_afs_iterate_dir): Allocate for complete inode.
(grub_afs_mount): Likewise.
(grub_afs_uuid) [MODE_BFS]: New function.
(grub_afs_fs) [MODE_BFS]: Add .uuid.
2011-10-27 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/fs/zfs/zfs.c (read_device): Silence spurious warning.

View file

@ -210,7 +210,14 @@ struct grub_afs_inode
grub_uint32_t unused;
struct grub_afs_datastream stream;
grub_uint32_t pad[4];
grub_uint32_t small_data[1];
grub_uint8_t small_data[0];
} __attribute__ ((packed));
struct grub_afs_small_data_element_header
{
grub_uint32_t type;
grub_uint16_t name_len;
grub_uint16_t value_len;
} __attribute__ ((packed));
struct grub_fshelp_node
@ -229,6 +236,19 @@ struct grub_afs_data
static grub_dl_t my_mod;
static int
grub_afs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node));
static grub_ssize_t
grub_afs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
grub_off_t pos, grub_size_t len, char *buf);
static grub_afs_off_t
grub_afs_run_to_num (struct grub_afs_sblock *sb,
struct grub_afs_blockrun *run)
@ -239,15 +259,87 @@ grub_afs_run_to_num (struct grub_afs_sblock *sb,
static grub_err_t
grub_afs_read_inode (struct grub_afs_data *data,
grub_uint32_t ino, struct grub_afs_inode *inode)
grub_uint64_t ino, struct grub_afs_inode *inode)
{
return grub_disk_read (data->disk,
ino *
(data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (struct grub_afs_inode),
inode);
0, data->sblock.block_size, inode);
}
#ifdef MODE_BFS
static grub_ssize_t
grub_afs_read_attribute (grub_fshelp_node_t node,
const char *name, char *buf, grub_size_t len)
{
grub_ssize_t read = -1;
auto int NESTED_FUNC_ATTR hook (const char *filename,
enum grub_fshelp_filetype filetype
__attribute__ ((unused)),
grub_fshelp_node_t attr_node);
int NESTED_FUNC_ATTR hook (const char *filename,
enum grub_fshelp_filetype filetype
__attribute__ ((unused)),
grub_fshelp_node_t attr_node)
{
if (grub_strcmp (filename, name) == 0)
{
read = grub_afs_read_file (attr_node, 0, 0, len, buf);
return 1;
}
return 0;
}
grub_uint8_t *ptr = node->inode.small_data;
grub_uint8_t *end = ((grub_uint8_t *) &node->inode
+ node->data->sblock.block_size);
while (ptr + sizeof (struct grub_afs_small_data_element_header) < end)
{
struct grub_afs_small_data_element_header *el;
char *el_name;
grub_uint8_t *data;
el = (struct grub_afs_small_data_element_header *) ptr;
if (el->name_len == 0)
break;
el_name = (char *) (el + 1);
data = (grub_uint8_t *) el_name + grub_afs_to_cpu16 (el->name_len) + 3;
ptr = data + grub_afs_to_cpu16 (el->value_len) + 1;
if (grub_memcmp (name, el_name, grub_afs_to_cpu16 (el->name_len)) == 0
&& name[el->name_len] == 0)
{
grub_size_t copy;
copy = len;
if (grub_afs_to_cpu16 (el->value_len) > copy)
copy = grub_afs_to_cpu16 (el->value_len);
grub_memcpy (buf, data, copy);
return copy;
}
}
{
struct grub_fshelp_node *fdiro;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
+ node->data->sblock.block_size
- sizeof (struct grub_afs_inode));
if (! fdiro)
return -1;
fdiro->data = node->data;
if (grub_afs_read_inode (node->data,
grub_afs_run_to_num (&node->data->sblock,
&node->inode.attrib_dir),
&fdiro->inode))
return -1;
grub_afs_iterate_dir (fdiro, hook);
}
return read;
}
#endif
static grub_disk_addr_t
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
@ -424,7 +516,9 @@ grub_afs_iterate_dir (grub_fshelp_node_t dir,
struct grub_fshelp_node *fdiro;
int mode, type;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
+ dir->data->sblock.block_size
- sizeof (struct grub_afs_inode));
if (! fdiro)
return 0;
@ -521,18 +615,31 @@ static struct grub_afs_data *
grub_afs_mount (grub_disk_t disk)
{
struct grub_afs_data *data = 0;
data = grub_malloc (sizeof (struct grub_afs_data));
if (!data)
return 0;
struct grub_afs_sblock sb;
grub_err_t err;
/* Read the superblock. */
if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
sizeof (struct grub_afs_sblock), &data->sblock))
goto fail;
err = grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
sizeof (struct grub_afs_sblock), &sb);
if (err)
{
if (err == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
return NULL;
}
if (! grub_afs_validate_sblock (&data->sblock))
goto fail;
if (! grub_afs_validate_sblock (&sb))
{
grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
return NULL;
}
data = grub_malloc (sizeof (struct grub_afs_data) + sb.block_size
- sizeof (struct grub_afs_inode));
if (!data)
return NULL;
data->sblock = sb;
data->diropen.data = data;
data->inode = &data->diropen.inode;
@ -681,6 +788,31 @@ grub_afs_label (grub_device_t device, char **label)
return grub_errno;
}
#ifdef MODE_BFS
static grub_err_t
grub_afs_uuid (grub_device_t device, char **uuid)
{
struct grub_afs_data *data;
grub_disk_t disk = device->disk;
grub_uint64_t vid;
grub_ssize_t read;
*uuid = NULL;
data = grub_afs_mount (disk);
if (!data)
return grub_errno;
read = grub_afs_read_attribute (&data->diropen, "be:volume_id",
(char *) &vid,
sizeof (vid));
if (read == sizeof (vid))
*uuid = grub_xasprintf ("%" PRIxGRUB_UINT64_T, grub_afs_to_cpu64 (vid));
grub_free (data);
return grub_errno;
}
#endif
static struct grub_fs grub_afs_fs = {
.name = GRUB_AFS_FSNAME,
@ -689,6 +821,9 @@ static struct grub_fs grub_afs_fs = {
.read = grub_afs_read,
.close = grub_afs_close,
.label = grub_afs_label,
#ifdef MODE_BFS
.uuid = grub_afs_uuid,
#endif
.next = 0
};