/*
 * misc.c
 *
 * PURPOSE
 *	Miscellaneous routines for the OSTA-UDF(tm) filesystem.
 *
 * 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.
 *
 *  (C) 1998 Dave Boynton
 *  (C) 1998-2004 Ben Fennema
 *  (C) 1999-2000 Stelias Computing Inc
 *
 * HISTORY
 *
 *  04/19/99 blf  partial support for reading/writing specific EA's
 */

#include "udfdecl.h"

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

#include "udf_i.h"
#include "udf_sb.h"

struct buffer_head *udf_tgetblk(struct super_block *sb, int block)
{
	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
		return sb_getblk(sb, udf_fixed_to_variable(block));
	else
		return sb_getblk(sb, block);
}

struct buffer_head *udf_tread(struct super_block *sb, int block)
{
	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
		return sb_bread(sb, udf_fixed_to_variable(block));
	else
		return sb_bread(sb, block);
}

struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
					   uint32_t type, uint8_t loc)
{
	uint8_t *ea = NULL, *ad = NULL;
	int offset;
	uint16_t crclen;
	int i;

	ea = UDF_I_DATA(inode);
	if (UDF_I_LENEATTR(inode)) {
		ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
	} else {
		ad = ea;
		size += sizeof(struct extendedAttrHeaderDesc);
	}

	offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
		UDF_I_LENALLOC(inode);

	/* TODO - Check for FreeEASpace */

	if (loc & 0x01 && offset >= size) {
		struct extendedAttrHeaderDesc *eahd;
		eahd = (struct extendedAttrHeaderDesc *)ea;

		if (UDF_I_LENALLOC(inode)) {
			memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
		}

		if (UDF_I_LENEATTR(inode)) {
			/* check checksum/crc */
			if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
			    le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) {
				return NULL;
			}
		} else {
			size -= sizeof(struct extendedAttrHeaderDesc);
			UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
			eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
			if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
				eahd->descTag.descVersion = cpu_to_le16(3);
			else
				eahd->descTag.descVersion = cpu_to_le16(2);
			eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
			eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
			eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
			eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
		}

		offset = UDF_I_LENEATTR(inode);
		if (type < 2048) {
			if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) {
				uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
				memmove(&ea[offset - aal + size],
					&ea[aal], offset - aal);
				offset -= aal;
				eahd->appAttrLocation = cpu_to_le32(aal + size);
			}
			if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode)) {
				uint32_t ial = le32_to_cpu(eahd->impAttrLocation);
				memmove(&ea[offset - ial + size],
					&ea[ial], offset - ial);
				offset -= ial;
				eahd->impAttrLocation = cpu_to_le32(ial + size);
			}
		} else if (type < 65536) {
			if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode)) {
				uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
				memmove(&ea[offset - aal + size],
					&ea[aal], offset - aal);
				offset -= aal;
				eahd->appAttrLocation = cpu_to_le32(aal + size);
			}
		}
		/* rewrite CRC + checksum of eahd */
		crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
		eahd->descTag.descCRCLength = cpu_to_le16(crclen);
		eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd +
							    sizeof(tag), crclen, 0));
		eahd->descTag.tagChecksum = 0;
		for (i = 0; i < 16; i++)
			if (i != 4)
				eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i];
		UDF_I_LENEATTR(inode) += size;
		return (struct genericFormat *)&ea[offset];
	}
	if (loc & 0x02) {
	}

	return NULL;
}

struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
					   uint8_t subtype)
{
	struct genericFormat *gaf;
	uint8_t *ea = NULL;
	uint32_t offset;

	ea = UDF_I_DATA(inode);

	if (UDF_I_LENEATTR(inode)) {
		struct extendedAttrHeaderDesc *eahd;
		eahd = (struct extendedAttrHeaderDesc *)ea;

		/* check checksum/crc */
		if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
		    le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) {
			return NULL;
		}

		if (type < 2048)
			offset = sizeof(struct extendedAttrHeaderDesc);
		else if (type < 65536)
			offset = le32_to_cpu(eahd->impAttrLocation);
		else
			offset = le32_to_cpu(eahd->appAttrLocation);

		while (offset < UDF_I_LENEATTR(inode)) {
			gaf = (struct genericFormat *)&ea[offset];
			if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
				return gaf;
			else
				offset += le32_to_cpu(gaf->attrLength);
		}
	}

	return NULL;
}

/*
 * udf_read_tagged
 *
 * PURPOSE
 *	Read the first block of a tagged descriptor.
 *
 * HISTORY
 *	July 1, 1997 - Andrew E. Mileski
 *	Written, tested, and released.
 */
struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
				    uint32_t location, uint16_t * ident)
{
	tag *tag_p;
	struct buffer_head *bh = NULL;
	register uint8_t checksum;
	register int i;

	/* Read the block */
	if (block == 0xFFFFFFFF)
		return NULL;

	bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
	if (!bh) {
		udf_debug("block=%d, location=%d: read failed\n",
			  block + UDF_SB_SESSION(sb), location);
		return NULL;
	}

	tag_p = (tag *)(bh->b_data);

	*ident = le16_to_cpu(tag_p->tagIdent);

	if (location != le32_to_cpu(tag_p->tagLocation)) {
		udf_debug("location mismatch block %u, tag %u != %u\n",
			  block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
		goto error_out;
	}

	/* Verify the tag checksum */
	checksum = 0U;
	for (i = 0; i < 4; i++)
		checksum += (uint8_t)(bh->b_data[i]);
	for (i = 5; i < 16; i++)
		checksum += (uint8_t)(bh->b_data[i]);
	if (checksum != tag_p->tagChecksum) {
		printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
		goto error_out;
	}

	/* Verify the tag version */
	if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
	    le16_to_cpu(tag_p->descVersion) != 0x0003U) {
		udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
			  le16_to_cpu(tag_p->descVersion), block);
		goto error_out;
	}

	/* Verify the descriptor CRC */
	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
	    le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
						   le16_to_cpu(tag_p->descCRCLength), 0)) {
		return bh;
	}
	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
		  block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC),
		  le16_to_cpu(tag_p->descCRCLength));

error_out:
	brelse(bh);
	return NULL;
}

struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc,
				     uint32_t offset, uint16_t * ident)
{
	return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
			       loc.logicalBlockNum + offset, ident);
}

void udf_update_tag(char *data, int length)
{
	tag *tptr = (tag *)data;
	int i;

	length -= sizeof(tag);

	tptr->tagChecksum = 0;
	tptr->descCRCLength = cpu_to_le16(length);
	tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));

	for (i = 0; i < 16; i++)
		if (i != 4)
			tptr->tagChecksum += (uint8_t)(data[i]);
}

void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
		 uint32_t loc, int length)
{
	tag *tptr = (tag *)data;
	tptr->tagIdent = cpu_to_le16(ident);
	tptr->descVersion = cpu_to_le16(version);
	tptr->tagSerialNum = cpu_to_le16(snum);
	tptr->tagLocation = cpu_to_le32(loc);
	udf_update_tag(data, length);
}
