Here is attached the latest working version of reiserfs handling.
What it does :
- Recognises the partition type
- Read the partition label (needs confirmation of the label position)
- List directory content (see limitations)
- Read file content (see limitations)
Limitations :
- Item (file & dir) size limited to one indirection block. Readable size is a
bit less than number_of_contiguous_indirect_pointers * block_size, which
means at most 16MB on a 8192 bytes/block reiserfs, 4MB on a 4096 bytes/block,
etc.
- No symlink support : although the symlinks can be read, they are read as a
text file containing a path, nothing more.
- No journal playback
- Alpha version : will potentially leak memory, be slow, not suitable for your
needs, not tested with all kinds of reiserfs options & versions... Play
with^W^WUse it at your own risks - risks which should be limited to wasting
time because no write is ever done to the partition, of course.
Ah, and it's not always 80-columns wordwrapped, other than that the coding
style should be respected. This will be fixed in the final version.
--
Vincent Pelletier
/* reiserfs.c - ReiserFS versions up to 3.6 */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
TODO:
implement journal handling (ram replay)
implement symlinks support
support items bigger than roughly (blocksize / 4) * blocksize
!! that goes for directories aswell, size in such case is metadata size.
test tail packing & direct files
validate partition label position
*/
#warning "TODO : symlinks, journal, support for items larger than (blocksize^2)/4, tail packing"
// #define GRUB_REISERFS_KEYV2_BITFIELD
// #define GRUB_REISERFS_DEBUG
// #define GRUB_REISERFS_JOURNALING
#include
#include
#include
#include
#include
#include
#include
#include
#define MIN(a, b) (((a)<(b))?(a):(b))
#define REISERFS_SUPER_BLOCK_OFFSET 0x1
#define REISERFS_MAGIC_LEN 12
#define REISERFS_MAGIC_STRING "ReIsEr2Fs\0\0\0"
/* 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
#define REISERFS_LABEL_OFFSET 0x64
enum grub_reiserfs_item_type
{
GRUB_REISERFS_STAT,
GRUB_REISERFS_DIRECTORY,
GRUB_REISERFS_DIRECT,
GRUB_REISERFS_INDIRECT,
GRUB_REISERFS_ANY, /* Matches both _DIRECT and _INDIRECT when searching. */
GRUB_REISERFS_UNKNOWN
};
struct grub_reiserfs_superblock
{
grub_uint32_t block_count;
grub_uint32_t block_free_count;
grub_uint32_t root_block;
grub_uint32_t journal_block;
grub_uint32_t journal_device;
grub_uint32_t journal_original_size;
grub_uint32_t journal_max_transaction_size;
grub_uint32_t journal_block_count;
grub_uint32_t journal_max_batch;
grub_uint32_t journal_max_commit_age;
grub_uint32_t journal_max_transaction_age;
grub_uint16_t block_size;
grub_uint16_t oid_max_size;
grub_uint16_t oid_current_size;
grub_uint16_t state;
grub_uint8_t magic_string[REISERFS_MAGIC_LEN];
grub_uint32_t function_hash_code;
grub_uint16_t tree_height;
grub_uint16_t bitmap_number;
grub_uint16_t version;
grub_uint16_t reserved;
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;
grub_uint32_t unflushed_offset;
grub_uint32_t mount_id;
} __attribute__ ((packed));
struct grub_reiserfs_transaction_header
{
grub_uint32_t id;
grub_uint32_t len;
grub_uint32_t mount_id;
char *data;
char checksum[12];
} __attribute__ ((packed));
#endif
struct grub_reiserfs_stat_item_v1
{
grub_uint16_t mode;
grub_uint16_t hardlink_count;
grub_uint16_t uid;
grub_uint16_t gid;
grub_uint32_t size;
grub_uint32_t atime;
grub_uint32_t mtime;
grub_uint32_t ctime;
grub_uint32_t rdev;
grub_uint32_t first_direct_byte;
} __attribute__ ((packed));
struct grub_reiserfs_stat_item_v2
{
grub_uint16_t mode;
grub_uint16_t reserved;
grub_uint32_t hardlink_count;
grub_uint64_t size;
grub_uint32_t uid;
grub_uint32_t gid;
grub_uint32_t atime;
grub_uint32_t mtime;
grub_uint32_t ctime;
grub_uint32_t blocks;
grub_uint32_t rdev;
grub_u