1/* 2 * brel_ma.c 3 * 4 * Copyright (C) 1996, 1997 Theodore Ts'o. 5 * 6 * TODO: rewrite to not use a direct array!!! (Fortunately this 7 * module isn't really used yet.) 8 * 9 * %Begin-Header% 10 * This file may be redistributed under the terms of the GNU Public 11 * License. 12 * %End-Header% 13 */ 14 15#include <fcntl.h> 16#include <stdio.h> 17#include <string.h> 18#if HAVE_UNISTD_H 19#include <unistd.h> 20#endif 21#if HAVE_ERRNO_H 22#include <errno.h> 23#endif 24 25#include "ext2_fs.h" 26#include "ext2fs.h" 27#include "brel.h" 28 29static errcode_t bma_put(ext2_brel brel, blk_t old, 30 struct ext2_block_relocate_entry *ent); 31static errcode_t bma_get(ext2_brel brel, blk_t old, 32 struct ext2_block_relocate_entry *ent); 33static errcode_t bma_start_iter(ext2_brel brel); 34static errcode_t bma_next(ext2_brel brel, blk_t *old, 35 struct ext2_block_relocate_entry *ent); 36static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new); 37static errcode_t bma_delete(ext2_brel brel, blk_t old); 38static errcode_t bma_free(ext2_brel brel); 39 40struct brel_ma { 41 __u32 magic; 42 blk_t max_block; 43 struct ext2_block_relocate_entry *entries; 44}; 45 46errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, 47 ext2_brel *new_brel) 48{ 49 ext2_brel brel = 0; 50 errcode_t retval; 51 struct brel_ma *ma = 0; 52 size_t size; 53 54 *new_brel = 0; 55 56 /* 57 * Allocate memory structures 58 */ 59 retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), 60 &brel); 61 if (retval) 62 goto errout; 63 memset(brel, 0, sizeof(struct ext2_block_relocation_table)); 64 65 retval = ext2fs_get_mem(strlen(name)+1, &brel->name); 66 if (retval) 67 goto errout; 68 strcpy(brel->name, name); 69 70 retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); 71 if (retval) 72 goto errout; 73 memset(ma, 0, sizeof(struct brel_ma)); 74 brel->priv_data = ma; 75 76 size = (size_t) (sizeof(struct ext2_block_relocate_entry) * 77 (max_block+1)); 78 retval = ext2fs_get_array(max_block+1, 79 sizeof(struct ext2_block_relocate_entry), &ma->entries); 80 if (retval) 81 goto errout; 82 memset(ma->entries, 0, size); 83 ma->max_block = max_block; 84 85 /* 86 * Fill in the brel data structure 87 */ 88 brel->put = bma_put; 89 brel->get = bma_get; 90 brel->start_iter = bma_start_iter; 91 brel->next = bma_next; 92 brel->move = bma_move; 93 brel->delete = bma_delete; 94 brel->free = bma_free; 95 96 *new_brel = brel; 97 return 0; 98 99errout: 100 bma_free(brel); 101 return retval; 102} 103 104static errcode_t bma_put(ext2_brel brel, blk_t old, 105 struct ext2_block_relocate_entry *ent) 106{ 107 struct brel_ma *ma; 108 109 ma = brel->priv_data; 110 if (old > ma->max_block) 111 return EXT2_ET_INVALID_ARGUMENT; 112 ma->entries[(unsigned)old] = *ent; 113 return 0; 114} 115 116static errcode_t bma_get(ext2_brel brel, blk_t old, 117 struct ext2_block_relocate_entry *ent) 118{ 119 struct brel_ma *ma; 120 121 ma = brel->priv_data; 122 if (old > ma->max_block) 123 return EXT2_ET_INVALID_ARGUMENT; 124 if (ma->entries[(unsigned)old].new == 0) 125 return ENOENT; 126 *ent = ma->entries[old]; 127 return 0; 128} 129 130static errcode_t bma_start_iter(ext2_brel brel) 131{ 132 brel->current = 0; 133 return 0; 134} 135 136static errcode_t bma_next(ext2_brel brel, blk_t *old, 137 struct ext2_block_relocate_entry *ent) 138{ 139 struct brel_ma *ma; 140 141 ma = brel->priv_data; 142 while (++brel->current < ma->max_block) { 143 if (ma->entries[(unsigned)brel->current].new == 0) 144 continue; 145 *old = brel->current; 146 *ent = ma->entries[(unsigned)brel->current]; 147 return 0; 148 } 149 *old = 0; 150 return 0; 151} 152 153static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new) 154{ 155 struct brel_ma *ma; 156 157 ma = brel->priv_data; 158 if ((old > ma->max_block) || (new > ma->max_block)) 159 return EXT2_ET_INVALID_ARGUMENT; 160 if (ma->entries[(unsigned)old].new == 0) 161 return ENOENT; 162 ma->entries[(unsigned)new] = ma->entries[old]; 163 ma->entries[(unsigned)old].new = 0; 164 return 0; 165} 166 167static errcode_t bma_delete(ext2_brel brel, blk_t old) 168{ 169 struct brel_ma *ma; 170 171 ma = brel->priv_data; 172 if (old > ma->max_block) 173 return EXT2_ET_INVALID_ARGUMENT; 174 if (ma->entries[(unsigned)old].new == 0) 175 return ENOENT; 176 ma->entries[(unsigned)old].new = 0; 177 return 0; 178} 179 180static errcode_t bma_free(ext2_brel brel) 181{ 182 struct brel_ma *ma; 183 184 if (!brel) 185 return 0; 186 187 ma = brel->priv_data; 188 189 if (ma) { 190 if (ma->entries) 191 ext2fs_free_mem(&ma->entries); 192 ext2fs_free_mem(&ma); 193 } 194 if (brel->name) 195 ext2fs_free_mem(&brel->name); 196 ext2fs_free_mem(&brel); 197 return 0; 198} 199