# $Header: ecmApplyOPatch.pl 13-sep-2007.05:23:45 sejain Exp $ # # Copyright (c) 2003, 2007, Oracle. All rights reserved. # # DESCRIPTION # ECM script to patch Oracle home with OPatch Interim patches # # USAGE # perl ecmApplyOPatch.pl [] [] # # command : apply | version # # options # -delay : Delay between retries if -retry (default 30) # -force : Rollback conflicting patches without prompt # -invPtrLoc : Path to location of oraInst.loc file # -jre : Path to JRE to use instead of in $OH # -jdk : Path to JDK to use instead of in $OH # -local : Patch the local node only in RAC env # -minimize_downtime : Only applies to RAC env # -no_bug_superset : Error if patch is a bug-superset of installed patch # -no_inventory : Bypass the OUI inventory for reading|updates # -oh : The directory to use for default $ORACLE_HOME # -patchid : Supply PSE patch number # -retry : Retry times to get inventory lock (default 10) # -silent : Suppresses any user-interaction (default) # -verbose : Output more patching info (default) # # params # : Location of patch files (default cwd) # # NOTES # # # MODIFIED (MM/DD/YY) # sejain 09/13/07 - bug-6410550 : making files generic # sejain 07/02/07 - Backport sejain_bug-5917213 from main # sejain 06/26/07 - bug-5917213:fixing the copy issue with already staged patches. # rrawat 04/10/07 - Bug-5890451 # rrawat 05/21/07 - Backport rrawat_bug-5890451 from main # milshah 02/02/06 - Backport milshah_bug-5001091 from main # milshah 01/25/06 - Run emdpatch.pl in background only for Custom Agent # Patching # milshah 11/11/05 - change statusf to always right shift return code # shgangul 09/21/05 - Findfile patchset.rsp instead of looking at a # hardcoded location # shgangul 09/19/05 - Bug 4610114: Handle status output from OPatch # properly # shgangul 07/27/05 - Invoke oui, if emdpatch.pl or opatch not found # shgangul 07/15/05 - Set patch_path for already staged patches # shgangul 07/14/05 - support extra unknown parameters, -asm # milshah 07/12/05 - redirect output to log file for custom agent apply # script # pdasika 04/28/05 - # shgangul 04/27/05 - Add support for -stage_location # shgangul 01/31/05 - bug 3845819: MAC OS port # mgoodric 01/31/05 - move functions to ecmCommon.pl # shgangul 12/01/04 - Review comments for bug fix 3313446 # shgangul 11/25/04 - Bug 3313446: Look for emdpatch.pl before invoking # OPatch # mbhoopat 03/10/04 - linux port # nsharma 01/19/04 - Fix linux path for echo,hostname,pwd,rm and sh # mgoodric 02/13/04 - Fix File::Find on Windows # mgoodric 12/22/03 - Look for opatch.pl in OH/OPatch in Agent's home # mgoodric 12/07/03 - Support -retry and -delay options # mgoodric 09/19/03 - Fix broken quoting programs for NT # mgoodric 09/15/03 - Fix quoting filespecs for NT # mgoodric 09/08/03 - Support new 10g OPatch options # mgoodric 08/21/03 - mgoodric_fix_pref_cred_030816 # mgoodric 08/19/03 - Created # --- Set up necessary variables for proper running of this environment --- use strict; use English; use Cwd(); use Cwd; use File::Basename; use File::Find; use File::Path; use File::Spec(); use File::Spec::Functions qw (:ALL); use File::Copy(); use File::Copy; use FileHandle; use User::pwent; my $scriptName = File::Basename::basename($0); my $osmScriptDir = File::Basename::dirname($0); my $ecmCommon = File::Spec->catfile($osmScriptDir, 'ecmCommon.pl'); require "$ecmCommon"; # ------ Initialize global variables ------------------------------------- use constant COPYRIGHT => "Copyright \251 2003, 2004, Oracle. All rights reserved."; use constant VERSION => '10.1.0.2'; use constant C_APPLY => 'apply'; use constant C_VERSION => 'version'; use constant S_DELAY => '-delay'; use constant S_FORCE => '-force'; use constant S_HELP => '-help'; use constant S_INVPTRLOC => '-invPtrLoc'; use constant S_JRE => '-jre'; use constant S_JDK => '-jdk'; use constant S_LOCAL => '-local'; use constant S_ASM => '-asm'; use constant S_MINIMIZEDOWNTIME => '-minimize_downtime'; use constant S_NOBUGSUPERSET => '-no_bug_superset'; use constant S_NOINVENTORY => '-no_inventory'; use constant S_OH => '-oh'; use constant S_PATCHID => '-patchid'; use constant S_RETRY => '-retry'; use constant S_SILENT => '-silent'; use constant S_VERSION => '-version'; use constant S_VERBOSE => '-verbose'; use constant S_EMPTY => ''; use constant S_SPACE => ' '; use constant S_QUOTE => '"'; use constant S_APOSTROPHE => "'"; use constant B_TRUE => 1; use constant B_FALSE => 0; use constant E_SUCCESS => 0; use constant E_FAIL => 1 * (1 << 8); use constant E_NO_ENV => 2 * (1 << 8); use constant E_NO_OPATCHPL => 3 * (1 << 8); use constant E_NO_INVENTORY => 4 * (1 << 8); use constant E_NO_COMMAND => 5 * (1 << 8); use constant E_INV_COMMAND => 6 * (1 << 8); use constant E_INV_ARG => 7 * (1 << 8); use constant E_TOO_MANY => 8 * (1 << 8); use constant E_MISSING_ARG => 9 * (1 << 8); my @ORACLE_ASMs = (); # -asm mjgdb817,msdfsjk,sdnms23 my $patch_path = S_EMPTY; # location of patch directory my $patch_id = S_EMPTY; # patch number (e.g. 2944899) my $patch_loc = S_EMPTY; # location of patch files my $inv_loc = S_EMPTY; # OUI inventory location my $apply_cmd = S_EMPTY; # apply command my $apply_opt = S_SILENT; # defaults to -silent my $local_opt = S_EMPTY; # if -local specified my $PERL = $^X; # Perl executable my $EMDROOT = $ENV{'EMDROOT'}; my $ORACLE_HOME = $ENV{'ORACLE_HOME'}; my $PERL5LIB = $ENV{'PERL5LIB'}; my $status = E_SUCCESS; # used to display if a patch is successful my $ret_status = E_SUCCESS; # used for testing system commands my $enable_retry = B_FALSE; # used to enable -no_inventory retry my $isHeader = B_FALSE; # used to detect printHeader # --------------------- OSD platform-specific --------------------------- my $NULL_DEVICE = '/dev/null'; my $OPATCHPL = 'opatch.pl'; my $PATCHSH = 'patch.sh'; my $DOTSLASH = './'; my $ECHO = '/usr/bin/echo'; my $HOSTNAME = '/usr/bin/hostname'; my $PWD = '/usr/bin/pwd'; my $RMFR = '/usr/bin/rm -fr'; my $SHELL = '/usr/bin/sh'; if (($^O eq 'linux') || ($^O eq 'darwin') ) { $ECHO = '/bin/echo'; $HOSTNAME = '/bin/hostname'; $PWD = '/bin/pwd'; $RMFR = '/bin/rm -fr'; $SHELL = '/bin/sh'; } my $INVPTRLOCFILE = 'oraInst.loc'; my $INVPTRLOCFILEPATH = S_EMPTY; # --------------------- Subroutines ------------------------------------- # printUsage() # # Display our help frame # sub printUsage { print STDOUT <<_EOM_ Usage: perl emdApplyOPatch.pl [] [] command : apply | version options -delay : Delay between retries if -retry (default 30) -force : Rollback conflicting patches without prompt -invPtrLoc : Path to location of oraInst.loc file -jre : Path to JRE to use instead of in \$OH -jdk : Path to JDK to use instead of in \$OH -local : Patch the local node only in RAC env -minimize_downtime : Only applies to RAC env -no_bug_superset : Error if patch is a bug-superset of installed patch -no_inventory : Bypass the OUI inventory for reading|updates -oh : The directory to use for default \$ORACLE_HOME -patchid : Supply PSE patch number -retry : Retry times to get inventory lock (default 10) -silent : Suppresses any user-interaction (default) -verbose : Output more patching info (default) patch_loc : Location of patch files (default cwd) Example: apply -silent -force _EOM_ ; } # printVersion() # # Display our Copyright # sub printVersion { printf(STDOUT "\n%s Version %s\n%s\n\n", $scriptName, VERSION, COPYRIGHT); } # setupOSD() # # Setup OSD commands # sub setupOSD { if (isEmpty($EMDROOT)) { abortf(E_NO_ENV, "No definition for: EMDROOT"); } if (isEmpty($ORACLE_HOME)) { abortf(E_NO_ENV, "No definition for: ORACLE_HOME"); } if (isEmpty($PERL5LIB)) { $PERL5LIB = getPERL5LIB(); $ENV{'PERL5LIB'} = $PERL5LIB; } if (onWindows()) { $NULL_DEVICE = 'NUL'; $PATCHSH = 'patch.bat'; $DOTSLASH = S_EMPTY; $ECHO = 'echo'; $HOSTNAME = 'hostname.exe'; $PWD = 'cd'; $RMFR = 'erase /s /q'; $SHELL = 'cmd.exe /c'; } } # getNumericArg(, ) # # Parse the argument as numeric # # Return value # sub getNumericArg($$) { my ($opt, $i) = @_; my $value = S_EMPTY; if ($i < (scalar(@ARGV) - 1)) { $i += 1; if (isNumeric($ARGV[$i])) { $value = $ARGV[$i]; } else { printHeader($0, $#ARGV) if (!$isHeader); abortf(E_INV_ARG, "Invalid value: $opt $ARGV[$i]"); } } else { printHeader($0, $#ARGV) if (!$isHeader); abortf(E_MISSING_ARG, "Missing value: $opt"); } return $value; } # getStringArg(, ) # # Parse the argument as string # # Return value # sub getStringArg($$) { my ($opt, $i) = @_; my $value = S_EMPTY; if ($i < (scalar(@ARGV) - 1)) { $i += 1; $value = $ARGV[$i]; } else { printHeader($0, $#ARGV) if (!$isHeader); abortf(E_MISSING_ARG, "Missing value: $opt"); } return $value; } # parseArgs() # # Parse the arguments and store them away for future use # sub parseArgs { my $opt = S_EMPTY; my $argcount = scalar(@ARGV); my $i = 0; $patch_path = currentDir(); $opt = $ARGV[$i]; # command if (isEmpty($opt)) { #abortf(E_NO_COMMAND, "No command specified."); printUsage(); cleanAndExit(1); } if (isMatch(S_HELP, $opt)) { printUsage(); cleanAndExit(0); } if (isMatch(S_VERSION, $opt)) { printVersion(); cleanAndExit(0); } if (isEqual(C_APPLY, $opt) || isEqual(C_VERSION, $opt)) { $apply_cmd = $opt; } else { printHeader($0, $#ARGV) if (!$isHeader); #abortf(E_INV_COMMAND, "Invalid command: $opt"); logf("Command not recognised. Invalid command: $opt"); } for ($i++ ; $i < $argcount ; $i++) { $opt = $ARGV[$i]; next if (isEmpty($opt)); if (isEqual('-', substr($opt, 0, 1))) { if (isMatch(S_HELP, $opt)) { printUsage(); cleanAndExit(0); } if (isEqual(S_INVPTRLOC, $opt)) { $inv_loc = $opt . S_SPACE . fnQuote(getStringArg($opt, $i)); $i++; } elsif (isEqual(S_OH, $opt)) { $ORACLE_HOME = getStringArg($opt, $i); $ENV{'ORACLE_HOME'} = $ORACLE_HOME; $i++; } elsif (isMatch(S_PATCHID, $opt)) { $patch_id = getNumericArg($opt, $i); $i++; } elsif (isEqual(S_NOINVENTORY, $opt)) { $local_opt = S_EMPTY; # S_LOCAL and S_NOINVENTORY are exclusive $inv_loc = S_NOINVENTORY; $enable_retry = B_FALSE; } elsif (isEqual(S_LOCAL, $opt)) { $local_opt = $opt; } elsif (!isEqual(S_SILENT, $opt)) { $apply_opt .= S_SPACE . $opt; } elsif (isEqual(S_ASM, $opt)) { $i ++; # Parse the ASM list and store it in ASM array my $asmlist = $ARGV[$i]; chomp $asmlist; @ORACLE_ASMs = split(/&/, $asmlist); # Get a list of uniq ASMs my @tempasms = (); for(my $asmi = 0; $asmi < scalar(@ORACLE_ASMs); $asmi++) { my $uniq = 1; for(my $asmj = 0; $asmj < scalar(@tempasms); $asmj++) { if ($ORACLE_ASMs[$asmi] eq $tempasms[$asmj]) { $uniq = 0; last; } } if ($uniq == 1) { push(@tempasms, $ORACLE_ASMs[$asmi]); } } @ORACLE_ASMs = @tempasms; } } else { $apply_opt .= S_SPACE . fnQuote($opt); } } if (isEmpty($inv_loc)) { $INVPTRLOCFILEPATH = File::Spec->catfile($ORACLE_HOME, $INVPTRLOCFILE); if (-f $INVPTRLOCFILEPATH) { $inv_loc = S_INVPTRLOC . S_SPACE . fnQuote($INVPTRLOCFILEPATH); } } # if (isEmpty($patch_id)) # { # $patch_id = File::Basename::basename($patch_path); # } } # logf() # # Display the message with timestamp # sub logf($) { my ($msg) = @_; printf(STDOUT "\n%s - %s\n", scalar(localtime()), $msg); } # errorf(,) # # Display an error message # sub errorf($;$) { my ($status, $msg) = @_; $msg = S_EMPTY if (!defined $msg); $status = E_FAIL if (!defined $status); printf(STDERR "\n---------- Error Message ----------\n"); printf(STDERR "Error: %03d\n", statusf($status)); printf(STDERR "%s\n", $msg) if (!isEmpty($msg)); printf(STDERR "----------- End Message -----------\n"); } # abortf(,) # # Display a fatal error message and terminate # sub abortf($;$) { my ($status, $msg) = @_; errorf($status, $msg); logf("Patching aborted."); cleanAndExit($status); } # statusf() # # Returns the termination status of command # sub statusf($) { my ($status) = @_; $status = E_FAIL if (!defined $status); $status = ($status >> 8); #$status = ($status >> 8) if ($status >= E_FAIL); return $status; } # cleanAndExit() # # Clean up and terminate with status # sub cleanAndExit($) { my ($status) = @_; if ($status >= E_FAIL) { exit statusf($status); } else { exit $status; } } # getOPatchVersion() # # Ask OPatch to list its version # sub getOPatchVersion($) { my ($opatch) = @_; $opatch = fnQuote($opatch); my $cmd = fnQuote($PERL); my $version = S_EMPTY; my $line = `$cmd $opatch version 2>&1`; chomp($line); if ($line =~ m/opatch\.pl version: /i) { my (@output) = split (' ', $line); $version = $output[$#output]; } return $version; } # Copy directory recursively to destination # result = copy_dir ( , ) # Copies the contents of Source directory to Destination directory sub copy_dir { my $src = $_[0]; # Source Directory my $dst = $_[1]; # Destination Directory my $result = E_FAIL; # Default to failure # Try to copy if both source and destination are directories if ( ( -d $src ) && ( -r $src ) && ( -d $dst ) && ( -w $dst) ) { $src =~ s/\\/\//g; $dst =~ s/\\/\//g; # Do not copy if the source and destination are the same # Return Success. if ( $src eq $dst ) { return 0; } find ( sub { my $targetdir = $File::Find::dir; my $target = $targetdir; $targetdir = $dst . substr($targetdir, length($src)); mkpath( $targetdir ) if not -e $targetdir; my $file = $_; my $source = "./" . $file; my $dest = "$targetdir/$file"; if ( ($file ne $scriptName) && (-f $source) ) { # Preserve the permissions and timestamp my @stats = stat ( $source ); my @filetime = (stat $source)[8,9]; copy ($source, $dest); chmod $stats[2], $dest; # Copy permission utime $stats[8], $stats[9], $dest; # Copy timestamp my $chown_result = 0; chown $stats[4], $stats[5], $dest or $chown_result = 1; # Copy Owner if ($chown_result) { my $s4 = $stats[4]; my $s5 = $stats[5]; errorf("Could not chown file ($dest) to $s4, $s5..."); } } }, $src ); $result = 0; # Copy success } return $result; } # --------------------- Main program ------------------------------------- # make sure output is flushed setOutputAutoflush(); # make sure environment is correct setupOSD(); # make sure arguments are correct parseArgs(); # output a little info for feedback printHeader($0, $#ARGV); $isHeader = B_TRUE; # Copy the patch from stage location to official staging location my $stagedPatch = $ENV{STAGED_PATCH}; print "env variable STAGED_PATCH=$stagedPatch....\n"; if( ($stagedPatch eq "TRUE") || ($stagedPatch eq "true") ) { my $patch_src = $ENV{PATCH_PATH}; my $patch_dst = File::Spec->catfile($ORACLE_HOME, 'EMStagedPatches', $ENV{PATCH_ID}); my $patch_id = $ENV{PATCH_ID}; mkpath $patch_dst; if ($patch_src =~ /\/$/) { chop($patch_src); } # bug 5867796 : add patch_id to patch source otherwise # everything in patch_src will get copied to official location. if ( $patch_src !~ /$patch_id$/) { $patch_src = File::Spec->catfile($patch_src, $patch_id); } if ( !( -d $patch_src )) { print(STDOUT "Patch does not exists at staged location $patch_src\n"); cleanAndExit(1); } if ( $patch_dst eq $patch_src) { print(STDOUT "Patch already staged at official location , continuing with patch application...\n"); } else { print(STDOUT "Patch already staged. Copying the staged patch from $patch_src to $patch_dst...\n"); if (copy_dir($patch_src, $patch_dst) != E_SUCCESS) { cleanAndExit(1); } } chdir $patch_dst; # Set $patch_path variable to be used later $patch_path = $patch_dst; } # Set the patch id based on patch_path if (isEmpty($patch_id)) { $patch_id = File::Basename::basename($patch_path); } # apply the patch or check for OPatch version if (isEqual(C_APPLY, $apply_cmd)) { logf("Attempting to apply patch to Oracle home ($ORACLE_HOME)..."); } elsif (isEqual(C_VERSION, $apply_cmd)) { logf("Executing OPatch to display its version..."); $apply_opt = S_EMPTY; $local_opt = S_EMPTY; $inv_loc = S_EMPTY; $patch_loc = S_EMPTY; $enable_retry = B_FALSE; } my $etc = S_EMPTY; my $opatch_version = S_EMPTY; my $opatch_path = S_EMPTY; my $opatch_pl = S_EMPTY; # Step 0: Look for emdpatch.pl. If emdpatch.pl is found, invoke it # or else fallback to existing mechanism my $opatch = S_EMPTY; # findFile($patch_path, mask($PATCHSH)); my $emdpatch_status = B_FALSE; my $emdpatch_found = B_FALSE; while (B_TRUE) { if (isEmpty($opatch)) { # Look for emdpatch.pl $opatch = findFile($patch_path, mask('emdpatch.pl')); # if emdpatch.pl not found, fallback to OPatch if (isEmpty($opatch)) { logf("Could not locate emdpatch.pl... Look for OPatch or OUI shiphomes"); last; } # emdpatch.pl is found $emdpatch_found = B_TRUE; # Change over the directory containing emdpatch.pl my $patch_home = File::Basename::dirname($opatch); my $emderror = B_FALSE; chdir($patch_home) or $emderror = B_TRUE; # Trap failure to change directory if ($emderror == B_TRUE) { $status = E_FAIL; errorf($status, "Could not cd to >$patch_home<: $!"); last; } logf("Applying Patch ${patch_id}..."); if (isEqual('emdpatch.pl', File::Basename::basename($opatch))) { my $agentCustScript = $ENV{EM_AGENT_CUSTOM_APPLY}; if(($agentCustScript eq "TRUE") || ($agentCustScript eq "true")) { # Unsetting the env variable because we invoke emdpatch.pl whcih bounces the agent and the agent comes # up in the same subshell and inherits all the env values of the shell including EM_AGENT_CUSTOM_APPLY $ENV{EM_AGENT_CUSTOM_APPLY} = ""; # If user decides to modify the custom script whcih is populated then the user needs to take care of the following things # 1) unsets EM_AGENT_CUSTOM_APPLY before bouncing the agent # 2) redirects the output of the patching process to applyPatch_${patch_id}.log which will reside in EMStagedPatches/${patch_id}/ # 3) If patching was successful then the applyPatch_${patch_id}.log needs to contain a line "applyPatch ${patch_is} successful" only then # will the patching operation succeed. logf("Running custom agent Patching script"); my $patch_log = File::Spec->catfile($patch_path, "applyPatch_${patch_id}.log"); #when you are using stage from another location, you could have copied over the patch log file #and showresults would succeed even if the patch job failed hence #rename log file if existing if (-e $patch_log) { rename $patch_log, "$patch_log.old"; } if (onWindows()) { $status = echodo('start /b ' . fnQuote($PERL) . ' -w ' . fnQuote($opatch) . " ${patch_id} >> " . fnQuote($patch_log) . " 2>&1"); } else { $status = echodo(fnQuote($PERL) . ' -w ' . fnQuote($opatch) . " ${patch_id} >> " . fnQuote($patch_log) . " 2>&1 &"); } } else { $status = echodo(fnQuote($PERL) . ' -w ' . fnQuote($opatch) . " ${patch_id} " . " 2>&1"); } } # right shift return value by 8 $status = statusf($status); # emdpatch.pl has succeeded if ($status == E_SUCCESS) { $emdpatch_status = B_TRUE; } last; } last; } # Step 1: try to find opatch.pl # my $inventory_file = ''; my $actions_file = ''; my $opatch_shiphome = B_FALSE; my $oui_shiphome = B_FALSE; my $Disk1 = ''; my $runInst_loc = ''; my $runInst_loc_win = ''; my $rsp_loc = ''; $opatch = S_EMPTY; # findFile($patch_path, mask($PATCHSH)); if ((isEmpty($opatch)) && (isEqual($emdpatch_found, B_FALSE))) { # Step 1.1: Detect the type of the shiphome $etc = findFile($patch_path, 'etc'); $etc = 'etc' if (isEmpty($etc)); $inventory_file = File::Spec->catfile($etc, 'config', 'inventory'); $actions_file = File::Spec->catfile($etc, 'config', 'actions'); $opatch_shiphome = B_FALSE; $oui_shiphome = B_FALSE; if ( (-f $inventory_file) && (-f $actions_file) ) { # This is an OPatch shiphome $opatch_shiphome = B_TRUE; } else { $Disk1 = findFile($patch_path, 'Disk1'); $runInst_loc = File::Spec -> catfile($Disk1, "runInstaller"); $runInst_loc_win = File::Spec -> catfile($Disk1, "setup.exe"); # $rsp_loc = File::Spec -> catfile($Disk1, "response", "patchset.rsp"); $rsp_loc = findFile($Disk1, "patchset.rsp"); if ( onWindows() ) { if ( (-f $runInst_loc_win) && (-f $rsp_loc) ) { $oui_shiphome = B_TRUE; } } else { if ( (-f $runInst_loc) && (-f $rsp_loc) ) { $oui_shiphome = B_TRUE; } } } # Step 1.2: Detect OPatch or OUI depending on type of shiphome if ( $opatch_shiphome == B_TRUE ) # If OPatch shiphome detected { $opatch_path = $patch_path; $opatch_pl = S_EMPTY; # findFile($opatch_path, mask($OPATCHPL)); if (!isEmpty($opatch_pl)) { my $version = S_EMPTY; # getOPatchVersion($opatch_pl); if ($version gt $opatch_version) { $opatch_version = $version; } $opatch = $opatch_pl; } $opatch_path = File::Spec->catfile($ORACLE_HOME, 'OPatch'); $opatch_pl = findFile($opatch_path, mask($OPATCHPL)); if (!isEmpty($opatch_pl) && isEmpty($opatch)) { my $version = S_EMPTY; # getOPatchVersion($opatch_pl); if ($version gt $opatch_version) { $opatch_version = $version; } $opatch = $opatch_pl; } $opatch_path = File::Spec->catfile($EMDROOT, 'OPatch'); $opatch_pl = findFile($opatch_path, mask($OPATCHPL)); if (isEmpty($opatch_pl)) { $opatch_path = File::Spec->catfile($EMDROOT, 'opatch'); $opatch_pl = findFile($opatch_path, mask($OPATCHPL)); } if (!isEmpty($opatch_pl) && isEmpty($opatch)) { my $version = S_EMPTY; #getOPatchVersion($opatch_pl); if ($version gt $opatch_version) { $opatch_version = $version; } $opatch = $opatch_pl; } if (isEmpty($opatch)) { $status = E_NO_OPATCHPL; errorf($status, "Could not find $OPATCHPL to apply patch"); } } elsif ( $oui_shiphome == B_TRUE ) # If OUI shiphome detected { # Invoke OUI as OUI shiphome is detected if ( onWindows() ) { $status = echodo("$runInst_loc_win -silent -ignoreSysPrereqs -waitForCompletion -noconsole -responseFile $rsp_loc $inv_loc ORACLE_HOME=$ORACLE_HOME"); } else { $status = echodo("$runInst_loc -silent -ignoreSysPrereqs -waitForCompletion -responseFile $rsp_loc $inv_loc ORACLE_HOME=$ORACLE_HOME <$NULL_DEVICE 2>&1"); } # right shift return value by 8 $status = statusf($status); } else { $status = E_NO_OPATCHPL; errorf($status, "Could not find $OPATCHPL or OUI to apply patch"); } } # Step 2: try to apply the patch, check status # if (($status == E_SUCCESS) && (isEqual($emdpatch_found, B_FALSE)) && ($opatch_shiphome == B_TRUE) ) { if (isEqual($OPATCHPL, File::Basename::basename($opatch))) { chdir(File::Basename::dirname($etc)); $local_opt = S_LOCAL; $status = echodo(fnQuote($PERL) . S_SPACE . fnQuote($opatch) . " $apply_cmd $apply_opt $local_opt $inv_loc $patch_loc 2>&1"); # right shift return value by 8 $status = statusf($status); if (($status != E_SUCCESS) && ($enable_retry == B_TRUE)) { $local_opt = S_EMPTY; # S_LOCAL and S_NOINVENTORY are exclusive $inv_loc = S_NOINVENTORY; $status = echodo(fnQuote($PERL) . S_SPACE . fnQuote($opatch) . " $apply_cmd $apply_opt $local_opt $inv_loc $patch_loc 2>&1" ); # right shift return value by 8 $status = statusf($status); } } else { chdir(File::Basename::dirname($opatch)); $status = echodo("$ECHO Y | $SHELL ${DOTSLASH}$PATCHSH 2>&1"); # right shift return value by 8 $status = statusf($status); } if (isEqual(C_APPLY, $apply_cmd) && ($status == E_SUCCESS)) { printf(STDOUT "\n\napplyPatch $patch_id successful\n\n"); } } # Step 3: terminate with status # if (isEqual(C_APPLY, $apply_cmd)) { if ($status == E_SUCCESS) { logf("Patching completed."); } else { logf("Patching failed."); } } cleanAndExit($status); # --------------------- End of Program -----------------------------------