badblocks.c revision 57dca85467cf3fc61565e916a5f2e35db8020d88
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 */ 37static 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 */ 68errcode_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 */ 76errcode_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 */ 100errcode_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 += 100; 111 retval = ext2fs_resize_mem(old_size, bb->size * sizeof(blk_t), 112 (void **) &bb->list); 113 if (retval) { 114 bb->size -= 100; 115 return retval; 116 } 117 } 118 119 /* 120 * Add special case code for appending to the end of the list 121 */ 122 i = bb->num-1; 123 if ((bb->num != 0) && (bb->list[i] == blk)) 124 return 0; 125 if ((bb->num == 0) || (bb->list[i] < blk)) { 126 bb->list[bb->num++] = blk; 127 return 0; 128 } 129 130 j = bb->num; 131 for (i=0; i < bb->num; i++) { 132 if (bb->list[i] == blk) 133 return 0; 134 if (bb->list[i] > blk) { 135 j = i; 136 break; 137 } 138 } 139 for (i=bb->num; i > j; i--) 140 bb->list[i] = bb->list[i-1]; 141 bb->list[j] = blk; 142 bb->num++; 143 return 0; 144} 145 146/* 147 * This procedure tests to see if a particular block is on a badblocks 148 * list. 149 */ 150int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) 151{ 152 int low, high, mid; 153 154 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) 155 return 0; 156 157 if (bb->num == 0) 158 return 0; 159 160 low = 0; 161 high = bb->num-1; 162 if (blk == bb->list[low]) 163 return 1; 164 if (blk == bb->list[high]) 165 return 1; 166 167 while (low < high) { 168 mid = (low+high)/2; 169 if (mid == low || mid == high) 170 break; 171 if (blk == bb->list[mid]) 172 return 1; 173 if (blk < bb->list[mid]) 174 high = mid; 175 else 176 low = mid; 177 } 178 return 0; 179} 180 181errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, 182 ext2_badblocks_iterate *ret) 183{ 184 ext2_badblocks_iterate iter; 185 errcode_t retval; 186 187 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); 188 189 retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_iterate), 190 (void **) &iter); 191 if (retval) 192 return retval; 193 194 iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; 195 iter->bb = bb; 196 iter->ptr = 0; 197 *ret = iter; 198 return 0; 199} 200 201int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) 202{ 203 ext2_badblocks_list bb; 204 205 if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) 206 return 0; 207 208 bb = iter->bb; 209 210 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) 211 return 0; 212 213 if (iter->ptr < bb->num) { 214 *blk = bb->list[iter->ptr++]; 215 return 1; 216 } 217 *blk = 0; 218 return 0; 219} 220 221void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) 222{ 223 if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) 224 return; 225 226 iter->bb = 0; 227 ext2fs_free_mem((void **) &iter); 228} 229 230int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) 231{ 232 EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); 233 EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); 234 235 if (bb1->num != bb2->num) 236 return 0; 237 238 if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) 239 return 0; 240 return 1; 241} 242