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