/* fsys_xfs.c - an implementation for the SGI XFS file system */
/*  
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2001,2002,2004  Free Software Foundation, Inc.
 *
 *  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; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will 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 to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifdef FSYS_XFS

#include "shared.h"
#include "filesys.h"
#include "xfs.h"

#define MAX_LINK_COUNT	8

typedef struct xad {
	xfs_fileoff_t offset;
	xfs_fsblock_t start;
	xfs_filblks_t len;
} xad_t;

struct xfs_info {
	int bsize;
	int dirbsize;
	int isize;
	unsigned int agblocks;
	int bdlog;
	int blklog;
	int inopblog;
	int agblklog;
	int agnolog;
	unsigned int nextents;
	xfs_daddr_t next;
	xfs_daddr_t daddr;
	xfs_dablk_t forw;
	xfs_dablk_t dablk;
	xfs_bmbt_rec_32_t *xt;
	xfs_bmbt_ptr_t ptr0;
	int btnode_ptr0_off;
	int i8param;
	int dirpos;
	int dirmax;
	int blkoff;
	int fpos;
	xfs_ino_t rootino;
};

static struct xfs_info xfs;

#define dirbuf		((char *)FSYS_BUF)
#define filebuf		((char *)FSYS_BUF + 4096)
#define inode		((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
#define icore		(inode->di_core)

#define	mask32lo(n)	(((xfs_uint32_t)1 << (n)) - 1)

#define	XFS_INO_MASK(k)		((xfs_uint32_t)((1ULL << (k)) - 1))
#define	XFS_INO_OFFSET_BITS	xfs.inopblog
#define	XFS_INO_AGBNO_BITS	xfs.agblklog
#define	XFS_INO_AGINO_BITS	(xfs.agblklog + xfs.inopblog)
#define	XFS_INO_AGNO_BITS	xfs.agnolog

static inline xfs_agblock_t
agino2agbno (xfs_agino_t agino)
{
	return agino >> XFS_INO_OFFSET_BITS;
}

static inline xfs_agnumber_t
ino2agno (xfs_ino_t ino)
{
	return ino >> XFS_INO_AGINO_BITS;
}

static inline xfs_agino_t
ino2agino (xfs_ino_t ino)
{
	return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
}

static inline int
ino2offset (xfs_ino_t ino)
{
	return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
}

static inline __const__ xfs_uint16_t
le16 (xfs_uint16_t x)
{
	__asm__("xchgb %b0,%h0"	\
		: "=q" (x) \
		:  "0" (x)); \
		return x;
}

static inline __const__ xfs_uint32_t
le32 (xfs_uint32_t x)
{
#if 0
        /* 386 doesn't have bswap.  */
	__asm__("bswap %0" : "=r" (x) : "0" (x));
#else
	/* This is slower but this works on all x86 architectures.  */
	__asm__("xchgb %b0, %h0" \
		"\n\troll $16, %0" \
		"\n\txchgb %b0, %h0" \
		: "=q" (x) : "0" (x));
#endif
	return x;
}

static inline __const__ xfs_uint64_t
le64 (xfs_uint64_t x)
{
	xfs_uint32_t h = x >> 32;
        xfs_uint32_t l = x & ((1ULL<<32)-1);
        return (((xfs_uint64_t)le32(l)) << 32) | ((xfs_uint64_t)(le32(h)));
}


static xfs_fsblock_t
xt_start (xfs_bmbt_rec_32_t *r)
{
	return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) | 
	       (((xfs_fsblock_t)le32 (r->l2)) << 11) |
	       (((xfs_fsblock_t)le32 (r->l3)) >> 21);
}

static xfs_fileoff_t
xt_offset (xfs_bmbt_rec_32_t *r)
{
	return (((xfs_fileoff_t)le32 (r->l0) &
		mask32lo(31)) << 23) |
		(((xfs_fileoff_t)le32 (r->l1)) >> 9);
}

static xfs_filblks_t
xt_len (xfs_bmbt_rec_32_t *r)
{
	return le32(r->l3) & mask32lo(21);
}

static inline int
xfs_highbit32(xfs_uint32_t v)
{
	int i;

	if (--v) {
		for (i = 0; i < 31; i++, v >>= 1) {
			if (v == 0)
				return i;
		}
	}
	return 0;
}

static int
isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
{
	return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
}

static xfs_daddr_t
agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
{
	return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
}

static xfs_daddr_t
fsb2daddr (xfs_fsblock_t fsbno)
{
	return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
			 (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
}

#undef offsetof
#define offsetof(t,m)	((int)&(((t *)0)->m))

static inline int
btroot_maxrecs (void)
{
	int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;

	return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
		(sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
}

static int
di_read (xfs_ino_t ino)
{
	xfs_agino_t agino;
	xfs_agnumber_t agno;
	xfs_agblock_t agbno;
	xfs_daddr_t daddr;
	int offset;

	agno = ino2agno (ino);
	agino = ino2agino (ino);
	agbno = agino2agbno (agino);
	offset = ino2offset (ino);
	daddr = agb2daddr (agno, agbno);

	devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);

	xfs.ptr0 = *(xfs_bmbt_ptr_t *)
		    (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
		    + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));

	return 1;
}

static void
init_extents (void)
{
	xfs_bmbt_ptr_t ptr0;
	xfs_btree_lblock_t h;

	switch (icore.di_format) {
	case XFS_DINODE_FMT_EXTENTS:
		xfs.xt = inode->di_u.di_bmx;
		xfs.nextents = le32 (icore.di_nextents);
		break;
	case XFS_DINODE_FMT_BTREE:
		ptr0 = xfs.ptr0;
		for (;;) {
			xfs.daddr = fsb2daddr (le64(ptr0));
			devread (xfs.daddr, 0,
				 sizeof(xfs_btree_lblock_t), (char *)&h);
			if (!h.bb_level) {
				xfs.nextents = le16(h.bb_numrecs);
				xfs.next = fsb2daddr (le64(h.bb_rightsib));
				xfs.fpos = sizeof(xfs_btree_block_t);
				return;
			}
			devread (xfs.daddr, xfs.btnode_ptr0_off,
				 sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
		}
	}
}

static xad_t *
next_extent (void)
{
	static xad_t xad;

	switch (icore.di_format) {
	case XFS_DINODE_FMT_EXTENTS:
		if (xfs.nextents == 0)
			return NULL;
		break;
	case XFS_DINODE_FMT_BTREE:
		if (xfs.nextents == 0) {
			xfs_btree_lblock_t h;
			if (xfs.next == 0)
				return NULL;
			xfs.daddr = xfs.next;
			devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
			xfs.nextents = le16(h.bb_numrecs);
			xfs.next = fsb2daddr (le64(h.bb_rightsib));
			xfs.fpos = sizeof(xfs_btree_block_t);
		}
		/* Yeah, I know that's slow, but I really don't care */
		devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
		xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
		xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
	}
	xad.offset = xt_offset (xfs.xt);
	xad.start = xt_start (xfs.xt);
	xad.len = xt_len (xfs.xt);
	++xfs.xt;
	--xfs.nextents;

	return &xad;
}

/*
 * Name lies - the function reads only first 100 bytes
 */
static void
xfs_dabread (void)
{
	xad_t *xad;
	xfs_fileoff_t offset;;

	init_extents ();
	while ((xad = next_extent ())) {
		offset = xad->offset;
		if (isinxt (xfs.dablk, offset, xad->len)) {
			devread (fsb2daddr (xad->start + xfs.dablk - offset),
				 0, 100, dirbuf);
			break;
		}
	}
}

static inline xfs_ino_t
sf_ino (char *sfe, int namelen)
{
	void *p = sfe + namelen + 3;

	return (xfs.i8param == 0)
		? le64(*(xfs_ino_t *)p) : le32(*(xfs_uint32_t *)p);
}

static inline xfs_ino_t
sf_parent_ino (void)
{
	return (xfs.i8param == 0)
		? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
		: le32(*(xfs_uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
}

static inline int
roundup8 (int n)
{
	return ((n+7)&~7);
}

static char *
next_dentry (xfs_ino_t *ino)
{
	int namelen = 1;
	int toread;
	static char usual[2][3] = {".", ".."};
	static xfs_dir2_sf_entry_t *sfe;
	char *name = usual[0];

	if (xfs.dirpos >= xfs.dirmax) {
		if (xfs.forw == 0)
			return NULL;
		xfs.dablk = xfs.forw;
		xfs_dabread ();
#define h	((xfs_dir2_leaf_hdr_t *)dirbuf)
		xfs.dirmax = le16 (h->count) - le16 (h->stale);
		xfs.forw = le32 (h->info.forw);
#undef h
		xfs.dirpos = 0;
	}

	switch (icore.di_format) {
	case XFS_DINODE_FMT_LOCAL:
		switch (xfs.dirpos) {
		case -2:
			*ino = 0;
			break;
		case -1:
			*ino = sf_parent_ino ();
			++name;
			++namelen;
			sfe = (xfs_dir2_sf_entry_t *)
				(inode->di_u.di_c 
				 + sizeof(xfs_dir2_sf_hdr_t)
				 - xfs.i8param);
			break;
		default:
			namelen = sfe->namelen;
			*ino = sf_ino ((char *)sfe, namelen);
			name = sfe->name;
			sfe = (xfs_dir2_sf_entry_t *)
				  ((char *)sfe + namelen + 11 - xfs.i8param);
		}
		break;
	case XFS_DINODE_FMT_BTREE:
	case XFS_DINODE_FMT_EXTENTS:
#define dau	((xfs_dir2_data_union_t *)dirbuf)
		for (;;) {
			if (xfs.blkoff >= xfs.dirbsize) {
				xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
				filepos &= ~(xfs.dirbsize - 1);
				filepos |= xfs.blkoff;
			}
			xfs_read (dirbuf, 4);
			xfs.blkoff += 4;
			if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
				toread = roundup8 (le16(dau->unused.length)) - 4;
				xfs.blkoff += toread;
				filepos += toread;
				continue;
			}
			break;
		}
		xfs_read ((char *)dirbuf + 4, 5);
		*ino = le64 (dau->entry.inumber);
		namelen = dau->entry.namelen;
#undef dau
		toread = roundup8 (namelen + 11) - 9;
		xfs_read (dirbuf, toread);
		name = (char *)dirbuf;
		xfs.blkoff += toread + 5;
	}
	++xfs.dirpos;
	name[namelen] = 0;

	return name;
}

static char *
first_dentry (xfs_ino_t *ino)
{
	xfs.forw = 0;
	switch (icore.di_format) {
	case XFS_DINODE_FMT_LOCAL:
		xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
		xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
		xfs.dirpos = -2;
		break;
	case XFS_DINODE_FMT_EXTENTS:
	case XFS_DINODE_FMT_BTREE:
		filepos = 0;
		xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
		if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
#define tail		((xfs_dir2_block_tail_t *)dirbuf)
			filepos = xfs.dirbsize - sizeof(*tail);
			xfs_read (dirbuf, sizeof(*tail));
			xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
#undef tail
		} else {
			xfs.dablk = (1ULL << 35) >> xfs.blklog;
#define h		((xfs_dir2_leaf_hdr_t *)dirbuf)
#define n		((xfs_da_intnode_t *)dirbuf)
			for (;;) {
				xfs_dabread ();
				if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
				    || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
					xfs.dirmax = le16 (h->count) - le16 (h->stale);
					xfs.forw = le32 (h->info.forw);
					break;
				}
				xfs.dablk = le32 (n->btree[0].before);
			}
#undef n
#undef h
		}
		xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
		filepos = xfs.blkoff;
		xfs.dirpos = 0;
	}
	return next_dentry (ino);
}

int
xfs_mount (void)
{
	xfs_sb_t super;

	if (!devread (0, 0, sizeof(super), (char *)&super)
	    || (le32(super.sb_magicnum) != XFS_SB_MAGIC)
	    || ((le16(super.sb_versionnum) 
		& XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
		return 0;
	}

	xfs.bsize = le32 (super.sb_blocksize);
	xfs.blklog = super.sb_blocklog;
	xfs.bdlog = xfs.blklog - SECTOR_BITS;
	xfs.rootino = le64 (super.sb_rootino);
	xfs.isize = le16 (super.sb_inodesize);
	xfs.agblocks = le32 (super.sb_agblocks);
	xfs.dirbsize = xfs.bsize << super.sb_dirblklog;

	xfs.inopblog = super.sb_inopblog;
	xfs.agblklog = super.sb_agblklog;
	xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));

	xfs.btnode_ptr0_off =
		((xfs.bsize - sizeof(xfs_btree_block_t)) /
		(sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
		 * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);

	return 1;
}

int
xfs_read (char *buf, int len)
{
	xad_t *xad;
	xfs_fileoff_t endofprev, endofcur, offset;
	xfs_filblks_t xadlen;
	int toread, startpos, endpos;

	if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
		grub_memmove (buf, inode->di_u.di_c + filepos, len);
		filepos += len;
		return len;
	}

	startpos = filepos;
	endpos = filepos + len;
	endofprev = (xfs_fileoff_t)-1;
	init_extents ();
	while (len > 0 && (xad = next_extent ())) {
		offset = xad->offset;
		xadlen = xad->len;
		if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
			endofcur = (offset + xadlen) << xfs.blklog; 
			toread = (endofcur >= endpos)
				  ? len : (endofcur - filepos);

			disk_read_func = disk_read_hook;
			devread (fsb2daddr (xad->start),
				 filepos - (offset << xfs.blklog), toread, buf);
			disk_read_func = NULL;

			buf += toread;
			len -= toread;
			filepos += toread;
		} else if (offset > endofprev) {
			toread = ((offset << xfs.blklog) >= endpos)
				  ? len : ((offset - endofprev) << xfs.blklog);
			len -= toread;
			filepos += toread;
			for (; toread; toread--) {
				*buf++ = 0;
			}
			continue;
		}
		endofprev = offset + xadlen; 
	}

	return filepos - startpos;
}

int
xfs_dir (char *dirname)
{
	xfs_ino_t ino, parent_ino, new_ino;
	xfs_fsize_t di_size;
	int di_mode;
	int cmp, n, link_count;
	char linkbuf[xfs.bsize];
	char *rest, *name, ch;

	parent_ino = ino = xfs.rootino;
	link_count = 0;
	for (;;) {
		di_read (ino);
		di_size = le64 (icore.di_size);
		di_mode = le16 (icore.di_mode);

		if ((di_mode & IFMT) == IFLNK) {
			if (++link_count > MAX_LINK_COUNT) {
				errnum = ERR_SYMLINK_LOOP;
				return 0;
			}
			if (di_size < xfs.bsize - 1) {
				filepos = 0;
				filemax = di_size;
				n = xfs_read (linkbuf, filemax);
			} else {
				errnum = ERR_FILELENGTH;
				return 0;
			}

			ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
			while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
			linkbuf[n] = 0;
			dirname = linkbuf;
			continue;
		}

		if (!*dirname || isspace (*dirname)) {
			if ((di_mode & IFMT) != IFREG) {
				errnum = ERR_BAD_FILETYPE;
				return 0;
			}
			filepos = 0;
			filemax = di_size;
			return 1;
		}

		if ((di_mode & IFMT) != IFDIR) {
			errnum = ERR_BAD_FILETYPE;
			return 0;
		}

		for (; *dirname == '/'; dirname++);

		for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
		*rest = 0;

		name = first_dentry (&new_ino);
		for (;;) {
			cmp = (!*dirname) ? -1 : substring (dirname, name);
#ifndef STAGE1_5
			if (print_possibilities && ch != '/' && cmp <= 0) {
				if (print_possibilities > 0)
					print_possibilities = -print_possibilities;
				print_a_completion (name);
			} else
#endif
			if (cmp == 0) {
				parent_ino = ino;
				if (new_ino)
					ino = new_ino;
		        	*(dirname = rest) = ch;
				break;
			}
			name = next_dentry (&new_ino);
			if (name == NULL) {
				if (print_possibilities < 0)
					return 1;

				errnum = ERR_FILE_NOT_FOUND;
				*rest = ch;
				return 0;
			}
		}
	}
}

#endif /* FSYS_XFS */
