Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3519293
  • 博文数量: 534
  • 博客积分: 11595
  • 博客等级: 上将
  • 技术积分: 5785
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-22 17:00
文章分类

全部博文(534)

文章存档

2015年(4)

2014年(27)

2013年(15)

2012年(38)

2011年(36)

2010年(85)

2009年(63)

2008年(142)

2007年(124)

分类: 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 . .. 2.4.9
#      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 [stopversion] [-ac [stopversion]]

其中 是指你要升级的内核源代码所在的目录。例如

1
patch-kernel . .. :表示在上级目录查找所有增量型“ patch ,并自动升级到最高版本

2
patch-kernel . .. -ac :表示在上级目录查找所有差分型“ patch ,并自动升级到最高版本

3
patch-kernel . .. 2.4.9 :表示使用上级目录的 patch-2.4.9 级当前目录下的内核源代码

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 函数用于在 指定的目录下查找任何名为 patch-x.y.z 的文件。

并能够根据常用的扩展名自动设置其解压方式,可以识别的扩展名有

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-2.4.9-ac5) - without path or extension

下面的 applyPatch()函数的作用是

1
、首先打印一个提示信息

2
、接下来是解压和打补丁

3
、如果 patch 成功(返回0),则输出 “done"

4
、否则输出 ”failedCleanup 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;
}

阅读(2183) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~