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 Library 8 * General Public License, version 2. 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 26 static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, 27 struct ext2_inode_relocate_entry *ent); 28 static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 29 struct ext2_inode_relocate_entry *ent); 30 static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 31 struct ext2_inode_relocate_entry *ent); 32 static errcode_t ima_start_iter(ext2_irel irel); 33 static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 34 struct ext2_inode_relocate_entry *ent); 35 static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 36 struct ext2_inode_reference *ref); 37 static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); 38 static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); 39 static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); 40 static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); 41 static 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 */ 47 struct inode_reference_entry { 48 __u16 num; 49 struct ext2_inode_reference *refs; 50 }; 51 52 struct 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 62 errcode_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_array(max_inode+1, sizeof(ext2_ino_t), 94 &ma->orig_map); 95 if (retval) 96 goto errout; 97 memset(ma->orig_map, 0, size); 98 99 size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * 100 (max_inode+1)); 101 retval = ext2fs_get_array((max_inode+1, 102 sizeof(struct ext2_inode_relocate_entry), &ma->entries); 103 if (retval) 104 goto errout; 105 memset(ma->entries, 0, size); 106 107 size = (size_t) (sizeof(struct inode_reference_entry) * 108 (max_inode+1)); 109 retval = ext2fs_get_mem(max_inode+1, 110 sizeof(struct inode_reference_entry), &ma->ref_entries); 111 if (retval) 112 goto errout; 113 memset(ma->ref_entries, 0, size); 114 ma->max_inode = max_inode; 115 116 /* 117 * Fill in the irel data structure 118 */ 119 irel->put = ima_put; 120 irel->get = ima_get; 121 irel->get_by_orig = ima_get_by_orig; 122 irel->start_iter = ima_start_iter; 123 irel->next = ima_next; 124 irel->add_ref = ima_add_ref; 125 irel->start_iter_ref = ima_start_iter_ref; 126 irel->next_ref = ima_next_ref; 127 irel->move = ima_move; 128 irel->delete = ima_delete; 129 irel->free = ima_free; 130 131 *new_irel = irel; 132 return 0; 133 134 errout: 135 ima_free(irel); 136 return retval; 137 } 138 139 static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, 140 struct ext2_inode_relocate_entry *ent) 141 { 142 struct inode_reference_entry *ref_ent; 143 struct irel_ma *ma; 144 errcode_t retval; 145 size_t size, old_size; 146 147 ma = irel->priv_data; 148 if (old > ma->max_inode) 149 return EXT2_ET_INVALID_ARGUMENT; 150 151 /* 152 * Force the orig field to the correct value; the application 153 * program shouldn't be messing with this field. 154 */ 155 if (ma->entries[(unsigned) old].new == 0) 156 ent->orig = old; 157 else 158 ent->orig = ma->entries[(unsigned) old].orig; 159 160 /* 161 * If max_refs has changed, reallocate the refs array 162 */ 163 ref_ent = ma->ref_entries + (unsigned) old; 164 if (ref_ent->refs && ent->max_refs != 165 ma->entries[(unsigned) old].max_refs) { 166 size = (sizeof(struct ext2_inode_reference) * ent->max_refs); 167 old_size = (sizeof(struct ext2_inode_reference) * 168 ma->entries[(unsigned) old].max_refs); 169 retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs); 170 if (retval) 171 return retval; 172 } 173 174 ma->entries[(unsigned) old] = *ent; 175 ma->orig_map[(unsigned) ent->orig] = old; 176 return 0; 177 } 178 179 static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 180 struct ext2_inode_relocate_entry *ent) 181 { 182 struct irel_ma *ma; 183 184 ma = irel->priv_data; 185 if (old > ma->max_inode) 186 return EXT2_ET_INVALID_ARGUMENT; 187 if (ma->entries[(unsigned) old].new == 0) 188 return ENOENT; 189 *ent = ma->entries[(unsigned) old]; 190 return 0; 191 } 192 193 static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 194 struct ext2_inode_relocate_entry *ent) 195 { 196 struct irel_ma *ma; 197 ext2_ino_t ino; 198 199 ma = irel->priv_data; 200 if (orig > ma->max_inode) 201 return EXT2_ET_INVALID_ARGUMENT; 202 ino = ma->orig_map[(unsigned) orig]; 203 if (ino == 0) 204 return ENOENT; 205 *old = ino; 206 *ent = ma->entries[(unsigned) ino]; 207 return 0; 208 } 209 210 static errcode_t ima_start_iter(ext2_irel irel) 211 { 212 irel->current = 0; 213 return 0; 214 } 215 216 static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 217 struct ext2_inode_relocate_entry *ent) 218 { 219 struct irel_ma *ma; 220 221 ma = irel->priv_data; 222 while (++irel->current < ma->max_inode) { 223 if (ma->entries[(unsigned) irel->current].new == 0) 224 continue; 225 *old = irel->current; 226 *ent = ma->entries[(unsigned) irel->current]; 227 return 0; 228 } 229 *old = 0; 230 return 0; 231 } 232 233 static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 234 struct ext2_inode_reference *ref) 235 { 236 struct irel_ma *ma; 237 size_t size; 238 struct inode_reference_entry *ref_ent; 239 struct ext2_inode_relocate_entry *ent; 240 errcode_t retval; 241 242 ma = irel->priv_data; 243 if (ino > ma->max_inode) 244 return EXT2_ET_INVALID_ARGUMENT; 245 246 ref_ent = ma->ref_entries + (unsigned) ino; 247 ent = ma->entries + (unsigned) ino; 248 249 /* 250 * If the inode reference array doesn't exist, create it. 251 */ 252 if (ref_ent->refs == 0) { 253 size = (size_t) ((sizeof(struct ext2_inode_reference) * 254 ent->max_refs)); 255 retval = ext2fs_get_array(ent->max_refs, 256 sizeof(struct ext2_inode_reference), &ref_ent->refs); 257 if (retval) 258 return retval; 259 memset(ref_ent->refs, 0, size); 260 ref_ent->num = 0; 261 } 262 263 if (ref_ent->num >= ent->max_refs) 264 return EXT2_ET_TOO_MANY_REFS; 265 266 ref_ent->refs[(unsigned) ref_ent->num++] = *ref; 267 return 0; 268 } 269 270 static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) 271 { 272 struct irel_ma *ma; 273 274 ma = irel->priv_data; 275 if (ino > ma->max_inode) 276 return EXT2_ET_INVALID_ARGUMENT; 277 if (ma->entries[(unsigned) ino].new == 0) 278 return ENOENT; 279 ma->ref_current = ino; 280 ma->ref_iter = 0; 281 return 0; 282 } 283 284 static errcode_t ima_next_ref(ext2_irel irel, 285 struct ext2_inode_reference *ref) 286 { 287 struct irel_ma *ma; 288 struct inode_reference_entry *ref_ent; 289 290 ma = irel->priv_data; 291 292 ref_ent = ma->ref_entries + ma->ref_current; 293 294 if ((ref_ent->refs == NULL) || 295 (ma->ref_iter >= ref_ent->num)) { 296 ref->block = 0; 297 ref->offset = 0; 298 return 0; 299 } 300 *ref = ref_ent->refs[ma->ref_iter++]; 301 return 0; 302 } 303 304 305 static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) 306 { 307 struct irel_ma *ma; 308 309 ma = irel->priv_data; 310 if ((old > ma->max_inode) || (new > ma->max_inode)) 311 return EXT2_ET_INVALID_ARGUMENT; 312 if (ma->entries[(unsigned) old].new == 0) 313 return ENOENT; 314 315 ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; 316 if (ma->ref_entries[(unsigned) new].refs) 317 ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); 318 ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; 319 320 ma->entries[(unsigned) old].new = 0; 321 ma->ref_entries[(unsigned) old].num = 0; 322 ma->ref_entries[(unsigned) old].refs = 0; 323 324 ma->orig_map[ma->entries[new].orig] = new; 325 return 0; 326 } 327 328 static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) 329 { 330 struct irel_ma *ma; 331 332 ma = irel->priv_data; 333 if (old > ma->max_inode) 334 return EXT2_ET_INVALID_ARGUMENT; 335 if (ma->entries[(unsigned) old].new == 0) 336 return ENOENT; 337 338 ma->entries[old].new = 0; 339 if (ma->ref_entries[(unsigned) old].refs) 340 ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); 341 ma->orig_map[ma->entries[(unsigned) old].orig] = 0; 342 343 ma->ref_entries[(unsigned) old].num = 0; 344 ma->ref_entries[(unsigned) old].refs = 0; 345 return 0; 346 } 347 348 static errcode_t ima_free(ext2_irel irel) 349 { 350 struct irel_ma *ma; 351 ext2_ino_t ino; 352 353 if (!irel) 354 return 0; 355 356 ma = irel->priv_data; 357 358 if (ma) { 359 if (ma->orig_map) 360 ext2fs_free_mem(&ma->orig_map); 361 if (ma->entries) 362 ext2fs_free_mem(&ma->entries); 363 if (ma->ref_entries) { 364 for (ino = 0; ino <= ma->max_inode; ino++) { 365 if (ma->ref_entries[(unsigned) ino].refs) 366 ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); 367 } 368 ext2fs_free_mem(&ma->ref_entries); 369 } 370 ext2fs_free_mem(&ma); 371 } 372 if (irel->name) 373 ext2fs_free_mem(&irel->name); 374 ext2fs_free_mem(&irel); 375 return 0; 376 } 377