/*
 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "libxfs.h"
#include "command.h"
#include "type.h"
#include "fprint.h"
#include "faddr.h"
#include "field.h"
#include "bmap.h"
#include "io.h"
#include "inode.h"
#include "output.h"
#include "init.h"

static int		bmap_f(int argc, char **argv);
static int		bmap_one_extent(xfs_bmbt_rec_t *ep,
					xfs_fileoff_t *offp, xfs_fileoff_t eoff,
					int *idxp, bmap_ext_t *bep);
static xfs_fsblock_t	select_child(xfs_fileoff_t off, xfs_bmbt_key_t *kp,
				     xfs_bmbt_ptr_t *pp, int nrecs);

static const cmdinfo_t	bmap_cmd =
	{ "bmap", NULL, bmap_f, 0, 3, 0, N_("[-ad] [block [len]]"),
	  N_("show block map for current file"), NULL };

void
bmap(
	xfs_fileoff_t		offset,
	xfs_filblks_t		len,
	int			whichfork,
	int			*nexp,
	bmap_ext_t		*bep)
{
	struct xfs_btree_block	*block;
	xfs_fsblock_t		bno;
	xfs_fileoff_t		curoffset;
	xfs_dinode_t		*dip;
	xfs_fileoff_t		eoffset;
	xfs_bmbt_rec_t		*ep;
	xfs_dinode_fmt_t	fmt;
	int			fsize;
	xfs_bmbt_key_t		*kp;
	int			n;
	int			nex;
	xfs_fsblock_t		nextbno;
	int			nextents;
	xfs_bmbt_ptr_t		*pp;
	xfs_bmdr_block_t	*rblock;
	typnm_t			typ;
	xfs_bmbt_rec_t		*xp;

	push_cur();
	set_cur_inode(iocur_top->ino);
	nex = *nexp;
	*nexp = 0;
	ASSERT(nex > 0);
	dip = iocur_top->data;
	n = 0;
	eoffset = offset + len - 1;
	curoffset = offset;
	fmt = (xfs_dinode_fmt_t)XFS_DFORK_FORMAT(dip, whichfork);
	typ = whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA;
	ASSERT(typtab[typ].typnm == typ);
	ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS ||
		fmt == XFS_DINODE_FMT_BTREE);
	if (fmt == XFS_DINODE_FMT_EXTENTS) {
		nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
		xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
		for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
			if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep))
				break;
		}
	} else if (fmt == XFS_DINODE_FMT_BTREE) {
		push_cur();
		rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
		fsize = XFS_DFORK_SIZE(dip, mp, whichfork);
		pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(fsize, 0));
		kp = XFS_BMDR_KEY_ADDR(rblock, 1);
		bno = select_child(curoffset, kp, pp,
					be16_to_cpu(rblock->bb_numrecs));
		for (;;) {
			set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno),
				blkbb, DB_RING_IGN, NULL);
			block = (struct xfs_btree_block *)iocur_top->data;
			if (be16_to_cpu(block->bb_level) == 0)
				break;
			pp = XFS_BMBT_PTR_ADDR(mp, block, 1,
				xfs_bmbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0));
			kp = XFS_BMBT_KEY_ADDR(mp, block, 1);
			bno = select_child(curoffset, kp, pp,
					be16_to_cpu(block->bb_numrecs));
		}
		for (;;) {
			nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
			nextents = be16_to_cpu(block->bb_numrecs);
			xp = (xfs_bmbt_rec_t *)
				XFS_BMBT_REC_ADDR(mp, block, 1);
			for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
				if (!bmap_one_extent(ep, &curoffset, eoffset,
						&n, bep)) {
					nextbno = NULLFSBLOCK;
					break;
				}
			}
			bno = nextbno;
			if (bno == NULLFSBLOCK)
				break;
			set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno),
				blkbb, DB_RING_IGN, NULL);
			block = (struct xfs_btree_block *)iocur_top->data;
		}
		pop_cur();
	}
	pop_cur();
	*nexp = n;
}

static int
bmap_f(
	int		argc,
	char		**argv)
{
	int		afork = 0;
	bmap_ext_t	be;
	int		c;
	xfs_fileoff_t	co, cosave;
	int		dfork = 0;
	xfs_dinode_t	*dip;
	xfs_fileoff_t	eo;
	xfs_filblks_t	len;
	int		nex;
	char		*p;
	int		whichfork;

	if (iocur_top->ino == NULLFSINO) {
		dbprintf(_("no current inode\n"));
		return 0;
	}
	optind = 0;
	if (argc) while ((c = getopt(argc, argv, "ad")) != EOF) {
		switch (c) {
		case 'a':
			afork = 1;
			break;
		case 'd':
			dfork = 1;
			break;
		default:
			dbprintf(_("bad option for bmap command\n"));
			return 0;
		}
	}
	if (afork + dfork == 0) {
		push_cur();
		set_cur_inode(iocur_top->ino);
		dip = iocur_top->data;
		if (be32_to_cpu(dip->di_nextents))
			dfork = 1;
		if (be16_to_cpu(dip->di_anextents))
			afork = 1;
		pop_cur();
	}
	if (optind < argc) {
		co = (xfs_fileoff_t)strtoull(argv[optind], &p, 0);
		if (*p != '\0') {
			dbprintf(_("bad block number for bmap %s\n"),
				argv[optind]);
			return 0;
		}
		optind++;
		if (optind < argc) {
			len = (xfs_filblks_t)strtoull(argv[optind], &p, 0);
			if (*p != '\0') {
				dbprintf(_("bad len for bmap %s\n"), argv[optind]);
				return 0;
			}
			eo = co + len - 1;
		} else
			eo = co;
	} else {
		co = 0;
		eo = -1;
	}
	cosave = co;
	for (whichfork = XFS_DATA_FORK;
	     whichfork <= XFS_ATTR_FORK;
	     whichfork++) {
		if (whichfork == XFS_DATA_FORK && !dfork)
			continue;
		if (whichfork == XFS_ATTR_FORK && !afork)
			continue;
		for (;;) {
			nex = 1;
			bmap(co, eo - co + 1, whichfork, &nex, &be);
			if (nex == 0)
				break;
			dbprintf(_("%s offset %lld startblock %llu (%u/%u) count "
				 "%llu flag %u\n"),
				whichfork == XFS_DATA_FORK ? _("data") : _("attr"),
				be.startoff, be.startblock,
				XFS_FSB_TO_AGNO(mp, be.startblock),
				XFS_FSB_TO_AGBNO(mp, be.startblock),
				be.blockcount, be.flag);
			co = be.startoff + be.blockcount;
		}
		co = cosave;
	}
	return 0;
}

void
bmap_init(void)
{
	add_command(&bmap_cmd);
}

static int
bmap_one_extent(
	xfs_bmbt_rec_t		*ep,
	xfs_fileoff_t		*offp,
	xfs_fileoff_t		eoff,
	int			*idxp,
	bmap_ext_t		*bep)
{
	xfs_filblks_t		c;
	xfs_fileoff_t		curoffset;
	int			f;
	int			idx;
	xfs_fileoff_t		o;
	xfs_fsblock_t		s;

	convert_extent(ep, &o, &s, &c, &f);
	curoffset = *offp;
	idx = *idxp;
	if (o + c <= curoffset)
		return 1;
	if (o > eoff)
		return 0;
	if (o < curoffset) {
		c -= curoffset - o;
		s += curoffset - o;
		o = curoffset;
	}
	if (o + c - 1 > eoff)
		c -= (o + c - 1) - eoff;
	bep[idx].startoff = o;
	bep[idx].startblock = s;
	bep[idx].blockcount = c;
	bep[idx].flag = f;
	*idxp = idx + 1;
	*offp = o + c;
	return 1;
}

void
convert_extent(
	xfs_bmbt_rec_t		*rp,
	xfs_fileoff_t		*op,
	xfs_fsblock_t		*sp,
	xfs_filblks_t		*cp,
	int			*fp)
{
	struct xfs_bmbt_irec	irec;

	libxfs_bmbt_disk_get_all(rp, &irec);
	*fp = irec.br_state == XFS_EXT_UNWRITTEN;
	*op = irec.br_startoff;
	*sp = irec.br_startblock;
	*cp = irec.br_blockcount;
}

void
make_bbmap(
	bbmap_t		*bbmap,
	int		nex,
	bmap_ext_t	*bmp)
{
	int		i;

	for (i = 0; i < nex; i++) {
		bbmap->b[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock);
		bbmap->b[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount);
	}
	bbmap->nmaps = nex;
}

static xfs_fsblock_t
select_child(
	xfs_fileoff_t	off,
	xfs_bmbt_key_t	*kp,
	xfs_bmbt_ptr_t	*pp,
	int		nrecs)
{
	int		i;

	for (i = 0; i < nrecs; i++) {
		if (be64_to_cpu(kp[i].br_startoff) == off)
			return be64_to_cpu(pp[i]);
		if (be64_to_cpu(kp[i].br_startoff) > off) {
			if (i == 0)
				return be64_to_cpu(pp[i]);
			else
				return be64_to_cpu(pp[i - 1]);
		}
	}
	return be64_to_cpu(pp[nrecs - 1]);
}
