linux/scripts/patch-kernel
<<
>>
Prefs
   1#! /bin/sh
   2# SPDX-License-Identifier: GPL-2.0
   3# Script to apply kernel patches.
   4#   usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
   5#     The source directory defaults to /usr/src/linux, and the patch
   6#     directory defaults to the current directory.
   7# e.g.
   8#   scripts/patch-kernel . ..
   9#      Update the kernel tree in the current directory using patches in the
  10#      directory above to the latest Linus kernel
  11#   scripts/patch-kernel . .. -ac
  12#      Get the latest Linux kernel and patch it with the latest ac patch
  13#   scripts/patch-kernel . .. 2.4.9
  14#      Gets standard kernel 2.4.9
  15#   scripts/patch-kernel . .. 2.4.9 -ac
  16#      Gets 2.4.9 with latest ac patches
  17#   scripts/patch-kernel . .. 2.4.9 -ac11
  18#      Gets 2.4.9 with ac patch ac11
  19#   Note: It uses the patches relative to the Linus kernels, not the
  20#   ac to ac relative patches
  21#
  22# It determines the current kernel version from the top-level Makefile.
  23# It then looks for patches for the next sublevel in the patch directory.
  24# This is applied using "patch -p1 -s" from within the kernel directory.
  25# A check is then made for "*.rej" files to see if the patch was
  26# successful.  If it is, then all of the "*.orig" files are removed.
  27#
  28#       Nick Holloway <Nick.Holloway@alfie.demon.co.uk>, 2nd January 1995.
  29#
  30# Added support for handling multiple types of compression. What includes
  31# gzip, bzip, bzip2, zip, compress, and plaintext.
  32#
  33#       Adam Sulmicki <adam@cfar.umd.edu>, 1st January 1997.
  34#
  35# Added ability to stop at a given version number
  36# Put the full version number (i.e. 2.3.31) as the last parameter
  37#       Dave Gilbert <linux@treblig.org>, 11th December 1999.
  38
  39# Fixed previous patch so that if we are already at the correct version
  40# not to patch up.
  41#
  42# Added -ac option, use -ac or -ac9 (say) to stop at a particular version
  43#       Dave Gilbert <linux@treblig.org>, 29th September 2001.
  44#
  45# Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.);
  46# update usage message;
  47# fix some whitespace damage;
  48# be smarter about stopping when current version is larger than requested;
  49#       Randy Dunlap <rdunlap@xenotime.net>, 2004-AUG-18.
  50#
  51# Add better support for (non-incremental) 2.6.x.y patches;
  52# If an ending version number if not specified, the script automatically
  53# increments the SUBLEVEL (x in 2.6.x.y) until no more patch files are found;
  54# however, EXTRAVERSION (y in 2.6.x.y) is never automatically incremented
  55# but must be specified fully.
  56#
  57# patch-kernel does not normally support reverse patching, but does so when
  58# applying EXTRAVERSION (x.y) patches, so that moving from 2.6.11.y to 2.6.11.z
  59# is easy and handled by the script (reverse 2.6.11.y and apply 2.6.11.z).
  60#       Randy Dunlap <rdunlap@xenotime.net>, 2005-APR-08.
  61
  62PNAME=patch-kernel
  63
  64# Set directories from arguments, or use defaults.
  65sourcedir=${1-/usr/src/linux}
  66patchdir=${2-.}
  67stopvers=${3-default}
  68
  69if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then
  70cat << USAGE
  71usage: $PNAME [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
  72  source directory defaults to /usr/src/linux,
  73  patch directory defaults to the current directory,
  74  stopversion defaults to <all in patchdir>.
  75USAGE
  76exit 1
  77fi
  78
  79# See if we have any -ac options
  80for PARM in $*
  81do
  82  case $PARM in
  83          -ac*)
  84                  gotac=$PARM;
  85
  86        esac;
  87done
  88
  89# ---------------------------------------------------------------------------
  90# arg1 is filename
  91noFile () {
  92        echo "cannot find patch file: ${patch}"
  93        exit 1
  94}
  95
  96# ---------------------------------------------------------------------------
  97backwards () {
  98        echo "$PNAME does not support reverse patching"
  99        exit 1
 100}
 101
 102# ---------------------------------------------------------------------------
 103# Find a file, first parameter is basename of file
 104# it tries many compression mechanisms and sets variables to say how to get it
 105findFile () {
 106  filebase=$1;
 107
 108  if [ -r ${filebase}.gz ]; then
 109                ext=".gz"
 110                name="gzip"
 111                uncomp="gunzip -dc"
 112  elif [ -r ${filebase}.bz  ]; then
 113                ext=".bz"
 114                name="bzip"
 115                uncomp="bunzip -dc"
 116  elif [ -r ${filebase}.bz2 ]; then
 117                ext=".bz2"
 118                name="bzip2"
 119                uncomp="bunzip2 -dc"
 120  elif [ -r ${filebase}.xz ]; then
 121                ext=".xz"
 122                name="xz"
 123                uncomp="xz -dc"
 124  elif [ -r ${filebase}.zip ]; then
 125                ext=".zip"
 126                name="zip"
 127                uncomp="unzip -d"
 128  elif [ -r ${filebase}.Z ]; then
 129                ext=".Z"
 130                name="uncompress"
 131                uncomp="uncompress -c"
 132  elif [ -r ${filebase} ]; then
 133                ext=""
 134                name="plaintext"
 135                uncomp="cat"
 136  else
 137        return 1;
 138  fi
 139
 140  return 0;
 141}
 142
 143# ---------------------------------------------------------------------------
 144# Apply a patch and check it goes in cleanly
 145# First param is patch name (e.g. patch-2.4.9-ac5) - without path or extension
 146
 147applyPatch () {
 148  echo -n "Applying $1 (${name})... "
 149  if $uncomp ${patchdir}/$1${ext} | patch -p1 -s -N -E -d $sourcedir
 150  then
 151    echo "done."
 152  else
 153    echo "failed.  Clean up yourself."
 154    return 1;
 155  fi
 156  if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
 157  then
 158    echo "Aborting.  Reject files found."
 159    return 1;
 160  fi
 161  # Remove backup files
 162  find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
 163
 164  return 0;
 165}
 166
 167# ---------------------------------------------------------------------------
 168# arg1 is patch filename
 169reversePatch () {
 170        echo -n "Reversing $1 (${name}) ... "
 171        if $uncomp ${patchdir}/"$1"${ext} | patch -p1 -Rs -N -E -d $sourcedir
 172        then
 173                echo "done."
 174        else
 175                echo "failed.  Clean it up."
 176                exit 1
 177        fi
 178        if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
 179        then
 180                echo "Aborting.  Reject files found."
 181                return 1
 182        fi
 183        # Remove backup files
 184        find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
 185
 186        return 0
 187}
 188
 189# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
 190# force $TMPFILEs below to be in local directory: a slash character prevents
 191# the dot command from using the search path.
 192TMPFILE=`mktemp ./.tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; }
 193grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE
 194tr -d [:blank:] < $TMPFILE > $TMPFILE.1
 195. $TMPFILE.1
 196rm -f $TMPFILE*
 197if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
 198then
 199    echo "unable to determine current kernel version" >&2
 200    exit 1
 201fi
 202
 203NAME=`grep ^NAME $sourcedir/Makefile`
 204NAME=${NAME##*=}
 205
 206echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)"
 207
 208# strip EXTRAVERSION to just a number (drop leading '.' and trailing additions)
 209EXTRAVER=
 210if [ x$EXTRAVERSION != "x" ]
 211then
 212        EXTRAVER=${EXTRAVERSION#.}
 213        EXTRAVER=${EXTRAVER%%[[:punct:]]*}
 214        #echo "$PNAME: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER"
 215fi
 216
 217#echo "stopvers=$stopvers"
 218if [ $stopvers != "default" ]; then
 219        STOPSUBLEVEL=`echo $stopvers | cut -d. -f3`
 220        STOPEXTRA=`echo $stopvers | cut -d. -f4`
 221        STOPFULLVERSION=${stopvers%%.$STOPEXTRA}
 222        #echo "#___STOPSUBLEVEL=/$STOPSUBLEVEL/, STOPEXTRA=/$STOPEXTRA/"
 223else
 224        STOPSUBLEVEL=9999
 225        STOPEXTRA=9999
 226fi
 227
 228# This all assumes a 2.6.x[.y] kernel tree.
 229# Don't allow backwards/reverse patching.
 230if [ $STOPSUBLEVEL -lt $SUBLEVEL ]; then
 231        backwards
 232fi
 233
 234if [ x$EXTRAVER != "x" ]; then
 235        CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
 236else
 237        CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
 238fi
 239
 240if [ x$EXTRAVER != "x" ]; then
 241        echo "backing up to: $VERSION.$PATCHLEVEL.$SUBLEVEL"
 242        patch="patch-${CURRENTFULLVERSION}"
 243        findFile $patchdir/${patch} || noFile ${patch}
 244        reversePatch ${patch} || exit 1
 245fi
 246
 247# now current is 2.6.x, with no EXTRA applied,
 248# so update to target SUBLEVEL (2.6.SUBLEVEL)
 249# and then to target EXTRAVER (2.6.SUB.EXTRAVER) if requested.
 250# If not ending sublevel is specified, it is incremented until
 251# no further sublevels are found.
 252
 253if [ $STOPSUBLEVEL -gt $SUBLEVEL ]; then
 254while :                         # incrementing SUBLEVEL (s in v.p.s)
 255do
 256    CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
 257    EXTRAVER=
 258    if [ x$STOPFULLVERSION = x$CURRENTFULLVERSION ]; then
 259        echo "Stopping at $CURRENTFULLVERSION base as requested."
 260        break
 261    fi
 262
 263    SUBLEVEL=$(($SUBLEVEL + 1))
 264    FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
 265    #echo "#___ trying $FULLVERSION ___"
 266
 267    if [ $(($SUBLEVEL)) -gt $(($STOPSUBLEVEL)) ]; then
 268        echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)"
 269        exit 1
 270    fi
 271
 272    patch=patch-$FULLVERSION
 273    # See if the file exists and find extension
 274    findFile $patchdir/${patch} || noFile ${patch}
 275
 276    # Apply the patch and check all is OK
 277    applyPatch $patch || break
 278done
 279#echo "#___sublevel all done"
 280fi
 281
 282# There is no incremental searching for extraversion...
 283if [ "$STOPEXTRA" != "" ]; then
 284while :                         # just to allow break
 285do
 286# apply STOPEXTRA directly (not incrementally) (x in v.p.s.x)
 287        FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$STOPEXTRA"
 288        #echo "#... trying $FULLVERSION ..."
 289        patch=patch-$FULLVERSION
 290
 291        # See if the file exists and find extension
 292        findFile $patchdir/${patch} || noFile ${patch}
 293
 294        # Apply the patch and check all is OK
 295        applyPatch $patch || break
 296        #echo "#___extraver all done"
 297        break
 298done
 299fi
 300
 301if [ x$gotac != x ]; then
 302  # Out great user wants the -ac patches
 303        # They could have done -ac (get latest) or -acxx where xx=version they want
 304        if [ $gotac = "-ac" ]; then
 305          # They want the latest version
 306                HIGHESTPATCH=0
 307                for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
 308                do
 309                        ACVALUE=`echo $PATCHNAMES | sed -e 's/^.*patch-[0-9.]*-ac\([0-9]*\).*/\1/'`
 310                        # Check it is actually a recognised patch type
 311                        findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break
 312
 313                  if [ $ACVALUE -gt $HIGHESTPATCH ]; then
 314                          HIGHESTPATCH=$ACVALUE
 315                  fi
 316                done
 317
 318                if [ $HIGHESTPATCH -ne 0 ]; then
 319                        findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break
 320                        applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH}
 321                else
 322                  echo "No -ac patches found"
 323                fi
 324        else
 325          # They want an exact version
 326                findFile $patchdir/patch-${CURRENTFULLVERSION}${gotac} || {
 327                  echo "Sorry, I couldn't find the $gotac patch for $CURRENTFULLVERSION.  Hohum."
 328                        exit 1
 329                }
 330                applyPatch patch-${CURRENTFULLVERSION}${gotac}
 331        fi
 332fi
 333