| /* |
| * brel_ma.c |
| * |
| * Copyright (C) 1996, 1997 Theodore Ts'o. |
| * |
| * TODO: rewrite to not use a direct array!!! (Fortunately this |
| * module isn't really used yet.) |
| * |
| * %Begin-Header% |
| * This file may be redistributed under the terms of the GNU Library |
| * General Public License, version 2. |
| * %End-Header% |
| */ |
| |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <string.h> |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #if HAVE_ERRNO_H |
| #include <errno.h> |
| #endif |
| |
| #include "ext2_fs.h" |
| #include "ext2fs.h" |
| #include "brel.h" |
| |
| static errcode_t bma_put(ext2_brel brel, blk_t old, |
| struct ext2_block_relocate_entry *ent); |
| static errcode_t bma_get(ext2_brel brel, blk_t old, |
| struct ext2_block_relocate_entry *ent); |
| static errcode_t bma_start_iter(ext2_brel brel); |
| static errcode_t bma_next(ext2_brel brel, blk_t *old, |
| struct ext2_block_relocate_entry *ent); |
| static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new); |
| static errcode_t bma_delete(ext2_brel brel, blk_t old); |
| static errcode_t bma_free(ext2_brel brel); |
| |
| struct brel_ma { |
| __u32 magic; |
| blk_t max_block; |
| struct ext2_block_relocate_entry *entries; |
| }; |
| |
| errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, |
| ext2_brel *new_brel) |
| { |
| ext2_brel brel = 0; |
| errcode_t retval; |
| struct brel_ma *ma = 0; |
| size_t size; |
| |
| *new_brel = 0; |
| |
| /* |
| * Allocate memory structures |
| */ |
| retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), |
| &brel); |
| if (retval) |
| goto errout; |
| memset(brel, 0, sizeof(struct ext2_block_relocation_table)); |
| |
| retval = ext2fs_get_mem(strlen(name)+1, &brel->name); |
| if (retval) |
| goto errout; |
| strcpy(brel->name, name); |
| |
| retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); |
| if (retval) |
| goto errout; |
| memset(ma, 0, sizeof(struct brel_ma)); |
| brel->priv_data = ma; |
| |
| size = (size_t) (sizeof(struct ext2_block_relocate_entry) * |
| (max_block+1)); |
| retval = ext2fs_get_array(max_block+1, |
| sizeof(struct ext2_block_relocate_entry), &ma->entries); |
| if (retval) |
| goto errout; |
| memset(ma->entries, 0, size); |
| ma->max_block = max_block; |
| |
| /* |
| * Fill in the brel data structure |
| */ |
| brel->put = bma_put; |
| brel->get = bma_get; |
| brel->start_iter = bma_start_iter; |
| brel->next = bma_next; |
| brel->move = bma_move; |
| brel->delete = bma_delete; |
| brel->free = bma_free; |
| |
| *new_brel = brel; |
| return 0; |
| |
| errout: |
| bma_free(brel); |
| return retval; |
| } |
| |
| static errcode_t bma_put(ext2_brel brel, blk_t old, |
| struct ext2_block_relocate_entry *ent) |
| { |
| struct brel_ma *ma; |
| |
| ma = brel->priv_data; |
| if (old > ma->max_block) |
| return EXT2_ET_INVALID_ARGUMENT; |
| ma->entries[(unsigned)old] = *ent; |
| return 0; |
| } |
| |
| static errcode_t bma_get(ext2_brel brel, blk_t old, |
| struct ext2_block_relocate_entry *ent) |
| { |
| struct brel_ma *ma; |
| |
| ma = brel->priv_data; |
| if (old > ma->max_block) |
| return EXT2_ET_INVALID_ARGUMENT; |
| if (ma->entries[(unsigned)old].new == 0) |
| return ENOENT; |
| *ent = ma->entries[old]; |
| return 0; |
| } |
| |
| static errcode_t bma_start_iter(ext2_brel brel) |
| { |
| brel->current = 0; |
| return 0; |
| } |
| |
| static errcode_t bma_next(ext2_brel brel, blk_t *old, |
| struct ext2_block_relocate_entry *ent) |
| { |
| struct brel_ma *ma; |
| |
| ma = brel->priv_data; |
| while (++brel->current < ma->max_block) { |
| if (ma->entries[(unsigned)brel->current].new == 0) |
| continue; |
| *old = brel->current; |
| *ent = ma->entries[(unsigned)brel->current]; |
| return 0; |
| } |
| *old = 0; |
| return 0; |
| } |
| |
| static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new) |
| { |
| struct brel_ma *ma; |
| |
| ma = brel->priv_data; |
| if ((old > ma->max_block) || (new > ma->max_block)) |
| return EXT2_ET_INVALID_ARGUMENT; |
| if (ma->entries[(unsigned)old].new == 0) |
| return ENOENT; |
| ma->entries[(unsigned)new] = ma->entries[old]; |
| ma->entries[(unsigned)old].new = 0; |
| return 0; |
| } |
| |
| static errcode_t bma_delete(ext2_brel brel, blk_t old) |
| { |
| struct brel_ma *ma; |
| |
| ma = brel->priv_data; |
| if (old > ma->max_block) |
| return EXT2_ET_INVALID_ARGUMENT; |
| if (ma->entries[(unsigned)old].new == 0) |
| return ENOENT; |
| ma->entries[(unsigned)old].new = 0; |
| return 0; |
| } |
| |
| static errcode_t bma_free(ext2_brel brel) |
| { |
| struct brel_ma *ma; |
| |
| if (!brel) |
| return 0; |
| |
| ma = brel->priv_data; |
| |
| if (ma) { |
| if (ma->entries) |
| ext2fs_free_mem(&ma->entries); |
| ext2fs_free_mem(&ma); |
| } |
| if (brel->name) |
| ext2fs_free_mem(&brel->name); |
| ext2fs_free_mem(&brel); |
| return 0; |
| } |