source: MondoRescue/branches/stable/mindi-busybox/e2fsprogs/ext2fs/irel_ma.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 8.6 KB
Line 
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    ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
313    ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
314
315    ma->entries[(unsigned) old].new = 0;
316    ma->ref_entries[(unsigned) old].num = 0;
317    ma->ref_entries[(unsigned) old].refs = 0;
318
319    ma->orig_map[ma->entries[new].orig] = new;
320    return 0;
321}
322
323static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
324{
325    struct irel_ma  *ma;
326
327    ma = irel->priv_data;
328    if (old > ma->max_inode)
329        return EXT2_ET_INVALID_ARGUMENT;
330    if (ma->entries[(unsigned) old].new == 0)
331        return ENOENT;
332
333    ma->entries[old].new = 0;
334    ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
335    ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
336
337    ma->ref_entries[(unsigned) old].num = 0;
338    ma->ref_entries[(unsigned) old].refs = 0;
339    return 0;
340}
341
342static errcode_t ima_free(ext2_irel irel)
343{
344    struct irel_ma  *ma;
345    ext2_ino_t  ino;
346
347    if (!irel)
348        return 0;
349
350    ma = irel->priv_data;
351
352    if (ma) {
353        ext2fs_free_mem(&ma->orig_map);
354        ext2fs_free_mem(&ma->entries);
355        if (ma->ref_entries) {
356            for (ino = 0; ino <= ma->max_inode; ino++) {
357                ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
358            }
359            ext2fs_free_mem(&ma->ref_entries);
360        }
361        ext2fs_free_mem(&ma);
362    }
363    ext2fs_free_mem(&irel->name);
364    ext2fs_free_mem(&irel);
365    return 0;
366}
Note: See TracBrowser for help on using the repository browser.