badblocks.c revision 9f8046fc6dfc13eee2f5c363214e60b533872cac
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#include "ext2_fs.h" 27#include "ext2fsP.h" 28 29/* 30 * Helper function for making a badblocks list 31 */ 32static errcode_t make_badblocks_list(int size, int num, blk_t *list, 33 ext2_badblocks_list *ret) 34{ 35 ext2_badblocks_list bb; 36 errcode_t retval; 37 38 retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_list), 39 (void **) &bb); 40 if (retval) 41 return retval; 42 memset(bb, 0, sizeof(struct ext2_struct_badblocks_list)); 43 bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; 44 bb->size = size ? size : 10; 45 bb->num = num; 46 retval = ext2fs_get_mem(bb->size * sizeof(blk_t), (void **) &bb->list); 47 if (!bb->list) { 48 ext2fs_free_mem((void **) &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 badblocks list. 62 */ 63errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) 64{ 65 return make_badblocks_list(size, 0, 0, ret); 66} 67 68/* 69 * This procedure copies a badblocks list 70 */ 71errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, 72 ext2_badblocks_list *dest) 73{ 74 errcode_t retval; 75 76 retval = make_badblocks_list(src->size, src->num, src->list, 77 dest); 78 if (retval) 79 return retval; 80 (*dest)->badblocks_flags = src->badblocks_flags; 81 return 0; 82} 83 84 85/* 86 * This procedure frees a badblocks list. 87 * 88 * (note: moved to closefs.c) 89 */ 90 91 92/* 93 * This procedure adds a block to a badblocks list. 94 */ 95errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) 96{ 97 errcode_t retval; 98 int i, j; 99 unsigned long old_size; 100 101 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); 102 103 if (bb->num >= bb->size) { 104 old_size = bb->size * sizeof(blk_t); 105 bb->size += 100; 106 retval = ext2fs_resize_mem(old_size, bb->size * sizeof(blk_t), 107 (void **) &bb->list); 108 if (retval) { 109 bb->size -= 100; 110 return retval; 111 } 112 } 113 114 /* 115 * Add special case code for appending to the end of the list 116 */ 117 i = bb->num-1; 118 if ((bb->num != 0) && (bb->list[i] == blk)) 119 return 0; 120 if ((bb->num == 0) || (bb->list[i] < blk)) { 121 bb->list[bb->num++] = blk; 122 return 0; 123 } 124 125 j = bb->num; 126 for (i=0; i < bb->num; i++) { 127 if (bb->list[i] == blk) 128 return 0; 129 if (bb->list[i] > blk) { 130 j = i; 131 break; 132 } 133 } 134 for (i=bb->num; i > j; i--) 135 bb->list[i] = bb->list[i-1]; 136 bb->list[j] = blk; 137 bb->num++; 138 return 0; 139} 140 141/* 142 * This procedure tests to see if a particular block is on a badblocks 143 * list. 144 */ 145int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) 146{ 147 int low, high, mid; 148 149 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) 150 return 0; 151 152 if (bb->num == 0) 153 return 0; 154 155 low = 0; 156 high = bb->num-1; 157 if (blk == bb->list[low]) 158 return 1; 159 if (blk == bb->list[high]) 160 return 1; 161 162 while (low < high) { 163 mid = (low+high)/2; 164 if (mid == low || mid == high) 165 break; 166 if (blk == bb->list[mid]) 167 return 1; 168 if (blk < bb->list[mid]) 169 high = mid; 170 else 171 low = mid; 172 } 173 return 0; 174} 175 176errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, 177 ext2_badblocks_iterate *ret) 178{ 179 ext2_badblocks_iterate iter; 180 errcode_t retval; 181 182 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); 183 184 retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_iterate), 185 (void **) &iter); 186 if (retval) 187 return retval; 188 189 iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; 190 iter->bb = bb; 191 iter->ptr = 0; 192 *ret = iter; 193 return 0; 194} 195 196int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) 197{ 198 ext2_badblocks_list bb; 199 200 if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) 201 return 0; 202 203 bb = iter->bb; 204 205 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) 206 return 0; 207 208 if (iter->ptr < bb->num) { 209 *blk = bb->list[iter->ptr++]; 210 return 1; 211 } 212 *blk = 0; 213 return 0; 214} 215 216void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) 217{ 218 if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) 219 return; 220 221 iter->bb = 0; 222 ext2fs_free_mem((void **) &iter); 223} 224 225int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) 226{ 227 EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); 228 EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); 229 230 if (bb1->num != bb2->num) 231 return 0; 232 233 if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) 234 return 0; 235 return 1; 236} 237