// 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]	= "   ",
		[BTRFS_FT_DIR] 		= "DIR",
		[BTRFS_FT_CHRDEV]	= "CHR",
		[BTRFS_FT_BLKDEV]	= "BLK",
		[BTRFS_FT_FIFO]		= "FIF",
		[BTRFS_FT_SOCK]		= "SCK",
		[BTRFS_FT_SYMLINK]	= "SYM",
	};
	u8 type = btrfs_dir_type(eb, di);
	char namebuf[BTRFS_NAME_LEN];
	char *target = NULL;
	char filetime[32];
	time_t mtime;
	int ret = 0;

	/* skip XATTRs in directory listing */
	if (type == BTRFS_FT_XATTR)
		return 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("?%3u? ", 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;
}
