irel_ma.c revision 9f8046fc6dfc13eee2f5c363214e60b533872cac
1/* 2 * irel_ma.c 3 * 4 * Copyright (C) 1996, 1997 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12#include <fcntl.h> 13#include <stdio.h> 14#include <string.h> 15#if HAVE_UNISTD_H 16#include <unistd.h> 17#endif 18#if HAVE_ERRNO_H 19#include <errno.h> 20#endif 21 22#include "ext2_fs.h" 23#include "ext2fs.h" 24#include "irel.h" 25 26static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, 27 struct ext2_inode_relocate_entry *ent); 28static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 29 struct ext2_inode_relocate_entry *ent); 30static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 31 struct ext2_inode_relocate_entry *ent); 32static errcode_t ima_start_iter(ext2_irel irel); 33static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 34 struct ext2_inode_relocate_entry *ent); 35static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 36 struct ext2_inode_reference *ref); 37static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); 38static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); 39static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); 40static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); 41static errcode_t ima_free(ext2_irel irel); 42 43/* 44 * This data structure stores the array of inode references; there is 45 * a structure for each inode. 46 */ 47struct inode_reference_entry { 48 __u16 num; 49 struct ext2_inode_reference *refs; 50}; 51 52struct irel_ma { 53 __u32 magic; 54 ext2_ino_t max_inode; 55 ext2_ino_t ref_current; 56 int ref_iter; 57 ext2_ino_t *orig_map; 58 struct ext2_inode_relocate_entry *entries; 59 struct inode_reference_entry *ref_entries; 60}; 61 62errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, 63 ext2_irel *new_irel) 64{ 65 ext2_irel irel = 0; 66 errcode_t retval; 67 struct irel_ma *ma = 0; 68 size_t size; 69 70 *new_irel = 0; 71 72 /* 73 * Allocate memory structures 74 */ 75 retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table), 76 (void **) &irel); 77 if (retval) 78 goto errout; 79 memset(irel, 0, sizeof(struct ext2_inode_relocation_table)); 80 81 retval = ext2fs_get_mem(strlen(name)+1, (void **) &irel->name); 82 if (retval) 83 goto errout; 84 strcpy(irel->name, name); 85 86 retval = ext2fs_get_mem(sizeof(struct irel_ma), (void **) &ma); 87 if (retval) 88 goto errout; 89 memset(ma, 0, sizeof(struct irel_ma)); 90 irel->priv_data = ma; 91 92 size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1)); 93 retval = ext2fs_get_mem(size, (void **) &ma->orig_map); 94 if (retval) 95 goto errout; 96 memset(ma->orig_map, 0, size); 97 98 size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * 99 (max_inode+1)); 100 retval = ext2fs_get_mem(size, (void **) &ma->entries); 101 if (retval) 102 goto errout; 103 memset(ma->entries, 0, size); 104 105 size = (size_t) (sizeof(struct inode_reference_entry) * 106 (max_inode+1)); 107 retval = ext2fs_get_mem(size, (void **) &ma->ref_entries); 108 if (retval) 109 goto errout; 110 memset(ma->ref_entries, 0, size); 111 ma->max_inode = max_inode; 112 113 /* 114 * Fill in the irel data structure 115 */ 116 irel->put = ima_put; 117 irel->get = ima_get; 118 irel->get_by_orig = ima_get_by_orig; 119 irel->start_iter = ima_start_iter; 120 irel->next = ima_next; 121 irel->add_ref = ima_add_ref; 122 irel->start_iter_ref = ima_start_iter_ref; 123 irel->next_ref = ima_next_ref; 124 irel->move = ima_move; 125 irel->delete = ima_delete; 126 irel->free = ima_free; 127 128 *new_irel = irel; 129 return 0; 130 131errout: 132 ima_free(irel); 133 return retval; 134} 135 136static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, 137 struct ext2_inode_relocate_entry *ent) 138{ 139 struct inode_reference_entry *ref_ent; 140 struct irel_ma *ma; 141 errcode_t retval; 142 size_t size, old_size; 143 144 ma = irel->priv_data; 145 if (old > ma->max_inode) 146 return EXT2_ET_INVALID_ARGUMENT; 147 148 /* 149 * Force the orig field to the correct value; the application 150 * program shouldn't be messing with this field. 151 */ 152 if (ma->entries[(unsigned) old].new == 0) 153 ent->orig = old; 154 else 155 ent->orig = ma->entries[(unsigned) old].orig; 156 157 /* 158 * If max_refs has changed, reallocate the refs array 159 */ 160 ref_ent = ma->ref_entries + (unsigned) old; 161 if (ref_ent->refs && ent->max_refs != 162 ma->entries[(unsigned) old].max_refs) { 163 size = (sizeof(struct ext2_inode_reference) * ent->max_refs); 164 old_size = (sizeof(struct ext2_inode_reference) * 165 ma->entries[(unsigned) old].max_refs); 166 retval = ext2fs_resize_mem(old_size, size, 167 (void **) &ref_ent->refs); 168 if (retval) 169 return retval; 170 } 171 172 ma->entries[(unsigned) old] = *ent; 173 ma->orig_map[(unsigned) ent->orig] = old; 174 return 0; 175} 176 177static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 178 struct ext2_inode_relocate_entry *ent) 179{ 180 struct irel_ma *ma; 181 182 ma = irel->priv_data; 183 if (old > ma->max_inode) 184 return EXT2_ET_INVALID_ARGUMENT; 185 if (ma->entries[(unsigned) old].new == 0) 186 return ENOENT; 187 *ent = ma->entries[(unsigned) old]; 188 return 0; 189} 190 191static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 192 struct ext2_inode_relocate_entry *ent) 193{ 194 struct irel_ma *ma; 195 ext2_ino_t ino; 196 197 ma = irel->priv_data; 198 if (orig > ma->max_inode) 199 return EXT2_ET_INVALID_ARGUMENT; 200 ino = ma->orig_map[(unsigned) orig]; 201 if (ino == 0) 202 return ENOENT; 203 *old = ino; 204 *ent = ma->entries[(unsigned) ino]; 205 return 0; 206} 207 208static errcode_t ima_start_iter(ext2_irel irel) 209{ 210 irel->current = 0; 211 return 0; 212} 213 214static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 215 struct ext2_inode_relocate_entry *ent) 216{ 217 struct irel_ma *ma; 218 219 ma = irel->priv_data; 220 while (++irel->current < ma->max_inode) { 221 if (ma->entries[(unsigned) irel->current].new == 0) 222 continue; 223 *old = irel->current; 224 *ent = ma->entries[(unsigned) irel->current]; 225 return 0; 226 } 227 *old = 0; 228 return 0; 229} 230 231static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 232 struct ext2_inode_reference *ref) 233{ 234 struct irel_ma *ma; 235 size_t size; 236 struct inode_reference_entry *ref_ent; 237 struct ext2_inode_relocate_entry *ent; 238 errcode_t retval; 239 240 ma = irel->priv_data; 241 if (ino > ma->max_inode) 242 return EXT2_ET_INVALID_ARGUMENT; 243 244 ref_ent = ma->ref_entries + (unsigned) ino; 245 ent = ma->entries + (unsigned) ino; 246 247 /* 248 * If the inode reference array doesn't exist, create it. 249 */ 250 if (ref_ent->refs == 0) { 251 size = (size_t) ((sizeof(struct ext2_inode_reference) * 252 ent->max_refs)); 253 retval = ext2fs_get_mem(size, (void **) &ref_ent->refs); 254 if (retval) 255 return retval; 256 memset(ref_ent->refs, 0, size); 257 ref_ent->num = 0; 258 } 259 260 if (ref_ent->num >= ent->max_refs) 261 return EXT2_ET_TOO_MANY_REFS; 262 263 ref_ent->refs[(unsigned) ref_ent->num++] = *ref; 264 return 0; 265} 266 267static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) 268{ 269 struct irel_ma *ma; 270 271 ma = irel->priv_data; 272 if (ino > ma->max_inode) 273 return EXT2_ET_INVALID_ARGUMENT; 274 if (ma->entries[(unsigned) ino].new == 0) 275 return ENOENT; 276 ma->ref_current = ino; 277 ma->ref_iter = 0; 278 return 0; 279} 280 281static errcode_t ima_next_ref(ext2_irel irel, 282 struct ext2_inode_reference *ref) 283{ 284 struct irel_ma *ma; 285 struct inode_reference_entry *ref_ent; 286 287 ma = irel->priv_data; 288 289 ref_ent = ma->ref_entries + ma->ref_current; 290 291 if ((ref_ent->refs == NULL) || 292 (ma->ref_iter >= ref_ent->num)) { 293 ref->block = 0; 294 ref->offset = 0; 295 return 0; 296 } 297 *ref = ref_ent->refs[ma->ref_iter++]; 298 return 0; 299} 300 301 302static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) 303{ 304 struct irel_ma *ma; 305 306 ma = irel->priv_data; 307 if ((old > ma->max_inode) || (new > ma->max_inode)) 308 return EXT2_ET_INVALID_ARGUMENT; 309 if (ma->entries[(unsigned) old].new == 0) 310 return ENOENT; 311 312 ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; 313 if (ma->ref_entries[(unsigned) new].refs) 314 ext2fs_free_mem((void **) &ma->ref_entries[(unsigned) new].refs); 315 ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; 316 317 ma->entries[(unsigned) old].new = 0; 318 ma->ref_entries[(unsigned) old].num = 0; 319 ma->ref_entries[(unsigned) old].refs = 0; 320 321 ma->orig_map[ma->entries[new].orig] = new; 322 return 0; 323} 324 325static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) 326{ 327 struct irel_ma *ma; 328 329 ma = irel->priv_data; 330 if (old > ma->max_inode) 331 return EXT2_ET_INVALID_ARGUMENT; 332 if (ma->entries[(unsigned) old].new == 0) 333 return ENOENT; 334 335 ma->entries[old].new = 0; 336 if (ma->ref_entries[(unsigned) old].refs) 337 ext2fs_free_mem((void **) &ma->ref_entries[(unsigned) old].refs); 338 ma->orig_map[ma->entries[(unsigned) old].orig] = 0; 339 340 ma->ref_entries[(unsigned) old].num = 0; 341 ma->ref_entries[(unsigned) old].refs = 0; 342 return 0; 343} 344 345static errcode_t ima_free(ext2_irel irel) 346{ 347 struct irel_ma *ma; 348 ext2_ino_t ino; 349 350 if (!irel) 351 return 0; 352 353 ma = irel->priv_data; 354 355 if (ma) { 356 if (ma->orig_map) 357 ext2fs_free_mem((void **) &ma->orig_map); 358 if (ma->entries) 359 ext2fs_free_mem((void **) &ma->entries); 360 if (ma->ref_entries) { 361 for (ino = 0; ino <= ma->max_inode; ino++) { 362 if (ma->ref_entries[(unsigned) ino].refs) 363 ext2fs_free_mem((void **) &ma->ref_entries[(unsigned) ino].refs); 364 } 365 ext2fs_free_mem((void **) &ma->ref_entries); 366 } 367 ext2fs_free_mem((void **) &ma); 368 } 369 if (irel->name) 370 ext2fs_free_mem((void **) &irel->name); 371 ext2fs_free_mem((void **) &irel); 372 return 0; 373} 374