1#! /bin/sh 2# Script to apply kernel patches. 3# usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] 4# The source directory defaults to /usr/src/linux, and the patch 5# directory defaults to the current directory. 6# e.g. 7# scripts/patch-kernel . .. 8# Update the kernel tree in the current directory using patches in the 9# directory above to the latest Linus kernel 10# scripts/patch-kernel . .. -ac 11# Get the latest Linux kernel and patch it with the latest ac patch 12# scripts/patch-kernel . .. 2.4.9 13# Gets standard kernel 2.4.9 14# scripts/patch-kernel . .. 2.4.9 -ac 15# Gets 2.4.9 with latest ac patches 16# scripts/patch-kernel . .. 2.4.9 -ac11 17# Gets 2.4.9 with ac patch ac11 18# Note: It uses the patches relative to the Linus kernels, not the 19# ac to ac relative patches 20# 21# It determines the current kernel version from the top-level Makefile. 22# It then looks for patches for the next sublevel in the patch directory. 23# This is applied using "patch -p1 -s" from within the kernel directory. 24# A check is then made for "*.rej" files to see if the patch was 25# successful. If it is, then all of the "*.orig" files are removed. 26# 27# Nick Holloway <Nick.Holloway@alfie.demon.co.uk>, 2nd January 1995. 28# 29# Added support for handling multiple types of compression. What includes 30# gzip, bzip, bzip2, zip, compress, and plaintext. 31# 32# Adam Sulmicki <adam@cfar.umd.edu>, 1st January 1997. 33# 34# Added ability to stop at a given version number 35# Put the full version number (i.e. 2.3.31) as the last parameter 36# Dave Gilbert <linux@treblig.org>, 11th December 1999. 37 38# Fixed previous patch so that if we are already at the correct version 39# not to patch up. 40# 41# Added -ac option, use -ac or -ac9 (say) to stop at a particular version 42# Dave Gilbert <linux@treblig.org>, 29th September 2001. 43# 44# Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.); 45# update usage message; 46# fix some whitespace damage; 47# be smarter about stopping when current version is larger than requested; 48# Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18. 49 50# Set directories from arguments, or use defaults. 51sourcedir=${1-/usr/src/linux} 52patchdir=${2-.} 53stopvers=${3-default} 54 55if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then 56cat << USAGE 57usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] 58 source directory defaults to /usr/src/linux, 59 patch directory defaults to the current directory, 60 stopversion defaults to <all in patchdir>. 61USAGE 62exit 1 63fi 64 65# See if we have any -ac options 66for PARM in $* 67do 68 case $PARM in 69 -ac*) 70 gotac=$PARM; 71 72 esac; 73done 74 75# --------------------------------------------------------------------------- 76# Find a file, first parameter is basename of file 77# it tries many compression mechanisms and sets variables to say how to get it 78findFile () { 79 filebase=$1; 80 81 if [ -r ${filebase}.gz ]; then 82 ext=".gz" 83 name="gzip" 84 uncomp="gunzip -dc" 85 elif [ -r ${filebase}.bz ]; then 86 ext=".bz" 87 name="bzip" 88 uncomp="bunzip -dc" 89 elif [ -r ${filebase}.bz2 ]; then 90 ext=".bz2" 91 name="bzip2" 92 uncomp="bunzip2 -dc" 93 elif [ -r ${filebase}.zip ]; then 94 ext=".zip" 95 name="zip" 96 uncomp="unzip -d" 97 elif [ -r ${filebase}.Z ]; then 98 ext=".Z" 99 name="uncompress" 100 uncomp="uncompress -c" 101 elif [ -r ${filebase} ]; then 102 ext="" 103 name="plaintext" 104 uncomp="cat" 105 else 106 return 1; 107 fi 108 109 return 0; 110} 111 112# --------------------------------------------------------------------------- 113# Apply a patch and check it goes in cleanly 114# First param is patch name (e.g. patch-2.4.9-ac5) - without path or extension 115 116applyPatch () { 117 echo -n "Applying $1 (${name})... " 118 if $uncomp ${patchdir}/$1${ext} | patch -p1 -s -N -E -d $sourcedir 119 then 120 echo "done." 121 else 122 echo "failed. Clean up yourself." 123 return 1; 124 fi 125 if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ] 126 then 127 echo "Aborting. Reject files found." 128 return 1; 129 fi 130 # Remove backup files 131 find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \; 132 133 return 0; 134} 135 136# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION 137TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; } 138grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE 139tr -d [:blank:] < $TMPFILE > $TMPFILE.1 140source $TMPFILE.1 141rm -f $TMPFILE* 142if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ] 143then 144 echo "unable to determine current kernel version" >&2 145 exit 1 146fi 147 148NAME=`grep ^NAME $sourcedir/Makefile` 149NAME=${NAME##*=} 150 151echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)" 152 153# strip EXTRAVERSION to just a number (drop leading '.' and trailing additions) 154EXTRAVER= 155if [ x$EXTRAVERSION != "x" ] 156then 157 if [ ${EXTRAVERSION:0:1} == "." ]; then 158 EXTRAVER=${EXTRAVERSION:1} 159 else 160 EXTRAVER=$EXTRAVERSION 161 fi 162 EXTRAVER=${EXTRAVER%%[[:punct:]]*} 163 #echo "patch-kernel: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER" 164fi 165 166#echo "stopvers=$stopvers" 167if [ $stopvers != "default" ]; then 168 STOPSUBLEVEL=`echo $stopvers | cut -d. -f3` 169 STOPEXTRA=`echo $stopvers | cut -d. -f4` 170 #echo "STOPSUBLEVEL=$STOPSUBLEVEL, STOPEXTRA=$STOPEXTRA" 171else 172 STOPSUBLEVEL=9999 173 STOPEXTRA=9999 174fi 175 176while : # incrementing SUBLEVEL (s in v.p.s) 177do 178 if [ x$EXTRAVER != "x" ]; then 179 CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER" 180 else 181 CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" 182 fi 183 184 if [ $stopvers == $CURRENTFULLVERSION ]; then 185 echo "Stopping at $CURRENTFULLVERSION base as requested." 186 break 187 fi 188 189 while : # incrementing EXTRAVER (x in v.p.s.x) 190 do 191 EXTRAVER=$((EXTRAVER + 1)) 192 FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER" 193 #echo "... trying $FULLVERSION ..." 194 195 patch=patch-$FULLVERSION 196 197 # See if the file exists and find extension 198 findFile $patchdir/${patch} || break 199 200 # Apply the patch and check all is OK 201 applyPatch $patch || break 202 203 continue 2 204 done 205 206 EXTRAVER= 207 SUBLEVEL=$((SUBLEVEL + 1)) 208 FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" 209 #echo "___ trying $FULLVERSION ___" 210 211 if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then 212 echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)" 213 exit 1 214 fi 215 216 patch=patch-$FULLVERSION 217 218 # See if the file exists and find extension 219 findFile $patchdir/${patch} || break 220 221 # Apply the patch and check all is OK 222 applyPatch $patch || break 223done 224#echo "base all done" 225 226if [ x$gotac != x ]; then 227 # Out great user wants the -ac patches 228 # They could have done -ac (get latest) or -acxx where xx=version they want 229 if [ $gotac == "-ac" ]; then 230 # They want the latest version 231 HIGHESTPATCH=0 232 for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.* 233 do 234 ACVALUE=`echo $PATCHNAMES | sed -e 's/^.*patch-[0-9.]*-ac\([0-9]*\).*/\1/'` 235 # Check it is actually a recognised patch type 236 findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break 237 238 if [ $ACVALUE -gt $HIGHESTPATCH ]; then 239 HIGHESTPATCH=$ACVALUE 240 fi 241 done 242 243 if [ $HIGHESTPATCH -ne 0 ]; then 244 findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break 245 applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} 246 else 247 echo "No -ac patches found" 248 fi 249 else 250 # They want an exact version 251 findFile $patchdir/patch-${CURRENTFULLVERSION}${gotac} || { 252 echo "Sorry, I couldn't find the $gotac patch for $CURRENTFULLVERSION. Hohum." 253 exit 1 254 } 255 applyPatch patch-${CURRENTFULLVERSION}${gotac} 256 fi 257fi 258