diff --git a/fs/ext2.c b/fs/ext2.c index ec66582..5dffd69 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -71,6 +71,21 @@ ? EXT2_GOOD_OLD_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. */ struct grub_ext2_sblock { @@ -109,6 +124,21 @@ struct grub_ext2_sblock char volume_name[16]; char last_mounted_on[64]; 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. */ @@ -166,6 +196,36 @@ struct ext2_dirent 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_ext2_data *data; @@ -181,6 +241,8 @@ struct grub_ext2_data grub_disk_t disk; struct grub_ext2_inode *inode; struct grub_fshelp_node diropen; + struct grub_fshelp_node logfile; + grub_fshelp_journal_t journal; }; #ifndef GRUB_UTIL @@ -196,7 +258,8 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group, struct grub_ext2_block_group *blkgrp) { 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)), group * sizeof (struct grub_ext2_block_group), sizeof (struct grub_ext2_block_group), (char *) blkgrp); @@ -221,7 +284,8 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock) grub_uint32_t indir[blksz / 4]; 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, 0, blksz, (char *) indir)) return grub_errno; @@ -237,13 +301,15 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock) grub_uint32_t indir[blksz / 4]; 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, 0, blksz, (char *) indir)) return grub_errno; 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, 0, blksz, (char *) indir)) return grub_errno; @@ -259,10 +325,9 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock) blknr = -1; } - return blknr; + return grub_fshelp_map_block (data->journal, blknr); } - /* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t @@ -308,8 +373,9 @@ grub_ext2_read_inode (struct grub_ext2_data *data, /* Read the inode. */ if (grub_disk_read (data->disk, - ((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) - << LOG2_EXT2_BLOCK_SIZE (data)), + grub_fshelp_map_block(data->journal, + grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) + << LOG2_EXT2_BLOCK_SIZE (data), EXT2_INODE_SIZE (data) * blkoff, sizeof (struct grub_ext2_inode), (char *) inode)) return grub_errno; @@ -317,6 +383,164 @@ grub_ext2_read_inode (struct grub_ext2_data *data, 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_uint32_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 + { + log->num_mappings = last_num; + data->journal = log; + } +} + static struct grub_ext2_data * grub_ext2_mount (grub_disk_t disk) { @@ -336,12 +560,14 @@ grub_ext2_mount (grub_disk_t disk) if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC) goto fail; + data->disk = disk; + grub_ext3_get_journal (data); + data->diropen.data = data; data->diropen.ino = 2; data->diropen.inode_read = 1; data->inode = &data->diropen.inode; - data->disk = disk; grub_ext2_read_inode (data, 2, data->inode); if (grub_errno) @@ -540,7 +766,11 @@ grub_ext2_open (struct grub_file *file, const char *name) static grub_err_t 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 grub_dl_unref (my_mod); diff --git a/fs/fshelp.c b/fs/fshelp.c index bbb58ac..d3c2423 100644 --- a/fs/fshelp.c +++ b/fs/fshelp.c @@ -72,7 +72,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, void free_node (grub_fshelp_node_t node) { - if (node != rootnode && node != currroot) + if (node != rootnode && node != currroot) grub_free (node); } @@ -310,3 +310,30 @@ grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow) return GRUB_ERR_NONE; } + +int +grub_fshelp_map_block (grub_fshelp_journal_t log, int block) +{ + int map_block; + + if ((! log) || (log->type == GRUB_FSHELP_JOURNAL_TYPE_NONE)) + return block; + + for (map_block = log->num_mappings - 1; map_block >= 0; map_block--) + { + if ((int) 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); +} diff --git a/fs/reiserfs.c b/fs/reiserfs.c index a4c60ca..79e559a 100644 --- a/fs/reiserfs.c +++ b/fs/reiserfs.c @@ -52,7 +52,8 @@ #define REISERFS_SUPER_BLOCK_OFFSET 0x10000 #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. */ #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04) #define REISERFS_MAX_LABEL_LENGTH 16 @@ -109,8 +110,6 @@ struct grub_reiserfs_superblock grub_uint32_t inode_generation; } __attribute__ ((packed)); -#ifdef GRUB_REISERFS_JOURNALING -# error "Journaling not yet supported." struct grub_reiserfs_journal_header { grub_uint32_t last_flush_uid; @@ -118,15 +117,20 @@ struct grub_reiserfs_journal_header grub_uint32_t mount_id; } __attribute__ ((packed)); -struct grub_reiserfs_transaction_header +struct grub_reiserfs_description_block { grub_uint32_t id; grub_uint32_t len; grub_uint32_t mount_id; - char *data; - char checksum[12]; + grub_uint32_t real_blocks[0]; +} __attribute__ ((packed)); + +struct grub_reiserfs_commit_block +{ + grub_uint32_t id; + grub_uint32_t len; + grub_uint32_t real_blocks[0]; } __attribute__ ((packed)); -#endif struct grub_reiserfs_stat_item_v1 { @@ -228,6 +232,7 @@ struct grub_reiserfs_data { struct grub_reiserfs_superblock superblock; grub_disk_t disk; + grub_fshelp_journal_t journal; }; /* 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 { grub_disk_read (data->disk, - (((grub_disk_addr_t) block_number * block_size) - >> GRUB_DISK_SECTOR_BITS), + grub_fshelp_map_block (data->journal, block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS), (((grub_off_t) block_number * block_size) & (GRUB_DISK_SECTOR_SIZE - 1)), 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); len = grub_le_to_cpu16 (found.header.item_size); - block = (((grub_disk_addr_t) found.block_number * block_size) - >> GRUB_DISK_SECTOR_BITS); + block = (grub_fshelp_map_block (node->data->journal, found.block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS)); offset = grub_le_to_cpu16 (found.header.item_location); symlink_buffer = grub_malloc (len); @@ -674,6 +679,115 @@ grub_reiserfs_read_symlink (grub_fshelp_node_t node) 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_uint32_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; + + 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); + if ((grub_le_to_cpu32 (db->id) <= seq_id) && (id <= 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; + }; + + if (! last_num) + grub_free (log); + else + { + log->num_mappings = last_num; + data->journal = log; + } +} + /* Fill the mounted filesystem structure and return it. */ static struct grub_reiserfs_data * grub_reiserfs_mount (grub_disk_t disk) @@ -687,12 +801,13 @@ grub_reiserfs_mount (grub_disk_t disk) if (grub_errno) goto fail; 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"); goto fail; } data->disk = disk; + grub_reiserfs_get_journal (data); return data; fail: @@ -740,8 +855,8 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, struct grub_reiserfs_item_header *item_headers; grub_disk_read (data->disk, - (((grub_disk_addr_t) block_number * block_size) - >> GRUB_DISK_SECTOR_BITS), + grub_fshelp_map_block (data->journal, block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS), (((grub_off_t) block_number * block_size) & (GRUB_DISK_SECTOR_SIZE - 1)), block_size, (char *) block_header); @@ -835,7 +950,8 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, { struct grub_reiserfs_stat_item_v1 entry_v1_stat; 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), sizeof (entry_v1_stat), (char *) &entry_v1_stat); @@ -877,7 +993,8 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, { struct grub_reiserfs_stat_item_v2 entry_v2_stat; 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), sizeof (entry_v2_stat), (char *) &entry_v2_stat); @@ -1025,8 +1142,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name) { struct grub_reiserfs_stat_item_v1 entry_v1_stat; grub_disk_read (data->disk, - (((grub_disk_addr_t) block_number * block_size) - >> GRUB_DISK_SECTOR_BITS), + grub_fshelp_map_block (data->journal, block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS), entry_location + (((grub_off_t) block_number * block_size) & (GRUB_DISK_SECTOR_SIZE - 1)), @@ -1039,8 +1156,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name) { struct grub_reiserfs_stat_item_v2 entry_v2_stat; grub_disk_read (data->disk, - (((grub_disk_addr_t) block_number * block_size) - >> GRUB_DISK_SECTOR_BITS), + grub_fshelp_map_block (data->journal, block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS), entry_location + (((grub_off_t) block_number * block_size) & (GRUB_DISK_SECTOR_SIZE - 1)), @@ -1108,8 +1225,8 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) switch (found.type) { case GRUB_REISERFS_DIRECT: - block = (((grub_disk_addr_t) found.block_number * block_size) - >> GRUB_DISK_SECTOR_BITS); + block = (grub_fshelp_map_block (data->journal, found.block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS)); grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); if (initial_position < current_position + item_size) { @@ -1141,8 +1258,8 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) if (! indirect_block_ptr) goto fail; grub_disk_read (found.data->disk, - (((grub_disk_addr_t) found.block_number * block_size) - >> GRUB_DISK_SECTOR_BITS), + grub_fshelp_map_block (data->journal, found.block_number) * + (block_size >> GRUB_DISK_SECTOR_BITS), grub_le_to_cpu16 (found.header.item_location), item_size, (char *) indirect_block_ptr); if (grub_errno) @@ -1153,9 +1270,9 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) && current_position < final_position; indirect_block++) { - block = ((grub_disk_addr_t) - grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) - * block_size) >> GRUB_DISK_SECTOR_BITS; + block = (grub_fshelp_map_block (data->journal, + grub_le_to_cpu32 (indirect_block_ptr[indirect_block])) * + (block_size >> GRUB_DISK_SECTOR_BITS)); grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block); if (current_position + block_size >= initial_position) { @@ -1254,6 +1371,7 @@ grub_reiserfs_close (grub_file_t file) struct grub_fshelp_node *node = file->data; struct grub_reiserfs_data *data = node->data; + grub_free (data->journal); grub_free (data); grub_free (node); #ifndef GRUB_UTIL diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h index e25dd16..d575007 100644 --- a/include/grub/fshelp.h +++ b/include/grub/fshelp.h @@ -34,6 +34,35 @@ enum grub_fshelp_filetype GRUB_FSHELP_SYMLINK }; +enum grub_fshelp_journal_type + { + GRUB_FSHELP_JOURNAL_TYPE_NONE, + GRUB_FSHELP_JOURNAL_TYPE_BLOCK, + GRUB_FSHELP_JOURNAL_TYPE_FILE + }; + +#define GRUB_FSHELP_JOURNAL_UNUSED_MAPPING (grub_uint32_t) -1 + +struct grub_fshelp_journal +{ + int type; + union + { + struct + { + grub_fshelp_node_t node; + int (*get_block) (grub_fshelp_node_t node, int block); + }; + grub_uint32_t blkno; + }; + int first_block; + int last_block; + int start_block; + int num_mappings; + grub_uint32_t mapping[0]; +}; +typedef struct grub_fshelp_journal *grub_fshelp_journal_t; + /* Lookup the node PATH. The node ROOTNODE describes the root of the 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 @@ -75,4 +104,7 @@ unsigned int EXPORT_FUNC(grub_fshelp_log2blksize) (unsigned int blksize, unsigned int *pow); +int +EXPORT_FUNC(grub_fshelp_map_block) (grub_fshelp_journal_t log, int block); + #endif /* ! GRUB_FSHELP_HEADER */