#!/bin/sh # # patcher.sh -delivery system for patches on NT/HPUX/SOLARIS # # version: 1.0 # created: 19981028-cfriesen # updated: 19990811-cfriesen # # # TODO list: # - shutdown nmserver and machd # - check if OPENSTEP apps are running # # debug="${DEBUG_PATCHER- > /dev/null}" #eval echo "executing: $0" backup_suffix=OS COMPRESS=Z # gnutar compress flag: 'Z' or 'z' or '' NO_ORIGINAL="File/Dir did not exist before patch." ORIGINAL_FILE="Existed before patch." # usage usage="usage: patcher.sh -install | -remove [-next_root ] [-backup_suffix ] -help" if [ $# -eq 0 ]; then echo "$usage" exit 0 fi eval echo "Processing args." $debug # process args while [ $# -gt 0 ]; do case $1 in -help) echo "" echo "$usage" echo "" echo "Arguments \(must have -install or -remove\):" echo " -install # install patch from tarfile" echo " -remove # remove files in patch tarfile" echo " # restoring previous versions" echo " -next_root # specify if NEXT_ROOT env not set" echo " -backup_suffix # used for backed-up files" echo "" exit 0 ;; -install) eval echo "-install options entered" $debug shift if [ "$installPackage" ]; then echo "*** ERROR *** -install is multiply defined." exit 1 fi if [ "$removePackage" ]; then echo "*** ERROR *** -install and -remove are exclusive." exit 1 fi if [ $# -eq 0 ]; then echo "*** ERROR *** no package spefified after -install option." exit 1 fi if [ -f "$1" ]; then installPackage=$1 fi if [ -f "`pwd`/$1" ]; then installPackage=`pwd`/$1 fi eval echo "installPackage: $installPackage" $debug shift ;; -remove) eval echo "-remove options entered" $debug shift if [ "$removePackage" ]; then echo "*** ERROR *** -remove is multiply defined." exit 1 fi if [ "$installPackage" ]; then echo "*** ERROR *** -install and -remove are exclusive." exit 1 fi if [ $# -eq 0 ]; then echo "*** ERROR *** no package spefified after -remove option." exit 1 fi if [ -f "$1" ]; then removePackage=$1 fi if [ -f "`pwd`/$1" ]; then removePackage=`pwd`/$1 fi eval echo "-removePackage: $removePackage" $debug shift ;; -next_root) shift if [ $# -eq 0 ]; then echo "*** ERROR *** no directory spefified after -next_root option." exit 1 fi next_root=$1 if [ `echo $next_root | grep '^.:$'` ]; then $next_root=$next_root/ fi if [ ! -d "$next_root" ]; then echo "*** ERROR *** NeXT root $next_root not found." exit 1 fi if [ "$NEXT_ROOT" ]; then echo "*** WARNING *** NEXT_ROOT environment var ingored, using $next_root" fi shift ;; -backup_suffix) shift if [ $# -eq 0 ]; then echo "*** ERROR *** no string spefified after -backup_suffix option." exit 1 fi backup_suffix=$1 shift ;; *) echo "**** ERROR **** Invalid option: $1" echo $usage exit 1 ;; esac done eval echo "Processing args done." $debug if [ ! "$installPackage" -a ! "$removePackage" ]; then echo "*** ERROR *** Failed to specify -install or -remove option." exit 1 fi eval echo "backup_suffix is $backup_suffix" $debug # Locate NeXT root, might be defines in environment as $NEXT_ROOT # if [ ! "$next_root" ]; then if [ "$NEXT_ROOT" ]; then if [ ! -d "$NEXT_ROOT" ]; then echo "*** ERROR *** $NEXT_ROOT does not exist!" exit 1 fi next_root=$NEXT_ROOT else if [ ! -d /NextLibrary ]; then echo "*** ERROR *** can not seem to find NeXT root, please specify using -next_root option." exit 1 fi next_root=/ fi fi eval echo "NEXT root is $next_root" $debug # find gnutar, $next_root exists at this point # HAVEGNUTAR=0 if [ ! "$GNUTAR" ]; then for x in /usr/bin/gnutar /tmp/gnutar $next_root/NextDeveloper/bin/gnutar /usr/local/bin/gnutar; do #eval echo "does $x exist?" $debug if [ -f "$x" ]; then GNUTAR=$x HAVEGNUTAR=1 break fi done # need to chech that which is in the path.... # better find it above as this will break on NT.... if [ $HAVEGNUTAR -eq 0 ]; then which gnutar | grep "no gnutar in" if [ $? -eq 0 ]; then echo "*** ERROR *** gnutar not in path." exit 1 else eval echo "using which to define GNUTAR" $debug GNUTAR=`which gnutar` fi fi fi trash=`echo "$GNUTAR" | grep -s gnutar` if [ $? -eq 1 ]; then echo "*** ERROR *** gnutar not in path" exit 1 fi `cp $GNUTAR /tmp/gnutar` GNUTAR=/tmp/gnutar eval echo "found gnutar at $GNUTAR" $debug if [ "$installPackage" ]; then eval echo echo "entered installPackage" $debug backupFileListing=./patcher.tmp if [ -f "$backupFileListing" ]; then rm $backupFileListing if [ $? -ne 0 ]; then echo "*** ERROR *** couldn't remove file $backupFileListing" exit 1 fi fi for fileEntry in `$GNUTAR ${COMPRESS}ft $installPackage | awk '{printf "%s ", $0}' ` ; do eval echo -n "$fileEntry" $debug if [ `echo $fileEntry | grep '/$'` ]; then fileEntryType="dir" else fileEntryType="file" # might be a link... fi eval echo " is a $fileEntryType" $debug oldfile=`echo ${next_root}/${fileEntry} | sed 's^/$^^'` newfile=${oldfile}.$backup_suffix if [ -f "$oldfile" -o -h "$oldfile" ]; then eval echo "*** EXISTING FILE *** $fileEntry" $debug if [ -f "$newfile" ]; then eval echo "*** WARNING *** file: $newfile exists ie already patched" $debug else if [ -f $oldfile ]; then chmod a+rw $oldfile fi if [ "$fileEntryType" = "file" ]; then mv $oldfile $newfile fi fi if [ $? -ne 0 ]; then echo "*** ERROR *** could not move $oldfile to ${oldfile}.$backup_suffix" exit 1 fi elif [ ! -d $oldfile ]; then # directory is not part of original distribution # need to make the directory hierarchy so we can make our # "back out" file if [ $fileEntryType = "dir" ]; then mkdir -p $oldfile chmod a+rw $oldfile fi echo $NO_ORIGINAL > "$newfile" # "backout file" fi done echo "No errors, extracting patch" COMPRESS=-$COMPRESS eval echo "COMPRESS: $COMPRESS" $debug eval echo "extracting patch..." $debug `$GNUTAR --directory $next_root ${COMPRESS} -x -f $installPackage ` if [ $? -ne 0 ]; then echo "*** ERROR *** errors while installing patch" # restore .$backup_suffix files... # by doing uninstall.... just do it or call myself with -remove???? if [ $? -ne 0 ]; then echo "*** WARING *** uninstall failed as well..." exit 1 fi else echo "" echo "Install of $installPackage successful" # grok for special files that will require a reboot... # and notify. fi exit 0 fi if [ "$removePackage" ]; then echo "scanning files for backups..." # scan to make sure every file has a backup file # for fileEntry in `$GNUTAR ${COMPRESS}ft $removePackage | awk '{printf "%s ", $0 }'`; do eval echo echo $fileEntry $debug oldfile=`echo ${next_root}/${fileEntry} | sed 's^/$^^'` newfile=${oldfile}.$backup_suffix how_many_failed=0 how_many_not_writable=0 if [ ! -d "$oldfile" ]; then if [ ! -f "$newfile" ]; then how_many_failed=1 echo "*** WARNING *** $oldfile does not have backup file $newfile" elif [ ! -w "$oldfile" ]; then how_many_not_writable=1 echo "*** ERROR *** do not have permission to overwrite $oldfile" fi fi done if [ $how_many_failed -gt 0 -o $how_many_not_writable -gt 0 ]; then if [ $how_many_failed -gt 0 ]; then echo "*** ERROR *** file(s) did not have backups..." fi if [ $how_many_not_writable -gt 0 ]; then echo "*** ERROR *** file(s) were not writable..." fi if [ ! "$FORCE_REMOVAL" ]; then echo " ... aborting patch removal." exit 1 else echo "*** WARNING *** -force option specified, removing patch anyway." fi fi problem_with_removal=0 # did scan, time to remove patch and restore files # for fileEntry in `$GNUTAR ${COMPRESS}ft $removePackage | awk '{printf "%s ", $0 }' ` ; do # since there would not be any system necessary file like a kernel # or some library used by OS, since we are making sure nmserver, # machd, or OS/WOF apps we can just remove the files or move the # backups. # # eval echo -n "Processing: $fileEntry" $debug if [ `echo $fileEntry | grep '/$'` ]; then fileEntryType="dir" else fileEntryType="file" fi eval echo " is a $fileEntryType" $debug patch_file=`echo ${next_root}/${fileEntry} | sed 's^/$^^'` original_file=${patch_file}.${backup_suffix} if [ $fileEntryType = "dir" ]; then if [ -f "$original_file" ]; then eval echo "FILE: $original_file" $debug grep -s "$NO_ORIGINAL" "$original_file" if [ $? -ne 0 ]; then echo "*** DEBRIS WARNING *** expected file: $original_file does not contain string: '$NO_ORIGINAL'" problem_with_removal=$problem_with_removal+1 else # try to remove it since the patch put it in... # eval echo "removing: $original_file" $debug \rm -f "$original_file" if [ $? -ne 0 ]; then echo "*** DEBRIS WARNING *** could not remove $file_to_remove" problem_with_removal=$problem_with_removal+1 fi # making a list of dirs to remove later #dirsToRemove="$dirsToRemove $patch_file" #eval echo "dirs to remove: $dirsToRemove" $debug fi else # it's a dir and has no backup file, so skip it continue fi elif [ $fileEntryType = "file" ]; then if [ ! -f "$original_file" ]; then if [ ! -f "$patch_file" -a "$FORCE" ]; then break 2 else eval echo "*** ERROR *** backup file does not exit, use -force to ignore" $debug exit 1 fi exit 1 fi eval echo "-moving: $original_file to: $patch_file" \mv -f "$original_file" "$patch_file" if [ $? -ne 0 ]; then echo "*** REMOVE WARNING *** could not move original file: $original_file to $patch_file" echo "*** REMOVE WARNING *** patch file $patch_file not removed!" problem_with_removal=$problem_with_removal+1 fi grep -s "$NO_ORIGINAL" "$patch_file" if [ $? -eq 0 ]; then echo "$NO_ORIGINAL : $patch_file" $debug \rm -f $patch_file if [ $? -ne 0 ]; then echo "*** DEBRIS WARNING *** could not remove file: $patch_file" fi fi fi done problem_with_removal=`echo $problem_with_removal | bc` if [ "$problem_with_removal" -ne 0 ]; then echo "" echo "*** ERROR *** TROUBLE REMOVING PATCH! SEE ABOVE FOR *** REMOVE WARNING ***" exit 1 else if [ ! "$FORCE_REMOVAL" ]; then echo " Removed patch successfully. Start nmserver and machd at your leisure." exit 0 else echo "*** WARNING *** -force options specified, see ERROR messages for possible problems." exit 1 fi fi fi