跳转至

diff 与 patch 命令


2017-02-09 by dongnan

问题描述

某台服务器系统为 centos 7.3 amd64 编译安装 libiconv-1.14 报错,提示以下错误信息:

In file included from progname.c:26:0:
./stdio.h:1010:1: error: ‘gets’ undeclared here (not in a function)
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");

解决方法参考:http://www.rootop.org/pages/3532.html

目标

减少人工操作(编辑 libiconv-1.14/srclib/stdio.h),使用 diff & patch 命令制作并应用补丁。

步骤

对比两个文件

diff new.h libiconv-1.14/srclib/stdio.h

1010d1009
< #if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16)
1012d1010
< #endif

创建 patch 文件

diff -uN libiconv-1.14/srclib/stdio.h new.h > diff.patch

# patch 文件内容
cat diff.patch
--- libiconv-1.14/srclib/stdio.h    2017-02-07 11:59:17.730000000 +0800
+++ new.h    2017-02-07 12:57:30.218000000 +0800
@@ -1007,8 +1007,10 @@
 /* It is very rare that the developer ever has full control of stdin,
    so any use of gets warrants an unconditional warning.  Assume it is
    always declared, since it is required by C89.  */
+#if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16)
 _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
 #endif
+#endif
 #if 0 || 0

使用 patch 命令 打补丁

patch -p2 < diff.patch libiconv-1.14/srclib/stdio.h

注意,p2 数字2

验证

对比文件

diff new.h libiconv-1.14/srclib/stdio.h
输出空,表示打补丁成功(文件相同)

如果反悔了,还可以去除补丁 使用 -R参数即可

patch -R -p2 < diff.patch libiconv-1.14/srclib/stdio.h
patching file libiconv-1.14/srclib/stdio.h

再次对比文件,两个文件恢复到初始状态

diff new.h libiconv-1.14/srclib/stdio.h

1010d1009
< #if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16)
1012d1010
< #endif

帮助

diff 命令

简单的说,diff的功能就是用来比较两个文件/夹的不同,然后记录下来,也就是所谓的diff补丁。

语法:diff 【选项】 源文件/夹(旧) 目的文件/夹(新),就是要给源文件(夹)打个补丁,使之变成目的文件(夹)。
-r ,是一个递归选项,设置了这个选项,diff会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,包括子目录文件。
-N ,选项确保补丁文件将正确地处理已经创建或删除文件的情况。
-u ,选项以统一格式创建补丁文件,这种格式比缺省格式更紧凑些。
一般 -uN 是一直使用的参数,而 -r 如果是含子目录就使用,不含则不使用,参考上面的示例。

补丁文件的结构

补丁头

补丁头是分别由 ---/+++开头的两行,用来表示要打补丁的文件;
--- 开头表示旧文件;
+++ 开头表示新文件。

一个补丁文件中可能包含以 ---/+++开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁。

--- libiconv-1.14/srclib/stdio.h    2017-02-07 11:59:17.730000000 +0800
+++ new.h    2017-02-07 12:57:30.218000000 +0800

补丁块

块是补丁中要修改的地方。它通常由一部分不用修改的东西开始和结束。 他们只是用来表示要修改的位置。他们通常以@@开始,结束于另一个块的开始或者一个新的补丁头。

块会缩进一列,这一列是用来表示这一行是要增加还是要删除的。
+号表示这一行是要加上的。
-号表示这一行是要删除的。
没有加号也没有减号表示这里只是引用的而不需要修改。

patch 命令

可以理解,patch 就是利用diff制作的补丁来实现源文件(夹)和目的文件(夹)的转换。

常用选项:
-pnum ,是指查找patch文件中指定的文件时,忽略前 num个目录,一个"/"为一层。
-R ,选项说明在补丁文件中的"新"文件和"旧"文件现在要调换过来了。
-E ,选项说明如果发现了空文件,那么就删除它。

参考

GNU Linux中使用diff生成补丁与用patch打补丁

回到页面顶部