#! /bin/sh # Script to ask user if they want patches applied or reversed. # Sun 12 Nov 2000 Harald Welte # - added support for other protocols than ipv4 # Tue 12 Feb 2002 Bob Hockney # - added support for reverting patches out # Fri 22 Feb 2002 Fabrice MARIE # - added support for userspace/ patches # Sat 25 Jan 2003 Jozsef Kadlecsik # - removed copying the source trees for testing # Fri 21 Feb 2003 Jozsef Kadlecsik # - added dependecy support # Sat 5 Apr 2003 Martin Josefsson # - added support for conflicting dependencies # - readded partial support for sourcetree copying # - fix support for userspace/ patches # Mon 7 Apr 2003 Martin Josefsson # - add support for batch testing # #set -x printheader() { clear 2> /dev/null echo "Welcome to Rusty's Patch-o-matic!" echo echo "Kernel: $KERNEL_DIR" echo "Userspace: $NETFILTERDIR" echo echo "Each patch is a new feature: many have minimal impact, some do not." echo "Almost every one has bugs, so I don't recommend applying them all!" echo "-------------------------------------------------------" if [ -n "$1" ]; then if [ $MODE ]; then echo -n "NOT applied: " else echo -n "Already applied: " fi rest=${1# } first=${rest%% *} rest=${1#*$first} echo $first for x in $rest do echo " $x" done echo fi } entertocont() { echo "" echo "[Press enter to continue]" read enter echo } # # WARNING: this function could fail, always check the output. # tmpdirname() { dd if=/dev/urandom bs=32 count=1 2>/dev/null | od -x -w32 -A n | tr -d ' ' } alloc_ktmpdir() { if [ "$KTMPDIR" == "$KERNEL_DIR" ]; then KTMPDIR=`tmpdirname` # I'm really paranoid. What if there's no /dev/urandom? if [ -z "$KTMPDIR" ]; then echo Failed to generate kernel tmpdirname: perhaps your /dev/urandom is broken >&2 free_utmpdir exit 1 fi KTMPDIR=$KERNEL_DIR/../$KTMPDIR if cp -al $KERNEL_DIR/. $KTMPDIR then : else echo Failed to make copy of $KERNEL_DIR >&2 free_ktmpdir free_utmpdir exit 1 fi fi } free_ktmpdir() { if [ "$KTMPDIR" != "$KERNEL_DIR" ]; then rm -rf $KTMPDIR KTMPDIR=$KERNEL_DIR fi } alloc_utmpdir() { if [ "$UTMPDIR" == "$NETFILTERDIR" ]; then UTMPDIR=`tmpdirname` # I'm really paranoid. What if there's no /dev/urandom? if [ -z "$UTMPDIR" ]; then echo Failed to generate userspace tmpdirname: perhaps your /dev/urandom is broken >&2 free_ktmpdir exit 1 fi UTMPDIR=$NETFILTERDIR/../$UTMPDIR if cp -al $NETFILTERDIR/. $UTMPDIR then : else echo Failed to make copy of $NETFILTERDIR >&2 free_utmpdir free_ktmpdir exit 1 fi fi } free_utmpdir() { if [ "$UTMPDIR" != "$NETFILTERDIR" ]; then rm -rf $UTMPDIR UTMPDIR=$NETFILTERDIR fi } # Too many rejects from trying to patch Configure.help/Config.help and Config.in. # So we use special format: First line specifies entry we want to # follow, and rest of file is pasted in under that. # Args: "patch" file, directory, file to patch, test mode apply_change() { PRIOR="`head -1 $1`" LINE=`fgrep -x -n "$PRIOR" $2/$3 | cut -d: -f1 | head -1` if [ -z "$LINE" ] then echo Could not find place to slot in $3 line >&2 return 1 fi rm -f $2/${3}.tmp if [ $MODE ]; then # Reverse "patch" # Need to search for previously inserted lines # Might not be immediately under $LINE BEGIN=2 TESTLINE=$BEGIN NUMLINES1=`sed -n \$= $1` NUMLINES2=`sed -n \$= $2/$3` while [ $TESTLINE -le $NUMLINES1 ]; do NOMATCH=`awk "NR==$LINE + $TESTLINE - 1" $2/$3|\ fgrep -vcx "\`sed -n -e ${TESTLINE}p $1\`"`; if [ $NOMATCH -ne 0 ]; then LINE=`expr $LINE + $TESTLINE - 1` TESTLINE=$BEGIN continue fi; TESTLINE=`expr $TESTLINE + 1`; done; if [ $LINE -lt $NUMLINES2 ] && \ (awk "NR==1,NR==$LINE" $2/$3 && awk "NR==$LINE + $NUMLINES1,NR=0" $2/$3) > $2/${3}.tmp then if [ "$4" = "test" ] then rm -f $2/${3}.tmp else mv $2/${3}.tmp $2/$3 fi echo " $3 updated" return 0 else echo Could not update $3 >&2 rm -f $2/${3}.tmp return 1 fi fi # Apply "patch" # Use awk to properly add newline if last line of code has only spaces # Necessary to properly remove inserted code if patch is reversed if (awk "NR==1,NR==$LINE" $2/$3 && awk "NR==2,NR==0" $1 && \ awk "NR==$LINE+1,NR==0" $2/$3) > $2/${3}.tmp then if [ "$4" = "test" ] then rm -f $2/${3}.tmp else mv $2/${3}.tmp $2/$3 fi else echo Could not slot in $3 line >&2 rm -f $2/${3}.tmp return 1 fi echo " Placed new $3 line" return 0 } # Args: configure.help file, Documentation file to which to add it. apply_config_help_change() { if [ "$2" = '/dev/null' ]; then #return 0 #Use this one if you don't care that the config*.help file is not getting updated return 1 #Fail fi BASEFILE=`basename $2` #Configure.help or Config.help PRIOR="`head -1 $1`" LINE=`fgrep -x -n "$PRIOR" $2 | cut -d: -f1 | head -1` if [ -z "$LINE" ] || [ "$LINE" -eq 0 ] then echo Could not find place to slot in $BASEFILE entry >&2 return 1 fi rm -f $2.tmp if [ $MODE ]; then # Reverse "patch" NUMLINES1=`sed -n \$= $1` NUMLINES2=`sed -n \$= $2` BEGIN=2 LINES=`fgrep -nx "\`sed -n 2p $1\`" $2 | cut -d: -f1` if [ -z "$LINES" ] then echo $BASEFILE text not found >&2 return 1 fi # First line of inserted text may appear more than once # Check each occurance MATCHES= for x in $LINES; do TESTLINE=$BEGIN # Be paranoid and check for match on all lines while `let "$TESTLINE <= $NUMLINES1"`; do NOMATCH=`awk "NR==$x + $TESTLINE - $BEGIN" $2|\ fgrep -xcv "\`sed -n -e ${TESTLINE}p $1\`"`; if [ $NOMATCH -ne 0 ]; then continue 2; fi TESTLINE=`expr $TESTLINE + 1`; done; # while MATCHES="$x $MATCHES" done; # for if [ ! "$MATCHES" ]; then echo $BASEFILE text not found >&2 return 1 fi; for x in $MATCHES; do # if (head -`expr $x - 1` $2 && \ # tail -n +`expr $x + $NUMLINES1` $2) > $2.tmp if (awk "NR==1,NR==$x - 1" $2 && \ awk "NR==$x + $NUMLINES1,NR=0" $2) > $2.tmp then if [ "$3" = "test" ] then rm -f $2.tmp else mv $2.tmp $2 fi else echo Could not update $BASEFILE >&2 rm -f $2.tmp return 1 fi done echo " $BASEFILE updated" return 0 fi #Apply "Patch" # Use awk to force newline if last line of $1 has only spaces # Necessary to properly remove inserted text if patch is reversed if (awk "NR==1,NR==$LINE-2" $2 && awk "NR==2,NR==0" $1 && echo && \ awk "NR==$LINE-1,NR==0" $2) > $2.tmp then if [ "$3" = "test" ] then rm -f $2.tmp else mv $2.tmp $2 fi else echo Could not slot in $BASEFILE entry >&2 rm -f $2.tmp return 1 fi echo " Placed new $BASEFILE entry" return 0 } # Don't like to use GLOBIGNORE stuff; can't use shopt (bash v1). expand_no_backups() { for expansion in $1 do case "$expansion" in "$1") ;; *~) ;; *) echo "$expansion";; esac done } apply_config_in_changes() { ret=0 for x in `expand_no_backups "$1.config.in*"` do apply_change $x $2 Config.in $3 || ret=1 done return $ret } apply_config_help_changes() { ret=0 for x in `expand_no_backups "$1.configure.help*"` do apply_config_help_change $x $2 $3 || ret=1 done return $ret } apply_makefile_changes() { ret=0 for x in `expand_no_backups "$1.makefile*"` do apply_change $x $2 Makefile $3 || ret=1 done return $ret } apply_conntrack_h_changes() { ret=0 case $2 in *ipv4) conntrack_h=ip_conntrack.h ;; *ipv6) conntrack_h=ip6_conntrack.h ;; *) return $ret ;; esac for x in `expand_no_backups "$1.${conntrack_h}*"` do apply_change $x $2 $conntrack_h $3 || ret=1 done return $ret } # Args: patch filename, protocol. test_patch_depend() { # Check the dependecy of the patch if [ -f "$1.depend" -a -z "$MODE" ]; then while read dep do if [ -z "${dep###*}" ]; then continue fi not=0 if [ -z "${dep##not *}" ]; then dep=${dep##not } not=1 fi if [ ! -f $dep ]; then echo >&2 echo "patch $dep which $1 depends on doesn't exist." >&2 echo "Report the problem to the patch-o-matic maintainer." >&2 echo >&2 return 1 fi f=${dep%%.patch*} # filename without .patch* p=${dep##$f.patch} # protocol, if exist p=${p##.} n=$f${p:+-$p} if [ "`echo $PROCESSED | grep $n`" ]; then if [ $not == 1 ]; then echo >&2 echo "Conflicting dependency." >&2 echo " $1" >&2 echo "is incompatible with" >&2 echo " $dep" >&2 echo >&2 return 1 else continue fi elif [ "`echo "$DEPEND" | grep " $dep "`" ]; then echo >&2 echo "Circular dependency, patch $1 cannot be applied." >&2 echo "Report the problem to the patch-o-matic maintainer." >&2 echo >&2 return 1 fi if [ $not == 1 ]; then echo Patch $1 conflicts with $dep... else echo Patch $1 depends on $dep... fi DEPEND="$DEPEND $dep " if ./isapplied $KTMPDIR $dep then if [ $not == 1 ]; then echo >&2 echo "Conflicting dependency." >&2 echo " $1" >&2 echo "is incompatible with" >&2 echo " $dep" >&2 echo >&2 return 1 fi elif [ $not == 1 ] || apply_patch_depend $dep ${p:-"ipv4"} test then : else return 1 fi done < $1.depend fi echo Testing patch $1... if [ -f "$KTMPDIR/net/$2/netfilter/Config.help" ]; then DOCUMENTATIONFILE="net/$2/netfilter/Config.help" elif [ -f "$KTMPDIR/Documentation/Configure.help" ]; then DOCUMENTATIONFILE="Documentation/Configure.help" else echo Warning - no help text file could be found in either >&2 echo $KTMPDIR/net/$2/netfilter/Config.help >&2 echo or $KTMPDIR/Documentation/Configure.help >&2 DOCUMENTATIONFILE=/dev/null fi if apply_config_in_changes $1 $KTMPDIR/net/$2/netfilter test && apply_config_help_changes $1 $KTMPDIR/$DOCUMENTATIONFILE test && apply_makefile_changes $1 $KTMPDIR/net/$2/netfilter test && apply_conntrack_h_changes $1 $KTMPDIR/include/linux/netfilter_$2 test then : else return 1 fi if (cd $KTMPDIR && if [ $MODE ]; then patch -R -p1 --dry-run else patch -p1 --dry-run fi > /dev/null) < $1 then : else echo "Failed to patch copy of $KERNEL_DIR" >&2 return 1 fi if [ ! -e $1.userspace ]; then echo " Patch $1 `modesense 2` cleanly." return 0 fi APPLIED= if STATUS=`./isapplied $UTMPDIR $1.userspace`; then APPLIED=Y ; fi if (cd $UTMPDIR && if [ $MODE ]; then if [ $APPLIED ]; then patch -R -p1 --dry-run else true fi else if [ -z $APPLIED ]; then patch -p1 --dry-run else true fi fi > /dev/null) < $1.userspace then : else echo Failed to patch copy of $NETFILTERDIR >&2 return 1 fi echo " Patch $1 `modesense 2` cleanly." return 0 } # I'm paranoid. Test patch first. # Args: patch filename, protocol. test_patch() { DEPEND=" $1 " test_patch_depend $1 $2 ret=$? free_ktmpdir free_utmpdir return $ret } # Args: patch filename, protocol. apply_patch_depend() { # Are we testing? if [ "$3" == "test" ]; then alloc_ktmpdir fi # Check the dependecy of the patch if [ "$3" != "force" -a -f "$1.depend" -a -z "$MODE" ]; then while read dep do if [ -z "${dep###*}" ]; then continue fi not=0 if [ -z "${dep##not *}" ]; then dep=${dep##not } not=1 fi if [ ! -f $dep ]; then echo >&2 echo "patch $dep which $1 depends on doesn't exist." >&2 echo "Report the problem to the patch-o-matic maintainer." >&2 echo >&2 return 1 fi f=${dep%%.patch*} # filename without .patch* p=${dep##$f.patch} # protocol, if exist p=${p##.} n=$f${p:+-$p} if [ "`echo $PROCESSED | grep $n`" ]; then if [ $not == 1 ]; then echo >&2 echo "Conflicting dependency." >&2 echo " $1" >&2 echo "is incompatible with" >&2 echo " $dep" >&2 echo >&2 return 1 else continue fi elif [ "`echo "$DEPEND" | grep " $dep "`" ]; then echo >&2 echo "Circular dependency, patch $1 cannot be applied." >&2 echo "Report the problem to the patch-o-matic maintainer." >&2 echo >&2 return 1 fi if [ $not == 1 ]; then echo Patch $1 conflicts with $dep... else echo Patch $1 depends on $dep... fi DEPEND="$DEPEND $dep " if ./isapplied $KTMPDIR $dep then if [ $not == 1 ]; then echo >&2 echo "Conflicting dependency." >&2 echo " $1" >&2 echo "is incompatible with" >&2 echo " $dep" >&2 echo >&2 return 1 fi elif [ $not == 1 ] || apply_patch_depend $dep ${p:-"ipv4"} $3 then : else return 1 fi done < $1.depend fi echo `modesense 3` patch $1... if (cd $KTMPDIR && if [ $MODE ]; then patch -R -p1 else patch -p1 fi > /dev/null) < $1 then : else echo "Failed to patch copy of $KERNEL_DIR" >&2 return 1 fi if [ -f "$KTMPDIR/net/$2/netfilter/Config.help" ]; then DOCUMENTATIONFILE="net/$2/netfilter/Config.help" elif [ -f "$KTMPDIR/Documentation/Configure.help" ]; then DOCUMENTATIONFILE="Documentation/Configure.help" else echo Warning - no help text file could be found in either >&2 echo $KTMPDIR/net/$2/netfilter/Config.help >&2 echo or $KTMPDIR/Documentation/Configure.help >&2 DOCUMENTATIONFILE=/dev/null fi apply_config_in_changes $1 $KTMPDIR/net/$2/netfilter/ apply_config_help_changes $1 $KTMPDIR/$DOCUMENTATIONFILE apply_makefile_changes $1 $KTMPDIR/net/$2/netfilter/ apply_conntrack_h_changes $1 $KTMPDIR/include/linux/netfilter_$2 if [ ! -e $1.userspace ]; then echo " Patch $1 `modesense 2` cleanly." return 0 fi # Are we testing? if [ "$3" == "test" ]; then alloc_utmpdir fi APPLIED= if STATUS=`./isapplied $UTMPDIR $1.userspace`; then APPLIED=Y ; fi if (cd $UTMPDIR && if [ $MODE ]; then if [ $APPLIED ]; then patch -R -p1 else true fi else if [ -z $APPLIED ]; then patch -p1 else true fi fi > /dev/null) < $1.userspace then : else echo Failed to patch copy of $NETFILTERDIR >&2 return 1 fi echo " Patch $1 `modesense 2` cleanly." if [ "$UTMPDIR" == "$NETFILTERDIR" ]; then echo " *******************" echo " ***** WARNING ***** You have applied a userspace patch, so do not forget to recompile" echo " ******************* and re-install iptables." echo " *******************" fi return 0 } # Args: patch filename, protocol. apply_patch() { DEPEND=" $1 " apply_patch_depend $1 $2 $3 } # Reverse order of arguments. reverse_args() { NUMARGS=$# while [ $NUMARGS -gt 0 ]; do eval "echo -n \${$NUMARGS}' '" NUMARGS=`expr $NUMARGS - 1` done } modesense() { case $1 in 1) if [ $MODE ]; then echo REVERSE; else echo apply; fi; ;; 2) if [ $MODE ]; then echo REVERSED; else echo applied; fi; ;; 3) if [ $MODE ]; then echo REVERSING; else echo Applying; fi; ;; esac } parse_filename() { SUITE=${1%%/*} FILE=${1##$SUITE/} BASE=${FILE%%.patch*} # filename without .patch* PROTO=${FILE##$BASE.patch} PROTO=${PROTO##.} } # Args: list of patches to process process_patches() { CURRENT=0 while [ $CURRENT -le $# ]; do CURRENT=`expr $CURRENT + 1` if [ $CURRENT -gt $# ]; then if [ $BATCH ] || [ $CHECKMODE ] || [ $TESTMODE ]; then if [ $CHECKMODE ] then printheader "$PROCESSED" printheader "$PROCESSED" > runme.out-check fi return fi printheader "$PROCESSED" ANSWER="" while [ ! $ANSWER ] do echo "-----------------------------------------------------------------" echo -n "No more patches to `modesense 1`! Q to Quit or ? for options "'[Q/a/r/b/?] ' read ANSWER case "$ANSWER" in a*|A*) WALK= NEWMODE= if ! [ "$NEWMODE" = "$MODE" ]; then PATCHES=`reverse_args $PATCHES`; fi; MODE=$NEWMODE continue 3 ;; r*|R*) WALK= NEWMODE=UN if ! [ "$NEWMODE" = "$MODE" ]; then PATCHES=`reverse_args $PATCHES`; fi; MODE=$NEWMODE continue 3 ;; b*|B*) WALK=1 BACK=1 SEEN=${SEEN%%$SUITE/$BASE${PROTO:+-$PROTO} } PROCESSED=${PROCESSED%% $SUITE/$BASE${PROTO:+-$PROTO}} if [ $CURRENT -gt 1 ]; then CURRENT=`expr $CURRENT - 2` else CURRENT=0 fi continue 2 ;; Q*|q*|'') ANSWER=Q continue 2 ;; *) ANSWER="" echo "Answer one of the following: " echo " A to restart patch-o-matic in apply mode" echo " R to restart patch-o-matic in REVERSE mode" echo " B to walk Back one patch in the list" echo " Q to quit immediately" echo " ? for help" ;; esac done fi THIS_PATCH=`eval echo -n \\\${$CURRENT}` > /dev/null parse_filename $THIS_PATCH # > /dev/null printheader "$PROCESSED" # Don't skip SEEN patches in REVERSE mode if [ ! $MODE ] && [ ! $BACK ] && echo $SEEN | tr ' ' '\012' | grep -q "$BASE${PROTO:+-$PROTO}\$" then # Patches seen at previous suites are skipped continue else if [ $MODE ] || ! echo $SEEN | tr ' ' '\012' | grep -q "$BASE${PROTO:+-$PROTO}\$"; then SEEN="$SEEN$SUITE/$BASE${PROTO:+-$PROTO} " elif [ $BACK ]; then if [ $CURRENT -gt 1 ]; then parse_filename `eval echo -n \\\${\`expr $CURRENT - 1\`}` > /dev/null SEEN=${SEEN%%$SUITE/$BASE${PROTO:+-$PROTO} } PROCESSED=${PROCESSED%% $SUITE/$BASE${PROTO:+-$PROTO}} CURRENT=`expr $CURRENT - 2` else CURRENT=0 fi continue fi echo -n "Testing... " APPLIED= if STATUS=`./isapplied $KERNEL_DIR $THIS_PATCH`; then APPLIED=Y ; fi if [ ! $WALK ] && ([ "$APPLIED" -a -z "$MODE" ] || [ ! "$APPLIED" -a -n "$MODE" ]); then PROCESSED="$PROCESSED $SUITE/$BASE${PROTO:+-$PROTO}" continue elif [ $CHECKMODE ] then continue else WALK= BACK= echo $STATUS echo The $SUITE/$BASE ${PROTO:+$PROTO } patch: if [ -f $THIS_PATCH.help ]; then while read LINE; do echo " $LINE"; done < $THIS_PATCH.help; fi ANSWER="" if [ $BATCH ] || [ $TESTMODE ] then if test_patch $THIS_PATCH ${PROTO:-"ipv4"} then if [ -z "$TESTMODE" ]; then apply_patch $THIS_PATCH ${PROTO:-"ipv4"} PROCESSED="$PROCESSED $SUITE/$BASE${PROTO:+-$PROTO}" fi ANSWER=Y else echo TEST FAILED: patch NOT `modesense 2`. exit 1 fi fi while [ "$ANSWER" = "" ] do echo "-----------------------------------------------------------------" echo -n "Do you want to `modesense 1` this patch "'[N/y/t/f/a/r/b/w/q/?] ' read ANSWER case "$ANSWER" in y*|Y*) if test_patch $THIS_PATCH ${PROTO:-"ipv4"} then apply_patch $THIS_PATCH ${PROTO:-"ipv4"} PROCESSED="$PROCESSED $SUITE/$BASE${PROTO:+-$PROTO}" else echo TEST FAILED: patch NOT `modesense 2`. ANSWER="" fi entertocont # pause before screen is cleared by printheader ;; t*|T*) ANSWER="" test_patch $THIS_PATCH ${PROTO:-"ipv4"} ;; f*|F*) apply_patch $THIS_PATCH ${PROTO:-"ipv4"} force PROCESSED="$PROCESSED $SUITE/$BASE${PROTO:+-$PROTO}" entertocont # pause before screen is cleared by printheader ;; a*|A*) NEWMODE= if ! [ "$NEWMODE" = "$MODE" ]; then PATCHES=`reverse_args $PATCHES`; fi; MODE=$NEWMODE continue 3 ;; r*|R*) NEWMODE=UN if ! [ "$NEWMODE" = "$MODE" ]; then PATCHES=`reverse_args $PATCHES`; fi; MODE=$NEWMODE continue 3 ;; b*|B*) WALK=1 BACK=1 SEEN=${SEEN%%$SUITE/$BASE${PROTO:+-$PROTO} } PROCESSED=${PROCESSED%% $SUITE/$BASE${PROTO:+-$PROTO}} if [ $CURRENT -gt 1 ]; then parse_filename `eval echo -n \\\${\`expr $CURRENT - 1\`}` > /dev/null SEEN=${SEEN%%$SUITE/$BASE${PROTO:+-$PROTO} } PROCESSED=${PROCESSED%% $SUITE/$BASE${PROTO:+-$PROTO}} CURRENT=`expr $CURRENT - 2` else CURRENT=0 fi continue 2 ;; w*|W*) WALK=1 if [ "$APPLIED" -a -z "$MODE" ] || [ ! "$APPLIED" -a -n "$MODE" ]; then PROCESSED="$PROCESSED $SUITE/$BASE${PROTO:+-$PROTO}" fi continue 2 ;; N*|n*|'') ANSWER=N if [ "$APPLIED" -a -z "$MODE" ] || [ ! "$APPLIED" -a -n "$MODE" ]; then PROCESSED="$PROCESSED $SUITE/$BASE${PROTO:+-$PROTO}" fi ;; q*|Q*) echo Bye! exit 0 ;; *) ANSWER="" echo "Answer one of the following: " echo " T to test that patch will `modesense 1` cleanly" echo " Y to `modesense 1` patch" echo " N to skip this patch" echo " F to `modesense 1` patch even if test fails" echo " A to restart patch-o-matic in apply mode" echo " R to restart patch-o-matic in REVERSE mode" echo " B to walk Back one patch in the list" echo " W to Walk forward one patch in the list" echo " Q to quit immediately" echo " ? for help" ;; esac done # while [ "$ANSWER" = "" ] fi fi done # [ $CURRENT -le $# ] } # Make sure we are in the correct directory if [ ! -f ./isapplied ] then echo echo Please call $0 from the patch-o-matic directory! exit 1 fi if [ -z "$NETFILTERDIR" ] then if [ -d ../userspace ] then export NETFILTERDIR=`cd ../userspace; pwd` else export NETFILTERDIR=`cd ..; pwd` fi fi UTMPDIR=$NETFILTERDIR # Make sure we have 'patch'... if patch -v >/dev/null 2>&1 then : else echo program \'patch\' is missing, please install it! exit 1 fi # Check to see if we are running in batch mode BATCH= if [ "$1" = "--batch" ]; then BATCH=1 shift fi TESTMODE= if [ "$1" = "--test" ]; then TESTMODE=1 shift fi CHECKMODE= if [ "$1" = "--check" ]; then CHECKMODE=1 shift fi # Check to see if we are applying or reversing patches MODE= if [ "$1" = "--reverse" ]; then shift MODE=UN fi # Check to see if there is excluded patches EXCLUDED= while [ "$1" = "--exclude" ]; do EXCLUDED="$EXCLUDED $2" shift shift done # Script arg: suite name or a single patch file PATCHES="" for arg; do if [ -d "$arg" -a -e $arg/SUITE ] then for x in `cat $arg/SUITE` do PATCHES="$PATCHES `ls $x/*.patch $x/*.patch.ipv6 2>/dev/null`" done elif [ -e "$arg" -a -n "${arg%%.patch*}" ] then PATCHES="$PATCHES $arg" else echo "ERROR: Invalid option $arg" exit 1 fi done if [ -z "$PATCHES" ]; then echo echo "Usage: $0 [--batch] [--reverse] [--exclude suite/patch-file ...] suite|suite/patch-file" echo echo " --batch batch mode, automatically applying patches" echo " --test test mode, automatically test patches" echo " --check check mode, automatically checks if patches are already applied" echo " produces a logfile: runme.out-check" echo " --reverse back out the selected patches" echo " --exclude excludes the named patches" echo echo Possible patch-o-matic suites: echo for x in */SUITE; do suite=${x%%/*} echo ${suite}: fold -s -w 56 $suite/DESCRIPTION | sed 's/^/ /' done exit 1 fi if [ $MODE ]; then PATCHES=`reverse_args $PATCHES` fi if [ -z "$KERNEL_DIR" ] then echo Hey\! KERNEL_DIR is not set. echo -n "Where is your kernel? [/usr/src/linux] " read KERNEL_DIR if (cd $KERNEL_DIR ) then : else echo "Failed to change directory to the kernel source dir $KERNEL_DIR" >&2 exit 1 fi fi echo "Examining kernel in $KERNEL_DIR" echo "-----------------------------------------------------------------" if [ ! -f ${KERNEL_DIR:=/usr/src/linux}/Makefile ] then echo $KERNEL_DIR doesn\'t look like a kernel tree to me. >&2 exit 1 fi VERSION=`grep '^VERSION' $KERNEL_DIR/Makefile | cut -d= -f2` PATCHLEVEL=`grep '^PATCHLEVEL' $KERNEL_DIR/Makefile | cut -d= -f2` if [ "$VERSION" -lt 2 -o "$PATCHLEVEL" -lt 4 ] then echo $KERNEL_DIR looks like a $VERSION.$PATCHLEVEL kernel tree to me. >&2 echo I expect a 2.4 kernel or above. >&2 exit 1 fi KTMPDIR=$KERNEL_DIR DONE= until [ $DONE ]; do PROCESSED= SEEN="${EXCLUDED//.patch/} " process_patches $PATCHES DONE=1 done echo echo Excellent\! Kernel is now ready for compilation. exit 0