void ext2fs_free(ext2_filsys fs) { if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)) return; if (fs->image_io != fs->io) { if (fs->image_io) io_channel_close(fs->image_io); } if (fs->io) { io_channel_close(fs->io); } ext2fs_free_mem(&fs->device_name); ext2fs_free_mem(&fs->super); ext2fs_free_mem(&fs->orig_super); ext2fs_free_mem(&fs->group_desc); ext2fs_free_block_bitmap(fs->block_map); ext2fs_free_inode_bitmap(fs->inode_map); ext2fs_badblocks_list_free(fs->badblocks); fs->badblocks = 0; ext2fs_free_dblist(fs->dblist); if (fs->icache) ext2fs_free_inode_cache(fs->icache); fs->magic = 0; ext2fs_free_mem(&fs); }
static void list_bad_blocks(ext2_filsys fs, int dump) { badblocks_list bb_list = 0; badblocks_iterate bb_iter; blk_t blk; errcode_t retval; const char *header, *fmt; retval = ext2fs_read_bb_inode(fs, &bb_list); if (retval) { com_err("ext2fs_read_bb_inode", retval, 0); return; } retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); if (retval) { com_err("ext2fs_badblocks_list_iterate_begin", retval, "%s", _("while printing bad block list")); return; } if (dump) { header = fmt = "%u\n"; } else { header = _("Bad blocks: %u"); fmt = ", %u"; } while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { printf(header ? header : fmt, blk); header = 0; } ext2fs_badblocks_list_iterate_end(bb_iter); if (!dump) fputc('\n', stdout); ext2fs_badblocks_list_free(bb_list); }
static errcode_t create_test_list(blk_t *vec, badblocks_list *ret) { errcode_t retval; badblocks_list bb; int i; retval = ext2fs_badblocks_list_create(&bb, 5); if (retval) { com_err("create_test_list", retval, "while creating list"); return retval; } for (i=0; vec[i]; i++) { retval = ext2fs_badblocks_list_add(bb, vec[i]); if (retval) { com_err("create_test_list", retval, "while adding test vector %d", i); ext2fs_badblocks_list_free(bb); return retval; } } *ret = bb; return 0; }
void badblocks_list_free(badblocks_list bb) { ext2fs_badblocks_list_free(bb); }
errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, ext2_inode_scan *ret_scan) { ext2_inode_scan scan; errcode_t retval; errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); /* * If fs->badblocks isn't set, then set it --- since the inode * scanning functions require it. */ if (fs->badblocks == 0) { /* * Temporarly save fs->get_blocks and set it to zero, * for compatibility with old e2fsck's. */ save_get_blocks = fs->get_blocks; fs->get_blocks = 0; retval = ext2fs_read_bb_inode(fs, &fs->badblocks); if (retval && fs->badblocks) { ext2fs_badblocks_list_free(fs->badblocks); fs->badblocks = 0; } fs->get_blocks = save_get_blocks; } retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); if (retval) return retval; memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); scan->magic = EXT2_ET_MAGIC_INODE_SCAN; scan->fs = fs; scan->inode_size = EXT2_INODE_SIZE(fs->super); scan->bytes_left = 0; scan->current_group = 0; scan->groups_left = fs->group_desc_count - 1; scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS; scan->current_block = ext2fs_inode_table_loc(scan->fs, scan->current_group); scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); scan->blocks_left = scan->fs->inode_blocks_per_group; if (ext2fs_has_group_desc_csum(fs)) { __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group); if (scan->inodes_left > unused) scan->inodes_left -= unused; else scan->inodes_left = 0; scan->blocks_left = (scan->inodes_left + (fs->blocksize / scan->inode_size - 1)) * scan->inode_size / fs->blocksize; } retval = io_channel_alloc_buf(fs->io, scan->inode_buffer_blocks, &scan->inode_buffer); scan->done_group = 0; scan->done_group_data = 0; scan->bad_block_ptr = 0; if (retval) { ext2fs_free_mem(&scan); return retval; } retval = ext2fs_get_mem(scan->inode_size + scan->inode_buffer_blocks, &scan->temp_buffer); if (retval) { ext2fs_free_mem(&scan->inode_buffer); ext2fs_free_mem(&scan); return retval; } memset(SCAN_BLOCK_STATUS(scan), 0, scan->inode_buffer_blocks); if (scan->fs->badblocks && scan->fs->badblocks->num) scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; if (ext2fs_has_group_desc_csum(fs)) scan->scan_flags |= EXT2_SF_DO_LAZY; *ret_scan = scan; return 0; }
int main(int argc, char **argv) { badblocks_list bb1, bb2, bb3, bb4, bb5; int equal; errcode_t retval; bb1 = bb2 = bb3 = bb4 = bb5 = 0; printf("test1: "); retval = create_test_list(test1, &bb1); if (retval == 0) print_list(bb1, 1); printf("\n"); printf("test2: "); retval = create_test_list(test2, &bb2); if (retval == 0) print_list(bb2, 1); printf("\n"); printf("test3: "); retval = create_test_list(test3, &bb3); if (retval == 0) print_list(bb3, 1); printf("\n"); printf("test4: "); retval = create_test_list(test4, &bb4); if (retval == 0) { print_list(bb4, 0); printf("\n"); validate_test_seq(bb4, test4a); } printf("\n"); printf("test5: "); retval = create_test_list(test5, &bb5); if (retval == 0) { print_list(bb5, 0); printf("\n"); do_test_seq(bb5, test5a); printf("After test5 sequence: "); print_list(bb5, 0); printf("\n"); } printf("\n"); if (bb1 && bb2 && bb3 && bb4 && bb5) { printf("Comparison tests:\n"); equal = ext2fs_badblocks_equal(bb1, bb2); printf("bb1 and bb2 are %sequal.\n", equal ? "" : "NOT "); if (equal) test_fail++; equal = ext2fs_badblocks_equal(bb1, bb3); printf("bb1 and bb3 are %sequal.\n", equal ? "" : "NOT "); if (!equal) test_fail++; equal = ext2fs_badblocks_equal(bb1, bb4); printf("bb1 and bb4 are %sequal.\n", equal ? "" : "NOT "); if (equal) test_fail++; equal = ext2fs_badblocks_equal(bb4, bb5); printf("bb4 and bb5 are %sequal.\n", equal ? "" : "NOT "); if (!equal) test_fail++; printf("\n"); } file_test(bb4); if (test_fail == 0) printf("ext2fs library badblocks tests checks out OK!\n"); if (bb1) ext2fs_badblocks_list_free(bb1); if (bb2) ext2fs_badblocks_list_free(bb2); if (bb3) ext2fs_badblocks_list_free(bb3); if (bb4) ext2fs_badblocks_list_free(bb4); return test_fail; }
void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, int replace_bad_blocks) { ext2_filsys fs = ctx->fs; errcode_t retval; badblocks_list bb_list = 0; FILE *f; char buf[1024]; e2fsck_read_bitmaps(ctx); /* * Make sure the bad block inode is sane. If there are any * illegal blocks, clear them. */ retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, check_bb_inode_blocks, 0); if (retval) { com_err("ext2fs_block_iterate", retval, "%s", _("while sanity checking the bad blocks inode")); goto fatal; } /* * If we're appending to the bad blocks inode, read in the * current bad blocks. */ if (!replace_bad_blocks) { retval = ext2fs_read_bb_inode(fs, &bb_list); if (retval) { com_err("ext2fs_read_bb_inode", retval, "%s", _("while reading the bad blocks inode")); goto fatal; } } /* * Now read in the bad blocks from the file; if * bad_blocks_file is null, then try to run the badblocks * command. */ if (bad_blocks_file) { f = fopen(bad_blocks_file, "r"); if (!f) { com_err("read_bad_blocks_file", errno, _("while trying to open %s"), bad_blocks_file); goto fatal; } } else { sprintf(buf, "badblocks -b %d -X %s%s%s %llu", fs->blocksize, (ctx->options & E2F_OPT_PREEN) ? "" : "-s ", (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "", fs->device_name, ext2fs_blocks_count(fs->super)-1); f = popen(buf, "r"); if (!f) { com_err("read_bad_blocks_file", errno, _("while trying popen '%s'"), buf); goto fatal; } } retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); if (bad_blocks_file) fclose(f); else pclose(f); if (retval) { com_err("ext2fs_read_bb_FILE", retval, "%s", _("while reading in list of bad blocks from file")); goto fatal; } /* * Finally, update the bad blocks from the bad_block_map */ printf("%s: Updating bad block inode.\n", ctx->device_name); retval = ext2fs_update_bb_inode(fs, bb_list); if (retval) { com_err("ext2fs_update_bb_inode", retval, "%s", _("while updating bad block inode")); goto fatal; } ext2fs_badblocks_list_free(bb_list); return; fatal: ctx->flags |= E2F_FLAG_ABORT; return; }
errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, ext2_inode_scan *ret_scan) { ext2_inode_scan scan; errcode_t retval; errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); /* * If fs->badblocks isn't set, then set it --- since the inode * scanning functions require it. */ if (fs->badblocks == 0) { /* * Temporarly save fs->get_blocks and set it to zero, * for compatibility with old e2fsck's. */ save_get_blocks = fs->get_blocks; fs->get_blocks = 0; retval = ext2fs_read_bb_inode(fs, &fs->badblocks); if (retval && fs->badblocks) { ext2fs_badblocks_list_free(fs->badblocks); fs->badblocks = 0; } fs->get_blocks = save_get_blocks; } retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); if (retval) return retval; memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); scan->magic = EXT2_ET_MAGIC_INODE_SCAN; scan->fs = fs; scan->inode_size = EXT2_INODE_SIZE(fs->super); scan->bytes_left = 0; scan->current_group = 0; scan->groups_left = fs->group_desc_count - 1; scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; scan->current_block = scan->fs-> group_desc[scan->current_group].bg_inode_table; scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); scan->blocks_left = scan->fs->inode_blocks_per_group; if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { scan->inodes_left -= fs->group_desc[scan->current_group].bg_itable_unused; scan->blocks_left = (scan->inodes_left + (fs->blocksize / scan->inode_size - 1)) * scan->inode_size / fs->blocksize; } retval = ext2fs_get_memalign(scan->inode_buffer_blocks * fs->blocksize, fs->blocksize, &scan->inode_buffer); scan->done_group = 0; scan->done_group_data = 0; scan->bad_block_ptr = 0; if (retval) { ext2fs_free_mem(&scan); return retval; } retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer); if (retval) { ext2fs_free_mem(&scan->inode_buffer); ext2fs_free_mem(&scan); return retval; } if (scan->fs->badblocks && scan->fs->badblocks->num) scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) scan->scan_flags |= EXT2_SF_DO_LAZY; *ret_scan = scan; return 0; }
void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, int replace_bad_blocks) { ext2_filsys fs = ctx->fs; errcode_t retval; badblocks_list bb_list = 0; FILE *f; char buf[1024]; e2fsck_read_bitmaps(ctx); retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, check_bb_inode_blocks, 0); if (retval) { com_err("ext2fs_block_iterate", retval, _("while sanity checking the bad blocks inode")); goto fatal; } if (!replace_bad_blocks) { retval = ext2fs_read_bb_inode(fs, &bb_list); if (retval) { com_err("ext2fs_read_bb_inode", retval, _("while reading the bad blocks inode")); goto fatal; } } if (bad_blocks_file) { f = fopen(bad_blocks_file, "r"); if (!f) { com_err("read_bad_blocks_file", errno, _("while trying to open %s"), bad_blocks_file); goto fatal; } } else { sprintf(buf, "badblocks -b %d -X %s%s%s %d", fs->blocksize, (ctx->options & E2F_OPT_PREEN) ? "" : "-s ", (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "", fs->device_name, fs->super->s_blocks_count-1); f = popen(buf, "r"); if (!f) { com_err("read_bad_blocks_file", errno, _("while trying popen '%s'"), buf); goto fatal; } } retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); if (bad_blocks_file) fclose(f); else pclose(f); if (retval) { com_err("ext2fs_read_bb_FILE", retval, _("while reading in list of bad blocks from file")); goto fatal; } printf("%s: Updating bad block inode.\n", ctx->device_name); retval = ext2fs_update_bb_inode(fs, bb_list); if (retval) { com_err("ext2fs_update_bb_inode", retval, _("while updating bad block inode")); goto fatal; } ext2fs_badblocks_list_free(bb_list); return; fatal: ctx->flags |= E2F_FLAG_ABORT; return; }