Support 4K sectors UDF inline files.
* grub-core/fs/udf.c (grub_udf_file_entry): Don't specify padding size. (grub_udf_extended_file_entry): Likewise. (grub_fshelp_node): Name the anonymous union. Put block at the end. All users updated. (get_fshelp_size): New function. (grub_udf_read_icb): Read whole block. (grub_udf_iterate_dir): Likewise. (grub_udf_dir): Likewise. (grub_udf_open): Likewise.
This commit is contained in:
parent
c82f16c1be
commit
a3a0eace51
2 changed files with 78 additions and 41 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2012-05-03 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Support 4K sectors UDF inline files.
|
||||||
|
|
||||||
|
* grub-core/fs/udf.c (grub_udf_file_entry): Don't specify padding size.
|
||||||
|
(grub_udf_extended_file_entry): Likewise.
|
||||||
|
(grub_fshelp_node): Name the anonymous union. Put block at the end.
|
||||||
|
All users updated.
|
||||||
|
(get_fshelp_size): New function.
|
||||||
|
(grub_udf_read_icb): Read whole block.
|
||||||
|
(grub_udf_iterate_dir): Likewise.
|
||||||
|
(grub_udf_dir): Likewise.
|
||||||
|
(grub_udf_open): Likewise.
|
||||||
|
|
||||||
2012-05-03 Vladimir Serbinenko <phcoder@gmail.com>
|
2012-05-03 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/fs/ufs.c (grub_ufs_get_file_block): Support triple indirect.
|
* grub-core/fs/ufs.c (grub_ufs_get_file_block): Support triple indirect.
|
||||||
|
|
|
@ -242,7 +242,7 @@ struct grub_udf_file_entry
|
||||||
grub_uint64_t unique_id;
|
grub_uint64_t unique_id;
|
||||||
grub_uint32_t ext_attr_length;
|
grub_uint32_t ext_attr_length;
|
||||||
grub_uint32_t alloc_descs_length;
|
grub_uint32_t alloc_descs_length;
|
||||||
grub_uint8_t ext_attr[1872];
|
grub_uint8_t ext_attr[0];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct grub_udf_extended_file_entry
|
struct grub_udf_extended_file_entry
|
||||||
|
@ -271,7 +271,7 @@ struct grub_udf_extended_file_entry
|
||||||
grub_uint64_t unique_id;
|
grub_uint64_t unique_id;
|
||||||
grub_uint32_t ext_attr_length;
|
grub_uint32_t ext_attr_length;
|
||||||
grub_uint32_t alloc_descs_length;
|
grub_uint32_t alloc_descs_length;
|
||||||
grub_uint8_t ext_attr[1832];
|
grub_uint8_t ext_attr[0];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct grub_udf_vrs
|
struct grub_udf_vrs
|
||||||
|
@ -356,13 +356,23 @@ struct grub_udf_data
|
||||||
struct grub_fshelp_node
|
struct grub_fshelp_node
|
||||||
{
|
{
|
||||||
struct grub_udf_data *data;
|
struct grub_udf_data *data;
|
||||||
|
int part_ref;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct grub_udf_file_entry fe;
|
struct grub_udf_file_entry fe;
|
||||||
struct grub_udf_extended_file_entry efe;
|
struct grub_udf_extended_file_entry efe;
|
||||||
|
char raw[0];
|
||||||
|
} block;
|
||||||
};
|
};
|
||||||
int part_ref;
|
|
||||||
};
|
static inline grub_size_t
|
||||||
|
get_fshelp_size (struct grub_udf_data *data)
|
||||||
|
{
|
||||||
|
struct grub_fshelp_node *x = NULL;
|
||||||
|
return sizeof (*x)
|
||||||
|
+ (1 << (GRUB_DISK_SECTOR_BITS
|
||||||
|
+ data->lbshift)) - sizeof (x->block);
|
||||||
|
}
|
||||||
|
|
||||||
static grub_dl_t my_mod;
|
static grub_dl_t my_mod;
|
||||||
|
|
||||||
|
@ -397,12 +407,13 @@ grub_udf_read_icb (struct grub_udf_data *data,
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
if (grub_disk_read (data->disk, block << data->lbshift, 0,
|
if (grub_disk_read (data->disk, block << data->lbshift, 0,
|
||||||
sizeof (struct grub_udf_file_entry),
|
1 << (GRUB_DISK_SECTOR_BITS
|
||||||
&node->fe))
|
+ data->lbshift),
|
||||||
|
&node->block))
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
if ((U16 (node->fe.tag.tag_ident) != GRUB_UDF_TAG_IDENT_FE) &&
|
if ((U16 (node->block.fe.tag.tag_ident) != GRUB_UDF_TAG_IDENT_FE) &&
|
||||||
(U16 (node->fe.tag.tag_ident) != GRUB_UDF_TAG_IDENT_EFE))
|
(U16 (node->block.fe.tag.tag_ident) != GRUB_UDF_TAG_IDENT_EFE))
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "invalid fe/efe descriptor");
|
return grub_error (GRUB_ERR_BAD_FS, "invalid fe/efe descriptor");
|
||||||
|
|
||||||
node->part_ref = icb->block.part_ref;
|
node->part_ref = icb->block.part_ref;
|
||||||
|
@ -418,16 +429,16 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
grub_ssize_t len;
|
grub_ssize_t len;
|
||||||
grub_disk_addr_t filebytes;
|
grub_disk_addr_t filebytes;
|
||||||
|
|
||||||
switch (U16 (node->fe.tag.tag_ident))
|
switch (U16 (node->block.fe.tag.tag_ident))
|
||||||
{
|
{
|
||||||
case GRUB_UDF_TAG_IDENT_FE:
|
case GRUB_UDF_TAG_IDENT_FE:
|
||||||
ptr = (char *) &node->fe.ext_attr[0] + U32 (node->fe.ext_attr_length);
|
ptr = (char *) &node->block.fe.ext_attr[0] + U32 (node->block.fe.ext_attr_length);
|
||||||
len = U32 (node->fe.alloc_descs_length);
|
len = U32 (node->block.fe.alloc_descs_length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GRUB_UDF_TAG_IDENT_EFE:
|
case GRUB_UDF_TAG_IDENT_EFE:
|
||||||
ptr = (char *) &node->efe.ext_attr[0] + U32 (node->efe.ext_attr_length);
|
ptr = (char *) &node->block.efe.ext_attr[0] + U32 (node->block.efe.ext_attr_length);
|
||||||
len = U32 (node->efe.alloc_descs_length);
|
len = U32 (node->block.efe.alloc_descs_length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -435,7 +446,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
|
if ((U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
|
||||||
== GRUB_UDF_ICBTAG_FLAG_AD_SHORT)
|
== GRUB_UDF_ICBTAG_FLAG_AD_SHORT)
|
||||||
{
|
{
|
||||||
struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr;
|
struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr;
|
||||||
|
@ -558,17 +569,17 @@ grub_udf_read_file (grub_fshelp_node_t node,
|
||||||
unsigned offset, unsigned length),
|
unsigned offset, unsigned length),
|
||||||
grub_off_t pos, grub_size_t len, char *buf)
|
grub_off_t pos, grub_size_t len, char *buf)
|
||||||
{
|
{
|
||||||
switch (U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
|
switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
|
||||||
{
|
{
|
||||||
case GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB:
|
case GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB:
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
ptr = ((U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) ?
|
ptr = ((U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) ?
|
||||||
((char *) &node->fe.ext_attr[0]
|
((char *) &node->block.fe.ext_attr[0]
|
||||||
+ U32 (node->fe.ext_attr_length)) :
|
+ U32 (node->block.fe.ext_attr_length)) :
|
||||||
((char *) &node->efe.ext_attr[0]
|
((char *) &node->block.efe.ext_attr[0]
|
||||||
+ U32 (node->efe.ext_attr_length)));
|
+ U32 (node->block.efe.ext_attr_length)));
|
||||||
|
|
||||||
grub_memcpy (buf, ptr + pos, len);
|
grub_memcpy (buf, ptr + pos, len);
|
||||||
|
|
||||||
|
@ -582,7 +593,7 @@ grub_udf_read_file (grub_fshelp_node_t node,
|
||||||
|
|
||||||
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
||||||
pos, len, buf, grub_udf_read_block,
|
pos, len, buf, grub_udf_read_block,
|
||||||
U64 (node->fe.file_size),
|
U64 (node->block.fe.file_size),
|
||||||
node->data->lbshift);
|
node->data->lbshift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,18 +849,17 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||||
struct grub_udf_file_ident dirent;
|
struct grub_udf_file_ident dirent;
|
||||||
grub_off_t offset = 0;
|
grub_off_t offset = 0;
|
||||||
|
|
||||||
child = grub_malloc (sizeof (struct grub_fshelp_node));
|
child = grub_malloc (get_fshelp_size (dir->data));
|
||||||
if (!child)
|
if (!child)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* The current directory is not stored. */
|
/* The current directory is not stored. */
|
||||||
grub_memcpy ((char *) child, (char *) dir,
|
grub_memcpy (child, dir, get_fshelp_size (dir->data));
|
||||||
sizeof (struct grub_fshelp_node));
|
|
||||||
|
|
||||||
if (hook (".", GRUB_FSHELP_DIR, child))
|
if (hook (".", GRUB_FSHELP_DIR, child))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
while (offset < U64 (dir->fe.file_size))
|
while (offset < U64 (dir->block.fe.file_size))
|
||||||
{
|
{
|
||||||
if (grub_udf_read_file (dir, 0, offset, sizeof (dirent),
|
if (grub_udf_read_file (dir, 0, offset, sizeof (dirent),
|
||||||
(char *) &dirent) != sizeof (dirent))
|
(char *) &dirent) != sizeof (dirent))
|
||||||
|
@ -864,7 +874,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||||
offset += sizeof (dirent) + U16 (dirent.imp_use_length);
|
offset += sizeof (dirent) + U16 (dirent.imp_use_length);
|
||||||
if (!(dirent.characteristics & GRUB_UDF_FID_CHAR_DELETED))
|
if (!(dirent.characteristics & GRUB_UDF_FID_CHAR_DELETED))
|
||||||
{
|
{
|
||||||
child = grub_malloc (sizeof (struct grub_fshelp_node));
|
child = grub_malloc (get_fshelp_size (dir->data));
|
||||||
if (!child)
|
if (!child)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -885,7 +895,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
|
||||||
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
|
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
|
||||||
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
|
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
|
||||||
if (child->fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
|
if (child->block.fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
|
||||||
type = GRUB_FSHELP_SYMLINK;
|
type = GRUB_FSHELP_SYMLINK;
|
||||||
|
|
||||||
if ((grub_udf_read_file (dir, 0, offset,
|
if ((grub_udf_read_file (dir, 0, offset,
|
||||||
|
@ -917,7 +927,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||||
static char *
|
static char *
|
||||||
grub_ufs_read_symlink (grub_fshelp_node_t node)
|
grub_ufs_read_symlink (grub_fshelp_node_t node)
|
||||||
{
|
{
|
||||||
grub_size_t sz = U64 (node->fe.file_size);
|
grub_size_t sz = U64 (node->block.fe.file_size);
|
||||||
grub_uint8_t *raw;
|
grub_uint8_t *raw;
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
|
@ -939,8 +949,8 @@ grub_udf_dir (grub_device_t device, const char *path,
|
||||||
const struct grub_dirhook_info *info))
|
const struct grub_dirhook_info *info))
|
||||||
{
|
{
|
||||||
struct grub_udf_data *data = 0;
|
struct grub_udf_data *data = 0;
|
||||||
struct grub_fshelp_node rootnode;
|
struct grub_fshelp_node *rootnode = 0;
|
||||||
struct grub_fshelp_node *foundnode;
|
struct grub_fshelp_node *foundnode = 0;
|
||||||
|
|
||||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||||
enum grub_fshelp_filetype filetype,
|
enum grub_fshelp_filetype filetype,
|
||||||
|
@ -954,10 +964,10 @@ grub_udf_dir (grub_device_t device, const char *path,
|
||||||
const struct grub_udf_timestamp *tstamp = NULL;
|
const struct grub_udf_timestamp *tstamp = NULL;
|
||||||
grub_memset (&info, 0, sizeof (info));
|
grub_memset (&info, 0, sizeof (info));
|
||||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||||
if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
||||||
tstamp = &node->fe.modification_time;
|
tstamp = &node->block.fe.modification_time;
|
||||||
else if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
||||||
tstamp = &node->efe.modification_time;
|
tstamp = &node->block.efe.modification_time;
|
||||||
|
|
||||||
if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
||||||
{
|
{
|
||||||
|
@ -991,10 +1001,14 @@ grub_udf_dir (grub_device_t device, const char *path,
|
||||||
if (!data)
|
if (!data)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (grub_udf_read_icb (data, &data->root_icb, &rootnode))
|
rootnode = grub_malloc (get_fshelp_size (data));
|
||||||
|
if (!rootnode)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (grub_fshelp_find_file (path, &rootnode,
|
if (grub_udf_read_icb (data, &data->root_icb, rootnode))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (grub_fshelp_find_file (path, rootnode,
|
||||||
&foundnode,
|
&foundnode,
|
||||||
grub_udf_iterate_dir, grub_ufs_read_symlink,
|
grub_udf_iterate_dir, grub_ufs_read_symlink,
|
||||||
GRUB_FSHELP_DIR))
|
GRUB_FSHELP_DIR))
|
||||||
|
@ -1002,10 +1016,12 @@ grub_udf_dir (grub_device_t device, const char *path,
|
||||||
|
|
||||||
grub_udf_iterate_dir (foundnode, iterate);
|
grub_udf_iterate_dir (foundnode, iterate);
|
||||||
|
|
||||||
if (foundnode != &rootnode)
|
if (foundnode != rootnode)
|
||||||
grub_free (foundnode);
|
grub_free (foundnode);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
grub_free (rootnode);
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
grub_dl_unref (my_mod);
|
||||||
|
@ -1017,7 +1033,7 @@ static grub_err_t
|
||||||
grub_udf_open (struct grub_file *file, const char *name)
|
grub_udf_open (struct grub_file *file, const char *name)
|
||||||
{
|
{
|
||||||
struct grub_udf_data *data;
|
struct grub_udf_data *data;
|
||||||
struct grub_fshelp_node rootnode;
|
struct grub_fshelp_node *rootnode = 0;
|
||||||
struct grub_fshelp_node *foundnode;
|
struct grub_fshelp_node *foundnode;
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
grub_dl_ref (my_mod);
|
||||||
|
@ -1026,10 +1042,14 @@ grub_udf_open (struct grub_file *file, const char *name)
|
||||||
if (!data)
|
if (!data)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (grub_udf_read_icb (data, &data->root_icb, &rootnode))
|
rootnode = grub_malloc (get_fshelp_size (data));
|
||||||
|
if (!rootnode)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (grub_fshelp_find_file (name, &rootnode,
|
if (grub_udf_read_icb (data, &data->root_icb, rootnode))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (grub_fshelp_find_file (name, rootnode,
|
||||||
&foundnode,
|
&foundnode,
|
||||||
grub_udf_iterate_dir, grub_ufs_read_symlink,
|
grub_udf_iterate_dir, grub_ufs_read_symlink,
|
||||||
GRUB_FSHELP_REG))
|
GRUB_FSHELP_REG))
|
||||||
|
@ -1037,7 +1057,9 @@ grub_udf_open (struct grub_file *file, const char *name)
|
||||||
|
|
||||||
file->data = foundnode;
|
file->data = foundnode;
|
||||||
file->offset = 0;
|
file->offset = 0;
|
||||||
file->size = U64 (foundnode->fe.file_size);
|
file->size = U64 (foundnode->block.fe.file_size);
|
||||||
|
|
||||||
|
grub_free (rootnode);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1045,6 +1067,7 @@ fail:
|
||||||
grub_dl_unref (my_mod);
|
grub_dl_unref (my_mod);
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
grub_free (rootnode);
|
||||||
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue