// SPDX-License-Identifier: GPL-2.0-only
/*
 * dir.c
 *
 * PURPOSE
 *  Directory handling routines for the OSTA-UDF(tm) filesystem.
 *
 * COPYRIGHT
 *  (C) 1998-2004 Ben Fennema
 *
 * HISTORY
 *
 *  10/05/98 dgb  Split directory operations into its own file
 *                Implemented directory reads via do_udf_readdir
 *  10/06/98      Made directory operations work!
 *  11/17/98      Rewrote directory to support ICBTAG_FLAG_AD_LONG
 *  11/25/98 blf  Rewrote directory handling (readdir+lookup) to support reading
 *                across blocks.
 *  12/12/98      Split out the lookup code to namei.c. bulk of directory
 *                code now in directory.c:udf_fileident_read.
 */

#include "udfdecl.h"

#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/bio.h>
#include <linux/iversion.h>

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

static int udf_readdir(struct file *file, struct dir_context *ctx)
{
	struct inode *dir = file_inode(file);
	loff_t nf_pos, emit_pos = 0;
	int flen;
	unsigned char *fname = NULL;
	int ret = 0;
	struct super_block *sb = dir->i_sb;
	bool pos_valid = false;
	struct udf_fileident_iter iter;

	if (ctx->pos == 0) {
		if (!dir_emit_dot(file, ctx))
			return 0;
		ctx->pos = 1;
	}
	nf_pos = (ctx->pos - 1) << 2;
	if (nf_pos >= dir->i_size)
		goto out;

	/*
	 * Something changed since last readdir (either lseek was called or dir
	 * changed)?  We need to verify the position correctly points at the
	 * beginning of some dir entry so that the directory parsing code does
	 * not get confused. Since UDF does not have any reliable way of
	 * identifying beginning of dir entry (names are under user control),
	 * we need to scan the directory from the beginning.
	 */
	if (!inode_eq_iversion(dir, *(u64 *)file->private_data)) {
		emit_pos = nf_pos;
		nf_pos = 0;
	} else {
		pos_valid = true;
	}

	fname = kmalloc(UDF_NAME_LEN, GFP_KERNEL);
	if (!fname) {
		ret = -ENOMEM;
		goto out;
	}

	for (ret = udf_fiiter_init(&iter, dir, nf_pos);
	     !ret && iter.pos < dir->i_size;
	     ret = udf_fiiter_advance(&iter)) {
		struct kernel_lb_addr tloc;
		udf_pblk_t iblock;

		/* Still not at offset where user asked us to read from? */
		if (iter.pos < emit_pos)
			continue;

		/* Update file position only if we got past the current one */
		pos_valid = true;
		ctx->pos = (iter.pos >> 2) + 1;

		if (iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
			if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
				continue;
		}

		if (iter.fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) {
			if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
				continue;
		}

		if (iter.fi.fileCharacteristics & FID_FILE_CHAR_PARENT) {
			if (!dir_emit_dotdot(file, ctx))
				goto out_iter;
			continue;
		}

		flen = udf_get_filename(sb, iter.name,
				iter.fi.lengthFileIdent, fname, UDF_NAME_LEN);
		if (flen < 0)
			continue;

		tloc = lelb_to_cpu(iter.fi.icb.extLocation);
		iblock = udf_get_lb_pblock(sb, &tloc, 0);
		if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN))
			goto out_iter;
	}

	if (!ret) {
		ctx->pos = (iter.pos >> 2) + 1;
		pos_valid = true;
	}
out_iter:
	udf_fiiter_release(&iter);
out:
	if (pos_valid)
		*(u64 *)file->private_data = inode_query_iversion(dir);
	kfree(fname);

	return ret;
}

static int udf_dir_open(struct inode *inode, struct file *file)
{
	file->private_data = kzalloc(sizeof(u64), GFP_KERNEL);
	if (!file->private_data)
		return -ENOMEM;
	return 0;
}

static int udf_dir_release(struct inode *inode, struct file *file)
{
	kfree(file->private_data);
	return 0;
}

static loff_t udf_dir_llseek(struct file *file, loff_t offset, int whence)
{
	return generic_llseek_cookie(file, offset, whence,
				     (u64 *)file->private_data);
}

/* readdir and lookup functions */
const struct file_operations udf_dir_operations = {
	.open			= udf_dir_open,
	.release		= udf_dir_release,
	.llseek			= udf_dir_llseek,
	.read			= generic_read_dir,
	.iterate_shared		= udf_readdir,
	.unlocked_ioctl		= udf_ioctl,
	.fsync			= generic_file_fsync,
};
