/*
 * filefrag.c --- display the fragmentation information for a file
 *
 * Copyright (C) 2011 Theodore Ts'o.  This file may be redistributed
 * under the terms of the GNU Public License.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
extern int optind;
extern char *optarg;
#endif

#include "debugfs.h"

#define VERBOSE_OPT	0x0001
#define DIR_OPT		0x0002
#define RECURSIVE_OPT	0x0004

struct dir_list {
	char		*name;
	ext2_ino_t	ino;
	struct dir_list	*next;
};

struct filefrag_struct {
	FILE		*f;
	const char	*name;
	const char	*dir_name;
	int		options;
	int		logical_width;
	int		physical_width;
	int		ext;
	int		cont_ext;
	e2_blkcnt_t	num;
	e2_blkcnt_t	logical_start;
	blk64_t		physical_start;
	blk64_t		expected;
	struct dir_list *dir_list, *dir_last;
};

static int int_log10(unsigned long long arg)
{
	int     l = 0;

	arg = arg / 10;
	while (arg) {
		l++;
		arg = arg / 10;
	}
	return l;
}

static void print_header(struct filefrag_struct *fs)
{
	if (fs->options & VERBOSE_OPT) {
		fprintf(fs->f, "%4s %*s %*s %*s %*s\n", "ext",
			fs->logical_width, "logical", fs->physical_width,
			"physical", fs->physical_width, "expected",
			fs->logical_width, "length");
	}
}

static void report_filefrag(struct filefrag_struct *fs)
{
	if (fs->num == 0)
		return;
	if (fs->options & VERBOSE_OPT) {
		if (fs->expected)
			fprintf(fs->f, "%4d %*lu %*llu %*llu %*lu\n", fs->ext,
				fs->logical_width,
				(unsigned long) fs->logical_start,
				fs->physical_width, fs->physical_start,
				fs->physical_width, fs->expected,
				fs->logical_width, (unsigned long) fs->num);
		else
			fprintf(fs->f, "%4d %*lu %*llu %*s %*lu\n", fs->ext,
				fs->logical_width,
				(unsigned long) fs->logical_start,
				fs->physical_width, fs->physical_start,
				fs->physical_width, "",
				fs->logical_width, (unsigned long) fs->num);
	}
	fs->ext++;
}

static int filefrag_blocks_proc(ext2_filsys ext4_fs EXT2FS_ATTR((unused)),
				blk64_t *blocknr, e2_blkcnt_t blockcnt,
				blk64_t ref_block EXT2FS_ATTR((unused)),
				int ref_offset EXT2FS_ATTR((unused)),
				void *private)
{
	struct filefrag_struct *fs = private;

	if (blockcnt < 0 || *blocknr == 0)
		return 0;

	if ((fs->num == 0) || (blockcnt != fs->logical_start + fs->num) ||
	    (*blocknr != fs->physical_start + fs->num)) {
		report_filefrag(fs);
		if (blockcnt == fs->logical_start + fs->num)
			fs->expected = fs->physical_start + fs->num;
		else
			fs->expected = 0;
		fs->logical_start = blockcnt;
		fs->physical_start = *blocknr;
		fs->num = 1;
		fs->cont_ext++;
	} else
		fs->num++;
	return 0;
}

static void filefrag(ext2_ino_t ino, struct ext2_inode *inode,
		     struct filefrag_struct *fs)
{
	errcode_t	retval;
	int		blocksize = current_fs->blocksize;

	fs->logical_width = int_log10((EXT2_I_SIZE(inode) + blocksize - 1) /
				      blocksize) + 1;
	if (fs->logical_width < 7)
		fs->logical_width = 7;
	fs->ext = 0;
	fs->cont_ext = 0;
	fs->logical_start = 0;
	fs->physical_start = 0;
	fs->num = 0;

	if (fs->options & VERBOSE_OPT) {
		blk64_t num_blocks = ext2fs_inode_i_blocks(current_fs, inode);

		if (!(current_fs->super->s_feature_ro_compat &
		     EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
		    !(inode->i_flags & EXT4_HUGE_FILE_FL))
			num_blocks /= current_fs->blocksize / 512;

		fprintf(fs->f, "\n%s has %llu block(s), i_size is %llu\n",
			fs->name, num_blocks, EXT2_I_SIZE(inode));
	}
	print_header(fs);
	retval = ext2fs_block_iterate3(current_fs, ino,
				       BLOCK_FLAG_READ_ONLY, NULL,
				       filefrag_blocks_proc, fs);
	if (retval)
		com_err("ext2fs_block_iterate3", retval, 0);

	report_filefrag(fs);
	fprintf(fs->f, "%s: %d contiguous extents%s\n", fs->name, fs->ext,
		LINUX_S_ISDIR(inode->i_mode) ? " (dir)" : "");
}

static int filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
			     int	entry,
			     struct ext2_dir_entry *dirent,
			     int	offset EXT2FS_ATTR((unused)),
			     int	blocksize EXT2FS_ATTR((unused)),
			     char	*buf EXT2FS_ATTR((unused)),
			     void	*private)
{
	struct filefrag_struct *fs = private;
	struct ext2_inode	inode;
	ext2_ino_t		ino;
	char			name[EXT2_NAME_LEN + 1];
	char			*cp;
	int			thislen;

	if (entry == DIRENT_DELETED_FILE)
		return 0;

	thislen = dirent->name_len & 0xFF;
	strncpy(name, dirent->name, thislen);
	name[thislen] = '\0';
	ino = dirent->inode;

	if (!strcmp(name, ".") || !strcmp(name, ".."))
		return 0;

	cp = malloc(strlen(fs->dir_name) + strlen(name) + 2);
	if (!cp) {
		fprintf(stderr, "Couldn't allocate memory for %s/%s\n",
			fs->dir_name, name);
		return 0;
	}

	sprintf(cp, "%s/%s", fs->dir_name, name);
	fs->name = cp;

	if (debugfs_read_inode(ino, &inode, fs->name))
		goto errout;

	filefrag(ino, &inode, fs);

	if ((fs->options & RECURSIVE_OPT) && LINUX_S_ISDIR(inode.i_mode)) {
		struct dir_list *p;

		p = malloc(sizeof(struct dir_list));
		if (!p) {
			fprintf(stderr, "Couldn't allocate dir_list for %s\n",
				fs->name);
			goto errout;
		}
		memset(p, 0, sizeof(struct dir_list));
		p->name = cp;
		p->ino = ino;
		if (fs->dir_last)
			fs->dir_last->next = p;
		else
			fs->dir_list = p;
		fs->dir_last = p;
		return 0;
	}
errout:
	free(cp);
	fs->name = 0;
	return 0;
}


static void dir_iterate(ext2_ino_t ino, struct filefrag_struct *fs)
{
	errcode_t	retval;
	struct dir_list	*p = NULL;

	fs->dir_name = fs->name;

	while (1) {
		retval = ext2fs_dir_iterate2(current_fs, ino, 0,
					     0, filefrag_dir_proc, fs);
		if (retval)
			com_err("ext2fs_dir_iterate2", retval, 0);
		if (p) {
			free(p->name);
			fs->dir_list = p->next;
			if (!fs->dir_list)
				fs->dir_last = 0;
			free(p);
		}
		p = fs->dir_list;
		if (!p)
			break;
		ino = p->ino;
		fs->dir_name = p->name;
	}
}

void do_filefrag(int argc, char *argv[])
{
	struct filefrag_struct fs;
	struct ext2_inode inode;
	ext2_ino_t	ino;
	int		c;

	memset(&fs, 0, sizeof(fs));
	if (check_fs_open(argv[0]))
		return;

	reset_getopt();
	while ((c = getopt(argc, argv, "dvr")) != EOF) {
		switch (c) {
		case 'd':
			fs.options |= DIR_OPT;
			break;
		case 'v':
			fs.options |= VERBOSE_OPT;
			break;
		case 'r':
			fs.options |= RECURSIVE_OPT;
			break;
		default:
			goto print_usage;
		}
	}

	if (argc > optind+1) {
	print_usage:
		com_err(0, 0, "Usage: filefrag [-dvr] file");
		return;
	}

	if (argc == optind) {
		ino = cwd;
		fs.name = ".";
	} else {
		ino = string_to_inode(argv[optind]);
		fs.name = argv[optind];
	}
	if (!ino)
		return;

	if (debugfs_read_inode(ino, &inode, argv[0]))
		return;

	fs.f = open_pager();
	fs.physical_width = int_log10(ext2fs_blocks_count(current_fs->super));
	fs.physical_width++;
	if (fs.physical_width < 8)
		fs.physical_width = 8;

	if (!LINUX_S_ISDIR(inode.i_mode) || (fs.options & DIR_OPT))
		filefrag(ino, &inode, &fs);
	else
		dir_iterate(ino, &fs);

	fprintf(fs.f, "\n");
	close_pager(fs.f);

	return;
}
