// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2018 Google LLC
 */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <openssl/sha.h>
#include <openssl/md5.h>

#include "utils.h"

#ifndef __S_IFREG
#define __S_IFREG S_IFREG
#endif

unsigned int rnd(unsigned int max, unsigned int *seed)
{
	return rand_r(seed) * ((uint64_t)max + 1) / RAND_MAX;
}

int remove_dir(const char *dir)
{
	int err = rmdir(dir);

	if (err && errno == ENOTEMPTY) {
		err = delete_dir_tree(dir);
		if (err)
			return err;
		return 0;
	}

	if (err && errno != ENOENT)
		return -errno;

	return 0;
}

int drop_caches(void)
{
	int drop_caches =
		open("/proc/sys/vm/drop_caches", O_WRONLY | O_CLOEXEC);
	int i;

	if (drop_caches == -1)
		return -errno;
	i = write(drop_caches, "3", 1);
	close(drop_caches);

	if (i != 1)
		return -errno;

	return 0;
}

int mount_fs(const char *mount_dir, const char *backing_dir,
	     int read_timeout_ms)
{
	static const char fs_name[] = INCFS_NAME;
	char mount_options[512];
	int result;

	snprintf(mount_options, ARRAY_SIZE(mount_options),
		 "read_timeout_ms=%u",
		  read_timeout_ms);

	result = mount(backing_dir, mount_dir, fs_name, 0, mount_options);
	if (result != 0)
		perror("Error mounting fs.");
	return result;
}

int mount_fs_opt(const char *mount_dir, const char *backing_dir,
		 const char *opt, bool remount)
{
	static const char fs_name[] = INCFS_NAME;
	int result;

	result = mount(backing_dir, mount_dir, fs_name,
		       remount ? MS_REMOUNT : 0, opt);
	if (result != 0)
		perror("Error mounting fs.");
	return result;
}

struct hash_section {
	uint32_t algorithm;
	uint8_t log2_blocksize;
	uint32_t salt_size;
	/* no salt */
	uint32_t hash_size;
	uint8_t hash[SHA256_DIGEST_SIZE];
} __packed;

struct signature_blob {
	uint32_t version;
	uint32_t hash_section_size;
	struct hash_section hash_section;
	uint32_t signing_section_size;
	uint8_t signing_section[];
} __packed;

size_t format_signature(void **buf, const char *root_hash, const char *add_data)
{
	size_t size = sizeof(struct signature_blob) + strlen(add_data) + 1;
	struct signature_blob *sb = malloc(size);

	*sb = (struct signature_blob){
		.version = INCFS_SIGNATURE_VERSION,
		.hash_section_size = sizeof(struct hash_section),
		.hash_section =
			(struct hash_section){
				.algorithm = INCFS_HASH_TREE_SHA256,
				.log2_blocksize = 12,
				.salt_size = 0,
				.hash_size = SHA256_DIGEST_SIZE,
			},
		.signing_section_size = sizeof(uint32_t) + strlen(add_data) + 1,
	};

	memcpy(sb->hash_section.hash, root_hash, SHA256_DIGEST_SIZE);
	memcpy((char *)sb->signing_section, add_data, strlen(add_data) + 1);
	*buf = sb;
	return size;
}

int crypto_emit_file(int fd, const char *dir, const char *filename,
		     incfs_uuid_t *id_out, size_t size, const char *root_hash,
		     const char *add_data)
{
	int mode = __S_IFREG | 0555;
	void *signature;
	int error = 0;

	struct incfs_new_file_args args = {
			.size = size,
			.mode = mode,
			.file_name = ptr_to_u64(filename),
			.directory_path = ptr_to_u64(dir),
			.file_attr = 0,
			.file_attr_len = 0
	};

	args.signature_size = format_signature(&signature, root_hash, add_data);
	args.signature_info = ptr_to_u64(signature);

	md5(filename, strlen(filename), (char *)args.file_id.bytes);

	if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0) {
		error = -errno;
		goto out;
	}

	*id_out = args.file_id;

out:
	free(signature);
	return error;
}

int emit_file(int fd, const char *dir, const char *filename,
	      incfs_uuid_t *id_out, size_t size, const char *attr)
{
	int mode = __S_IFREG | 0555;
	struct incfs_new_file_args args = { .size = size,
					    .mode = mode,
					    .file_name = ptr_to_u64(filename),
					    .directory_path = ptr_to_u64(dir),
					    .signature_info = ptr_to_u64(NULL),
					    .signature_size = 0,
					    .file_attr = ptr_to_u64(attr),
					    .file_attr_len =
						    attr ? strlen(attr) : 0 };

	md5(filename, strlen(filename), (char *)args.file_id.bytes);

	if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0)
		return -errno;

	*id_out = args.file_id;
	return 0;
}

int get_file_bmap(int cmd_fd, int ino, unsigned char *buf, int buf_size)
{
	return 0;
}

int get_file_signature(int fd, unsigned char *buf, int buf_size)
{
	struct incfs_get_file_sig_args args = {
		.file_signature = ptr_to_u64(buf),
		.file_signature_buf_size = buf_size
	};

	if (ioctl(fd, INCFS_IOC_READ_FILE_SIGNATURE, &args) == 0)
		return args.file_signature_len_out;
	return -errno;
}

loff_t get_file_size(const char *name)
{
	struct stat st;

	if (stat(name, &st) == 0)
		return st.st_size;
	return -ENOENT;
}

int open_commands_file(const char *mount_dir)
{
	char cmd_file[255];
	int cmd_fd;

	snprintf(cmd_file, ARRAY_SIZE(cmd_file),
			"%s/%s", mount_dir, INCFS_PENDING_READS_FILENAME);
	cmd_fd = open(cmd_file, O_RDONLY | O_CLOEXEC);

	if (cmd_fd < 0)
		perror("Can't open commands file");
	return cmd_fd;
}

int open_log_file(const char *mount_dir)
{
	char file[255];
	int fd;

	snprintf(file, ARRAY_SIZE(file), "%s/.log", mount_dir);
	fd = open(file, O_RDWR | O_CLOEXEC);
	if (fd < 0)
		perror("Can't open log file");
	return fd;
}

int open_blocks_written_file(const char *mount_dir)
{
	char file[255];
	int fd;

	snprintf(file, ARRAY_SIZE(file),
			"%s/%s", mount_dir, INCFS_BLOCKS_WRITTEN_FILENAME);
	fd = open(file, O_RDONLY | O_CLOEXEC);

	if (fd < 0)
		perror("Can't open blocks_written file");
	return fd;
}

int wait_for_pending_reads(int fd, int timeout_ms,
	struct incfs_pending_read_info *prs, int prs_count)
{
	ssize_t read_res = 0;

	if (timeout_ms > 0) {
		int poll_res = 0;
		struct pollfd pollfd = {
			.fd = fd,
			.events = POLLIN
		};

		poll_res = poll(&pollfd, 1, timeout_ms);
		if (poll_res < 0)
			return -errno;
		if (poll_res == 0)
			return 0;
		if (!(pollfd.revents | POLLIN))
			return 0;
	}

	read_res = read(fd, prs, prs_count * sizeof(*prs));
	if (read_res < 0)
		return -errno;

	return read_res / sizeof(*prs);
}

int wait_for_pending_reads2(int fd, int timeout_ms,
	struct incfs_pending_read_info2 *prs, int prs_count)
{
	ssize_t read_res = 0;

	if (timeout_ms > 0) {
		int poll_res = 0;
		struct pollfd pollfd = {
			.fd = fd,
			.events = POLLIN
		};

		poll_res = poll(&pollfd, 1, timeout_ms);
		if (poll_res < 0)
			return -errno;
		if (poll_res == 0)
			return 0;
		if (!(pollfd.revents | POLLIN))
			return 0;
	}

	read_res = read(fd, prs, prs_count * sizeof(*prs));
	if (read_res < 0)
		return -errno;

	return read_res / sizeof(*prs);
}

char *concat_file_name(const char *dir, const char *file)
{
	char full_name[FILENAME_MAX] = "";

	if (snprintf(full_name, ARRAY_SIZE(full_name), "%s/%s", dir, file) < 0)
		return NULL;
	return strdup(full_name);
}

int delete_dir_tree(const char *dir_path)
{
	DIR *dir = NULL;
	struct dirent *dp;
	int result = 0;

	dir = opendir(dir_path);
	if (!dir) {
		result = -errno;
		goto out;
	}

	while ((dp = readdir(dir))) {
		char *full_path;

		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
			continue;

		full_path = concat_file_name(dir_path, dp->d_name);
		if (dp->d_type == DT_DIR)
			result = delete_dir_tree(full_path);
		else
			result = unlink(full_path);
		free(full_path);
		if (result)
			goto out;
	}

out:
	if (dir)
		closedir(dir);
	if (!result)
		rmdir(dir_path);
	return result;
}

void sha256(const char *data, size_t dsize, char *hash)
{
	SHA256_CTX ctx;

	SHA256_Init(&ctx);
	SHA256_Update(&ctx, data, dsize);
	SHA256_Final((unsigned char *)hash, &ctx);
}

void md5(const char *data, size_t dsize, char *hash)
{
	MD5_CTX ctx;

	MD5_Init(&ctx);
	MD5_Update(&ctx, data, dsize);
	MD5_Final((unsigned char *)hash, &ctx);
}
