1 /* vi: set sw=4 ts=4: */
5 * Copyright (C) 1996, 1997 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Public
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
);
45 * This data structure stores the array of inode references; there is
46 * a structure for each inode.
48 struct inode_reference_entry
{
50 struct ext2_inode_reference
*refs
;
56 ext2_ino_t ref_current
;
59 struct ext2_inode_relocate_entry
*entries
;
60 struct inode_reference_entry
*ref_entries
;
63 errcode_t
ext2fs_irel_memarray_create(char *name
, ext2_ino_t max_inode
,
68 struct irel_ma
*ma
= 0;
74 * Allocate memory structures
76 retval
= ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table
),
80 memset(irel
, 0, sizeof(struct ext2_inode_relocation_table
));
82 retval
= ext2fs_get_mem(strlen(name
)+1, &irel
->name
);
85 strcpy(irel
->name
, name
);
87 retval
= ext2fs_get_mem(sizeof(struct irel_ma
), &ma
);
90 memset(ma
, 0, sizeof(struct irel_ma
));
93 size
= (size_t) (sizeof(ext2_ino_t
) * (max_inode
+1));
94 retval
= ext2fs_get_mem(size
, &ma
->orig_map
);
97 memset(ma
->orig_map
, 0, size
);
99 size
= (size_t) (sizeof(struct ext2_inode_relocate_entry
) *
101 retval
= ext2fs_get_mem(size
, &ma
->entries
);
104 memset(ma
->entries
, 0, size
);
106 size
= (size_t) (sizeof(struct inode_reference_entry
) *
108 retval
= ext2fs_get_mem(size
, &ma
->ref_entries
);
111 memset(ma
->ref_entries
, 0, size
);
112 ma
->max_inode
= max_inode
;
115 * Fill in the irel data structure
119 irel
->get_by_orig
= ima_get_by_orig
;
120 irel
->start_iter
= ima_start_iter
;
121 irel
->next
= ima_next
;
122 irel
->add_ref
= ima_add_ref
;
123 irel
->start_iter_ref
= ima_start_iter_ref
;
124 irel
->next_ref
= ima_next_ref
;
125 irel
->move
= ima_move
;
126 irel
->delete = ima_delete
;
127 irel
->free
= ima_free
;
137 static errcode_t
ima_put(ext2_irel irel
, ext2_ino_t old
,
138 struct ext2_inode_relocate_entry
*ent
)
140 struct inode_reference_entry
*ref_ent
;
143 size_t size
, old_size
;
145 ma
= irel
->priv_data
;
146 if (old
> ma
->max_inode
)
147 return EXT2_ET_INVALID_ARGUMENT
;
150 * Force the orig field to the correct value; the application
151 * program shouldn't be messing with this field.
153 if (ma
->entries
[(unsigned) old
].new == 0)
156 ent
->orig
= ma
->entries
[(unsigned) old
].orig
;
159 * If max_refs has changed, reallocate the refs array
161 ref_ent
= ma
->ref_entries
+ (unsigned) old
;
162 if (ref_ent
->refs
&& ent
->max_refs
!=
163 ma
->entries
[(unsigned) old
].max_refs
) {
164 size
= (sizeof(struct ext2_inode_reference
) * ent
->max_refs
);
165 old_size
= (sizeof(struct ext2_inode_reference
) *
166 ma
->entries
[(unsigned) old
].max_refs
);
167 retval
= ext2fs_resize_mem(old_size
, size
, &ref_ent
->refs
);
172 ma
->entries
[(unsigned) old
] = *ent
;
173 ma
->orig_map
[(unsigned) ent
->orig
] = old
;
177 static errcode_t
ima_get(ext2_irel irel
, ext2_ino_t old
,
178 struct ext2_inode_relocate_entry
*ent
)
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)
187 *ent
= ma
->entries
[(unsigned) old
];
191 static errcode_t
ima_get_by_orig(ext2_irel irel
, ext2_ino_t orig
, ext2_ino_t
*old
,
192 struct ext2_inode_relocate_entry
*ent
)
197 ma
= irel
->priv_data
;
198 if (orig
> ma
->max_inode
)
199 return EXT2_ET_INVALID_ARGUMENT
;
200 ino
= ma
->orig_map
[(unsigned) orig
];
204 *ent
= ma
->entries
[(unsigned) ino
];
208 static errcode_t
ima_start_iter(ext2_irel irel
)
214 static errcode_t
ima_next(ext2_irel irel
, ext2_ino_t
*old
,
215 struct ext2_inode_relocate_entry
*ent
)
219 ma
= irel
->priv_data
;
220 while (++irel
->current
< ma
->max_inode
) {
221 if (ma
->entries
[(unsigned) irel
->current
].new == 0)
223 *old
= irel
->current
;
224 *ent
= ma
->entries
[(unsigned) irel
->current
];
231 static errcode_t
ima_add_ref(ext2_irel irel
, ext2_ino_t ino
,
232 struct ext2_inode_reference
*ref
)
236 struct inode_reference_entry
*ref_ent
;
237 struct ext2_inode_relocate_entry
*ent
;
240 ma
= irel
->priv_data
;
241 if (ino
> ma
->max_inode
)
242 return EXT2_ET_INVALID_ARGUMENT
;
244 ref_ent
= ma
->ref_entries
+ (unsigned) ino
;
245 ent
= ma
->entries
+ (unsigned) ino
;
248 * If the inode reference array doesn't exist, create it.
250 if (ref_ent
->refs
== 0) {
251 size
= (size_t) ((sizeof(struct ext2_inode_reference
) *
253 retval
= ext2fs_get_mem(size
, &ref_ent
->refs
);
256 memset(ref_ent
->refs
, 0, size
);
260 if (ref_ent
->num
>= ent
->max_refs
)
261 return EXT2_ET_TOO_MANY_REFS
;
263 ref_ent
->refs
[(unsigned) ref_ent
->num
++] = *ref
;
267 static errcode_t
ima_start_iter_ref(ext2_irel irel
, ext2_ino_t ino
)
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)
276 ma
->ref_current
= ino
;
281 static errcode_t
ima_next_ref(ext2_irel irel
,
282 struct ext2_inode_reference
*ref
)
285 struct inode_reference_entry
*ref_ent
;
287 ma
= irel
->priv_data
;
289 ref_ent
= ma
->ref_entries
+ ma
->ref_current
;
291 if ((ref_ent
->refs
== NULL
) ||
292 (ma
->ref_iter
>= ref_ent
->num
)) {
297 *ref
= ref_ent
->refs
[ma
->ref_iter
++];
302 static errcode_t
ima_move(ext2_irel irel
, ext2_ino_t old
, ext2_ino_t
new)
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)
312 ma
->entries
[(unsigned) new] = ma
->entries
[(unsigned) old
];
313 ext2fs_free_mem(&ma
->ref_entries
[(unsigned) new].refs
);
314 ma
->ref_entries
[(unsigned) new] = ma
->ref_entries
[(unsigned) old
];
316 ma
->entries
[(unsigned) old
].new = 0;
317 ma
->ref_entries
[(unsigned) old
].num
= 0;
318 ma
->ref_entries
[(unsigned) old
].refs
= 0;
320 ma
->orig_map
[ma
->entries
[new].orig
] = new;
324 static errcode_t
ima_delete(ext2_irel irel
, ext2_ino_t old
)
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)
334 ma
->entries
[old
].new = 0;
335 ext2fs_free_mem(&ma
->ref_entries
[(unsigned) old
].refs
);
336 ma
->orig_map
[ma
->entries
[(unsigned) old
].orig
] = 0;
338 ma
->ref_entries
[(unsigned) old
].num
= 0;
339 ma
->ref_entries
[(unsigned) old
].refs
= 0;
343 static errcode_t
ima_free(ext2_irel irel
)
351 ma
= irel
->priv_data
;
354 ext2fs_free_mem(&ma
->orig_map
);
355 ext2fs_free_mem(&ma
->entries
);
356 if (ma
->ref_entries
) {
357 for (ino
= 0; ino
<= ma
->max_inode
; ino
++) {
358 ext2fs_free_mem(&ma
->ref_entries
[(unsigned) ino
].refs
);
360 ext2fs_free_mem(&ma
->ref_entries
);
362 ext2fs_free_mem(&ma
);
364 ext2fs_free_mem(&irel
->name
);
365 ext2fs_free_mem(&irel
);