Linux中是否有任何方法使用c生成存储在内存中的两个文件的diff / patch,使用通用格式(即:统一差异,与命令行{{1}一样)实用工具)?
我正在开发一个系统,我在内存中生成两个文本文件,没有可用的外部存储空间。我需要创建两个文件的逐行差异,因为它们是diff
,所以它们没有文件名,这使我无法简单地调用mmap
。
我有可供使用的文件描述符(system("diff file1.txt file2.txt")
),这是我唯一的数据入口点。有没有办法通过比较两个打开的文件生成差异/补丁?如果实现是MIT / BSD许可(即:非GPL),那就更好了。
谢谢。
答案 0 :(得分:4)
在Linux上,您可以使用/ dev / fd / pseudo文件系统(/ proc / self / fd的符号链接)。使用snprintf()为fd2构建snprintf(path1, PATH_MAX, "/dev/fd/%d", fd1);
ditto等文件描述符的路径,并在它们上运行 diff 。
答案 1 :(得分:2)
考虑到要求,最好的选择是实现自己的内存diff -au
。您可以根据需要调整OpenBSD的diff
的相关部分。
以下是如何通过管道使用/usr/bin/diff
命令获取存储在内存中的两个字符串之间的统一差异的概述:
创建三个管道: I1 , I2 和 O 。
分叉子进程。
在子进程中:
将管道 I1 和 I2 的读取端移动到描述符3和4,将管道 O 的写入端移动到描述符1。
在子进程中关闭这些管道的另一端。打开描述符0从/ dev / null读取,描述符2写入/ dev / null。
执行execl("/usr/bin/diff", "diff", "-au", "/proc/self/fd/3", "/proc/self/fd/4", NULL);
这将在子进程中执行diff
二进制文件。它将读取两个管道 I1 和 I2 的输入,并将差异输出到管道 O 。
父进程关闭 I1 和 I2 管道的读取端,以及 O 管道的写入端。
父进程将比较数据写入 I1 和 I2 管道的写入端,并从的读取端读取差异O 管道。
请注意,父进程必须使用select()
或poll()
或类似方法(最好使用非阻塞描述符)以避免死锁。 (如果父和子同时尝试读取或同时写入,则会发生死锁。)通常,父进程必须不惜一切代价避免阻塞,因为这可能会导致死锁。
当完全写入输入数据时,父进程必须关闭管道的相应写端,以便子进程检测到输入结束。 (除非发生错误,否则必须在子进程关闭 O 管道末尾之前关闭写入结束。)
当父进程注意到 O 管道中没有更多数据可用时(read()
返回0
),它已经关闭了< em> I1 和 I2 管道,或者出现错误。如果没有错误,则数据传输完成,并且可以获得子进程。
父进程使用例如子进程收回子进程。 waitpid()
。请注意,如果存在任何差异,diff
将返回退出状态为1。
您可以使用第四个管道从子进程接收标准错误流; diff
通常不会输出任何标准错误。
您可以使用第五个管道,在子项中将O_CLOEXEC
标记为fcntl()
,以检测execl()
个错误。 O_CLOEXEC
标志表示在执行另一个二进制文件时关闭描述符,因此父进程可以通过检测读取端中的数据结尾来检测diff
命令的成功启动(read()
返回0
)。如果execl()
失败,孩子可以例如将errno
值(作为十进制数或int
)写入此管道,以便父进程可以读取失败的确切原因。
总之,完整的方法(记录标准错误,并检测exec错误)使用10个描述符。这不应该是正常应用程序中的问题,但可能很重要 - 例如,考虑面向Internet的服务器,其中包含传入连接使用的描述符。