#!/usr/local/bin/perl
# 
# $Header: install/tools/deinstall/bootstrap.pl /st_install_11.2.0/2 2011/05/10 11:12:24 vkoganol Exp $
#
# bootstrap.pl
# 
# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      bootstrap.pl - This script will first validate if the files required for deinstalling ORACLE_HOME is 
#                     present in ORACLE_HOME and bootstraps it to the location passed from shell/batch script.
#                     This script will be run only in cases when running the deinstall tool from installed ORACLE_HOME.
#
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    vkoganol    05/10/11 - XbranchMerge vkoganol_bug-12433438 from main
#    vkoganol    05/08/11 - Correcting script name in error message
#    vkoganol    12/20/10 - XbranchMerge vkoganol_bug-10153797 from
#                           st_install_11.2.0
#    ssampath    06/10/10 - Recently PERL added some new directories. Fail the
#                           tool if the file and the directory does not exist
#                           in OH
#    ssampath    06/09/10 - Reuse old tmpdir location when -giclean is passed
#    ssampath    03/25/10 - XbranchMerge ssampath_bug-9342491 from
#                           st_install_11.2.0.1.0
#    ssampath    01/18/10 - Creation
# 
use Cwd;
use File::Basename;
use File::Path;
use File::Copy;
use File::Find;

$notRecommendedMessage = "It is not recommended to run the script directly.  Execute deinstall or deinstall.bat which executes this script with right set of arguments\n";

$homeVersion = shift;

if($homeVersion eq "")
{
   print "Deinstall tool version is one of the required arguments for this perl script. $notRecommendedMessage";
   exit 1;
}

if($homeVersion) {
   $ORACLE_HOME = shift @ARGV;
   if($ORACLE_HOME eq "")
   {
      print "The Oracle home directory is one of the required arguments for this perl script. $notRecommendedMessage";
      exit 1;
   }
}

$ID = exists($ENV{ID}) ? $ENV{ID} : '/usr/bin/id';
$LSL = exists($ENV{LSL}) ? $ENV{LSL} : '/bin/ls -l';
$isWindows = ($^O =~ /.*MSWin.*/) ? 1 : 0;
if ($isWindows)  {
 	$dirSep = '\\';
 	$pathSep = ';';
        $arch = $ENV{PROCESSOR_ARCHITECTURE};
	$bits = $ENV{PROCESSOR_ARCHITEW6432};
	$is32Bit = (($arch eq 'x86') && ($bit eq '')) ? 1 : 0;
} else {
 	$dirSep = '/';
 	$pathSep = ':';
}

$bootstrapDir = processTmp();

# Check if this script is run as root on Linux.  If so, then error out.
# This is fix for bug 5024086.
if (! $isWindows) {
	my $id = `$ID`;
	$id =~ /.*?\((\w+)\).*/;
	$user = $1;
	#print "\n\$user = $user\n";
	if ($user eq 'root') {
		print "\nERROR: You must not be logged in as root to run the deinstall tool.\n";
		print "       Log in as Oracle user and rerun the deinstall tool.\n";
		exit 1;
	}
}

mkpath($bootstrapDir) or die "ERROR: Unable to make boot strap directory $bootstrapDir: $!\n" if(! -d $bootstrapDir);
if($homeVersion) {
   validateOwner();
   filesListCheck();

   # copy contents of ORACLE_HOME/deinstall/* and jdk to the bootstrap directory
   my @sourceDirs = ($ORACLE_HOME.$dirSep.'deinstall',$ORACLE_HOME.$dirSep.'jdk');
   my $dest = $bootstrapDir;
      
   if ( $^O eq "MSWin32" ) {
      system("xcopy /y/s/i/e/q $sourceDirs[0] $dest");
      system("xcopy /y/s/i/e/q $sourceDirs[1] $dest\\jdk");
   }
   else {
      system("cp -rf $sourceDirs[0]/* $dest");
      system("cp -rf $sourceDirs[1] $dest");
   } 
}

# The value of TEMP location is printed to STDOUT which will be 
# captured by shell script.
print $bootstrapDir;

sub validateOwner() {
   # Check that user running this script is owner of Oracle Home.
   $homeInventory = $ORACLE_HOME.$dirSep.'inventory';
   if (! $isWindows) {
        my $id = `$ID`;
        $id =~ /.*?\((\w+)\).*/;
        $user = $1;
	#print "\n\$user = $user\n";
	if (-d $ORACLE_HOME) {
		if (-d $homeInventory) {
			my @lsCmdOutput = `$LSL $ORACLE_HOME`;
			my $inventoryOwner;
			foreach $lineOut (@lsCmdOutput) {
				chomp($lineOut);
				$lineOut =~ s/^\s+//;
				$lineOut =~ s/\s+$//;
				if ($lineOut =~ /.+?\s+[0-9]+\s+(.+?)\s+.*inventory/) {
					$inventoryOwner = $1;
					#print "owner = $inventoryOwner\n";
				}
			}
			if ($user ne $inventoryOwner) {
				print "You must be the owner of this Oracle Home to deinstall/deconfigure it.\n";
				exit 1;
			}
		} else {
			print "The home inventory does not exist on this Oracle Home: $ORACLE_HOME\n";
			print "Please create '$homeInventory' as original user and rerun this script.\n";
			exit 1;
		}
	} else {
		print "The Oracle Home '$ORACLE_HOME' does not exist.\n";
		print "Please re-create the Oracle Home as original user and rerun this script.\n";
		exit 1;
	}
   }
}

sub filesListCheck() {
	my $filePath;
	my $command;
	# Check to see if all the files we require for running Files List
	# is present in the home.  If it is not present, then there is
	# no point in continuing further.
	$filePath = $ORACLE_HOME.$dirSep."deinstall".$dirSep."jlib".$dirSep."deinstall_wrapper.jar";
	unless (-f $filePath) {
		print "\nThe deinstall file, deinstall_wrapper.jar does not exist in ORACLE_HOME, $ORACLE_HOME/deinstall/jlib directory.  Hence, you cannot use deinstallation and deconfiguration tool that is installed in the home.  Download stand-alone version of the tool from OTN to deconfigure and deinstall the home.\n";
		exit 1;
	}
	# Extract required files from .lst
	$command = $ORACLE_HOME.$dirSep."jdk".$dirSep."bin".$dirSep."jar tf";
	$filePath = $ORACLE_HOME.$dirSep."deinstall".$dirSep."jlib".$dirSep."deinstall_wrapper.jar";
	my @fileToExtract = grep { /.*\.lst/ } `$command $filePath`;
	my $fileToExtract = $fileToExtract[0];
	chomp($fileToExtract);
	#print "\n\$fileToExtract = $fileToExtract\n";
	chdir($bootstrapDir) or die "ERROR: Cannot change to directory $bootstrapDir: $!\n";
	
	$command = $ORACLE_HOME.$dirSep."jdk".$dirSep."bin".$dirSep."jar xf";
	system("$command $filePath $fileToExtract");
	# required_files.lst is already extracted to bootstrapDir.
	
	my $fileName = $bootstrapDir.$dirSep."mapfiles".$dirSep."required_files.lst";

	#my $fileName = $ORACLE_HOME.$dirSep."deinstall".$dirSep."mapfiles".$dirSep."required_files.lst";
	open(FILE, "<$fileName") or die "ERROR: Unable to open required_files.lst: $!\n";
	my @files = ();
	while (my $file = <FILE>) {
		chomp($file);
		push(@files, $file) unless ($file =~ /\w+\.dll/ && (! $isWindows)); # if non-windows, skip .dlls
	}
	close(FILE);
	foreach $file (@files) {
		$file =~ s/\//\\/g if ($isWindows);
		#print "\nProcessing file $file\n";
		my $compFile = 'oui'.$dirSep.'bin'.$dirSep.'ouica.properties';
		next if ($file eq $compFile); # drop extraneous oui/bin/ouica.properties
		next if ($file =~ /.+_tmp.*/);
                next if ($file eq 'bin'.$dirSep.'ODBTREEVIEW.OCX' && !$is32Bit);
                next if ($file eq 'bin'.$dirSep.'OO4OADDIN.DLL' && !$is32Bit);
                next if ($file eq 'bin'.$dirSep.'OO4OCODEWIZ.DLL' && !$is32Bit);
		my ($fileName, $fileDir, $fileExt) = fileparse($file, '\..*');
		# Correctly rename for EM template files which have been instantiated under different names
		if ($file =~ /\w+\.template$/) {
			my @fnArr = split(/\./, $fileExt);
			$fileName .= ".".$fnArr[1];
			$file = length($fileDir) > 0 ? $fileDir.$fileName : $fileName;
		}
		push(@filesToCopy, $file);
		if (! -f $ORACLE_HOME.$dirSep.$file && ! -d $ORACLE_HOME.$dirSep.$file) {
			print "ERROR: Cannot find $file in the ORACLE_HOME $ORACLE_HOME.  You must download the standalone version of the deinstall tool from OTN to deconfigure/deinstall this Oracle Home.\n";
			$deinstallDir=$ORACLE_HOME.$dirSep."deinstall";
			chdir($deinstallDir) or die "ERROR: Cannot change to directory $deinstallDir : $!\n";
			rmtree($bootstrapDir) if (-d $bootstrapDir);
			exit 1;
		} else {
                        createSubDirs($fileDir);
			my $from = $ORACLE_HOME.$dirSep.$file;
			my $to = $bootstrapDir.$dirSep.$fileDir;
                       
                        if ($isWindows)  {
			   copy($from, $to);
                        } else {
                          system("cp -rf $from $to");
                        }
                        #print "\nCopied file $from to $to\n";
		}
	}
}

sub createSubDirs {
    my ($input) = @_;
    my $intrPath = "";

    #Loop through the sections
    foreach(split/\Q$dirSep\E/,$input) {
        #Add to path
        $intrPath .= $_ . $dirSep;

	#print "Create path $intrPath\n";
	mkdir($intrPath) or die "ERROR: Unable to create directory $intrPath: $!\n" if(! -d $intrPath);
    }
}

sub processTmp() {
   my $tmpSearch = '-tmpdir';
   my $giCleanSearch = '-giclean';
   my $giCleanFound = 0;
   my ($sec, $min, $hr, $mDay, $mon, $yr, $wDay, $yDay, $dst) = localtime;
   my $year = $yr + 1900;
   my $month = $mon + 1;
   my $seconds = ($hr * 60 * 60) + ($min * 60) + $sec;
   my $noonSeconds = (12 * 60 * 60);
   my $amPm = ($seconds > $noonSeconds) ? 'PM' : 'AM';
   my $hour = ($seconds > $noonSeconds) ? ($hr - 12) : $hr;
   my $dteTimeStamp = sprintf("%d-%02d-%02d_%02d-%02d-%02d%s", $year, $month, $mDay, $hour, $min, $sec, $amPm);
   my $defaultTmp = "/tmp";
   my $tmp = "";

   while ( $arg = shift @ARGV) {
      if(lc($arg) eq $giCleanSearch) {
         $giCleanFound = 1;
      }

      if(lc($arg) eq $tmpSearch) {
         $tmp = shift @ARGV;
         break ;
      }
   }

   if($isWindows) {
      $defaultTmp = $ENV{SystemDrive}.$dirSep.'temp';
   }

   my $scratchArea = $tmp ? $tmp :
                     ($ENV{TEMP} ? $ENV{TEMP} : $defaultTmp);

   if($giCleanFound)
   {
      return $scratchArea;
   }
   else
   {
      return $scratchArea.$dirSep.'deinstall'.$dteTimeStamp;
   }
}
