// SPDX-License-Identifier: GPL-2.0+
/*
 * BTRFS filesystem implementation for U-Boot
 *
 * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
 */

#include <linux/kernel.h>
#include <malloc.h>
#include <memalign.h>
#include "btrfs.h"
#include "disk-io.h"
#include "volumes.h"

/*
 * Read the content of symlink inode @ino of @root, into @target.
 * NOTE: @target will not be \0 termiated, caller should handle it properly.
 *
 * Return the number of read data.
 * Return <0 for error.
 */
int btrfs_readlink(struct btrfs_root *root, u64 ino, char *target)
{
	struct btrfs_path path;
	struct btrfs_key key;
	struct btrfs_file_extent_item *fi;
	int ret;

	key.objectid = ino;
	key.type = BTRFS_EXTENT_DATA_KEY;
	key.offset = 0;
	btrfs_init_path(&path);

	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
	if (ret < 0)
		return ret;
	if (ret > 0) {
		ret = -ENOENT;
		goto out;
	}
	fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
			    struct btrfs_file_extent_item);
	if (btrfs_file_extent_type(path.nodes[0], fi) !=
	    BTRFS_FILE_EXTENT_INLINE) {
		ret = -EUCLEAN;
		error("Extent for symlink %llu must be INLINE type!", ino);
		goto out;
	}
	if (btrfs_file_extent_compression(path.nodes[0], fi) !=
	    BTRFS_COMPRESS_NONE) {
		ret = -EUCLEAN;
		error("Extent for symlink %llu must not be compressed!", ino);
		goto out;
	}
	if (btrfs_file_extent_ram_bytes(path.nodes[0], fi) >=
	    root->fs_info->sectorsize) {
		ret = -EUCLEAN;
		error("Symlink %llu extent data too large (%llu)!\n",
			ino, btrfs_file_extent_ram_bytes(path.nodes[0], fi));
		goto out;
	}
	read_extent_buffer(path.nodes[0], target,
			btrfs_file_extent_inline_start(fi),
			btrfs_file_extent_ram_bytes(path.nodes[0], fi));
	ret = btrfs_file_extent_ram_bytes(path.nodes[0], fi);
out:
	btrfs_release_path(&path);
	return ret;
}

static int lookup_root_ref(struct btrfs_fs_info *fs_info,
			   u64 rootid, u64 *root_ret, u64 *dir_ret)
{
	struct btrfs_root *root = fs_info->tree_root;
	struct btrfs_root_ref *root_ref;
	struct btrfs_path path;
	struct btrfs_key key;
	int ret;

	btrfs_init_path(&path);
	key.objectid = rootid;
	key.type = BTRFS_ROOT_BACKREF_KEY;
	key.offset = (u64)-1;

	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
	if (ret < 0)
		return ret;
	/* Should not happen */
	if (ret == 0) {
		ret = -EUCLEAN;
		goto out;
	}
	ret = btrfs_previous_item(root, &path, rootid, BTRFS_ROOT_BACKREF_KEY);
	if (ret < 0)
		goto out;
	if (ret > 0) {
		ret = -ENOENT;
		goto out;
	}
	btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
	root_ref = btrfs_item_ptr(path.nodes[0], path.slots[0],
				  struct btrfs_root_ref);
	*root_ret = key.offset;
	*dir_ret = btrfs_root_ref_dirid(path.nodes[0], root_ref);
out:
	btrfs_release_path(&path);
	return ret;
}

/*
 * To get the parent inode of @ino of @root.
 *
 * @root_ret and @ino_ret will be filled.
 *
 * NOTE: This function is not reliable. It can only get one parent inode.
 * The get the proper parent inode, we need a full VFS inodes stack to
 * resolve properly.
 */
static int get_parent_inode(struct btrfs_root *root, u64 ino,
			    struct btrfs_root **root_ret, u64 *ino_ret)
{
	struct btrfs_fs_info *fs_info = root->fs_info;
	struct btrfs_path path;
	struct btrfs_key key;
	int ret;

	if (ino == BTRFS_FIRST_FREE_OBJECTID) {
		u64 parent_root = -1;

		/* It's top level already, no more parent */
		if (root->root_key.objectid == BTRFS_FS_TREE_OBJECTID) {
			*root_ret = fs_info->fs_root;
			*ino_ret = BTRFS_FIRST_FREE_OBJECTID;
			return 0;
		}

		ret = lookup_root_ref(fs_info, root->root_key.objectid,
				      &parent_root, ino_ret);
		if (ret < 0)
			return ret;

		key.objectid = parent_root;
		key.type = BTRFS_ROOT_ITEM_KEY;
		key.offset = (u64)-1;
		*root_ret = btrfs_read_fs_root(fs_info, &key);
		if (IS_ERR(*root_ret))
			return PTR_ERR(*root_ret);

		return 0;
	}

	btrfs_init_path(&path);
	key.objectid = ino;
	key.type = BTRFS_INODE_REF_KEY;
	key.offset = (u64)-1;

	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
	if (ret < 0)
		return ret;
	/* Should not happen */
	if (ret == 0) {
		ret = -EUCLEAN;
		goto out;
	}
	ret = btrfs_previous_item(root, &path, ino, BTRFS_INODE_REF_KEY);
	if (ret < 0)
		goto out;
	if (ret > 0) {
		ret = -ENOENT;
		goto out;
	}
	btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
	*root_ret = root;
	*ino_ret = key.offset;
out:
	btrfs_release_path(&path);
	return ret;
}

static inline int next_length(const char *path)
{
	int res = 0;
	while (*path != '\0' && *path != '/') {
		++res;
		++path;
		if (res > BTRFS_NAME_LEN)
			break;
	}
	return res;
}

static inline const char *skip_current_directories(const char *cur)
{
	while (1) {
		if (cur[0] == '/')
			++cur;
		else if (cur[0] == '.' && cur[1] == '/')
			cur += 2;
		else
			break;
	}

	return cur;
}

/*
 * Resolve one filename of @ino of @root.
 *
 * key_ret:	The child key (either INODE_ITEM or ROOT_ITEM type)
 * type_ret:	BTRFS_FT_* of the child inode.
 *
 * Return 0 with above members filled.
 * Return <0 for error.
 */
static int resolve_one_filename(struct btrfs_root *root, u64 ino,
				const char *name, int namelen,
				struct btrfs_key *key_ret, u8 *type_ret)
{
	struct btrfs_dir_item *dir_item;
	struct btrfs_path path;
	int ret = 0;

	btrfs_init_path(&path);

	dir_item = btrfs_lookup_dir_item(NULL, root, &path, ino, name,
					 namelen, 0);
	if (IS_ERR(dir_item)) {
		ret = PTR_ERR(dir_item);
		goto out;
	}

	btrfs_dir_item_key_to_cpu(path.nodes[0], dir_item, key_ret);
	*type_ret = btrfs_dir_type(path.nodes[0], dir_item);
out:
	btrfs_release_path(&path);
	return ret;
}

/*
 * Resolve a full path @filename. The start point is @ino of @root.
 *
 * The result will be filled into @root_ret, @ino_ret and @type_ret.
 */
int btrfs_lookup_path(struct btrfs_root *root, u64 ino, const char *filename,
			struct btrfs_root **root_ret, u64 *ino_ret,
			u8 *type_ret, int symlink_limit)
{
	struct btrfs_fs_info *fs_info = root->fs_info;
	struct btrfs_root *next_root;
	struct btrfs_key key;
	const char *cur = filename;
	u64 next_ino;
	u8 next_type;
	u8 type = BTRFS_FT_UNKNOWN;
	int len;
	int ret = 0;

	/* If the path is absolute path, also search from fs root */
	if (*cur == '/') {
		root = fs_info->fs_root;
		ino = btrfs_root_dirid(&root->root_item);
		type = BTRFS_FT_DIR;
	}

	while (*cur != '\0') {
		cur = skip_current_directories(cur);

		len = next_length(cur);
		if (len > BTRFS_NAME_LEN) {
			error("%s: Name too long at \"%.*s\"", __func__,
			       BTRFS_NAME_LEN, cur);
			return -ENAMETOOLONG;
		}

		if (len == 1 && cur[0] == '.')
			break;

		if (len == 2 && cur[0] == '.' && cur[1] == '.') {
			/* Go one level up */
			ret = get_parent_inode(root, ino, &next_root, &next_ino);
			if (ret < 0)
				return ret;
			root = next_root;
			ino = next_ino;
			goto next;
		}

		if (!*cur)
			break;

		ret = resolve_one_filename(root, ino, cur, len, &key, &type);
		if (ret < 0)
			return ret;

		if (key.type == BTRFS_ROOT_ITEM_KEY) {
			/* Child inode is a subvolume */

			next_root = btrfs_read_fs_root(fs_info, &key);
			if (IS_ERR(next_root))
				return PTR_ERR(next_root);
			root = next_root;
			ino = btrfs_root_dirid(&root->root_item);
		} else if (type == BTRFS_FT_SYMLINK && symlink_limit >= 0) {
			/* Child inode is a symlink */

			char *target;

			if (symlink_limit == 0) {
				error("%s: Too much symlinks!", __func__);
				return -EMLINK;
			}
			target = malloc(fs_info->sectorsize);
			if (!target)
				return -ENOMEM;
			ret = btrfs_readlink(root, key.objectid, target);
			if (ret < 0) {
				free(target);
				return ret;
			}
			target[ret] = '\0';

			ret = btrfs_lookup_path(root, ino, target, &next_root,
						&next_ino, &next_type,
						symlink_limit);
			if (ret < 0)
				return ret;
			root = next_root;
			ino = next_ino;
			type = next_type;
		} else {
			/* Child inode is an inode */
			ino = key.objectid;
		}
next:
		cur += len;
	}

	/* We haven't found anything, but still get no error? */
	if (type == BTRFS_FT_UNKNOWN && !ret)
		ret = -EUCLEAN;

	if (!ret) {
		*root_ret = root;
		*ino_ret = ino;
		*type_ret = type;
	}

	return ret;
}

/*
 * Read out inline extent.
 *
 * Since inline extent should only exist for offset 0, no need for extra
 * parameters.
 * Truncating should be handled by the caller.
 *
 * Return the number of bytes read.
 * Return <0 for error.
 */
int btrfs_read_extent_inline(struct btrfs_path *path,
			     struct btrfs_file_extent_item *fi, char *dest)
{
	struct extent_buffer *leaf = path->nodes[0];
	int slot = path->slots[0];
	char *cbuf = NULL;
	char *dbuf = NULL;
	u32 csize;
	u32 dsize;
	int ret;

	csize = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(slot));
	if (btrfs_file_extent_compression(leaf, fi) == BTRFS_COMPRESS_NONE) {
		/* Uncompressed, just read it out */
		read_extent_buffer(leaf, dest,
				btrfs_file_extent_inline_start(fi),
				csize);
		return csize;
	}

	/* Compressed extent, prepare the compressed and data buffer */
	dsize = btrfs_file_extent_ram_bytes(leaf, fi);
	cbuf = malloc(csize);
	dbuf = malloc(dsize);
	if (!cbuf || !dbuf) {
		ret = -ENOMEM;
		goto out;
	}
	read_extent_buffer(leaf, cbuf, btrfs_file_extent_inline_start(fi),
			   csize);
	ret = btrfs_decompress(btrfs_file_extent_compression(leaf, fi),
			       cbuf, csize, dbuf, dsize);
	if (ret < 0) {
		ret = -EIO;
		goto out;
	}
	/*
	 * The compressed part ends before sector boundary, the remaining needs
	 * to be zeroed out.
	 */
	if (ret < dsize)
		memset(dbuf + ret, 0, dsize - ret);
	memcpy(dest, dbuf, dsize);
	ret = dsize;
out:
	free(cbuf);
	free(dbuf);
	return ret;
}

/*
 * Read out regular extent.
 *
 * Truncating should be handled by the caller.
 *
 * @offset and @len should not cross the extent boundary.
 * Return the number of bytes read.
 * Return <0 for error.
 */
int btrfs_read_extent_reg(struct btrfs_path *path,
			  struct btrfs_file_extent_item *fi, u64 offset,
			  int len, char *dest)
{
	struct extent_buffer *leaf = path->nodes[0];
	struct btrfs_fs_info *fs_info = leaf->fs_info;
	struct btrfs_key key;
	u64 extent_num_bytes;
	u64 disk_bytenr;
	u64 read;
	char *cbuf = NULL;
	char *dbuf = NULL;
	u32 csize;
	u32 dsize;
	bool finished = false;
	int num_copies;
	int i;
	int slot = path->slots[0];
	int ret;

	btrfs_item_key_to_cpu(leaf, &key, slot);
	extent_num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
	ASSERT(IS_ALIGNED(offset, fs_info->sectorsize) &&
	       IS_ALIGNED(len, fs_info->sectorsize));
	ASSERT(offset >= key.offset &&
	       offset + len <= key.offset + extent_num_bytes);

	/* Preallocated or hole , fill @dest with zero */
	if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_PREALLOC ||
	    btrfs_file_extent_disk_bytenr(leaf, fi) == 0) {
		memset(dest, 0, len);
		return len;
	}

	if (btrfs_file_extent_compression(leaf, fi) == BTRFS_COMPRESS_NONE) {
		u64 logical;

		logical = btrfs_file_extent_disk_bytenr(leaf, fi) +
			  btrfs_file_extent_offset(leaf, fi) +
			  offset - key.offset;
		read = len;

		num_copies = btrfs_num_copies(fs_info, logical, len);
		for (i = 1; i <= num_copies; i++) {
			ret = read_extent_data(fs_info, dest, logical, &read, i);
			if (ret < 0 || read != len)
				continue;
			finished = true;
			break;
		}
		if (!finished)
			return -EIO;
		return len;
	}

	csize = btrfs_file_extent_disk_num_bytes(leaf, fi);
	dsize = btrfs_file_extent_ram_bytes(leaf, fi);
	disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
	num_copies = btrfs_num_copies(fs_info, disk_bytenr, csize);

	cbuf = malloc_cache_aligned(csize);
	dbuf = malloc_cache_aligned(dsize);
	if (!cbuf || !dbuf) {
		ret = -ENOMEM;
		goto out;
	}
	/* For compressed extent, we must read the whole on-disk extent */
	for (i = 1; i <= num_copies; i++) {
		read = csize;
		ret = read_extent_data(fs_info, cbuf, disk_bytenr,
				       &read, i);
		if (ret < 0 || read != csize)
			continue;
		finished = true;
		break;
	}
	if (!finished) {
		ret = -EIO;
		goto out;
	}

	ret = btrfs_decompress(btrfs_file_extent_compression(leaf, fi), cbuf,
			       csize, dbuf, dsize);
	if (ret < 0) {
		ret = -EIO;
		goto out;
	}
	/*
	 * The compressed part ends before sector boundary, the remaining needs
	 * to be zeroed out.
	 */
	if (ret < dsize)
		memset(dbuf + ret, 0, dsize - ret);
	/* Then copy the needed part */
	memcpy(dest,
	       dbuf + btrfs_file_extent_offset(leaf, fi) + offset - key.offset,
	       len);
	ret = len;
out:
	free(cbuf);
	free(dbuf);
	return ret;
}

/*
 * Get the first file extent that covers bytenr @file_offset.
 *
 * @file_offset must be aligned to sectorsize.
 *
 * return 0 for found, and path points to the file extent.
 * return >0 for not found, and fill @next_offset.
 * @next_offset can be 0 if there is no next file extent.
 * return <0 for error.
 */
static int lookup_data_extent(struct btrfs_root *root, struct btrfs_path *path,
			      u64 ino, u64 file_offset, u64 *next_offset)
{
	struct btrfs_key key;
	struct btrfs_file_extent_item *fi;
	u8 extent_type;
	int ret = 0;

	ASSERT(IS_ALIGNED(file_offset, root->fs_info->sectorsize));
	key.objectid = ino;
	key.type = BTRFS_EXTENT_DATA_KEY;
	key.offset = file_offset;

	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	/* Error or we're already at the file extent */
	if (ret <= 0)
		return ret;
	/* Check previous file extent */
	ret = btrfs_previous_item(root, path, ino, BTRFS_EXTENT_DATA_KEY);
	if (ret < 0)
		return ret;
	if (ret > 0)
		goto check_next;
	/* Now the key.offset must be smaller than @file_offset */
	btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
	if (key.objectid != ino ||
	    key.type != BTRFS_EXTENT_DATA_KEY)
		goto check_next;

	fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
			    struct btrfs_file_extent_item);
	extent_type = btrfs_file_extent_type(path->nodes[0], fi);
	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
		if (file_offset == 0)
			return 0;
		/* Inline extent should be the only extent, no next extent. */
		*next_offset = 0;
		return 1;
	}

	/* This file extent covers @file_offset */
	if (key.offset <= file_offset && key.offset +
	    btrfs_file_extent_num_bytes(path->nodes[0], fi) > file_offset)
		return 0;
check_next:
	ret = btrfs_next_item(root, path);
	if (ret < 0)
		return ret;
	if (ret > 0) {
		*next_offset = 0;
		return 1;
	}

	btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
	fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
			    struct btrfs_file_extent_item);
	/* Next next data extent */
	if (key.objectid != ino ||
	    key.type != BTRFS_EXTENT_DATA_KEY) {
		*next_offset = 0;
		return 1;
	}
	/* Current file extent already beyond @file_offset */
	if (key.offset > file_offset) {
		*next_offset = key.offset;
		return 1;
	}
	/* This file extent covers @file_offset */
	if (key.offset <= file_offset && key.offset +
	    btrfs_file_extent_num_bytes(path->nodes[0], fi) > file_offset)
		return 0;
	/* This file extent ends before @file_offset, check next */
	ret = btrfs_next_item(root, path);
	if (ret < 0)
		return ret;
	if (ret > 0) {
		*next_offset = 0;
		return 1;
	}
	btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
	if (key.type != BTRFS_EXTENT_DATA_KEY || key.objectid != ino) {
		*next_offset = 0;
		return 1;
	}
	*next_offset = key.offset;
	return 1;
}

static int read_and_truncate_page(struct btrfs_path *path,
				  struct btrfs_file_extent_item *fi,
				  int start, int len, char *dest)
{
	struct extent_buffer *leaf = path->nodes[0];
	struct btrfs_fs_info *fs_info = leaf->fs_info;
	u64 aligned_start = round_down(start, fs_info->sectorsize);
	u8 extent_type;
	char *buf;
	int page_off = start - aligned_start;
	int page_len = fs_info->sectorsize - page_off;
	int ret;

	ASSERT(start + len <= aligned_start + fs_info->sectorsize);
	buf = malloc_cache_aligned(fs_info->sectorsize);
	if (!buf)
		return -ENOMEM;

	extent_type = btrfs_file_extent_type(leaf, fi);
	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
		ret = btrfs_read_extent_inline(path, fi, buf);
		if (ret < 0) {
			free(buf);
			return ret;
		}
		memcpy(dest, buf + page_off, min3(page_len, ret, len));
		free(buf);
		return len;
	}

	ret = btrfs_read_extent_reg(path, fi,
			round_down(start, fs_info->sectorsize),
			fs_info->sectorsize, buf);
	if (ret < 0) {
		free(buf);
		return ret;
	}
	memcpy(dest, buf + page_off, min(page_len, len));
	free(buf);
	return len;
}

int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len,
		    char *dest)
{
	struct btrfs_fs_info *fs_info = root->fs_info;
	struct btrfs_file_extent_item *fi;
	struct btrfs_path path;
	struct btrfs_key key;
	u64 aligned_start = round_down(file_offset, fs_info->sectorsize);
	u64 aligned_end = round_down(file_offset + len, fs_info->sectorsize);
	u64 next_offset;
	u64 cur = aligned_start;
	int ret = 0;

	btrfs_init_path(&path);

	/* Set the whole dest all zero, so we won't need to bother holes */
	memset(dest, 0, len);

	/* Read out the leading unaligned part */
	if (aligned_start != file_offset) {
		ret = lookup_data_extent(root, &path, ino, aligned_start,
					 &next_offset);
		if (ret < 0)
			goto out;
		if (ret == 0) {
			/* Read the unaligned part out*/
			fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
					struct btrfs_file_extent_item);
			ret = read_and_truncate_page(&path, fi, file_offset,
					round_up(file_offset, fs_info->sectorsize) -
					file_offset, dest);
			if (ret < 0)
				goto out;
			cur += fs_info->sectorsize;
		} else {
			/* The whole file is a hole */
			if (!next_offset) {
				memset(dest, 0, len);
				return len;
			}
			cur = next_offset;
		}
	}

	/* Read the aligned part */
	while (cur < aligned_end) {
		u64 extent_num_bytes;
		u8 type;

		btrfs_release_path(&path);
		ret = lookup_data_extent(root, &path, ino, cur, &next_offset);
		if (ret < 0)
			goto out;
		if (ret > 0) {
			/* No next, direct exit */
			if (!next_offset) {
				ret = 0;
				goto out;
			}
			/*
			 * Find a extent gap, mostly caused by NO_HOLE feature.
			 * Just to next offset directly.
			 */
			if (next_offset > cur) {
				cur = next_offset;
				continue;
			}
		}
		fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
				    struct btrfs_file_extent_item);
		btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
		type = btrfs_file_extent_type(path.nodes[0], fi);
		if (type == BTRFS_FILE_EXTENT_INLINE) {
			ret = btrfs_read_extent_inline(&path, fi, dest);
			goto out;
		}
		/* Skip holes, as we have zeroed the dest */
		if (type == BTRFS_FILE_EXTENT_PREALLOC ||
		    btrfs_file_extent_disk_bytenr(path.nodes[0], fi) == 0) {
			cur = key.offset + btrfs_file_extent_num_bytes(
					path.nodes[0], fi);
			continue;
		}

		/* Read the remaining part of the extent */
		extent_num_bytes = btrfs_file_extent_num_bytes(path.nodes[0],
							       fi);
		ret = btrfs_read_extent_reg(&path, fi, cur,
				min(extent_num_bytes, aligned_end - cur),
				dest + cur - file_offset);
		if (ret < 0)
			goto out;
		cur += min(extent_num_bytes, aligned_end - cur);
	}

	/* Read the tailing unaligned part*/
	if (file_offset + len != aligned_end) {
		btrfs_release_path(&path);
		ret = lookup_data_extent(root, &path, ino, aligned_end,
					 &next_offset);
		/* <0 is error, >0 means no extent */
		if (ret)
			goto out;
		fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
				    struct btrfs_file_extent_item);
		ret = read_and_truncate_page(&path, fi, aligned_end,
				file_offset + len - aligned_end,
				dest + aligned_end - file_offset);
	}
out:
	btrfs_release_path(&path);
	if (ret < 0)
		return ret;
	return len;
}
