badblocks.c revision f75c28de4731c2cd09f6ca1a23e25c968a1edc2f
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c --- routines to manipulate the bad block structure 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. 521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 144cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 164cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 191d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_STAT_H 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 211d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 221d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 241d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 26b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#if EXT2_FLAT_INCLUDES 27b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 28b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#else 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/ext2_fs.h> 30b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#endif 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "ext2fsP.h" 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 35a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * Helper function for making a badblocks list 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 37a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'ostatic errcode_t make_badblocks_list(int size, int num, blk_t *list, 38a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o ext2_badblocks_list *ret) 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2_badblocks_list bb; 417b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 42a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 437b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_list), 447b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &bb); 457b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 467b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 4721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o memset(bb, 0, sizeof(struct ext2_struct_badblocks_list)); 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o bb->size = size ? size : 10; 50a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o bb->num = num; 517b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(bb->size * sizeof(blk_t), (void **) &bb->list); 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!bb->list) { 537b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &bb); 547b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 56a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (list) 57a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o memcpy(bb->list, list, bb->size * sizeof(blk_t)); 58a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o else 59a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o memset(bb->list, 0, bb->size * sizeof(blk_t)); 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *ret = bb; 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 63a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 64a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 65a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o/* 66a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * This procedure creates an empty badblocks list. 67a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o */ 68a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'oerrcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) 69a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o{ 70a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return make_badblocks_list(size, 0, 0, ret); 71a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o} 72a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 73a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o/* 74a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o * This procedure copies a badblocks list 75a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o */ 76a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'oerrcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, 77a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o ext2_badblocks_list *dest) 78a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o{ 79a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o errcode_t retval; 80a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 81a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o retval = make_badblocks_list(src->size, src->num, src->list, 82a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o dest); 83a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (retval) 84a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return retval; 85a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o (*dest)->badblocks_flags = src->badblocks_flags; 86a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 87a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o} 88a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This procedure frees a badblocks list. 9221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 9321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * (note: moved to closefs.c) 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 95f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This procedure adds a block to a badblocks list. 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 10021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'oerrcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1027b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 1037b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o int i, j; 10476f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o unsigned long old_size; 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 106f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); 107f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (bb->num >= bb->size) { 10976f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o old_size = bb->size * sizeof(blk_t); 110f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o bb->size += 100; 11176f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o retval = ext2fs_resize_mem(old_size, bb->size * sizeof(blk_t), 1127b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &bb->list); 11376f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o if (retval) { 114f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o bb->size -= 100; 1157b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 11676f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o } 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 11921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o j = bb->num; 12021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o for (i=0; i < bb->num; i++) { 12121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (bb->list[i] == blk) 12221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 12321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (bb->list[i] > blk) { 12421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o j = i; 12521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o break; 12621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 12721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 12821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o for (i=bb->num; i > j; i--) 12921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o bb->list[i] = bb->list[i-1]; 13021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o bb->list[j] = blk; 13121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o bb->num++; 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This procedure tests to see if a particular block is on a badblocks 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * list. 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 13921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'oint ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 14121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int low, high, mid; 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 14321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) 14421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 145f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 146f635d7f65bd002984ce9a202d491d4f187b996b2Theodore Ts'o if (bb->num == 0) 147f635d7f65bd002984ce9a202d491d4f187b996b2Theodore Ts'o return 0; 148f635d7f65bd002984ce9a202d491d4f187b996b2Theodore Ts'o 14921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o low = 0; 15021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o high = bb->num-1; 15121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (blk == bb->list[low]) 15221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 1; 15321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (blk == bb->list[high]) 15421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 1; 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 15621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o while (low < high) { 15721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o mid = (low+high)/2; 15821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (mid == low || mid == high) 15921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o break; 16021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (blk == bb->list[mid]) 16121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 1; 16221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (blk < bb->list[mid]) 16321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o high = mid; 16421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else 16521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o low = mid; 16621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 17021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'oerrcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, 17121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2_badblocks_iterate *ret) 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 17321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2_badblocks_iterate iter; 1747b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); 177f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1787b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_iterate), 1797b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &iter); 1807b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1817b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 183f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o iter->bb = bb; 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o iter->ptr = 0; 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *ret = iter; 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 19021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'oint ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) 1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 19221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2_badblocks_list bb; 193f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 194f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) 195f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 196f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 197f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o bb = iter->bb; 198f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 199f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) 200f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (iter->ptr < bb->num) { 2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *blk = bb->list[iter->ptr++]; 2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *blk = 0; 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 21021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ovoid ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 212f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) 213f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 214f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o iter->bb = 0; 2167b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &iter); 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 218