Beispiel #1
0
static int process_block(ext2_filsys fs, blk_t	*block_nr,
			 e2_blkcnt_t blockcnt, blk_t ref_block,
			 int ref_offset, void *priv_data)
{
	struct process_block_struct *pb;
	errcode_t	retval;
	int		ret;
	blk_t		block, orig;

	pb = (struct process_block_struct *) priv_data;
	block = orig = *block_nr;
	ret = 0;
	
	/*
	 * Let's see if this is one which we need to relocate
	 */
	if (ext2fs_test_block_bitmap(pb->reserve, block)) {
		do {
			if (++block >= fs->super->s_blocks_count)
				block = fs->super->s_first_data_block;
			if (block == orig) {
				pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
				return BLOCK_ABORT;
			}
		} while (ext2fs_test_block_bitmap(pb->reserve, block) ||
			 ext2fs_test_block_bitmap(pb->alloc_map, block));

		retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
		if (retval) {
			pb->error = retval;
			return BLOCK_ABORT;
		}
		retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
		if (retval) {
			pb->error = retval;
			return BLOCK_ABORT;
		}
		*block_nr = block;
		ext2fs_mark_block_bitmap(pb->alloc_map, block);
		ret = BLOCK_CHANGED;
		if (pb->flags & EXT2_BMOVE_DEBUG)
			printf("ino=%ld, blockcnt=%lld, %u->%u\n", pb->ino,
			       blockcnt, orig, block);
	}
	if (pb->add_dir) {
		retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
					      block, (int) blockcnt);
		if (retval) {
			pb->error = retval;
			ret |= BLOCK_ABORT;
		}
	}
	return ret;
}
Beispiel #2
0
// Subfunction for "local_block_iterate3()" for check if blocks not allocated and not recovered
 static int check_block_stat(ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt,
                  blk64_t /*ref_blk*/x, int /*ref_offset*/y, void *priv )
{
//FIXME: 
	if (*blocknr >= fs->super->s_blocks_count)
		return BLOCK_ERROR;
	struct alloc_recover_stat *stat = priv;
        if ( ext2fs_test_block_bitmap (fs->block_map, *blocknr ))
		(stat->allocated)++ ;	
	if ((bmap) && ( ext2fs_test_block_bitmap (bmap, *blocknr )))
		(stat->recovered)++ ;
return 0;
}
Beispiel #3
0
void do_dump_unused(int argc EXT2FS_ATTR((unused)), char **argv)
{
	unsigned long	blk;
	unsigned char buf[EXT2_MAX_BLOCK_SIZE];
	unsigned int	i;
	errcode_t	retval;

	if (common_args_process(argc, argv, 1, 1,
				"dump_unused", "", 0))
		return;

	for (blk=current_fs->super->s_first_data_block;
	     blk < current_fs->super->s_blocks_count; blk++) {
		if (ext2fs_test_block_bitmap(current_fs->block_map,blk))
			continue;
		retval = io_channel_read_blk(current_fs->io, blk, 1, buf);
		if (retval) {
			com_err(argv[0], retval, "While reading block\n");
			return;
		}
		for (i=0; i < current_fs->blocksize; i++)
			if (buf[i])
				break;
		if (i >= current_fs->blocksize)
			continue;
		printf("\nUnused block %lu contains non-zero data:\n\n",
		       blk);
		for (i=0; i < current_fs->blocksize; i++)
			fputc(buf[i], stdout);
	}
}
Beispiel #4
0
//Subfunction for  "local_block_iterate3()" read a blocks of a long symlink 
static int read_syslink_block ( ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt,
                  blk64_t /*ref_blk*/x, int /*ref_offset*/y, void *priv )
{
	char *charbuf =((struct privat*)priv)->buf;
//	__u32 nbytes;
	errcode_t retval;
//	int blocksize = fs->blocksize;

	if (*blocknr >= fs->super->s_blocks_count)
		return BLOCK_ERROR;

	if (((struct privat*)priv)->flag){
        	int allocated = ext2fs_test_block_bitmap ( fs->block_map, *blocknr );
        	if ( allocated ){
			((struct privat*)priv)->error = 1;
//			fprintf(stderr,"Block %10lu is allocated.\n",*blocknr);
                	return (BLOCK_ABORT | BLOCK_ERROR);
		}
	}
	retval = io_channel_read_blk ( fs->io,  *blocknr,  1,  charbuf );
	if (retval){
		((struct privat*)priv)->error = retval;
		 return (BLOCK_ERROR);
	}
	if (bmap)
		ext2fs_mark_generic_bitmap(bmap, *blocknr);
return 0;
}
Beispiel #5
0
int empty_pass1(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt,
		blk_t ref_block, int ref_offset, void *priv_data)
{
	empty_dir_info edi = (empty_dir_info) priv_data;
	blk_t	block, new_block;
	errcode_t	retval;

	if (blockcnt < 0)
		return 0;
	block = *block_nr;
	do {
		retval = ext2fs_bmap(fs, edi->ino, &edi->inode,
				     edi->block_buf, 0, edi->logblk,
				     &new_block);
		if (retval)
			return DIRENT_ABORT;   
		if (new_block == 0)
			break;
		edi->logblk++;
	} while (ext2fs_test_block_bitmap(edi->empty_dir_blocks, new_block));

	if (new_block == block)
		return 0;
	if (new_block == 0)
		edi->freed_blocks++;
	*block_nr = new_block;
	return BLOCK_CHANGED;
}
//Subfunction for  "local_block_iterate3()" for load the first blocks to identify filetype 
int first_blocks ( ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt,
                  blk64_t /*ref_blk*/x, int /*ref_offset*/y, void *priv )
{
        char *charbuf = NULL;

	errcode_t retval;
	int blocksize = fs->blocksize;

	if ((blockcnt >= 12) || ((struct privat*)priv)->count >=12)
		return BLOCK_ABORT;
	charbuf = (char*)((struct privat*)priv)->buf + (blocksize * blockcnt);

	if (((struct privat*)priv)->flag){
        	int allocated = ext2fs_test_block_bitmap ( fs->block_map, *blocknr );
        	if ( allocated ){
			((struct privat*)priv)->error = BLOCK_ABORT | BLOCK_ERROR ;
                	return (BLOCK_ABORT | BLOCK_ERROR);
		}
	}

	retval = io_channel_read_blk ( fs->io,  *blocknr,  1,  charbuf );
	((struct privat*)priv)->count = blockcnt;
	if (retval){
		 ((struct privat*)priv)->error = BLOCK_ERROR ;
		 return (BLOCK_ERROR);
	}
return retval;
}
Beispiel #7
0
//Subfunction for  "local_block_iterate3()" for recover the blocks of a real file 
static int write_block ( ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt,
                  blk64_t /*ref_blk*/x, int /*ref_offset*/y, void *priv )
{
	int fd = ((struct privat*)priv)->fd;
        char *charbuf =((struct privat*)priv)->buf;
	__u32 nbytes;
	errcode_t retval;
	int blocksize = fs->blocksize;

	if (*blocknr >= fs->super->s_blocks_count)
		return BLOCK_ERROR;
#ifdef DEBUG
	printf("%c",(ext2fs_test_block_bitmap ( fs->block_map, *blocknr ))? 'X' : 'O');
#endif

	if (((struct privat*)priv)->flag){
        	int allocated = ext2fs_test_block_bitmap ( fs->block_map, *blocknr );
        	if ( allocated ){
//			fprintf(stderr,"Block %10lu is allocated.\n",*blocknr);
			((struct privat*)priv)->error = BLOCK_ABORT | BLOCK_ERROR ;
                	return (BLOCK_ABORT | BLOCK_ERROR);
		}
	}

	retval = io_channel_read_blk ( fs->io,  *blocknr,  1,  charbuf );
	if (retval){
		 ((struct privat*)priv)->error = BLOCK_ERROR ;
		 return (BLOCK_ERROR);
	}
	if (bmap)
		ext2fs_mark_generic_bitmap(bmap, *blocknr);

 	lseek(fd,(unsigned long long )blocksize * blockcnt, SEEK_SET);

	nbytes = write(fd, charbuf, blocksize);
        if ((unsigned) nbytes != blocksize){
		fprintf(stderr, "Error while writing file\n");
		((struct privat*)priv)->error = BLOCK_ERROR ;
        	return 8;
	}
return retval;
}
static int set_bad_block_proc(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 set_badblock_record *rec = (struct set_badblock_record *)
		priv_data;
	errcode_t	retval;
	blk_t		blk;

	if (blockcnt >= 0) {
		/*
		 * Get the next bad block.
		 */
		if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
			return BLOCK_ABORT;
		rec->bad_block_count++;
	} else {
		/*
		 * An indirect block; fetch a block from the
		 * previously used indirect block list.  The block
		 * most be not marked as used; if so, get another one.
		 * If we run out of reserved indirect blocks, allocate
		 * a new one.
		 */
	retry:
		if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
			blk = rec->ind_blocks[rec->ind_blocks_ptr++];
			if (ext2fs_test_block_bitmap(fs->block_map, blk))
				goto retry;
		} else {
			retval = ext2fs_new_block(fs, 0, 0, &blk);
			if (retval) {
				rec->err = retval;
				return BLOCK_ABORT;
			}
		}
		retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
		if (retval) {
			rec->err = retval;
			return BLOCK_ABORT;
		}
	}

	/*
	 * Update block counts
	 */
	ext2fs_block_alloc_stats(fs, blk, +1);

	*block_nr = blk;
	return BLOCK_CHANGED;
}
Beispiel #9
0
// Subfunction for "local_block_iterate3()" for check if the blocks allocated
 static int check_block(ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt,
                  blk64_t /*ref_blk*/x, int /*ref_offset*/y, void *priv )
{
//FIXME: 
	if (*blocknr >= fs->super->s_blocks_count)
		return BLOCK_ERROR;
	struct alloc_stat *stat = priv;
        if ( ext2fs_test_block_bitmap ( fs->block_map, *blocknr ))
		(stat->allocated)++ ;	
	else
		(stat->not_allocated)++ ;
	if (bmap)
		ext2fs_mark_generic_bitmap(bmap, *blocknr);
return 0;
}
Beispiel #10
0
/*
 * Verify the touched map
 */
static void check_map(void)
{
	int	i, j, first=1;
	unsigned long	blk;

	for (i=0; test_vec[i]; i++) {
		if (ext2fs_test_block_bitmap(touched_map, test_vec[i])) {
			printf("Bad block was touched --- %u\n", test_vec[i]);
			failed++;
			first_no_comma = 1;
		}
		ext2fs_mark_block_bitmap(touched_map, test_vec[i]);
	}
	for (i = 0; i < test_fs->group_desc_count; i++) {
		for (j=0, blk = test_fs->group_desc[i].bg_inode_table;
		     j < test_fs->inode_blocks_per_group;
		     j++, blk++) {
			if (!ext2fs_test_block_bitmap(touched_map, blk) &&
			    !ext2fs_test_block_bitmap(bad_block_map, blk)) {
				printf("Missing block --- %lu\n", blk);
				failed++;
			}
		}
	}
	printf("Bad inodes: ");
	for (i=1; i <= test_fs->super->s_inodes_count; i++) {
		if (ext2fs_test_inode_bitmap(bad_inode_map, i)) {
			if (first)
				first = 0;
			else
				printf(", ");
			printf("%u", i);
		}
	}
	printf("\n");
}
Beispiel #11
0
static void check_block_end(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	blk_t	end, save_blocks_count, i;
	struct problem_context	pctx;

	clear_problem_context(&pctx);

	end = fs->block_map->start +
		(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
	pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
						     &save_blocks_count);
	if (pctx.errcode) {
		pctx.num = 3;
		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
		return;
	}
	if (save_blocks_count == end)
		return;

	/* Protect loop from wrap-around if end is maxed */	
	for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
		if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
			if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
				for (i = save_blocks_count + 1; i <= end; i++)
					ext2fs_mark_block_bitmap(fs->block_map,
								 i);
				ext2fs_mark_bb_dirty(fs);
			} else
				ext2fs_unmark_valid(fs);
			break;
		}
	}

	pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
						     save_blocks_count, 0);
	if (pctx.errcode) {
		pctx.num = 4;
		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
		return;
	}
}
Beispiel #12
0
static void test_read_blk(unsigned long block, int count, errcode_t err)
{
	int	i;

	if (first_no_comma)
		first_no_comma = 0;
	else
		printf(", ");

	if (count > 1)
		printf("%lu-%lu", block, block+count-1);
	else
		printf("%lu", block);

	for (i=0; i < count; i++, block++) {
		if (ext2fs_test_block_bitmap(touched_map, block)) {
			printf("\nDuplicate block?!? --- %lu\n", block);
			failed++;
			first_no_comma = 1;
		}
		ext2fs_mark_block_bitmap(touched_map, block);
	}
}
Beispiel #13
0
errcode_t ext2fs_check_desc(ext2_filsys fs)
{
	ext2fs_block_bitmap bmap;
	errcode_t retval;
	dgrp_t i;
	blk_t first_block = fs->super->s_first_data_block;
	blk_t last_block = fs->super->s_blocks_count-1;
	blk_t blk, b;
	int j;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	retval = ext2fs_allocate_block_bitmap(fs, "check_desc map", &bmap);
	if (retval)
		return retval;

	for (i = 0; i < fs->group_desc_count; i++)
		ext2fs_reserve_super_and_bgd(fs, i, bmap);

	for (i = 0; i < fs->group_desc_count; i++) {
		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
					       EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
			first_block = ext2fs_group_first_block(fs, i);
			last_block = ext2fs_group_last_block(fs, i);
			if (i == (fs->group_desc_count - 1))
				last_block = fs->super->s_blocks_count-1;
		}

		blk = fs->group_desc[i].bg_block_bitmap;
		if (blk < first_block || blk > last_block ||
		    ext2fs_test_block_bitmap(bmap, blk)) {
			retval = EXT2_ET_GDESC_BAD_BLOCK_MAP;
			goto errout;
		}
		ext2fs_mark_block_bitmap(bmap, blk);

		blk = fs->group_desc[i].bg_inode_bitmap;
		if (blk < first_block || blk > last_block ||
		    ext2fs_test_block_bitmap(bmap, blk)) {
			retval = EXT2_ET_GDESC_BAD_INODE_MAP;
			goto errout;
		}
		ext2fs_mark_block_bitmap(bmap, blk);

		blk = fs->group_desc[i].bg_inode_table;
		if (blk < first_block ||
		    ((blk + fs->inode_blocks_per_group - 1) > last_block)) {
			retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
			goto errout;
		}
		for (j = 0, b = blk; j < fs->inode_blocks_per_group;
		     j++, b++) {
			if (ext2fs_test_block_bitmap(bmap, b)) {
				retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
				goto errout;
			}
			ext2fs_mark_block_bitmap(bmap, b);
		}
	}
errout:
	ext2fs_free_block_bitmap(bmap);
	return retval;
}
// search inode by use imap (step1: flag 1 = only directory ; step2: flag 0 = only file)
static void search_imap_inode(char* des_dir, __u32 t_after, __u32 t_before, int flag)
{
struct ext2_group_desc 			*gdp;
struct 	ext2_inode_large 		*inode;
//struct dir_list_head_t 			*dir = NULL;
struct ring_buf* 			i_list = NULL;
r_item*					item = NULL;
int  					zero_flag, retval, load, x ,i ;
char 					*pathname = NULL;
char					*i_pathname = NULL;
char 					*buf= NULL;
unsigned char				*tmp_buf = NULL;
__u32 					blocksize, inodesize, inode_max, inode_per_group, block_count;
__u32 					inode_per_block , inode_block_group, group;
blk_t 					block_nr;
__u32   				c_time, d_time, mode;
ext2_ino_t 				first_block_inode_nr , inode_nr;


pathname = malloc(26);
blocksize = current_fs->blocksize;
inodesize = current_fs->super->s_inode_size;
inode_max = current_fs->super->s_inodes_count;
inode_per_group = current_fs->super->s_inodes_per_group;
buf = malloc(blocksize);
if (! (flag & 0x01) ){
	tmp_buf = malloc (12 * blocksize);
	if (!tmp_buf)
		goto errout;
	cookie = magic_open(MAGIC_MIME | MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_ELF | MAGIC_CONTINUE);
	if ((! cookie) ||  magic_load(cookie, NULL)){
		fprintf(stderr,"ERROR: can't find libmagic\n");
		goto errout;
	}
}

inode_per_block = blocksize / inodesize;
inode_block_group = inode_per_group / inode_per_block;

for (group = 0 ; group < current_fs->group_desc_count ; group++){
#ifdef EXT2_FLAG_64BITS
	gdp = ext2fs_group_desc(current_fs, current_fs->group_desc, group);
#else
	gdp = &current_fs->group_desc[group];
#endif
	zero_flag = 0;

	if (!(flag & 0x02)){ //skip this in disaster mode
		// NEXT GROUP IF INODE NOT INIT
		if (gdp->bg_flags & (EXT2_BG_INODE_UNINIT)) continue;
	
		// SET ZERO-FLAG IF FREE INODES == INODE/GROUP for fast ext3 
		if (gdp->bg_free_inodes_count == inode_per_group) zero_flag = 1;
	}

//FIXME for struct ext4_group_desc 48/64BIT	
	for (block_nr = gdp->bg_inode_table , block_count = 0 ;
			 block_nr < (gdp->bg_inode_table + inode_block_group); block_nr++, block_count++) {
		
		if (!(flag & 0x02)){ //skip this in disaster mode
			// break if the first block only zero inode
			if ((block_count ==1) && (zero_flag == (inode_per_block + 1))) break;
		}

//FIXME  inode_max ????	
		first_block_inode_nr = (group * inode_per_group) + (block_count * inode_per_block) + 1;
		load = 0;
		for (i = 0; i<inode_per_block;i++){
			if ( ! ext2fs_test_block_bitmap(imap,first_block_inode_nr + i)){
				load++;
				break;
			}
		}

		if (load){		 
			retval = read_block ( current_fs , &block_nr , buf);
			if (retval) return;

			for (inode_nr = first_block_inode_nr ,x = 0; x < inode_per_block ; inode_nr++ , x++){

				if ( ! ext2fs_test_block_bitmap(imap,inode_nr)){
	
					inode = (struct ext2_inode_large*) (buf + (x*inodesize));
					c_time = ext2fs_le32_to_cpu(inode->i_ctime);
					mode = ext2fs_le32_to_cpu(inode->i_mode);
					if ( ! ( flag & 0x02)) { 
						//no check this inode in disaster mode
 						if ((! c_time ) && (!(inode->i_mode & LINUX_S_IFMT)) ) {
							if(zero_flag) zero_flag++ ;
						continue;
						}
	
						d_time = ext2fs_le32_to_cpu(inode->i_dtime);
						if ( (! d_time) || d_time <= t_after){
							ext2fs_mark_generic_bitmap(imap,inode_nr);
						continue;
						}
					}
// 1. magical step 
					if (LINUX_S_ISDIR(mode) && ( flag & 0x01) && (pathname)){ 
						sprintf(pathname,"<%lu>",(long unsigned int)inode_nr);

	
						struct dir_list_head_t * dir = NULL;
						if (flag & 0x02){
							//disaster mode 
							//only search for undeleted entry 
							dir = get_dir3(NULL,0, inode_nr , "MAGIC-1",pathname, t_after,t_before, 0);
							if (dir) {
								lookup_local(des_dir, dir,t_after,t_before, RECOV_ALL | LOST_DIR_SEARCH );
								clear_dir_list(dir);
							}
						}
						else{   //search for all 
							dir = get_dir3(NULL,0, inode_nr , "MAGIC-1",pathname, t_after,t_before, DELETED_OPT);
							if (dir) {
								lookup_local(des_dir,dir,t_after,t_before,DELETED_OPT|RECOV_ALL|LOST_DIR_SEARCH);
								clear_dir_list(dir);
							}
						}

						
					}

// 2. magical step
					if (! (flag & 0x01) ){
						i_list = get_j_inode_list(current_fs->super, inode_nr);
						item = get_undel_inode(i_list,t_after,t_before);
						ext2fs_mark_generic_bitmap(imap,inode_nr);

						if (item) {
							if (! LINUX_S_ISDIR(item->inode->i_mode) ) {
								i_pathname = identify_filename(i_pathname, tmp_buf,
										(struct ext2_inode*)item->inode, inode_nr);
								sprintf(pathname,"<%lu>",(long unsigned int)inode_nr);
								recover_file(des_dir,"MAGIC-2", ((i_pathname)?i_pathname : pathname),
									     (struct ext2_inode*)item->inode, inode_nr, 0);
								if(i_pathname){
									free(i_pathname);
									i_pathname = NULL;
								}
							}
						}
						if (i_list) ring_del(i_list);
					}	
				}
			}
		}
	}
}
errout:
	if (pathname)
		 free(pathname);

	if(buf) {
		free(buf);
		buf = NULL;
	}

	if (tmp_buf){
		free(tmp_buf);
		tmp_buf = NULL;
	}
	if (cookie){
		magic_close(cookie);
		cookie = 0;
	}
return;
}