badblocks.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * badblocks.c --- routines to manipulate the bad block structure
  4. *
  5. * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
  6. *
  7. * %Begin-Header%
  8. * This file may be redistributed under the terms of the GNU Public
  9. * License.
  10. * %End-Header%
  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. #include "ext2_fs.h"
  26. #include "ext2fsP.h"
  27. /*
  28. * Helper function for making a badblocks list
  29. */
  30. static errcode_t make_u32_list(int size, int num, __u32 *list,
  31. ext2_u32_list *ret)
  32. {
  33. ext2_u32_list bb;
  34. errcode_t retval;
  35. retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
  36. if (retval)
  37. return retval;
  38. memset(bb, 0, sizeof(struct ext2_struct_u32_list));
  39. bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
  40. bb->size = size ? size : 10;
  41. bb->num = num;
  42. retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
  43. if (!bb->list) {
  44. ext2fs_free_mem(&bb);
  45. return retval;
  46. }
  47. if (list)
  48. memcpy(bb->list, list, bb->size * sizeof(blk_t));
  49. else
  50. memset(bb->list, 0, bb->size * sizeof(blk_t));
  51. *ret = bb;
  52. return 0;
  53. }
  54. /*
  55. * This procedure creates an empty u32 list.
  56. */
  57. errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
  58. {
  59. return make_u32_list(size, 0, 0, ret);
  60. }
  61. /*
  62. * This procedure creates an empty badblocks list.
  63. */
  64. errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
  65. {
  66. return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
  67. }
  68. /*
  69. * This procedure copies a badblocks list
  70. */
  71. errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
  72. {
  73. errcode_t retval;
  74. retval = make_u32_list(src->size, src->num, src->list, dest);
  75. if (retval)
  76. return retval;
  77. (*dest)->badblocks_flags = src->badblocks_flags;
  78. return 0;
  79. }
  80. errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
  81. ext2_badblocks_list *dest)
  82. {
  83. return ext2fs_u32_copy((ext2_u32_list) src,
  84. (ext2_u32_list *) dest);
  85. }
  86. /*
  87. * This procedure frees a badblocks list.
  88. *
  89. * (note: moved to closefs.c)
  90. */
  91. /*
  92. * This procedure adds a block to a badblocks list.
  93. */
  94. errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
  95. {
  96. errcode_t retval;
  97. int i, j;
  98. unsigned long old_size;
  99. EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
  100. if (bb->num >= bb->size) {
  101. old_size = bb->size * sizeof(__u32);
  102. bb->size += 100;
  103. retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
  104. &bb->list);
  105. if (retval) {
  106. bb->size -= 100;
  107. return retval;
  108. }
  109. }
  110. /*
  111. * Add special case code for appending to the end of the list
  112. */
  113. i = bb->num-1;
  114. if ((bb->num != 0) && (bb->list[i] == blk))
  115. return 0;
  116. if ((bb->num == 0) || (bb->list[i] < blk)) {
  117. bb->list[bb->num++] = blk;
  118. return 0;
  119. }
  120. j = bb->num;
  121. for (i=0; i < bb->num; i++) {
  122. if (bb->list[i] == blk)
  123. return 0;
  124. if (bb->list[i] > blk) {
  125. j = i;
  126. break;
  127. }
  128. }
  129. for (i=bb->num; i > j; i--)
  130. bb->list[i] = bb->list[i-1];
  131. bb->list[j] = blk;
  132. bb->num++;
  133. return 0;
  134. }
  135. errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
  136. {
  137. return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
  138. }
  139. /*
  140. * This procedure finds a particular block is on a badblocks
  141. * list.
  142. */
  143. int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
  144. {
  145. int low, high, mid;
  146. if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
  147. return -1;
  148. if (bb->num == 0)
  149. return -1;
  150. low = 0;
  151. high = bb->num-1;
  152. if (blk == bb->list[low])
  153. return low;
  154. if (blk == bb->list[high])
  155. return high;
  156. while (low < high) {
  157. mid = (low+high)/2;
  158. if (mid == low || mid == high)
  159. break;
  160. if (blk == bb->list[mid])
  161. return mid;
  162. if (blk < bb->list[mid])
  163. high = mid;
  164. else
  165. low = mid;
  166. }
  167. return -1;
  168. }
  169. /*
  170. * This procedure tests to see if a particular block is on a badblocks
  171. * list.
  172. */
  173. int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
  174. {
  175. if (ext2fs_u32_list_find(bb, blk) < 0)
  176. return 0;
  177. else
  178. return 1;
  179. }
  180. int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
  181. {
  182. return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
  183. }
  184. /*
  185. * Remove a block from the badblock list
  186. */
  187. int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
  188. {
  189. int remloc, i;
  190. if (bb->num == 0)
  191. return -1;
  192. remloc = ext2fs_u32_list_find(bb, blk);
  193. if (remloc < 0)
  194. return -1;
  195. for (i = remloc; i < bb->num - 1; i++)
  196. bb->list[i] = bb->list[i+1];
  197. bb->num--;
  198. return 0;
  199. }
  200. void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
  201. {
  202. ext2fs_u32_list_del(bb, blk);
  203. }
  204. errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
  205. ext2_u32_iterate *ret)
  206. {
  207. ext2_u32_iterate iter;
  208. errcode_t retval;
  209. EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
  210. retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
  211. if (retval)
  212. return retval;
  213. iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
  214. iter->bb = bb;
  215. iter->ptr = 0;
  216. *ret = iter;
  217. return 0;
  218. }
  219. errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
  220. ext2_badblocks_iterate *ret)
  221. {
  222. return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
  223. (ext2_u32_iterate *) ret);
  224. }
  225. int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
  226. {
  227. ext2_u32_list bb;
  228. if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
  229. return 0;
  230. bb = iter->bb;
  231. if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
  232. return 0;
  233. if (iter->ptr < bb->num) {
  234. *blk = bb->list[iter->ptr++];
  235. return 1;
  236. }
  237. *blk = 0;
  238. return 0;
  239. }
  240. int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
  241. {
  242. return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
  243. (__u32 *) blk);
  244. }
  245. void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
  246. {
  247. if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
  248. return;
  249. iter->bb = 0;
  250. ext2fs_free_mem(&iter);
  251. }
  252. void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
  253. {
  254. ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
  255. }
  256. int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
  257. {
  258. EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
  259. EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
  260. if (bb1->num != bb2->num)
  261. return 0;
  262. if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
  263. return 0;
  264. return 1;
  265. }
  266. int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
  267. {
  268. return ext2fs_u32_list_equal((ext2_u32_list) bb1,
  269. (ext2_u32_list) bb2);
  270. }
  271. int ext2fs_u32_list_count(ext2_u32_list bb)
  272. {
  273. return bb->num;
  274. }