如何轻松修复Fedora程序包 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

如何轻松修复Fedora程序包

xiaohui 技术 2020-02-16 10:30:00
421857
收藏

导语:Fedora 是一个 Linux 发行版,是一款由全球社区爱好者构建的面向日常应用的快速、稳定、强大的操作系统。

Fedora 是一个 Linux 发行版,是一款由全球社区爱好者构建的面向日常应用的快速、稳定、强大的操作系统。 [1] 它允许任何人自由地使用、修改和重发布,无论现在还是将来。它由一个强大的社群开发,这个社群的成员以自己的不懈努力,提供并维护自由、开放源码的程序和开放的标准。

尽管许多Linux用户是开发人员,但相当一部分开发人员在使用时会经常干预或扩展已发行的程序包。当程序包中有待处理的功能,或者程序包中有漏洞时,用户通常会等待发行维护者对其进行修复,或者使用独立的解决方案(例如自制程序)来自行构建。

幸运的是,在Fedora中,开发人员可以处理每个程序包自身的问题,并使构建修改版本变得异常容易。

安装原始程序包

首先,我们从安装几个基本系统程序包开始,这些程序包将帮助我们处理程序包构建:

$ sudo dnf install fedpkg make

假设我们要考虑zsh(Z Shell)的补丁或功能,就需要考虑什么是生成二进制文件的源程序包项目。查询rpm工具很容易,根据已安装程序包的文件名,可以显示源程序包RPM的名称。例如:

$ rpm -qif /usr/bin/zsh | grep 'Source RPM'
Source RPM  : zsh-5.7.1-4.fc30.src.rpm

源RPM名称也是zsh,这并不奇怪。但是,其他包可能不是这样。

通常,源程序包的RPM名称与 Git存储库的名称相匹配,这意味着,Fedora在该Git存储库中维护允许构建它的脚本。从Fedora的Git服务器克隆源程序包非常容易,并且不需要成为Fedora社区成员或使用任何其他凭据。对于zsh,我们可以使用fedpkg执行以下命令:

$ fedpkg co -a zsh
Cloning into 'zsh'...
remote: Counting objects: 1023, done.
remote: Compressing objects: 100% (777/777), done.
remote: Total 1023 (delta 556), reused 423 (delta 216)
Receiving objects: 100% (1023/1023), 235.29 KiB | 271.00 KiB/s, done.
Resolving deltas: 100% (556/556), done.

对于每个程序包,每个版本的Fedora的源都保存在不同的分支中。因此,我们可以找出与我们要为其构建的发行版本匹配的分支:

$ cd zsh
$ git checkout -b f31 origin/f31
Branch 'f31' set up to track remote branch 'f31' from 'origin'.
Switched to a new branch 'f31'

从现在开始,我们将在程序包的工作目录中调用fedpkg。

设置构建环境

对于正常运行的开发环境,不同的程序包将有不同的要求。幸运的是,Fedora的dnf可以帮助我们引入它可以构建的任何程序包所需的依赖项。这可以通过dnf builddep命令来完成。对于我们的用例,我们可以引入zsh依赖项:

$ sudo dnf builddep zsh

直接建立可分配的RPM

在修改包之前,有必要测试一下,看看我们是否能够在不进行任何修改的情况下正确地构建它,以下命令将尝试从代码的当前状态构建二进制RPM:

$ fedpkg local

我们可以观察到已经生成了以下RPM:

$ ls -l1 x86_64/ noarch/
noarch/:
total 452
-rw-rw-r--. 1 user user 459748 Jan 14 13:58 zsh-html-5.7.1-4.fc31.noarch.rpm

x86_64/:
total 5476
-rw-rw-r--. 1 user user 2999294 Jan 14 13:58 zsh-5.7.1-4.fc31.x86_64.rpm
-rw-rw-r--. 1 user user 1771784 Jan 14 13:58 zsh-debuginfo-5.7.1-4.fc31.x86_64.rpm
-rw-rw-r--. 1 user user  829306 Jan 14 13:58 zsh-debugsource-5.7.1-4.fc31.x86_64.rpm

或者,在模拟容器中构建RPM。

甚至在Docker容器流行之前,Fedora就向我们提供了一个名为mock的工具,该工具会创建了一个用于构建程序包的独立环境。因此,可以使用它独立于开发环境来构建程序包。

首先,我们需要确保安装了mock。

$ sudo dnf install mock

然后,我们可以告诉fedpkg使用mock来构建包:

$ fedpkg mockbuild

mock的构建输出全部被移动到一个目录,其中包含构建的日志文件以及程序包的版本和名称:

$ ls -lR results_zsh/*/*
results_zsh/5.7.1/4.fc31:
total 9852
-rw-rw-r--. 1 user user  190779 Jan 14 14:10 build.log
-rw-rw-r--. 1 user user    2744 Jan 14 14:03 hw_info.log
-rw-rw-r--. 1 user user   52642 Jan 14 14:08 installed_pkgs.log
-rw-rw-r--. 1 user user  614047 Jan 14 14:10 root.log
-rw-rw-r--. 1 user user     998 Jan 14 14:10 state.log
-rw-r--r--. 1 user mock 3146067 Jan 14 14:06 zsh-5.7.1-4.fc31.src.rpm
-rw-r--r--. 1 user mock 2999346 Jan 14 14:10 zsh-5.7.1-4.fc31.x86_64.rpm
-rw-r--r--. 1 user mock 1772488 Jan 14 14:10 zsh-debuginfo-5.7.1-4.fc31.x86_64.rpm
-rw-r--r--. 1 user mock  829174 Jan 14 14:10 zsh-debugsource-5.7.1-4.fc31.x86_64.rpm
-rw-r--r--. 1 user mock  459682 Jan 14 14:10 zsh-html-5.7.1-4.fc31.noarch.rpm

使用mock执行构建的优势在于,它可以验证构建的依赖项是否正确指定,并且还可以用于在同一台计算机上针对发行版的不同版本进行构建。另外,它也是Fedora自己的构建服务器(即Copr)背后的运行设备。

添加补丁

要为程序包生成补丁,我们需要包本身的源代码,而不是告诉我们如何构建它的Fedora脚本的源代码。

有多种获取源代码的方法,其中一种是使用fedpkg。我们可以让它创建一个目录,其中包含已准备好构建的修补程序包源代码。这个过程将执行RPM规范源代码的准备阶段,结果通常是工作树下的一个目录。

$ fedpkg prep

因为Fedora源代码包不会考虑源代码控制方面的问题,所以它们只包含某个版本源代码的压缩文件。在源代码控制中不跟踪创建的目录,如果要修改它,通常最好将它移到另一个目录,并使用Git对其进行初始化。如下所示:

$ mv zsh-5.7.1 ../zsh-5.7.1
$ cd ../zsh-5.7.1
$ git init && git add -f . && git commit -m "Base version"

在这个示例中,我们的zsh-5.7.1只是该Fedora维护版本的代表,它可能已经被Fedora进行了某种程度的修补,但是它可以并且应该被用作我们进一步修补的基础。但是,我们可能想要克隆完整的项目,在这种情况下,zsh方便于完整的Git历史浏览。

$ cd ..
$ git clone git://git.code.sf.net/p/zsh/code zsh-upstream
Cloning into 'zsh-upstream'...
remote: Enumerating objects: 94026, done.
remote: Counting objects: 100% (94026/94026), done.
remote: Compressing objects: 100% (25128/25128), done.
remote: Total 94026 (delta 73505), reused 87930 (delta 68487)
Receiving objects: 100% (94026/94026), 16.60 MiB | 1.07 MiB/s, done.
Resolving deltas: 100% (73505/73505), done.

回到任何一个源代码克隆,我们都可以继续提交更改并通过提交生成补丁,以下就是一个简单补丁的示例:

$ git diff HEAD
diff --git a/Src/hist.c b/Src/hist.c
index dbdc1e4..cdb1dd1 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -580,7 +580,7 @@ histsubchar(int c)
      */
     lexraw_mark = zshlex_raw_mark(-1);-    /* look, no goto's */+    /* look, no goto's! */     if (isfirstch && c == hatchar) {
        int gbal = 0;

$ git commit -m "Adding an exclamation mark to Src/hist.c"
[f31 c00d68b] Adding an exclamation mark to Src/hist.c
 2 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 0001-zsh-5.7.1-zle-history-avoid-crash.patch

$ git format-patch HEAD~1 -o ../zsh
../zsh/0001-Adding-an-exclamation-mark-to-Src-hist.c.patch

git format-patch是一个方便的命令,可以将git提交为文件,它的输出可以作为程序包构建过程的输入,因为Fedora中的程序包标准要求其上层的源代码与在其上生成的补丁分开。

将补丁文件添加到Fedora程序包的源规范中可能会有些棘手,但是经过几次之后,你了解到打包格式比起初看起来更简单。对于zsh,我们只需要在zsh.spec开头的Patch

$ git diff
diff --git a/zsh.spec b/zsh.spec
index 0d77f70..0022a90 100644
--- a/zsh.spec
+++ b/zsh.spec
@@ -14,6 +14,7 @@ Source6: dotzshrc

 # make failed searches of history in Zle robust (#1722703)
 Patch1:  0001-zsh-5.7.1-zle-history-avoid-crash.patch+Patch2:  0001-Adding-an-exclamation-mark-to-Src-hist.c.patch
 BuildRequires: autoconf
 BuildRequires: coreutils

较旧的程序包可能需要更多更改,例如,在文件中进一步添加与上述准备阶段有关的额外%patch行。

识别修补过的程序包

如果没有其他的.spec字段被更改,我们修改后的包在元数据中与原始包几乎没有区别。通常情况下这是不需要的。因此,最好将.spec修改为在程序包的Release字段中包含一个字符串。例如:

diff --git a/zsh.spec b/zsh.spec
index 0022a90..78c362e 100644
--- a/zsh.spec
+++ b/zsh.spec
@@ -1,7 +1,7 @@
 Summary: Powerful interactive shell
 Name: zsh
 Version: 5.7.1-Release: 4%{?dist}+Release: 4%{?dist}.daloni License: MIT
 URL: http://zsh.sourceforge.net/
 Source0: https://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.xz

我们可以看到,在构建之后。

$ ls -l1 x86_64/ noarch/

noarch/:
total 452
-rw-rw-r--. 1 user user 459790 Jan 14 15:15 zsh-html-5.7.1-4.fc31.daloni.noarch.rpm

x86_64/:
total 5476
-rw-rw-r--. 1 user user 2999482 Jan 14 15:15 zsh-5.7.1-4.fc31.daloni.x86_64.rpm
-rw-rw-r--. 1 user user 1773094 Jan 14 15:15 zsh-debuginfo-5.7.1-4.fc31.daloni.x86_64.rpm
-rw-rw-r--. 1 user user  829124 Jan 14 15:15 zsh-debugsource-5.7.1-4.fc31.daloni.x86_64.rpm

安装程序包

可以通过dnf install安装新程序包,一旦安装了修补程序包,就可以通过各种方式安装的dnf list的输出进行重复查找,从而轻松发现它们。

$ sudo dnf install x86_64/zsh-5.7.1-4.fc31.daloni.x86_64.rpm

$ dnf list installed | grep @@commandline
zsh.x86_64              5.7.1-4.fc31.daloni                    @@commandline

$ dnf list installed | grep daloni
zsh.x86_64              5.7.1-4.fc31.daloni                    @@commandline

避免补丁在版本升级时被覆盖

当Fedora发布新版本的程序包时,自动系统升级可能会覆盖补丁。虽然有几种方法可以防止这个情况的发生,但我最喜欢的一种方法是从dnf的配置中排除对此类程序包的升级。

$ grep exclude /etc/dnf/dnf.conf
exclude=zsh

不过,处理程序包的话题已经超出了本文的范围。

保留debuginfo!

如果修补的程序包崩溃并生成了一个核心文件,那么构建中生成的特殊的debuginfo程序包在检查这个corefile时可能很方便。因此,你可能需要保留这些debuginfo程序包,特别是因为复制的构建有时很难与原始的二进制兼容性完全匹配。这取决于构建包的确定性如何,这是程序包自身构建系统固有的问题。

本文翻译自:https://blog.aloni.org/posts/how-to-easily-patch-fedora-packages/如若转载,请注明原文地址:
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务