/*
 * directory.c
 *
 * PURPOSE
 *	Directory related functions
 *
 * CONTACTS
 *	E-mail regarding any portion of the Linux UDF file system should be
 *	directed to the development team mailing list (run by majordomo):
 *		linux_udf@hpesjro.fc.hp.com
 *
 * COPYRIGHT
 *	This file is distributed under the terms of the GNU General Public
 *	License (GPL). Copies of the GPL can be obtained from:
 *		ftp://prep.ai.mit.edu/pub/gnu/GPL
 *	Each contributing author retains all rights to their own work.
 */

#include "udfdecl.h"
#include "udf_i.h"

#include <linux/fs.h>
#include <linux/string.h>
#include <linux/buffer_head.h>

#if 0
static uint8_t *
udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
		kernel_lb_addr fe_loc, int *pos, int *offset,
		struct buffer_head **bh, int *error)
{
	int loffset = *offset;
	int block;
	uint8_t *ad;
	int remainder;

	*error = 0;

	ad = (uint8_t *)(*bh)->b_data + *offset;
	*offset += ad_size;

	if (!ad)
	{
		udf_release_data(*bh);
		*error = 1;
		return NULL;
	}

	if (*offset == dir->i_sb->s_blocksize)
	{
		udf_release_data(*bh);
		block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
		if (!block)
			return NULL;
		if (!(*bh = udf_tread(dir->i_sb, block)))
			return NULL;
	}
	else if (*offset > dir->i_sb->s_blocksize)
	{
		ad = tmpad;

		remainder = dir->i_sb->s_blocksize - loffset;
		memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder);

		udf_release_data(*bh);
		block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
		if (!block)
			return NULL;
		if (!((*bh) = udf_tread(dir->i_sb, block)))
			return NULL;

		memcpy((uint8_t *)ad + remainder, (*bh)->b_data, ad_size - remainder);
		*offset = ad_size - remainder;
	}
	return ad;
}
#endif

struct fileIdentDesc *
udf_fileident_read(struct inode *dir, loff_t *nf_pos,
	struct udf_fileident_bh *fibh,
	struct fileIdentDesc *cfi,
	kernel_lb_addr *bloc, uint32_t *extoffset, 
	kernel_lb_addr *eloc, uint32_t *elen,
	uint32_t *offset, struct buffer_head **bh)
{
	struct fileIdentDesc *fi;
	int i, num, block;
	struct buffer_head * tmp, * bha[16];

	fibh->soffset = fibh->eoffset;

	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
	{
		fi = udf_get_fileident(UDF_I_DATA(dir) -
			(UDF_I_EFE(dir) ?
				sizeof(struct extendedFileEntry) :
				sizeof(struct fileEntry)),
			dir->i_sb->s_blocksize, &(fibh->eoffset));

		if (!fi)
			return NULL;

		*nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);

		memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));

		return fi;
	}

	if (fibh->eoffset == dir->i_sb->s_blocksize)
	{
		int lextoffset = *extoffset;

		if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
			(EXT_RECORDED_ALLOCATED >> 30))
		{
			return NULL;
		}

		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);

		(*offset) ++;

		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
			*offset = 0;
		else
			*extoffset = lextoffset;

		udf_release_data(fibh->sbh);
		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
			return NULL;
		fibh->soffset = fibh->eoffset = 0;

		if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
		{
			i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
			if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits))
				i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset;
			for (num=0; i>0; i--)
			{
				block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i);
				tmp = udf_tgetblk(dir->i_sb, block);
				if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
					bha[num++] = tmp;
				else
					brelse(tmp);
			}
			if (num)
			{
				ll_rw_block(READA, num, bha);
				for (i=0; i<num; i++)
					brelse(bha[i]);
			}
		}
	}
	else if (fibh->sbh != fibh->ebh)
	{
		udf_release_data(fibh->sbh);
		fibh->sbh = fibh->ebh;
	}

	fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
		&(fibh->eoffset));

	if (!fi)
		return NULL;

	*nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);

	if (fibh->eoffset <= dir->i_sb->s_blocksize)
	{
		memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
	}
	else if (fibh->eoffset > dir->i_sb->s_blocksize)
	{
		int lextoffset = *extoffset;

		if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
			(EXT_RECORDED_ALLOCATED >> 30))
		{
			return NULL;
		}

		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);

		(*offset) ++;

		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
			*offset = 0;
		else
			*extoffset = lextoffset;

		fibh->soffset -= dir->i_sb->s_blocksize;
		fibh->eoffset -= dir->i_sb->s_blocksize;

		if (!(fibh->ebh = udf_tread(dir->i_sb, block)))
			return NULL;

		if (sizeof(struct fileIdentDesc) > - fibh->soffset)
		{
			int fi_len;

			memcpy((uint8_t *)cfi, (uint8_t *)fi, - fibh->soffset);
			memcpy((uint8_t *)cfi - fibh->soffset, fibh->ebh->b_data,
				sizeof(struct fileIdentDesc) + fibh->soffset);

			fi_len = (sizeof(struct fileIdentDesc) + cfi->lengthFileIdent +
				le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;

			*nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
			fibh->eoffset = fibh->soffset + fi_len;
		}
		else
		{
			memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
		}
	}
	return fi;
}

struct fileIdentDesc * 
udf_get_fileident(void * buffer, int bufsize, int * offset)
{
	struct fileIdentDesc *fi;
	int lengthThisIdent;
	uint8_t * ptr;
	int padlen;

	if ( (!buffer) || (!offset) ) {
		udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
		return NULL;
	}

	ptr = buffer;

	if ( (*offset > 0) && (*offset < bufsize) ) {
		ptr += *offset;
	}
	fi=(struct fileIdentDesc *)ptr;
	if (le16_to_cpu(fi->descTag.tagIdent) != TAG_IDENT_FID)
	{
		udf_debug("0x%x != TAG_IDENT_FID\n",
			le16_to_cpu(fi->descTag.tagIdent));
		udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
			*offset, (unsigned long)sizeof(struct fileIdentDesc), bufsize);
		return NULL;
	}
	if ( (*offset + sizeof(struct fileIdentDesc)) > bufsize )
	{
		lengthThisIdent = sizeof(struct fileIdentDesc);
	}
	else
		lengthThisIdent = sizeof(struct fileIdentDesc) +
			fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);

	/* we need to figure padding, too! */
	padlen = lengthThisIdent % UDF_NAME_PAD;
	if (padlen)
		lengthThisIdent += (UDF_NAME_PAD - padlen);
	*offset = *offset + lengthThisIdent;

	return fi;
}

#if 0
static extent_ad *
udf_get_fileextent(void * buffer, int bufsize, int * offset)
{
	extent_ad * ext;
	struct fileEntry *fe;
	uint8_t * ptr;

	if ( (!buffer) || (!offset) )
	{
		printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
		return NULL;
	}

	fe = (struct fileEntry *)buffer;

	if ( le16_to_cpu(fe->descTag.tagIdent) != TAG_IDENT_FE )
	{
		udf_debug("0x%x != TAG_IDENT_FE\n",
			le16_to_cpu(fe->descTag.tagIdent));
		return NULL;
	}

	ptr=(uint8_t *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);

	if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
	{
		ptr += *offset;
	}

	ext = (extent_ad *)ptr;

	*offset = *offset + sizeof(extent_ad);
	return ext;
}
#endif

short_ad *
udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
{
	short_ad *sa;

	if ( (!ptr) || (!offset) )
	{
		printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
		return NULL;
	}

	if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
		return NULL;
	else if ((sa = (short_ad *)ptr)->extLength == 0)
		return NULL;

	if (inc)
		*offset += sizeof(short_ad);
	return sa;
}

long_ad *
udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc)
{
	long_ad *la;

	if ( (!ptr) || (!offset) ) 
	{
		printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
		return NULL;
	}

	if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
		return NULL;
	else if ((la = (long_ad *)ptr)->extLength == 0)
		return NULL;

	if (inc)
		*offset += sizeof(long_ad);
	return la;
}
