blob: f8a562a53d2b4c944544ff3ac5efa62608899c5a [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * badblocks.c --- routines to manipulate the bad block structure
3 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +00004 * 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%
Theodore Ts'o3839e651997-04-26 13:21:57 +000010 */
11
12#include <stdio.h>
13#include <string.h>
14#include <unistd.h>
15#include <stdlib.h>
16#include <fcntl.h>
17#include <time.h>
18#include <sys/stat.h>
19#include <sys/types.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000020#if HAVE_ERRNO_H
21#include <errno.h>
22#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000023
Theodore Ts'o3839e651997-04-26 13:21:57 +000024#include <linux/ext2_fs.h>
25
Theodore Ts'o21c84b71997-04-29 16:15:03 +000026#include "ext2fsP.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000027
28/*
Theodore Ts'oa29f4d31997-04-29 21:26:48 +000029 * Helper function for making a badblocks list
Theodore Ts'o3839e651997-04-26 13:21:57 +000030 */
Theodore Ts'oa29f4d31997-04-29 21:26:48 +000031static errcode_t make_badblocks_list(int size, int num, blk_t *list,
32 ext2_badblocks_list *ret)
Theodore Ts'o3839e651997-04-26 13:21:57 +000033{
Theodore Ts'o21c84b71997-04-29 16:15:03 +000034 ext2_badblocks_list bb;
Theodore Ts'oa29f4d31997-04-29 21:26:48 +000035
Theodore Ts'o21c84b71997-04-29 16:15:03 +000036 bb = malloc(sizeof(struct ext2_struct_badblocks_list));
Theodore Ts'o3839e651997-04-26 13:21:57 +000037 if (!bb)
38 return ENOMEM;
Theodore Ts'o21c84b71997-04-29 16:15:03 +000039 memset(bb, 0, sizeof(struct ext2_struct_badblocks_list));
Theodore Ts'of3db3561997-04-26 13:34:30 +000040 bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
Theodore Ts'o3839e651997-04-26 13:21:57 +000041 bb->size = size ? size : 10;
Theodore Ts'oa29f4d31997-04-29 21:26:48 +000042 bb->num = num;
Theodore Ts'o3839e651997-04-26 13:21:57 +000043 bb->list = malloc(bb->size * sizeof(blk_t));
44 if (!bb->list) {
45 free(bb);
46 return ENOMEM;
47 }
Theodore Ts'oa29f4d31997-04-29 21:26:48 +000048 if (list)
49 memcpy(bb->list, list, bb->size * sizeof(blk_t));
50 else
51 memset(bb->list, 0, bb->size * sizeof(blk_t));
Theodore Ts'o3839e651997-04-26 13:21:57 +000052 *ret = bb;
53 return 0;
54}
Theodore Ts'oa29f4d31997-04-29 21:26:48 +000055
56
57/*
58 * This procedure creates an empty badblocks list.
59 */
60errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
61{
62 return make_badblocks_list(size, 0, 0, ret);
63}
64
65/*
66 * This procedure copies a badblocks list
67 */
68errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
69 ext2_badblocks_list *dest)
70{
71 errcode_t retval;
72
73 retval = make_badblocks_list(src->size, src->num, src->list,
74 dest);
75 if (retval)
76 return retval;
77 (*dest)->badblocks_flags = src->badblocks_flags;
78 return 0;
79}
80
Theodore Ts'o3839e651997-04-26 13:21:57 +000081
82/*
83 * This procedure frees a badblocks list.
Theodore Ts'o21c84b71997-04-29 16:15:03 +000084 *
85 * (note: moved to closefs.c)
Theodore Ts'o3839e651997-04-26 13:21:57 +000086 */
Theodore Ts'of3db3561997-04-26 13:34:30 +000087
Theodore Ts'o3839e651997-04-26 13:21:57 +000088
89/*
90 * This procedure adds a block to a badblocks list.
91 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +000092errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
Theodore Ts'o3839e651997-04-26 13:21:57 +000093{
Theodore Ts'o21c84b71997-04-29 16:15:03 +000094 int i, j;
95 blk_t *new_list;
Theodore Ts'o3839e651997-04-26 13:21:57 +000096
Theodore Ts'of3db3561997-04-26 13:34:30 +000097 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
98
Theodore Ts'o3839e651997-04-26 13:21:57 +000099 if (bb->num >= bb->size) {
100 bb->size += 10;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000101 new_list = realloc(bb->list, bb->size * sizeof(blk_t));
102 if (!new_list)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000103 return ENOMEM;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000104 bb->list = new_list;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000105 }
106
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000107 j = bb->num;
108 for (i=0; i < bb->num; i++) {
109 if (bb->list[i] == blk)
110 return 0;
111 if (bb->list[i] > blk) {
112 j = i;
113 break;
114 }
115 }
116 for (i=bb->num; i > j; i--)
117 bb->list[i] = bb->list[i-1];
118 bb->list[j] = blk;
119 bb->num++;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000120 return 0;
121}
122
123/*
124 * This procedure tests to see if a particular block is on a badblocks
125 * list.
126 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000127int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000128{
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000129 int low, high, mid;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000130
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000131 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
132 return 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000133
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000134 low = 0;
135 high = bb->num-1;
136 if (blk == bb->list[low])
137 return 1;
138 if (blk == bb->list[high])
139 return 1;
140
141 while (low < high) {
142 mid = (low+high)/2;
143 if (mid == low || mid == high)
144 break;
145 if (blk == bb->list[mid])
Theodore Ts'o3839e651997-04-26 13:21:57 +0000146 return 1;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000147 if (blk < bb->list[mid])
148 high = mid;
149 else
150 low = mid;
151 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000152 return 0;
153}
154
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000155errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
156 ext2_badblocks_iterate *ret)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000157{
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000158 ext2_badblocks_iterate iter;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000159
Theodore Ts'of3db3561997-04-26 13:34:30 +0000160 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
161
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000162 iter = malloc(sizeof(struct ext2_struct_badblocks_iterate));
Theodore Ts'o3839e651997-04-26 13:21:57 +0000163 if (!iter)
164 return ENOMEM;
165
Theodore Ts'of3db3561997-04-26 13:34:30 +0000166 iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000167 iter->bb = bb;
168 iter->ptr = 0;
169 *ret = iter;
170 return 0;
171}
172
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000173int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000174{
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000175 ext2_badblocks_list bb;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000176
177 if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
178 return 0;
179
180 bb = iter->bb;
181
182 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
183 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000184
185 if (iter->ptr < bb->num) {
186 *blk = bb->list[iter->ptr++];
187 return 1;
188 }
189 *blk = 0;
190 return 0;
191}
192
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000193void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000194{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000195 if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
196 return;
197
Theodore Ts'o3839e651997-04-26 13:21:57 +0000198 iter->bb = 0;
199 free(iter);
200}
201
202
203
204
205