// SPDX-License-Identifier: GPL-2.0+
/*
 * BTRFS filesystem implementation for U-Boot
 *
 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
 */

#include <config.h>
#include <malloc.h>
#include <uuid.h>
#include <linux/time.h>
#include "btrfs.h"
#include "crypto/hash.h"
#include "disk-io.h"

struct btrfs_fs_info *current_fs_info;

static int show_dir(struct btrfs_root *root, struct extent_buffer *eb,
		    struct btrfs_dir_item *di)
{
	struct btrfs_fs_info *fs_info = root->fs_info;
	struct btrfs_inode_item ii;
	struct btrfs_key key;
	static const char* dir_item_str[] = {
		[BTRFS_FT_REG_FILE]	= "FILE",
		[BTRFS_FT_DIR] 		= "DIR",
		[BTRFS_FT_CHRDEV]	= "CHRDEV",
		[BTRFS_FT_BLKDEV]	= "BLKDEV",
		[BTRFS_FT_FIFO]		= "FIFO",
		[BTRFS_FT_SOCK]		= "SOCK",
		[BTRFS_FT_SYMLINK]	= "SYMLINK",
		[BTRFS_FT_XATTR]	= "XATTR"
	};
	u8 type = btrfs_dir_type(eb, di);
	char namebuf[BTRFS_NAME_LEN];
	char *target = NULL;
	char filetime[32];
	time_t mtime;
	int ret = 0;

	btrfs_dir_item_key_to_cpu(eb, di, &key);

	if (key.type == BTRFS_ROOT_ITEM_KEY) {
		struct btrfs_root *subvol;

		/* It's a subvolume, get its mtime from root item */
		subvol = btrfs_read_fs_root(fs_info, &key);
		if (IS_ERR(subvol)) {
			ret = PTR_ERR(subvol);
			error("Can't find root %llu", key.objectid);
			return ret;
		}
		mtime = btrfs_stack_timespec_sec(&subvol->root_item.otime);
	} else {
		struct btrfs_path path;

		/* It's regular inode, get its mtime from inode item */
		btrfs_init_path(&path);
		ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
		if (ret > 0)
			ret = -ENOENT;
		if (ret < 0) {
			error("Can't find inode %llu", key.objectid);
			btrfs_release_path(&path);
			return ret;
		}
		read_extent_buffer(path.nodes[0], &ii,
			btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
			sizeof(ii));
		btrfs_release_path(&path);
		mtime = btrfs_stack_timespec_sec(&ii.mtime);
	}
	ctime_r(&mtime, filetime);

	if (type == BTRFS_FT_SYMLINK) {
		target = malloc(fs_info->sectorsize);
		if (!target) {
			error("Can't alloc memory for symlink %llu",
				key.objectid);
			return -ENOMEM;
		}
		ret = btrfs_readlink(root, key.objectid, target);
		if (ret < 0) {
			error("Failed to read symlink %llu", key.objectid);
			goto out;
		}
		target[ret] = '\0';
	}

	if (type < ARRAY_SIZE(dir_item_str) && dir_item_str[type])
		printf("<%s> ", dir_item_str[type]);
	else
		printf("DIR_ITEM.%u", type);
	if (type == BTRFS_FT_CHRDEV || type == BTRFS_FT_BLKDEV) {
		ASSERT(key.type == BTRFS_INODE_ITEM_KEY);
		printf("%4llu,%5llu  ", btrfs_stack_inode_rdev(&ii) >> 20,
				btrfs_stack_inode_rdev(&ii) & 0xfffff);
	} else {
		if (key.type == BTRFS_INODE_ITEM_KEY)
			printf("%10llu  ", btrfs_stack_inode_size(&ii));
		else
			printf("%10llu  ", 0ULL);
	}

	read_extent_buffer(eb, namebuf, (unsigned long)(di + 1),
			   btrfs_dir_name_len(eb, di));
	printf("%24.24s  %.*s", filetime, btrfs_dir_name_len(eb, di), namebuf);
	if (type == BTRFS_FT_SYMLINK)
		printf(" -> %s", target ? target : "?");
	printf("\n");
out:
	free(target);
	return ret;
}

int btrfs_probe(struct blk_desc *fs_dev_desc,
		struct disk_partition *fs_partition)
{
	struct btrfs_fs_info *fs_info;
	int ret = -1;

	btrfs_hash_init();
	fs_info = open_ctree_fs_info(fs_dev_desc, fs_partition);
	if (fs_info) {
		current_fs_info = fs_info;
		ret = 0;
	}
	return ret;
}

int btrfs_ls(const char *path)
{
	struct btrfs_fs_info *fs_info = current_fs_info;
	struct btrfs_root *root = fs_info->fs_root;
	u64 ino = BTRFS_FIRST_FREE_OBJECTID;
	u8 type;
	int ret;

	ASSERT(fs_info);
	ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
				path, &root, &ino, &type, 40);
	if (ret < 0) {
		printf("Cannot lookup path %s\n", path);
		return ret;
	}

	if (type != BTRFS_FT_DIR) {
		error("Not a directory: %s", path);
		return -ENOENT;
	}
	ret = btrfs_iter_dir(root, ino, show_dir);
	if (ret < 0) {
		error("An error occurred while listing directory %s", path);
		return ret;
	}
	return 0;
}

int btrfs_exists(const char *file)
{
	struct btrfs_fs_info *fs_info = current_fs_info;
	struct btrfs_root *root;
	u64 ino;
	u8 type;
	int ret;

	ASSERT(fs_info);

	ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
				file, &root, &ino, &type, 40);
	if (ret < 0)
		return 0;

	if (type == BTRFS_FT_REG_FILE)
		return 1;
	return 0;
}

int btrfs_size(const char *file, loff_t *size)
{
	struct btrfs_fs_info *fs_info = current_fs_info;
	struct btrfs_inode_item *ii;
	struct btrfs_root *root;
	struct btrfs_path path;
	struct btrfs_key key;
	u64 ino;
	u8 type;
	int ret;

	ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
				file, &root, &ino, &type, 40);
	if (ret < 0) {
		printf("Cannot lookup file %s\n", file);
		return ret;
	}
	if (type != BTRFS_FT_REG_FILE) {
		printf("Not a regular file: %s\n", file);
		return -ENOENT;
	}
	btrfs_init_path(&path);
	key.objectid = ino;
	key.type = BTRFS_INODE_ITEM_KEY;
	key.offset = 0;

	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
	if (ret < 0) {
		printf("Cannot lookup ino %llu\n", ino);
		return ret;
	}
	if (ret > 0) {
		printf("Ino %llu does not exist\n", ino);
		ret = -ENOENT;
		goto out;
	}
	ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
			    struct btrfs_inode_item);
	*size = btrfs_inode_size(path.nodes[0], ii);
out:
	btrfs_release_path(&path);
	return ret;
}

int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
	       loff_t *actread)
{
	struct btrfs_fs_info *fs_info = current_fs_info;
	struct btrfs_root *root;
	loff_t real_size = 0;
	u64 ino;
	u8 type;
	int ret;

	ASSERT(fs_info);
	ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
				file, &root, &ino, &type, 40);
	if (ret < 0) {
		error("Cannot lookup file %s", file);
		return ret;
	}

	if (type != BTRFS_FT_REG_FILE) {
		error("Not a regular file: %s", file);
		return -EINVAL;
	}

	if (!len) {
		ret = btrfs_size(file, &real_size);
		if (ret < 0) {
			error("Failed to get inode size: %s", file);
			return ret;
		}
		len = real_size;
	}

	if (len > real_size - offset)
		len = real_size - offset;

	ret = btrfs_file_read(root, ino, offset, len, buf);
	if (ret < 0) {
		error("An error occurred while reading file %s", file);
		return ret;
	}

	*actread = len;
	return 0;
}

void btrfs_close(void)
{
	if (current_fs_info) {
		close_ctree_fs_info(current_fs_info);
		current_fs_info = NULL;
	}
}

int btrfs_uuid(char *uuid_str)
{
#ifdef CONFIG_LIB_UUID
	if (current_fs_info)
		uuid_bin_to_str(current_fs_info->super_copy->fsid, uuid_str,
				UUID_STR_FORMAT_STD);
	return 0;
#endif
	return -ENOSYS;
}
