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

#include "btrfs.h"
#include <config.h>
#include <malloc.h>
#include <uuid.h>
#include <linux/time.h>

struct btrfs_info btrfs_info;

static int readdir_callback(const struct btrfs_root *root,
			    struct btrfs_dir_item *item)
{
	static const char typestr[BTRFS_FT_MAX][4] = {
		[BTRFS_FT_UNKNOWN]  = " ? ",
		[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",
		[BTRFS_FT_XATTR]    = " ? ",
	};
	struct btrfs_inode_item inode;
	const char *name = (const char *) (item + 1);
	char filetime[32], *target = NULL;
	time_t mtime;

	if (btrfs_lookup_inode(root, &item->location, &inode, NULL)) {
		printf("%s: Cannot find inode item for directory entry %.*s!\n",
		       __func__, item->name_len, name);
		return 0;
	}

	mtime = inode.mtime.sec;
	ctime_r(&mtime, filetime);

	if (item->type == BTRFS_FT_SYMLINK) {
		target = malloc(min(inode.size + 1,
				    (u64) btrfs_info.sb.sectorsize));

		if (target && btrfs_readlink(root, item->location.objectid,
					     target)) {
			free(target);
			target = NULL;
		}

		if (!target)
			printf("%s: Cannot read symlink target!\n", __func__);
	}

	printf("<%s> ", typestr[item->type]);
	if (item->type == BTRFS_FT_CHRDEV || item->type == BTRFS_FT_BLKDEV)
		printf("%4u,%5u  ", (unsigned int) (inode.rdev >> 20),
			(unsigned int) (inode.rdev & 0xfffff));
	else
		printf("%10llu  ", inode.size);

	printf("%24.24s  %.*s", filetime, item->name_len, name);

	if (item->type == BTRFS_FT_SYMLINK) {
		printf(" -> %s", target ? target : "?");
		if (target)
			free(target);
	}

	printf("\n");

	return 0;
}

int btrfs_probe(struct blk_desc *fs_dev_desc,
		struct disk_partition *fs_partition)
{
	btrfs_blk_desc = fs_dev_desc;
	btrfs_part_info = fs_partition;

	memset(&btrfs_info, 0, sizeof(btrfs_info));

	btrfs_hash_init();
	if (btrfs_read_superblock())
		return -1;

	if (btrfs_chunk_map_init()) {
		printf("%s: failed to init chunk map\n", __func__);
		return -1;
	}

	btrfs_info.tree_root.objectid = 0;
	btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
	btrfs_info.chunk_root.objectid = 0;
	btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;

	if (btrfs_read_chunk_tree()) {
		printf("%s: failed to read chunk tree\n", __func__);
		return -1;
	}

	if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
			    &btrfs_info.fs_root, NULL)) {
		printf("%s: failed to find default subvolume\n", __func__);
		return -1;
	}

	return 0;
}

int btrfs_ls(const char *path)
{
	struct btrfs_root root = btrfs_info.fs_root;
	u64 inr;
	u8 type;

	inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);

	if (inr == -1ULL) {
		printf("Cannot lookup path %s\n", path);
		return -1;
	}

	if (type != BTRFS_FT_DIR) {
		printf("Not a directory: %s\n", path);
		return -1;
	}

	if (btrfs_readdir(&root, inr, readdir_callback)) {
		printf("An error occured while listing directory %s\n", path);
		return -1;
	}

	return 0;
}

int btrfs_exists(const char *file)
{
	struct btrfs_root root = btrfs_info.fs_root;
	u64 inr;
	u8 type;

	inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);

	return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
}

int btrfs_size(const char *file, loff_t *size)
{
	struct btrfs_root root = btrfs_info.fs_root;
	struct btrfs_inode_item inode;
	u64 inr;
	u8 type;

	inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
				40);

	if (inr == -1ULL) {
		printf("Cannot lookup file %s\n", file);
		return -1;
	}

	if (type != BTRFS_FT_REG_FILE) {
		printf("Not a regular file: %s\n", file);
		return -1;
	}

	*size = inode.size;
	return 0;
}

int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
	       loff_t *actread)
{
	struct btrfs_root root = btrfs_info.fs_root;
	struct btrfs_inode_item inode;
	u64 inr, rd;
	u8 type;

	inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
				40);

	if (inr == -1ULL) {
		printf("Cannot lookup file %s\n", file);
		return -1;
	}

	if (type != BTRFS_FT_REG_FILE) {
		printf("Not a regular file: %s\n", file);
		return -1;
	}

	if (!len)
		len = inode.size;

	if (len > inode.size - offset)
		len = inode.size - offset;

	rd = btrfs_file_read(&root, inr, offset, len, buf);
	if (rd == -1ULL) {
		printf("An error occured while reading file %s\n", file);
		return -1;
	}

	*actread = rd;
	return 0;
}

void btrfs_close(void)
{
	btrfs_chunk_map_exit();
}

int btrfs_uuid(char *uuid_str)
{
#ifdef CONFIG_LIB_UUID
	uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);
	return 0;
#endif
	return -ENOSYS;
}
