Home | History | Annotate | Download | only in ext2fs
      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