disk_scanner fs module for BFS filesystems

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2285 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2002-12-22 22:47:17 +00:00
parent 36fc6e8559
commit 03d06845e6
1 changed files with 225 additions and 0 deletions

View File

@ -0,0 +1,225 @@
// bfs.c
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fs_device.h>
#include <KernelExport.h>
#include <disk_scanner/fs.h>
#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
};