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