全部博文(534)
分类: LINUX
2007-09-28 17:23:39
九、patch-kernel 脚本分析
在 tarball 中有一个 scripts/ 目录,里面有一个 patch-kernel 脚本,用于自动升级内核。
当你要打的 patch 较多时,使用该脚本是一个不错的选择。
下面会对其内容逐行分析
CODE:
#! /bin/sh
# Script to apply kernel patches.
# usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
# The source directory defaults to /usr/src/linux, and the patch
# directory defaults to the current directory.
# e.g.
# scripts/patch-kernel . ..
# Update the kernel tree in the current directory using patches in the
# directory above to the latest Linus kernel
# scripts/patch-kernel . .. -ac
# Get the latest Linux kernel and patch it with the latest ac patch
# scripts/patch-kernel . ..
# Gets standard kernel 2.4.9
# scripts/patch-kernel . .. 2.4.9 -ac
# Gets 2.4.9 with latest ac patches
# scripts/patch-kernel . .. 2.4.9 -ac11
# Gets 2.4.9 with ac patch ac11
# Note: It uses the patches relative to the Linus kernels, not the
# ac to ac relative patches
#
# It determines the current kernel version from the top-level Makefile.
# It then looks for patches for the next sublevel in the patch directory.
# This is applied using "patch -p1 -s" from within the kernel directory.
# A check is then made for "*.rej" files to see if the patch was
# successful. If it is, then all of the "*.orig" files are removed.
#
# Nick Holloway <[email]Nick.Holloway@alfie.demon.co.uk[/email]>, 2nd January 1995.
#
# Added support for handling multiple types of compression. What includes
# gzip, bzip, bzip2, zip, compress, and plaintext.
#
# Adam Sulmicki <[email]adam@cfar.umd.edu[/email]>, 1st January 1997.
#
# Added ability to stop at a given version number
# Put the full version number (i.e. 2.3.31) as the last parameter
# Dave Gilbert <[email]linux@treblig.org[/email]>, 11th December 1999.
# Fixed previous patch so that if we are already at the correct version
# not to patch up.
#
# Added -ac option, use -ac or -ac9 (say) to stop at a particular version
# Dave Gilbert <[email]linux@treblig.org[/email]>, 29th September 2001.
使用 patch-kernel 的前提是 Makefile 的 EXTRAVERSION 值必须为空
patch-kernel 脚本的功能就是自动给指定内核打上补丁,它有两种工作模式 :
1、一种是用于处理多个”增量型“的补丁,这通过
但前提是你要准备从当前版本到
2、一种是用于处理”差分型“的补丁,它是通过 -ac 指定。同样也有两种模式 :
a)如果 -ac 后面没有任何参数,则自动升级到
b)如果 -ac 后面带指定版本,则直接升级到该指定版本
patch-kernel 脚本的语法格式为 :patch-kernel
1、patch-kernel . .. :表示在上级目录查找所有”增量型“ patch ,并自动升级到最高版本
2、patch-kernel . .. -ac :表示在上级目录查找所有 ”差分型“ patch ,并自动升级到最高版本
3、patch-kernel . ..
4、patch-kernel . .. 2.4.9 -ac :表示使用上级目录的最新版本的”差分补丁“文件升级当前目录下的内核源代码到 2.4.9
5、patch-kernel . .. 2.4.9 -ac9 :表示使用上级目录的 patch-2.4.9-ac*.* 文件升级当前内核到 2.4.9
CODE:
# Set directories from arguments, or use defaults.
sourcedir=${1-/usr/src/linux} # 注释 :sourcedir 默认返回 /usr/src/linux
patchdir=${2-.} # 注释 :patchdir 默认返回当前目录(.)
stopvers=${3-imnotaversion} # 注释 :stopvers 默认返回 immotaversion
if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then # 注释 :这部分是对用户输入的命令进行语法的检查
cat << USAGE
usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
The source directory defaults to /usr/src/linux, and
the patch directory defaults to the current directory.
USAGE
exit 1
fi
CODE:
# See if we have any -ac options # 注释 :检查用户是否指定了 -ac 选项
for PARM in $* # 注释 :检查所有位置参数,
do
case $PARM in # 如果 PARM 的值是匹配 '-ac*' ,则把 PARM 的值赋予变量 gotac
-ac*)
gotac=$PARM; # 如果没有发现任何 -ac* 字符串,则 gotac 的值为空
esac;
done
# 注释 :gotac 变量的值控制了 patch 的方式是”增量“还是”差分型“
CODE:
下面的 findfile 函数用于在
并能够根据常用的扩展名自动设置其解压方式,可以识别的扩展名有 :
1、.gz :使用 gunzip -dc 解压
2、.bz :使用 bunzip -dc 解压
3、.bz2 :使用 bunzip2 -dc 解压
4、.zip :使用 unzip -d 解压
5、.Z :使用 uncompress -c 解压
6、无扩展名。使用 cat 直接输出
7、如果都不是,则返回 1
# ---------------------------------------------------------------------------
# Find a file, first parameter is basename of file
# it tries many compression mechanisms and sets variables to say how to get it
findFile () {
filebase=$1;
if [ -r ${filebase}.gz ]; then
ext=".gz"
name="gzip"
uncomp="gunzip -dc"
elif [ -r ${filebase}.bz ]; then
ext=".bz"
name="bzip"
uncomp="bunzip -dc"
elif [ -r ${filebase}.bz2 ]; then
ext=".bz2"
name="bzip2"
uncomp="bunzip2 -dc"
elif [ -r ${filebase}.zip ]; then
ext=".zip"
name="zip"
uncomp="unzip -d"
elif [ -r ${filebase}.Z ]; then
ext=".Z"
name="uncompress"
uncomp="uncompress -c"
elif [ -r ${filebase} ]; then
ext=""
name="plaintext"
uncomp="cat"
else
return 1;
fi
return 0;
}
CODE:
# ---------------------------------------------------------------------------
# Apply a patch and check it goes in cleanly
# First param is patch name (e.g. patch-
下面的 applyPatch()函数的作用是 :
1、首先打印一个提示信息
2、接下来是解压和打补丁
3、如果 patch 成功(返回0),则输出 “done"
4、否则输出 ”failed,Cleanup up yourself“ ,并返回 1
5、再检查 $sourcedir 下是否存在以 .rej 结尾的文件(含隐藏文件),如果有则打印一个信息 “Aborting.Reject files found"
表示有某些 hunk 没有成功 apply ,并返回 1
6、如果没有找到 .rej 文件,则表示整个 patch 成功地 apply 了。再查找是否有 .orig 文件。这些文件是 patch 在工作时
自动备份的源文件(见 patch 的 --backup-if-mismatch)并删除它们 ,最后返回 0 的 exit status
applyPatch () {
echo -n "Applying $1 (${name})... "
if $uncomp ${patchdir}/$1${ext} | patch -p1 -s -N -E -d $sourcedir
then
echo "done."
else
echo "failed. Clean up yourself."
return 1;
fi
if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
then
echo "Aborting. Reject files found."
return 1;
fi
# Remove backup files
find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
return 0;
}