/* * This function is called to deallocate a block, and is an interator * functioned called by deallocate inode via ext2fs_iterate_block(). */ static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt, blk_t ref_block, int ref_offset, void *priv_data) { e2fsck_t ctx = (e2fsck_t) priv_data; if (HOLE_BLKADDR(*block_nr)) return 0; ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); ext2fs_unmark_block_bitmap(fs->block_map, *block_nr); return 0; }
static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), blk_t ref_block EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), void *priv_data) { e2fsck_t ctx = (e2fsck_t) priv_data; if (HOLE_BLKADDR(*block_nr)) return 0; if ((*block_nr < fs->super->s_first_data_block) || (*block_nr >= fs->super->s_blocks_count)) return 0; ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); ext2fs_block_alloc_stats(fs, *block_nr, -1); return 0; }
/* * This function is called to deallocate a block, and is an interator * functioned called by deallocate inode via ext2fs_iterate_block(). */ static int deallocate_inode_block(ext2_filsys fs, blk64_t *block_nr, e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), blk64_t ref_block EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), void *priv_data) { struct del_block *p = priv_data; if (HOLE_BLKADDR(*block_nr)) return 0; if ((*block_nr < fs->super->s_first_data_block) || (*block_nr >= ext2fs_blocks_count(fs->super))) return 0; ext2fs_unmark_block_bitmap2(p->ctx->block_found_map, *block_nr); ext2fs_block_alloc_stats2(fs, *block_nr, -1); p->num++; return 0; }
static int fill_dir_block(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt, blk_t ref_block EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), void *priv_data) { struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data; struct hash_entry *new_array, *ent; struct ext2_dir_entry *dirent; char *dir; unsigned int offset, dir_offset, rec_len; int hash_alg; if (blockcnt < 0) return 0; offset = blockcnt * fs->blocksize; if (offset + fs->blocksize > fd->inode->i_size) { fd->err = EXT2_ET_DIR_CORRUPTED; return BLOCK_ABORT; } dir = (fd->buf+offset); if (HOLE_BLKADDR(*block_nr)) { memset(dir, 0, fs->blocksize); dirent = (struct ext2_dir_entry *) dir; (void) ext2fs_set_rec_len(fs, fs->blocksize, dirent); } else { fd->err = ext2fs_read_dir_block(fs, *block_nr, dir); if (fd->err) return BLOCK_ABORT; } hash_alg = fs->super->s_def_hash_version; if ((hash_alg <= EXT2_HASH_TEA) && (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) hash_alg += 3; /* While the directory block is "hot", index it. */ dir_offset = 0; while (dir_offset < fs->blocksize) { dirent = (struct ext2_dir_entry *) (dir + dir_offset); (void) ext2fs_get_rec_len(fs, dirent, &rec_len); if (((dir_offset + rec_len) > fs->blocksize) || (rec_len < 8) || ((rec_len % 4) != 0) || (((dirent->name_len & 0xFF)+8) > rec_len)) { fd->err = EXT2_ET_DIR_CORRUPTED; return BLOCK_ABORT; } dir_offset += rec_len; if (dirent->inode == 0) continue; if (!fd->compress && ((dirent->name_len&0xFF) == 1) && (dirent->name[0] == '.')) continue; if (!fd->compress && ((dirent->name_len&0xFF) == 2) && (dirent->name[0] == '.') && (dirent->name[1] == '.')) { fd->parent = dirent->inode; continue; } if (fd->num_array >= fd->max_array) { new_array = realloc(fd->harray, sizeof(struct hash_entry) * (fd->max_array+500)); if (!new_array) { fd->err = ENOMEM; return BLOCK_ABORT; } fd->harray = new_array; fd->max_array += 500; } ent = fd->harray + fd->num_array++; ent->dir = dirent; fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); ent->ino = dirent->inode; if (fd->compress) ent->hash = ent->minor_hash = 0; else { fd->err = ext2fs_dirhash(hash_alg, dirent->name, dirent->name_len & 0xFF, fs->super->s_hash_seed, &ent->hash, &ent->minor_hash); if (fd->err) return BLOCK_ABORT; } } return 0; }