// 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;

	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 occured 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 occured 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;
}
