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 29 static errcode_t bma_put(ext2_brel brel, blk_t old, 30 struct ext2_block_relocate_entry *ent); 31 static errcode_t bma_get(ext2_brel brel, blk_t old, 32 struct ext2_block_relocate_entry *ent); 33 static errcode_t bma_start_iter(ext2_brel brel); 34 static errcode_t bma_next(ext2_brel brel, blk_t *old, 35 struct ext2_block_relocate_entry *ent); 36 static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new); 37 static errcode_t bma_delete(ext2_brel brel, blk_t old); 38 static errcode_t bma_free(ext2_brel brel); 39 40 struct brel_ma { 41 __u32 magic; 42 blk_t max_block; 43 struct ext2_block_relocate_entry *entries; 44 }; 45 46 errcode_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 99 errout: 100 bma_free(brel); 101 return retval; 102 } 103 104 static 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 116 static 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 130 static errcode_t bma_start_iter(ext2_brel brel) 131 { 132 brel->current = 0; 133 return 0; 134 } 135 136 static 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 153 static 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 167 static 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 180 static 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