From 03d06845e602068d722e57a9a24b9bfed6cdd881 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Sun, 22 Dec 2002 22:47:17 +0000 Subject: [PATCH] disk_scanner fs module for BFS filesystems git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2285 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/disk_scanner/fs/bfs.c | 225 +++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 src/add-ons/kernel/disk_scanner/fs/bfs.c diff --git a/src/add-ons/kernel/disk_scanner/fs/bfs.c b/src/add-ons/kernel/disk_scanner/fs/bfs.c new file mode 100644 index 0000000000..dc1fe4986c --- /dev/null +++ b/src/add-ons/kernel/disk_scanner/fs/bfs.c @@ -0,0 +1,225 @@ +// bfs.c + +#include +#include +#include +#include + +#include +#include +#include + +#define BFS_FS_MODULE_NAME "disk_scanner/fs/bfs/v1" + +//#define TRACE(x) +#define TRACE(x) dprintf x + +// prototypes +static status_t read_block(int fd, off_t offset, size_t size, uchar **block); +static bool bfs_fs_identify(int deviceFD, struct extended_partition_info *partitionInfo); + +//---------------------------------------------------------------------- +// Stolen from src/add-ons/kernel/file_systems/bfs/bfs.h +//---------------------------------------------------------------------- + +typedef struct block_run +{ + int32 allocation_group; + uint16 start; + uint16 length; +} block_run; + +typedef block_run inode_addr; + +#define BFS_DISK_NAME_LENGTH 32 + +typedef struct disk_super_block +{ + char name[BFS_DISK_NAME_LENGTH]; + int32 magic1; + int32 fs_byte_order; + uint32 block_size; + uint32 block_shift; + off_t num_blocks; + off_t used_blocks; + int32 inode_size; + int32 magic2; + int32 blocks_per_ag; + int32 ag_shift; + int32 num_ags; + int32 flags; + block_run log_blocks; + off_t log_start; + off_t log_end; + int32 magic3; + inode_addr root_dir; + inode_addr indices; + int32 pad[8]; +} disk_super_block; + +#define SUPER_BLOCK_FS_LENDIAN 'BIGE' /* BIGE */ + +#define SUPER_BLOCK_MAGIC1 'BFS1' /* BFS1 */ +#define SUPER_BLOCK_MAGIC2 0xdd121031 +#define SUPER_BLOCK_MAGIC3 0x15b6830e + +#define SUPER_BLOCK_DISK_CLEAN 'CLEN' /* CLEN */ +#define SUPER_BLOCK_DISK_DIRTY 'DIRT' /* DIRT */ + +static +char * +get_tupel(uint32 id) +{ + static unsigned char tupel[5]; + int16 i; + + tupel[0] = 0xff & (id >> 24); + tupel[1] = 0xff & (id >> 16); + tupel[2] = 0xff & (id >> 8); + tupel[3] = 0xff & (id); + tupel[4] = 0; + for (i = 0;i < 4;i++) + if (tupel[i] < ' ' || tupel[i] > 128) + tupel[i] = '.'; + + return (char *)tupel; +} + +static +void +dump_super_block(disk_super_block *superBlock) +{ + dprintf("disk_super_block:\n"); + dprintf(" name = %s\n",superBlock->name); + dprintf(" magic1 = %#08lx (%s) %s\n",superBlock->magic1, get_tupel(superBlock->magic1), (superBlock->magic1 == SUPER_BLOCK_MAGIC1 ? "valid" : "INVALID")); + dprintf(" fs_byte_order = %#08lx (%s)\n",superBlock->fs_byte_order, get_tupel(superBlock->fs_byte_order)); + dprintf(" block_size = %lu\n",superBlock->block_size); + dprintf(" block_shift = %lu\n",superBlock->block_shift); + dprintf(" num_blocks = %Lu\n",superBlock->num_blocks); + dprintf(" used_blocks = %Lu\n",superBlock->used_blocks); + dprintf(" inode_size = %lu\n",superBlock->inode_size); + dprintf(" magic2 = %#08lx (%s) %s\n",superBlock->magic2, get_tupel(superBlock->magic2), (superBlock->magic2 == (int)SUPER_BLOCK_MAGIC2 ? "valid" : "INVALID")); + dprintf(" blocks_per_ag = %lu\n",superBlock->blocks_per_ag); + dprintf(" ag_shift = %lu (%lld bytes)\n",superBlock->ag_shift, 1LL << superBlock->ag_shift); + dprintf(" num_ags = %lu\n",superBlock->num_ags); + dprintf(" flags = %#08lx (%s)\n",superBlock->flags, get_tupel(superBlock->flags)); +// dump_block_run(" log_blocks = ",superBlock->log_blocks); + dprintf(" log_start = %Lu\n",superBlock->log_start); + dprintf(" log_end = %Lu\n",superBlock->log_end); + dprintf(" magic3 = %#08lx (%s) %s\n",superBlock->magic3, get_tupel(superBlock->magic3), (superBlock->magic3 == SUPER_BLOCK_MAGIC3 ? "valid" : "INVALID")); +// dump_block_run(" root_dir = ",superBlock->root_dir); +// dump_block_run(" indices = ",superBlock->indices); +} + +static +inline int64 +divide_roundup(int64 num,int32 divisor) +{ + return (num + divisor - 1) / divisor; +} +//---------------------------------------------------------------------- +// End stolen BFS code +//---------------------------------------------------------------------- + +// std_ops +static +status_t +std_ops(int32 op, ...) +{ + TRACE(("fs/bfs: std_ops(0x%lx)\n", op)); + switch(op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + } + return B_ERROR; +} + +// read_block +static +status_t +read_block(int fd, off_t offset, size_t size, uchar **block) +{ + status_t error = (block && size > 0 ? B_OK : B_BAD_VALUE); + if (error == B_OK) { + *block = malloc(size); + if (*block) { + if (read_pos(fd, offset, *block, size) != (ssize_t)size) { + error = errno; + if (error == B_OK) + error = B_ERROR; + free(*block); + *block = NULL; + } + } else + error = B_NO_MEMORY; + } + return error; +} + +// bfs_fs_identify +/*! \brief Returns true if the given partition is a valid BFS partition. + + See fs_identify_hook() for more information. +*/ +static +bool +bfs_fs_identify(int deviceFD, struct extended_partition_info *partitionInfo) +{ + bool result = false; + TRACE(("fs/bfs: identify(%d, %p, offset: %lld)\n", deviceFD, partitionInfo, + partitionInfo ? partitionInfo->info.offset : -1)); + + if (partitionInfo) { + uchar *buffer = NULL; + disk_super_block *superBlock = NULL; + status_t error = read_block(deviceFD, partitionInfo->info.offset, + 1024, &buffer); + if (!error && buffer) { + superBlock = (disk_super_block*)(buffer+512); +// dump_super_block(superBlock); + + if (superBlock->magic1 != (int32)SUPER_BLOCK_MAGIC1 + || superBlock->magic2 != (int32)SUPER_BLOCK_MAGIC2 + || superBlock->magic3 != (int32)SUPER_BLOCK_MAGIC3 + || (int32)superBlock->block_size != superBlock->inode_size + || superBlock->fs_byte_order != SUPER_BLOCK_FS_LENDIAN + || (1UL << superBlock->block_shift) != superBlock->block_size + || superBlock->num_ags < 1 + || superBlock->ag_shift < 1 + || superBlock->blocks_per_ag < 1 + || superBlock->num_blocks < 10 + || superBlock->num_ags != divide_roundup(superBlock->num_blocks,1L << superBlock->ag_shift)) + { + result = false; + } else { + strcpy(partitionInfo->file_system_short_name, "bfs"); + strcpy(partitionInfo->file_system_long_name, "Be File System"); + strcpy(partitionInfo->volume_name, superBlock->name); + strcpy(partitionInfo->mounted_at, "???"); + result = true; + } + free(buffer); + } + } + return result; +} + +static fs_module_info bfs_fs_module = +{ + // module_info + { + BFS_FS_MODULE_NAME, + 0, // better B_KEEP_LOADED? + std_ops + }, + bfs_fs_identify +}; + +_EXPORT fs_module_info *modules[] = +{ + &bfs_fs_module, + NULL +}; + +