2008-05-20 Bean <bean123ch@gmail.com>

* fs/fshelp.c (grub_fshelp_map_block): New function.
	(grub_fshelp_find_file): Use 64-bit type for pos and block address.
	Use `>>' and `&' operator to avoid 64-bit divide and modulo.

	* include/grub/fshelp.h (grub_fshelp_journal_type): New enum.
	(GRUB_FSHELP_JOURNAL_UNUSED_MAPPING): New macro.
	(grub_fshelp_journal): New structure.
	(grub_fshelp_map_block): New function prototype.
	(grub_fshelp_read_file): Use grub_disk_addr_t as block type.
	(grub_fshelp_map_block): Likewise.

	* fs/ext2.c (EXT3_FEATURE_COMPAT_HAS_JOURNAL): New macro.
	(EXT3_JOURNAL_MAGIC_NUMBER): Likewise.
	(EXT3_JOURNAL_DESCRIPTOR_BLOCK): Likewise.
	(EXT3_JOURNAL_COMMIT_BLOCK): Likewise.
	(EXT3_JOURNAL_SUPERBLOCK_V1): Likewise.
	(EXT3_JOURNAL_SUPERBLOCK_V2): Likewise.
	(EXT3_JOURNAL_REVOKE_BLOCK): Likewise.
	(EXT3_JOURNAL_FLAG_ESCAPE): Likewise.
	(EXT3_JOURNAL_FLAG_SAME_UUID): Likewise.
	(EXT3_JOURNAL_FLAG_DELETED): Likewise.
	(EXT3_JOURNAL_FLAG_LAST_TAG): Likewise.
	(grub_ext2_sblock): New members for journal support.
	(grub_ext3_journal_header): New structure.
	(grub_ext3_journal_revoke_header): Likewise.
	(grub_ext3_journal_block_tag): Likewise.
	(grub_ext3_journal_sblock): Likewise.
	(grub_fshelp_node): New members logfile and journal.
	(grub_ext2_read_block): Change block type to grub_disk_addr_t. Use
	grub_fshelp_map_block to get real block number.
	(grub_ext2_blockgroup): Use grub_fshelp_map_block to get real block
	number.
	(grub_ext2_read_inode): Likewise.
	(grub_ext3_get_journal): New function.
	(grub_read_inode): Initialize journal using grub_ext3_get_journal.
	(grub_ext2_close): Release memory used by journal.

	* fs/reiserfs.c (REISERFS_MAGIC_STRING): Changed to "ReIsEr".
	(REISERFS_MAGIC_DESC_BLOCK): New macro.
	(grub_reiserfs_transaction_header): Renamed to
	grub_reiserfs_description_block, replace field data with real_blocks.
	(grub_reiserfs_commit_block): New structure.
	(grub_reiserfs_data): New member journal.
	(grub_reiserfs_get_item): Use grub_fshelp_map_block to get real block
	number.
	(grub_reiserfs_read_symlink): Likewise.
	(grub_reiserfs_iterate_dir): Likewise.
	(grub_reiserfs_open): Likewise.
	(grub_reiserfs_read): Likewise.
	(grub_reiserfs_get_journal): New function.
	(grub_reiserfs_mount): Use "ReIsEr" as super block magic, as there are
	three varieties ReIsErFs, ReIsEr2Fs and ReIsEr3Fs. Initialize journal
	using grub_reiserfs_get_journal.
	(grub_reiserfs_close): Release memory used by journal.

	* fs/affs.c (grub_affs_read_block): Change block type to
	grub_disk_addr_t. Use grub_divmod64 to do 64-bit division.

	* fs/afs.c (grub_afs_read_block): Change block type to grub_disk_addr_t.

	* fs/hfsplus.c (grub_hfsplus_read_block): Likewise.

	* fs/ntfs.c (grub_ntfs_read_block): Likewise.

	* fs/udf.c (grub_udf_read_block): Change block type to
	grub_disk_addr_t. Use type cast to avoid warning.

	* fs/xfs.c (grub_xfs_read_block): Likewise.
This commit is contained in:
bean 2008-05-20 05:00:53 +00:00
parent b7c6bed50e
commit 887d2619bf
12 changed files with 575 additions and 83 deletions

View file

@ -1,3 +1,74 @@
2008-05-20 Bean <bean123ch@gmail.com>
* fs/fshelp.c (grub_fshelp_map_block): New function.
(grub_fshelp_find_file): Use 64-bit type for pos and block address.
Use `>>' and `&' operator to avoid 64-bit divide and modulo.
* include/grub/fshelp.h (grub_fshelp_journal_type): New enum.
(GRUB_FSHELP_JOURNAL_UNUSED_MAPPING): New macro.
(grub_fshelp_journal): New structure.
(grub_fshelp_map_block): New function prototype.
(grub_fshelp_read_file): Use grub_disk_addr_t as block type.
(grub_fshelp_map_block): Likewise.
* fs/ext2.c (EXT3_FEATURE_COMPAT_HAS_JOURNAL): New macro.
(EXT3_JOURNAL_MAGIC_NUMBER): Likewise.
(EXT3_JOURNAL_DESCRIPTOR_BLOCK): Likewise.
(EXT3_JOURNAL_COMMIT_BLOCK): Likewise.
(EXT3_JOURNAL_SUPERBLOCK_V1): Likewise.
(EXT3_JOURNAL_SUPERBLOCK_V2): Likewise.
(EXT3_JOURNAL_REVOKE_BLOCK): Likewise.
(EXT3_JOURNAL_FLAG_ESCAPE): Likewise.
(EXT3_JOURNAL_FLAG_SAME_UUID): Likewise.
(EXT3_JOURNAL_FLAG_DELETED): Likewise.
(EXT3_JOURNAL_FLAG_LAST_TAG): Likewise.
(grub_ext2_sblock): New members for journal support.
(grub_ext3_journal_header): New structure.
(grub_ext3_journal_revoke_header): Likewise.
(grub_ext3_journal_block_tag): Likewise.
(grub_ext3_journal_sblock): Likewise.
(grub_fshelp_node): New members logfile and journal.
(grub_ext2_read_block): Change block type to grub_disk_addr_t. Use
grub_fshelp_map_block to get real block number.
(grub_ext2_blockgroup): Use grub_fshelp_map_block to get real block
number.
(grub_ext2_read_inode): Likewise.
(grub_ext3_get_journal): New function.
(grub_read_inode): Initialize journal using grub_ext3_get_journal.
(grub_ext2_close): Release memory used by journal.
* fs/reiserfs.c (REISERFS_MAGIC_STRING): Changed to "ReIsEr".
(REISERFS_MAGIC_DESC_BLOCK): New macro.
(grub_reiserfs_transaction_header): Renamed to
grub_reiserfs_description_block, replace field data with real_blocks.
(grub_reiserfs_commit_block): New structure.
(grub_reiserfs_data): New member journal.
(grub_reiserfs_get_item): Use grub_fshelp_map_block to get real block
number.
(grub_reiserfs_read_symlink): Likewise.
(grub_reiserfs_iterate_dir): Likewise.
(grub_reiserfs_open): Likewise.
(grub_reiserfs_read): Likewise.
(grub_reiserfs_get_journal): New function.
(grub_reiserfs_mount): Use "ReIsEr" as super block magic, as there are
three varieties ReIsErFs, ReIsEr2Fs and ReIsEr3Fs. Initialize journal
using grub_reiserfs_get_journal.
(grub_reiserfs_close): Release memory used by journal.
* fs/affs.c (grub_affs_read_block): Change block type to
grub_disk_addr_t. Use grub_divmod64 to do 64-bit division.
* fs/afs.c (grub_afs_read_block): Change block type to grub_disk_addr_t.
* fs/hfsplus.c (grub_hfsplus_read_block): Likewise.
* fs/ntfs.c (grub_ntfs_read_block): Likewise.
* fs/udf.c (grub_udf_read_block): Change block type to
grub_disk_addr_t. Use type cast to avoid warning.
* fs/xfs.c (grub_xfs_read_block): Likewise.
2008-05-16 Christian Franke <franke@computer.org> 2008-05-16 Christian Franke <franke@computer.org>
* commands/cat.c (grub_cmd_cat): Remove non-ESC keys from keyboard queue * commands/cat.c (grub_cmd_cat): Remove non-ESC keys from keyboard queue

View file

@ -109,18 +109,19 @@ static grub_dl_t my_mod;
#endif #endif
static int static grub_disk_addr_t
grub_affs_read_block (grub_fshelp_node_t node, int fileblock) grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
int links; int links;
grub_uint32_t pos; grub_uint32_t pos;
int block = node->block; int block = node->block;
struct grub_affs_file file; struct grub_affs_file file;
struct grub_affs_data *data = node->data; struct grub_affs_data *data = node->data;
grub_uint32_t mod;
/* Find the block that points to the fileblock we are looking up by /* Find the block that points to the fileblock we are looking up by
following the chain until the right table is reached. */ following the chain until the right table is reached. */
for (links = fileblock / (data->htsize); links; links--) for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
{ {
grub_disk_read (data->disk, block + data->blocksize - 1, grub_disk_read (data->disk, block + data->blocksize - 1,
data->blocksize * (GRUB_DISK_SECTOR_SIZE data->blocksize * (GRUB_DISK_SECTOR_SIZE
@ -133,7 +134,7 @@ grub_affs_read_block (grub_fshelp_node_t node, int fileblock)
} }
/* Translate the fileblock to the block within the right table. */ /* Translate the fileblock to the block within the right table. */
fileblock = fileblock % (data->htsize); fileblock = mod;
grub_disk_read (data->disk, block, grub_disk_read (data->disk, block,
GRUB_AFFS_BLOCKPTR_OFFSET GRUB_AFFS_BLOCKPTR_OFFSET
+ (data->htsize - fileblock - 1) * sizeof (pos), + (data->htsize - fileblock - 1) * sizeof (pos),
@ -567,4 +568,3 @@ GRUB_MOD_FINI(affs)
{ {
grub_fs_unregister (&grub_affs_fs); grub_fs_unregister (&grub_affs_fs);
} }

View file

@ -199,12 +199,12 @@ grub_afs_read_inode (struct grub_afs_data *data,
} }
static int static int
grub_afs_read_block (grub_fshelp_node_t node, int fileblock) grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_afs_sblock *sb = &node->data->sblock; struct grub_afs_sblock *sb = &node->data->sblock;
struct grub_afs_datastream *ds = &node->inode.stream; struct grub_afs_datastream *ds = &node->inode.stream;
if ((grub_uint32_t) fileblock < U64 (sb, ds->max_direct_range)) if (fileblock < U64 (sb, ds->max_direct_range))
{ {
int i; int i;
@ -215,7 +215,7 @@ grub_afs_read_block (grub_fshelp_node_t node, int fileblock)
fileblock -= U16 (sb, ds->direct[i].len); fileblock -= U16 (sb, ds->direct[i].len);
} }
} }
else if ((grub_uint32_t) fileblock < U64 (sb, ds->max_indirect_range)) else if (fileblock < U64 (sb, ds->max_indirect_range))
{ {
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun); int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk]; struct grub_afs_blockrun indir[ptrs_per_blk];

261
fs/ext2.c
View file

@ -71,6 +71,21 @@
? EXT2_GOOD_OLD_INODE_SIZE \ ? EXT2_GOOD_OLD_INODE_SIZE \
: grub_le_to_cpu16 (data->sblock.inode_size)) : grub_le_to_cpu16 (data->sblock.inode_size))
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
#define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
#define EXT3_JOURNAL_DESCRIPTOR_BLOCK 1
#define EXT3_JOURNAL_COMMIT_BLOCK 2
#define EXT3_JOURNAL_SUPERBLOCK_V1 3
#define EXT3_JOURNAL_SUPERBLOCK_V2 4
#define EXT3_JOURNAL_REVOKE_BLOCK 5
#define EXT3_JOURNAL_FLAG_ESCAPE 1
#define EXT3_JOURNAL_FLAG_SAME_UUID 2
#define EXT3_JOURNAL_FLAG_DELETED 4
#define EXT3_JOURNAL_FLAG_LAST_TAG 8
/* The ext2 superblock. */ /* The ext2 superblock. */
struct grub_ext2_sblock struct grub_ext2_sblock
{ {
@ -109,6 +124,21 @@ struct grub_ext2_sblock
char volume_name[16]; char volume_name[16];
char last_mounted_on[64]; char last_mounted_on[64];
grub_uint32_t compression_info; grub_uint32_t compression_info;
grub_uint8_t prealloc_blocks;
grub_uint8_t prealloc_dir_blocks;
grub_uint16_t reserved_gdt_blocks;
grub_uint8_t journal_uuid[16];
grub_uint32_t journal_inum;
grub_uint32_t journal_dev;
grub_uint32_t last_orphan;
grub_uint32_t hash_seed[4];
grub_uint8_t def_hash_version;
grub_uint8_t jnl_backup_type;
grub_uint16_t reserved_word_pad;
grub_uint32_t default_mount_opts;
grub_uint32_t first_meta_bg;
grub_uint32_t mkfs_time;
grub_uint32_t jnl_blocks[17];
}; };
/* The ext2 blockgroup. */ /* The ext2 blockgroup. */
@ -166,6 +196,36 @@ struct ext2_dirent
grub_uint8_t filetype; grub_uint8_t filetype;
}; };
struct grub_ext3_journal_header
{
grub_uint32_t magic;
grub_uint32_t block_type;
grub_uint32_t sequence;
};
struct grub_ext3_journal_revoke_header
{
struct grub_ext3_journal_header header;
grub_uint32_t count;
grub_uint32_t data[0];
};
struct grub_ext3_journal_block_tag
{
grub_uint32_t block;
grub_uint32_t flags;
};
struct grub_ext3_journal_sblock
{
struct grub_ext3_journal_header header;
grub_uint32_t block_size;
grub_uint32_t maxlen;
grub_uint32_t first;
grub_uint32_t sequence;
grub_uint32_t start;
};
struct grub_fshelp_node struct grub_fshelp_node
{ {
struct grub_ext2_data *data; struct grub_ext2_data *data;
@ -181,6 +241,8 @@ struct grub_ext2_data
grub_disk_t disk; grub_disk_t disk;
struct grub_ext2_inode *inode; struct grub_ext2_inode *inode;
struct grub_fshelp_node diropen; struct grub_fshelp_node diropen;
struct grub_fshelp_node logfile;
grub_fshelp_journal_t journal;
}; };
#ifndef GRUB_UTIL #ifndef GRUB_UTIL
@ -196,20 +258,21 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
struct grub_ext2_block_group *blkgrp) struct grub_ext2_block_group *blkgrp)
{ {
return grub_disk_read (data->disk, return grub_disk_read (data->disk,
((grub_le_to_cpu32 (data->sblock.first_data_block) + 1) (grub_fshelp_map_block (data->journal,
grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
<< LOG2_EXT2_BLOCK_SIZE (data)), << LOG2_EXT2_BLOCK_SIZE (data)),
group * sizeof (struct grub_ext2_block_group), group * sizeof (struct grub_ext2_block_group),
sizeof (struct grub_ext2_block_group), (char *) blkgrp); sizeof (struct grub_ext2_block_group), (char *) blkgrp);
} }
static int static grub_disk_addr_t
grub_ext2_read_block (grub_fshelp_node_t node, int fileblock) grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_ext2_data *data = node->data; struct grub_ext2_data *data = node->data;
struct grub_ext2_inode *inode = &node->inode; struct grub_ext2_inode *inode = &node->inode;
int blknr; int blknr;
int blksz = EXT2_BLOCK_SIZE (data); unsigned int blksz = EXT2_BLOCK_SIZE (data);
int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data); int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
/* Direct blocks. */ /* Direct blocks. */
@ -221,7 +284,8 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock)
grub_uint32_t indir[blksz / 4]; grub_uint32_t indir[blksz / 4];
if (grub_disk_read (data->disk, if (grub_disk_read (data->disk,
grub_le_to_cpu32 (inode->blocks.indir_block) grub_fshelp_map_block(data->journal,
grub_le_to_cpu32 (inode->blocks.indir_block))
<< log2_blksz, << log2_blksz,
0, blksz, (char *) indir)) 0, blksz, (char *) indir))
return grub_errno; return grub_errno;
@ -237,13 +301,15 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock)
grub_uint32_t indir[blksz / 4]; grub_uint32_t indir[blksz / 4];
if (grub_disk_read (data->disk, if (grub_disk_read (data->disk,
grub_le_to_cpu32 (inode->blocks.double_indir_block) grub_fshelp_map_block(data->journal,
grub_le_to_cpu32 (inode->blocks.double_indir_block))
<< log2_blksz, << log2_blksz,
0, blksz, (char *) indir)) 0, blksz, (char *) indir))
return grub_errno; return grub_errno;
if (grub_disk_read (data->disk, if (grub_disk_read (data->disk,
grub_le_to_cpu32 (indir[rblock / perblock]) grub_fshelp_map_block(data->journal,
grub_le_to_cpu32 (indir[rblock / perblock]))
<< log2_blksz, << log2_blksz,
0, blksz, (char *) indir)) 0, blksz, (char *) indir))
return grub_errno; return grub_errno;
@ -259,10 +325,9 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock)
blknr = -1; blknr = -1;
} }
return blknr; return grub_fshelp_map_block (data->journal, blknr);
} }
/* Read LEN bytes from the file described by DATA starting with byte /* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */ POS. Return the amount of read bytes in READ. */
static grub_ssize_t static grub_ssize_t
@ -308,8 +373,9 @@ grub_ext2_read_inode (struct grub_ext2_data *data,
/* Read the inode. */ /* Read the inode. */
if (grub_disk_read (data->disk, if (grub_disk_read (data->disk,
((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) grub_fshelp_map_block(data->journal,
<< LOG2_EXT2_BLOCK_SIZE (data)), grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
<< LOG2_EXT2_BLOCK_SIZE (data),
EXT2_INODE_SIZE (data) * blkoff, EXT2_INODE_SIZE (data) * blkoff,
sizeof (struct grub_ext2_inode), (char *) inode)) sizeof (struct grub_ext2_inode), (char *) inode))
return grub_errno; return grub_errno;
@ -317,6 +383,169 @@ grub_ext2_read_inode (struct grub_ext2_data *data,
return 0; return 0;
} }
static void
grub_ext3_get_journal (struct grub_ext2_data *data)
{
char buf[1 << LOG2_BLOCK_SIZE (data)];
struct grub_ext3_journal_sblock *jsb;
grub_fshelp_journal_t log;
int last_num, num, block, log2bs;
grub_uint32_t seq;
auto void next_block (void);
void next_block (void)
{
block++;
if (block >= log->last_block)
block = log->first_block;
}
data->journal = 0;
if (! (data->sblock.feature_compatibility & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
return;
if (! data->sblock.journal_inum)
return;
data->logfile.data = data;
data->logfile.ino = data->sblock.journal_inum;
data->logfile.inode_read = 1;
if (grub_ext2_read_inode (data, data->logfile.ino, &data->logfile.inode))
return;
log2bs = LOG2_EXT2_BLOCK_SIZE (data);
if (grub_fshelp_read_file (data->disk, &data->logfile, 0,
0, sizeof (struct grub_ext3_journal_sblock),
buf, grub_ext2_read_block,
sizeof (buf), log2bs) !=
sizeof (struct grub_ext3_journal_sblock))
return;
jsb = (struct grub_ext3_journal_sblock *) &buf[0];
if (grub_be_to_cpu32 (jsb->header.magic) != EXT3_JOURNAL_MAGIC_NUMBER)
return;
/* Empty journal. */
if (! jsb->start)
return;
log = grub_malloc (sizeof (struct grub_fshelp_journal) +
grub_be_to_cpu32 (jsb->maxlen) * sizeof (grub_disk_addr_t));
if (! log)
return;
log->type = GRUB_FSHELP_JOURNAL_TYPE_FILE;
log->node = &data->logfile;
log->get_block = grub_ext2_read_block;
log->first_block = grub_be_to_cpu32 (jsb->first);
log->last_block = grub_be_to_cpu32 (jsb->maxlen);
log->start_block = grub_be_to_cpu32 (jsb->start);
last_num = num = 0;
block = log->start_block;
seq = grub_be_to_cpu32 (jsb->sequence);
while (1)
{
struct grub_ext3_journal_header *jh;
if (grub_fshelp_read_file (data->disk, &data->logfile, 0,
block << (log2bs + 9), sizeof (buf),
buf, grub_ext2_read_block,
log->last_block << (log2bs + 9),
log2bs) !=
(int) sizeof (buf))
break;
jh = (struct grub_ext3_journal_header *) &buf[0];
if (grub_be_to_cpu32 (jh->magic) != EXT3_JOURNAL_MAGIC_NUMBER)
break;
if (grub_be_to_cpu32 (jh->sequence) != seq)
break;
log->mapping[num++] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING;
next_block();
switch (grub_be_to_cpu32 (jh->block_type))
{
case EXT3_JOURNAL_DESCRIPTOR_BLOCK:
{
struct grub_ext3_journal_block_tag *tag;
int ofs, flags;
ofs = sizeof (struct grub_ext3_journal_header);
do
{
tag = (struct grub_ext3_journal_block_tag *) &buf[ofs];
ofs += sizeof (struct grub_ext3_journal_block_tag);
if (ofs > (int) sizeof (buf))
break;
flags = grub_be_to_cpu32 (tag->flags);
if (! (flags & EXT3_JOURNAL_FLAG_SAME_UUID))
ofs += 16;
log->mapping[num++] = grub_be_to_cpu32 (tag->block);
next_block();
}
while (! (flags & EXT3_JOURNAL_FLAG_LAST_TAG));
continue;
}
case EXT3_JOURNAL_COMMIT_BLOCK:
{
seq++;
last_num = num - 1;
continue;
}
case EXT3_JOURNAL_REVOKE_BLOCK:
{
struct grub_ext3_journal_revoke_header *jrh;
grub_uint32_t i;
jrh = (struct grub_ext3_journal_revoke_header *) jh;
for (i = 0; i < grub_be_to_cpu32 (jrh->count); i++)
{
int j;
grub_uint32_t map;
map = grub_be_to_cpu32 (jrh->data[i]);
for (j = 0; j < num; j++)
if (log->mapping[j] == map)
log->mapping[j] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING;
}
continue;
}
default:
last_num = 0;
goto quit;
}
}
quit:
if (! last_num)
grub_free (log);
else
{
int size;
size = sizeof (struct grub_fshelp_journal) +
last_num * sizeof (grub_disk_addr_t);
log->num_mappings = last_num;
data->journal = grub_realloc (log, size);
}
}
static struct grub_ext2_data * static struct grub_ext2_data *
grub_ext2_mount (grub_disk_t disk) grub_ext2_mount (grub_disk_t disk)
{ {
@ -336,12 +565,14 @@ grub_ext2_mount (grub_disk_t disk)
if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC) if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC)
goto fail; goto fail;
data->disk = disk;
grub_ext3_get_journal (data);
data->diropen.data = data; data->diropen.data = data;
data->diropen.ino = 2; data->diropen.ino = 2;
data->diropen.inode_read = 1; data->diropen.inode_read = 1;
data->inode = &data->diropen.inode; data->inode = &data->diropen.inode;
data->disk = disk;
grub_ext2_read_inode (data, 2, data->inode); grub_ext2_read_inode (data, 2, data->inode);
if (grub_errno) if (grub_errno)
@ -540,7 +771,11 @@ grub_ext2_open (struct grub_file *file, const char *name)
static grub_err_t static grub_err_t
grub_ext2_close (grub_file_t file) grub_ext2_close (grub_file_t file)
{ {
grub_free (file->data); if (file->data)
{
grub_free (((struct grub_ext2_data *) file->data)->journal);
grub_free (file->data);
}
#ifndef GRUB_UTIL #ifndef GRUB_UTIL
grub_dl_unref (my_mod); grub_dl_unref (my_mod);

View file

@ -72,7 +72,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
void free_node (grub_fshelp_node_t node) void free_node (grub_fshelp_node_t node)
{ {
if (node != rootnode && node != currroot) if (node != rootnode && node != currroot)
grub_free (node); grub_free (node);
} }
@ -223,25 +223,26 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
grub_ssize_t grub_ssize_t
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset,
int pos, grub_size_t len, char *buf, unsigned length),
int (*get_block) (grub_fshelp_node_t node, int block), grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
grub_off_t filesize, int log2blocksize) grub_off_t filesize, int log2blocksize)
{ {
int i; grub_disk_addr_t i, blockcnt;
int blockcnt;
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS); int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
/* Adjust LEN so it we can't read past the end of the file. */ /* Adjust LEN so it we can't read past the end of the file. */
if (len > filesize) if (pos + len > filesize)
len = filesize; len = filesize - pos;
blockcnt = ((len + pos) + blocksize - 1) / blocksize; blockcnt = ((len + pos) + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
for (i = pos / blocksize; i < blockcnt; i++) for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
{ {
int blknr; grub_disk_addr_t blknr;
int blockoff = pos % blocksize; int blockoff = pos & (blocksize - 1);
int blockend = blocksize; int blockend = blocksize;
int skipfirst = 0; int skipfirst = 0;
@ -255,7 +256,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
/* Last block. */ /* Last block. */
if (i == blockcnt - 1) if (i == blockcnt - 1)
{ {
blockend = (len + pos) % blocksize; blockend = (len + pos) & (blocksize - 1);
/* The last portion is exactly blocksize. */ /* The last portion is exactly blocksize. */
if (! blockend) if (! blockend)
@ -263,7 +264,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
} }
/* First block. */ /* First block. */
if (i == pos / blocksize) if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
{ {
skipfirst = blockoff; skipfirst = blockoff;
blockend -= skipfirst; blockend -= skipfirst;
@ -310,3 +311,30 @@ grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
grub_disk_addr_t
grub_fshelp_map_block (grub_fshelp_journal_t log, grub_disk_addr_t block)
{
int map_block;
if (! log)
return block;
for (map_block = log->num_mappings - 1; map_block >= 0; map_block--)
{
if (log->mapping[map_block] == block)
break;
}
if (map_block < 0)
return block;
map_block += log->start_block;
if (map_block >= log->last_block)
map_block -= log->last_block - log->first_block;
if (log->type == GRUB_FSHELP_JOURNAL_TYPE_BLOCK)
return log->blkno + map_block;
else
return log->get_block (log->node, map_block);
}

View file

@ -285,8 +285,8 @@ static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
/* Search for the block FILEBLOCK inside the file NODE. Return the /* Search for the block FILEBLOCK inside the file NODE. Return the
blocknumber of this block on disk. */ blocknumber of this block on disk. */
static int static grub_disk_addr_t
grub_hfsplus_read_block (grub_fshelp_node_t node, int fileblock) grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_hfsplus_btnode *nnode = 0; struct grub_hfsplus_btnode *nnode = 0;
int blksleft = fileblock; int blksleft = fileblock;

View file

@ -331,8 +331,8 @@ retry:
return 0; return 0;
} }
static int static grub_disk_addr_t
grub_ntfs_read_block (grub_fshelp_node_t node, int block) grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
{ {
struct grub_ntfs_rlst *ctx; struct grub_ntfs_rlst *ctx;

View file

@ -52,7 +52,8 @@
#define REISERFS_SUPER_BLOCK_OFFSET 0x10000 #define REISERFS_SUPER_BLOCK_OFFSET 0x10000
#define REISERFS_MAGIC_LEN 12 #define REISERFS_MAGIC_LEN 12
#define REISERFS_MAGIC_STRING "ReIsEr2Fs\0\0\0" #define REISERFS_MAGIC_STRING "ReIsEr"
#define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB"
/* If the 3rd bit of an item state is set, then it's visible. */ /* If the 3rd bit of an item state is set, then it's visible. */
#define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04) #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
#define REISERFS_MAX_LABEL_LENGTH 16 #define REISERFS_MAX_LABEL_LENGTH 16
@ -109,8 +110,6 @@ struct grub_reiserfs_superblock
grub_uint32_t inode_generation; grub_uint32_t inode_generation;
} __attribute__ ((packed)); } __attribute__ ((packed));
#ifdef GRUB_REISERFS_JOURNALING
# error "Journaling not yet supported."
struct grub_reiserfs_journal_header struct grub_reiserfs_journal_header
{ {
grub_uint32_t last_flush_uid; grub_uint32_t last_flush_uid;
@ -118,15 +117,20 @@ struct grub_reiserfs_journal_header
grub_uint32_t mount_id; grub_uint32_t mount_id;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_reiserfs_transaction_header struct grub_reiserfs_description_block
{ {
grub_uint32_t id; grub_uint32_t id;
grub_uint32_t len; grub_uint32_t len;
grub_uint32_t mount_id; grub_uint32_t mount_id;
char *data; grub_uint32_t real_blocks[0];
char checksum[12]; } __attribute__ ((packed));
struct grub_reiserfs_commit_block
{
grub_uint32_t id;
grub_uint32_t len;
grub_uint32_t real_blocks[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
#endif
struct grub_reiserfs_stat_item_v1 struct grub_reiserfs_stat_item_v1
{ {
@ -228,6 +232,7 @@ struct grub_reiserfs_data
{ {
struct grub_reiserfs_superblock superblock; struct grub_reiserfs_superblock superblock;
grub_disk_t disk; grub_disk_t disk;
grub_fshelp_journal_t journal;
}; };
/* Internal-only functions. Not to be used outside of this file. */ /* Internal-only functions. Not to be used outside of this file. */
@ -504,8 +509,8 @@ grub_reiserfs_get_item (struct grub_reiserfs_data *data,
do do
{ {
grub_disk_read (data->disk, grub_disk_read (data->disk,
(((grub_disk_addr_t) block_number * block_size) grub_fshelp_map_block (data->journal, block_number) *
>> GRUB_DISK_SECTOR_BITS), (block_size >> GRUB_DISK_SECTOR_BITS),
(((grub_off_t) block_number * block_size) (((grub_off_t) block_number * block_size)
& (GRUB_DISK_SECTOR_SIZE - 1)), & (GRUB_DISK_SECTOR_SIZE - 1)),
block_size, (char *) block_header); block_size, (char *) block_header);
@ -655,8 +660,8 @@ grub_reiserfs_read_symlink (grub_fshelp_node_t node)
block_size = grub_le_to_cpu16 (node->data->superblock.block_size); block_size = grub_le_to_cpu16 (node->data->superblock.block_size);
len = grub_le_to_cpu16 (found.header.item_size); len = grub_le_to_cpu16 (found.header.item_size);
block = (((grub_disk_addr_t) found.block_number * block_size) block = (grub_fshelp_map_block (node->data->journal, found.block_number) *
>> GRUB_DISK_SECTOR_BITS); (block_size >> GRUB_DISK_SECTOR_BITS));
offset = grub_le_to_cpu16 (found.header.item_location); offset = grub_le_to_cpu16 (found.header.item_location);
symlink_buffer = grub_malloc (len + 1); symlink_buffer = grub_malloc (len + 1);
@ -675,6 +680,124 @@ grub_reiserfs_read_symlink (grub_fshelp_node_t node)
return 0; return 0;
} }
static void
grub_reiserfs_get_journal (struct grub_reiserfs_data *data)
{
int block_size = grub_le_to_cpu16 (data->superblock.block_size);
char buf[block_size];
struct grub_reiserfs_journal_header *jh;
grub_fshelp_journal_t log;
grub_uint32_t seq_id, mount_id;
int num_blocks = grub_le_to_cpu32 (data->superblock.journal_original_size);
int base_block = grub_le_to_cpu32 (data->superblock.journal_block);
int last_num, num, block;
data->journal = 0;
if (! data->superblock.journal_block)
return;
if (grub_disk_read (data->disk,
(base_block + num_blocks)
* (block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (struct grub_reiserfs_journal_header),
buf))
return;
log = grub_malloc (sizeof (struct grub_fshelp_journal) +
num_blocks * sizeof (grub_disk_addr_t));
if (! log)
return;
jh = (struct grub_reiserfs_journal_header *) &buf[0];
log->type = GRUB_FSHELP_JOURNAL_TYPE_BLOCK;
log->blkno = base_block;
log->first_block = 0;
log->last_block = num_blocks;
log->start_block = grub_le_to_cpu32 (jh->unflushed_offset);
seq_id = grub_le_to_cpu32 (jh->last_flush_uid);
mount_id = grub_le_to_cpu32 (jh->mount_id);
last_num = num = 0;
block = log->start_block;
while (1)
{
struct grub_reiserfs_description_block *db;
struct grub_reiserfs_commit_block *cb;
grub_uint32_t i, len, half_len, id, mid;
if (grub_disk_read (data->disk,
(base_block + block)
* (block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (buf), buf))
break;
if (grub_memcmp (&buf[block_size - REISERFS_MAGIC_LEN],
REISERFS_MAGIC_DESC_BLOCK,
sizeof (REISERFS_MAGIC_DESC_BLOCK) - 1))
break;
db = (struct grub_reiserfs_description_block *) &buf[0];
id = grub_le_to_cpu32 (db->id);
len = grub_le_to_cpu32 (db->len);
mid = grub_le_to_cpu32 (db->mount_id);
if ((id <= seq_id) && (mid <= mount_id))
break;
log->mapping[num++] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING;
half_len = ((block_size - 24) >> 2);
if (half_len > len)
half_len = len;
for (i = 0; i < half_len; i++)
log->mapping[num++] = db->real_blocks[i];
block += grub_le_to_cpu32 (db->len) + 1;
if (block >= log->last_block)
block -= log->last_block;
if (grub_disk_read (data->disk,
(base_block + block)
* (block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (buf), buf))
break;
cb = (struct grub_reiserfs_commit_block *) &buf[0];
if ((grub_le_to_cpu32 (cb->id) != id) ||
(grub_le_to_cpu32 (cb->len) != len))
break;
for (i = 0; i < len - half_len; i++)
log->mapping[num++] = cb->real_blocks[i];
last_num = num;
log->mapping[num++] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING;
block++;
if (block >= log->last_block)
block -= log->last_block;
seq_id = id;
mount_id = mid;
};
if (! last_num)
grub_free (log);
else
{
int size;
size = sizeof (struct grub_fshelp_journal) +
last_num * sizeof (grub_disk_addr_t);
log->num_mappings = last_num;
data->journal = grub_realloc (log, size);
}
}
/* Fill the mounted filesystem structure and return it. */ /* Fill the mounted filesystem structure and return it. */
static struct grub_reiserfs_data * static struct grub_reiserfs_data *
grub_reiserfs_mount (grub_disk_t disk) grub_reiserfs_mount (grub_disk_t disk)
@ -688,12 +811,13 @@ grub_reiserfs_mount (grub_disk_t disk)
if (grub_errno) if (grub_errno)
goto fail; goto fail;
if (grub_memcmp (data->superblock.magic_string, if (grub_memcmp (data->superblock.magic_string,
REISERFS_MAGIC_STRING, REISERFS_MAGIC_LEN)) REISERFS_MAGIC_STRING, sizeof (REISERFS_MAGIC_STRING) - 1))
{ {
grub_error (GRUB_ERR_BAD_FS, "not a reiserfs filesystem"); grub_error (GRUB_ERR_BAD_FS, "not a reiserfs filesystem");
goto fail; goto fail;
} }
data->disk = disk; data->disk = disk;
grub_reiserfs_get_journal (data);
return data; return data;
fail: fail:
@ -741,8 +865,8 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
struct grub_reiserfs_item_header *item_headers; struct grub_reiserfs_item_header *item_headers;
grub_disk_read (data->disk, grub_disk_read (data->disk,
(((grub_disk_addr_t) block_number * block_size) grub_fshelp_map_block (data->journal, block_number) *
>> GRUB_DISK_SECTOR_BITS), (block_size >> GRUB_DISK_SECTOR_BITS),
(((grub_off_t) block_number * block_size) (((grub_off_t) block_number * block_size)
& (GRUB_DISK_SECTOR_SIZE - 1)), & (GRUB_DISK_SECTOR_SIZE - 1)),
block_size, (char *) block_header); block_size, (char *) block_header);
@ -836,7 +960,8 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
{ {
struct grub_reiserfs_stat_item_v1 entry_v1_stat; struct grub_reiserfs_stat_item_v1 entry_v1_stat;
grub_disk_read (data->disk, grub_disk_read (data->disk,
((grub_disk_addr_t) entry_block_number * block_size) >> GRUB_DISK_SECTOR_BITS, grub_fshelp_map_block (data->journal, entry_block_number) *
(block_size >> GRUB_DISK_SECTOR_BITS),
grub_le_to_cpu16 (entry_item->header.item_location), grub_le_to_cpu16 (entry_item->header.item_location),
sizeof (entry_v1_stat), sizeof (entry_v1_stat),
(char *) &entry_v1_stat); (char *) &entry_v1_stat);
@ -878,7 +1003,8 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
{ {
struct grub_reiserfs_stat_item_v2 entry_v2_stat; struct grub_reiserfs_stat_item_v2 entry_v2_stat;
grub_disk_read (data->disk, grub_disk_read (data->disk,
((grub_disk_addr_t) entry_block_number * block_size) >> GRUB_DISK_SECTOR_BITS, grub_fshelp_map_block (data->journal, entry_block_number) *
(block_size >> GRUB_DISK_SECTOR_BITS),
grub_le_to_cpu16 (entry_item->header.item_location), grub_le_to_cpu16 (entry_item->header.item_location),
sizeof (entry_v2_stat), sizeof (entry_v2_stat),
(char *) &entry_v2_stat); (char *) &entry_v2_stat);
@ -1026,8 +1152,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name)
{ {
struct grub_reiserfs_stat_item_v1 entry_v1_stat; struct grub_reiserfs_stat_item_v1 entry_v1_stat;
grub_disk_read (data->disk, grub_disk_read (data->disk,
(((grub_disk_addr_t) block_number * block_size) grub_fshelp_map_block (data->journal, block_number) *
>> GRUB_DISK_SECTOR_BITS), (block_size >> GRUB_DISK_SECTOR_BITS),
entry_location entry_location
+ (((grub_off_t) block_number * block_size) + (((grub_off_t) block_number * block_size)
& (GRUB_DISK_SECTOR_SIZE - 1)), & (GRUB_DISK_SECTOR_SIZE - 1)),
@ -1040,8 +1166,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name)
{ {
struct grub_reiserfs_stat_item_v2 entry_v2_stat; struct grub_reiserfs_stat_item_v2 entry_v2_stat;
grub_disk_read (data->disk, grub_disk_read (data->disk,
(((grub_disk_addr_t) block_number * block_size) grub_fshelp_map_block (data->journal, block_number) *
>> GRUB_DISK_SECTOR_BITS), (block_size >> GRUB_DISK_SECTOR_BITS),
entry_location entry_location
+ (((grub_off_t) block_number * block_size) + (((grub_off_t) block_number * block_size)
& (GRUB_DISK_SECTOR_SIZE - 1)), & (GRUB_DISK_SECTOR_SIZE - 1)),
@ -1109,8 +1235,8 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
switch (found.type) switch (found.type)
{ {
case GRUB_REISERFS_DIRECT: case GRUB_REISERFS_DIRECT:
block = (((grub_disk_addr_t) found.block_number * block_size) block = (grub_fshelp_map_block (data->journal, found.block_number) *
>> GRUB_DISK_SECTOR_BITS); (block_size >> GRUB_DISK_SECTOR_BITS));
grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
if (initial_position < current_position + item_size) if (initial_position < current_position + item_size)
{ {
@ -1142,8 +1268,8 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
if (! indirect_block_ptr) if (! indirect_block_ptr)
goto fail; goto fail;
grub_disk_read (found.data->disk, grub_disk_read (found.data->disk,
(((grub_disk_addr_t) found.block_number * block_size) grub_fshelp_map_block (data->journal, found.block_number) *
>> GRUB_DISK_SECTOR_BITS), (block_size >> GRUB_DISK_SECTOR_BITS),
grub_le_to_cpu16 (found.header.item_location), grub_le_to_cpu16 (found.header.item_location),
item_size, (char *) indirect_block_ptr); item_size, (char *) indirect_block_ptr);
if (grub_errno) if (grub_errno)
@ -1154,9 +1280,9 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
&& current_position < final_position; && current_position < final_position;
indirect_block++) indirect_block++)
{ {
block = ((grub_disk_addr_t) block = (grub_fshelp_map_block (data->journal,
grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) grub_le_to_cpu32 (indirect_block_ptr[indirect_block])) *
* block_size) >> GRUB_DISK_SECTOR_BITS; (block_size >> GRUB_DISK_SECTOR_BITS));
grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block); grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block);
if (current_position + block_size >= initial_position) if (current_position + block_size >= initial_position)
{ {
@ -1255,6 +1381,7 @@ grub_reiserfs_close (grub_file_t file)
struct grub_fshelp_node *node = file->data; struct grub_fshelp_node *node = file->data;
struct grub_reiserfs_data *data = node->data; struct grub_reiserfs_data *data = node->data;
grub_free (data->journal);
grub_free (data); grub_free (data);
grub_free (node); grub_free (node);
#ifndef GRUB_UTIL #ifndef GRUB_UTIL

View file

@ -219,8 +219,8 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
return grub_error (GRUB_ERR_FILE_READ_ERROR, "SFS extent not found"); return grub_error (GRUB_ERR_FILE_READ_ERROR, "SFS extent not found");
} }
static int static grub_disk_addr_t
grub_sfs_read_block (grub_fshelp_node_t node, int fileblock) grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
int blk = node->block; int blk = node->block;
int size = 0; int size = 0;
@ -239,7 +239,7 @@ grub_sfs_read_block (grub_fshelp_node_t node, int fileblock)
if (err) if (err)
return 0; return 0;
if (fileblock < size) if (fileblock < (unsigned int) size)
return fileblock + blk; return fileblock + blk;
fileblock -= size; fileblock -= size;

View file

@ -404,8 +404,8 @@ grub_udf_read_icb (struct grub_udf_data *data,
return 0; return 0;
} }
static int static grub_disk_addr_t
grub_udf_read_block (grub_fshelp_node_t node, int fileblock) grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
char *ptr; char *ptr;
int len; int len;
@ -429,7 +429,7 @@ grub_udf_read_block (grub_fshelp_node_t node, int fileblock)
len /= sizeof (struct grub_udf_short_ad); len /= sizeof (struct grub_udf_short_ad);
while (len > 0) while (len > 0)
{ {
if (fileblock < (int) U32 (ad->length)) if (fileblock < U32 (ad->length))
return ((U32 (ad->position) & GRUB_UDF_EXT_MASK) ? 0 : return ((U32 (ad->position) & GRUB_UDF_EXT_MASK) ? 0 :
(grub_udf_get_block (node->data, (grub_udf_get_block (node->data,
node->part_ref, node->part_ref,
@ -448,7 +448,7 @@ grub_udf_read_block (grub_fshelp_node_t node, int fileblock)
len /= sizeof (struct grub_udf_long_ad); len /= sizeof (struct grub_udf_long_ad);
while (len > 0) while (len > 0)
{ {
if (fileblock < (int) U32 (ad->length)) if (fileblock < U32 (ad->length))
return ((U32 (ad->block.block_num) & GRUB_UDF_EXT_MASK) ? 0 : return ((U32 (ad->block.block_num) & GRUB_UDF_EXT_MASK) ? 0 :
(grub_udf_get_block (node->data, (grub_udf_get_block (node->data,
ad->block.part_ref, ad->block.part_ref,

View file

@ -220,8 +220,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
} }
static int static grub_disk_addr_t
grub_xfs_read_block (grub_fshelp_node_t node, int fileblock) grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_xfs_btree_node *leaf = 0; struct grub_xfs_btree_node *leaf = 0;
int ex, nrec; int ex, nrec;
@ -244,7 +244,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, int fileblock)
for (i = 0; i < nrec; i++) for (i = 0; i < nrec; i++)
{ {
if ((grub_uint64_t) fileblock < grub_be_to_cpu64 (keys[i])) if (fileblock < grub_be_to_cpu64 (keys[i]))
break; break;
} }
@ -292,8 +292,8 @@ grub_xfs_read_block (grub_fshelp_node_t node, int fileblock)
for (ex = 0; ex < nrec; ex++) for (ex = 0; ex < nrec; ex++)
{ {
grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (exts, ex); grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (exts, ex);
int offset = GRUB_XFS_EXTENT_OFFSET (exts, ex); grub_uint64_t offset = GRUB_XFS_EXTENT_OFFSET (exts, ex);
int size = GRUB_XFS_EXTENT_SIZE (exts, ex); grub_uint64_t size = GRUB_XFS_EXTENT_SIZE (exts, ex);
/* Sparse block. */ /* Sparse block. */
if (fileblock < offset) if (fileblock < offset)

View file

@ -34,6 +34,34 @@ enum grub_fshelp_filetype
GRUB_FSHELP_SYMLINK GRUB_FSHELP_SYMLINK
}; };
enum grub_fshelp_journal_type
{
GRUB_FSHELP_JOURNAL_TYPE_BLOCK,
GRUB_FSHELP_JOURNAL_TYPE_FILE
};
#define GRUB_FSHELP_JOURNAL_UNUSED_MAPPING (grub_disk_addr_t) -1
struct grub_fshelp_journal
{
int type;
union
{
struct
{
grub_fshelp_node_t node;
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node, grub_disk_addr_t block);
};
grub_disk_addr_t blkno;
};
int first_block;
int last_block;
int start_block;
int num_mappings;
grub_disk_addr_t mapping[0];
};
typedef struct grub_fshelp_journal *grub_fshelp_journal_t;
/* Lookup the node PATH. The node ROOTNODE describes the root of the /* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is directory tree. The node found is returned in FOUNDNODE, which is
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
@ -64,15 +92,18 @@ EXPORT_FUNC(grub_fshelp_find_file) (const char *path,
grub_ssize_t grub_ssize_t
EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node, EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned offset,
unsigned length), unsigned length),
int pos, grub_size_t len, char *buf, grub_off_t pos, grub_size_t len, char *buf,
int (*get_block) (grub_fshelp_node_t node, grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
int block), grub_disk_addr_t block),
grub_off_t filesize, int log2blocksize); grub_off_t filesize, int log2blocksize);
unsigned int unsigned int
EXPORT_FUNC(grub_fshelp_log2blksize) (unsigned int blksize, EXPORT_FUNC(grub_fshelp_log2blksize) (unsigned int blksize,
unsigned int *pow); unsigned int *pow);
grub_disk_addr_t
EXPORT_FUNC(grub_fshelp_map_block) (grub_fshelp_journal_t log, grub_disk_addr_t block);
#endif /* ! GRUB_FSHELP_HEADER */ #endif /* ! GRUB_FSHELP_HEADER */