Whamcloud - gitweb
valid_blk.c (ext2fs_inode_has_valid_blocks): Fix bug which
[tools/e2fsprogs.git] / lib / ext2fs / brel_ma.c
1 /*
2  * brel_ma.c
3  * 
4  * Copyright (C) 1996, 1997 Theodore Ts'o.
5  *
6  * TODO: rewrite to not use a direct array!!!  (Fortunately this
7  * module isn't really used yet.)
8  *
9  * %Begin-Header%
10  * This file may be redistributed under the terms of the GNU Public
11  * License.
12  * %End-Header%
13  */
14
15 #include <fcntl.h>
16 #include <stdio.h>
17 #include <string.h>
18 #if HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #if HAVE_ERRNO_H
22 #include <errno.h>
23 #endif
24
25 #include "ext2_fs.h"
26 #include "ext2fs.h"
27 #include "brel.h"
28
29 static errcode_t bma_put(ext2_brel brel, blk_t old,
30                         struct ext2_block_relocate_entry *ent);
31 static errcode_t bma_get(ext2_brel brel, blk_t old,
32                         struct ext2_block_relocate_entry *ent);
33 static errcode_t bma_start_iter(ext2_brel brel);
34 static errcode_t bma_next(ext2_brel brel, blk_t *old,
35                          struct ext2_block_relocate_entry *ent);
36 static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
37 static errcode_t bma_delete(ext2_brel brel, blk_t old);
38 static errcode_t bma_free(ext2_brel brel);
39
40 struct brel_ma {
41         __u32 magic;
42         blk_t max_block;
43         struct ext2_block_relocate_entry *entries;
44 };
45
46 errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
47                                       ext2_brel *new_brel)
48 {
49         ext2_brel               brel = 0;
50         errcode_t       retval;
51         struct brel_ma  *ma = 0;
52         size_t          size;
53
54         *new_brel = 0;
55
56         /*
57          * Allocate memory structures
58          */
59         retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
60                                 (void **) &brel);
61         if (retval)
62                 goto errout;
63         memset(brel, 0, sizeof(struct ext2_block_relocation_table));
64         
65         retval = ext2fs_get_mem(strlen(name)+1, (void **) &brel->name);
66         if (retval)
67                 goto errout;
68         strcpy(brel->name, name);
69         
70         retval = ext2fs_get_mem(sizeof(struct brel_ma), (void **) &ma);
71         if (retval)
72                 goto errout;
73         memset(ma, 0, sizeof(struct brel_ma));
74         brel->priv_data = ma;
75         
76         size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
77                          (max_block+1));
78         retval = ext2fs_get_mem(size, (void **) &ma->entries);
79         if (retval)
80                 goto errout;
81         memset(ma->entries, 0, size);
82         ma->max_block = max_block;
83
84         /*
85          * Fill in the brel data structure
86          */
87         brel->put = bma_put;
88         brel->get = bma_get;
89         brel->start_iter = bma_start_iter;
90         brel->next = bma_next;
91         brel->move = bma_move;
92         brel->delete = bma_delete;
93         brel->free = bma_free;
94         
95         *new_brel = brel;
96         return 0;
97
98 errout:
99         bma_free(brel);
100         return retval;
101 }
102
103 static errcode_t bma_put(ext2_brel brel, blk_t old,
104                         struct ext2_block_relocate_entry *ent)
105 {
106         struct brel_ma  *ma;
107
108         ma = brel->priv_data;
109         if (old > ma->max_block)
110                 return EXT2_ET_INVALID_ARGUMENT;
111         ma->entries[(unsigned)old] = *ent;
112         return 0;
113 }
114
115 static errcode_t bma_get(ext2_brel brel, blk_t old,
116                         struct ext2_block_relocate_entry *ent)
117 {
118         struct brel_ma  *ma;
119
120         ma = brel->priv_data;
121         if (old > ma->max_block)
122                 return EXT2_ET_INVALID_ARGUMENT;
123         if (ma->entries[(unsigned)old].new == 0)
124                 return ENOENT;
125         *ent = ma->entries[old];
126         return 0;
127 }
128
129 static errcode_t bma_start_iter(ext2_brel brel)
130 {
131         brel->current = 0;
132         return 0;
133 }
134
135 static errcode_t bma_next(ext2_brel brel, blk_t *old,
136                           struct ext2_block_relocate_entry *ent)
137 {
138         struct brel_ma  *ma;
139
140         ma = brel->priv_data;
141         while (++brel->current < ma->max_block) {
142                 if (ma->entries[(unsigned)brel->current].new == 0)
143                         continue;
144                 *old = brel->current;
145                 *ent = ma->entries[(unsigned)brel->current];
146                 return 0;
147         }
148         *old = 0;
149         return 0;
150 }
151
152 static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
153 {
154         struct brel_ma  *ma;
155
156         ma = brel->priv_data;
157         if ((old > ma->max_block) || (new > ma->max_block))
158                 return EXT2_ET_INVALID_ARGUMENT;
159         if (ma->entries[(unsigned)old].new == 0)
160                 return ENOENT;
161         ma->entries[(unsigned)new] = ma->entries[old];
162         ma->entries[(unsigned)old].new = 0;
163         return 0;
164 }
165
166 static errcode_t bma_delete(ext2_brel brel, blk_t old)
167 {
168         struct brel_ma  *ma;
169
170         ma = brel->priv_data;
171         if (old > ma->max_block)
172                 return EXT2_ET_INVALID_ARGUMENT;
173         if (ma->entries[(unsigned)old].new == 0)
174                 return ENOENT;
175         ma->entries[(unsigned)old].new = 0;
176         return 0;
177 }
178
179 static errcode_t bma_free(ext2_brel brel)
180 {
181         struct brel_ma  *ma;
182
183         if (!brel)
184                 return 0;
185
186         ma = brel->priv_data;
187
188         if (ma) {
189                 if (ma->entries)
190                         ext2fs_free_mem((void **) &ma->entries);
191                 ext2fs_free_mem((void **) &ma);
192         }
193         if (brel->name)
194                 ext2fs_free_mem((void **) &brel->name);
195         ext2fs_free_mem((void **) &brel);
196         return 0;
197 }