Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / lib / ext2fs / badblocks.c
1 /*
2  * badblocks.c --- routines to manipulate the bad block structure
3  * 
4  * Copyright (C) 1994, 1995, 1996 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 <stdio.h>
13 #include <string.h>
14 #if HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 #include <fcntl.h>
18 #include <time.h>
19 #if HAVE_SYS_STAT_H
20 #include <sys/stat.h>
21 #endif
22 #if HAVE_SYS_TYPES_H
23 #include <sys/types.h>
24 #endif
25
26 #if EXT2_FLAT_INCLUDES
27 #include "ext2_fs.h"
28 #else
29 #include <linux/ext2_fs.h>
30 #endif
31
32 #include "ext2fsP.h"
33
34 /*
35  * Helper function for making a badblocks list
36  */
37 static errcode_t make_badblocks_list(int size, int num, blk_t *list,
38                                      ext2_badblocks_list *ret)
39 {
40         ext2_badblocks_list     bb;
41         errcode_t               retval;
42         
43         retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_list),
44                                 (void **) &bb);
45         if (retval)
46                 return retval;
47         memset(bb, 0, sizeof(struct ext2_struct_badblocks_list));
48         bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
49         bb->size = size ? size : 10;
50         bb->num = num;
51         retval = ext2fs_get_mem(bb->size * sizeof(blk_t), (void **) &bb->list);
52         if (!bb->list) {
53                 ext2fs_free_mem((void **) &bb);
54                 return retval;
55         }
56         if (list)
57                 memcpy(bb->list, list, bb->size * sizeof(blk_t));
58         else
59                 memset(bb->list, 0, bb->size * sizeof(blk_t));
60         *ret = bb;
61         return 0;
62 }
63         
64
65 /*
66  * This procedure creates an empty badblocks list.
67  */
68 errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
69 {
70         return make_badblocks_list(size, 0, 0, ret);
71 }
72
73 /*
74  * This procedure copies a badblocks list
75  */
76 errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
77                                 ext2_badblocks_list *dest)
78 {
79         errcode_t       retval;
80         
81         retval = make_badblocks_list(src->size, src->num, src->list,
82                                      dest);
83         if (retval)
84                 return retval;
85         (*dest)->badblocks_flags = src->badblocks_flags;
86         return 0;
87 }
88
89
90 /*
91  * This procedure frees a badblocks list.
92  *
93  * (note: moved to closefs.c)
94  */
95
96
97 /*
98  * This procedure adds a block to a badblocks list.
99  */
100 errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
101 {
102         errcode_t       retval;
103         int             i, j;
104         unsigned long   old_size;
105
106         EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
107
108         if (bb->num >= bb->size) {
109                 old_size = bb->size * sizeof(blk_t);
110                 bb->size += 10;
111                 retval = ext2fs_resize_mem(old_size, bb->size * sizeof(blk_t),
112                                            (void **) &bb->list);
113                 if (retval) {
114                         bb->size -= 10;
115                         return retval;
116                 }
117         }
118
119         j = bb->num;
120         for (i=0; i < bb->num; i++) {
121                 if (bb->list[i] == blk)
122                         return 0;
123                 if (bb->list[i] > blk) {
124                         j = i;
125                         break;
126                 }
127         }
128         for (i=bb->num; i > j; i--)
129                 bb->list[i] = bb->list[i-1];
130         bb->list[j] = blk;
131         bb->num++;
132         return 0;
133 }
134
135 /*
136  * This procedure tests to see if a particular block is on a badblocks
137  * list.
138  */
139 int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
140 {
141         int     low, high, mid;
142
143         if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
144                 return 0;
145
146         if (bb->num == 0)
147                 return 0;
148
149         low = 0;
150         high = bb->num-1;
151         if (blk == bb->list[low])
152                 return 1;
153         if (blk == bb->list[high])
154                 return 1;
155
156         while (low < high) {
157                 mid = (low+high)/2;
158                 if (mid == low || mid == high)
159                         break;
160                 if (blk == bb->list[mid])
161                         return 1;
162                 if (blk < bb->list[mid])
163                         high = mid;
164                 else
165                         low = mid;
166         }
167         return 0;
168 }
169
170 errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
171                                               ext2_badblocks_iterate *ret)
172 {
173         ext2_badblocks_iterate iter;
174         errcode_t               retval;
175
176         EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
177
178         retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_iterate),
179                               (void **) &iter);
180         if (retval)
181                 return retval;
182
183         iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
184         iter->bb = bb;
185         iter->ptr = 0;
186         *ret = iter;
187         return 0;
188 }
189
190 int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
191 {
192         ext2_badblocks_list     bb;
193
194         if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
195                 return 0;
196
197         bb = iter->bb;
198
199         if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
200                 return 0;
201         
202         if (iter->ptr < bb->num) {
203                 *blk = bb->list[iter->ptr++];
204                 return 1;
205         } 
206         *blk = 0;
207         return 0;
208 }
209
210 void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
211 {
212         if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
213                 return;
214
215         iter->bb = 0;
216         ext2fs_free_mem((void **) &iter);
217 }
218
219
220
221
222