irel_ma.c revision c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4e
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 &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, &irel->name); 82 if (retval) 83 goto errout; 84 strcpy(irel->name, name); 85 86 retval = ext2fs_get_mem(sizeof(struct irel_ma), &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, &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, &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, &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, &ref_ent->refs); 167 if (retval) 168 return retval; 169 } 170 171 ma->entries[(unsigned) old] = *ent; 172 ma->orig_map[(unsigned) ent->orig] = old; 173 return 0; 174} 175 176static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 177 struct ext2_inode_relocate_entry *ent) 178{ 179 struct irel_ma *ma; 180 181 ma = irel->priv_data; 182 if (old > ma->max_inode) 183 return EXT2_ET_INVALID_ARGUMENT; 184 if (ma->entries[(unsigned) old].new == 0) 185 return ENOENT; 186 *ent = ma->entries[(unsigned) old]; 187 return 0; 188} 189 190static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 191 struct ext2_inode_relocate_entry *ent) 192{ 193 struct irel_ma *ma; 194 ext2_ino_t ino; 195 196 ma = irel->priv_data; 197 if (orig > ma->max_inode) 198 return EXT2_ET_INVALID_ARGUMENT; 199 ino = ma->orig_map[(unsigned) orig]; 200 if (ino == 0) 201 return ENOENT; 202 *old = ino; 203 *ent = ma->entries[(unsigned) ino]; 204 return 0; 205} 206 207static errcode_t ima_start_iter(ext2_irel irel) 208{ 209 irel->current = 0; 210 return 0; 211} 212 213static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 214 struct ext2_inode_relocate_entry *ent) 215{ 216 struct irel_ma *ma; 217 218 ma = irel->priv_data; 219 while (++irel->current < ma->max_inode) { 220 if (ma->entries[(unsigned) irel->current].new == 0) 221 continue; 222 *old = irel->current; 223 *ent = ma->entries[(unsigned) irel->current]; 224 return 0; 225 } 226 *old = 0; 227 return 0; 228} 229 230static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 231 struct ext2_inode_reference *ref) 232{ 233 struct irel_ma *ma; 234 size_t size; 235 struct inode_reference_entry *ref_ent; 236 struct ext2_inode_relocate_entry *ent; 237 errcode_t retval; 238 239 ma = irel->priv_data; 240 if (ino > ma->max_inode) 241 return EXT2_ET_INVALID_ARGUMENT; 242 243 ref_ent = ma->ref_entries + (unsigned) ino; 244 ent = ma->entries + (unsigned) ino; 245 246 /* 247 * If the inode reference array doesn't exist, create it. 248 */ 249 if (ref_ent->refs == 0) { 250 size = (size_t) ((sizeof(struct ext2_inode_reference) * 251 ent->max_refs)); 252 retval = ext2fs_get_mem(size, &ref_ent->refs); 253 if (retval) 254 return retval; 255 memset(ref_ent->refs, 0, size); 256 ref_ent->num = 0; 257 } 258 259 if (ref_ent->num >= ent->max_refs) 260 return EXT2_ET_TOO_MANY_REFS; 261 262 ref_ent->refs[(unsigned) ref_ent->num++] = *ref; 263 return 0; 264} 265 266static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) 267{ 268 struct irel_ma *ma; 269 270 ma = irel->priv_data; 271 if (ino > ma->max_inode) 272 return EXT2_ET_INVALID_ARGUMENT; 273 if (ma->entries[(unsigned) ino].new == 0) 274 return ENOENT; 275 ma->ref_current = ino; 276 ma->ref_iter = 0; 277 return 0; 278} 279 280static errcode_t ima_next_ref(ext2_irel irel, 281 struct ext2_inode_reference *ref) 282{ 283 struct irel_ma *ma; 284 struct inode_reference_entry *ref_ent; 285 286 ma = irel->priv_data; 287 288 ref_ent = ma->ref_entries + ma->ref_current; 289 290 if ((ref_ent->refs == NULL) || 291 (ma->ref_iter >= ref_ent->num)) { 292 ref->block = 0; 293 ref->offset = 0; 294 return 0; 295 } 296 *ref = ref_ent->refs[ma->ref_iter++]; 297 return 0; 298} 299 300 301static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) 302{ 303 struct irel_ma *ma; 304 305 ma = irel->priv_data; 306 if ((old > ma->max_inode) || (new > ma->max_inode)) 307 return EXT2_ET_INVALID_ARGUMENT; 308 if (ma->entries[(unsigned) old].new == 0) 309 return ENOENT; 310 311 ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; 312 if (ma->ref_entries[(unsigned) new].refs) 313 ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); 314 ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; 315 316 ma->entries[(unsigned) old].new = 0; 317 ma->ref_entries[(unsigned) old].num = 0; 318 ma->ref_entries[(unsigned) old].refs = 0; 319 320 ma->orig_map[ma->entries[new].orig] = new; 321 return 0; 322} 323 324static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) 325{ 326 struct irel_ma *ma; 327 328 ma = irel->priv_data; 329 if (old > ma->max_inode) 330 return EXT2_ET_INVALID_ARGUMENT; 331 if (ma->entries[(unsigned) old].new == 0) 332 return ENOENT; 333 334 ma->entries[old].new = 0; 335 if (ma->ref_entries[(unsigned) old].refs) 336 ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); 337 ma->orig_map[ma->entries[(unsigned) old].orig] = 0; 338 339 ma->ref_entries[(unsigned) old].num = 0; 340 ma->ref_entries[(unsigned) old].refs = 0; 341 return 0; 342} 343 344static errcode_t ima_free(ext2_irel irel) 345{ 346 struct irel_ma *ma; 347 ext2_ino_t ino; 348 349 if (!irel) 350 return 0; 351 352 ma = irel->priv_data; 353 354 if (ma) { 355 if (ma->orig_map) 356 ext2fs_free_mem(&ma->orig_map); 357 if (ma->entries) 358 ext2fs_free_mem(&ma->entries); 359 if (ma->ref_entries) { 360 for (ino = 0; ino <= ma->max_inode; ino++) { 361 if (ma->ref_entries[(unsigned) ino].refs) 362 ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); 363 } 364 ext2fs_free_mem(&ma->ref_entries); 365 } 366 ext2fs_free_mem(&ma); 367 } 368 if (irel->name) 369 ext2fs_free_mem(&irel->name); 370 ext2fs_free_mem(&irel); 371 return 0; 372} 373