#!/bin/sh # Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. # # $Id: mopatch,v 5.1.2.16 2011-07-29 12:57:31 jschmidt Exp $ # # MOPatch - Install Multiple Oracle Patches in One Run. # # Call mopatch -h for a short command-line overview. See # readme.txt under $ORACLE_HOME/MOPatch or SAP note 1027012 for # complete documentation. # ############################### # # included blocks and functions # ############################### IFS=" " SPC=" " TAB=" " NL=" " ( unset CDPATH ) 1>/dev/null 2>&1 && unset CDPATH PS1='$ ' PS2='> ' PS4='+ ' logopen=0 logfile="" logerrhdl=2 rlogopen=0 verbosep=0 internalerror=0 cmdlineerror=0 conflicterror=0 opatcherror=0 linkerror=0 usage() { echo "$1" 1>&2 echo "$USAGE" 1>&2 exit 2 } error() { p_4_0_class="" if test "X$1" = "X-c"; then p_4_0_class=$2 shift shift else p_4_0_class="internalerror" fi if test $logopen = 1; then echo 1>&2 echo "$1" 1>&2 # keep noise low in recursive calls if test $rlogopen = 0; then echo "Refer to log file${NL} $logfile${NL}for more information." 1>&2 fi echo 1>&3 echo "$1 Exiting." 1>&3 else echo "$1" 1>&2 fi case $p_4_0_class in internalerror) exit 1 ;; cmdlineerror) exit 2 ;; conflicterror) exit 4 ;; opatcherror) exit 8 ;; linkerror) exit 16 ;; ""|*[!0-9]*) exit 1 ;; *) exit $p_4_0_class ;; esac } logerr() { p_4_1_quiet="" if test "X$1" = "X-q"; then p_4_1_quiet=1 shift else p_4_1_quiet=0 fi p_4_1_class="" if test "X$1" = "X-c"; then p_4_1_class=$2 shift 2 else p_4_1_class="internalerror" fi if test $p_4_1_quiet = 1; then if test $logopen = 1; then echo "$1" 1>&3 fi else echo "$1 Continuing." 1>&2 if test $logopen = 1; then echo "$1 Continuing." 1>&3 fi fi eval "$p_4_1_class"='1' return 0 } err() { if test $# = 1; then echo "$1" 1>&2 echo "$1" 1>&3 else echo 1>&2 echo 1>&3 fi return 0 } out() { if test $# = 1; then echo "$1" 1>&1 echo "$1" 1>&3 else echo 1>&1 echo 1>&3 fi return 0 } log() { if test $# = 1; then echo "$1" 1>&3 else echo 1>&3 fi return 0 } verbose() { if test $# = 1; then if test $verbosep = 1; then echo "$1" 1>&1 fi echo "$1" 1>&3 else if test $verbosep = 1; then echo 1>&1 fi echo 1>&3 fi return 0 } rawout() { if test $# = 1; then echo "$1" 1>&1 else echo 1>&1 fi return 0 } patchnoboringp() { if test $patchno = "INVALID"; then return 0 else case $patchbase in p${patchno}_*.zip|*/p${patchno}_*.zip|*!${patchno}) return 0 ;; *) return 1 ;; esac fi } addtopatchlist() { p_4_2_flag="" l_4_2_flagp="" if test "X$1" = "X-f"; then p_4_2_flag=$2 l_4_2_flagp=1 shift 2 else p_4_2_flag=" " l_4_2_flagp=0 fi p_4_2_patchlist=$1 p_4_2_patchlistn="${1}n" p_4_2_patchlistf="${1}f" shift p_4_2_patchno="" if test "X$1" = "X-n"; then p_4_2_patchno=$2 shift 2 fi l_4_2_patchlist="" l_4_2_patchlistn="" l_4_2_patchlistf="" eval "l_4_2_patchlist=\${$p_4_2_patchlist-}" eval "l_4_2_patchlistn=\${$p_4_2_patchlistn-}" eval "l_4_2_patchlistf=\${$p_4_2_patchlistf-}" if test "X$p_4_2_patchno" != "X"; then l_4_2_patchlist="$l_4_2_patchlist$NL$p_4_2_flag $p_4_2_patchno" elif patchnoboringp; then l_4_2_patchlist="$l_4_2_patchlist$NL$p_4_2_flag $patchbase" else l_4_2_patchlist="$l_4_2_patchlist$NL$p_4_2_flag $patchbase (patch number $patchno)" fi if test $# -gt 0; then l_4_2_patchlist="$l_4_2_patchlist$1" fi l_4_2_patchlistn=`expr $l_4_2_patchlistn + 1 2>&3` l_4_2_patchlistf="$l_4_2_patchlistf$p_4_2_flag" eval "$p_4_2_patchlist"='$l_4_2_patchlist' eval "$p_4_2_patchlistn"='$l_4_2_patchlistn' if test $l_4_2_flagp = 1; then eval "$p_4_2_patchlistf"='$l_4_2_patchlistf' fi return 0 } perror() { p_4_3_class="" if test "X$1" = "X-c"; then p_4_3_class=$2 shift shift else p_4_3_class="internalerror" fi err "Processing patch \"$patchbase\"...failed." err "Reason: $1" if test $# -gt 1; then addtopatchlist failed "$2" else addtopatchlist failed fi eval "$p_4_3_class"='1' return 0 } pskip() { p_4_4_class="" if test "X$1" = "X-c"; then p_4_4_class=$2 shift 2 fi p_4_4_flag="" if test "X$1" = "X-f"; then p_4_4_flag=$2 shift 2 fi out "Processing patch \"$patchbase\"...skipped." verbose "Reason: $2" if test "X$p_4_4_flag" != "X" && test $# -gt 2; then addtopatchlist -f "$p_4_4_flag" "$1" "$3" elif test "X$p_4_4_flag" != "X"; then addtopatchlist -f "$p_4_4_flag" "$1" elif test $# -gt 2; then addtopatchlist "$1" "$3" else addtopatchlist "$1" fi if test "X$p_4_4_class" != "X"; then eval "$p_4_4_class"='1' fi return 0 } mlp() { case $1 in *$NL*) return 0 ;; *) return 1 ;; esac } swp() { case $1 in *[$SPC$TAB$NL]*) return 1 ;; *) return 0 ;; esac } mwp() { case $1 in *[$SPC$TAB$NL]*) return 0 ;; *) return 1 ;; esac } numberp() { case $1 in ""|*[!0-9]*) return 1 ;; *) return 0 ;; esac } varnamep() { case $1 in ""|*[!a-zA-Z0-9_]*) return 1 ;; *) return 0 ;; esac } versionp() { case $1 in # awkward but fast. Most common case duplicated as first test. [0-9][0-9].[0-9].[0-9].[0-9].[0-9]) return 0 ;; [0-9].[0-9].[0-9].[0-9].[0-9]) return 0 ;; [0-9].[0-9].[0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9].[0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9].[0-9].[0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9].[0-9][0-9].[0-9].[0-9]) return 0 ;; [0-9].[0-9].[0-9][0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9].[0-9][0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9].[0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9].[0-9].[0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9][0-9].[0-9].[0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9][0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9].[0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9][0-9].[0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9][0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9][0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9].[0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9].[0-9][0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9]) return 0 ;; [0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9]) return 0 ;; *) return 1 ;; esac } verstest() { p_4_7_prec="" if test "X$1" = "X-d"; then p_4_7_prec=$2 shift 2 else p_4_7_prec=4 fi p_4_7_relop=$2 # convert version strings to version numbers and right-pad the # resulting numbers with zeroes to ten digits p_4_7_v1=`verstonum "$1" || :` p_4_7_v2=`verstonum "$3" || :` case $p_4_7_v1 in ??????????) : ;; ????????) p_4_7_v1="${p_4_7_v1}00" ;; ??????) p_4_7_v1="${p_4_7_v1}0000" ;; ????) p_4_7_v1="${p_4_7_v1}000000" ;; ??) p_4_7_v1="${p_4_7_v1}00000000" ;; *) return 1 ;; esac case $p_4_7_v2 in ??????????) : ;; ????????) p_4_7_v2="${p_4_7_v2}00" ;; ??????) p_4_7_v2="${p_4_7_v2}0000" ;; ????) p_4_7_v2="${p_4_7_v2}000000" ;; ??) p_4_7_v2="${p_4_7_v2}00000000" ;; *) return 1 ;; esac if test "X$p_4_7_relop" = "X=" || test "X$p_4_7_relop" = "X!=" || test $p_4_7_prec = 0; then if test $p_4_7_v1 "$p_4_7_relop" $p_4_7_v2; then return 0 else return 1 fi fi l_4_7_splitss="" case $p_4_7_prec in 4) l_4_7_splitss='s/^\(........\)\(..\)$/\1\&\2/' ;; 3) l_4_7_splitss='s/^\(......\)\(....\)$/\1\&\2/' ;; 2) l_4_7_splitss='s/^\(....\)\(......\)$/\1\&\2/' ;; 1) l_4_7_splitss='s/^\(..\)\(........\)$/\1\&\2/' ;; esac p_4_7_v1=`echo $p_4_7_v1 | sed "$l_4_7_splitss" 2>&$logerrhdl` p_4_7_v2=`echo $p_4_7_v2 | sed "$l_4_7_splitss" 2>&$logerrhdl` l_oldifs=$IFS; IFS="&"; set -f; set x $p_4_7_v1; shift; set +f; IFS=$l_oldifs l_4_7_v1mj=$1 l_4_7_v1mi=$2 l_oldifs=$IFS; IFS="&"; set -f; set x $p_4_7_v2; shift; set +f; IFS=$l_oldifs l_4_7_v2mj=$1 l_4_7_v2mi=$2 if test $l_4_7_v1mj = $l_4_7_v2mj && test $l_4_7_v1mi "$p_4_7_relop" $l_4_7_v2mi; then return 0 else return 1 fi } globtest() { p_4_8_filetest=$1 shift for l_4_8_item in ${1+"$@"} do if test "$p_4_8_filetest" "$l_4_8_item"; then return 0 fi done return 1 } memberp() { if test $# = 2; then if test "X$1" = "X"; then return 1 else l_4_5_dellist=" $2 " case $l_4_5_dellist in *[$SPC$TAB$NL]"$1"[$SPC$TAB$NL]*) return 0 ;; *) return 1 ;; esac fi else if test "X$2" = "X"; then return 1 else l_4_5_dellist="$1$3$1" case $l_4_5_dellist in *"$1$2$1"*) return 0 ;; *) return 1 ;; esac fi fi } verstonum() { if test "X$1" = "X"; then echo "" return 1 fi l_4_6_nver="" l_4_6_bad=0 l_oldifs=$IFS; IFS="."; set -f; set x $1; shift; set +f; IFS=$l_oldifs for l_4_6_v in "$@" do case $l_4_6_v in [0-9][0-9]) l_4_6_nver="${l_4_6_nver}${l_4_6_v}" ;; [0-9]) l_4_6_nver="${l_4_6_nver}0${l_4_6_v}" ;; *) l_4_6_bad=1 ;; esac done if test $l_4_6_bad = 0; then echo $l_4_6_nver return 0 else echo "" return 1 fi } quotemeta() { l_4_9_scqre="" # special char quoting regexp if test "X${1-}" = "X-x"; then l_4_9_scqre='\.\*\[\\\^\$(){}?+|' shift else l_4_9_scqre='\.\*\[\\\^\$' fi if test "X${1-}" = "X-s"; then l_4_9_scqre="$l_4_9_scqre\\$2" shift shift fi if sed 's/\(['"$l_4_9_scqre"']\)/\\\1/g'; then return 0 else return 1 fi } basenamef() { case $1 in *$NL*) echo "Internal error: Invalid newline characters in file name." 1>&2 return 1 ;; esac if test "X$1" = "X"; then echo "" return 0 elif expr "//$1" : '.*/\(.*\)$'; then return 0 else return 1 fi } exitvalf() { l_4_10_exitval=0 if test $internalerror != 0; then l_4_10_exitval=`expr $l_4_10_exitval + 1` fi if test $cmdlineerror != 0; then l_4_10_exitval=`expr $l_4_10_exitval + 2` fi if test $conflicterror != 0; then l_4_10_exitval=`expr $l_4_10_exitval + 4` fi if test $opatcherror != 0; then l_4_10_exitval=`expr $l_4_10_exitval + 8` fi if test $linkerror != 0; then l_4_10_exitval=`expr $l_4_10_exitval + 16` fi case $l_4_10_exitval in [0-9]|[0-9][0-9]) echo "$l_4_10_exitval" return 0 ;; *) echo "Internal error: Invalid exit value \"$l_4_10_exitval\"." 1>&2 echo "1" return 1 ;; esac } platforminfof() { l_4_11_platform="" if test $# -gt 0; then l_4_11_platform=$1 else l_4_11_uname="" if l_4_11_uname=`uname -s -m 2>&3`; then : else logerr -q "Cannot execute \"uname\" to determine platform." echo "" return 1 fi # handle some exceptions case $l_4_11_uname in AIX\ *) l_4_11_platform="aix" ;; HP-UX\ 9000/785) l_4_11_platform="hp_ux_9000_800" ;; SunOS\ sun4[cdmsv]) l_4_11_platform="sunos_sun4u" ;; SunOS\ sun4us) l_4_11_platform="sunos_sun4u" ;; *) l_4_11_platform=`printf '%s\n' "$l_4_11_uname" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 2>&3 | sed 's/[^a-z0-9]/_/g' 2>&3` ;; esac fi case $l_4_11_platform in aix|212|rs6000_64) l_4_11_platform="aix 212 rs6000_64" ;; hp_ux_9000_800|59|hp_64) l_4_11_platform="hp_ux_9000_800 59 hp_64" ;; hp_ux_ia64|197|hpia64) l_4_11_platform="hp_ux_ia64 197 hpia64" ;; sunos_sun4u|23|sun_64) l_4_11_platform="sunos_sun4u 23 sun_64" ;; sunos_i86pc|267|sunx86_64) l_4_11_platform="sunos_i86pc 267 sunx86_64" ;; osf1_alpha|87|alphaosf) l_4_11_platform="osf1_alpha 87 alphaosf" ;; linux_x86_64|226|linuxx86_64) l_4_11_platform="linux_x86_64 226 linuxx86_64" ;; linux_i686|46|linuxintel) l_4_11_platform="linux_i686 46 linuxintel" ;; linux_ia64|214|linuxia64) l_4_11_platform="linux_ia64 214 linuxia64" ;; linux_ppc64|227|linuxppc64) l_4_11_platform="linux_ppc64 227 linuxppc64" ;; *) logerr -q "Cannot determine platform from \"$l_4_11_platform\"." echo "" return 1 ;; esac # determine kernel version l_4_11_release="" if l_4_11_release=`uname -r 2>&3`; then : else logerr -q "Cannot execute \"uname\" to determine kernel version." echo "" return 1 fi if mwp "$l_4_11_release"; then logerr -q "Cannot determine kernel version from \"$l_4_11_release\"." echo "" return 1 fi echo "$l_4_11_platform $l_4_11_release" return 0 } RDBMSVERRE='^[ ]*SQL\*Plus:[ ][ ]*Release[ ][ ]*[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*[ ][ ]*(-[ ][ ]*)?Production[ ]*$' RDBMSVER10SE='^[ ]*SQL\*Plus:[ ][ ]*Release[ ][ ]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ ][ ]*-[ ][ ]*Production[ ]*$' RDBMSVER11SE='^[ ]*SQL\*Plus:[ ][ ]*Release[ ][ ]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ ][ ]*Production[ ]*$' rdbmsversionf() { # determine and verify Oracle RDBMS version l_4_12_rdbmsver="" l_4_12_rdbmsverlog="$tmpdir/rdbmsver.log" log "executing: \"$ORACLE_HOME/bin/sqlplus\" -v" # SQL*Plus depends on the shared library path, so better # explicitly set that if LD_LIBRARY_PATH="$ORACLE_HOME/lib" \ SHLIB_PATH="$ORACLE_HOME/lib" \ LIBPATH="$ORACLE_HOME/lib" \ "$ORACLE_HOME/bin/sqlplus" -v 1>"$l_4_12_rdbmsverlog" 2>&3; then l_4_12_rdbmsver=`( egrep "$RDBMSVERRE" "$l_4_12_rdbmsverlog" 2>&3 || : ) | sed 's/'"$RDBMSVER10SE"'/\1/;s/'"$RDBMSVER11SE"'/\1/' 2>&3` if versionp "$l_4_12_rdbmsver"; then : else logerr -q "Cannot determine Oracle RDBMS version from \"$l_4_12_rdbmsver\"." echo "" return 1 fi else logerr -q "Cannot execute SQL*Plus to determine Oracle RDBMS version." echo "" return 1 fi # determine and verify Oracle RDBMS numeric version l_4_12_rdbmsnver="" if l_4_12_rdbmsnver=`verstonum "$l_4_12_rdbmsver"`; then : else logerr -q "Cannot determine Oracle RDBMS numeric version from \"$l_4_12_rdbmsver\"." echo "" return 1 fi # determine Oracle RDBMS version components l_oldifs=$IFS; IFS="."; set -f; set x $l_4_12_rdbmsver; shift; set +f; IFS=$l_oldifs echo "$l_4_12_rdbmsver $l_4_12_rdbmsnver $1 $2 $3 $4 $5" return 0 } OPVERRE='^[ ]*OPatch[ ][ ]*Version:[ ][ ]*[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*[ ]*$' OPVERSE='^[ ]*OPatch[ ][ ]*Version:[ ][ ]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ ]*$' OPVERSION_NAPPLYP=3 OPVERSION_CUSP=4 OPVERSION_XMLINVP=5 OPVERSION_HPATCHP=6 OPVERSION_PSUSP=7 opversionf() { # determine and verify OPatch version l_4_13_opver="" l_4_13_opverlog="$tmpdir/opver.log" log "executing: \"$opatch\" version ${1+$*}" if "$opatch" version ${1+"$@"} 1>"$l_4_13_opverlog" 2>&3; then l_4_13_opver=`( grep "$OPVERRE" "$l_4_13_opverlog" 2>&3 || : ) | sed 's/'"$OPVERSE"'/\1/' 2>&3` if versionp "$l_4_13_opver"; then : else logerr -q "Cannot determine OPatch version from \"$l_4_13_opver\"." echo "" return 1 fi else logerr -q "Cannot execute OPatch to determine OPatch version." echo "" return 1 fi # determine and verify OPatch numeric version l_4_13_opnver="" if l_4_13_opnver=`verstonum "$l_4_13_opver"`; then : else logerr -q "Cannot determine OPatch numeric version from \"$l_4_13_opver\"." echo "" return 1 fi # OPVD: determine n-apply support. We could have used function # "verstest" for this and all the following tests, but the # present mixture of "case" statements and comparisons with # "$l_opnver" is probably faster. l_4_13_napplyp="" case $l_4_13_opver in 11.2.*) l_4_13_napplyp=1 ;; 11.1.*) l_4_13_napplyp=1 ;; 10.2.0.5.*) l_4_13_napplyp=1 ;; 10.2.0.4.*) if test $l_4_13_opnver -ge 1002000402; then # 10.2.0.4.2 l_4_13_napplyp=1 else l_4_13_napplyp=0 fi ;; 10.2.0.2.*) if test $l_4_13_opnver -ge 1002000203; then # 10.2.0.2.3 l_4_13_napplyp=1 else l_4_13_napplyp=0 fi ;; *) l_4_13_napplyp=0 ;; esac # OPVD: determine patch storage clean-up support l_4_13_cusp="" case $l_4_13_opver in 11.2.*) l_4_13_cusp=1 ;; 11.1.*) l_4_13_cusp=1 ;; 10.2.0.5.*) l_4_13_cusp=1 ;; 10.2.0.4.*) if test $l_4_13_opnver -ge 1002000402; then # 10.2.0.4.2 l_4_13_cusp=1 else l_4_13_cusp=0 fi ;; 10.2.0.2.*) if test $l_4_13_opnver -ge 1002000204; then # 10.2.0.2.4 l_4_13_cusp=1 else l_4_13_cusp=0 fi ;; *) l_4_13_cusp=0 ;; esac # OPVD: determine "correct" XML inventory support l_4_13_xmlinvp="" case $l_4_13_opver in 11.2.*) l_4_13_xmlinvp=1 ;; 11.1.*) l_4_13_xmlinvp=1 ;; 10.2.0.5.*) l_4_13_xmlinvp=1 ;; 10.2.0.4.*) if test $l_4_13_opnver -ge 1002000402; then # 10.2.0.4.2 l_4_13_xmlinvp=1 else l_4_13_xmlinvp=0 fi ;; 10.2.0.2.*) if test $l_4_13_opnver -ge 1002000205; then # 10.2.0.2.5 l_4_13_xmlinvp=1 else l_4_13_xmlinvp=0 fi ;; *) l_4_13_xmlinvp=0 ;; esac # OPVD: determine online patch apply support l_4_13_hpatchp="" case $l_4_13_opver in 11.2.*) l_4_13_hpatchp=1 ;; 11.1.*) l_4_13_hpatchp=1 ;; *) l_4_13_hpatchp=0 ;; esac # OPVD: determine PSU and dependency handling support l_4_13_psusp="" case $l_4_13_opver in 11.2.*) l_4_13_psusp=1 ;; 11.1.*) if test $l_4_13_opnver -ge 1101000607; then # 11.1.0.6.7 l_4_13_psusp=1 else l_4_13_psusp=0 fi ;; 10.2.0.5.*) l_4_13_psusp=1 ;; 10.2.0.4.*) if test $l_4_13_opnver -ge 1002000407; then # 10.2.0.4.7 l_4_13_psusp=1 else l_4_13_psusp=0 fi ;; *) l_4_13_psusp=0 ;; esac # $1 $2 $3 $4 $5 $6 $7 echo "$l_4_13_opver $l_4_13_opnver $l_4_13_napplyp $l_4_13_cusp $l_4_13_xmlinvp $l_4_13_hpatchp $l_4_13_psusp" return 0 } PMDXMLGESS='s/&/\&/g;s//\>/g;s/'\''/\'/g;s/"/\"/g' pmdtbiids="" pmdinsids="" pmdrlbids="" pmdpatchbase="" pmdpatchsrc="" pmdpatchmlc="" pmdpatchno="" pmdpatchstamp="" pmdpatchflags="" pmdpatchprqs="" pmdpatchovls="" pmdpatchfiles="" pmdpatchmakes="" pmdcache() { p_7_0_invtype=$1 p_7_0_patchid=$2 l_7_0_pmd="" if test "X$p_7_0_invtype" = "Xtbi" && eval test '"X${hash_pmdtbi_'"$p_7_0_patchid"'+X}"' = '"XX"'; then eval l_7_0_pmd=\${hash_pmdtbips_"$p_7_0_patchid"-} l_oldifs=$IFS; IFS="&"; set -f; set x $l_7_0_pmd; shift; set +f; IFS=$l_oldifs pmdpatchbase=$1 pmdpatchsrc=$2 pmdpatchmlc=$3 eval l_7_0_pmd=\${hash_pmdtbi_"$p_7_0_patchid"-} l_oldifs=$IFS; IFS="&"; set -f; set x $l_7_0_pmd; shift; set +f; IFS=$l_oldifs pmdpatchno=$1 pmdpatchstamp=$2 pmdpatchflags=$3 eval pmdpatchprqs=\${hash_pmdtbiprs_"$p_7_0_patchid"-} eval pmdpatchovls=\${hash_pmdtbiols_"$p_7_0_patchid"-} eval pmdpatchfiles=\${hash_pmdtbifls_"$p_7_0_patchid"-} eval pmdpatchmakes=\${hash_pmdtbimks_"$p_7_0_patchid"-} return 0 elif test "X$p_7_0_invtype" = "Xins" && eval test '"X${hash_pmdins_'"$p_7_0_patchid"'+X}"' = '"XX"'; then pmdpatchbase="" pmdpatchsrc="" pmdpatchmlc="" eval l_7_0_pmd=\${hash_pmdins_"$p_7_0_patchid"-} l_oldifs=$IFS; IFS="&"; set -f; set x $l_7_0_pmd; shift; set +f; IFS=$l_oldifs pmdpatchno=$1 pmdpatchstamp=$2 pmdpatchflags=$3 eval pmdpatchprqs=\${hash_pmdinsprs_"$p_7_0_patchid"-} eval pmdpatchovls=\${hash_pmdinsols_"$p_7_0_patchid"-} eval pmdpatchfiles=\${hash_pmdinsfls_"$p_7_0_patchid"-} eval pmdpatchmakes=\${hash_pmdinsmks_"$p_7_0_patchid"-} return 0 elif test "X$p_7_0_invtype" = "Xrlb" && eval test '"X${hash_pmdrlb_'"$p_7_0_patchid"'+X}"' = '"XX"'; then pmdpatchbase="" pmdpatchsrc="" pmdpatchmlc="" eval l_7_0_pmd=\${hash_pmdrlb_"$p_7_0_patchid"-} l_oldifs=$IFS; IFS="&"; set -f; set x $l_7_0_pmd; shift; set +f; IFS=$l_oldifs pmdpatchno=$1 pmdpatchstamp=$2 pmdpatchflags=$3 eval pmdpatchprqs=\${hash_pmdrlbprs_"$p_7_0_patchid"-} eval pmdpatchovls=\${hash_pmdrlbols_"$p_7_0_patchid"-} eval pmdpatchfiles=\${hash_pmdrlbfls_"$p_7_0_patchid"-} eval pmdpatchmakes=\${hash_pmdrlbmks_"$p_7_0_patchid"-} return 0 else pmdpatchbase="" pmdpatchsrc="" pmdpatchmlc="" pmdpatchno="" pmdpatchstamp="" pmdpatchflags="" pmdpatchprqs="" pmdpatchovls="" pmdpatchfiles="" pmdpatchmakes="" return 1 fi } pmdget() { p_7_1_invtype=$1 p_7_1_patchid=$2 shift 2 # true ampersand-list of variable references # "${pmd-}" to the patch metadata l_7_1_fields="" while test $# -gt 0; do if test $# -gt 1; then l_7_1_fields="$l_7_1_fields\${pmd$1-}&" else l_7_1_fields="$l_7_1_fields\${pmd$1-}" fi shift done # we may call "pmdcache" here without being afraid of # overwriting the caller's cache, since we only ever will be # called in a command substitution if pmdcache "$p_7_1_invtype" $p_7_1_patchid; then eval "printf '%s\n' \"$l_7_1_fields\"" return 0 else echo "" return 1 fi } pmdfind() { p_7_2_invtype=$1 shift # determine query command l_7_2_query=":" while test $# -gt 0; do l_7_2_param1=$1 l_7_2_op=$2 l_7_2_param2=$3 shift 3 case $l_7_2_op in "~") if test "X$l_7_2_param1" = "Xpatchflags"; then l_7_2_query="$l_7_2_query && ( case \$pmdpatchflags in *' $l_7_2_param2 '*) exit 0 ;; *) exit 1 ;; esac )" else l_7_2_query="$l_7_2_query && ( case \${pmd$l_7_2_param1-} in $l_7_2_param2) exit 0 ;; *) exit 1 ;; esac )" fi ;; "!~") if test "X$l_7_2_param1" = "Xpatchflags"; then l_7_2_query="$l_7_2_query && ( case \$pmdpatchflags in *' $l_7_2_param2 '*) exit 1 ;; *) exit 0 ;; esac )" else l_7_2_query="$l_7_2_query && ( case \${pmd$l_7_2_param1-} in $l_7_2_param2) exit 1 ;; *) exit 0 ;; esac )" fi ;; *) case $l_7_2_param1 in patch*) l_7_2_param1="\"\${pmd$l_7_2_param1-}\"" ;; *\'*) l_7_2_param1=`printf '%s\n' "$l_7_2_param1" | sed "s/'/'\\\\\\\\''/g" 2>&3` l_7_2_param1="'$l_7_2_param1'" ;; *) l_7_2_param1="'$l_7_2_param1'" ;; esac case $l_7_2_param2 in patch*) l_7_2_param2="\"\${pmd$l_7_2_param2-}\"" ;; *\'*) l_7_2_param2=`printf '%s\n' "$l_7_2_param2" | sed "s/'/'\\\\\\\\''/g" 2>&3` l_7_2_param2="'$l_7_2_param2'" ;; *) l_7_2_param2="'$l_7_2_param2'" ;; esac l_7_2_query="$l_7_2_query && test $l_7_2_param1 '$l_7_2_op' $l_7_2_param2" ;; esac done l_7_2_patchids="" case $p_7_2_invtype in tbi) l_7_2_patchids=$pmdtbiids ;; ins) l_7_2_patchids=$pmdinsids ;; rlb) l_7_2_patchids=$pmdrlbids ;; esac l_7_2_result="" l_oldifs=$IFS; IFS=" "; set -f; set x $l_7_2_patchids; shift; set +f; IFS=$l_oldifs for l_7_2_patchid in ${1+"$@"}; do # redirect "eval"'s STDERR to the log file to not loose # potential error messages if ( pmdcache "$p_7_2_invtype" $l_7_2_patchid && eval "$l_7_2_query" 2>&3 ); then l_7_2_result="$l_7_2_result$l_7_2_patchid " fi done echo "$l_7_2_result" if test "X$l_7_2_result" != "X"; then return 0 else return 1 fi } pmdcpmv() { # verify existence of patch in source inventory case $2 in tbi) eval test '"X${hash_pmdtbi_'"$4"'+X}"' = '"XX"' || return 1 ;; ins) eval test '"X${hash_pmdins_'"$4"'+X}"' = '"XX"' || return 1 ;; rlb) eval test '"X${hash_pmdrlb_'"$4"'+X}"' = '"XX"' || return 1 ;; esac # copy patch from source to destination inventory. Do not # check whether the source patch fields actually exist or not - # function "pmdcache" does not, either. eval "hash_pmd${3}ps_${5}=\${hash_pmd${2}ps_${4}-}" eval "hash_pmd${3}_${5}=\${hash_pmd${2}_${4}-}" eval "hash_pmd${3}prs_${5}=\${hash_pmd${2}prs_${4}-}" eval "hash_pmd${3}ols_${5}=\${hash_pmd${2}ols_${4}-}" eval "hash_pmd${3}fls_${5}=\${hash_pmd${2}fls_${4}-}" eval "hash_pmd${3}mks_${5}=\${hash_pmd${2}mks_${4}-}" if test "X$1" = "X-m"; then # remove patch from source inventory unset "hash_pmd${2}ps_${4}" unset "hash_pmd${2}_${4}" unset "hash_pmd${2}prs_${4}" unset "hash_pmd${2}ols_${4}" unset "hash_pmd${2}fls_${4}" unset "hash_pmd${2}mks_${4}" fi # add patch ID to destination list, if required case $3 in tbi) memberp " " $5 "$pmdtbiids" || pmdtbiids="$pmdtbiids${5} " ;; ins) memberp " " $5 "$pmdinsids" || pmdinsids="$pmdinsids${5} " ;; rlb) memberp " " $5 "$pmdrlbids" || pmdrlbids="$pmdrlbids${5} " ;; esac if test "X$1" = "X-m"; then # remove patch ID from source list case $2 in tbi) pmdtbiids=`echo "$pmdtbiids" | sed "s/^$4 //;s/ $4 / /" 2>&3` || return 1 ;; ins) pmdinsids=`echo "$pmdinsids" | sed "s/^$4 //;s/ $4 / /" 2>&3` || return 1 ;; rlb) pmdrlbids=`echo "$pmdrlbids" | sed "s/^$4 //;s/ $4 / /" 2>&3` || return 1 ;; esac fi return 0 } pmdmv2front() { p_7_3_invtype=$1 shift l_7_3_patchids="" case $p_7_3_invtype in tbi) l_7_3_patchids=$pmdtbiids ;; ins) l_7_3_patchids=$pmdinsids ;; rlb) l_7_3_patchids=$pmdrlbids ;; esac l_7_3_frontids="" for l_7_3_patchid in ${1+"$@"} do l_7_3_frontids="$l_7_3_frontids$l_7_3_patchid " l_7_3_patchids=`echo "$l_7_3_patchids" | sed "s/^$l_7_3_patchid //;s/ $l_7_3_patchid / /" 2>&3` done case $p_7_3_invtype in tbi) pmdtbiids="$l_7_3_frontids$l_7_3_patchids" ;; ins) pmdinsids="$l_7_3_frontids$l_7_3_patchids" ;; rlb) pmdrlbids="$l_7_3_frontids$l_7_3_patchids" ;; esac return 0 } pmdflaginfo() { l_7_4_pmflag="" if pmdflagset "exec" "shtdwn"; then l_7_4_pmflag=" " elif pmdflagset "hpatch"; then l_7_4_pmflag="*" else l_7_4_pmflag="+" fi l_7_4_piiflag="" if pmdflagset "psu" "catpsu"; then l_7_4_piiflag="!" elif pmdflagset "catcpu"; then l_7_4_piiflag="*" elif pmdflagset "cpumlc" "cpurlb"; then # molecules of a CPU do not have their own post-installation # instructions l_7_4_piiflag=" " elif pmdflagset "sql"; then l_7_4_piiflag="+" else l_7_4_piiflag=" " fi l_7_4_flagstring="" if pmdflagset "psu" "catpsu"; then l_7_4_flagstring="${l_7_4_flagstring}psu " elif pmdflagset "catcpu"; then l_7_4_flagstring="${l_7_4_flagstring}cpu " elif pmdflagset "cpumlc" "cpurlb"; then # PSUs routinely contain CPU molecules, so this must come in # an "elif" branch l_7_4_flagstring="${l_7_4_flagstring}cpumlc " fi if pmdflagset "sql"; then l_7_4_flagstring="${l_7_4_flagstring}sql " fi if pmdflagset "java"; then l_7_4_flagstring="${l_7_4_flagstring}java " fi if pmdflagset "opatch"; then l_7_4_flagstring="${l_7_4_flagstring}opatch " fi l_oldifs=$IFS; IFS=" "; set -f; set x $l_7_4_flagstring; shift; set +f; IFS=$l_oldifs l_7_4_flagstring=${1+$*} echo "$l_7_4_pmflag&$l_7_4_piiflag&$l_7_4_flagstring" return 0 } pmdflagset() { for l_7_5_patchflag in "$@" do case $pmdpatchflags in *" $l_7_5_patchflag "*) return 0 ;; esac done return 1 } pmdflagclr() { for l_7_6_patchflag in "$@" do case $pmdpatchflags in *" $l_7_6_patchflag "*) return 1 ;; esac done return 0 } pmdfilep() { case $1 in ""|*[/$NL!\&]*) return 1 ;; *) return 0 ;; esac } pmddirp() { case $1 in ""|*[$NL!\&]*) return 1 ;; *) return 0 ;; esac } pmdtbihdr() { p_7_7_patchid=$1 l_7_7_patchbasexml=`printf '%s\n' "$2" | sed "$PMDXMLGESS" 2>&3` l_7_7_patchsrcxml=`printf '%s\n' "$3" | sed "$PMDXMLGESS" 2>&3` l_7_7_patchmlcxml=`printf '%s\n' "$4" | sed "$PMDXMLGESS" 2>&3` shift 4 printf '%s\n' "" 1>&6 printf '%s\n' "$l_7_7_patchbasexml" 1>&6 printf '%s\n' "$l_7_7_patchsrcxml" 1>&6 printf '%s\n' "$l_7_7_patchmlcxml" 1>&6 for l_7_7_patchflag in ${1+"$@"} do pmdtbiflg "$l_7_7_patchflag" done return 0 } pmdtbiflg() { echo "$1" 1>&6 return 0 } pmdtbiftr() { for l_7_8_patchflag in ${1+"$@"} do pmdtbiflg "$l_7_8_patchflag" done echo "" 1>&6 return 0 } pmdtbipatch() { pmdtbihdr "$@" pmdtbiftr return 0 } pmdtbifiles() { if sed "$PMDXMLGESS;"'s/^.*$/&<\/file>/' 1>&6 2>&3; then return 0 else return 1 fi } RDM_CKSUM_OPI="" RDM_CKSUM_PDII="" RDM_CKSUM_PII="" RDM_CKSUM_PIS="" RDM_CKSUM_PPII="" RDM_CKSUM_PPIS="" RDM_CKSUM_PSI="" RDM_CKSUM_TITLE="" RDM_CKSUM_OPI="${RDM_CKSUM_OPI}1427214443 1066${NL}" RDM_CKSUM_OPI="${RDM_CKSUM_OPI}3097530531 218${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}1015428360 565${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}1398202640 340${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}3488603691 1060${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}3583276666 291${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}3618834345 46${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}4283373679 55${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}716516252 364${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}762288036 1072${NL}" RDM_CKSUM_PDII="${RDM_CKSUM_PDII}883562646 64${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}1061769835 879${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}1507303873 1087${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}1609721226 222${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}2106167260 424${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}3072166991 859${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}3167795196 330${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}3638857628 652${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}393391967 918${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}4122196222 1091${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}4174258423 595${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}823668502 495${NL}" RDM_CKSUM_PII="${RDM_CKSUM_PII}955715494 326${NL}" RDM_CKSUM_PIS="${RDM_CKSUM_PIS}2449779061 664${NL}" RDM_CKSUM_PIS="${RDM_CKSUM_PIS}3388953630 1334${NL}" RDM_CKSUM_PIS="${RDM_CKSUM_PIS}4159378879 330${NL}" RDM_CKSUM_PPII="${RDM_CKSUM_PPII}1202926162 16${NL}" RDM_CKSUM_PPII="${RDM_CKSUM_PPII}254360664 5${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}2485116716 2346${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}2691260191 2387${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}3090244385 1625${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}3400764618 2391${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}657248193 2391${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}741892207 2079${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}856494134 2375${NL}" RDM_CKSUM_PPIS="${RDM_CKSUM_PPIS}985602706 2371${NL}" RDM_CKSUM_PSI="${RDM_CKSUM_PSI}1872289112 388${NL}" RDM_CKSUM_PSI="${RDM_CKSUM_PSI}1931427268 658${NL}" RDM_CKSUM_PSI="${RDM_CKSUM_PSI}3262758368 130${NL}" RDM_CKSUM_PSI="${RDM_CKSUM_PSI}3262758368 130${NL}" RDM_CKSUM_PSI="${RDM_CKSUM_PSI}4129019391 222${NL}" RDM_CKSUM_TITLE="${RDM_CKSUM_TITLE}1167487607 2302${NL}" RDM_CKSUM_TITLE="${RDM_CKSUM_TITLE}3529710619 808${NL}" eval hash_RDM_CKSUMS_"opi"='"$RDM_CKSUM_OPI"' eval hash_RDM_CKSUMS_"pdii"='"$RDM_CKSUM_PDII"' eval hash_RDM_CKSUMS_"pii"='"$RDM_CKSUM_PII"' eval hash_RDM_CKSUMS_"pis"='"$RDM_CKSUM_PIS"' eval hash_RDM_CKSUMS_"ppii"='"$RDM_CKSUM_PPII"' eval hash_RDM_CKSUMS_"ppis"='"$RDM_CKSUM_PPIS"' eval hash_RDM_CKSUMS_"psi"='"$RDM_CKSUM_PSI"' eval hash_RDM_CKSUMS_"title"='"$RDM_CKSUM_TITLE"' rdmnonstdp="" rdmdel() { while test $# -gt 0; do echo "${1},${2}d" 1>&6 shift 2 done return 0 } rdmscreen() { p_9_0_sectype=$1 p_9_0_secbeg=$2 p_9_0_secend=$3 shift 3 # calculate and normalize checksum. PD (osf1_alpha): Set # environment variable "$CMD_ENV" to force Posixly correct # results. l_9_0_cksum="" if l_9_0_cksum=`CMD_ENV=xpg4 cksum 2>&3`; then : else logerr "Cannot calculate README checksum ($p_9_0_sectype, $p_9_0_secbeg, $p_9_0_secend)." return 1 fi l_9_0_cksum=`set $l_9_0_cksum; echo "$1 $2"` eval l_9_0_cksums=\${hash_RDM_CKSUMS_"$p_9_0_sectype"-} if memberp "$NL" "$l_9_0_cksum" "$l_9_0_cksums"; then rdmdel $p_9_0_secbeg $p_9_0_secend return 0 elif test $flag_readme_strip_log = 1; then log "wrong checksum ($p_9_0_sectype, $p_9_0_secbeg, $p_9_0_secend): $l_9_0_cksum" l_9_0_sectpuc=`echo "$p_9_0_sectype" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 2>&3` echo "${p_9_0_secbeg}i\\${NL}RDM_CKSUM_${l_9_0_sectpuc}=\"\${RDM_CKSUM_${l_9_0_sectpuc}}$l_9_0_cksum\${NL}\"" 1>&6 echo "${p_9_0_secend}a\\${NL}RDM_CKSUM_${l_9_0_sectpuc}=\"\${RDM_CKSUM_${l_9_0_sectpuc}}$l_9_0_cksum\${NL}\"" 1>&6 rdmdel ${1+"$@"} return 1 else rdmdel ${1+"$@"} return 1 fi } rdmdocflags() { if test "X$documentedf" != "X"; then echo fi case $documentedf in *"+"*) echo "Patches marked with a \"+\" contain a non-standard README file." ;; esac case $documentedf in *"-"*) echo "Patches marked with a \"-\" are part of an n-apply patch or a patch" echo "bundle and do not have their own README file. Check the tracking bug." ;; esac case $documentedf in *"*"*) echo "Patches marked with a \"*\" do not contain a \"README.txt\" file, but" echo "may contain other installation information, such as a" echo "\"README.html\". See below for more information." ;; esac case $documentedf in *"!"*) echo "Patches marked with a \"!\" could not be properly processed. Refer" echo "to the MOPatch log file for more information." ;; esac return 0 } rdmheader() { if $MOPATCH_TEST_MIGRATE; then cat << EOF 1>&1 || return 1 Collected patch READMEs ======================= This file was generated by MOPatch on $1. It contains the collected README files of the following patches: $installed The file $2, which was generated in the same directory as this file, contains the stripped README files of these patches, which should be more readable. Please read this information carefully before installing the patches. EOF else cat << EOF 1>&1 || return 1 Collected patch READMEs ======================= This file was generated by MOPatch on $1. It contains the collected README files of the following patches: $documented `rdmdocflags` The file $2, which was generated in the same directory as this file, contains the stripped README files of these patches, which should be more readable. Please read this information carefully before installing the patches. EOF fi return 0 } rdmfooter() { return 0 } rdmsheader() { if $MOPATCH_TEST_MIGRATE; then cat << EOF 1>&1 || return 1 Stripped patch READMEs ====================== This file was generated by MOPatch on $1. It contains the collected and stripped README files of the following patches: $installed The file $2, which was generated in the same directory as this file, contains the complete, unstripped README files of these patches. This file was generated by stripping the standard, repeating portion of the patch READMEs, leaving only the patch-specific information. For completeness the standard patch README was included once immediately after this introduction. Please read the standard patch README and the patch-specific information carefully before installing the patches. Please note that the heuristics that MOPatch uses to distinguish the standard from the patch-specific information may fail in rare circumstances. If you find garbled or meaningless text in the patch-specific information below, please refer to the unstripped patch READMEs in file $2 for the full information. EOF else cat << EOF 1>&1 || return 1 Stripped patch READMEs ====================== This file was generated by MOPatch on $1. It contains the collected and stripped README files of the following patches: $documented `rdmdocflags` The file $2, which was generated in the same directory as this file, contains the complete, unstripped README files of these patches. This file was generated by stripping the standard, repeating portion of the patch READMEs, leaving only the patch-specific information. For completeness the standard patch README was appended once at the very end of this README. Please read the standard patch README and the patch-specific information carefully before installing the patches. EOF fi if $MOPATCH_TEST_MIGRATE; then cat << 'EOF' 1>&1 || return 1 Standard patch README ===================== WARNING: Failure to carefully read and understand these requirements may result in your applying a patch that can cause your Oracle Server to malfunction, including interruption of service and/or loss of data. If you do not meet all of the following requirements, please log an iTAR, so that an Oracle Support Analyst may review your situation. The Oracle analyst will help you determine if this patch is suitable for you to apply to your system. We recommend that you avoid applying any temporary patch unless directed by an Oracle Support Analyst who has reviewed your system and determined that it is applicable. Requirements: - You must have located this patch via a Bug Database entry and have the exact symptoms described in the bug entry. - Your system configuration (Oracle Server version and patch level, OS Version) must exactly match those in the bug database entry - You must have NO OTHER PATCHES installed on your Oracle Server since the latest patch set (or base release x.y.z if you have no patch sets installed). - [Oracle 9.2.0.2 & above] You must have Perl 5.00503 (or later) installed under the ORACLE_HOME, or elsewhere within the host environment. OPatch is no longer included in patches as of 9.2.0.2. Refer to the following link for details on Perl and OPatch: http://metalink.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=189489.1 - [IBM AIX O/S & Java patches for Oracle 9.2] In order to apply java class updates to IBM AIX based systems using java_131, you must update your java if you are running a version prior to Service Refresh build date 20030630a. This is necessary to fix IBM Defect#60472. To identify which java build date you are on, enter the following command ; > $ORACLE_HOME/jdk/bin/java -fullversion ... example response ... java full version "J2RE 1.3.1 IBM AIX build ca131-20030630a" The string ends in the date format YYYYMMDD or YYYYMMDDa where 'a' indicates an updated release to the original build. You should always apply the latest AIX Java SDK 1.3.1 Service Update available from IBM. As a minimum, the above service refresh can be found under APAR IY47055. The signature for the updated JVM is ca131-20030630a. Information on the latest available fixes, as well as how to apply the APARs to your AIX systems, is available at the IBM Java site. If you are running AIX 5L, you can safely ignore any comment against the APAR that says (AIXV43 only). The APAR is applicable to both AIX 4.3 and AIX 5L. Once you have updated your java installation you need to copy these updated files to Oracle's copies in $ORACLE_HOME/jdk. As the Oracle owner, simply issue the following commands; > cd /usr/java131 > cp -fpR * $ORACLE_HOME/jdk If you do NOT meet these requirements, or are not certain that you meet these requirements, please log an iTAR requesting assistance with this patch and Support will make a determination about whether you should apply this patch. Patch Installation Instructions: -------------------------------- To apply the patch, unzip the PSE container file: pNNNNNN_VVVVV_PPPPPP.zip % unzip NNNNNN.zip Set your current directory to the directory where the patch is located: % cd NNNNNN On AIX platforms only for 10201 Patches : Ensure environment variable OBJECT_MODE is set to 32_64 e.g. % setenv OBJECT_MODE 32_64 or $ export OBJECT_MODE=32_64 Ensure that the directory containing the opatch script appears in your $PATH; then enter the following command: % opatch apply Patch Special Instructions: --------------------------- Make sure all instances running under the ORACLE_HOME being patched are cleanly shutdown before installing this patch. Also ensure that the tool used to terminate the instance(s) has exited cleanly. If the Oracle inventory is not setup correctly this utility will fail. To check accessibility to the inventory you can use the command % opatch lsinventory If you have any problems installing this PSE or are not sure about inventory setup please call Oracle support. Patch Deinstallation Instructions: ---------------------------------- Use the following command: % cd NNNNNN % opatch rollback -id NNNNNN ======================================================================== The standard patch README ends here, patch-specific information follows. EOF fi return 0 } rdmsfooter() { if $MOPATCH_TEST_MIGRATE; then : else cat << 'EOF' 1>&1 || return 1 Standard patch README ===================== Patch Preinstall Steps: ----------------------- 1. For non-recommended patches, you must have the exact symptoms described in the service request (SR). 2. Verify the OUI Inventory. OPatch needs access to a valid OUI inventory to apply patches. Validate the OUI inventory with the following command: % opatch lsinventory If the command errors out, contact Oracle Support and work to validate and verify the inventory setup before proceeding. 3. Review and download the latest version of OPatch. Oracle recommends that all customers be on the latest version of OPatch. Please review the following metalink note and follow the instructions to update to the latest version if needed: https://metalink.oracle.com/metalink/plsql/ml2_documents.showNOT?p_id=224346.1 4. Confirm executables appear in your system PATH. The patching process will use the unzip and the opatch executables. After sourcing the ORACLE_HOME environment, confirm both of these exist before continuing: - "which opatch" - "which unzip" If either of these executables do not show up in the PATH, correct the problem before proceeding. 5. Create a location for storing the unzipped patch. This location will be referred to later in the document as . 6. Unzip the patch zip file into the . unzip -d p__.zip 7. Shut down services running from the ORACLE_HOME. Before applying this patch, do a clean shut down of all services running from the ORACLE_HOME. (a) In a non-RAC environment or a RAC environment with shared ORACLE_HOME: Shut down all services that are running from this ORACLE_HOME. Confirm the return status from each shutdown command to verify the shutdown is successful and there are no errors. (b) In a RAC environment with distributed ORACLE_HOMEs: For each node in the RAC system, shut down the services for the specific machine that are running from the ORACLE_HOME. OPatch will be used on each node in the RAC system one at a time. If this patch is not rolling RAC installable treat it as a non-RAC environment and shut down all services. 8. Apply pre-requisite updates. Patch Installation Steps: ------------------------- 1. Set your current directory to the directory where the patch is located. % cd / 2. Apply the patch. For an offline patch: --------------------- (a) In a non-RAC environment or a RAC environment with shared ORACLE_HOME: Use the following command to apply the patch to the ORACLE_HOME: % opatch apply (b) In a RAC environment with distributed ORACLE_HOMEs: 1. Stop instances running on node 1. 2. Run 'opatch apply /' on node 1. 3. When the apply finishes, opatch asks for confirmation before going on to apply the patch to node 2. 4. Start instances on node 1. 5. Stop instances running on node 2. 6. Ask opatch to continue to applying the patch to node 2. 7. Start instances on node 2. For an online patch: -------------------- (a) In a non-RAC environment or a RAC environment with shared ORACLE_HOME: Use the following command to apply the patch to the ORACLE_HOME: % opatch apply online -connectString ::: (b) In a RAC environment with distributed ORACLE_HOMEs: 1. Stop instances running on node 1. 2. Run 'opatch apply online -connectString :::,::: /8898589 ' on node 1. 3. When the apply finishes, opatch asks for confirmation before going on to apply the patch to node 2. When OPatch starts, it will validate the patch and make sure there are no conflicts with the software already installed in the ORACLE_HOME. OPatch categorizes two types of conflicts: (a) Conflicts with a patch already applied to the ORACLE_HOME: In this case, please stop the patch installation and contact Oracle Support Services. (b) Conflicts with subset patch already applied to the ORACLE_HOME: In this case, please continue the install, as the new patch contains all the fixes from the existing patch in the ORACLE_HOME. The subset patch will automatically be rolled back prior to the installation of the new patch. Patch Deinstallation Instructions: ---------------------------------- 1. Make sure to follow the same pre-install steps when deinstalling a patch. This includes verifying the inventory and shutting down any services running from the ORACLE_HOME / machine before rolling the patch back. 2. Change to the directory where the patch was unzipped. % cd / 3. Run OPatch to deinstall the patch. For an offline patch: --------------------- (a) In a non-RAC environment or a RAC environment with shared ORACLE_HOME: Use the following command to rollback the patch from the ORACLE_HOME: % opatch rollback -id (b) In a RAC environment with distributed ORACLE_HOMEs: 1. Stop instances running on node 1. 2. Run 'opatch rollback -id /' on node 1. 3. When the rollback finishes, opatch asks for confirmation before going on to rollback the patch to node 2. 4. Start instances on node 1. 5. Stop instances running on node 2. 6. Ask opatch to continue to rollbacking the patch to node 2. 7. Start instances on node 2. For an online patch: -------------------- (a) In a non-RAC environment: Use the following command to rollback the patch from the ORACLE_HOME: % opatch rollback -id online -connectString ::: (b) In a RAC environment: 1. Stop instances running on node 1. 2. Run 'opatch rollback -id online -connectString :::,::: /' on node 1. 3. When the rollback finishes, opatch asks for confirmation before going on to rollback the patch to node 2. EOF fi return 0 } ########## # # runmodep # ########## # run mode. One of "apply" or "doc". runmode="" # returns whether MOPatch is running in one of the specified modes. # # Implements: macro # # Variables: # $runmode # # Parameters: # runmode [runmode ...] runmodep() { for l_2_0_mode in "$@" do if test "X$l_2_0_mode" = "X$runmode"; then return 0 fi done return 1 } ################################ # # constants and global variables # ################################ # let OPatch and other tools write their messages in English. # This is really essential since we grep for certain (english) # keywords in the output generated by OPatch. LANG=C; export LANG # PD (some platforms): fix sort order LC_COLLATE=C; export LC_COLLATE # OPVD (newer versions) EMDROOT=1; export EMDROOT # keep test result filter in sync with the usage string REVISION='$Revision: 5.1.2.16 $' CRNOTICE="Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved." HEADER="MOPatch - Install Multiple Oracle Patches in One Run - 2.1.11." USAGE1="Usage: mopatch [-hvdin] [-c cleanup-freq] [-f conflict-rules]" USAGE2=" [-o opatch-param] [-j jre] [-p inv-ptr-loc]" USAGE3=" [-m make-utility] [-z unzip-utility] [-C creds]" USAGE4=" [-s patch-source-path] [patch-base]" USAGE="$USAGE1$NL$USAGE2$NL$USAGE3$NL$USAGE4" DATE=`date` STIMESTAMP=`date "+%Y%m%d%H%M%S"` LTIMESTAMP=`date "+%Y_%m_%d-%H-%M-%S"` # regexps to determine disk free space from df output DFRE='^.*[ ][ ]*[0-9][0-9]*[ ][ ]*[0-9][0-9]*[ ][ ]*[0-9][0-9]*[ ][ ]*[0-9][0-9]*%[ ][ ]*.*$' DFSE='^.*[ ][ ]*[0-9][0-9]*[ ][ ]*[0-9][0-9]*[ ][ ]*\([0-9][0-9]*\)[ ][ ]*[0-9][0-9]*%[ ][ ]*\(.*\)$' # regepxs to extract information from lsinventory output. PD # (sunos_*): "sed" does not properly handle quantifiers on # sub-expressions, so do not try to combine "PATCHINVSE" and # "PSUINVSE" into one regular expression. PATCHINVEE='^Patch(set[ ][ ]*Update|[ ][ ]*\(online\))?[ ][ ]*[0-9][0-9]*[ ]*:' PATCHINVSE='^Patch[ ][ ]*\([0-9][0-9]*\)[ ]*:.*$' PSUINVSE='^Patchset[ ][ ]*Update[ ][ ]*\([0-9][0-9]*\)[ ]*:.*$' PTCHONLNINVSE='^Patch[ ][ ]*(online)[ ][ ]*\([0-9][0-9]*\)[ ]*:.*$' # printf format specifier and regexp for link script maintenance LINKSCRIPTGENFS='( cd "%s/%s" && cat "%s" 1>/dev/null && "%s" -f "%s" %s ORACLE_HOME="%s" ) || exit $?\n' LINKSCRIPTVERFS='^( cd "%s/.*" && cat ".*" 1>/dev/null && ".*" -f ".*" .* ORACLE_HOME="%s" ) || exit \\$?$\n' # set to one of "true" or "false". Remove this variable and all # references to it after migrating the test results. Also remove # it as a built-in from the syntax checker. (incomplete) MOPATCH_TEST_MIGRATE=${MOPATCH_TEST_MIGRATE-false} export MOPATCH_TEST_MIGRATE # warnings to be ignored. Newline-list of either 5-digit OUI # error codes or (un-anchored) regexps matching the first line of # the warning to be ignored. wtbis="" # make targets to be ignored. Blank-list of make targets to be # ignored. # # The targets "igenlibociicus" and "igenlibociei" may trigger # C-compiler invocation. The targets ipc_* may modify customer # settings. mttbis="igenlibociicus igenlibociei ipc_none ipc_udp ipc_g ipc_rds ipc_relink " # temp file name tfn="" if test "X$RANDOM" = "X$RANDOM"; then tfn="mopatch-$STIMESTAMP-$$" else tfn="mopatch-$RANDOM-$$" fi # option and parameter variables dryrun=0 ilink=0 nomake=0 flags="" # most come early cufr=0 # clean-up frequency crrules="" opatchopts="-silent" jre="" invptrloc="" make="" unzip="" onlnmode=0 patchsrcpath="" pspspp=0 # patch source path specified timeout=20 xlogfile="" reserve=0 patchdir="" uspltf="" # user-specified platform opatchveropts="" opatchlsiopts="-retry 0" opatchcuopts="-silent -force" # flags. Most of them are relevant for development and testing # only. Use only when you know what you are doing. # # local_opatch # add the "-local" option to all OPatch calls # 5117016_check # PD, DBVD (sunos_sun4u, 10.2.0.2.0): check for mandatory patch # 5117016 # sol10_ar_check # PD (sunos_* 5.10): check for ar problems # ignore_installed # ignore installed patches in documentation mode # ignore_warnings # ignore warnings known to be uncritical # ignore_makes # ignore make targets known to be critical # ignore_ubps # ignore certain unbundled patches # free_space_check # check for sufficient patch storage free space # free_space_log # write patch storage free space to log file # readme_strip_log # write information on readme stripping to log file # apply_napply # apply n-apply patches # apply_cpu # apply critical patch updates # apply_psu # apply patchset updates # stress_test # ensure deterministic operation for stress tests # clean_up # call "opatch util cleanup" when required # clean_up_final # call "opatch util cleanup" after complete installation # clean_up_tmpdir # clean up temporary directory after execution flag_local_opatch=1 flag_5117016_check=1 flag_sol10_ar_check=1 flag_ignore_installed=0 flag_ignore_warnings=1 flag_ignore_makes=1 flag_ignore_ubps=1 flag_free_space_check=1 flag_free_space_log=0 flag_readme_strip_log=0 flag_apply_napply=1 flag_apply_cpu=1 flag_apply_psu=1 flag_stress_test=0 flag_clean_up=1 flag_clean_up_final=1 flag_clean_up_tmpdir=1 ######################################### # # parse and verify options and parameters # ######################################### # keep for later oargv="" if test $# = 0; then oargv=$0 else oargv="$0 $*" fi # verify and read rc file # begin clitest (4.189) mopatchrcfile="" if test "X$ORACLE_HOME" != "X" && test -f "$ORACLE_HOME/.mopatchrc"; then if cat "$ORACLE_HOME/.mopatchrc" 1>/dev/null 2>&1; then : else usage "Invalid MOPatch rc file \"$ORACLE_HOME/.mopatchrc\" specified." fi mopatchrcfile=`cat "$ORACLE_HOME/.mopatchrc" | grep -v '^[ ]*$' | grep -v '^[ ]*#'` # eliminate newlines mopatchrcfile=`l_oldifs=$IFS; IFS="$NL"; set -f; set x $mopatchrcfile; shift; set +f; IFS=$l_oldifs; printf '%s\n' "$*"` fi # verify and read rc variable mopatchrcenv="" if test "X$MOPATCHRC" != "X"; then if mlp "$MOPATCHRC"; then usage "Invalid MOPatch rc variable \"MOPATCHRC\" specified (contains newline characters)." fi mopatchrcenv=$MOPATCHRC fi # verify commandline for parameter in ${1+"$@"} do if mlp "$parameter"; then usage "Invalid parameter \"$parameter\" specified (contains newline characters)." fi done # include rc file and variable into commandline set x $mopatchrcfile $mopatchrcenv ${1+"$@"} shift while getopts :vdinlF:c:f:o:j:p:m:z:C:s:T:L:R:P: c; do case $c in v) verbosep=1 ;; d) dryrun=1 ;; i) ilink=1 ;; n) nomake=1 ;; l) : ;; # keep for backward compatibility F) flags="$flags $OPTARG" ;; c) cufr=$OPTARG ;; f) # note that even with an empty option argument this # variable gets non-empty! crrules="$crrules $OPTARG" ;; o) # verify this here since later we loose all information on # containing whitespace if mwp "$OPTARG"; then usage "Invalid OPatch option \"$OPTARG\" specified (contains whitespace)." fi case $OPTARG in -oh|-jre|-jdk|-invPtrLoc) usage "Invalid OPatch option \"$OPTARG\" specified (conflicts with MOPatch)." ;; esac opatchopts="$opatchopts $OPTARG" ;; j) jre=$OPTARG ;; p) invptrloc=$OPTARG ;; m) make=$OPTARG ;; z) unzip=$OPTARG ;; C) onlnmode=1 opatchopts="$opatchopts -connectString $OPTARG" ;; s) if test $pspspp = 0; then patchsrcpath=$OPTARG pspspp=1 else patchsrcpath="$patchsrcpath:$OPTARG" fi ;; T) timeout=$OPTARG ;; L) xlogfile=$OPTARG ;; R) reserve=$OPTARG ;; P) uspltf=$OPTARG ;; *) cat << EOF 1>&2 Invalid or incomplete option specified. $USAGE MOPatch uses the patch source path to look up the packed patches to be installed. MOPatch uses the patch base directory patch-base as installation stage and working directory. If not specified, it defaults to the current directory. Options: -h show a short command-line overview. See readme.txt under \$ORACLE_HOME/MOPatch or SAP note 1027012 for complete documentation. -v be verbose; produce more diagnostic output -d extract patch documentation -i link immediately; do not defer until complete patch installation -n do not link after complete patch installation; create link script only. Ignored with option -i. -c cleanup-freq clean up the internal OPatch patch storage after applying the specified number of patches. If zero, clean up only if required. Defaults to zero. Patch storage clean-up is available only with sufficiently recent OPatch versions. -f conflict-rules resolve conflicts according to the specified rules. Available rules are "old" (keep installed patch in case of conflicts), "new" (apply new patch), "cpu" (favor CPU or CPU molecule if it conflicts with a non-CPU patch), "psu" (favor PSU if it conflicts with a non-PSU patch), or an integer patch ID (keep or apply that patch if it conflicts with another patch). The rules must be specified as a comma-separated list. They default to "psu,new". -o opatch-param pass the specified parameter verbatim to OPatch. To pass an option like "-delay 10" to OPatch, specify two options to MOPatch: "-o -delay -o 10". There must be no whitespace inside the parameter. There must be no "-oh", "-jre", "-jdk", or "-invPtrLoc" OPatch option among the specified parameters. -j jre pass the specified Java Runtime Environment to all OPatch calls -p inv-ptr-loc pass the specified inventory pointer location to all OPatch calls. There must be no whitespace inside inv-ptr-loc. Defaults to \$ORACLE_HOME/oraInst.loc if that file exists and if it points to a valid inventory. -m make-utility use the specified make utility to build the Oracle executable and shared libraries after applying patches. Ignored with option -i. Defaults to "/usr/ccs/bin/make" or "/usr/bin/make", if one of those exists, or otherwise to the first executable named "make" that is found in PATH. -z unzip-utility use the specified unzip utility to unpack patches. Defaults to \$ORACLE_HOME/bin/unzip, if that exists, or otherwise to the first executable named "unzip" that is found in PATH. -s patch-source-path use the specified path to look up the patches to be installed. May be specified more than once. Defaults to the patch base directory. The patch source path must be a colon-separated list of packed patch files or directories containing packed patch files. This utility requires environment variable ORACLE_HOME to be set. $HEADER $CRNOTICE EOF exit 2 ;; esac done # PD (osf1_alpha): check for non-Posix "/bin/sh" if test "X${OPTIND-}" = "X"; then error "Cannot use non-Posix /bin/sh. On Tru64, use /usr/bin/posix/sh." fi # shift may not be portable i=$OPTIND while test $i -gt 1; do i=`expr $i - 1` shift done # determine run mode runmode="" if test $dryrun = 0; then runmode="apply" else runmode="doc" fi # verify and set flags oldifs=$IFS IFS=", $TAB$NL" for flag in $flags do # generously ignore empty flags which may have been introduced # by strange word splitting rules if test "X$flag" = "X"; then continue fi # word splitting eliminated newlines flagvalue="" if expr "X$flag" : 'X!.*$' 1>/dev/null; then flag=`expr "X$flag" : 'X!\(.*\)$'` flagvalue=0 else flagvalue=1 fi # verify and set flag if varnamep "$flag" && flagvar="flag_$flag" && eval test '"X${'"$flagvar"'+X}"' = '"XX"'; then eval "$flagvar"='$flagvalue' else usage "Invalid flag \"$flag\" specified." fi done IFS=$oldifs if runmodep "apply" && test $flag_ignore_installed = 1; then usage "Invalid flag \"ignore_installed\" in apply mode specified." fi # verify clean-up frequency if numberp "$cufr"; then : else usage "Invalid clean-up frequency \"$cufr\" specified." fi # end clitest (4.189) # determine and verify conflict resolution rules if test "X$crrules" = "X"; then crrules="psu new" fi oldifs=$IFS IFS=", $TAB$NL" for crrule in $crrules do case $crrule in # generously ignore empty splitting rules "") : ;; old|new|psu|cpu) : ;; *) if numberp "$crrule"; then : else usage "Invalid conflict resolution rule \"$crrule\" specified." fi ;; esac done IFS=$oldifs # calculate and verify OPatch options if test $verbosep = 1; then opatchopts="$opatchopts -verbose" fi if test $ilink = 0; then opatchopts="$opatchopts -no_relink" fi if test $flag_local_opatch = 1; then # OPVD (>= 10.2.0.2.4): do not add option "-local" to # opatchlsiopts, since "opatch lsinventory" rejects it opatchopts="$opatchopts -local" opatchcuopts="$opatchcuopts -local" fi if test "X$jre" != "X"; then if mwp "$jre"; then usage "Invalid Java Runtime Environment \"$jre\" specified (contains whitespace)." fi if test -d "$jre"; then : else usage "Invalid Java Runtime Environment \"$jre\" specified (no such directory)." fi if test -f "$jre/bin/java"; then : else usage "Invalid Java Runtime Environment \"$jre\" specified (no \"java\" executable)." fi opatchopts="$opatchopts -jre $jre" opatchveropts="$opatchveropts -jre $jre" opatchlsiopts="$opatchlsiopts -jre $jre" opatchcuopts="$opatchcuopts -jre $jre" fi if test "X$invptrloc" != "X"; then if mwp "$invptrloc"; then usage "Invalid inventory pointer location \"$invptrloc\" specified (contains whitespace)." fi opatchopts="$opatchopts -invPtrLoc $invptrloc" opatchlsiopts="$opatchlsiopts -invPtrLoc $invptrloc" opatchcuopts="$opatchcuopts -invPtrLoc $invptrloc" elif test "X$ORACLE_HOME" != "X" && swp "$ORACLE_HOME" && test -f "$ORACLE_HOME/oraInst.loc"; then # check whether $ORACLE_HOME/oraInst.loc is a valid inventory # pointer. Use it, if this is the case. Otherwise, silently # do nothing. invptrloc="$ORACLE_HOME/oraInst.loc" inv=`grep '^[ ]*inventory_loc[ ]*=[ ]*/.*$' "$invptrloc" 2>/dev/null | sed 's/^[ ]*inventory_loc[ ]*=[ ]*//' 2>/dev/null` if test "X$inv" != "X" && test -d "$inv" && test -f "$inv/ContentsXML/inventory.xml"; then invxml="$inv/ContentsXML/inventory.xml" ohre=`printf '%s\n' "$ORACLE_HOME" | quotemeta -x 2>/dev/null` # this regexp could be more relaxed w.r.t. whitespace, but # better keep it readable than perfect if egrep '' "$invxml" 1>/dev/null 2>&1; then opatchopts="$opatchopts -invPtrLoc $invptrloc" opatchlsiopts="$opatchlsiopts -invPtrLoc $invptrloc" opatchcuopts="$opatchcuopts -invPtrLoc $invptrloc" fi fi fi if test $ilink = 0; then # determine and verify make utility if test "X$make" = "X"; then if test -x "/usr/ccs/bin/make"; then make="/usr/ccs/bin/make" elif test -x "/usr/bin/make"; then make="/usr/bin/make" else oldifs=$IFS IFS=: for path in $PATH do if test -x "$path/make"; then make="$path/make" break fi done IFS=$oldifs fi fi if test "X$make" = "X"; then usage "No make utility found or specified." elif test ! -x "$make"; then usage "Invalid make utility \"$make\" found or specified." fi fi # determine and verify unzip utility. Prefer unzip from Oracle # Home. if test "X$unzip" = "X" && test "X$ORACLE_HOME" != "X" && test -x "$ORACLE_HOME/bin/unzip"; then unzip="$ORACLE_HOME/bin/unzip" fi if test "X$unzip" = "X"; then oldifs=$IFS IFS=: for path in $PATH do if test -x "$path/unzip"; then unzip="$path/unzip" break fi done IFS=$oldifs fi if test "X$unzip" = "X"; then usage "No unzip utility found or specified." elif "$unzip" 1>/dev/null; then : else usage "Invalid unzip utility \"$unzip\" found or specified." fi # verify "df" loop timeout and file system reserve if numberp "$timeout" && test $timeout -gt 0; then : else usage "Invalid df loop timeout \"$timeout\" specified." fi if numberp "$reserve"; then : else usage "Invalid file system reserve \"$reserve\" specified." fi # verify user-specified platform if test "X$uspltf" = "X" || platforminfof "$uspltf" 1>/dev/null 2>&1 3>&1; then : else usage "Invalid platform ID \"$uspltf\" specified." fi # determine and verify patch base directory patchdir="" if test $# -gt 1; then shift usage "Extra parameters specified: $*" elif test $# -eq 1; then patchdir=$1 else patchdir=. fi if test "X$patchdir" != "X" && test -d "$patchdir" && touch "$patchdir/$tfn" && rm -f "$patchdir/$tfn" && ( cd "$patchdir" && ls 1>/dev/null ); then : else usage "Invalid or inaccessible patch base directory \"$patchdir\" specified." fi # default patch source directory to patch base directory. # Variable "$patchsrctype" is used in messages to identify origin # of problems. Thanks to the above tests, errors with respect to # the patch base directory may occur only in the "test -d" branch # in the below "for" loop. patchsrctype="" if test $pspspp = 0; then patchsrcpath=$patchdir patchsrctype="patch base directory" else patchsrctype="patch source directory" fi # verify patch source (or base) directory. Note that # "$patchsrcpath" is not necessarily a colon-list, so be careful # when splitting. As a side-effect of the below verification, # all items of the source path are guaranteed to be newline-free. l_oldifs=$IFS; IFS=":"; set -f; set x $patchsrcpath; shift; set +f; IFS=$l_oldifs if test $# = 0; then usage "Invalid patch source path \"$patchsrcpath\" specified (contains empty items)." fi # determine wether the patch source path is a singleton. Needed # to calculate the patch basenames later. pspstp="" if test $# = 1; then pspstp=1 else pspstp=0 fi ppfp=0 # packed patches found uppfp=0 # unpacked patches found for item in "$@" do if test "X$item" = "X"; then usage "Invalid patch source path \"$patchsrcpath\" specified (contains empty items)." elif test -f "$item"; then if pmddirp "$item"; then : else usage "Invalid patch source file \"$item\" specified (contains strange characters)." fi if cat "$item" 1>/dev/null; then : else usage "Invalid or inaccessible patch source file \"$item\" specified." fi # assume any user-specified file to be a packed patch ppfp=1 elif test -d "$item"; then if pmddirp "$item"; then : else usage "Invalid $patchsrctype \"$item\" specified (contains strange characters)." fi if ( cd "$item" && ls 1>/dev/null ); then : else usage "Invalid or inaccessible $patchsrctype \"$item\" specified." fi # heuristically check whether an unpacked patch was specified # as patch source directory if test $pspspp = 1 && # the former should find one-offs, the latter CPUs and # other n-apply patches globtest -f "$item/etc/config/inventory" \ "$item/etc/config/inventory.xml" \ "$item/etc/config/actions " \ "$item/etc/config/actions.xml" \ "$item/patchmd.xml"; then usage "Invalid patch source directory \"$item\" specified (contains an unpacked patch)." fi # heuristically check for the existence of unpacked patches if globtest -f "$item"/[0-9]*[0-9]/etc/config/inventory \ "$item"/[0-9]*[0-9]/etc/config/inventory.xml \ "$item"/[0-9]*[0-9]/etc/config/actions \ "$item"/[0-9]*[0-9]/etc/config/actions.xml \ "$item"/[0-9]*[0-9]/[0-9]*[0-9]/etc/config/inventory \ "$item"/[0-9]*[0-9]/[0-9]*[0-9]/etc/config/inventory.xml \ "$item"/[0-9]*[0-9]/[0-9]*[0-9]/etc/config/actions \ "$item"/[0-9]*[0-9]/[0-9]*[0-9]/etc/config/actions.xml; then uppfp=1 fi # find and verify all packed patches for patchsrc in \ "$item"/[pP][0-9][0-9][0-9][0-9][0-9][0-9]*.[zZ][iI][pP] \ "$item"/SAP_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP] \ "$item"/SGR_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP] \ "$item"/SXD_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP] do if test "X$patchsrc" != "X$item/[pP][0-9][0-9][0-9][0-9][0-9][0-9]*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/SAP_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/SGR_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/SXD_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP]"; then ppfp=1 if pmddirp "$patchsrc"; then : else usage "Invalid $patchsrctype \"$item\" specified (patch \"$patchsrc\" contains strange characters)." fi fi done else usage "Invalid patch source path item \"$item\" specified (neither file nor directory)." fi done # check for packed patches if test $pspspp = 0; then patchsrctype="patch base directory" else patchsrctype="patch source path" fi if test $ppfp = 0 && test $uppfp = 1; then usage "Invalid $patchsrctype \"$patchsrcpath\" specified (contains unpacked patches only)." elif test $ppfp = 0; then usage "Invalid $patchsrctype \"$patchsrcpath\" specified (does not contain any packed patches)." fi # verify Oracle Home if test "X$ORACLE_HOME" = "X"; then usage "No Oracle Home specified." fi opatch="$ORACLE_HOME/OPatch/opatch" if test ! -d "$ORACLE_HOME"; then usage "Invalid Oracle Home \"$ORACLE_HOME\" specified (not a directory)." elif test ! -d "$ORACLE_HOME/OPatch" || test ! -d "$ORACLE_HOME/OPatch/jlib" || test ! -x "$opatch"; then usage "Invalid Oracle Home \"$ORACLE_HOME\" specified (no appropriate OPatch found)." elif touch "$ORACLE_HOME/$tfn" && rm -f "$ORACLE_HOME/$tfn"; then : else usage "Invalid Oracle Home \"$ORACLE_HOME\" specified (unwritable)." fi case $ORACLE_HOME in */) usage "Invalid Oracle Home \"$ORACLE_HOME\" specified (trailing slash)." ;; esac ############################################# # # miscellaneous validation and initialization # ############################################# # clean-up trap. Gets successively extended as there is more to # clean up. cutrap=":" # create PID file pidfile="$ORACLE_HOME/.mopatchpid" if test -f "$pidfile"; then error "Cannot start MOPatch (already running according to PID file \"$pidfile\")." elif echo $$ 1>"$pidfile"; then cutrap="$cutrap;"'rm -f "$pidfile"' trap "$cutrap" 0 else error "Cannot create PID file \"$pidfile\"." fi # seems that the clean-up trap does not get called at signals # without the following trap 'exit 2' 1 2 3 15 # prepare for handling user interrupts signalled=0 trap 'signalled=1; cmdlineerror=1' USR1 # save TTY state and disable ^C as interrupt if in apply mode. # Do not be too picky if the "stty" calls fail. if runmodep "apply"; then ttys=`stty -g 2>/dev/null` stty "intr" "^-" 1>/dev/null 2>&1 cutrap="$cutrap;"'test "X$ttys" != "X" && stty "$ttys"' trap "$cutrap" 0 fi # determine and create patch storage test file used for calls to # "df". Be careful here since the patch storage may not exist # yet and since there may be all kinds of symbolic links and # stuff. Customers annoyed by the growing patch storage may have # moved it out of the volume holding the Oracle Home. pstf="" if test -d "$ORACLE_HOME/.patch_storage"; then pstf="$ORACLE_HOME/.patch_storage/$tfn-pstf" else pstf="$ORACLE_HOME/$tfn-pstf" fi if touch "$pstf"; then cutrap="$cutrap;"'rm -f "$pstf"' trap "$cutrap" 0 else error "Cannot create patch storage test file \"$pstf\"." fi # test for non-empty link script linkscript="$patchdir/link.sh" lsne="" # link script non-empty if test -s "$linkscript"; then lsne=1 else lsne=0 fi # verify existing link script if test $ilink = 0 && test $lsne = 1; then ohre=`printf '%s\n' "$ORACLE_HOME" | quotemeta` linkre=`printf "$LINKSCRIPTVERFS" "$ohre" "$ohre"` if grep -v "$linkre" "$linkscript"; then error "Cannot verify link script \"$linkscript\" (probably different Oracle Home)." fi fi # open link script for appending, if required. Open it even in # documentation mode, but do not change it at all. if test $ilink = 0; then if ( exec 4>>"$linkscript" && exec 4>&- ) && exec 4>>"$linkscript"; then : else error "Cannot open link script \"$linkscript\" for appending." fi fi cutrap="$cutrap;"'test -s "$linkscript" || rm -f "$linkscript"' trap "$cutrap" 0 # open the readme collection and the stripped readme collection # in documentation mode readmecoll="$patchdir/READMES-$LTIMESTAMP.txt" readmescoll="$patchdir/READMES-STRIPPED-$LTIMESTAMP.txt" if runmodep "doc"; then if ( exec 8>"$readmecoll" && exec 8>&- ) && exec 8>"$readmecoll"; then : else error "Cannot open readme collection \"$readmecoll\" for writing." fi cutrap="$cutrap;"'test -s "$readmecoll" || rm -f "$readmecoll"' trap "$cutrap" 0 if ( exec 9>"$readmescoll" && exec 9>&- ) && exec 9>"$readmescoll"; then : else error "Cannot open stripped readme collection \"$readmescoll\" for writing." fi cutrap="$cutrap;"'test -s "$readmescoll" || rm -f "$readmescoll"' trap "$cutrap" 0 fi # create a temporary directory tmpdir="" { tmpdir=`( umask 077 && mktemp -d "$patchdir/mopatch-XXXXXX" ) 2>/dev/null` && test "X$tmpdir" != "X" && test -d "$tmpdir" } || { tmpdir="$patchdir/$tfn-tmpdir" ( umask 077 && mkdir "$tmpdir" ) } || { error "Cannot create temporary directory \"$tmpdir\"." } cutrap="$cutrap;"'test $flag_clean_up_tmpdir = 1 && rm -rf "$tmpdir"' trap "$cutrap" 0 # create patch staging directory patchstage="$tmpdir/stage" if mkdir "$patchstage"; then : else error "Cannot create patch staging directory \"$patchstage\"." fi # the following writes information to the log file. Add an empty # line to set it off from our header. (incomplete) log 3>/dev/null # determine platform information (incomplete) platforminfo="" if test "X$uspltf" = "X"; then if platforminfo=`platforminfof 3>/dev/null`; then : else error "Cannot determine platform information." fi else platforminfo=`platforminfof "$uspltf" 3>/dev/null` fi l_oldifs=$IFS; IFS=" "; set -f; set x $platforminfo; shift; set +f; IFS=$l_oldifs platform=$1 kernelver=$4 # determine Oracle RDBMS version (incomplete) if rdbmsversion=`rdbmsversionf 3>/dev/null`; then : else error "Cannot determine Oracle RDBMS version." fi l_oldifs=$IFS; IFS=" "; set -f; set x $rdbmsversion; shift; set +f; IFS=$l_oldifs rdbmsver=$1 rdbmsnver=$2 rdbmsmver=$3 # determine OPatch version and feature support (incomplete) if opversion=`opversionf $opatchveropts 3>/dev/null`; then : else error "Cannot determine OPatch version and feature support." fi l_oldifs=$IFS; IFS=" "; set -f; set x $opversion; shift; set +f; IFS=$l_oldifs opver=$1 opnver=$2 eval "cusp=\${$OPVERSION_CUSP-}" eval "xmlinvp=\${$OPVERSION_XMLINVP-}" eval "psusp=\${$OPVERSION_PSUSP-}" # OPVD (early versions): verify "correct" XML inventory support if test $xmlinvp = 0; then error "Cannot run with OPatch version \"$opver\". Please update." fi # determine Oracle Home type ohtype="" if test -d "$ORACLE_HOME/inventory/Components21/oracle.crs"; then ohtype="gi" else ohtype="rdbms" fi # determine options to execute "df" dfopts="" if df -Pk "$pstf" 1>/dev/null 2>&1; then # require Posix-output if available ... dfopts="-Pk" else # ... otherwise hope for something similar dfopts="-k" fi # determine patch storage free space. Be even more careful here # since "df" has a very different output format across different # flavors of Unices. If something goes wrong, do not error out # but fall back to not taking into account patch storage free # space at all. # # If flag psfsps flips to false (here or later), then # - do not use the value of variables psfsp, ppsfsp, or psmp in # any way and # - do not try to re-calculate psfsp or ppsfsp. # # Similarly for flag psrsps and variables lss and psrsp. # # Working with disk free space involves numbers that may be too # large for the standard "expr" and "test" utilities. We have to # use "dc" for these calculations and comparisons. For our own # reference those "dc" relational operators that are portable: # # nm>a if m > n or n < m then a # nm m then a psfsp=`df $dfopts "$pstf" | grep "$DFRE" | sed 's/'"$DFSE"'/\1/'` ppsfsp="" # previous patch storage free space psmp="" # patch storage mount point psfsps="" # patch storage free space is secure if numberp "$psfsp"; then # take file system reserve into account if test $reserve != 0; then # d := max( 0, psfsp - reserve ) d=`echo "0k[0]sa $psfsp $reserve-d0>apq" | dc` if numberp "$d"; then psfsp=$d else # this should not normally happen so it is OK to simply # error out here error "Cannot calculate \"$d\" as max( 0, $psfsp - $reserve )." fi fi ppsfsp=0 psmp=`df $dfopts "$pstf" | grep "$DFRE" | sed 's/'"$DFSE"'/\2/'` psfsps=1 else logerr "Cannot determine patch storage free space from \"$psfsp\"." psfsp=0 ppsfsp=0 psmp="" psfsps=0 fi # determine size of libserver.a lss=`du -k "$ORACLE_HOME/lib/libserver${rdbmsmver}.a" | grep '^[0-9][0-9]*[ ][ ]*.*$' | sed 's/^\([0-9][0-9]*\)[ ][ ]*.*$/\1/'` psrsp="" # patch storage required space psrsps="" # patch storage required space is secure if numberp "$lss"; then # double size of libserver.a to determine disk space required # in the patch storage for installation of one patch psrsp=`expr $lss + $lss` psrsps=1 else logerr "Cannot determine size of \"$ORACLE_HOME/lib/libserver${rdbmsmver}.a\" from \"$lss\"." lss=0 psrsp=0 psrsps=0 fi # determine "df" loop count and sleep interval. Give smart OSs a # chance to react faster in "df" loops. dfloop="" dfslpi="" if sleep 0.5 1>/dev/null 2>&1 && test $flag_stress_test = 0; then dfloop=`expr $timeout + $timeout` dfslpi=0.5 else dfloop=$timeout dfslpi=1 fi # determine non-traditional "awk" interpreter awk="" for exec in "gawk" "mawk" "nawk" "awk" do if ( "$exec" -v foo=bar '{}' 0/dev/null 2>&1; then awk=$exec break; fi done if test "X$awk" = "X"; then error "Cannot find non-traditional \"awk\" interpreter." fi ################################################## # # open log file and write some initial information # ################################################## logdir="$ORACLE_HOME/cfgtoollogs/mopatch" if test -d "$logdir" || mkdir "$logdir"; then : else error "Cannot create log directory \"$logdir\"." fi if test "X$xlogfile" = "X"; then logfile="$logdir/mopatch-$LTIMESTAMP.log" if ( exec 3>"$logfile" && exec 3>&- ) && exec 3>"$logfile"; then : else error "Cannot open log file \"$logfile\" for writing." fi else logfile=$xlogfile fi logopen=1 logerrhdl=3 # brush up log file name which from here is used only in messages logfile=`echo "$logfile" | sed 's/^.*\/cfgtoollogs\//$ORACLE_HOME\/cfgtoollogs\//' 2>&3` # brush up revision revision=`printf '%s\n' "$REVISION" | sed 's/^\$Revisio[n]: //;s/ \$$//' 2>&3` # write our header before doing anything else out "$HEADER" out "$CRNOTICE" # write some diagnostic information verbose verbose "Version: 2.1.11" verbose "Revision: $revision" verbose "Command-line: $oargv" verbose verbose "Oracle Home: $ORACLE_HOME" verbose "RDBMS version: $rdbmsver" verbose "OPatch version:$opver" if test $cusp = 1; then verbose "Clean-up: supported" else verbose "Clean-up: not supported" fi if $MOPATCH_TEST_MIGRATE; then : else if test $psusp = 1; then verbose "PSUs: supported" else verbose "PSUs: not supported" fi fi verbose "Log file: $logfile" verbose "Patch base: $patchdir" verbose "Patch source: $patchsrcpath" if test $ilink = 0; then verbose "Link script: $linkscript" else verbose "Link script: " fi if runmodep "doc"; then verbose "Readmes: $readmecoll" verbose "Strpd. Readmes:$readmescoll" else verbose "Readmes: " verbose "Strpd. Readmes:" fi if test $ilink = 0; then verbose "make utility: $make" else verbose "make utility: " fi verbose "unzip utility: $unzip" if test $verbosep = 0; then rawout rawout "Log file: $logfile" fi verbose verbose "User name: $LOGNAME" pwd=`pwd 2>&3` verbose "Working dir: $pwd" uname=`uname -a 2>&3` verbose "System: $uname" if test $psfsps = 1; then verbose "Disk free: $psfsp KBytes on $psmp" else verbose "Disk free: " fi if test $psfsps = 1 && test $psrsps = 1; then verbose "Disk required: $psrsp KBytes on $psmp" else verbose "Disk required: " fi if test $ilink = 0 && test $lsne = 1; then verbose verbose "Re-using previous link script \"$linkscript\"." fi ########################################################### # # get pre-run patch inventory and analyze installed patches # ########################################################### out out "Getting pre-run patch inventory..." preinvlog="$tmpdir/preinv.log" preinvxml="$tmpdir/preinv.xml" preinvawk="$tmpdir/preinv.awk" preinvsh="$tmpdir/preinv.sh" log "executing: \"$opatch\" lsinventory $opatchlsiopts -xml \"$preinvxml\"" if "$opatch" lsinventory $opatchlsiopts -xml "$preinvxml" 1>"$preinvlog" 2>&1; then cat "$preinvlog" 1>&3 2>&1 out "Getting pre-run patch inventory...done." else cat "$preinvlog" 1>&3 2>&1 out "Getting pre-run patch inventory...failed." error -c opatcherror "Cannot get pre-run patch inventory." fi # newline-list of the CPU molecules listed in the rollback.lst # files under $ORACLE_HOME/cpu. We'll add that information to # the inventory manually. cpurlbs="" if globtest -f "$ORACLE_HOME"/cpu/*/rollback_*.lst; then cpurlbs=`cat "$ORACLE_HOME"/cpu/*/rollback_*.lst 2>&3 | tr ',' '\012' 2>&3 | sed '/^[^0-9]*$/d;/[0-9][^0-9][0-9]/d;s/^[^0-9]*\([0-9][0-9]*\)[^0-9]*$/\1/' 2>&3 | sort 2>&3 | uniq 2>&3` fi if test $signalled = 1; then error -c cmdlineerror "Interrupted." fi if $MOPATCH_TEST_MIGRATE; then : else verbose verbose "Analyzing installed patches..." fi # determine installed patches from log file iplog=`egrep "$PATCHINVEE" "$preinvlog" 2>&3 | sed 's/'"$PATCHINVSE"'/\1/;s/'"$PSUINVSE"'/\1/;s/'"$PTCHONLNINVSE"'/\1/' 2>&3 | sort -n 2>&3` # create awk script to augment inventory agminvawk="$tmpdir/agminv.awk" if ( exec 6>"$agminvawk" && exec 6>&- ) 1>&3 2>&1 && exec 6>"$agminvawk"; then : else verbose "Analyzing installed patches...failed." error "Cannot open inventory augmentation awk script \"$agminvawk\" for writing." fi echo "{ print; }" 1>&6 l_oldifs=$IFS; IFS="$NL"; set -f; set x $iplog; shift; set +f; IFS=$l_oldifs for patchid in ${1+"$@"} do # newline-terminated augmentation data agmdata="" if memberp "$NL" $patchid "$cpurlbs"; then agmdata="$agmdatatrue$NL" fi # this is an ugly hack. OPatch does not provide the complete # information in the XML generated by option "-xml", so we have # to look up that information in the "raw" inventory patchinvxml="" if test -f "$ORACLE_HOME/inventory/oneoffs/$patchid/etc/config/inventory.xml"; then patchinvxml="$ORACLE_HOME/inventory/oneoffs/$patchid/etc/config/inventory.xml" elif test -f "$ORACLE_HOME/inventory/oneoffs/$patchid/etc/config/inventory"; then patchinvxml="$ORACLE_HOME/inventory/oneoffs/$patchid/etc/config/inventory" else verbose "Analyzing installed patches...failed." error "Cannot find raw patch inventory file for patch $patchid." fi prqovls=`egrep '^[ ]*<(prereq|overlay) oneoff_id="[0-9][0-9]*"/>[ ]*$' "$patchinvxml" 2>&3` if test "X$prqovls" != "X"; then agmdata="$agmdata$prqovls$NL" fi if test "X$agmdata" != "X"; then printf '%s\n' '/^[ ]*[ ]*$/ {' 1>&6 printf '%s' "$agmdata" | sed -e 's/\([\\"]\)/\\\1/g;s/^.*$/ print "&";/' 1>&6 printf '%s\n' "}" 1>&6 fi done exec 6>&- if test -s "$agminvawk"; then preinvtmp="$preinvxml.tmp" if "$awk" -f "$agminvawk" "$preinvxml" 1>"$preinvtmp" 2>&3 && mv "$preinvtmp" "$preinvxml" 1>&3 2>&1; then : else verbose "Analyzing installed patches...failed." error "Cannot augment pre-run patch inventory." fi fi unset cpurlbs # create awk script to parse patch metadata cat << 'EOF' 1>"$preinvawk" 2>&3 || BEGIN { for ( i in XML_GES ) delete XML_GES[i]; XML_GES["&"] = "&"; XML_GES["<"] = "<"; XML_GES[">"] = ">"; XML_GES["'"] = "'"; XML_GES["""] = "\""; } function chop( s ) { return substr( s, 1, length( s ) - 1 ); } function squote( s, qs, b ) { qs = ""; b = 0; while ( b = index( s, "'" ) ) { qs = qs substr( s, 1, b - 1 ) "'\\''"; s = substr( s, b + 1 ); } return qs s; } function aquote( s, qs ) { qs = ""; while ( match( s, /[\\"]/ ) ) { qs = qs substr( s, 1, RSTART - 1 ) "\\" substr( s, RSTART, 1 ); s = substr( s, RSTART + 1 ); } return qs s; } function xunquote( s, uqs, b ) { uqs = ""; while ( b = index( s, "&" ) ) { uqs = uqs substr( s, 1, b - 1 ); s = substr( s, b ); if ( match( s, /^&(amp|[lg]t|apos|quot);/ ) ) { uqs = uqs XML_GES[substr( s, 1, RLENGTH )]; s = substr( s, RLENGTH + 1 ); } else { uqs = uqs "&"; s = substr( s, 2 ); } } return uqs s; } function sort( s, a, v, n, i, j ) { n = split( s, a, " " ); if ( n <= 1 ) return s; a[1] = "" a[1]; for ( i = 2; i <= n; i++ ) { v = "" a[i]; j = i - 1; while ( (j >= 1) && (a[j] > v) ) { a[j+1] = a[j]; j--; } a[j+1] = v; } s = ""; for ( i = 1; i <= n; i++ ) s = s a[i] " "; return s; } function psver( vs ) { if ( match( vs, /^[^.]+\.[^.]+\.[^.]+\.[^.]+\./ ) ) return substr( vs, 1, RLENGTH - 1 ); else return vs; } function prstree( id, s, a, v, n, i, b, m, j ) { if ( ! (id in patchidset) ) { return ""; } else { delete patchidset[id]; n = split( patchidprs[id], a, " " ); s = ""; for ( i = 1; i <= n; i++ ) { v = "" a[i]; if ( v in patchno2id ) { m = split( patchno2id[v], b, " " ); for ( j = 1; j <= m; j++ ) s = s prstree( "" b[j] ); } } return s id " "; } } BEGIN { for ( i in errors ) delete errors[i]; errcnt = 0; ftlcnt = 0; } function _logerror( message ) { if ( errors[message]++ < 10 ) { errors[errcnt + ftlcnt] = NR ": " message; return 1; } else return 0; } function error( message ) { if ( _logerror( message ) ) errcnt++; } function fatal( message ) { if ( _logerror( message ) ) ftlcnt++; } BEGIN { state = "bad"; for ( i in states ) delete states[i]; statess = 0; for ( i in PATCH_STATES ) delete PATCH_STATES[i]; PATCH_STATES["ipt"] = 1; PATCH_STATES["ipi"] = 1; PATCH_STATES["ipa"] = 1; PATCH_STATES["ipo"] = 1; PATCH_STATES["ipc"] = 1; for ( i in eeps ) delete eeps[i]; } function push( newstate ) { states[statess++] = state = newstate; } function pop( oldstate ) { if ( statess > 0 ) { for ( c in eeps ) if ( index( c, state ) == 1 ) eeps[c] = 0; statess--; } oldstate = state; if ( statess > 0 ) state = states[statess - 1]; else state = "bad"; return oldstate; } function eepcs( id ) { return 0 + eeps[state id]; } function event( id ) { eeps[state id]++; } function invxml() { error( "invalid XML tag or element in state " state ); if ( state in PATCH_STATES ) patchinv = 1; } function _invcnt( id, n, cond ) { if ( index( id, "!" ) == 1 ) error( "invalid number of " id " events in state " state " (" n " " cond ")" ); else error( "invalid number of <" id "> elements in state " state " (" n " " cond ")" ); if ( state in PATCH_STATES ) patchinv = 1; return 0; } function none( id, n ) { return ((n = eepcs( id )) == 0) || _invcnt( id, n, "!= 0" ); } function one( id, n ) { return ((n = eepcs( id )) == 1) || _invcnt( id, n, "!= 1" ); } function alo( id, n ) { return ((n = eepcs( id )) >= 1) || _invcnt( id, n, "< 1" ); } function amo( id, n ) { return ((n = eepcs( id )) <= 1) || _invcnt( id, n, "> 1" ); } BEGIN { tagname = ""; tagtype = ""; tagid = ""; tagtext = ""; tagacnt = 0; for ( i in tagattr ) delete tagattr[i]; } function parsetag( s, # unparsed input line b, # beginning of something l, # length of something aq, # attribute quote an, # attribute name av ) # attribute value { s = $0; tagacnt = 0; for ( i in tagattr ) delete tagattr[i]; if ( match( s, /^ *<[a-zA-Z0-9_.:-]+/ ) ) { b = index( s, "<" ) + 1; l = RLENGTH - b + 1; tagname = substr( s, b, l ); s = substr( s, RLENGTH + 1 ); while ( match( s, /^ +[a-zA-Z0-9_.:-]+=["']/ ) ) { b = index( s, "=" ); an = substr( s, 1, b - 1 ); # contains leading whitespace aq = substr( s, b + 1, 1 ); av = ""; s = substr( s, RLENGTH + 1 ); l = 1; while ( (l == 1) && ((b = index( s, aq )) == 0) ) { av = av s "\n"; l = getline s; } if ( l != 1 ) { s = ""; break; } av = av substr( s, 1, b - 1 ); s = substr( s, b + 1 ); sub( /^ +/, "", an ); av = xunquote( av ); tagacnt++; tagattr[an] = av; } if ( match( s, /^\/> *$/) ) { tagtype = "empty"; tagid = "#" tagname; tagtext = ""; eeps[state tagname]++; } else if ( match( s, /^> *$/ ) ) { tagtype = "start"; tagid = "<" tagname; tagtext = ""; eeps[state tagname]++; } else if ( match( s, />[^<]*<\/[a-zA-Z0-9_.:-]+> *$/ ) ) { tagtype = "text"; tagid = "'" tagname; tagtext = xunquote( substr( s, 2, index( s, "<" ) - 2 ) ); eeps[state tagname]++; } else { tagtype = "error"; tagid = "!" tagname; tagtext = ""; } } else if ( match( s, /^ *<\/[a-zA-Z0-9_.:-]+> *$/ ) ) { b = index( s, "" ) - b; tagname = substr( s, b, l ); tagtype = "end"; tagid = ">" tagname; tagtext = ""; } else { tagname = ""; tagtype = "error"; tagid = "!"; tagtext = ""; } return tagtype; } BEGIN { for ( i in MONTH_NUMBERS ) delete MONTH_NUMBERS[i]; MONTH_NUMBERS["jan"] = "01"; MONTH_NUMBERS["feb"] = "02"; MONTH_NUMBERS["mar"] = "03"; MONTH_NUMBERS["apr"] = "04"; MONTH_NUMBERS["may"] = "05"; MONTH_NUMBERS["jun"] = "06"; MONTH_NUMBERS["jul"] = "07"; MONTH_NUMBERS["aug"] = "08"; MONTH_NUMBERS["sep"] = "09"; MONTH_NUMBERS["oct"] = "10"; MONTH_NUMBERS["nov"] = "11"; MONTH_NUMBERS["dec"] = "12"; for ( i in DVSF ) delete DVSF[i]; DVSF["catmac.sql"] = 1; DVSF["catmacc.sql"] = 1; DVSF["catmacd.sql"] = 1; DVSF["catmacg.sql"] = 1; DVSF["catmach.sql"] = 1; DVSF["catmacp.sql"] = 1; DVSF["catmacr.sql"] = 1; DVSF["catmacs.sql"] = 1; DVSF["catmact.sql"] = 1; DVSF["catmacpre.sql"] = 1; DVSF["catmacpost.sql"] = 1; DVSF["dvmacfnc.plb"] = 1; DVSF["prvtmacp.plb"] = 1; for ( i in ZEROES ) delete ZEROES[i]; ZEROES[0] = "0000000000"; ZEROES[1] = "000000000"; ZEROES[2] = "00000000"; ZEROES[3] = "0000000"; ZEROES[4] = "000000"; ZEROES[5] = "00000"; ZEROES[6] = "0000"; ZEROES[7] = "000"; ZEROES[8] = "00"; ZEROES[9] = "0"; ZEROES[10] = ""; hdt = ""; for ( i in comps ) delete comps[i]; ### comps ### for ( i in patchidset ) delete patchidset[i]; patchidcnt = 0; for ( i in patchidlst ) delete patchidlst[i]; for ( i in patchno2id ) delete patchno2id[i]; for ( i in patchidprs ) delete patchidprs[i]; FS = "\n"; } (NR == 1) { next; } (/^ *$/) { next; } (parsetag() == "error") { error( "invalid input line" ); if ( state in PATCH_STATES ) patchinv = 1; next; } (state == "ipt") && (tagid == "oneoff_inventory") { if ( ! one( "!reference_id" ) ) patchno = "INVALID"; if ( ! one( "date_of_patch" ) ) patchstamp = "INVALID"; amo( "mopatch_cpurlb" ); one( "instance_shutdown" ); amo( "PatchSetUpdate" ); pop(); next; } (state == "ipi") { next; } (state == "ipa") && (invtype == "tbi") && (tagtype == "start") && ("version" in tagattr) && ("opt_req" in tagattr) && ((tagattr["opt_req"] == "R") || ((tagattr["opt_req"] == "O") && (tagname in comps) && (psver( tagattr["version"] ) == psver( comps[tagname] )))) { event( "!comp" ); push( "ipc" ); patchcomp = tagname; next; } (state == "ipa") && (invtype == "ins") && (tagid == "COMP") { pop(); next; } (state == "ipc") { invxml(); next; } (state == "ipa") && (invtype == "tbi") && (tagtype == "start") && ("version" in tagattr) && ("opt_req" in tagattr) { event( "!comp" ); push( "ipo" ); patchcomp = tagname; next; } (state == "ipo") && (invtype == "tbi") && (tagname == patchcomp) && (tagtype == "end") { patchcomp = ""; pop(); next; } (state == "ipo") { next; } (state == "ipt") && (tagid == "oneoff_actions") { alo( "!comp" ); pop(); next; } (state == "ipa") { invxml(); next; } BEGIN { patchid = 0; patchno = "INVALID"; patchinv = 0; patchbase = "INVALID"; patchsrc = "INVALID"; patchmlc = "INVALID"; patchstamp = "INVALID"; patchprqs = ""; patchovls = ""; patchfiles = ""; patchmakes = ""; for ( i in patchflags ) delete patchflags[i]; patchcomp = ""; } (state == "ips") && (tagid == "INTERIM_PATCH") { if ( invtype == "tbi" ) { if ( ! one( "patchbase" ) ) patchbase = "INVALID"; if ( ! one( "patchsrc" ) ) patchsrc = "INVALID"; if ( ! one( "patchmlc" ) ) patchmlc = "INVALID"; } if ( ! one( "oneoff_inventory" ) ) { patchno = "INVALID"; patchstamp = "INVALID"; } one( "oneoff_actions" ); if ( patchid in patchidset ) fatal( "invalid duplicate patch ID " patchid ); else patchidset[patchid] = 1; patchidlst[patchidcnt++] = patchid; if ( patchno in patchno2id ) patchno2id[patchno] = patchno2id[patchno] patchid " "; else patchno2id[patchno] = patchid " "; patchidprs[patchid] = patchprqs; if ( patchinv && (! ("inv" in patchflags)) ) pfls = "inv "; else pfls = ""; for ( pfl in patchflags ) pfls = pfls pfl " "; if ( invtype == "tbi" ) { print "hash_pmdtbips_" patchid "='" squote( patchbase "&" patchsrc "&" patchmlc ) "'"; print "hash_pmdtbi_" patchid "='" patchno "&" patchstamp "& " pfls "'"; if ( patchprqs != "" ) print "hash_pmdtbiprs_" patchid "='" patchprqs "'"; if ( patchovls != "" ) print "hash_pmdtbiols_" patchid "='" sort( patchovls ) "'"; if ( patchfiles != "" ) print "hash_pmdtbifls_" patchid "='" squote( chop( patchfiles ) ) "'"; if ( patchmakes == "INVALID" ) print "hash_pmdtbimks_" patchid "='" patchmakes "'"; else if ( patchmakes != "" ) print "hash_pmdtbimks_" patchid "='" squote( chop( patchmakes ) ) "'"; } else { print "hash_pmdins_" patchid "='" patchno "&" patchstamp "& " pfls "'"; if ( patchprqs != "" ) print "hash_pmdinsprs_" patchid "='" patchprqs "'"; if ( patchovls != "" ) print "hash_pmdinsols_" patchid "='" sort( patchovls ) "'"; if ( patchfiles != "" ) print "hash_pmdinsfls_" patchid "='" squote( chop( patchfiles ) ) "'"; if ( patchmakes == "INVALID" ) print "hash_pmdinsmks_" patchid "='" patchmakes "'"; else if ( patchmakes != "" ) print "hash_pmdinsmks_" patchid "='" squote( chop( patchmakes ) ) "'"; } pop(); next; } (state == "ipt") { invxml(); next; } (state == "ioh") && (tagid == "ONEOFF_LIST") { pop(); next; } (state == "ips") { invxml(); next; } (state == "ics") && (tagid == "COMP") { if ( alo( "!VERSION" ) && (invtype == "ins") && (hdt == "COMPS") ) { cmpphrln=" comps[\"" aquote( cn ) "\"] = \"" aquote( cv ) "\";"; cmpphrln=" print \"" aquote( cmpphrln ) "\";" print cmpphrln; } pop(); next; } (state == "icp") && (tagid == "'VERSION") { event( "!VERSION" ); cv = tagtext; next; } (state == "icp") { invxml(); next; } (state == "ioh") && (tagid == "'" squote( cmpphrs ) "' || exit 1"; print "/^ ### comps ###$/ {"; } next; } (state == "ioh") && (tagid == "#COMPS") { if ( (invtype == "ins") && (hdt == "") ) { print "cat << 'COMPS' 1>'" squote( cmpphrs ) "' || exit 1"; print "/^ ### comps ###$/ {"; print " next;"; print "}"; print "{ print; }"; print "COMPS"; } next; } (state == "ics") && (tagid == ">COMPS") { if ( (invtype == "ins") && (hdt == "COMPS") ) { print " next;"; print "}"; print "{ print; }"; print "COMPS"; hdt = ""; } pop(); next; } (state == "ics") { invxml(); next; } (state == "ioh") && (tagid == "NODE_LIST") { pop(); next; } (state == "ins") { next; } (state == "ooa") && (tagid == "HOME") { one( "NODE_LIST" ); one( "COMPS" ); one( "ONEOFF_LIST" ); pop(); next; } (state == "ioh") { invxml(); next; } BEGIN { push( "ooa" ); } END { one( "!HOME" ); if ( (state = pop()) != "ooa" ) fatal( "invalid EOF in state " state ); } (state == "ooa") { next; } END { if ( hdt != "" ) { print hdt; fatal( "invalid open here-document in output" ); } if ( invtype == "tbi" ) { patchids = ""; for ( i = 0; i < patchidcnt; i++ ) patchids = patchids prstree( patchidlst[i] ); print "pmdtbiids='" patchids "'"; } else { patchids = ""; for ( i = 0; i < patchidcnt; i++ ) patchids = patchids patchidlst[i] " "; print "pmdinsids='" patchids "'"; } for ( i = 0; i < (errcnt + ftlcnt); i++ ) print "echo '" squote( errors[i] ) "' 1>&2"; if ( ((invtype == "ins") && ((errcnt + ftlcnt) > 0)) || ((invtype == "tbi") && (ftlcnt > 0)) ) print "exit 1"; } EOF { verbose "Analyzing installed patches...failed." error "Cannot create awk script \"$preinvawk\"." } # parse and test patch metadata. PD (sunos_*): Do not use # "return" statements in the generated shell script. cmpphrs="$tmpdir/cmpphrs.awk" if "$awk" -f "$preinvawk" \ -v oh="$ORACLE_HOME" \ -v invtype="ins" \ -v cmpphrs="$cmpphrs" \ "$preinvxml" 1>"$preinvsh" 2>&3 && ( . "$preinvsh" ) 1>&3 2>&1; then : else verbose "Analyzing installed patches...failed." error "Cannot parse and test patch metadata." fi # read patch metadata . "$preinvsh" 1>/dev/null 2>&1 # determine installed patches from patch metadata ipmd="" for patchid in $pmdinsids do if patchno=`pmdget ins $patchid patchno`; then : else error "Cannot determine patch number of patch $patchid." fi ipmd="$ipmd$patchno$NL" done ipmd=`printf '%s' "$ipmd" | sort -n 2>&3` # verify lists of installed patches cat << EOF 1>"$tmpdir/iplog" 2>&3 $iplog EOF cat << EOF 1>"$tmpdir/ipmd" 2>&3 $ipmd EOF if diff "$tmpdir/iplog" "$tmpdir/ipmd" 1>&3 2>&1; then : else verbose "Analyzing installed patches...failed." error "Cannot verify lists of installed patches." fi if $MOPATCH_TEST_MIGRATE; then : else verbose "Analyzing installed patches...done." fi if test $signalled = 1; then error -c cmdlineerror "Interrupted." fi if test "X$ipmd" != "X"; then verbose verbose "Patches installed in Oracle Home $ORACLE_HOME:" # use sorted list here! for patchid in $ipmd do # all installed patched must be valid, so no extra checks on # that are required here pmdcache ins $patchid patchflaginfo=`pmdflaginfo` l_oldifs=$IFS; IFS="&"; set -f; set x $patchflaginfo; shift; set +f; IFS=$l_oldifs patchmode=$1 patchflags=${3-} if $MOPATCH_TEST_MIGRATE; then verbose " $pmdpatchno" else if test "X$patchflags" != "X"; then verbose "$patchmode $pmdpatchno ($patchflags)" else verbose "$patchmode $pmdpatchno" fi fi done if runmodep "doc" && test $flag_ignore_installed = 1; then verbose verbose "Ignoring installed patches in documentation mode due to flag" verbose "\"ignore_installed\"." fi else verbose verbose "No patches installed in Oracle Home $ORACLE_HOME." fi if test $signalled = 1; then error -c cmdlineerror "Interrupted." fi ############################ # # analyze patches to process # ############################ if $MOPATCH_TEST_MIGRATE; then : else out out "Analyzing patches to process..." fi # newline-list of patches to install patchsrcs="" l_oldifs=$IFS; IFS=":"; set -f; set x $patchsrcpath; shift; set +f; IFS=$l_oldifs for item in "$patchsrcfile" "$patchsrcdir" ${1+"$@"} do if test "X$item" = "X"; then continue elif test -f "$item"; then patchsrcs="$patchsrcs$item$NL" else # newline-list of lowercase patch names and newline-list of # ampersand-records # # & lpatchsrcs="" spatchsrcs="" for patchsrc in \ "$item"/[pP][0-9][0-9][0-9][0-9][0-9][0-9]*.[zZ][iI][pP] \ "$item"/SAP_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP] \ "$item"/SGR_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP] \ "$item"/SXD_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP] \ "$item"/GIPSU_[0-9][0-9][0-9][0-9][0-9]*[0-9]_*.[zZ][iI][pP] \ "$item"/EXA_[0-9][0-9][0-9][0-9][0-9]*[0-9]_*.[zZ][iI][pP] do if test "X$patchsrc" != "X$item/[pP][0-9][0-9][0-9][0-9][0-9][0-9]*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/SAP_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/SGR_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/SXD_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]_*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/GIPSU_[0-9][0-9][0-9][0-9][0-9]*[0-9]_*.[zZ][iI][pP]" && test "X$patchsrc" != "X$item/EXA_[0-9][0-9][0-9][0-9][0-9]*[0-9]_*.[zZ][iI][pP]"; then case $patchsrc in "$item"/GIPSU_[0-9][0-9][0-9][0-9][0-9]*[0-9]_*.[zZ][iI][pP]|\ "$item"/EXA_[0-9][0-9][0-9][0-9][0-9]*[0-9]_*.[zZ][iI][pP]) if test $flag_ignore_ubps = 1; then continue fi ;; esac lpatchsrc=`printf '%s\n' "$patchsrc" | sed 's/\.[zZ][iI][pP]$/.zip/;''s/P\([0-9][0-9][0-9][0-9][0-9][0-9][^\/]*.zip\)$/p\1/' 2>&3` if memberp "$NL" "$lpatchsrc" "$lpatchsrcs"; then continue fi lpatchsrcs="$lpatchsrcs$lpatchsrc$NL" spatchsrcs="$spatchsrcs$lpatchsrc&$patchsrc$NL" fi done # sort patches to install by lowercase patch basename and # strip off sort key if test "X$spatchsrcs" != "X"; then if spatchsrcs=`printf '%s' "$spatchsrcs" | sort -k1,1 -t "&" 2>&3`; then : else out "Analyzing patches to process...failed." error "Cannot sort list of patches from patch source directory \"$item\"." fi l_oldifs=$IFS; IFS="$NL"; set -f; set x $spatchsrcs; shift; set +f; IFS=$l_oldifs for spatchsrc in "$@" do l_oldifs=$IFS; IFS="&"; set -f; set x $spatchsrc; shift; set +f; IFS=$l_oldifs patchsrcs="$patchsrcs$2$NL" done fi fi done unset spatchsrcs unset lpatchsrcs tbiinvawk="$tmpdir/tbiinv.awk" tbiinvxml="$tmpdir/tbiinv.xml" tbiinvsh="$tmpdir/tbiinv.sh" # modify awk script to parse patch metadata of to-be-installed # patches if "$awk" -f "$cmpphrs" "$preinvawk" 1>"$tbiinvawk" 2>&3; then : else out "Analyzing patches to process...failed." error "Cannot create awk script \"$tbiinvawk\"." fi # open to-be-installed inventory and write its header if ( exec 6>"$tbiinvxml" && exec 6>&- ) 1>&3 2>&1 && exec 6>"$tbiinvxml"; then : else out "Analyzing patches to process...failed." error "Cannot open to-be-installed inventory \"$tbiinvxml\" for writing." fi echo "" 1>&6 echo "" 1>&6 echo "" 1>&6 echo "" 1>&6 echo "" 1>&6 # loop through the patches to install, extract patch listings and # metadata, and write them to the to-be-installed inventory. # Never exit this loop with an error, log errors and write # appropriate patch metadata instead. patchid=0 l_oldifs=$IFS; IFS="$NL"; set -f; set x $patchsrcs; shift; set +f; IFS=$l_oldifs for patchsrc in "$@" do # determine patch basename first. The patch basename is used # as an unique identifier in the output and the log file, and # for nothing else. Keep the patch basename always lowercase. # This will still be unique, since we removed duplicate (up to # case) patches in the above loop. if patchbase=`printf '%s\n' "$patchsrc" | sed -e 's/\.[zZ][iI][pP]$/.zip/' \ -e 's/P\([0-9][0-9][0-9][0-9][0-9][0-9][^\/]*.zip\)$/p\1/' \ -e 's/^\.\///;s/\/\/\/*/\//g;' 2>&3`; then : else logerr "Cannot determine patch basename from \"$patchsrc\"." pmdtbipatch $patchid "INVALID" "$patchsrc" "INVALID" "genfld" patchid=`expr $patchid + 1 2>&3` continue fi # if the patch source path is a singleton, simplify the patch # basename by using only, well, the basename if test $pspstp = 1; then if npatchbase=`basenamef "$patchbase" 2>&3`; then patchbase=$npatchbase else logerr "Cannot determine simplified patch basename from \"$patchbase\"." pmdtbipatch $patchid "$patchbase" "$patchsrc" "INVALID" "genfld" patchid=`expr $patchid + 1 2>&3` continue fi fi if test -f "$patchsrc"; then : else pmdtbipatch $patchid "$patchbase" "$patchsrc" "INVALID" "nonfile" patchid=`expr $patchid + 1 2>&3` continue fi # test zip file and get patch file contents patchtest="$tmpdir/patchtest" if "$unzip" -t "$patchsrc" 1>"$patchtest" 2>&3; then : else pmdtbipatch $patchid "$patchbase" "$patchsrc" "INVALID" "nonzip" patchid=`expr $patchid + 1 2>&3` continue fi # determine zip file contents from test output patchls="$tmpdir/patchls" if grep '^[ ]*testing:[ ][ ]*' "$patchtest" 2>&3 | sed 's/^[ ]*testing:[ ][ ]*//;s/[ ][ ]*OK$//' 2>&3 | sort 1>"$patchls" 2>&3; then : else logerr "Cannot determine zip file contents from test output for patch \"$patchbase\"." pmdtbipatch $patchid "$patchbase" "$patchsrc" "INVALID" "genfld" patchid=`expr $patchid + 1 2>&3` continue fi # to-be-installed patch molecules. List of directory names # where one of the files etc/config/inventory or # etc/config/actions exist: # # / # ... # # ... # # A molecule ID may be a directory name of any depth, it must # not necessarily be numeric. # # We intentionally sort the molecules in reverse order. tbipmlcs=`egrep '[0-9][0-9]*(/.*)?/etc/config/(inventory|actions)(\.xml)?$' "$patchls" 2>&3 | sed 's,/etc/config/[^/][^/]*$,,' 2>&3 | sort -r 2>&3 | uniq 2>&3` simple="" if test "X$tbipmlcs" = "X"; then # non-OPatch patch pmdtbihdr $patchid "$patchbase" "$patchsrc" "INVALID" "nonop" if cat "$patchls" | pmdtbifiles; then : else logerr "Cannot extract patch molecule listing for patch \"$patchbase\"." pmdtbiflg "genfld" fi pmdtbiftr patchid=`expr $patchid + 1 2>&3` continue elif swp "$tbipmlcs"; then simple=1 else simple=0 if test $flag_apply_napply = 0; then # n-apply patch. Do not inspect molecules any further. pmdtbihdr $patchid "$patchbase" "$patchsrc" "INVALID" "napply" if cat "$patchls" | pmdtbifiles; then : else logerr "Cannot extract patch molecule listing for patch \"$patchbase\"." pmdtbiflg "genfld" fi pmdtbiftr patchid=`expr $patchid + 1 2>&3` continue fi fi patchrootbase=$patchbase l_oldifs=$IFS; IFS="$NL"; set -f; set x $tbipmlcs; shift; set +f; IFS=$l_oldifs for patchmlc in "$@" # patch molecule do # verify patch molecule patchmlcxml="" if pmddirp "$patchmlc"; then : else logerr "Cannot verify patch molecule \"$patchmlc\" for patch \"$patchbase\"." pmdtbipatch $patchid "$patchbase" "$patchsrc" "INVALID" "genfld" patchid=`expr $patchid + 1 2>&3` continue fi # re-determine patch basename if test $simple = 0; then # patch molecule ID pmlcid=`printf '%s\n' "$patchmlc" | tr '/' '!' 2>&3` # carefully simplify SBP basenames further by stripping off # the leading SBP directory name l_oldifs=$IFS; IFS="!"; set -f; set x $pmlcid; shift; set +f; IFS=$l_oldifs case $1 in SAP_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]|\ SBP_[0-9][0-9][0-9][0-9][0-9]*[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]) # SBP directory name infix if sbpdnifx=`printf '%s\n' "$1" | sed "s/^S[AB]P_//" 2>&3`; then case $patchrootbase in SAP_"$sbpdnifx"_*.zip|*/SAP_"$sbpdnifx"_*.zip|\ SGR_"$sbpdnifx"_*.zip|*/SGR_"$sbpdnifx"_*.zip|\ SXD_"$sbpdnifx"_*.zip|*/SXD_"$sbpdnifx"_*.zip) if npmlcid=`printf '%s\n' "$pmlcid" | sed "s/^$1!//" 2>&3`; then pmlcid=$npmlcid fi ;; esac fi ;; esac patchbase="$patchrootbase!$pmlcid" else patchbase=$patchrootbase fi # tracking bug of n-apply patches trkbug="" if expr "X$patchmlc" : 'X\([0-9][0-9]*\)/\1$' 1>/dev/null 2>&3; then trkbug=1 else trkbug=0 fi pmdtbihdr $patchid "$patchbase" "$patchsrc" "$patchmlc" if test $simple = 0; then pmdtbiflg "nonsmpl" fi if test $trkbug = 1; then pmdtbiflg "trkbug" fi # extract patch or patch molecule listing. For non-simple # patches, remove the extracted patch molecule listing from # the overall listing. if test $simple = 1; then if cat "$patchls" 2>&3 | pmdtbifiles; then : else logerr "Cannot extract patch molecule listing for patch \"$patchbase\"." pmdtbiftr "genfld" patchid=`expr $patchid + 1 2>&3` continue fi elif test $trkbug = 1; then # seems to be the tracking bug of an n-apply patch. Add # the top-level files to the patch molecule listing. if pmlcre=`printf '%s\n' "$patchmlc" | quotemeta -x 2>&3` && egrep "^$pmlcre/"'|^[0-9][0-9]*/[^/][^/]*$' "$patchls" 2>&3 | pmdtbifiles && # this may fail for the top-level patch ( egrep -v "^$pmlcre/"'|^[0-9][0-9]*/[^/][^/]*$' "$patchls" 1>"$patchls.tmp" 2>&3 || : ) && mv "$patchls.tmp" "$patchls" 1>&3 2>&1; then : else logerr "Cannot extract patch molecule listing for patch \"$patchbase\"." pmdtbiftr "genfld" patchid=`expr $patchid + 1 2>&3` continue fi else if pmlcre=`printf '%s\n' "$patchmlc" | quotemeta 2>&3` && grep "^$pmlcre/" "$patchls" 2>&3 | pmdtbifiles && ( grep -v "^$pmlcre/" "$patchls" 1>"$patchls.tmp" 2>&3 || : ) && mv "$patchls.tmp" "$patchls" 1>&3 2>&1; then : else logerr "Cannot extract patch molecule listing for patch \"$patchbase\"." pmdtbiftr "genfld" patchid=`expr $patchid + 1 2>&3` continue fi fi # extract patch metadata patchmd="$tmpdir/patchmd" if { "$unzip" -qq -p "$patchsrc" \ "$patchmlc/etc/config/inventory" \ "$patchmlc/etc/config/actions" 1>"$patchmd" 2>&3 || "$unzip" -qq -p "$patchsrc" \ "$patchmlc/etc/config/inventory.xml" \ "$patchmlc/etc/config/actions.xml" 1>"$patchmd" 2>&3 }; then : else logerr "Cannot extract patch metadata for patch \"$patchbase\"." pmdtbiftr "genfld" patchid=`expr $patchid + 1 2>&3` continue fi # check for DOS line endings in patch metadata if od -b "$patchmd" 2>&3 | grep ' 015' 1>/dev/null 2>&3; then pmdtbiflg "dos" fi # remove DOS line endings and append patch metadata to the # to-be-installed inventory. Add trailing whitespace to the # patch metadata. OOAISE='<\/oneoff_actions>[ ]*' OOIASE='<\/oneoff_inventory>[ ]*' if ( cat "$patchmd" 2>&3 && echo ) | tr -d '\015' 2>&3 | sed -e "s/$OOAISE/<\/oneoff_actions>\\${NL}/" \ -e "s/$OOIASE/<\/oneoff_inventory>\\${NL}/" 1>&6 2>&3; then : else logerr "Cannot append patch metadata for patch \"$patchbase\"." pmdtbiftr "genfld" patchid=`expr $patchid + 1 2>&3` continue fi pmdtbiftr patchid=`expr $patchid + 1 2>&3` done done # write footer of to-be-installed inventory and close it echo "" 1>&6 echo "" 1>&6 exec 6>&- if "$awk" -f "$tbiinvawk" \ -v oh="$ORACLE_HOME" \ -v invtype="tbi" \ "$tbiinvxml" 1>"$tbiinvsh" 2>&3 && ( . "$tbiinvsh" ) 1>&3 2>&1; then : else out "Analyzing patches to process...failed." error "Cannot parse and test patch metadata." fi # read patch metadata . "$tbiinvsh" 1>/dev/null 2>&1 # this is a hack: move PSU without prerequisite patches to front. # # We need this in the following situation: # # A is a subset of B # B conflicts with PSU # A and PSU are disjunct # B is installed # A and PSU are to-be-installed # # In that situation, A will not get installed if it comes before # the PSU in the list of patches to-be-installed. A generic # solution to this problem would be challenging to implement ... if patchids=`pmdfind tbi patchflags "~" catpsu patchprqs = ""`; then pmdmv2front tbi $patchids fi # PD, DBVD (sunos_sun4u, 10.2.0.2.0): ensure that patch 5117016 # gets installed first if test "X$platform" = "Xsunos_sun4u" && test "X$rdbmsver" = "X10.2.0.2.0" && test $flag_5117016_check = 1; then if patchids=`pmdfind tbi patchno = 5117016`; then pmdmv2front tbi $patchids elif pmdfind ins patchno = 5117016 1>/dev/null; then : else out "Analyzing patches to process...failed." error "Cannot find mandatory patch 5117016." fi fi # move any OPatch patches to the front of the list. This must # come after any other patches were moved to front. if patchids=`pmdfind tbi patchflags "~" opatch`; then pmdmv2front tbi $patchids fi if $MOPATCH_TEST_MIGRATE; then : else out "Analyzing patches to process...done." fi verbose verbose "Operations to be executed:" for patchid in $pmdtbiids do pmdcache tbi $patchid # make sure that patches with invalid basenames may be properly # traced back in the log file patchbase="" if test "X$pmdpatchbase" != "XINVALID"; then patchbase=$pmdpatchbase else patchbase="INVALID_ID_$patchid" fi patchflaginfo=`pmdflaginfo` l_oldifs=$IFS; IFS="&"; set -f; set x $patchflaginfo; shift; set +f; IFS=$l_oldifs patchmode=$1 patchflags=${3-} if $MOPATCH_TEST_MIGRATE; then verbose " apply patch $patchbase" else if test "X$patchflags" != "X"; then verbose " apply patch $patchbase ($patchflags)" else verbose " apply patch $patchbase" fi fi done set -f; set x $pmdtbiids; shift; set +f tbipn=$# ################################################## # # more miscellaneous validation and initialization # ################################################## # PD, OPVD (sunos_* 5.10, 10.2.*): take care of ar verification # message if { test "X$platform" = "Xsunos_sun4u" || test "X$platform" = "Xsunos_i86pc" } && test "X$kernelver" = "X5.10" && test $flag_sol10_ar_check = 1; then wtbis="${wtbis}"'OUI-67124:Verification of '\''ar'\'' actions failed\.'"$NL" fi # OPVD: ignore some warnings (it is sure funny to change error # numbers from release to release!). Do not ignore warnings # other than those to detect OPatch internal changes as soon as # possible in our stress test suite. if verstest "$opver" -ge "11.2.0.1.1" || verstest "$opver" -ge "11.1.0.6.9" || verstest "$opver" -ge "10.2.0.4.9" || verstest "$opver" -ge "10.2.0.5.0"; then wtbis="${wtbis}67620${NL}" # resource S_REVISED_BUG_SUPERSET else wtbis="${wtbis}67078${NL}" # resource S_BUG_SUPERSET fi # OPVD (>= 10.2.0.4.3): create required directory if verstest -d 0 "$opver" -ge "10.2.0.4.3" && test ! -d "$ORACLE_HOME/ccr_stage"; then if mkdir "$ORACLE_HOME/ccr_stage" 1>&3 2>&1; then echo "Do not remove this directory. It is required" 1>>"$ORACLE_HOME/ccr_stage/readme.txt" echo "for proper operation of OPatch." 1>>"$ORACLE_HOME/ccr_stage/readme.txt" else error "Cannot create directory \"$ORACLE_HOME/ccr_stage\"." fi fi if runmodep "apply"; then # create awk script to parse OPatch output opopawk="$tmpdir/opoparser.awk" cat << 'EOF' 1>"$opopawk" 2>&3 || function squote( s, qs, b ) { qs = ""; b = 0; while ( b = index( s, "'" ) ) { qs = qs substr( s, 1, b - 1 ) "'\\''"; s = substr( s, b + 1 ); } return qs s; } function zeropad( s ) { if ( length( s ) <= 10 ) return ZEROES[length( s )] s; else { error = 1; return substr( s, 1, 10 ); } } function sort( s, a, v, n, i, j, r ) { i = 1; for ( v in s ) a[i++] = v; n = i - 1; a[1] = zeropad( a[1] ); for ( i = 2; i <= n; i++ ) { v = zeropad( a[i] ); j = i - 1; while ( (j >= 1) && (a[j] > v) ) { a[j+1] = a[j]; j--; } a[j+1] = v; } r = ""; for ( i = 1; i <= n; i++ ) { v = a[i]; sub( /^0+/, "", v ); if ( i < n ) r = r v " "; else r = r v; } return r; } BEGIN { error = 0; state = "ooa"; logfile = "INVALID"; for ( i in resources ) delete resource[i]; for ( i in rbps ) delete rbps[i]; for ( i in prereqs ) delete prereqs[i]; for ( i in conflicts ) delete conflicts[i]; prereqsp = 0; conflictsp = 0; for ( i in warnings ) delete warnings[i]; for ( i in ZEROES ) delete ZEROES[i]; ZEROES[0] = "0000000000"; ZEROES[1] = "000000000"; ZEROES[2] = "00000000"; ZEROES[3] = "0000000"; ZEROES[4] = "000000"; ZEROES[5] = "00000"; ZEROES[6] = "0000"; ZEROES[7] = "000"; ZEROES[8] = "00"; ZEROES[9] = "0"; ZEROES[10] = ""; } /^Log file location +: +/ { sub( /^Log file location +: +/, "", $0 ); logfile = $0; next; } /^OPatch Session completed with warnings\.$/ { resources["S_OPATCH_COMPLETED_WITH_WARNINGS"] = 1; next; } /^ApplySession failed during prerequisite checks: / { resources["S_OPATCH_SESSION_PREREQ_FAIL"] = 1; next; } /^ApplySession system modification phase did not start: / { resources["S_OPATCH_SESSION_PREP_FAIL"] = 1; next; } /^ApplySession failed: / { resources["S_OPATCH_SESSION_FAIL"] = 1; next; } /^ApplySession system modification phase did not start: / { resources["S_OPATCH_APPLY_SESSION_PREP_FAIL"] = 1; next; } /^Apply Session failed: / { resources["S_OPATCH_APPLY_SESSION_FAIL"] = 1; next; } /^Interim patch [0-9]+ is a subset of the patch\(es\)/ { resources["S_BUG_SUBSET"] = 1; next; } /^OPatch cannot autorollback a Online patch while applying a regular patch\.$/ { resources["S_AUTOROLLBACK_ONLINE_ERROR"] = 1; next; } /^OPatch cannot autorollback an online patch while applying a regular patch\.$/ { resources["S_AUTOROLLBACK_ONLINE_ERROR"] = 1; next; } /^OPatch cannot roll back an online patch while applying a regular patch\.$/ { resources["S_AUTOROLLBACK_ONLINE_ERROR"] = 1; next; } /^Online patch should not "superset" Regular patch\(es\)\.$/ { resources["S_ONLINE_NOT_SUPERSET_REGULAR"] = 1; next; } /^OPatch cannot autorollback a regular patch while applying an online patch\.$/ { resources["S_ONLINE_NOT_SUPERSET_REGULAR"] = 1; next; } /^OPatch cannot roll back a regular patch while applying an online patch\.$/ { resources["S_ONLINE_NOT_SUPERSET_REGULAR"] = 1; next; } /^System intact, OPatch will not attempt to restore the system$/ { resources["S_NO_RESTORE"] = 1; next; } /^RollbackSession removing interim patch '[0-9]+' from inventory$/ { resources["S_REMOVING_FROM_INVENTORY"] = 1; sub( /^RollbackSession removing interim patch '/, "", $0 ); sub( /' from inventory$/, "", $0 ); rbps[$0] = 1; next; } /^Conflict patches: +[0-9]+(,? +[0-9]+)*$/ { resources["S_CONFLICT_MESSAGE"] = 1; sub( /^Conflict patches: +/, "", $0 ); split( $0, l, /,? +/ ); for ( i in l ) conflicts["" l[i]] = 1; conflictsp = 1; next; } /^Interim patch [0-9]+ conflict with patch\(es\) \[ *[0-9]+( +[0-9]+)* *\] in the Oracle Home$/ { resources["S_REVISED_CONFLICT"] = 1; sub( /^Interim patch [0-9]+ conflict with patch\(es\) \[ */, "", $0 ); sub( / *\] in the Oracle Home$/, "", $0 ); split( $0, l, / +/ ); for ( i in l ) conflicts["" l[i]] = 1; conflictsp = 1; next; } /^Required patch\(es\) \[ ([0-9]+ )+\] for patch '[0-9]+' are not present in the Oracle Home\.$/ { sub( /^Required patch\(es\) \[ /, "", $0 ); sub( / \] for patch '[0-9]+' are not present in the Oracle Home\.$/, "", $0 ); split( $0, l, / / ); for ( i in l ) prereqs["" l[i]] = 1; prereqsp = 1; next; } /^The following warnings have occurred during OPatch execution:$/ { state = "iws"; next; } (state == "iws") && /^[0-9]+\) [A-Z][A-Z][A-Z]-[0-9][0-9][0-9][0-9][0-9]:/ { key = $0; sub( /^[0-9]+\) [A-Z][A-Z][A-Z]-/, "", key ); key = substr( key, 1, 5 ); value = $0; sub( /^[0-9]+\) [A-Z][A-Z][A-Z]-[0-9][0-9][0-9][0-9][0-9]:/, "", value ); if ( key in warnings ) warnings[key] = warnings[key] "\n" value else warnings[key] = value; next; } (state == "iws") && /^-+$/ { state = "ooa"; next; } END { print "opologfile='" squote( logfile ) "'" status = ""; if ( "S_OPATCH_COMPLETED_WITH_WARNINGS" in resources ) status = "success"; else if ( ("S_OPATCH_SESSION_PREREQ_FAIL" in resources) || ("S_OPATCH_SESSION_PREP_FAIL" in resources) || ("S_OPATCH_SESSION_FAIL" in resources) || ("S_OPATCH_APPLY_SESSION_PREP_FAIL" in resources) || ("S_OPATCH_APPLY_SESSION_FAIL" in resources) ) status = "error"; else if ( exitval == 0 ) status = "success"; else status = "error"; if ( status == "error" ) { if ( ! ("S_NO_RESTORE" in resources) ) status = "fatal"; else if ( "S_BUG_SUBSET" in resources ) status = "subset"; else if ( "S_AUTOROLLBACK_ONLINE_ERROR" in resources ) status = "onlntooffl" else if ( "S_ONLINE_NOT_SUPERSET_REGULAR" in resources ) status = "offltoonln" else if ( prereqsp ) status = "prereqs"; else if ( conflictsp ) status = "conflicts"; } print "opostatus='" status "'"; print "oporbps='" sort( rbps ) "'"; print "opoprereqs='" sort( prereqs ) "'"; print "opoconflicts='" sort( conflicts ) "'"; warnings_s = ""; for ( warning in warnings ) { print "hash_opowarnings_" warning "='" squote( warnings[warning] ) "'"; warnings_s = warnings_s warning " "; } sub( / $/, "", warnings_s ); print "opowarnings='" warnings_s "'"; if ( error != 0 ) { print "echo 'unexpected error' 1>&2"; print "exit 1;"; } if ( state != "ooa" ) { print "echo 'invalid EOF in state " state "' 1>&2"; print "exit 1;"; } } EOF error "Cannot create awk script \"$opopawk\"." fi if runmodep "doc"; then # create awk script to parse patch readmes rdmpawk="$tmpdir/rdmparser.awk" cat << 'EOF' 1>"$rdmpawk" 2>&3 || BEGIN { tkn = 0; val = ""; pos = 0; latkn1 = 0; laval1 = ""; lapos1 = 0; latkn2 = 0; laval2 = ""; lapos2 = 0; bufcnt = 0; } function pushtoken( newtkn, newval, newpos ) { if ( bufcnt == 0 ) { tkn = newtkn; val = newval; pos = newpos; bufcnt++; return 1; } else if ( bufcnt == 1 ) { latkn1 = newtkn; laval1 = newval; lapos1 = newpos; bufcnt++; return 1; } else if ( bufcnt == 2 ) { latkn2 = newtkn; laval2 = newval; lapos2 = newpos; bufcnt++; return 0; } } function hastoken() { return (bufcnt > 0); } function shifttoken() { if ( bufcnt == 0 ) return 0; else if ( bufcnt == 1 ) { bufcnt--; return 0; } else if ( bufcnt == 2 ) { tkn = latkn1; val = laval1; pos = lapos1; bufcnt--; return 1; } else if ( bufcnt == 3 ) { tkn = latkn1; latkn1 = latkn2; val = laval1; laval1 = laval2; pos = lapos1; lapos1 = lapos2; bufcnt--; return 1 } } BEGIN { cbl = 0; cbls = ""; sectype = "specl"; secid = "start"; secbeg = 1; secend = 0; sechsz = 0; secknp = 1; secbd = ""; secbdcnt = 0; for ( i in secbds ) delete secbds[i]; SECTION_TITLE_MAP["readmetxtofpatch"] = "title:title"; SECTION_TITLE_MAP["interimpatchforbasebug"] = "specl:interim"; SECTION_TITLE_MAP["datetimestamp"] = "specl:metadata"; SECTION_TITLE_MAP["bugsfixedbythispatch"] = "specl:bugsfxd"; SECTION_TITLE_MAP["patchspecificfootxtofpatch"] = "specl:psftop"; SECTION_TITLE_MAP["opatchinformation"] = "known:opi"; SECTION_TITLE_MAP["opatchutilityinformation"] = "known:opi"; SECTION_TITLE_MAP["patchpreinstallsteps"] = "known:ppis"; SECTION_TITLE_MAP["patchinstallationinstructions"] = "known:pii"; SECTION_TITLE_MAP["patchinstallationsteps"] = "known:pis"; SECTION_TITLE_MAP["patchspecialinstructions"] = "known:psi"; SECTION_TITLE_MAP["patchdeinstallationinstructions"] = "known:pdii"; SECTION_TITLE_MAP["patchpostinstallinstructions"] = "known:ppii"; } function startsec( title, beg, hsz, s ) { cbl = 0; cbls = ""; if ( title in SECTION_TITLE_MAP ) { s = SECTION_TITLE_MAP[title]; sectype = substr( s, 1, 5 ); secid = substr( s, 7 ); } else { sectype = "unknw"; secid = "unknown"; } secbeg = beg; secend = 0; sechsz = hsz; secknp = 1; secbd = ""; secbdcnt = 0; } function writesecscreen() { print "cat << 'EOF' | rdmscreen " secid " " secbeg " " secend cbls " || rdmnonstdp=1"; for ( i = 0; i < secbdcnt; i++ ) print secbds[i]; if ( secbd != "" ) print secbd; print "EOF" } function writesecdel() { print "rdmdel " secbeg " " secend; } function writecbldel( nonstdp ) { if ( cbls != "" ) print "rdmdel" cbls; if ( nonstdp ) print "rdmnonstdp=1"; if ( nonstdp && rdmstriplog ) { print "echo \"" secbeg "i\\\\${NL}RDM_NON_STD\" 1>&6" print "echo \"" secend "a\\\\${NL}RDM_NON_STD\" 1>&6" } } function writesec( end, i ) { secend = end; if ( cbl > 1 ) cbls = cbls " " (secend - cbl + 1) " " (secend - 1); if ( sectype == "specl" ) { if ( secid == "start" ) { if ( secend == 0 ) ; else if ( secknp ) writesecdel(); else writecbldel( 1 ); } else if ( secid == "metadata" ) writecbldel( ! secknp ); else if ( secid == "bugsfxd" ) writecbldel( ! secknp ); else if ( secknp && (secid == "interim") && (ENVIRON["MOPATCH_TEST_MIGRATE"] == "true") ) { print "rdmdel " (secbeg - 1) " " secbeg; print "rdmdel " (secbeg + 2) " " (secbeg + 2); } else if ( secknp ) writesecdel(); else writecbldel( 1 ); } else if ( sectype == "title" ) { if ( (secbdcnt == 0) && (secbd == "") ) writecbldel( 0 ); else { secbeg += sechsz; if ( cbl > 0 ) secend -= 1; writesecscreen(); } } else if ( sectype == "known" ) { if ( (secbdcnt == 0) && (secbd == "") ) writesecdel(); else writesecscreen(); } else if ( rdmstriplog ) { if ( (secbdcnt == 0) && (secbd == "") ) writesecdel(); else writesecscreen(); } else { if ( (secbdcnt == 0) && (secbd == "") ) writesecdel(); else writecbldel( 1 ); } } function parsetoken() { if ( (bufcnt == 3) && (tkn == TOKEN_UNDER) && (latkn1 > TOKEN_NONHDR) && (latkn2 == TOKEN_UNDER) ) { writesec( pos - 1 ); startsec( laval1, pos, 3 ); shifttoken(); shifttoken(); shifttoken(); } else if ( (bufcnt >= 2) && (tkn > TOKEN_NONHDR) && (latkn1 == TOKEN_UNDER) ) { writesec( pos - 1 ); startsec( val, pos, 2 ); shifttoken(); shifttoken(); } else if ( tkn == TOKEN_EMPTY ) { cbl++; shifttoken(); } else { if ( cbl > 1 ) cbls = cbls " " (pos - cbl) " " (pos - 2); cbl = 0; secbd = secbd val; if ( length( secbd ) > 80 ) { secbds[secbdcnt++] = substr( secbd, 1, 80 ); secbd = substr( secbd, 81 ); } if ( sectype == "specl" ) { if ( secid == "metadata" ) { if ( tkn != TOKEN_META ) secknp = 0; } else if ( secid == "bugsfxd" ) { if ( tkn != TOKEN_BUGDSC ) secknp = 0; } else secknp = 0; } shifttoken(); } } BEGIN { TOKEN_EMPTY = 0; TOKEN_UNDER = 1; TOKEN_NONHDR = 2; TOKEN_BUGDSC = 3; TOKEN_TEXT = 4; TOKEN_META = 5; FS = "\n"; } { line = $0; sub( /^#/, "", line ); sub( /^[ \t]+/, "", line ); sub( /[ \t\r]+$/, "", line ); if ( line == "" ) { newtkn = TOKEN_EMPTY; newval = ""; } else if ( line ~ /^-----+$/ ) { newtkn = TOKEN_UNDER; newval = ""; } else if ( line ~ /^=====+$/ ) { newtkn = TOKEN_UNDER; newval = ""; } else { line = tolower( line ); if ( line ~ /^for +(off|on)line +patch *:$/ ) newtkn = TOKEN_NONHDR; else if ( line ~ /^[0-9][0-9][0-9][0-9][0-9][0-9]+[ :-]+.*[a-z].*$/ ) newtkn = TOKEN_BUGDSC; else if ( line ~ /^.*[a-z0-9].* : .*[a-z0-9].*$/ ) newtkn = TOKEN_META; else newtkn = TOKEN_TEXT; if ( ENVIRON["MOPATCH_TEST_MIGRATE"] == "true" ) gsub( /p[0-9][0-9][0-9][0-9][0-9][0-9]+_[0-9][0-9][0-9][0-9]+_[^.]*\.zip/, "patchfile", line ); else gsub( /p[0-9][0-9][0-9][0-9][0-9][0-9]+_[0-9][0-9][0-9][0-9][0-9]+_[^.]*\.zip/, "patchfile", line ); gsub( /[0-9][0-9][0-9][0-9][0-9][0-9]+/, "patchno", line ); if ( ENVIRON["MOPATCH_TEST_MIGRATE"] == "true" ) sub( /^readme\.txt of .*:$/, "readmetxtofpatch", line ); else sub( /^readme for .*:$/, "readmetxtofpatch", line ); sub( /^interim +patch +for +base +bugs?:.*$/, "interimpatchforbasebug", line ); sub( /^(date:|march|april|may).* 20[0-9][0-9]$/, "datetimestamp", line ); sub( /^bugs +fixed +by +this +patch:$/, "bugsfixedbythispatch", line ); if ( ENVIRON["MOPATCH_TEST_MIGRATE"] == "true" ) sub( /^patch-specific (pre|post|init)\.txt of .*:$/, "patchspecificfootxtofpatch", line ); else sub( /^patch-specific information from (pre|post|init)\.txt:$/, "patchspecificfootxtofpatch", line ); gsub( /[^a-z]+/, "", line ); newval = line; } if ( pushtoken( newtkn, newval, NR ) ) next; } { parsetoken(); } END { while ( hastoken() ) parsetoken(); writesec( NR ); print ":" } EOF error "Cannot create awk script \"$rdmpawk\"." fi ########### # # main loop # ########### patchn=0 # patch index # patches ... documented="" # ... successfully documented installed="" # ... successfully installed installedwarning="" # ... installed with warnings failed="" # ... with installation failed fatal="" # ... with installation fatally failed uninstalled="" # ... successfully uninstalled documentedn=0 installedn=0 installedwarningn=0 failedn=0 fataln=0 uninstalledn=0 documentedf="" # patches skipped due to ... conflictskipped="" # ... conflicts prereqskipped="" # ... missing prereq patches nonpatchskipped="" # ... bad format installedskipped="" # ... already installed fatalskipped="" # ... previous fatal errors signalskipped="" # ... user interrupt conflictskippedn=0 prereqskippedn=0 nonpatchskippedn=0 installedskippedn=0 fatalskippedn=0 signalskippedn=0 nonpatchskippedf="" installedskippedf="" # patches with potential post-installation instructions uninstalledpii="" installedpii="" uninstalledpiin=0 installedpiin=0 uninstalledpiif="" installedpiif="" # set after each apply either to 1 if the apply was cleaned up or # to 0 if the apply was not cleaned up cleanedup=1 # in non-verbose mode, write an empty line only once, otherwise # write it before each patch if test $verbosep = 0; then rawout fi for patchid in $pmdtbiids do # we should not get errors here pmdcache tbi $patchid || : patchn=`expr $patchn + 1 2>&3` patchwtbis=$wtbis # make sure that patches with invalid basenames may be properly # traced back in the log files patchbase="" if test "X$pmdpatchbase" != "XINVALID"; then patchbase=$pmdpatchbase else patchbase="INVALID_ID_$patchid" fi verbose out "Processing patch \"$patchbase\"...($patchn of $tbipn)" # any of these may equal the plain string "INVALID". However, # functions "addtopatchlist", "perror", and "pskip" handle # these cases well, and so do the function from the patch # metadata library. In other words, we do not need to care # immediately about "INVALID" patch metadata parts. patchsrc=$pmdpatchsrc patchmlc=$pmdpatchmlc patchno=$pmdpatchno patchstamp=$pmdpatchstamp patchmakes=$pmdpatchmakes if test $signalled = 1; then pskip signalskipped "User interrupt."; continue 1 fi # check whether the patch file is actually a file if pmdflagset "nonfile"; then perror "Cannot process non-file."; continue 1 fi # check whether the patch file is a zip file if pmdflagset "nonzip"; then perror "Cannot unpack ZIP archive."; continue 1 fi # check for DOS line endings in patch metadata if pmdflagset "dos" && test $flag_stress_test = 1; then perror "Cannot process DOS line endings in patch metadata."; continue 1 fi # check whether the patch is an OPatch patch if pmdflagset "nonop"; then pskip nonpatchskipped "Probably not an OPatch patch."; continue 1 fi # check whether the patch is an n-apply patch if pmdflagset "napply"; then pskip nonpatchskipped "Probably an n-apply or a CRS bundle patch."; continue 1 fi if pmdflagset "genfld"; then perror "Cannot determine patch metadata."; continue 1 fi # verify patch source if test "X$patchsrc" = "XINVALID"; then perror "Cannot check patch file."; continue 1 fi # verify patch molecule if test "X$patchmlc" = "XINVALID"; then perror "Cannot check patch molecule."; continue 1 fi # verify patch number if test "X$patchno" = "XINVALID"; then if $MOPATCH_TEST_MIGRATE; then case $patchbase in p1000023_*_BAD_PATCH_NO_1.zip) perror "Cannot extract patch number from \"\"."; continue 1 ;; p1000024_*_BAD_PATCH_NO_2.zip) perror "Cannot extract patch number from \"1000024${NL}1000024\"."; continue 1 ;; esac else perror "Cannot check patch number."; continue 1 fi fi # verify patch stamp if test "X$patchstamp" = "XINVALID"; then if $MOPATCH_TEST_MIGRATE; then case $patchbase in p1000025_*_BAD_TIMESTAMP_1.zip) perror "Cannot check timestamp line."; continue 1 ;; p1000026_*_BAD_TIMESTAMP_2.zip) perror "Cannot extract patch timestamp from \"2-Oct-2007-14:47:24${NL}8-Oct-2007-14:49:24\"."; continue 1 ;; esac else perror "Cannot check patch timestamp."; continue 1 fi fi # verify make lines if $MOPATCH_TEST_MIGRATE; then if test "X$patchmakes" = "XINVALID"; then perror "Cannot check link lines."; continue 1 fi else if test "X$patchmakes" = "XINVALID"; then perror "Cannot check make lines."; continue 1 fi fi if $MOPATCH_TEST_MIGRATE || test $rdbmsnver -lt 1102000200; then # 11.2.0.2.0 if pmdflagset "crs"; then pskip -f "+" nonpatchskipped "Is a CRS patch."; continue 1 fi if pmdflagset "nonsmpl" && pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "crs" 1>/dev/null; then pskip -f "+" nonpatchskipped "Is part of a CRS bundle patch."; continue 1 fi else if pmdflagset "gi" && pmdflagclr "rdbms" && test "X$ohtype" = "Xrdbms"; then pskip -f "#" nonpatchskipped "Is a Grid Infrastructure patch."; continue 1 elif pmdflagclr "gi" && test "X$ohtype" = "Xgi"; then pskip -f "#" nonpatchskipped "Is an RDBMS patch."; continue 1 fi fi if $MOPATCH_TEST_MIGRATE; then if test $flag_apply_cpu = 0; then if pmdflagset "catcpu"; then pskip -f "*" nonpatchskipped "Is a Critical Patch Update (CPU)."; continue 1 elif pmdflagset "cpumlc" || { pmdflagset "nonsmpl" && pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "catcpu" 1>/dev/null }; then pskip -f "*" nonpatchskipped "Is a molecule of a Critical Patch Update (CPU)."; continue 1 fi fi fi if pmdflagset "psu" "catpsu" && test $flag_apply_psu = 0; then pskip -f "!" nonpatchskipped "Is a Patchset Update (PSU)."; continue 1 fi if $MOPATCH_TEST_MIGRATE; then if pmdflagset "dvsp"; then pskip -f "-" nonpatchskipped "Is a Database Vault special patch."; continue 1 fi else # DBVD (< 11.2.0.1.0): do not automatically install Database # Vault special patches if test $rdbmsnver -lt 1102000100 && # 11.2.0.1.0 pmdflagset "dvsp"; then pskip -f "-" nonpatchskipped "Is a Database Vault special patch."; continue 1 fi fi if pmdflagset "hpatch" && test "X$onlnmode" = "X0"; then pskip -f "@" nonpatchskipped "Is an online patch."; continue 1 fi if pmdflagclr "hpatch" && test "X$onlnmode" = "X1"; then pskip -f "@" nonpatchskipped "Is an offline patch."; continue 1 fi if test $psusp = 0; then if pmdflagset "psu"; then perror "Cannot install PSU with OPatch version \"$opversion\"."; continue 1 fi if test "X$pmdpatchprs" != "X"; then perror "Cannot install patch with prerequisites with OPatch version \"$opver\"."; continue 1 fi if test "X$pmdpatchols" != "X"; then perror "Cannot install patch with overlays with OPatch version \"$opver\"."; continue 1 fi fi # finally, verify overall patch metadata correctness if pmdflagset "inv"; then perror "Cannot parse patch metadata."; continue 1 fi # check whether the patch is installed already. Be careful to # compare only patches of identical modes. if test $flag_ignore_installed = 0; then # look for the correct patch mode fop="" if pmdflagset "hpatch"; then fop="~" else fop="!~" fi if patchinvid=`pmdfind ins patchno = "$patchno" \ patchflags "$fop" "hpatch"`; then set -f; set x $patchinvid; shift; set +f if test $# != 1; then perror "Cannot uniquely identify patch $patchno."; continue 1 fi # determine timestamp and overlays of installed patch if patchinvinfo=`pmdget ins $patchinvid patchstamp patchovls`; then : else perror "Cannot get patch metadata of patch $patchinvid."; continue 2 fi l_oldifs=$IFS; IFS="&"; set -f; set x $patchinvinfo; shift; set +f; IFS=$l_oldifs patchinvstamp=$1 patchinvovls=${2-} patchovls=$pmdpatchovls if test "X$patchinvovls" = "X$patchovls" && test "X$patchinvstamp" = "X$patchstamp"; then pskip installedskipped "Already installed."; continue 1 elif test "X$patchinvovls" = "X$patchovls"; then # compare timestamps and skip installation of older patches # d := (patchinvstamp > patchstamp) ? 1 : 0 d=`echo "0k[sb]sa 1 0 $patchstamp $patchinvstamp>apq" | dc 2>&3` if test "X$d" = "X1"; then pskip -f "+" installedskipped "Newer patch already installed."; continue 1 elif test "X$d" != "X0"; then perror "Cannot calculate \"$d\" as ($patchinvstamp > $patchstamp) ? 1 : 0."; continue 1 fi elif printf '%s\n%s\n' "$patchovls" "$patchinvovls" | sort -c 1>/dev/null 2>&1; then # consider overlays that are lexicographically larger as # newer pskip -f "+" installedskipped "Newer patch already installed."; continue 1 fi fi fi if test $fataln != 0; then pskip fatalskipped "Previous fatal error."; continue 1 fi # clean up the patch staging directory if rm -rf "$patchstage"/* 1>&3 2>&1; then : else perror "Cannot clean up temporary patch staging directory."; continue 1 fi # unpack the patch log "executing: \"$unzip\" -qq -d \"$tmpdir\" \"$patchsrc\" \"$patchmlc/*\"" if "$unzip" -qq -d "$patchstage" "$patchsrc" "$patchmlc/*" 1>&3 2>&1; then : else perror "Cannot unpack patch."; continue 1 fi # check whether we have enough patch storage free space to # install the patch. OPatch has its own check, but that # heavily underestimates the required patch storage free space. if test $psfsps = 1 && test $psrsps = 1 && test $flag_free_space_check = 1; then # d := (psrsp > psfsp) ? 1 : 0 d=`echo "0k[sb]sa 1 0 $psfsp $psrsp>apq" | dc 2>&3` if test "X$d" = "X1"; then perror "Cannot allocate ${psrsp}KB on \"$psmp\", only ${psfsp}KB free."; continue 1 elif test "X$d" != "X0"; then perror "Cannot calculate \"$d\" as ($psrsp > $psfsp) ? 1 : 0."; continue 1 fi fi # make all copy targets user-writable, if required. It would # be nice to undo these changes after patch installation, but # then the (possibly automated) rollback of the patch may fail. l_oldifs=$IFS; IFS="$NL"; set -f; set x $pmdpatchfiles; shift; set +f; IFS=$l_oldifs for patchfile in ${1+"$@"} do # replace prefix by Oracle Home patchfile="$ORACLE_HOME/"`printf '%s\n' "$patchfile" | sed 's/^%ORACLE_HOME%\///' 2>&3` if test -f "$patchfile" && test ! -w "$patchfile"; then if runmodep "apply"; then out "Adding missing write permissions for patch copy target \"$patchfile\"." if chmod u+w "$patchfile" 1>&3 2>&1; then : else perror "Cannot add write permissions for patch copy target \"$patchfile\"."; continue 2 fi else out "Would add missing write permissions for patch copy target \"$patchfile\"." fi fi done if runmodep "doc"; then # update the readme collections. Write our readme to a # temporary file first. readmetmp="$tmpdir/readme.txt" readmesh="$tmpdir/readme.sh" readmesed="$tmpdir/readme.sed" if ( exec 6>"$readmetmp" && exec 6>&- ) 1>&3 2>&1 && exec 6>"$readmetmp"; then : else perror "Cannot open temporary readme file \"$readmetmp\" for writing."; continue 1 fi # keep the readme parser in sync with this title if $MOPATCH_TEST_MIGRATE; then echo "README.txt of $patchbase:" 1>&6 echo "README.txt of $patchbase:" | sed 's/./=/g' 1>&6 2>&3 echo 1>&6 else if patchnoboringp; then echo "Readme for $patchbase:" 1>&6 echo "Readme for $patchbase:" | sed 's/./=/g' 1>&6 2>&3 echo 1>&6 else echo "Readme for $patchbase (patch number $patchno):" 1>&6 echo "Readme for $patchbase (patch number $patchno):" | sed 's/./=/g' 1>&6 2>&3 echo 1>&6 fi fi docflag=" " readmetxt="$patchstage/$patchmlc/README.txt" readmehtml="$patchstage/$patchmlc/README.html" if test -f "$readmetxt"; then if cat "$readmetxt" 1>&6 2>&3; then : else perror "Cannot append file \"README.txt\" to temporary readme."; continue 1 fi elif test -f "$readmehtml"; then readmehtmlcoll="" if pmdflagset "catpsu"; then readmehtmlcoll="$patchdir/README-PSU.html" elif pmdflagset "catcpu"; then readmehtmlcoll="$patchdir/README-CPU.html" elif pmdflagset "sbp"; then readmehtmlcoll="$patchdir/README-SBP.html" else readmehtmlcoll="$patchdir/README-$patchno-$LTIMESTAMP.html" fi if cp "$readmehtml" "$readmehtmlcoll" 1>&3 2>&1; then docflag="*" echo "This patch contains a \"README.html\" file. MOPatch extracted it to" 1>&6 echo " $readmehtmlcoll" 1>&6 echo "Please check that file for installation information." 1>&6 echo 1>&6 else perror "Cannot extract file \"README.html\" to patch base directory \"$patchdir\"."; continue 1 fi elif pmdflagset "rdmhtml"; then docflag="*" echo "This patch contains a \"README.html\" file in a non-standard" 1>&6 echo "location. Please check it for installation information." 1>&6 echo 1>&6 elif pmdflagset "rdmtxt"; then docflag="*" echo "This patch contains a \"README.txt\" file in a non-standard" 1>&6 echo "location. Please check it for installation information." 1>&6 echo 1>&6 elif pmdflagset "nonsmpl" && # "patch is not part of an SBP" ( pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "sbp" 1>/dev/null && exit 1 || : ) && { # prefer readmes from tracking bugs readmeids=`pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "trkbug" patchflags "~" "rdmhtml"` || readmeids=`pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "trkbug" patchflags "~" "rdmtxt"` || readmeids=`pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "rdmhtml"` || readmeids=`pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "rdmtxt"` }; then docflag="-" echo "This patch is part of an n-apply patch or a patch bundle. It" 1>&6 echo "does not have a README file, but the following patches, that are" 1>&6 echo "part of the same bundle, have README files:" 1>&6 echo "" 1>&6 l_oldifs=$IFS; IFS=" "; set -f; set x $readmeids; shift; set +f; IFS=$l_oldifs for readmeid in "$@" do readmebase=`pmdget tbi $readmeid patchbase` printf ' %s\n' "$readmebase" 1>&6 done echo 1>&6 else docflag="*" if $MOPATCH_TEST_MIGRATE; then logerr "Cannot append file \"README.txt\" to readme collection." echo " Cannot find file \"README.txt\". Please check patch" 1>&6 echo " \"$patchbase\" for other README files." 1>&6 echo 1>&6 else echo "This patch does not contain a \"README.txt\" file nor a" 1>&6 echo "\"README.html\" file. Please check it for other installation" 1>&6 echo "information." 1>&6 echo 1>&6 fi fi # handle patch-specific documentation for psdoc in "pre" "post" "ini" do psdoctxt="$patchstage/$patchmlc/custom/$psdoc.txt" if test -f "$psdoctxt"; then # keep the readme parser in sync with this title if $MOPATCH_TEST_MIGRATE; then echo "Patch-specific $psdoc.txt of $patchbase:" 1>&6 echo "Patch-specific $psdoc.txt of $patchbase:" | sed 's/./=/g' 1>&6 2>&3 else echo "Patch-Specific Information from $psdoc.txt:" 1>&6 echo "Patch-Specific Information from $psdoc.txt:" | sed 's/./=/g' 1>&6 2>&3 fi echo 1>&6 if cat "$psdoctxt" 1>&6 2>&3; then echo 1>&6 else docflag="!" logerr "Cannot append file \"$psdoctxt\" to temporary readme." fi fi done exec 6>&- # append temporary readme file to readme collection if cat "$readmetmp" 1>&8; then : else perror "Cannot append temporary readme to readme collection."; continue 1 fi # strip temporary readme file and append it to readme # collection rdmstriplog="" if test $flag_readme_strip_log = 1; then rdmstriplog=1 else rdmstriplog=0 fi rdmnonstdp=0 if "$awk" -f "$rdmpawk" \ -v rdmstriplog=$rdmstriplog \ "$readmetmp" 1>"$readmesh" 2>&3 && . "$readmesh" 2>&3 6>"$readmesed" && sed -f "$readmesed" "$readmetmp" 1>&9 2>&3; then : else docflag="!" logerr "Cannot strip temporary readme and append to stripped readme collection." # append unstripped readme as a fallback cat "$readmetmp" 1>&9 fi if $MOPATCH_TEST_MIGRATE; then addtopatchlist installed elif test "X$docflag" != "X "; then addtopatchlist -f "$docflag" documented elif test $rdmnonstdp = 1; then addtopatchlist -f "+" documented else addtopatchlist documented fi out "Processing patch \"$patchbase\"...done." elif runmodep "apply"; then # do it! log "executing: ( cd \"$patchstage/$patchmlc\" && \"$opatch\" apply $opatchopts )" exitval="" applylog="$tmpdir/apply.log" if ( cd "$patchstage/$patchmlc" 1>&3 2>&1 && "$opatch" apply $opatchopts ) 1>"$applylog" 2>&1; then exitval=0 else exitval=$? fi cat "$applylog" 1>&3 2>&1 # parse OPatch output if opovars=`cut -b1-1000 "$applylog" 2>&3 | "$awk" -f "$opopawk" \ -v opver="$opver" \ -v exitval=$exitval \ -v mode="apply" 2>&3` && ( eval "$opovars" ) 1>&3 2>&1; then eval "$opovars" else perror "Cannot parse OPatch output."; continue 1 fi # try to resolve conflicts crforce="" if test "X$opostatus" = "Xconflicts"; then conflicts=$opoconflicts # we have the new patch in $patchno and the old patches # in $conflicts. Now see which has precedence. crforce="" l_oldifs=$IFS; IFS=", $TAB$NL"; set -f; set x $crrules; shift; set +f; IFS=$l_oldifs for crrule in ${1+"$@"} do if test "X$crrule" = "X"; then : elif test "X$crrule" = "Xold"; then crforce=0 break elif test "X$crrule" = "Xnew"; then crforce=1 break elif test "X$crrule" = "Xpsu"; then newpsup="" if pmdflagset "psu" "catpsu"; then newpsup=1 else newpsup=0 fi oldpsup=0 l_oldifs=$IFS; IFS=" "; set -f; set x $conflicts; shift; set +f; IFS=$l_oldifs for conflict in "$@" do if ( pmdcache ins $conflict && pmdflagset "psu" "catpsu" ); then oldpsup=1 break fi done if test $newpsup = 1 && test $oldpsup = 0; then crforce=1 break elif test $newpsup = 0 && test $oldpsup = 1; then crforce=0 break fi elif test "X$crrule" = "Xcpu"; then newcpup="" if pmdflagset "catcpu" "cpumlc" || { pmdflagset "nonsmpl" && pmdfind tbi patchsrc = "$patchsrc" patchflags "~" "catcpu" 1>/dev/null }; then newcpup=1 else newcpup=0 fi oldcpup=0 l_oldifs=$IFS; IFS=" "; set -f; set x $conflicts; shift; set +f; IFS=$l_oldifs for conflict in "$@" do if ( pmdcache ins $conflict && pmdflagset "catcpu" "cpumlc" "cpurlb" ); then oldcpup=1 break fi done if test $newcpup = 1 && test $oldcpup = 0; then crforce=1 break elif test $newcpup = 0 && test $oldcpup = 1; then crforce=0 break fi elif numberp "$crrule"; then if test $crrule = $patchno; then crforce=1 break elif memberp " " $crrule "$conflicts"; then crforce=0 break fi fi done if test "X$crforce" = "X"; then crforce=1 fi if test $crforce = 1; then # do it again! log "executing: ( cd \"$patchstage/$patchmlc\" && \"$opatch\" apply -force $opatchopts )" exitval="" applylog="$tmpdir/apply.log" if ( cd "$patchstage/$patchmlc" 1>&3 2>&1 && "$opatch" apply -force $opatchopts ) 1>"$applylog" 2>&1; then exitval=0 else exitval=$? fi cat "$applylog" 1>&3 2>&1 # parse OPatch output if opovars=`cut -b1-1000 "$applylog" 2>&3 | "$awk" -f "$opopawk" \ -v opver="$opver" \ -v exitval=$exitval \ -v mode="forcedapply" 2>&3` && ( eval "$opovars" ) 1>&3 2>&1; then eval "$opovars" else perror "Cannot parse OPatch output."; continue 1 fi # ignore conflict warnings if verstest "$opver" -ge "11.2.0.1.1" || verstest "$opver" -ge "11.1.0.6.9" || verstest "$opver" -ge "10.2.0.4.9" || verstest "$opver" -ge "10.2.0.5.0"; then patchwtbis="${patchwtbis}67619${NL}" # resource S_REVISED_CONFLICT else patchwtbis="${patchwtbis}67012${NL}" # resource S_CONFLICT fi fi fi # determine und brush up OPatch log file name. Used in # messages only. if test -f "$opologfile"; then if ohre=`printf '%s\n' "$ORACLE_HOME" | quotemeta -s '/' 2>&3` && oplfn=`echo "$opologfile" | sed 's/^'"$ohre"'\//$ORACLE_HOME\//' 2>&3`; then opologfile=$oplfn fi else opologfile="" fi # if the installation was successful, check for patches that # have been rolled back due to patch conflict or superset # installation if test "X$opostatus" = "Xsuccess"; then l_oldifs=$IFS; IFS=" "; set -f; set x $oporbps; shift; set +f; IFS=$l_oldifs for rbp in ${1+"$@"} do xmessage="" if test "X$crforce" != "X" && test $crforce = 1; then xmessage=" (conflicted with $patchbase)" else xmessage=" (superseeded by $patchbase)" fi addtopatchlist uninstalled -n $rbp "$xmessage" if pmdcpmv -m ins rlb $rbp $rbp; then : else logerr "Cannot mark patch $rbp as rolled back." fi # determine make lines of rolled back patch and append # them to those of the patch just installed if rlbmakes=`pmdget rlb $rbp patchmakes`; then : else logerr "Cannot determine make lines of patch $rbp." fi if test "X$rlbmakes" != "X"; then # "$patchmakes" may contain a true newline-list (if it # has been initialized from "$pmdpatchmakes"), so be # careful to add a final newline in this case case $patchmakes in ""|*$NL) : ;; *) patchmakes="$patchmakes$NL" ;; esac patchmakes="$patchmakes$rlbmakes$NL" fi # determine post-installation instructions for patches # that were rolled back as a result of conflict # resolution. For superseeded patches no further # post-installation instructions should be required than # those given by the superset patch. if test "X$crforce" != "X" && test $crforce = 1; then if patchflaginfo=`pmdcache rlb $rbp && pmdflaginfo`; then : else logerr "Cannot determine post-installation instructions of patch $rbp." fi l_oldifs=$IFS; IFS="&"; set -f; set x $patchflaginfo; shift; set +f; IFS=$l_oldifs piiflag=$2 if test "X$piiflag" != "X "; then addtopatchlist -f "$piiflag" uninstalledpii -n "$rbp" fi fi done fi if test "X$opostatus" = "Xerror"; then xmessage="$NL OPatch log file:$NL $opologfile" perror -c opatcherror "Cannot apply patch." "$xmessage"; continue 1 elif test "X$opostatus" = "Xfatal"; then addtopatchlist fatal xmessage="$NL OPatch log file:$NL $opologfile" perror -c opatcherror "Cannot apply patch due to fatal error." "$xmessage"; continue 1 elif test "X$opostatus" = "Xonlntooffl"; then xmessage="$NL OPatch log file:$NL $opologfile" pskip -f "@" installedskipped "Online patch already installed." "$xmessage"; continue 1 elif test "X$opostatus" = "Xoffltoonln"; then xmessage="$NL OPatch log file:$NL $opologfile" pskip -f "@" installedskipped "Offline patch already installed." "$xmessage"; continue 1 elif test "X$opostatus" = "Xsubset"; then xmessage="$NL OPatch log file:$NL $opologfile" pskip -f "*" installedskipped "Superset patch already installed." "$xmessage"; continue 1 elif test "X$opostatus" = "Xprereqs"; then xmessage="$NL missing prereqs: $opoprereqs$NL OPatch log file:$NL $opologfile" pskip -c conflicterror prereqskipped "Missing prerequisite patches." "$xmessage"; continue 1 elif test "X$opostatus" = "Xconflicts"; then xmessage="$NL conflicts with: $opoconflicts$NL OPatch log file:$NL $opologfile" pskip -c conflicterror conflictskipped "Patch conflicts." "$xmessage"; continue 1 fi # append make lines to link script if test $ilink = 0; then l_oldifs=$IFS; IFS="$NL"; set -f; set x $patchmakes; shift; set +f; IFS=$l_oldifs for patchmake in ${1+"$@"} do l_oldifs=$IFS; IFS="&"; set -f; set x $patchmake; shift; set +f; IFS=$l_oldifs mkd=$1 mkf=$2 mkt=$3 # remove any trailing slashes from the make directory. The # above split ensures that there are no newlines in "$mkd". case $mkd in */) mkd=`expr "X$mkd" : "X\(.*\)/$" 2>&3` ;; esac # check whether all make parameters are make targets and, # as such, indpendent of each other amkpi=1 # all make parameters independent set -f; set x $mkt; shift; set +f for mktitem in "$@" do if varnamep "$mktitem"; then : else amkpi=0 break fi done # handle make targets independently of each other if that # is possible if test $amkpi = 1; then set -f; set x $mkt; shift; set +f else # dummy split l_oldifs=$IFS; IFS="&"; set -f; set x $mkt; shift; set +f; IFS=$l_oldifs fi for mktitem in "$@" do if test $flag_ignore_makes = 1 && memberp " " "$mktitem" "$mttbis"; then : else # strip prefix from make directory mkd=`printf '%s\n' "$mkd" | sed 's/^%ORACLE_HOME%\///' 2>&3` printf "$LINKSCRIPTGENFS" \ "$ORACLE_HOME" "$mkd" "$mkf" "$make" "$mkf" "$mktitem" "$ORACLE_HOME" 1>&4 fi done done fi # handle warnings if test "X$opowarnings" = "X"; then addtopatchlist installed elif test $flag_ignore_warnings = 1; then awi=1 # all warnings ignored l_oldifs=$IFS; IFS=" "; set -f; set x $opowarnings; shift; set +f; IFS=$l_oldifs for warning in ${1+"$@"} do twi=0 # this warning ignored l_oldifs=$IFS; IFS="$NL"; set -f; set x $patchwtbis; shift; set +f; IFS=$l_oldifs for wtbi in ${1+"$@"} do case $wtbi in [0-9][0-9][0-9][0-9][0-9]) if test "X$warning" = "X$wtbi"; then twi=1 break fi ;; *) eval warningtexts=\${hash_opowarnings_"$warning"-} l_oldifs=$IFS; IFS="$NL"; set -f; set x $warningtexts; shift; set +f; IFS=$l_oldifs for warningtext in "$@" do if expr "XOUI-$warning:$warningtext" : "X$wtbi" 1>/dev/null 2>&3; then twi=1 break 2 fi done ;; esac done if test $twi = 0; then awi=0 break fi done if test $awi = 1; then # all warnings ignored - consider this patch being # installed OK addtopatchlist installed else xmessage="$NL OPatch log file:$NL $opologfile" addtopatchlist installedwarning "$xmessage" fi else xmessage="$NL OPatch log file:$NL $opologfile" addtopatchlist installedwarning "$xmessage" fi if pmdcpmv -c tbi ins $patchid $patchno; then : else logerr "Cannot mark patch as installed." fi # determine post-installation instructions if patchflaginfo=`pmdcache ins $patchno && pmdflaginfo`; then : else logerr "Cannot determine post-installation instructions." fi l_oldifs=$IFS; IFS="&"; set -f; set x $patchflaginfo; shift; set +f; IFS=$l_oldifs piiflag=$2 if test "X$piiflag" != "X "; then addtopatchlist -f "$piiflag" installedpii fi # re-calculate patch storage free space if test $psfsps = 1; then psfsp=`df $dfopts "$pstf" 2>&3 | grep "$DFRE" 2>&3 | sed 's/'"$DFSE"'/\1/' 2>&3` if test $flag_stress_test = 1 && test $flag_clean_up = 1; then out "patch storage free space raw: $psfsp" fi if numberp "$psfsp"; then # we need this "raw" value for later ppsfsp=$psfsp # take file system reserve into account if test $reserve != 0; then # d := max( 0, psfsp - reserve ) d=`echo "0k[0]sa $psfsp $reserve-d0>apq" | dc 2>&3` if numberp "$d"; then psfsp=$d else logerr "Cannot calculate \"$d\" as max( 0, $psfsp - $reserve )." psfsp=0 ppsfsp=0 psfsps=0 fi fi else logerr "Cannot determine patch storage free space from \"$psfsp\"." psfsp=0 ppsfsp=0 psfsps=0 fi if test $flag_free_space_log = 1; then if test $psfsps = 1; then log "patch storage free space: $psfsp KBytes on $psmp" else log "patch storage free space: " fi fi fi out "Processing patch \"$patchbase\"...done." if test $cusp = 1; then # determine whether to clean up patch storage cleanup="" if test $cufr -gt 0; then cumod=`expr \( $installedn + $installedwarningn \) % $cufr 2>&3` if test $cumod = 0; then cleanup=1 else cleanup=0 fi elif test $psfsps = 1 && test $psrsps = 1; then # d := (psrsp > psfsp) ? 1 : 0 d=`echo "0k[sb]sa 1 0 $psfsp $psrsp>apq" | dc 2>&3` if test "X$d" = "X1"; then cleanup=1 elif test "X$d" = "X0"; then cleanup=0 else logerr "Cannot calculate \"$d\" as ($psrsp > $psfsp) ? 1 : 0." cleanup=0 fi else cleanup=0 fi # clean up patch storage, if required pschmin="" # patch storage change minimum pschmax="" # patch storage change maximum if test $cleanup = 1 && test $flag_clean_up = 1; then verbose out "Cleaning up patch storage..." # OPVD (10.2.0.2.4): clean up lock file since opatch # cleanup may fail to do so culog="$tmpdir/cleanup.log" log "executing: \"$opatch\" util cleanup $opatchcuopts" if "$opatch" util cleanup $opatchcuopts 1>"$culog" 2>&1 && { test -s "$ORACLE_HOME/.patch_storage/patch_locked" || rm -f "$ORACLE_HOME/.patch_storage/patch_locked" 1>&3 2>&1 }; then # closing "...done." is logged below cat "$culog" 1>&3 2>&1 # determine patch storage allocated space (in bytes) # before and after clean-up CURE='^Size of directory ".*" (before|after) cleanup is [0-9][0-9]* bytes\.$' CUBSE='^Size of directory ".*" before cleanup is \([0-9][0-9]*\) bytes\.$' CUASE='^Size of directory ".*" after cleanup is \([0-9][0-9]*\) bytes\.$' psaspprepost=`egrep "$CURE" "$culog" 2>&3 | sed 's/'"$CUBSE"'/\1/;s/'"$CUASE"'/\1/' 2>&3` l_oldifs=$IFS; IFS="$NL"; set -f; set x $psaspprepost; shift; set +f; IFS=$l_oldifs psasppre=$1 psasppost=$2 # determine patch storage change minimum if numberp "$psasppre" && numberp "$psasppost"; then # d := (psasppre - psasppost) / 2048 d=`echo "0k $psasppre $psasppost-2048/pq" | dc 2>&3` # fail silently if the above calculation failed - # should not happen too often, anyway if numberp "$d" && test $flag_stress_test = 0; then pschmin=$d elif test $psrsps = 1; then pschmin=$lss else pschmin=102400 fi else logerr "Cannot determine patch storage freed space from \"$psaspprepost\"." if test $psrsps = 1; then pschmin=$lss else pschmin=102400 fi fi # determine patch storage change maximum if test $psrsps = 1; then pschmax=$lss else pschmax=1024 fi if test $flag_stress_test = 1; then out "patch storage change minimum: $pschmin" out "patch storage change maximum: $pschmax" fi cleanedup=1 else cat "$culog" 1>&3 2>&1 out "Cleaning up patch storage...failed." logerr -c opatcherror "Cannot clean up patch storage." pschmin=0 pschmax=0 cleanedup=0 fi else pschmin=0 pschmax=0 cleanedup=0 fi # re-calculate patch storage free space after cleaning up. # This is a bit tricky since some file systems do not # immediately report all free blocks to the operating system # after unlinking files. So we first wait for the "df" # results to change substantially (at least by pschmin), and # then we wait for them to not change too much (at most by # pschmax). This heuristic does not really help if there is # other activtiy on the disk. But timeouts guarantee that # the code works in this case, too. if test $cleanedup = 1; then dfcount=0 while test $psfsps = 1 && test $dfcount -lt $dfloop; do psfsp=`df $dfopts "$pstf" 2>&3 | grep "$DFRE" 2>&3 | sed 's/'"$DFSE"'/\1/' 2>&3` if test $flag_stress_test = 1; then out "patch storage free space raw: $psfsp" fi if numberp "$psfsp"; then : else logerr "Cannot determine patch storage free space from \"$psfsp\"." psfsp=0 ppsfsp=0 psfsps=0 break fi # d := abs( psfsp - ppsfsp ) < pschmin ? 1 : 0 d=`echo "0k[_1*]sa[sc]sb 1 0 $psfsp $ppsfsp-d0>a $pschmin>bpq" | dc 2>&3` if test "X$d" = "X0"; then ppsfsp=$psfsp break elif test "X$d" != "X1"; then logerr "Cannot calculate \"$d\" as abs( $psfsp - $ppsfsp ) < $pschmin ? 1 : 0." psfsp=0 ppsfsp=0 psfsps=0 break fi sleep $dfslpi 1>&3 2>&1 dfcount=`expr $dfcount + 1 2>&3` done dfcount=0 while test $psfsps = 1 && test $dfcount -lt $dfloop; do psfsp=`df $dfopts "$pstf" 2>&3 | grep "$DFRE" 2>&3 | sed 's/'"$DFSE"'/\1/' 2>&3` if test $flag_stress_test = 1; then out "patch storage free space raw: $psfsp" fi if numberp "$psfsp"; then : else logerr "Cannot determine patch storage free space from \"$psfsp\"." psfsp=0 ppsfsp=0 psfsps=0 break fi # d := abs( psfsp - ppsfsp ) > pschmax ? 1 : 0 d=`echo "0k[_1*]sa[sc]sb 1 0 $psfsp $ppsfsp-d0>a $pschmax&3` if test "X$d" = "X0"; then break elif test "X$d" != "X1"; then logerr "Cannot calculate \"$d\" as abs( $psfsp - $ppsfsp ) > $pschmax ? 1 : 0." psfsp=0 ppsfsp=0 psfsps=0 break fi sleep $dfslpi 1>&3 2>&1 dfcount=`expr $dfcount + 1 2>&3` ppsfsp=$psfsp done # take file system reserve into account if test $psfsps = 1 && test $reserve != 0; then # d := max( 0, psfsp - reserve ) d=`echo "0k[0]sa $psfsp $reserve-d0>apq" | dc 2>&3` if numberp "$d"; then psfsp=$d else logerr "Cannot calculate \"$d\" as max( 0, $psfsp - $reserve )." psfsp=0 ppsfsp=0 psfsps=0 fi fi if test $flag_free_space_log = 1; then if test $psfsps = 1; then log "patch storage free space: $psfsp KBytes on $psmp" else log "patch storage free space: " fi fi out "Cleaning up patch storage...done." fi else # clean-up not supported cleanedup=0 fi fi done # remove leading and trailing newlines documented=`echo "$documented" | sed 1d 2>&3` installed=`echo "$installed" | sed 1d 2>&3` installedwarning=`echo "$installedwarning" | sed 1d 2>&3` failed=`echo "$failed" | sed 1d 2>&3` fatal=`echo "$fatal" | sed 1d 2>&3` uninstalled=`echo "$uninstalled" | sed 1d 2>&3` conflictskipped=`echo "$conflictskipped" | sed 1d 2>&3` prereqskipped=`echo "$prereqskipped" | sed 1d 2>&3` nonpatchskipped=`echo "$nonpatchskipped" | sed 1d 2>&3` installedskipped=`echo "$installedskipped" | sed 1d 2>&3` fatalskipped=`echo "$fatalskipped" | sed 1d 2>&3` signalskipped=`echo "$signalskipped" | sed 1d 2>&3` uninstalledpii=`echo "$uninstalledpii" | sed 1d 2>&3` installedpii=`echo "$installedpii" | sed 1d 2>&3` ################################ # # finally clean up patch storage # ################################ # flag cleanedup may be 1 either because the previous apply was # cleaned up or because there was no apply at all. In the latter # case, clean up if and only if the link script also would be # executed, since this is typically the last step in a sequence # of multiple calls to MOPatch. This is not entirely consistent # with the policy of execution of intermediate clean-ups, since # those are done even in case of previous failed installations. # But this is just the way it is. if runmodep "apply" && test $cusp = 1 && { test $cleanedup = 0 || { test $installedn = 0 && test $installedwarningn = 0 && test -s "$linkscript" && test $conflictskippedn = 0 } } && test $failedn = 0 && test $signalled = 0 && test $flag_clean_up_final = 1; then out out "Cleaning up patch storage..." # OPVD (10.2.0.2.4): clean up lock file since opatch cleanup # may fail to do so log "executing: \"$opatch\" util cleanup $opatchcuopts" if "$opatch" util cleanup $opatchcuopts 1>&3 2>&1 && { test -s "$ORACLE_HOME/.patch_storage/patch_locked" || rm -f "$ORACLE_HOME/.patch_storage/patch_locked" 1>&3 2>&1 }; then out "Cleaning up patch storage...done." else out "Cleaning up patch storage...failed." logerr -c opatcherror "Cannot clean up patch storage." fi fi ##################### # # process link script # ##################### if test $ilink = 0; then # close link script exec 4>&- if runmodep "apply" && test -s "$linkscript" && test $nomake = 0 && test $failedn = 0 && test $conflictskippedn = 0 && test $signalled = 0 && sort "$linkscript" 2>&3 | uniq 1>"$tmpdir/linkscript.tmp" 2>&3 && mv "$tmpdir/linkscript.tmp" "$linkscript" 1>&3 2>&1; then out out "Executing link script \"$linkscript\"..." log "executing: /bin/sh \"$linkscript\"" if \ /bin/sh "$linkscript" 1>&3 2>&1; then out "Executing link script \"$linkscript\"...done." if rm -f "$linkscript" 1>&3 2>&1; then : else logerr "Cannot clean up link script \"$linkscript\"." fi linkfailed=0 else out "Executing link script \"$linkscript\"...failed." logerr -c linkerror "Cannot execute link script." linkfailed=1 fi elif runmodep "apply" && test -s "$linkscript" && test $nomake = 0 && test $failedn = 0 && test $conflictskippedn = 0 && test $signalled = 0; then # link script preparation failed. Mark as internal error but # otherwise be silent about it (should not happen, anyway). internalerror=1 linkfailed=2 elif runmodep "apply" && test -s "$linkscript"; then # prepare link script for manual execution if user demanded # that or in case of errors, conflicts, or user interrupt out out "Preparing link script \"$linkscript\"..." if sort "$linkscript" 2>&3 | uniq 1>"$tmpdir/linkscript.tmp" 2>&3 && mv "$tmpdir/linkscript.tmp" "$linkscript" 1>&3 2>&1; then out "Preparing link script \"$linkscript\"...done." else out "Preparing link script \"$linkscript\"...failed." logerr "Cannot prepare link script for manual execution." fi linkfailed=2 else # link script empty or running in documentation mode linkfailed=2 fi fi ############################## # # get post-run patch inventory # ############################## out out "Getting post-run patch inventory..." # determine installed patches ips="" ipsvp="" # installed patches valid postinvlog="$tmpdir/postinv.log" log "executing: \"$opatch\" lsinventory $opatchlsiopts" if "$opatch" lsinventory $opatchlsiopts 1>"$postinvlog" 2>&1; then cat "$postinvlog" 1>&3 2>&1 ips=`egrep "$PATCHINVEE" "$postinvlog" 2>&3 | sed 's/'"$PATCHINVSE"'/\1/;s/'"$PSUINVSE"'/\1/;s/'"$PTCHONLNINVSE"'/\1/' 2>&3 | sort -n 2>&3` ipsvp=1 else cat "$postinvlog" 1>&3 2>&1 out "Getting post-run patch inventory...failed." logerr -c opatcherror "Cannot get post-run patch inventory." ips="INVALID" ipsvp=0 fi # verify installed patches if test $ipsvp = 1; then l_oldifs=$IFS; IFS="$NL"; set -f; set x $ips; shift; set +f; IFS=$l_oldifs for patchid in ${1+"$@"} do if memberp " " $patchid "$pmdinsids"; then : else logerr "Cannot verify installed patches ($patchid missing)." ipsvp=0 break fi done fi if test $ipsvp = 1; then l_oldifs=$IFS; IFS=" "; set -f; set x $pmdinsids; shift; set +f; IFS=$l_oldifs for patchid in ${1+"$@"} do if memberp "$NL" $patchid "$ips"; then : else logerr "Cannot verify installed patches ($patchid unexpected)." ipsvp=0 break fi done fi if test "X$ips" != "XINVALID"; then out "Getting post-run patch inventory...done." else out "Getting post-run patch inventory...failed." fi ################################# # # post-process readme collections # ################################# if runmodep "doc"; then # close readme collections exec 9>&- exec 8>&- if test ! -s "$readmecoll" || { readmecolltmp="$tmpdir/readmes.txt" && readmescollb=`basenamef "$readmescoll" 2>&3` && rdmheader "$DATE" "$readmescollb" 1>>"$readmecolltmp" 2>&3 && sed 's/^#//' "$readmecoll" 1>>"$readmecolltmp" 2>&3 && rdmfooter 1>>"$readmecolltmp" 2>&3 && mv "$readmecolltmp" "$readmecoll" 1>&3 2>&1 }; then : else logerr "Cannot post-process readme collection \"$readmecoll\"." fi if test ! -s "$readmescoll" || { readmescolltmp="$tmpdir/readmes.txt" && readmecollb=`basenamef "$readmecoll" 2>&3` rdmsheader "$DATE" "$readmecollb" 1>>"$readmescolltmp" 2>&3 && sed 's/^#//' "$readmescoll" 1>>"$readmescolltmp" 2>&3 && rdmsfooter 1>>"$readmescolltmp" 2>&3 && mv "$readmescolltmp" "$readmescoll" 1>&3 2>&1 }; then : else logerr "Cannot post-process stripped readme collection \"$readmecoll\"." fi fi ############### # # write summary # ############### # patch installation or check status out if runmodep "apply"; then out "Patch Installation Status:" out "--------------------------" else if $MOPATCH_TEST_MIGRATE; then out "Patch Check Status:" out "-------------------" else out "Patch Documentation Status:" out "---------------------------" fi fi # failed patches. Use a maximum line width of 65 characters in # this and all following messages. if test $failedn != 0; then if runmodep "apply"; then out out "Failed to install $failedn of $tbipn patches:" out "$failed" else if $MOPATCH_TEST_MIGRATE; then out out "Failed to check $failedn of $tbipn patches:" out "$failed" else out out "Failed to document $failedn of $tbipn patches:" out "$failed" fi fi fi # fatally failed patches if test $fataln != 0; then out out "Of the patches mentioned above, patch" out "$fatal" out "failed to install since OPatch experienced a fatal error. Please" out "refer to the corresponding OPatch log file to see whether OPatch" out "was able to completely restore the Oracle Home to a consistent" out "state." out out "If OPatch was not able to restore the Oracle Home, follow the" out "instructions provided in the OPatch log file to manually restore" out "the Oracle Home." out out "DO NOT TRY TO RUN OPATCH OR MOPATCH AGAIN BEFORE THE ORACLE HOME" out "WAS COMPLETELY RESTORED, AS THIS MAY RESULT IN AN INCONSISTENT" out "ORACLE HOME, WHICH CANNOT BE RESTORED TO A CONSISTENT STATE." out "RESOLVE THE FATAL ERROR FIRST BEFORE TRYING TO RESOLVE ANY OTHER," out "NON-FATAL ERRORS OR PATCH CONFLICTS." out out "Contact Oracle or SAP Support if in doubt whether your Oracle" out "Home is in a consistent state." elif test $failedn != 0; then out out "Please check any OPatch log files mentioned above and log file" out " $logfile" out "for details. Resolve the problems and re-run MOPatch." fi # skipped patches (previous fatal errors) if test $fatalskippedn != 0; then out out "Skipped $fatalskippedn of $tbipn patches due to the above fatal error:" out "$fatalskipped" fi # skipped patches (user interrupt) if test $signalskippedn != 0; then out out "Skipped $signalskippedn of $tbipn patches due to user interrupt:" out "$signalskipped" out out "Re-run MOPatch to install the patches." fi # skipped patches (conflicts) if test $conflictskippedn != 0; then out out "Skipped $conflictskippedn of $tbipn patches due to patch conflicts:" out "$conflictskipped" out out "Please check the OPatch log files mentioned above and log file" out " $logfile" out "for details. Resolve the conflicts. Install the patches" out "manually or re-run MOPatch." fi # skipped patched (missing prereq patches) if test $prereqskippedn != 0; then out out "Skipped $prereqskippedn of $tbipn patches due to missing prerequisite patches:" out "$prereqskipped" out out "Please check the OPatch log files mentioned above and log file" out " $logfile" out "for details. Provide the missing prerequisite patches. Install" out "them and the skipped patches manually or re-run MOPatch." fi # skipped patches (bad format) if $MOPATCH_TEST_MIGRATE; then if test $nonpatchskippedn != 0; then out out "Skipped $nonpatchskippedn of $tbipn patches since they do not seem to be plain OPatch" out "patches:" out "$nonpatchskipped" fi else if test $nonpatchskippedn != 0; then out out "Skipped $nonpatchskippedn of $tbipn patches since they do not seem to be plain OPatch" out "patches or since they are otherwise not appropriate for installing:" out "$nonpatchskipped" fi fi if test "X$nonpatchskippedf" != "X"; then out fi if $MOPATCH_TEST_MIGRATE; then case $nonpatchskippedf in *"*"*) out "Patches marked with a \"*\" were skipped since they are Critical" out "Patch Updates (CPUs). CPUs require special attention and, hence," out "are not automatically installed by MOPatch. Refer to SAP note" out "850306 for more information." ;; esac else case $nonpatchskippedf in *"*"*) out "Patches marked with a \"*\" were skipped since they are Critical" out "Patch Updates (CPUs) or parts of a CPU and flag \"apply_cpu\" was" out "disabled." esac case $nonpatchskippedf in *"!"*) out "Patches marked with a \"!\" were skipped since they are Patchset" out "Updates (PSUs) and flag \"apply_cpu\" was disabled." ;; esac fi if $MOPATCH_TEST_MIGRATE; then case $nonpatchskippedf in *"+"*) out "Patches marked with a \"+\" were skipped since they are CRS" out "patches. CRS patches must not be installed in an RDBMS home, but" out "in a CRS home." ;; esac else case $nonpatchskippedf in *"+"*) out "Patches marked with a \"+\" were skipped since they are CRS patches" out "or part of a CRS bundle patch. CRS patches must not be installed" out "in an RDBMS home, but in a CRS home." ;; esac fi case $nonpatchskippedf in *"-"*) out "Patches marked with a \"-\" were skipped since they are Database" out "Vault special patches. These require a special installation" out "procedure. See SAP note 1020937." ;; esac if $MOPATCH_TEST_MIGRATE; then : else case $nonpatchskippedf in *"@"*) if test $onlnmode = 1; then out "Patches marked with a \"@\" were skipped since they are offline" out "patches and MOPatch is running in online mode." else out "Patches marked with a \"@\" were skipped since they are online" out "patches and MOPatch is running in offline mode. For each online" out "patch there is a usually a corresponding offline patch that fixes" out "the same problem. Check whether the corresponding offline" out "patches were successfully installed." fi ;; esac case $nonpatchskippedf in *"#"*) if test "X$ohtype" = "Xgi"; then out "Patches marked with a \"#\" were skipped since they are RDBMS" out "patches and the current Oracle Home is a Grid Infrastructure" out "Home." else out "Patches marked with a \"#\" were skipped since they are Grid" out "Infrastructure patches and the current Oracle Home is an RDBMS" out "Home." fi ;; esac fi if test $nonpatchskippedn != 0; then out out "Please check the listed patches and, if required, install them" out "manually according to their installation instructions." fi # skipped patches (already installed) if test $installedskippedn != 0; then out out "Skipped $installedskippedn of $tbipn patches since they were already installed:" out "$installedskipped" fi if test "X$installedskippedf" != "X"; then out fi case $installedskippedf in *"*"*) out "Patches marked with a \"*\" were skipped since a superset patch" out "comprising them was already present. Refer to the OPatch log" out "files mentioned above for information on the superset patches." esac case $installedskippedf in *"+"*) out "Patches marked with a \"+\" were skipped since a patch with the" out "same patch ID but with a newer creation date was already present." esac if $MOPATCH_TEST_MIGRATE; then : else case $installedskippedf in *"@"*) if test $onlnmode = 1; then out "Patches marked with a \"@\" were skipped since an offline patch" out "with the same patch ID is already present." else out "Patches marked with a \"@\" were skipped since an online patch" out "with the same patch ID is already present." fi ;; esac fi # installed patches if test $installedn != 0; then if runmodep "apply"; then out out "Installed $installedn of $tbipn patches successfully:" out "$installed" elif $MOPATCH_TEST_MIGRATE; then out out "Checked $installedn of $tbipn patches successfully:" out "$installed" out out "Please refer to the READMEs generated in" out " $readmescoll" out "for patch-specific installation instructions before continuing" out "patch installation." fi fi if $MOPATCH_TEST_MIGRATE; then : else if test $documentedn != 0; then out out "Checked $documentedn of $tbipn patches successfully:" out "$documented" if test "X$documentedf" != "X"; then out out "All specially marked patches in the list above contain non-" out "standard documentation and, hence, may require special" out "installation instructions. Please refer to the READMEs" out "collected in" out " $readmescoll" out "for more information." fi fi fi # installed patches with warnings if test $installedwarningn != 0; then out out "Installed $installedwarningn of $tbipn patches with warnings:" out "$installedwarning" out out "Please check the OPatch log files mentioned above or log file" out " $logfile" out "for details." fi if $MOPATCH_TEST_MIGRATE; then # uninstalled patches if test $uninstalledn = 1; then out out "Uninstalled 1 patch since it was superseeded by a newer patch:" out "$uninstalled" elif test $uninstalledn != 0; then out out "Uninstalled $uninstalledn patches since they were superseeded by newer" out "patches:" out "$uninstalled" fi else # uninstalled patches if test $uninstalledn = 1; then out out "Uninstalled 1 patch since it was superseeded by or conflicted" out "with a newly installed patch:" out "$uninstalled" elif test $uninstalledn != 0; then out out "Uninstalled $uninstalledn patches since they were superseeded by or" out "conflicted with newly installed patches:" out "$uninstalled" fi fi # patch inventory status out out "Patch Inventory Status:" out "-----------------------" if test "X$ips" = "X"; then out "No patches installed in Oracle Home $ORACLE_HOME." elif test "X$ips" = "XINVALID"; then out "Patches installed in Oracle Home $ORACLE_HOME:" out " " else out "Patches installed in Oracle Home $ORACLE_HOME:" l_oldifs=$IFS; IFS="$NL"; set -f; set x $ips; shift; set +f; IFS=$l_oldifs for patchid in "$@" do if $MOPATCH_TEST_MIGRATE; then out " $patchid" else if pmdcache ins $patchid; then patchflaginfo=`pmdflaginfo` l_oldifs=$IFS; IFS="&"; set -f; set x $patchflaginfo; shift; set +f; IFS=$l_oldifs patchmode=$1 patchflags=${3-} if test "X$patchflags" != "X"; then out "$patchmode $pmdpatchno ($patchflags)" else out "$patchmode $pmdpatchno" fi else out " $patchid" fi fi done fi # link status if test $ilink = 0; then out out "Link Status:" out "------------" if test $linkfailed = 0; then out "Link script \"$linkscript\" executed successfully." elif test $linkfailed = 1; then out "Failed to execute link script. Please check the log file" out " $logfile" out "for details. Resolve the problems. Re-start MOPatch to execute" out "the link script or execute it manually as" out " /bin/sh \"$linkscript\"" elif test $linkfailed = 2 && runmodep "doc"; then if $MOPATCH_TEST_MIGRATE; then out "Link script \"$linkscript\" not executed in dry-run mode." else out "Link script \"$linkscript\" not executed in documentation mode." fi elif test $linkfailed = 2 && test ! -s "$linkscript"; then out "Link script \"$linkscript\" empty, not executed." elif test $linkfailed = 2 && test $nomake = 1; then out "Link script not executed due to option \"-n\" specified to" out "MOPatch. Please execute the link script manually as" out " /bin/sh \"$linkscript\"" elif test $linkfailed = 2 && test $failedn != 0; then out "Link script not executed due to patch installation failures." out "Please check the log file" out " $logfile" out "for details. Resolve the problems. Re-start MOPatch to execute" out "the link script or execute it manually as" out " /bin/sh \"$linkscript\"" elif test $linkfailed = 2 && test $conflictskippedn != 0; then out "Link script not executed due to patch conflicts. Please check" out "the log file" out " $logfile" out "for details. Resolve the conflicts as described in SAP note" out "1027012. Re-start MOPatch to execute the link script or execute" out "it manually as" out " /bin/sh \"$linkscript\"" elif test $linkfailed = 2 && test $signalled != 0; then out "Link script not executed due to user interrupt." out "Re-start MOPatch to execute the link script or execute it" out "manually as" out " /bin/sh \"$linkscript\"" elif test $linkfailed = 2; then out "Link script \"$linkscript\" not executed due to script" out "preparation failures." else logerr "Internal error: Invalid link script status \"$linkfailed\"." fi fi ######################## # # miscellaneous clean-up # ######################## # close log file logerrhdl=2 logopen=0 if test "X$xlogfile" = "X"; then exec 3>&- fi exit `exitvalf`