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