Home | History | Annotate | Download | only in ext2fs
      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 Library
      8  * General Public License, version 2.
      9  * %End-Header%
     10  */
     11 
     12 #include "config.h"
     13 #include <stdio.h>
     14 #include <string.h>
     15 #if HAVE_UNISTD_H
     16 #include <unistd.h>
     17 #endif
     18 #include <fcntl.h>
     19 #include <time.h>
     20 #if HAVE_SYS_STAT_H
     21 #include <sys/stat.h>
     22 #endif
     23 #if HAVE_SYS_TYPES_H
     24 #include <sys/types.h>
     25 #endif
     26 
     27 #include "ext2_fs.h"
     28 #include "ext2fsP.h"
     29 
     30 /*
     31  * Helper function for making a badblocks list
     32  */
     33 static errcode_t make_u32_list(int size, int num, __u32 *list,
     34 			       ext2_u32_list *ret)
     35 {
     36 	ext2_u32_list	bb;
     37 	errcode_t	retval;
     38 
     39 	retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
     40 	if (retval)
     41 		return retval;
     42 	memset(bb, 0, sizeof(struct ext2_struct_u32_list));
     43 	bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
     44 	bb->size = size ? size : 10;
     45 	bb->num = num;
     46 	retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list);
     47 	if (retval) {
     48 		ext2fs_free_mem(&bb);
     49 		return retval;
     50 	}
     51 	if (list)
     52 		memcpy(bb->list, list, bb->size * sizeof(blk_t));
     53 	else
     54 		memset(bb->list, 0, bb->size * sizeof(blk_t));
     55 	*ret = bb;
     56 	return 0;
     57 }
     58 
     59 
     60 /*
     61  * This procedure creates an empty u32 list.
     62  */
     63 errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
     64 {
     65 	return make_u32_list(size, 0, 0, ret);
     66 }
     67 
     68 /*
     69  * This procedure creates an empty badblocks list.
     70  */
     71 errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
     72 {
     73 	return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
     74 }
     75 
     76 
     77 /*
     78  * This procedure copies a badblocks list
     79  */
     80 errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
     81 {
     82 	errcode_t	retval;
     83 
     84 	retval = make_u32_list(src->size, src->num, src->list, dest);
     85 	if (retval)
     86 		return retval;
     87 	(*dest)->badblocks_flags = src->badblocks_flags;
     88 	return 0;
     89 }
     90 
     91 errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
     92 				ext2_badblocks_list *dest)
     93 {
     94 	return ext2fs_u32_copy((ext2_u32_list) src,
     95 			       (ext2_u32_list *) dest);
     96 }
     97 
     98 /*
     99  * This procedure frees a badblocks list.
    100  *
    101  * (note: moved to closefs.c)
    102  */
    103 
    104 
    105 /*
    106  * This procedure adds a block to a badblocks list.
    107  */
    108 errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
    109 {
    110 	errcode_t	retval;
    111 	int		i, j;
    112 	unsigned long	old_size;
    113 
    114 	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
    115 
    116 	if (bb->num >= bb->size) {
    117 		old_size = bb->size * sizeof(__u32);
    118 		bb->size += 100;
    119 		retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
    120 					   &bb->list);
    121 		if (retval) {
    122 			bb->size -= 100;
    123 			return retval;
    124 		}
    125 	}
    126 
    127 	/*
    128 	 * Add special case code for appending to the end of the list
    129 	 */
    130 	i = bb->num-1;
    131 	if ((bb->num != 0) && (bb->list[i] == blk))
    132 		return 0;
    133 	if ((bb->num == 0) || (bb->list[i] < blk)) {
    134 		bb->list[bb->num++] = blk;
    135 		return 0;
    136 	}
    137 
    138 	j = bb->num;
    139 	for (i=0; i < bb->num; i++) {
    140 		if (bb->list[i] == blk)
    141 			return 0;
    142 		if (bb->list[i] > blk) {
    143 			j = i;
    144 			break;
    145 		}
    146 	}
    147 	for (i=bb->num; i > j; i--)
    148 		bb->list[i] = bb->list[i-1];
    149 	bb->list[j] = blk;
    150 	bb->num++;
    151 	return 0;
    152 }
    153 
    154 errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
    155 {
    156 	return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
    157 }
    158 
    159 /*
    160  * This procedure finds a particular block is on a badblocks
    161  * list.
    162  */
    163 int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
    164 {
    165 	int	low, high, mid;
    166 
    167 	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
    168 		return -1;
    169 
    170 	if (bb->num == 0)
    171 		return -1;
    172 
    173 	low = 0;
    174 	high = bb->num-1;
    175 	if (blk == bb->list[low])
    176 		return low;
    177 	if (blk == bb->list[high])
    178 		return high;
    179 
    180 	while (low < high) {
    181 		mid = ((unsigned)low + (unsigned)high)/2;
    182 		if (mid == low || mid == high)
    183 			break;
    184 		if (blk == bb->list[mid])
    185 			return mid;
    186 		if (blk < bb->list[mid])
    187 			high = mid;
    188 		else
    189 			low = mid;
    190 	}
    191 	return -1;
    192 }
    193 
    194 /*
    195  * This procedure tests to see if a particular block is on a badblocks
    196  * list.
    197  */
    198 int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
    199 {
    200 	if (ext2fs_u32_list_find(bb, blk) < 0)
    201 		return 0;
    202 	else
    203 		return 1;
    204 }
    205 
    206 int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
    207 {
    208 	return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
    209 }
    210 
    211 
    212 /*
    213  * Remove a block from the badblock list
    214  */
    215 int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
    216 {
    217 	int	remloc, i;
    218 
    219 	if (bb->num == 0)
    220 		return -1;
    221 
    222 	remloc = ext2fs_u32_list_find(bb, blk);
    223 	if (remloc < 0)
    224 		return -1;
    225 
    226 	for (i = remloc ; i < bb->num-1; i++)
    227 		bb->list[i] = bb->list[i+1];
    228 	bb->num--;
    229 	return 0;
    230 }
    231 
    232 void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
    233 {
    234 	ext2fs_u32_list_del(bb, blk);
    235 }
    236 
    237 errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
    238 					ext2_u32_iterate *ret)
    239 {
    240 	ext2_u32_iterate iter;
    241 	errcode_t		retval;
    242 
    243 	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
    244 
    245 	retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
    246 	if (retval)
    247 		return retval;
    248 
    249 	iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
    250 	iter->bb = bb;
    251 	iter->ptr = 0;
    252 	*ret = iter;
    253 	return 0;
    254 }
    255 
    256 errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
    257 					      ext2_badblocks_iterate *ret)
    258 {
    259 	return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
    260 					      (ext2_u32_iterate *) ret);
    261 }
    262 
    263 
    264 int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
    265 {
    266 	ext2_u32_list	bb;
    267 
    268 	if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
    269 		return 0;
    270 
    271 	bb = iter->bb;
    272 
    273 	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
    274 		return 0;
    275 
    276 	if (iter->ptr < bb->num) {
    277 		*blk = bb->list[iter->ptr++];
    278 		return 1;
    279 	}
    280 	*blk = 0;
    281 	return 0;
    282 }
    283 
    284 int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
    285 {
    286 	return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
    287 				       (__u32 *) blk);
    288 }
    289 
    290 
    291 void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
    292 {
    293 	if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
    294 		return;
    295 
    296 	iter->bb = 0;
    297 	ext2fs_free_mem(&iter);
    298 }
    299 
    300 void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
    301 {
    302 	ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
    303 }
    304 
    305 
    306 int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
    307 {
    308 	EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
    309 	EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
    310 
    311 	if (bb1->num != bb2->num)
    312 		return 0;
    313 
    314 	if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
    315 		return 0;
    316 	return 1;
    317 }
    318 
    319 int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
    320 {
    321 	return ext2fs_u32_list_equal((ext2_u32_list) bb1,
    322 				     (ext2_u32_list) bb2);
    323 }
    324 
    325 int ext2fs_u32_list_count(ext2_u32_list bb)
    326 {
    327 	return bb->num;
    328 }
    329