From 9c46627afb5b895109c28f017d5c6c1805c1c51d Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 1 Sep 2008 23:50:42 -0400 Subject: [PATCH] Extract common OMFS code into a library --- Makefile | 13 +- bits.h | 26 --- check.c | 52 ++--- create_fs.c | 88 +++---- dirscan.c | 14 +- fix.c | 15 +- io.c | 4 +- libomfs/Makefile | 11 + libomfs/bitmap.c | 112 +++++++++ libomfs/bits.h | 40 ++++ config.h => libomfs/config.h | 20 +- crc.c => libomfs/crc.c | 0 crc.h => libomfs/crc.h | 0 libomfs/omfs.c | 532 +++++++++++++++++++++++++++++++++++++++++++ libomfs/omfs.h | 55 +++++ libomfs/omfs_fs.h | 83 +++++++ omfs.c | 221 ------------------ omfs.h | 113 --------- 18 files changed, 942 insertions(+), 457 deletions(-) delete mode 100644 bits.h create mode 100644 libomfs/Makefile create mode 100644 libomfs/bitmap.c create mode 100644 libomfs/bits.h rename config.h => libomfs/config.h (79%) rename crc.c => libomfs/crc.c (100%) rename crc.h => libomfs/crc.h (100%) create mode 100644 libomfs/omfs.c create mode 100644 libomfs/omfs.h create mode 100644 libomfs/omfs_fs.h delete mode 100644 omfs.c delete mode 100644 omfs.h diff --git a/Makefile b/Makefile index 2be1915..ab07de7 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ VERSION=0.1.0 DISTNAME=omfsprogs-$(VERSION) -DISTFILES=*.[ch] Makefile README COPYING +DISTFILES=*.[ch] Makefile README COPYING libs/*.[ch] libs/Makefile TESTFILES=test/*.[ch] test/Makefile test/*.sh -COMMON_SRCS=crc.c omfs.c dirscan.c stack.c io.c +COMMON_SRCS=dirscan.c stack.c io.c COMMON_OBJS=$(COMMON_SRCS:.c=.o) OMFSCK_SRCS=omfsck.c fix.c check.c @@ -15,18 +15,19 @@ MKOMFS_OBJS=$(MKOMFS_SRCS:.c=.o) $(COMMON_OBJS) OMFSDUMP_SRCS=omfsdump.c dump.c OMFSDUMP_OBJS=$(OMFSDUMP_SRCS:.c=.o) $(COMMON_OBJS) -CFLAGS=-g -Wall -Wpadded -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE +CFLAGS=-g -Wall -Wpadded -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -I libomfs +LIBS=-Llibomfs -lomfs all: omfsck mkomfs omfsdump omfsck: $(OMFSCK_OBJS) - gcc -o omfsck $(OMFSCK_OBJS) + gcc -o omfsck $(OMFSCK_OBJS) $(LIBS) mkomfs: $(MKOMFS_OBJS) - gcc -o mkomfs $(MKOMFS_OBJS) + gcc -o mkomfs $(MKOMFS_OBJS) $(LIBS) omfsdump: $(OMFSDUMP_OBJS) - gcc -o omfsdump $(OMFSDUMP_OBJS) + gcc -o omfsdump $(OMFSDUMP_OBJS) $(LIBS) clean: $(RM) omfsck mkomfs *.o diff --git a/bits.h b/bits.h deleted file mode 100644 index 72d05c8..0000000 --- a/bits.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _BITS_H -#define _BITS_H - -inline int test_bit(u8* buf, u64 offset) -{ - return buf[offset >> 3] & (1<<(offset & 7)); -} - -inline void init_bit(u8* buf, u64 offset, int value) -{ - int mask = ((value & 1) << (offset & 7)); - buf[offset >> 3] &= ~mask; - buf[offset >> 3] |= mask; -} - -inline void clear_bit(u8* buf, u64 offset) -{ - buf[offset >> 3] &= ~(1 << (offset & 7)); -} - -inline void set_bit(u8* buf, u64 offset) -{ - buf[offset >> 3] |= 1 << (offset & 7); -} - -#endif diff --git a/check.c b/check.c index b8d8e79..b4934b8 100644 --- a/check.c +++ b/check.c @@ -31,9 +31,9 @@ int check_crc(u8 *blk) oi = (struct omfs_inode *) blk; crc = crc_ccitt_msb(0, blk + hdr_size, - swap_be32(oi->head.body_size)); + swap_be32(oi->i_head.h_body_size)); - return (crc == swap_be16(oi->head.crc)); + return (crc == swap_be16(oi->i_head.h_crc)); } int check_header(u8 *blk) @@ -48,14 +48,14 @@ int check_header(u8 *blk) for (i = 1; i < OMFS_XOR_COUNT; i++) xor ^= blk[i]; - return (xor == oi->head.check_xor); + return (xor == oi->i_head.h_check_xor); } int check_sanity(check_context_t *ctx) { omfs_inode_t *inode = ctx->current_inode; - if (swap_be32(inode->head.body_size) > - swap_be32(ctx->omfs_info->super->sys_blocksize)) + if (swap_be32(inode->i_head.h_body_size) > + swap_be32(ctx->omfs_info->super->s_sys_blocksize)) return 0; // check device size here too. @@ -73,9 +73,10 @@ int check_bitmap(check_context_t *ctx) if (!ctx->bitmap) return 0; - bsize = (swap_be64(super->num_blocks) + 7) / 8; - first_blk = swap_be64(root->bitmap) + (bsize + - swap_be32(super->blocksize)-1) / swap_be32(super->blocksize); + bsize = (swap_be64(super->s_num_blocks) + 7) / 8; + first_blk = swap_be64(root->r_bitmap) + (bsize + + swap_be32(super->s_blocksize)-1) / + swap_be32(super->s_blocksize); for (i=0; i < first_blk; i++) set_bit(ctx->visited, i); @@ -108,8 +109,7 @@ void visit_extents(check_context_t *ctx) u8 *buf; next = ctx->block; - buf = omfs_get_block(ctx->omfs_info->dev, - ctx->omfs_info->super, next); + buf = omfs_get_block(ctx->omfs_info, next); if (!buf) return; @@ -117,17 +117,17 @@ void visit_extents(check_context_t *ctx) for(;;) { - extent_count = swap_be32(oe->extent_count); + extent_count = swap_be32(oe->e_extent_count); last = next; - next = swap_be64(oe->next); - entry = &oe->entry; + next = swap_be64(oe->e_next); + entry = &oe->e_entry; // ignore last entry as it is the terminator for (; extent_count > 1; extent_count--) { - u64 start = swap_be64(entry->cluster); + u64 start = swap_be64(entry->e_cluster); - for (i=0; iblocks); i++) + for (i=0; ie_blocks); i++) set_bit(ctx->visited, start + i); entry++; @@ -140,8 +140,7 @@ void visit_extents(check_context_t *ctx) break; free(buf); - buf = omfs_get_block(ctx->omfs_info->dev, - ctx->omfs_info->super, next); + buf = omfs_get_block(ctx->omfs_info, next); if (!buf) goto err; oe = (struct omfs_extent *) &buf[OMFS_EXTENT_CONT]; @@ -162,7 +161,7 @@ int check_inode(check_context_t *ctx) fix_problem(E_LOOP, ctx); return 0; } - for (i=0; i < swap_be32(ctx->omfs_info->super->mirrors); i++) + for (i=0; i < swap_be32(ctx->omfs_info->super->s_mirrors); i++) set_bit(ctx->visited, ctx->block + i); if (!check_sanity(ctx)) @@ -180,22 +179,22 @@ int check_inode(check_context_t *ctx) fix_problem(E_HEADER_CRC, ctx); ret = 0; } - if (swap_be64(inode->head.self) != ctx->block) + if (swap_be64(inode->i_head.h_self) != ctx->block) { fix_problem(E_SELF_PTR, ctx); ret = 0; } - if (swap_be64(inode->parent) != ctx->parent) + if (swap_be64(inode->i_parent) != ctx->parent) { fix_problem(E_PARENT_PTR, ctx); ret = 0; } - if (omfs_compute_hash(ctx->omfs_info, inode->name) != ctx->hash) + if (omfs_compute_hash(ctx->omfs_info, inode->i_name) != ctx->hash) { fix_problem(E_HASH_WRONG, ctx); ret = 0; } - if (inode->type == OMFS_FILE) + if (inode->i_type == OMFS_FILE) { visit_extents(ctx); } @@ -229,20 +228,21 @@ int check_fs(FILE *fp, check_fs_config_t *config) ctx.config = config; - if (omfs_read_super(fp, &super)) + if (omfs_read_super(&info)) { fix_problem(E_READ_SUPER, &ctx); return 0; } - if (omfs_read_root_block(fp, &super, &root)) + if (omfs_read_root_block(&info)) { fix_problem(E_READ_ROOT, &ctx); return 0; } ctx.omfs_info = &info; - ctx.bitmap = omfs_get_bitmap(&info); - bsize = (swap_be64(info.super->num_blocks) + 7) / 8; + omfs_load_bitmap(&info); + ctx.bitmap = info.bitmap->bmap; + bsize = (swap_be64(info.super->s_num_blocks) + 7) / 8; ctx.visited = calloc(1, bsize); /* FIXME error codes are all over the place. */ diff --git a/create_fs.c b/create_fs.c index fe3a0c8..86fda86 100644 --- a/create_fs.c +++ b/create_fs.c @@ -51,64 +51,68 @@ int create_fs(FILE *fp, u64 sectors, fs_config_t *config) omfs_super_t super = { - .root_block = swap_be64(ROOT_BLK), - .num_blocks = swap_be64(blocks), - .magic = swap_be32(OMFS_MAGIC), - .blocksize = swap_be32(block_size), - .mirrors = swap_be32(2), - .sys_blocksize = swap_be32(2048), + .s_root_block = swap_be64(ROOT_BLK), + .s_num_blocks = swap_be64(blocks), + .s_magic = swap_be32(OMFS_MAGIC), + .s_blocksize = swap_be32(block_size), + .s_mirrors = swap_be32(2), + .s_sys_blocksize = swap_be32(2048), }; omfs_root_t root = { - .head.self = swap_be64(ROOT_BLK), - .head.body_size = swap_be32(sizeof(omfs_root_t) - sizeof(struct omfs_header)), - .head.version = 1, - .head.type = OMFS_INODE_SYSTEM, - .head.magic = OMFS_IMAGIC, - .num_blocks = super.num_blocks, - .root_dir = swap_be64(ROOT_DIR_BLK), - .bitmap = swap_be64(BITMAP_BLK), - .blocksize = super.blocksize, - .clustersize = swap_be32(config->cluster_size), - .mirrors = swap_be64(super.mirrors), + .r_head.h_self = swap_be64(ROOT_BLK), + .r_head.h_body_size = swap_be32(sizeof(omfs_root_t) - sizeof(struct omfs_header)), + .r_head.h_version = 1, + .r_head.h_type = OMFS_INODE_SYSTEM, + .r_head.h_magic = OMFS_IMAGIC, + .r_num_blocks = super.s_num_blocks, + .r_root_dir = swap_be64(ROOT_DIR_BLK), + .r_bitmap = swap_be64(BITMAP_BLK), + .r_blocksize = super.s_blocksize, + .r_clustersize = swap_be32(config->cluster_size), + .r_mirrors = swap_be64(super.s_mirrors), }; - safe_strncpy(super.name, label, OMFS_SUPER_NAMELEN); - safe_strncpy(root.name, label, OMFS_NAMELEN); + omfs_bitmap_t bitmap; + + safe_strncpy(super.s_name, label, OMFS_SUPER_NAMELEN); + safe_strncpy(root.r_name, label, OMFS_NAMELEN); + + info.dev = fp; + info.super = &super; + info.root = &root; + info.bitmap = &bitmap; // super block - omfs_write_super(fp, &super); - omfs_write_root_block(fp, &super, &root); + omfs_write_super(&info); + omfs_write_root_block(&info); u64 now = time(NULL) * 1000LL; // root directory omfs_inode_t root_ino = { - .head.self = swap_be64(ROOT_DIR_BLK), - .head.body_size = swap_be32(swap_be32(super.sys_blocksize) - sizeof(omfs_header_t)), - .head.version = 1, - .head.type = OMFS_INODE_NORMAL, - .head.magic = OMFS_IMAGIC, - .parent = ~0, - .sibling = ~0, - .ctime = swap_be64(now), - .type = 'D', - .one_goes_here = swap_be32(1), - .size = swap_be64(swap_be32(super.sys_blocksize)) + .i_head.h_self = swap_be64(ROOT_DIR_BLK), + .i_head.h_body_size = swap_be32(swap_be32(super.s_sys_blocksize) - sizeof(omfs_header_t)), + .i_head.h_version = 1, + .i_head.h_type = OMFS_INODE_NORMAL, + .i_head.h_magic = OMFS_IMAGIC, + .i_parent = ~0, + .i_sibling = ~0, + .i_ctime = swap_be64(now), + .i_type = 'D', + .i_fill2 = swap_be32(1), + .i_size = swap_be64(swap_be32(super.s_sys_blocksize)) }; - u8 *data = calloc(1, swap_be32(super.sys_blocksize)); + u8 *data = calloc(1, swap_be32(super.s_sys_blocksize)); if (!data) return 0; memcpy(data, &root_ino, sizeof (omfs_inode_t)); memset(data + OMFS_DIR_START, 0xff, - swap_be32(super.sys_blocksize) - OMFS_DIR_START); + swap_be32(super.s_sys_blocksize) - OMFS_DIR_START); - info.dev = fp; - info.super = &super; - info.root = &root; omfs_write_inode(&info, (omfs_inode_t *) data); free(data); @@ -116,17 +120,17 @@ int create_fs(FILE *fp, u64 sectors, fs_config_t *config) // free space bitmap. We already know that blocks 0-5 are // going to be set; the first available cluster has to take // into account the size of the free space bitmap. - int bitmap_size = (swap_be64(super.num_blocks) + 7)/8; + int bitmap_size = (swap_be64(super.s_num_blocks) + 7)/8; int first_blk = BITMAP_BLK + (bitmap_size + - swap_be32(super.blocksize)-1) / swap_be32(super.blocksize); + swap_be32(super.s_blocksize)-1) / swap_be32(super.s_blocksize); - u8 *bitmap = calloc(1, bitmap_size); + bitmap.bmap = calloc(1, bitmap_size); for (i=0; iinode; /* push next sibling all then all children */ - if (ino->sibling != ~0) + if (ino->i_sibling != ~0) { - tmp = omfs_get_inode(d->omfs_info, swap_be64(ino->sibling)); + tmp = omfs_get_inode(d->omfs_info, swap_be64(ino->i_sibling)); if (!tmp) { res = -1; @@ -51,15 +51,15 @@ int traverse (dirscan_t *d, dirscan_entry_t *entry) } enew = _create_entry(tmp, entry->level, entry->hindex, - entry->parent, swap_be64(ino->sibling)); + entry->parent, swap_be64(ino->i_sibling)); traverse(d, enew); } - if (ino->type == OMFS_DIR) + if (ino->i_type == OMFS_DIR) { int i; u64 *ptr = (u64*) ((u8*) ino + OMFS_DIR_START); - int num_entries = (swap_be32(ino->head.body_size) + + int num_entries = (swap_be32(ino->i_head.h_body_size) + sizeof(omfs_header_t) - OMFS_DIR_START) / 8; for (i=0; ivisit = visit; d->user_data = user_data; - root_ino = omfs_get_inode(info, swap_be64(info->root->root_dir)); + root_ino = omfs_get_inode(info, swap_be64(info->root->r_root_dir)); if (!root_ino) goto error; res = traverse(d, _create_entry(root_ino, 0, 0, ~0, - swap_be64(info->root->root_dir))); + swap_be64(info->root->r_root_dir))); dirscan_end(d); diff --git a/fix.c b/fix.c index 4ff1628..e76fd00 100644 --- a/fix.c +++ b/fix.c @@ -57,7 +57,7 @@ omfs_inode_t *find_node(check_context_t *ctx, int *is_parent) { omfs_release_inode(inode); inode = omfs_get_inode(ctx->omfs_info, swap_be64(*chain_ptr)); - chain_ptr = &inode->sibling; + chain_ptr = &inode->i_sibling; } if (*chain_ptr == ~0) @@ -75,7 +75,7 @@ static u64 *get_entry(struct omfs_inode *inode, int hash, int is_parent) if (is_parent) entry = (u64 *) ((u8 *) inode + OMFS_DIR_START) + hash; else - entry = &inode->sibling; + entry = &inode->i_sibling; return entry; } @@ -120,21 +120,21 @@ static void move_file(check_context_t *ctx, u64 dest_dir) return; } entry = get_entry(source, ctx->hash, is_parent); - *entry = ctx->current_inode->sibling; + *entry = ctx->current_inode->i_sibling; res = omfs_write_inode(ctx->omfs_info, source); omfs_release_inode(source); if (res) perror("omfsck"); dest = omfs_get_inode(ctx->omfs_info, dest_dir); - if (dest->type != OMFS_DIR) + if (dest->i_type != OMFS_DIR) { printf("Huh, tried to move it to a non-dir.. oh well.\n"); return; } - hash = omfs_compute_hash(ctx->omfs_info, ctx->current_inode->name); + hash = omfs_compute_hash(ctx->omfs_info, ctx->current_inode->i_name); entry = get_entry(dest, hash, 1); - ctx->current_inode->sibling = *entry; + ctx->current_inode->i_sibling = *entry; *entry = swap_be64(ctx->block); res = omfs_write_inode(ctx->omfs_info, dest); if (res) @@ -198,7 +198,8 @@ void fix_problem(check_error_t error, check_context_t *ctx) if (prompt_yesno("Rebuild?")) { printf("Okay writing computed bitmap.\n"); - omfs_write_bitmap(ctx->omfs_info, ctx->visited); + ctx->omfs_info->bitmap->bmap = ctx->visited; + omfs_flush_bitmap(ctx->omfs_info); } else printf("Skipping.\n"); diff --git a/io.c b/io.c index 8c21933..8db9cd6 100644 --- a/io.c +++ b/io.c @@ -29,10 +29,10 @@ static void expand_custom(char ch, check_context_t *ctx) fputc('$', stdout); break; case 'I': - printf("%llx", swap_be64(ctx->current_inode->head.self)); + printf("%llx", swap_be64(ctx->current_inode->i_head.h_self)); break; case 'F': - s = escape(ctx->current_inode->name); + s = escape(ctx->current_inode->i_name); printf("%s", s); free(s); break; diff --git a/libomfs/Makefile b/libomfs/Makefile new file mode 100644 index 0000000..1876bca --- /dev/null +++ b/libomfs/Makefile @@ -0,0 +1,11 @@ +LIBOMFS_SRCS=crc.c omfs.c bitmap.c +LIBOMFS_OBJS=$(LIBOMFS_SRCS:.c=.o) + +CFLAGS=-g -Wall -Wpadded -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE + +all: libomfs.a + +libomfs.a: libomfs.a($(LIBOMFS_OBJS)) + +clean: + $(RM) libomfs.a *.o diff --git a/libomfs/bitmap.c b/libomfs/bitmap.c new file mode 100644 index 0000000..cf36c9c --- /dev/null +++ b/libomfs/bitmap.c @@ -0,0 +1,112 @@ +/* Routines for bitmap allocation */ +#include +#include "omfs.h" +#include "bits.h" +#include "errno.h" + + +static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; + +unsigned long omfs_count_free(omfs_info_t *info) +{ + unsigned int i; + unsigned long sum = 0; + size_t bsize = (swap_be64(info->super->s_num_blocks) + 7) / 8; + + u8 *map = info->bitmap->bmap; + + for (i = 0; i < bsize; i++) + sum += nibblemap[map[i] & 0xf] + nibblemap[(map[i] >> 4) & 0xf]; + + return sum; +} + +/* + * Mark the bitmap block which holds an allocated/cleared bit dirty. + * Call after every set_bit/clear_bit in the bitmap. Block is the + * *data* block number. + */ +static void mark_dirty(omfs_info_t *info, u64 block) +{ + int blocksize = swap_be32(info->super->s_blocksize); + u64 bit_blk = (block >> 3) / blocksize; + set_bit(info->bitmap->dirty, bit_blk); +} + +/* + * Scan through a bitmap for power-of-two sized region (max 8). This + * should help to keep down fragmentation as mirrors will generally + * align to 2 blocks and clusters to 8. + */ +static int scan(u8* buf, int bsize, int bits) +{ + int shift = 1 << bits; + int mask = shift - 1; + int m, i; + + for (i=0; i < bsize * 8; i += bits) + { + m = mask << (i & 7); + if (!(buf[ i >> 3 ] & m)) + { + buf[ i >> 3 ] |= m; + break; + } + } + return i; +} + +int omfs_clear_range(omfs_info_t *info, u64 start, int count) +{ + int i; + u8 *bitmap = info->bitmap->bmap; + + for (i=0; i < count; i++) { + clear_bit(bitmap, i + start); + mark_dirty(info, i + start); + } + + omfs_flush_bitmap(info); + return 0; +} + +int omfs_allocate_one_block(omfs_info_t *info, u64 block) +{ + int ok = 0; + u8 *bitmap = info->bitmap->bmap; + + if (!test_bit(bitmap, block)) + { + set_bit(bitmap, block); + mark_dirty(info, block); + omfs_flush_bitmap(info); + ok = 1; + } + return ok; +} + +int omfs_allocate_block(omfs_info_t *info, int size, u64 *return_block) +{ + size_t bsize; + int ret = 0; + int block, i; + + u8 *bitmap = info->bitmap->bmap; + + bsize = (swap_be64(info->super->s_num_blocks) + 7) / 8; + + block = scan(bitmap, bsize, size); + if (block == bsize * 8) { + ret = -ENOSPC; + goto out; + } + *return_block = block; + + for (i=0; i < size; i++) + mark_dirty(info, block + i); + + omfs_flush_bitmap(info); +out: + return ret; +} + diff --git a/libomfs/bits.h b/libomfs/bits.h new file mode 100644 index 0000000..073b4d7 --- /dev/null +++ b/libomfs/bits.h @@ -0,0 +1,40 @@ +#ifndef _BITS_H +#define _BITS_H + +static inline int test_bit(u8* buf, u64 offset) +{ + return buf[offset >> 3] & (1<<(offset & 7)); +} + +static inline void init_bit(u8* buf, u64 offset, int value) +{ + int mask = ((value & 1) << (offset & 7)); + buf[offset >> 3] &= ~mask; + buf[offset >> 3] |= mask; +} + +static inline void clear_bit(u8* buf, u64 offset) +{ + buf[offset >> 3] &= ~(1 << (offset & 7)); +} + +static inline void set_bit(u8* buf, u64 offset) +{ + buf[offset >> 3] |= 1 << (offset & 7); +} + +static inline int is_power_of_two(int i) +{ + return !(i & (i-1)); +} + +static inline int log_2(int i) +{ + int count = 0; + + for (i>>=1;i;i>>=1) + count++; + return count; +} + +#endif diff --git a/config.h b/libomfs/config.h similarity index 79% rename from config.h rename to libomfs/config.h index 480d5c1..7de8516 100644 --- a/config.h +++ b/libomfs/config.h @@ -1,17 +1,23 @@ #ifndef _CONFIG_H #define _CONFIG_H +#include + typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; typedef char s8; -typedef short s16; -typedef int s32; -typedef long long s64; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef u64 __be64; +typedef u32 __be32; +typedef u16 __be16; -#if 0 +#if __BYTE_ORDER == __BIG_ENDIAN #define swap_be64(a) (a) #define swap_be32(a) (a) #define swap_be16(a) (a) diff --git a/crc.c b/libomfs/crc.c similarity index 100% rename from crc.c rename to libomfs/crc.c diff --git a/crc.h b/libomfs/crc.h similarity index 100% rename from crc.h rename to libomfs/crc.h diff --git a/libomfs/omfs.c b/libomfs/omfs.c new file mode 100644 index 0000000..66218f7 --- /dev/null +++ b/libomfs/omfs.c @@ -0,0 +1,532 @@ +/* + * Super/root block reading routines + */ +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "omfs.h" +#include "bits.h" +#include "crc.h" + +static void _omfs_make_empty_table(u8 *buf, int offset) +{ + struct omfs_extent *oe = (struct omfs_extent *) &buf[offset]; + oe->e_next = ~0ULL; + oe->e_extent_count = swap_be32(1), + oe->e_fill = swap_be32(0x22), + oe->e_entry.e_cluster = ~0ULL; + oe->e_entry.e_blocks = ~0ULL; +} + + +static void _omfs_swap_buffer(void *buf, int count) +{ + int i; + u32 *ibuf = (u32 *) buf; + + count >>= 2; + + for (i=0; iswap) + _omfs_swap_buffer(info->super, sizeof(struct omfs_super_block)); + + pthread_mutex_lock(&info->dev_mutex); + fseeko(info->dev, 0LL, SEEK_SET); + count = fwrite(info->super, 1, sizeof(struct omfs_super_block), info->dev); + pthread_mutex_unlock(&info->dev_mutex); + + if (info->swap) + _omfs_swap_buffer(info->super, sizeof(struct omfs_super_block)); + + if (count < sizeof(struct omfs_super_block)) + return -1; + + return 0; +} + +/* + * Read the superblock and store the result in ret + */ +int omfs_read_super(omfs_info_t *info) +{ + int count, err = 0; + + pthread_mutex_lock(&info->dev_mutex); + fseeko(info->dev, 0LL, SEEK_SET); + count = fread(info->super, 1, sizeof(struct omfs_super_block), info->dev); + pthread_mutex_unlock(&info->dev_mutex); + + if (count < sizeof(struct omfs_super_block)) + { + err = -EIO; + goto out; + } + + info->swap = 0; + if (info->super->s_magic == OMFS_MAGIC) // unswapped + { + _omfs_swap_buffer(info->super, count); + info->swap = 1; + } + else if (swap_be32(info->super->s_magic) != OMFS_MAGIC) + err = -EMEDIUMTYPE; + +out: + return err; +} + +static int _omfs_write_block(omfs_info_t *info, + u64 block, u8* buf, size_t len, int mirrors) +{ + int i, count, ret = 0; + FILE *dev = info->dev; + struct omfs_super_block *sb = info->super; + + if (info->swap) + _omfs_swap_buffer(buf, len); + + pthread_mutex_lock(&info->dev_mutex); + for (i=0; is_blocksize), SEEK_SET); + count = fwrite(buf, 1, len, dev); + if (count != len) + { + ret = -1; + goto out; + } + } +out: + if (info->swap) + _omfs_swap_buffer(buf, len); + pthread_mutex_unlock(&info->dev_mutex); + return ret; +} + + +/* + * Read the numbered block into a raw array. + * buf must be at least blocksize bytes. + */ +static int _omfs_read_block(omfs_info_t *info, u64 block, u8 *buf) +{ + int count, ret = 0; + FILE *dev = info->dev; + struct omfs_super_block *sb = info->super; + int blocksize; + + blocksize = swap_be32(sb->s_blocksize); + + pthread_mutex_lock(&info->dev_mutex); + fseeko(dev, block * blocksize, SEEK_SET); + count = fread(buf, 1, blocksize, dev); + pthread_mutex_unlock(&info->dev_mutex); + + if (info->swap) + _omfs_swap_buffer(buf, count); + + if (count < blocksize) + ret = -1; + + return ret; +} + +static void _update_header_checksums(u8 *buf, int block_size) +{ + int xor, i; + omfs_header_t *header = (omfs_header_t *) buf; + u8 *body = buf + sizeof(omfs_header_t); + int body_size = block_size - sizeof(omfs_header_t); + + header->h_crc = swap_be16(crc_ccitt_msb(0, body, body_size)); + + xor = buf[0]; + for (i=1; ih_check_xor = xor; +} + + +int omfs_write_root_block(omfs_info_t *info) +{ + u64 block = swap_be64(info->root->r_head.h_self); + return _omfs_write_block(info, block, (u8*) info->root, + sizeof(struct omfs_root_block), + swap_be32(info->super->s_mirrors)); +} + + +static u8 *_omfs_get_block(omfs_info_t *info, u64 block) +{ + u8 *buf; + if (!(buf = malloc(swap_be32(info->super->s_blocksize)))) + return 0; + + if (_omfs_read_block(info, block, buf)) + { + free(buf); + return 0; + } + + return buf; +} + +u8 *omfs_get_block(omfs_info_t *info, u64 block) +{ + return _omfs_get_block(info, block); +} + +int omfs_read_root_block(omfs_info_t *info) +{ + u8 *buf; + + buf = _omfs_get_block(info, swap_be64(info->super->s_root_block)); + if (!buf) + return -1; + + memcpy(info->root, buf, sizeof(struct omfs_root_block)); + free(buf); + return 0; +} + +/* + * Write an inode to the device. + */ +int omfs_write_inode(omfs_info_t *info, omfs_inode_t *inode) +{ + struct timezone tz; + struct timeval tv; + u64 ctime; + int size = swap_be32(inode->i_head.h_body_size) + sizeof(omfs_header_t); + + gettimeofday(&tv, &tz); + + ctime = tv.tv_sec * 1000LL + tv.tv_usec; + inode->i_ctime = swap_be64(ctime); + + _update_header_checksums((u8*)inode, size); + + return _omfs_write_block(info, swap_be64(inode->i_head.h_self), + (u8*) inode, size, swap_be32(info->super->s_mirrors)); +} + +omfs_inode_t *omfs_new_inode(omfs_info_t *info, u64 block, + char *name, char type) +{ + u8 *buf; + omfs_inode_t *inode; + + inode = omfs_get_inode(info, block); + if (!inode) + return NULL; + + memset(inode, 0, swap_be32(info->super->s_blocksize)); + + inode->i_head.h_self = swap_be64(block); + inode->i_head.h_version = 1; + inode->i_head.h_magic = OMFS_IMAGIC; + inode->i_head.h_body_size = swap_be32( + swap_be32(info->super->s_sys_blocksize) - sizeof(struct omfs_header)); + inode->i_head.h_type = OMFS_INODE_NORMAL; + inode->i_type = type; + inode->i_parent = ~0ULL; + inode->i_sibling = ~0ULL; + inode->i_fill2 = swap_be32(1); + strncpy(inode->i_name, name, OMFS_NAMELEN); + inode->i_name[OMFS_NAMELEN-1] = 0; + inode->i_size = swap_be64((u64) swap_be32(info->super->s_sys_blocksize)); + + buf = (u8*) inode; + if (type == OMFS_FILE) + { + inode->i_size = 0; + _omfs_make_empty_table(buf, OMFS_EXTENT_START); + } + else if (type == OMFS_INODE_CONTINUATION) + { + inode->i_head.h_type = OMFS_INODE_CONTINUATION; + _omfs_make_empty_table(buf, OMFS_EXTENT_CONT); + } + else + { + memset(&buf[OMFS_DIR_START], 0xff, + swap_be32(info->super->s_sys_blocksize) - OMFS_DIR_START); + } + + return inode; +} + +omfs_inode_t *omfs_get_inode(omfs_info_t *info, u64 block) +{ + u8 *buf; + buf = omfs_get_block(info, block); + if (!buf) + return NULL; + + return (omfs_inode_t *) buf; +} + +void omfs_release_inode(omfs_inode_t *oi) +{ + free(oi); +} + +int omfs_flush_bitmap(omfs_info_t *info) +{ + size_t size, bsize, count, ret = 0; + u64 bitmap_blk = swap_be64(info->root->r_bitmap); + int blocksize = swap_be32(info->super->s_blocksize); + u8 *bmap = info->bitmap->bmap; + int i; + + if (bitmap_blk == ~0) + return 0; + + size = (swap_be64(info->super->s_num_blocks) + 7) / 8; + bsize = (size + blocksize - 1) / blocksize; + + pthread_mutex_lock(&info->dev_mutex); + for (i=0; i < bsize * 8; i++, bitmap_blk++, bmap += blocksize) + { + if (test_bit(info->bitmap->dirty, i)) + { + fseeko(info->dev, bitmap_blk * blocksize, SEEK_SET); + count = fwrite(bmap, 1, blocksize, info->dev); + if (size != count) { + ret = -EIO; + goto out; + } + clear_bit(info->bitmap->dirty, i); + } + } + +out: + pthread_mutex_unlock(&info->dev_mutex); + return ret; +} + +int omfs_write_block(omfs_info_t *info, u64 block, u8* buf) +{ + return _omfs_write_block(info, block, buf, + swap_be32(info->super->s_blocksize), 1); +} + +static void set_inuse_file(omfs_info_t *info, omfs_inode_t *file, u8 *bmap) +{ + struct omfs_extent *oe; + struct omfs_extent_entry *entry; + u64 next; + int extent_count, i; + omfs_inode_t *inode; + + if (!file) + return; + + next = swap_be64(file->i_head.h_self); + inode = file; + oe = (struct omfs_extent *) (((u8*) inode) + OMFS_EXTENT_START); + + for(;;) + { + extent_count = swap_be32(oe->e_extent_count); + + for (i=0; isuper->s_mirrors); i++) + set_bit(bmap, next + i); + + next = swap_be64(oe->e_next); + entry = &oe->e_entry; + + // ignore last entry as it is the terminator + for (; extent_count > 1; extent_count--) + { + u64 start = swap_be64(entry->e_cluster); + + for (i=0; ie_blocks); i++) + set_bit(bmap, start + i); + + entry++; + } + + if (next == ~0) + break; + + if (inode != file) + omfs_release_inode(inode); + + inode = omfs_get_inode(info, next); + if (!inode) + goto err; + + oe = (struct omfs_extent *) (((u8*) inode) + OMFS_EXTENT_CONT); + } + + if (inode != file) + omfs_release_inode(inode); +err: + return; +} + +static void set_inuse_dir(omfs_info_t *info, omfs_inode_t *dir, u8 *bmap) +{ + u64 *ptr; + int i; + + if (!dir) + return; + + int num_entries = (swap_be32(dir->i_head.h_body_size) + + sizeof(omfs_header_t) - OMFS_DIR_START) / 8; + + ptr = (u64*) ((u8*) dir + OMFS_DIR_START); + + for (i=0; isuper->s_mirrors); i++) + set_bit(bmap, swap_be64(dir->i_head.h_self) + i); + + for (i=0; ii_type == OMFS_DIR) + set_inuse_dir(info, tmp, bmap); + else + set_inuse_file(info, tmp, bmap); + + inum = swap_be64(tmp->i_sibling); + omfs_release_inode(tmp); + } + } +} + +static void set_inuse_bits(omfs_info_t *info) +{ + u8 *bmap = info->bitmap->bmap; + u64 root_dir; + int i; + omfs_inode_t *root; + + root_dir = swap_be64(info->root->r_root_dir); + + for (i=0; iroot->r_bitmap); + int blocksize = swap_be32(info->super->s_blocksize); + int size_blks; + struct omfs_bitmap *bitmap; + int ret = 0; + + size = (swap_be64(info->super->s_num_blocks) + 7) / 8; + + // round up to a full block + size_blks = (size + blocksize - 1) / blocksize; + size = size_blks * blocksize; + + dirty_size = (size_blks + 7) / 8; + + if (!(buf = malloc(size))) { + ret = -ENOMEM; + goto out1; + } + + if (!(dirty_bits = calloc(1, dirty_size))) { + ret = -ENOMEM; + goto out2; + } + + bitmap = malloc(sizeof(struct omfs_bitmap)); + if (!bitmap) { + ret = -ENOMEM; + goto out3; + } + + info->bitmap = bitmap; + bitmap->dirty = dirty_bits; + bitmap->bmap = buf; + + if (bitmap_blk == ~0) + { + // create the bitmap by traversal + memset(buf, 0, size); + set_inuse_bits(info); + } + else + { + pthread_mutex_lock(&info->dev_mutex); + fseeko(info->dev, bitmap_blk * blocksize, SEEK_SET); + fread(buf, 1, size, info->dev); + pthread_mutex_unlock(&info->dev_mutex); + } + goto out1; + +out3: + free(dirty_bits); +out2: + free(buf); +out1: + return ret; +} + +int omfs_compute_hash(omfs_info_t *info, char *filename) +{ + int hash = 0, i; + int m = (swap_be32(info->super->s_sys_blocksize) - OMFS_DIR_START) / 8; + + for (i=0; idev); +} + +void omfs_clear_data(omfs_info_t *info, u64 block, int count) +{ + int i; + + for (i=0; i < count; i++, block++) + { + u8 *buf = omfs_get_block(info, block); + if (!buf) + return; + + memset(buf, 0, swap_be32(info->super->s_blocksize)); + omfs_write_block(info, block, buf); + free(buf); + } +} + diff --git a/libomfs/omfs.h b/libomfs/omfs.h new file mode 100644 index 0000000..1e854c4 --- /dev/null +++ b/libomfs/omfs.h @@ -0,0 +1,55 @@ +#ifndef _OMFS_H +#define _OMFS_H + +#include +#include "config.h" +#include "omfs_fs.h" +#include "crc.h" + +struct omfs_info { + FILE *dev; + struct omfs_super_block *super; + struct omfs_root_block *root; + struct omfs_bitmap *bitmap; + int swap; + pthread_mutex_t dev_mutex; +}; + +struct omfs_bitmap { + u8 *dirty; + u8 *bmap; +}; + +typedef struct omfs_info omfs_info_t; +typedef struct omfs_header omfs_header_t; +typedef struct omfs_super_block omfs_super_t; +typedef struct omfs_bitmap omfs_bitmap_t; +typedef struct omfs_root_block omfs_root_t; +typedef struct omfs_inode omfs_inode_t; + +int omfs_read_super(omfs_info_t *info); +int omfs_write_super(omfs_info_t *info); +int omfs_read_root_block(omfs_info_t *info); +int omfs_write_root_block(omfs_info_t *info); +u8 *omfs_get_block(omfs_info_t *info, u64 block); +int omfs_write_block(omfs_info_t *info, u64 block, u8* buf); +void omfs_release_block(u8 *buf); +int omfs_check_crc(u8 *blk); +omfs_inode_t *omfs_get_inode(omfs_info_t *info, u64 block); +int omfs_write_inode(omfs_info_t *info, omfs_inode_t *inode); +void omfs_release_inode(omfs_inode_t *inode); +void omfs_sync(omfs_info_t *info); +int omfs_load_bitmap(omfs_info_t *info); +int omfs_flush_bitmap(omfs_info_t *info); +int omfs_compute_hash(omfs_info_t *info, char *filename); +omfs_inode_t *omfs_new_inode(omfs_info_t *info, u64 block, char *name, + char type); +void omfs_clear_data(omfs_info_t *info, u64 block, int count); + +/* bitmap.c */ +int omfs_allocate_one_block(omfs_info_t *info, u64 block); +int omfs_allocate_block(omfs_info_t *info, int size, u64 *return_block); +int omfs_clear_range(omfs_info_t *info, u64 start, int count); +unsigned long omfs_count_free(omfs_info_t *info); + +#endif diff --git a/libomfs/omfs_fs.h b/libomfs/omfs_fs.h new file mode 100644 index 0000000..4561a09 --- /dev/null +++ b/libomfs/omfs_fs.h @@ -0,0 +1,83 @@ +#ifndef _OMFS_FS_H +#define _OMFS_FS_H + +/* OMFS On-disk structures */ + +#define OMFS_MAGIC 0xC2993D87 +#define OMFS_IMAGIC 0xD2 + +#define OMFS_DIR 'D' +#define OMFS_FILE 'F' +#define OMFS_INODE_NORMAL 'e' +#define OMFS_INODE_CONTINUATION 'c' +#define OMFS_INODE_SYSTEM 's' +#define OMFS_SUPER_NAMELEN 64 +#define OMFS_NAMELEN 256 +#define OMFS_DIR_START 0x1b8 +#define OMFS_EXTENT_START 0x1d0 +#define OMFS_EXTENT_CONT 0x40 +#define OMFS_XOR_COUNT 19 +#define OMFS_MAX_BLOCK_SIZE 8192 + +struct omfs_super_block { + char s_fill1[192]; + char s_name[OMFS_SUPER_NAMELEN]; + __be64 s_root_block; /* block number of omfs_root_block */ + __be64 s_num_blocks; /* total number of FS blocks */ + __be32 s_magic; /* OMFS_MAGIC */ + __be32 s_blocksize; /* size of a block */ + __be32 s_mirrors; /* # of mirrors of system blocks */ + __be32 s_sys_blocksize; /* size of non-data blocks */ +}; + +struct omfs_header { + __be64 h_self; /* FS block where this is located */ + __be32 h_body_size; /* size of useful data after header */ + __be16 h_crc; /* crc-ccitt of body_size bytes */ + char h_fill1[2]; + u8 h_version; /* version, always 1 */ + char h_type; /* OMFS_INODE_X */ + u8 h_magic; /* OMFS_IMAGIC */ + u8 h_check_xor; /* XOR of header bytes before this */ + __be32 h_fill2; +}; + +struct omfs_root_block { + struct omfs_header r_head; /* header */ + __be64 r_fill1; + __be64 r_num_blocks; /* total number of FS blocks */ + __be64 r_root_dir; /* block # of root directory */ + __be64 r_bitmap; /* block # of free space bitmap */ + __be32 r_blocksize; /* size of a block */ + __be32 r_clustersize; /* size allocated for data blocks */ + __be64 r_mirrors; /* # of mirrors of system blocks */ + char r_name[OMFS_NAMELEN]; /* partition label */ + __be64 r_fill2; +}; + +struct omfs_inode { + struct omfs_header i_head; /* header */ + __be64 i_parent; /* parent containing this inode */ + __be64 i_sibling; /* next inode in hash bucket */ + __be64 i_ctime; /* ctime, in milliseconds */ + char i_fill1[35]; + char i_type; /* OMFS_[DIR,FILE] */ + __be32 i_fill2; + char i_fill3[64]; + char i_name[OMFS_NAMELEN]; /* filename */ + __be64 i_size; /* size of file, in bytes */ +}; + +struct omfs_extent_entry { + __be64 e_cluster; /* start location of a set of blocks */ + __be64 e_blocks; /* number of blocks after e_cluster */ +}; + +struct omfs_extent { + __be64 e_next; /* next extent table location */ + __be32 e_extent_count; /* total # extents in this table */ + __be32 e_fill; + struct omfs_extent_entry e_entry; /* start of extent entries */ +}; + +#endif diff --git a/omfs.c b/omfs.c deleted file mode 100644 index 1ccdf0a..0000000 --- a/omfs.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Super/root block reading routines - */ -#include -#include -#include -#include -#include "omfs.h" -#include "crc.h" - -static void _omfs_swap_buffer(void *buf, int count) -{ -#ifdef RTV_HACK - // only valid for Replay 4xxx and 5xxx: unconditionally force change - // of endianness - int i; - u32 *ibuf = (u32 *) buf; - count >>= 2; - - for (i=0; imirrors); i++) - { - fseeko(dev, (block + i) * swap_be32(sb->blocksize), SEEK_SET); - count = fwrite(buf, 1, len, dev); - if (count != len) - return -1; - } - return 0; -} - - -/* - * Read the numbered block into a raw array. - * buf must be at least blocksize bytes. - */ -static int _omfs_read_block(FILE *dev, struct omfs_super_block *sb, - u64 block, u8 *buf) -{ - int count; - fseeko(dev, block * swap_be32(sb->blocksize), SEEK_SET); - count = fread(buf, 1, swap_be32(sb->blocksize), dev); - - if (count < swap_be32(sb->blocksize)) - return -1; - - _omfs_swap_buffer(buf, count); - return 0; -} - -static void _update_header_checksums(u8 *buf, int block_size) -{ - int xor, i; - omfs_header_t *header = (omfs_header_t *) buf; - u8 *body = buf + sizeof(omfs_header_t); - int body_size = block_size - sizeof(omfs_header_t); - - header->crc = swap_be16(crc_ccitt_msb(0, body, body_size)); - - xor = buf[0]; - for (i=1; icheck_xor = xor; -} - - -int omfs_write_root_block(FILE *dev, struct omfs_super_block *sb, - struct omfs_root_block *root) -{ - u64 block = swap_be64(root->head.self); - return _omfs_write_block(dev, sb, block, (u8*) root, - sizeof(struct omfs_root_block)); -} - - -int omfs_read_root_block(FILE *dev, struct omfs_super_block *sb, - struct omfs_root_block *root) -{ - u8 *buf; - - buf = omfs_get_block(dev, sb, swap_be64(sb->root_block)); - if (!buf) - return -1; - - memcpy(root, buf, sizeof(struct omfs_root_block)); - free(buf); - return 0; -} - -u8 *omfs_get_block(FILE *dev, struct omfs_super_block *sb, u64 block) -{ - u8 *buf; - if (!(buf = malloc(swap_be32(sb->blocksize)))) - return 0; - - if (_omfs_read_block(dev, sb, block, buf)) - { - free(buf); - return 0; - } - - return buf; -} - -/* - * Write an inode to the device. - */ -int omfs_write_inode(omfs_info_t *info, omfs_inode_t *inode) -{ - int size = swap_be32(inode->head.body_size) + sizeof(omfs_header_t); - - _update_header_checksums((u8*)inode, size); - - return _omfs_write_block(info->dev, info->super, - swap_be64(inode->head.self), (u8*) inode, size); -} - -omfs_inode_t *omfs_get_inode(omfs_info_t *info, u64 block) -{ - u8 *buf; - buf = omfs_get_block(info->dev, info->super, block); - if (!buf) - return NULL; - - return (omfs_inode_t *) buf; -} - -void omfs_release_inode(omfs_inode_t *oi) -{ - free(oi); -} - -int omfs_write_bitmap(omfs_info_t *info, u8* bitmap) -{ - size_t size, count; - u64 bitmap_blk = swap_be64(info->root->bitmap); - - size = (swap_be64(info->super->num_blocks) + 7) / 8; - fseeko(info->dev, bitmap_blk * swap_be32(info->super->blocksize), - SEEK_SET); - count = fwrite(bitmap, 1, size, info->dev); - if (size != count) - return -1; - return 0; -} - -u8 *omfs_get_bitmap(omfs_info_t *info) -{ - size_t size; - u8 *buf; - u64 bitmap_blk = swap_be64(info->root->bitmap); - if (bitmap_blk == ~0) - return NULL; - - size = (swap_be64(info->super->num_blocks) + 7) / 8; - - if (!(buf = malloc(size))) - return NULL; - - fseeko(info->dev, bitmap_blk * swap_be32(info->super->blocksize), SEEK_SET); - fread(buf, 1, size, info->dev); - return buf; -} - -int omfs_compute_hash(omfs_info_t *info, char *filename) -{ - int hash = 0, i; - int m = (swap_be32(info->super->sys_blocksize) - OMFS_DIR_START) / 8; - - for (i=0; idev); -} diff --git a/omfs.h b/omfs.h deleted file mode 100644 index 19babc9..0000000 --- a/omfs.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef _OMFS_H -#define _OMFS_H - -#include "config.h" -#include - -#define OMFS_MAGIC 0xC2993D87 -#define OMFS_IMAGIC 0xD2 - -#define OMFS_DIR 'D' -#define OMFS_FILE 'F' -#define OMFS_INODE_NORMAL 'e' -#define OMFS_INODE_CONTINUATION 'c' -#define OMFS_INODE_SYSTEM 's' -#define OMFS_SUPER_NAMELEN 64 -#define OMFS_NAMELEN 256 -#define OMFS_DIR_START 0x1b8 -#define OMFS_EXTENT_START 0x1d0 -#define OMFS_EXTENT_CONT 0x40 -#define OMFS_XOR_COUNT 19 - - -struct omfs_info { - FILE *dev; - struct omfs_super_block *super; - struct omfs_root_block *root; -}; - -struct omfs_super_block { - char fill1[192]; - char name[OMFS_SUPER_NAMELEN]; - u64 root_block; - u64 num_blocks; - u32 magic; - u32 blocksize; - u32 mirrors; - u32 sys_blocksize; -}; - -struct omfs_header { - u64 self; - u32 body_size; - u16 crc; - char fill1[2]; - u8 version; - char type; - u8 magic; - u8 check_xor; - u32 fill2; -}; - -struct omfs_root_block { - struct omfs_header head; - u64 fill1; - u64 num_blocks; - u64 root_dir; - u64 bitmap; - u32 blocksize; - u32 clustersize; - u64 mirrors; - char name[OMFS_NAMELEN]; - u64 fill2; -}; - -struct omfs_inode { - struct omfs_header head; - u64 parent; - u64 sibling; - u64 ctime; - char fill1[35]; - char type; - u32 one_goes_here; - char fill3[64]; - char name[OMFS_NAMELEN]; - u64 size; -}; - -struct omfs_extent_entry { - u64 cluster; - u64 blocks; -}; - -struct omfs_extent { - u64 next; - u32 extent_count; - u32 fill; - struct omfs_extent_entry entry; -}; - -typedef struct omfs_info omfs_info_t; -typedef struct omfs_header omfs_header_t; -typedef struct omfs_super_block omfs_super_t; -typedef struct omfs_root_block omfs_root_t; -typedef struct omfs_inode omfs_inode_t; - -int omfs_read_super(FILE *dev, struct omfs_super_block *ret); -int omfs_write_super(FILE *dev, struct omfs_super_block *super); -int omfs_read_root_block(FILE *dev, struct omfs_super_block *sb, - struct omfs_root_block *root); -int omfs_write_root_block(FILE *dev, struct omfs_super_block *sb, - struct omfs_root_block *root); -u8 *omfs_get_block(FILE *dev, struct omfs_super_block *sb, u64 block); -void omfs_release_block(u8 *buf); -int omfs_check_crc(u8 *blk); -omfs_inode_t *omfs_get_inode(omfs_info_t *info, u64 block); -int omfs_write_inode(omfs_info_t *info, omfs_inode_t *inode); -void omfs_release_inode(omfs_inode_t *inode); -int omfs_write_bitmap(omfs_info_t *info, u8 *bitmap); -u8 *omfs_get_bitmap(omfs_info_t *info); -void omfs_sync(omfs_info_t *info); -int omfs_compute_hash(omfs_info_t *info, char *filename); - -#endif -- 2.11.4.GIT