// SPDX-License-Identifier: GPL-2.0-only
/*
 * directory.c
 *
 * PURPOSE
 *	Directory related functions
 *
 */

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

#include <linux/fs.h>
#include <linux/string.h>
#include <linux/bio.h>
#include <linux/crc-itu-t.h>
#include <linux/iversion.h>

static int udf_verify_fi(struct udf_fileident_iter *iter)
{
	unsigned int len;

	if (iter->fi.descTag.tagIdent != cpu_to_le16(TAG_IDENT_FID)) {
		udf_err(iter->dir->i_sb,
			"directory (ino %lu) has entry at pos %llu with incorrect tag %x\n",
			iter->dir->i_ino, (unsigned long long)iter->pos,
			le16_to_cpu(iter->fi.descTag.tagIdent));
		return -EFSCORRUPTED;
	}
	len = udf_dir_entry_len(&iter->fi);
	if (le16_to_cpu(iter->fi.lengthOfImpUse) & 3) {
		udf_err(iter->dir->i_sb,
			"directory (ino %lu) has entry at pos %llu with unaligned length of impUse field\n",
			iter->dir->i_ino, (unsigned long long)iter->pos);
		return -EFSCORRUPTED;
	}
	/*
	 * This is in fact allowed by the spec due to long impUse field but
	 * we don't support it. If there is real media with this large impUse
	 * field, support can be added.
	 */
	if (len > 1 << iter->dir->i_blkbits) {
		udf_err(iter->dir->i_sb,
			"directory (ino %lu) has too big (%u) entry at pos %llu\n",
			iter->dir->i_ino, len, (unsigned long long)iter->pos);
		return -EFSCORRUPTED;
	}
	if (iter->pos + len > iter->dir->i_size) {
		udf_err(iter->dir->i_sb,
			"directory (ino %lu) has entry past directory size at pos %llu\n",
			iter->dir->i_ino, (unsigned long long)iter->pos);
		return -EFSCORRUPTED;
	}
	if (udf_dir_entry_len(&iter->fi) !=
	    sizeof(struct tag) + le16_to_cpu(iter->fi.descTag.descCRCLength)) {
		udf_err(iter->dir->i_sb,
			"directory (ino %lu) has entry where CRC length (%u) does not match entry length (%u)\n",
			iter->dir->i_ino,
			(unsigned)le16_to_cpu(iter->fi.descTag.descCRCLength),
			(unsigned)(udf_dir_entry_len(&iter->fi) -
							sizeof(struct tag)));
		return -EFSCORRUPTED;
	}
	return 0;
}

static int udf_copy_fi(struct udf_fileident_iter *iter)
{
	struct udf_inode_info *iinfo = UDF_I(iter->dir);
	u32 blksize = 1 << iter->dir->i_blkbits;
	u32 off, len, nameoff;
	int err;

	/* Skip copying when we are at EOF */
	if (iter->pos >= iter->dir->i_size) {
		iter->name = NULL;
		return 0;
	}
	if (iter->dir->i_size < iter->pos + sizeof(struct fileIdentDesc)) {
		udf_err(iter->dir->i_sb,
			"directory (ino %lu) has entry straddling EOF\n",
			iter->dir->i_ino);
		return -EFSCORRUPTED;
	}
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		memcpy(&iter->fi, iinfo->i_data + iinfo->i_lenEAttr + iter->pos,
		       sizeof(struct fileIdentDesc));
		err = udf_verify_fi(iter);
		if (err < 0)
			return err;
		iter->name = iinfo->i_data + iinfo->i_lenEAttr + iter->pos +
			sizeof(struct fileIdentDesc) +
			le16_to_cpu(iter->fi.lengthOfImpUse);
		return 0;
	}

	off = iter->pos & (blksize - 1);
	len = min_t(u32, sizeof(struct fileIdentDesc), blksize - off);
	memcpy(&iter->fi, iter->bh[0]->b_data + off, len);
	if (len < sizeof(struct fileIdentDesc))
		memcpy((char *)(&iter->fi) + len, iter->bh[1]->b_data,
		       sizeof(struct fileIdentDesc) - len);
	err = udf_verify_fi(iter);
	if (err < 0)
		return err;

	/* Handle directory entry name */
	nameoff = off + sizeof(struct fileIdentDesc) +
				le16_to_cpu(iter->fi.lengthOfImpUse);
	if (off + udf_dir_entry_len(&iter->fi) <= blksize) {
		iter->name = iter->bh[0]->b_data + nameoff;
	} else if (nameoff >= blksize) {
		iter->name = iter->bh[1]->b_data + (nameoff - blksize);
	} else {
		iter->name = iter->namebuf;
		len = blksize - nameoff;
		memcpy(iter->name, iter->bh[0]->b_data + nameoff, len);
		memcpy(iter->name + len, iter->bh[1]->b_data,
		       iter->fi.lengthFileIdent - len);
	}
	return 0;
}

/* Readahead 8k once we are at 8k boundary */
static void udf_readahead_dir(struct udf_fileident_iter *iter)
{
	unsigned int ralen = 16 >> (iter->dir->i_blkbits - 9);
	struct buffer_head *tmp, *bha[16];
	int i, num;
	udf_pblk_t blk;

	if (iter->loffset & (ralen - 1))
		return;

	if (iter->loffset + ralen > (iter->elen >> iter->dir->i_blkbits))
		ralen = (iter->elen >> iter->dir->i_blkbits) - iter->loffset;
	num = 0;
	for (i = 0; i < ralen; i++) {
		blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc,
					iter->loffset + i);
		tmp = sb_getblk(iter->dir->i_sb, blk);
		if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
			bha[num++] = tmp;
		else
			brelse(tmp);
	}
	if (num) {
		bh_readahead_batch(num, bha, REQ_RAHEAD);
		for (i = 0; i < num; i++)
			brelse(bha[i]);
	}
}

static struct buffer_head *udf_fiiter_bread_blk(struct udf_fileident_iter *iter)
{
	udf_pblk_t blk;

	udf_readahead_dir(iter);
	blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc, iter->loffset);
	return sb_bread(iter->dir->i_sb, blk);
}

/*
 * Updates loffset to point to next directory block; eloc, elen & epos are
 * updated if we need to traverse to the next extent as well.
 */
static int udf_fiiter_advance_blk(struct udf_fileident_iter *iter)
{
	int8_t etype = -1;
	int err = 0;

	iter->loffset++;
	if (iter->loffset < DIV_ROUND_UP(iter->elen, 1<<iter->dir->i_blkbits))
		return 0;

	iter->loffset = 0;
	err = udf_next_aext(iter->dir, &iter->epos, &iter->eloc,
			    &iter->elen, &etype, 1);
	if (err < 0)
		return err;
	else if (err == 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
		if (iter->pos == iter->dir->i_size) {
			iter->elen = 0;
			return 0;
		}
		udf_err(iter->dir->i_sb,
			"extent after position %llu not allocated in directory (ino %lu)\n",
			(unsigned long long)iter->pos, iter->dir->i_ino);
		return -EFSCORRUPTED;
	}
	return 0;
}

static int udf_fiiter_load_bhs(struct udf_fileident_iter *iter)
{
	int blksize = 1 << iter->dir->i_blkbits;
	int off = iter->pos & (blksize - 1);
	int err;
	struct fileIdentDesc *fi;

	/* Is there any further extent we can map from? */
	if (!iter->bh[0] && iter->elen) {
		iter->bh[0] = udf_fiiter_bread_blk(iter);
		if (!iter->bh[0]) {
			err = -ENOMEM;
			goto out_brelse;
		}
		if (!buffer_uptodate(iter->bh[0])) {
			err = -EIO;
			goto out_brelse;
		}
	}
	/* There's no next block so we are done */
	if (iter->pos >= iter->dir->i_size)
		return 0;
	/* Need to fetch next block as well? */
	if (off + sizeof(struct fileIdentDesc) > blksize)
		goto fetch_next;
	fi = (struct fileIdentDesc *)(iter->bh[0]->b_data + off);
	/* Need to fetch next block to get name? */
	if (off + udf_dir_entry_len(fi) > blksize) {
fetch_next:
		err = udf_fiiter_advance_blk(iter);
		if (err)
			goto out_brelse;
		iter->bh[1] = udf_fiiter_bread_blk(iter);
		if (!iter->bh[1]) {
			err = -ENOMEM;
			goto out_brelse;
		}
		if (!buffer_uptodate(iter->bh[1])) {
			err = -EIO;
			goto out_brelse;
		}
	}
	return 0;
out_brelse:
	brelse(iter->bh[0]);
	brelse(iter->bh[1]);
	iter->bh[0] = iter->bh[1] = NULL;
	return err;
}

int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
		    loff_t pos)
{
	struct udf_inode_info *iinfo = UDF_I(dir);
	int err = 0;
	int8_t etype;

	iter->dir = dir;
	iter->bh[0] = iter->bh[1] = NULL;
	iter->pos = pos;
	iter->elen = 0;
	iter->epos.bh = NULL;
	iter->name = NULL;
	/*
	 * When directory is verified, we don't expect directory iteration to
	 * fail and it can be difficult to undo without corrupting filesystem.
	 * So just do not allow memory allocation failures here.
	 */
	iter->namebuf = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL | __GFP_NOFAIL);

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		err = udf_copy_fi(iter);
		goto out;
	}

	err = inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
			 &iter->eloc, &iter->elen, &iter->loffset, &etype);
	if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
		if (pos == dir->i_size)
			return 0;
		udf_err(dir->i_sb,
			"position %llu not allocated in directory (ino %lu)\n",
			(unsigned long long)pos, dir->i_ino);
		err = -EFSCORRUPTED;
		goto out;
	}
	err = udf_fiiter_load_bhs(iter);
	if (err < 0)
		goto out;
	err = udf_copy_fi(iter);
out:
	if (err < 0)
		udf_fiiter_release(iter);
	return err;
}

int udf_fiiter_advance(struct udf_fileident_iter *iter)
{
	unsigned int oldoff, len;
	int blksize = 1 << iter->dir->i_blkbits;
	int err;

	oldoff = iter->pos & (blksize - 1);
	len = udf_dir_entry_len(&iter->fi);
	iter->pos += len;
	if (UDF_I(iter->dir)->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
		if (oldoff + len >= blksize) {
			brelse(iter->bh[0]);
			iter->bh[0] = NULL;
			/* Next block already loaded? */
			if (iter->bh[1]) {
				iter->bh[0] = iter->bh[1];
				iter->bh[1] = NULL;
			} else {
				err = udf_fiiter_advance_blk(iter);
				if (err < 0)
					return err;
			}
		}
		err = udf_fiiter_load_bhs(iter);
		if (err < 0)
			return err;
	}
	return udf_copy_fi(iter);
}

void udf_fiiter_release(struct udf_fileident_iter *iter)
{
	iter->dir = NULL;
	brelse(iter->bh[0]);
	brelse(iter->bh[1]);
	iter->bh[0] = iter->bh[1] = NULL;
	kfree(iter->namebuf);
	iter->namebuf = NULL;
}

static void udf_copy_to_bufs(void *buf1, int len1, void *buf2, int len2,
			     int off, void *src, int len)
{
	int copy;

	if (off >= len1) {
		off -= len1;
	} else {
		copy = min(off + len, len1) - off;
		memcpy(buf1 + off, src, copy);
		src += copy;
		len -= copy;
		off = 0;
	}
	if (len > 0) {
		if (WARN_ON_ONCE(off + len > len2 || !buf2))
			return;
		memcpy(buf2 + off, src, len);
	}
}

static uint16_t udf_crc_fi_bufs(void *buf1, int len1, void *buf2, int len2,
				int off, int len)
{
	int copy;
	uint16_t crc = 0;

	if (off >= len1) {
		off -= len1;
	} else {
		copy = min(off + len, len1) - off;
		crc = crc_itu_t(crc, buf1 + off, copy);
		len -= copy;
		off = 0;
	}
	if (len > 0) {
		if (WARN_ON_ONCE(off + len > len2 || !buf2))
			return 0;
		crc = crc_itu_t(crc, buf2 + off, len);
	}
	return crc;
}

static void udf_copy_fi_to_bufs(char *buf1, int len1, char *buf2, int len2,
				int off, struct fileIdentDesc *fi,
				uint8_t *impuse, uint8_t *name)
{
	uint16_t crc;
	int fioff = off;
	int crcoff = off + sizeof(struct tag);
	unsigned int crclen = udf_dir_entry_len(fi) - sizeof(struct tag);
	char zeros[UDF_NAME_PAD] = {};
	int endoff = off + udf_dir_entry_len(fi);

	udf_copy_to_bufs(buf1, len1, buf2, len2, off, fi,
			 sizeof(struct fileIdentDesc));
	off += sizeof(struct fileIdentDesc);
	if (impuse)
		udf_copy_to_bufs(buf1, len1, buf2, len2, off, impuse,
				 le16_to_cpu(fi->lengthOfImpUse));
	off += le16_to_cpu(fi->lengthOfImpUse);
	if (name) {
		udf_copy_to_bufs(buf1, len1, buf2, len2, off, name,
				 fi->lengthFileIdent);
		off += fi->lengthFileIdent;
		udf_copy_to_bufs(buf1, len1, buf2, len2, off, zeros,
				 endoff - off);
	}

	crc = udf_crc_fi_bufs(buf1, len1, buf2, len2, crcoff, crclen);
	fi->descTag.descCRC = cpu_to_le16(crc);
	fi->descTag.descCRCLength = cpu_to_le16(crclen);
	fi->descTag.tagChecksum = udf_tag_checksum(&fi->descTag);

	udf_copy_to_bufs(buf1, len1, buf2, len2, fioff, fi, sizeof(struct tag));
}

void udf_fiiter_write_fi(struct udf_fileident_iter *iter, uint8_t *impuse)
{
	struct udf_inode_info *iinfo = UDF_I(iter->dir);
	void *buf1, *buf2 = NULL;
	int len1, len2 = 0, off;
	int blksize = 1 << iter->dir->i_blkbits;

	off = iter->pos & (blksize - 1);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		buf1 = iinfo->i_data + iinfo->i_lenEAttr;
		len1 = iter->dir->i_size;
	} else {
		buf1 = iter->bh[0]->b_data;
		len1 = blksize;
		if (iter->bh[1]) {
			buf2 = iter->bh[1]->b_data;
			len2 = blksize;
		}
	}

	udf_copy_fi_to_bufs(buf1, len1, buf2, len2, off, &iter->fi, impuse,
			    iter->name == iter->namebuf ? iter->name : NULL);

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		mark_inode_dirty(iter->dir);
	} else {
		mark_buffer_dirty_inode(iter->bh[0], iter->dir);
		if (iter->bh[1])
			mark_buffer_dirty_inode(iter->bh[1], iter->dir);
	}
	inode_inc_iversion(iter->dir);
}

void udf_fiiter_update_elen(struct udf_fileident_iter *iter, uint32_t new_elen)
{
	struct udf_inode_info *iinfo = UDF_I(iter->dir);
	int diff = new_elen - iter->elen;

	/* Skip update when we already went past the last extent */
	if (!iter->elen)
		return;
	iter->elen = new_elen;
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
		iter->epos.offset -= sizeof(struct short_ad);
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
		iter->epos.offset -= sizeof(struct long_ad);
	udf_write_aext(iter->dir, &iter->epos, &iter->eloc, iter->elen, 1);
	iinfo->i_lenExtents += diff;
	mark_inode_dirty(iter->dir);
}

/* Append new block to directory. @iter is expected to point at EOF */
int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
{
	struct udf_inode_info *iinfo = UDF_I(iter->dir);
	int blksize = 1 << iter->dir->i_blkbits;
	struct buffer_head *bh;
	sector_t block;
	uint32_t old_elen = iter->elen;
	int err;
	int8_t etype;

	if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
		return -EINVAL;

	/* Round up last extent in the file */
	udf_fiiter_update_elen(iter, ALIGN(iter->elen, blksize));

	/* Allocate new block and refresh mapping information */
	block = iinfo->i_lenExtents >> iter->dir->i_blkbits;
	bh = udf_bread(iter->dir, block, 1, &err);
	if (!bh) {
		udf_fiiter_update_elen(iter, old_elen);
		return err;
	}
	err = inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
		   &iter->loffset, &etype);
	if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
		udf_err(iter->dir->i_sb,
			"block %llu not allocated in directory (ino %lu)\n",
			(unsigned long long)block, iter->dir->i_ino);
		return -EFSCORRUPTED;
	}
	if (!(iter->pos & (blksize - 1))) {
		brelse(iter->bh[0]);
		iter->bh[0] = bh;
	} else {
		iter->bh[1] = bh;
	}
	return 0;
}

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

	if ((!ptr) || (!offset)) {
		pr_err("%s: invalidparms\n", __func__);
		return NULL;
	}

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

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

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

	if ((!ptr) || (!offset)) {
		pr_err("%s: invalidparms\n", __func__);
		return NULL;
	}

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

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