diff options
Diffstat (limited to 'packaging/utils/patcher')
| -rwxr-xr-x | packaging/utils/patcher | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/packaging/utils/patcher b/packaging/utils/patcher new file mode 100755 index 000000000..ba31bdd26 --- /dev/null +++ b/packaging/utils/patcher @@ -0,0 +1,188 @@ +#! /bin/sh +# smart patch applier +# Copyright (C) 1999, 2001 Henry Spencer. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# patcher [-v] [-c] targetdir target [ key patchfile ] ... +# In targetdir, patch target from patchfile unless it already contains +# key and it appears to have been patched with the same patch. (If the +# patch has changed, undo the old one and then put the new one in.) Save +# original as target.preipsec, and patched copy as target.wipsec, with +# patch md5sum stored as target.ipsecmd5. If the patch doesn't work, +# put the original back and save the patch attempt as target.mangled. +# If there are no key+patchfile pairs, undo any old patch and leave it +# at that. +# -v means verbose +# -c means do "patching" by appending rather than by using patch(1) +# +# RCSID $Id: patcher,v 1.1 2004/03/15 20:35:27 as Exp $ + +PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin +export PATH +umask 022 + +verbose= +modifier=patch +for dummy +do + case "$1" in + -v) verbose=yes ;; + -c) modifier=cat ;; + --) shift ; break ;; + -*) echo "$0: unknown option \`$1'" >&2 ; exit 2 ;; + *) break ;; + esac + shift +done +if test $# -lt 2 +then + echo "Usage: $0 [-v] [-c] targetdir target [ key patchfile ] ..." >&2 + exit 2 +fi + +need() { + if test ! -f $1 + then + echo "$0: cannot find file \`$1'" >&2 + exit 1 + fi +} + +note() { + if test "$verbose" + then + echo "* $1" + fi +} + +dir="$1" +target="$2" +shift ; shift +it=$dir/$target +need $it + + + +patches= +if test ! -s $it.ipsecmd5 +then + # no records of patching... + while test $# -ge 2 + do + key="$1" + patchfile="$2" + shift ; shift + need $patchfile + + if egrep -q "$key" $it + then + # patched but no record of how + note "$it no longer needs patch $patchfile" + else + patches="$patches $patchfile" + fi + done +elif test ! -f $it.preipsec -o ! -f $it.wipsec +then + echo "$0: $it.preipsec or .wipsec is missing!" >&2 + exit 1 +else + # determine whether patches have changed + tmp=/tmp/patcher.$$ + >$tmp + while test $# -ge 2 + do + key="$1" + patchfile="$2" + shift ; shift + need $patchfile + md5sum $patchfile | awk '{print $1}' >>$tmp + + if egrep -q "$key" $it.preipsec + then + note "$it no longer needs patch $patchfile" + else + patches="$patches $patchfile" + fi + done + if cmp -s $tmp $it.ipsecmd5 + then + note "$it already fully patched" + rm -f $tmp + exit 0 + fi + rm -f $tmp + + # must undo old patch(es) + note "$it old patches must be undone, undoing them..." + if ! cmp -s $it $it.wipsec + then + note "$it has changed, cannot undo old patches!" + echo "$0: cannot unpatch $it, it has changed since patching" >&2 + exit 1 + fi + rm $it + mv $it.preipsec $it + rm $it.wipsec $it.ipsecmd5 +fi + +# if no necessary patches, we're done +if test " $patches" = " " +then + note "$it no longer needs patching" + exit 0 +fi + +# try to figure out patch options +if test " $modifier" = " patch" +then + if patch --help >/dev/null 2>/dev/null + then + # looks like a modern version + popts='-p1 -b' + else + # looks like an old one + popts='-p1' + fi +fi + +# do it +>$it.ipsecmd5 +for patchfile in $patches +do + note "applying $patchfile to $it..." + + # make local copy - this defeats hard and soft links + mv $it $it.preipsec || exit 0 + rm -f $it + cp -p $it.preipsec $it + + case "$modifier" in + patch) ( cd $dir ; patch $popts ) <$patchfile ;; + cat) cat $patchfile >>$it ;; + esac + status=$? + if test $status -ne 0 + then + note "$it patch failed, restoring original" + echo "$0: patch on $it failed!" >&2 + echo "$0: restoring original $it," >&2 + echo "$0: leaving patch attempt in $it.mangled" >&2 + mv $it $it.mangled + mv $it.preipsec $it + rm -f $it.ipsecmd5 + exit 1 + fi + rm -f $it.orig # some patch versions leave debris + md5sum $patchfile | awk '{print $1}' >>$it.ipsecmd5 +done +cp -p $it $it.wipsec |
