/*
 * emptydir.c --- clear empty directory blocks
 *
 * Copyright (C) 1998 Theodore Ts'o
 *
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Public
 * License.
 * %End-Header%
 *
 * This file has the necessary routines to search for empty directory
 * blocks and get rid of them.
 */

#include "e2fsck.h"
#include "problem.h"

/*
 * For e2fsck.h
 */
struct empty_dir_info_struct {
	ext2_dblist empty_dblist;
	ext2fs_block_bitmap empty_dir_blocks;
	ext2fs_inode_bitmap dir_map;
	char *block_buf;
	ext2_ino_t ino;
	struct ext2_inode inode;
	blk64_t	logblk;
	blk64_t	freed_blocks;
};

typedef struct empty_dir_info_struct *empty_dir_info;

extern empty_dir_info init_empty_dir(e2fsck_t ctx);
extern void free_empty_dirblock(empty_dir_info edi);
extern void add_empty_dirblock(empty_dir_info edi,
			       struct ext2_db_entry2 *db);
extern void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi);


empty_dir_info init_empty_dir(e2fsck_t ctx)
{
	empty_dir_info	edi;
	errcode_t	retval;

	edi = malloc(sizeof(struct empty_dir_info_struct));
	if (!edi)
		return NULL;

	memset(edi, 0, sizeof(struct empty_dir_info_struct));

	retval = ext2fs_init_dblist(ctx->fs, &edi->empty_dblist);
	if (retval)
		goto errout;

	retval = ext2fs_allocate_block_bitmap(ctx->fs, _("empty dirblocks"),
					      &edi->empty_dir_blocks);
	if (retval)
		goto errout;

	retval = ext2fs_allocate_inode_bitmap(ctx->fs, _("empty dir map"),
					      &edi->dir_map);
	if (retval)
		goto errout;

	return (edi);

errout:
	free_empty_dirblock(edi);
	return NULL;
}

void free_empty_dirblock(empty_dir_info edi)
{
	if (!edi)
		return;
	if (edi->empty_dblist)
		ext2fs_free_dblist(edi->empty_dblist);
	if (edi->empty_dir_blocks)
		ext2fs_free_block_bitmap(edi->empty_dir_blocks);
	if (edi->dir_map)
		ext2fs_free_inode_bitmap(edi->dir_map);

	memset(edi, 0, sizeof(struct empty_dir_info_struct));
	free(edi);
}

void add_empty_dirblock(empty_dir_info edi,
			struct ext2_db_entry2 *db)
{
	if (!edi || !db)
		return;

	if (db->ino == 11)
		return;		/* Inode number 11 is usually lost+found */

	printf(_("Empty directory block %u (#%d) in inode %u\n"),
	       db->blk, db->blockcnt, db->ino);

	ext2fs_mark_block_bitmap2(edi->empty_dir_blocks, db->blk);
	if (ext2fs_test_inode_bitmap(edi->dir_map, db->ino))
		return;
	ext2fs_mark_inode_bitmap(edi->dir_map, db->ino);

	ext2fs_add_dir_block2(edi->empty_dblist, db->ino,
			      db->blk, db->blockcnt);
}

/*
 * Helper function used by fix_directory.
 *
 * XXX need to finish this.  General approach is to use bmap to
 * iterate over all of the logical blocks using the bmap function, and
 * copy the block reference as necessary.  Big question --- what do
 * about error recovery?
 *
 * Also question --- how to free the indirect blocks.
 */
int empty_pass1(ext2_filsys fs, blk64_t *block_nr, e2_blkcnt_t blockcnt,
		blk64_t ref_block, int ref_offset, void *priv_data)
{
	empty_dir_info edi = (empty_dir_info) priv_data;
	blk64_t	block, new_block;
	errcode_t	retval;

	if (blockcnt < 0)
		return 0;
	block = *block_nr;
	do {
		retval = ext2fs_bmap2(fs, edi->ino, &edi->inode,
				      edi->block_buf, 0, edi->logblk, 0,
				      &new_block);
		if (retval)
			return DIRENT_ABORT;   /* XXX what to do? */
		if (new_block == 0)
			break;
		edi->logblk++;
	} while (ext2fs_test_block_bitmap2(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;
}

static int fix_directory(ext2_filsys fs,
			 struct ext2_db_entry2 *db,
			 void *priv_data)
{
	errcode_t	retval;

	empty_dir_info edi = (empty_dir_info) priv_data;

	edi->logblk = 0;
	edi->freed_blocks = 0;
	edi->ino = db->ino;

	retval = ext2fs_read_inode(fs, db->ino, &edi->inode);
	if (retval)
		return 0;

	retval = ext2fs_block_iterate3(fs, db->ino, 0, edi->block_buf,
				       empty_pass1, edi);
	if (retval)
		return 0;

	if (edi->freed_blocks) {
		edi->inode.i_size -= edi->freed_blocks * fs->blocksize;
		ext2fs_iblk_add_blocks(fs, &edi->inode, edi->freed_blocks);
		retval = ext2fs_write_inode(fs, db->ino, &edi->inode);
		if (retval)
			return 0;
	}
	return 0;
}

void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi)
{
	if (!edi)
		return;

	edi->block_buf = malloc(ctx->fs->blocksize * 3);

	if (edi->block_buf) {
		(void) ext2fs_dblist_iterate2(edi->empty_dblist,
					      fix_directory, &edi);
	}
	free(edi->block_buf);
	free_empty_dirblock(edi);
}

