# 
# $Header: usm/src/cmds/acfsroot/acfsroot.pl /st_usm_11.2/13 2013/03/13 11:14:31 plancian Exp $
#
# acfsroot.pl
# 
# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      acfsroot.pl
#
#    DESCRIPTION
#      install/uninstall USM components from the distribution files
#      See section 4.2.1 of Design Note Supporting USM Installation
#
#    NOTES
#      acfsroot install [-h] [-s | -v | -t <0,1,2>] [-l <directory>]
#          install USM kernel drivers and commands.
#      acfsroot uninstall [-h] [-s | -v | -t <0,1,2>]
#          uninstall USM kernel drivers and commands.
#      acfsroot version_check [-h] [-t <0,1,2>] [-l <location>]
#          check if USM components are available for installation.
#      acfsroot enable [-h] [-s | -v | -t <0,1,2>]
#          enable ADVM/ACFS CRS resources.
#      acfsroot disable [-h] [-s | -v | -t <0,1,2>]
#          disable ADVM/ACFS CRS resources.
#
#    INSTALL ACTIONS
#      - verify that the user has root privs.
#      - checks that the proper install files exists
#      - unloads currently loaded drivers (if any).
#      - removes currently installed USM install files (if any).
#      - installs from the selected distribution files
#      - Loads the drivers to make sure that they load properly.
#      - Performs any required OSD actions, if needed.
#
#      User output should be done in this file when possible to ensure
#      cross platform similarity in command look and feel. However, it is 
#      understood that some OSD actions are specific to one platform only,
#      in which case it makes sense to do the output there.
#
#    MODIFIED   (MM/DD/YY)
#    plancian    03/11/13 - Add fvdroot test functionality
#    oehmoda     08/02/12 - Replace calling lib_check_any_driver_installed by
#                           calling lib_check_uninstall_required in install()
#                           and uninstall().
#                         - Moved message 9312, "Existing ADVM/ACFS
#                           installation detected." when a previous install
#                           is detected in uninstall() to
#                           osds_acfslib::lib_osds_check_uninstall_required()
#                           on all the platforms except AIX because we always
#                           run uninstall on AIX without checking for existing
#                           installation.
#    argardu     06/04/12 - Include tracing option in acfs install perl scripts
#    agraves     04/25/12 - Fix message.
#    anjiwaji    01/24/12 - Backport anjiwaji_bug13446398 from main
#    averhuls    10/20/11 - Backport averhuls_bug-13073625 from main
#    averhuls    07/21/11 - XbranchMerge averhuls_crs_modify_and_more from main
#    averhuls    07/21/11 - reregister->enable, unregister->disable.
#                           modify 9427 message.
#    averhuls    06/30/11 - return USM_REBOOT_RECOMMENDED on unload failures.
#    gsanders    06/30/11 - Backport gsanders_bug-12692110 from main
#    agraves     04/15/11 - Backport agraves_bug-12348303 from main
#    agraves     03/29/11 - Backport agraves_bug-11833948 from main
#    anjiwaji    03/23/11 - Add a verbose flag to wrap messages in acfslib.
#                           Also reorganize the usage messages. 
#    averhuls    03/15/11 - Backport averhuls_bug-11849923 from main
#    averhuls    10/26/10 - Alternative path location must be absolute - check
#                           for it.
#    averhuls    09/02/10 - Add the "preserve" option to uninstall to
#                           allow the preservation of the tunable parameters.
#    certan      06/28/10 - Pass $install_files_loc to uninstall() and
#                           osds_usm_uninstall() as distribution files may be
#                           needed during uninstall process
#    jinjche     06/02/10 - Add reregister and unregister subcommands for
#                           managing CRS ACFS resources
#    agraves     04/10/10 - Change message 9316 to include the media location.
#    averhuls    03/17/10 - Return USM_NOT_SUPPORTED if the platform does not
#                           support USM.
#    anjiwaji    02/10/10 - Change install and uninstall to check if any
#                           drivers are running.
#    certan      11/25/09 - During the install process, pass the location
#                           of install files to lib_unload_usm_drivers so
#                           that new utilities can be used if the old
#                           utilities cannot be found
#    agraves     04/30/09 - Make messages be consistent with Bill Manry's
#                           review.
#    averhuls    03/17/09 - Correctly detect NT absolute paths in
#                           get_oracle_home().
#    averhuls    03/16/09 - Fix wrapper scripts if USM is not supported on
#                           a machine.
#    averhuls    02/19/09 - Remove lib_osds references - everything goes thru
#                           lib.
#    averhuls    01/30/09 - rename usm_ to acfs.
#    averhuls    01/21/09 - For version_check, list where it is searching for
#                           media.
#    averhuls    12/23/08 - Use message catalog.
#    averhuls    11/06/08 - Fix Windows shiphome problem where the
#                           "lib" directory might be "LIB".
#    averhuls    11/03/08 - Use library functions from usm_lib.pm.
#    averhuls    10/20/08 - Remove "USM" from print statements.
#    averhuls    10/14/08 - Search for usm_driver_state.pl not usm_driver_state
#                           because that is common to all platforms.
#    averhuls    08/26/08 - convert constants implemented as variables to real
#                           constants
#    averhuls    07/25/08 - Fix uninitialized error if executed on Redhat4.
#                           -s only prints error messages (bug 7279974).
#    averhuls    07/02/08 - remove the -u option.
#    averhuls    04/11/08 - fix minor problems found during beta.
#    averhuls    03/13/08 - Improve printing. change usm_log_error() calls
#                           to usm_print(). Use usm_driver_state rather
#                           than an internal OSD function to determine
#                           if USM drivers are loaded.
#    averhuls    02/14/08 - minor cleanup.
#    averhuls    12/18/07 - Enhancement. if no install media found, list where
#                           it was liiking for them
#    averhuls    11/12/07 - move root validation to osd code
#    averhuls    10/16/07 - Look for media in the default location unless -l is
#                           specified.
#    averhuls    10/08/07 - Add switch to tell if a suitable RPM is available.
#    averhuls    06/29/07 - Creation
# 

use strict;
use Getopt::Std;
use Cwd;
use Cwd 'abs_path';
use File::Basename;
use Switch;
use English;
use acfslib;
use osds_acfsroot;

sub main
{
  my ($sub_command);         # start or stop
  my ($preserve) = 0;        # uninstall: preserve tunable files - default = no.
  my ($return_code);         # as the name implies 
  # user options
  my (%opt);                 # user options hash - used by getopts()
  my ($install_kernel_vers); # -k : install kernel version (other than current)
  my ($install_files_loc);   # -l : location(s) of the distribution files 
                             # -s : silent operation - no console output 
                             # -v : verbose operation - additional output
                             # -h : help

  # user flags. See description above or usage message output
  my (%flags) = ( install       => 'hsvk:t:l:',
                  uninstall     => 'hsvpt:',
                  enable        => 'hst:v',
                  disable       => 'hsvt:',
                  version_check => 'ht:l:k:',
                );

  # supplied by the front end driver and 'guaranteed' to be there.
  # command is what the user actually typed in (sans directories).
  $COMMAND = shift(@ARGV);

  # supplied by user
  $sub_command = shift(@ARGV);

  # Enable command line access to library functions
  if (defined($sub_command) && ($sub_command eq 'lib_run_func'))
  {
    exit lib_run_func "@ARGV";
  }

  if (!lib_usm_supported())
  {
    # OSD specific message generated in lib_usm_supported().
    if ($sub_command eq "install")
    {
      # Resolve ORACLE_HOME in the "wrapper scripts".
      osds_fix_wrapper_scripts();
      exit USM_NOT_SUPPORTED;
    }
    elsif ($sub_command eq "enable")
    {
      # Enable requires a previous installation.
      exit USM_NOT_SUPPORTED;
    }
    else
    {
      # all other sub-commands fall through.
    }
  }

  # sub commands "install", "uninstall", "enable", "disable", or "version_check"
  # must be supplied by the user.
  if (defined($sub_command))
  {
    if (!(($sub_command eq 'install') ||
          ($sub_command eq 'uninstall') ||
          ($sub_command eq 'enable') ||
          ($sub_command eq 'disable') ||
          ($sub_command eq 'version_check')))
    {
      # illegal sub-command
      usage("invalid", 0);
      exit USM_FAIL;
    }
  }
  else
  {
    # no sub-command
    usage("invalid", 0);
    exit USM_FAIL;
  }

  # parse user options
  %opt=();
  getopts($flags{$sub_command}, \%opt) or usage($sub_command, 1);
  if ($opt{'k'})
  {
    $install_kernel_vers = $opt{'k'};
  }
  if ($opt{'p'})
  {
    $preserve = 1;
  }
  if ($opt{'l'})
  {
    $install_files_loc = $opt{'l'};
    if (! File::Spec->file_name_is_absolute($install_files_loc))
    {
      lib_error_print(9388,
        "An absolute path name must be specified for the alternate location.");
      exit USM_FAIL;
    }
  }
  if ($opt{'h'})
  {
    # print help information
    usage($sub_command, 0);
    exit USM_SUCCESS;
  }

  if ($opt{'s'} && $opt{'v'})
  {
    lib_error_print(9160,
      "Can not use the silent and verbose options at the same time.");
      exit USM_FAIL;
  }


  if ($opt{'s'})
  {
    # do not generate console output - default is not silent.
    $SILENT = 1;
  }
  if ($opt{'v'})
  {
    # Generate additional console output - default is not verbose.
    $VERBOSE = 1;
  }
  $_ORA_USM_TRACE_ENABLED = 0;
  $_ORA_USM_TRACE_LEVEL = 0;
  if ( defined $opt{'t'}  )
  {
    if ($opt{'v'} || $opt{'s'})
    {
      lib_error_print(9188,
      "cannot use the trace option with the silent or verbose options");
      exit(USM_FAIL);
    }
    $_ORA_USM_TRACE_LEVEL = $opt{'t'};

    if( $_ORA_USM_TRACE_LEVEL == 0){
        $SILENT = 1;
        $VERBOSE = 0;
    }elsif( $_ORA_USM_TRACE_LEVEL == 1){
        $VERBOSE = 1;
        $SILENT = 0;
    }elsif( $_ORA_USM_TRACE_LEVEL == 2){
        $VERBOSE = 1;
        $SILENT = 0;
        $_ORA_USM_TRACE_ENABLED = 1;
    }else{
        lib_error_print( 9175, "Invalid trace level. Valid values for trace level are 0, 1 or 2.");      
        exit(USM_FAIL);    
    }
  } 
  # determine $ORACLE_HOME for this system
  get_oracle_home();

  ##### command parsing complete #####

  # perform required OSD initialization, if any.
  $return_code = osds_initialize($install_kernel_vers, $sub_command);
  if ($return_code != USM_SUCCESS)
  {
    # error messages generated by osds_initialize().
    exit USM_FAIL;
  }

  # use the default location for media unless the user specified otherwise
  if (!defined($install_files_loc))
  {
    $install_files_loc = $USM_DFLT_MEDIA_LOC; 
  }

  # version availability checks don't require privileged access
  if ($sub_command eq 'version_check')
  {
    # check the availability of USM components
    $return_code = version_check($install_kernel_vers, $install_files_loc);
    exit $return_code;
  }

  # verify root access
  if (!lib_am_root())
  {
    lib_error_print(9130, "Root access required");
    exit USM_FAIL;
  }

  if ($sub_command eq 'install')
  {
    lib_trace( 9180, "Sub-command is '%s'", "install" );
    # install the USM components
    $return_code = install($install_kernel_vers, $install_files_loc);
  }
  else
  {
    if ($sub_command eq 'uninstall')
    {
      # uninstall the USM components
      # pass $install_files_loc to uninstall() as distribution files may be
      # needed during uninstall process
      $return_code = uninstall($install_files_loc, $preserve);
    }
    else
    {
      if ($sub_command eq 'enable')
      {
        # enable the ACFS resources
        $return_code = enable();
      }
      else
      {
        if ($sub_command eq 'disable')
        {
          # disable the ACFS resources
          $return_code = disable();
        }
      }
    }
  }

  exit $return_code;
} # end main

sub install
{
  my ($install_kernel_vers, $install_files_loc,) = @_;
  my ($no_load) = 0;             # Do not load the newly installed bits.
  my ($preserve) = 1;            # Any tunable files are preserved.
  my ($return_code);
  my ($kernel_version) = osds_get_kernel_version();
  my ($reboot_recommended) = 0;
  my ($previous_install_detected_msg) = 0; # Do not print out the "previous
                                           # install detected" message when
                                           # calling lib_check_uninstall_
                                           # required() because it is going
                                           # to get printed out when we call
                                           # uninstall().
  lib_trace( 9176, "Entering '%s'", "install");

  if (defined($install_kernel_vers))
  {
    lib_trace( 9181, "Kernel version is '%s'", $install_kernel_vers);
    # We're installing USM for another kernel version - do not attempt to
    # load the drivers. The presumed scenario is that the user wants to
    # install USM for an about to be upgraded kernel. This way, USM can
    # be up and running upon reboot. Dunno if anyone will ever use this.
    $kernel_version = $install_kernel_vers;
    $no_load = 1;
  }  
  
  # First, find the distribution files from which to install
  # No point in going on if they can't be found.
  $return_code = osds_search_for_distribution_files($install_files_loc);
  if ($return_code == USM_SUCCESS)
  {
    lib_inform_print(9300, "ADVM/ACFS distribution files found.");
  }
  else
  {
    lib_error_print(9301, "ADVM/ACFS installation cannot proceed:");
    if (defined($install_files_loc))
    {
      lib_error_print(9317,
                     "No ADVM/ACFS distribution media detected at " .
                     "location: '%s'", $install_files_loc);
    }
    else
    {
      lib_error_print(9303,
         "No installation files found for OS kernel version %s.", $kernel_version);
    }
    lib_trace( 9178, "Return code = %s", "USM_FAIL");
    lib_trace( 9177, "Return from '%s'", "install");
    return USM_FAIL;

  }

  # Can't continue if the currently loaded drivers can't be unloaded
  $return_code = lib_unload_usm_drivers($install_files_loc);
  if (($return_code != USM_SUCCESS) || (testFailMode() == 1))
  {
    if (($return_code == USM_REBOOT_RECOMMENDED) || (testFailMode() == 1))
    {
      lib_error_print(9427, "Failed to unload ADVM/ACFS drivers. A system reboot is recommended.");
      lib_trace( 9178, "Return code = %s", "USM_REBOOT_RECOMMENDED");
      lib_trace( 9177, "Return from '%s'", "install");
      return $return_code;
    }
    else
    {
      lib_error_print(9304,
          "Installation cannot proceed: Failed to unload ADVM/ACFS drivers.");
      lib_trace( 9178, "Return code = %s", "NOT USM_REBOOT_RECOMMENDED");
      lib_trace( 9177, "Return from '%s'", "install");
      return $return_code;
    }
  }

  # Search for a previous installation and remove it if found.
  if (lib_check_uninstall_required($previous_install_detected_msg))
  {
    # Pass $install_files_loc to uninstall() as distribution files may be
    # needed during uninstall process
    if (uninstall($install_files_loc, $preserve) == USM_FAIL)
    {
      lib_error_print(9305, "ADVM/ACFS installation can not proceed:");
      lib_error_print(9306, "Failed to uninstall previous installation.");
      lib_trace( 9178, "Return code = %s", "USM_FAIL");
      lib_trace( 9177, "Return from '%s'", "install");
      return USM_FAIL;
    }
  }

  # We have distribution files and no USM components are currently 
  # installed or loaded - we can proceed with the installation.
  lib_inform_print(9307, "Installing requested ADVM/ACFS software.");

  # osds_search_for_distribution files() has set which files need
  # to be installed.
  $return_code = osds_install_from_distribution_files($reboot_recommended);

  if ($return_code == USM_SUCCESS)
  {
    if ($no_load == 0)
    {
      lib_inform_print (9308, "Loading installed ADVM/ACFS drivers.");
    }

    # ensure that all utilities and drivers are where they are expected to be
    $return_code = osds_load_and_verify_usm_state($no_load);
    if (($return_code == USM_SUCCESS) && (testFailMode() != 2))
    {
      if ($reboot_recommended)
      {
        $return_code = USM_REBOOT_RECOMMENDED;
      }
      lib_inform_print(9309, "ADVM/ACFS installation correctness verified.");
    }
    else
    {
      lib_error_print(9428,
         "Failed to load ADVM/ACFS drivers. A system reboot is recommended.");
      lib_error_print(9310, "ADVM/ACFS installation failed.");
      lib_trace( 9178, "Return code = %s", "USB_REBOOT_RECOMMENDED");
      $return_code = USM_REBOOT_RECOMMENDED;
    }
  }
  else
  {
    lib_error_print(9310, "ADVM/ACFS installation failed.");
    lib_trace( 9178, "Return code = %s", "USM_FAIL");
    $return_code = USM_FAIL;
  }
  lib_trace( 9177, "Return from '%s'", "install");
  return $return_code;
} # end install

# Enable ACFS drivers and registry resources
sub enable
{
  my $ret = USM_SUCCESS;
  my $ret1 = USM_SUCCESS;

  lib_trace( 9176, "Entering '%s'", "enable");
  # We are guaranteed here that the ADVM/ACFS supports this OS.

  if ((lib_check_drivers_installed() == 0) || (lib_check_drivers_loaded() == 0))
  {
    lib_error_print(9167,
              "ADVM/ACFS is not installed or loaded. Run 'acfsroot install'.");
    lib_trace( 9178, "Return code = %s", "USM_FAIL");
    lib_trace( 9177, "Return from '%s'", "enable");
    return USM_FAIL;
  }

  if (!((-e <$ORACLE_HOME/bin/crsctl*>) || (-l <$ORACLE_HOME/bin/crsctl*>)))
  {
    lib_error_print(5062, "cannot query CRS resource");
    lib_trace( 9178, "Return code = %s", "USM_FAIL");
    lib_trace( 9177, "Return from '%s'", "enable");
    return USM_FAIL;
  }

  # For some reason, crsctl will sometimes return 0 even if
  # crs is down.  I suppose this is because the command 
  # executed successfully.
  open CRSCTL, "$ORACLE_HOME/bin/crsctl check crs |";
  while (<CRSCTL>)
  {
    if (/CRS-4639/)
    {
      lib_error_print(5062, "cannot query CRS resource");
      close CRSCTL;
      lib_trace( 9178, "Return code = %s", "USM_FAIL");
      lib_trace( 9177, "Return from '%s'", "enable");
      return USM_FAIL;
    }
  }
  close CRSCTL;

  if ((usm_resource_exists("drivers") == USM_SUCCESS) &&
      (usm_resource_exists("registry") == USM_SUCCESS))
  {
    # Upgrade the resources.
    $ret1 = modify_usm_drivers_resource();
    if ($ret1 != USM_SUCCESS)
    { 
      $ret = USM_FAIL;
    }

    $ret1 = modify_usm_registry_resource();
    if ($ret1 != USM_SUCCESS)
    {
      $ret = USM_FAIL;
    }
  }
  else
  {
    # Install and start the resources.
    $ret1 = add_usm_drivers_resource();
    if ($ret1 != USM_SUCCESS)
    {
      $ret = USM_FAIL;
    }

    $ret1 = start_usm_drivers_resource();
    if ($ret1 != USM_SUCCESS)
    {
      $ret = USM_FAIL;
    }

    $ret1 = add_acfs_registry();
    if ($ret1 != USM_SUCCESS)
    {
      $ret = USM_FAIL;
    }

    $ret1 = start_acfs_registry();
    if ($ret1 != USM_SUCCESS)
    {
      $ret = USM_FAIL;
    }
  }
  if( $ret == USM_SUCCESS){
      lib_trace( 9178, "Return code = %s", "USM_SUCCESS");
  }elsif( $ret == USM_FAIL){
      lib_trace( 9178, "Return code = %s", "USM_FAIL");
  }else{
      lib_trace( 9178, "Return code = %s", "$ret");
  }
  lib_trace( 9177, "Return from '%s'", "enable");

  return $ret;
} 

# Disable ACFS drivers and registry resources
sub disable
{
  my $ret = USM_SUCCESS;

  lib_trace( 9176, "Entering '%s'", "disable");

  my $ret1 = stop_acfs_registry();
  if ($ret1 != USM_SUCCESS)
  {
    $ret = USM_FAIL;
  }

  $ret1 = delete_acfs_registry();
  if ($ret1 != USM_SUCCESS)
  {
    $ret = USM_FAIL;
  }

  $ret1 = delete_usm_drivers_resource();
  if ($ret1 != USM_SUCCESS)
  {
    $ret = USM_FAIL;
  }

  if( $ret == USM_SUCCESS){
      lib_trace( 9178, "Return code = %s", "USM_SUCCESS");
  }elsif( $ret == USM_FAIL){
      lib_trace( 9178, "Return code = %s", "USM_FAIL");
  }else{
      lib_trace( 9178, "Return code = %s", "$ret");
  }
  
  lib_trace( 9177, "Return from '%s'", "disable");
  return $ret;
}

sub uninstall
{
  my ($install_files_loc, $preserve) = @_;
  my ($return_code);
  my ($previous_install_detected_msg) = 1; # print out the "previous
                                           # installation detected" message
                                           # when we call:
                                           # lib_check_uninstall_required
  lib_trace( 9176, "Entering '%s'", "uninstall");
  # Search for a previous installation
  if (!lib_check_uninstall_required($previous_install_detected_msg))
  {
    lib_error_print(9313, "No ADVM/ACFS installation detected.");
    lib_trace( 9178, "Return code = %s", "USM_SUCCESS");
    lib_trace( 9177, "Return from '%s'", "uninstall");
    return USM_SUCCESS;
  }

  # Can't continue if the currently loaded drivers can't be unloaded
  $return_code = lib_unload_usm_drivers();
  if ($return_code != USM_SUCCESS)
  {
    lib_trace( 9178, "Return code = %s", "NOT USM_SUCCESS");
    lib_trace( 9177, "Return from '%s'", "uninstall");
    return $return_code;
  }

  lib_inform_print(9314, "Removing previous ADVM/ACFS installation.");

  # Pass $install_files_loc to osds_usm_uninstall() as distribution files may
  # be needed during uninstall process
  $return_code = osds_usm_uninstall($install_files_loc, $preserve);
  if ($return_code == USM_SUCCESS)
  {
    lib_inform_print(9315,
                       "Previous ADVM/ACFS components successfully removed."); 
  }

  if( $return_code == USM_SUCCESS){
      lib_trace( 9178, "Return code = %s", "USM_SUCCESS");
  }elsif( $return_code == USM_FAIL){
      lib_trace( 9178, "Return code = %s", "USM_FAIL");
  }else{
      lib_trace( 9178, "Return code = %s", "$return_code");
  }
  lib_trace( 9177, "Return from '%s'", "uninstall");

  return $return_code;
} # end uninstall

sub version_check
{
  lib_trace( 9176, "Entering '%s'", "vers check");
  my ($install_kernel_vers, $install_files_loc) = @_;
  my ($return_code);
  my ($kernel_version) = osds_get_kernel_version();

  $return_code = osds_search_for_distribution_files($install_files_loc);

  if ($return_code == 0)
  {
    lib_inform_print(9316, 
          "Valid ADVM/ACFS distribution media detected at: '%s'",
          $install_files_loc);
  }
  else
  {
    lib_error_print(9317, "No ADVM/ACFS distribution media detected at " .
                          "location: '%s'", $install_files_loc);
  }

  lib_trace( 9178, "Return code = %s", "$return_code");
  lib_trace( 9177, "Return from '%s'", "vers check");
  return $return_code;
} # end check

################################################
# The following are static functions.
################################################

# There are 3 different ways of getting ORACLE_HOME:
# 1) From the environment.  This may be set by rootcrs or the user.
# 2) From the current location of the command.
# 3) From the crsconfig_params file.

# deinstall tree - Oracle provides a package of software
#     that contains all the tools necessary to remove the 
#     Oracle software - this is called the deinstall.
#     In the event that you remove the Grid Home from 
#     your system, this is the standalone deinstall,
#     although it currently doesn't work.  Our deinstall
#     is part of this throught the deinstall mapfiles.

# There are 5 different uses of the env ORACLE_HOME:
# 1) From the deinstall tree - if the Grid Home that is being removed
#    is gone, it will point to non-existent Grid Home.
# 2) From the deinstall tree, pointing to the Grid Home to remove.
# 3) From the rootcrs.pl during install.
# 4) From the rootcrs.pl during deinstall, but not from the deinstall tree.
# 5) And the final one, manually during our patching procedures.

# In all cases, we don't fully trust the passed in ORACLE_HOME, as the
# user may have incorrectly set it.  We also don't really want to force
# the user to set it, except in certain situations.

# So, we rely on a heuristic, which should catch all cases:
# 1) Find out where we are running from.  In most cases, acfsroot.pl
#    will run from ORACLE_HOME/lib.  (The only case this isn't true for
#    is an ACFS only patch or a command line manual install.)
# 2) Find out what the passed in ORACLE_HOME is.
# 3) See if either discovered or passed in ORACLE_HOME has a crsconfig_params
#    file.
# 4) Get ORACLE_HOME from the params file.
# 5) Use the param file ORACLE_HOME for comparison if it exists, or the env
#    if it doesn't.
# 6) Convert both the passed in  or params ORACLE_HOME (if it exists) and the
#    discovered "ORACLE_HOME" to an absolute path, which will
#    correctly dereference all symlinks in the path.  Compare these
#    two values.  If they match, then use the passed in\params ORACLE_HOME,
#    and assume that it is correct (most times it will be coming from 
#    rootcrs).  This will cover most normal installs, and will
#    catch symlinks.
# 7) If they do not match, then use the discovered value.  This is 
#    because during deinstall, one of two things can happen:
#    a) We are running from the deinstall tree, and the ORACLE_HOME 
#       that is passed in is not valid.  We want to use our tools out
#       of the deinstall tree.
#    b) We are running from the deinstall tree, and the ORACLE_HOME
#       that is passed in is valid, but it doesn't matter to us,
#       we still use our tools out of the deinstall tree.
#    And during install, one of 3 things can happen:
#    a) We are running from rootcrs, and the value matches.
#    b) We are running from the command line during a manual patch\install
#       and the user has the incorrect ORACLE_HOME specified.  In 
#       this case, assume we are running from the GridHome. (However,
#       this case will be covered by getting it from the params file.)

# Bug 11833948 was a bug where the OH was a symlink, yet we used the
# real path of the directory.  This resulted in not being able to contact
# the ASM instance for some reason.  Changing the OH to the symlinked 
# path made things work again.

sub get_oracle_home
{
  my ($dir) = dirname($0);          # $0 is built in acfstoolsdriver.{sh,bat}

  my $discovered_ORACLE_HOME;       # the ORACLE_HOME from bin location.
  my $param_ORACLE_HOME;            # the ORACLE_HOME in the param file.
  my $env_ORACLE_HOME;              # the ORACLE_HOME in the env.
  my $compare_ORACLE_HOME;          # the final choice we are comparing against.
  my $paramfile  = "";              # The location of the parameter file.

  lib_trace( 9176, "Entering '%s'", "get ora home");
  if (defined($ENV{SRCHOME}))
  {
    # We're in a development environment, we'll use that $ORACLE_HOME.
    $ORACLE_HOME = $ENV{ORACLE_HOME};
    lib_trace( 9182, "Variable '%s' has value '%s'", "ORACLE_HOME", "$ORACLE_HOME");
    return;
  }

  # We're in a production environment.

  # This file lives in $ORACLE_HOME/lib - drop the trailing /lib
  $dir =~ s/\/lib$//;

  # This is where we are running from.
  $discovered_ORACLE_HOME = $dir;

  # Remove any trailing '\n's.
  chomp($discovered_ORACLE_HOME);

  # Now the env location, for safety.
  if (defined($ENV{ORACLE_HOME}))
  {
    $env_ORACLE_HOME = $ENV{ORACLE_HOME};
    chomp($env_ORACLE_HOME);
  }

  # Now we try to get the information from the params file,
  # just in case it matches somewhere else.
  # We use this param file in a few places now... should we
  # have a function to access it and get info?

  #  Most times we are running out of the grid home, or a place with
  # a crsconfig_params.
  $paramfile = $discovered_ORACLE_HOME . "crs/install/crsconfig_params";

  if ( ! -e $paramfile )
  {
    # Try the location of the env ORACLE_HOME for kicks.
    $paramfile = $env_ORACLE_HOME . "/crs/install/crsconfig_params";
  }
  # This will fail if $paramfile doesn't exist, leaving us with nothing.
  open PARAMS, $paramfile;
    
  while (<PARAMS>)
  {
     if (m/^ORACLE_HOME/)
     {
        my @LINE = split /=/;
        $param_ORACLE_HOME = $LINE[$#LINE];
        # Remove any trailing '\n's
        chomp($param_ORACLE_HOME);
        last;
     }
  }


  close (PARAMS);

  # Now, compare the env and the param file.  If they are different, use 
  # the param file (assuming it is not null).
  # If they are the same, use the param file.
  # If we couldn't get to the param file, use the env location.
  if (defined($param_ORACLE_HOME) )
  {
    $compare_ORACLE_HOME = $param_ORACLE_HOME;
    lib_verbose_print(9500, "Location of Oracle Home is '%s' " .
                      "as determined from the internal configuration data", 
                      $ORACLE_HOME);
    
  }
  else  #param is not defined.
  {
    if (defined($env_ORACLE_HOME))
    {
      $compare_ORACLE_HOME = $env_ORACLE_HOME;
      lib_verbose_print(9501, "Location of Oracle Home is '%s' " .
                        "as determined from the ORACLE_HOME " . 
                        "environment variable", 
                        $ORACLE_HOME);
    }
  }


  # Now, compare the abs_path of all dirs found and use the one we trust.
  if (abs_path($compare_ORACLE_HOME) eq abs_path($discovered_ORACLE_HOME))
  {
    # This will take into account symlinks.
    $ENV{ORACLE_HOME} = $compare_ORACLE_HOME;
  }
  else
  {
    # They differed (after abs_path), so assume the user 
    # had something wrong somewhere, and use what we know
    # to be true.
    # Or the user is running deinstall, where ORACLE_HOME can point
    # to some invalid location not consistent with where we are
    # running out of.
    #  This is okay - the system location of our files won't 
    #   change, and that's where we want to remove things from.
    #  OUI can handle cleaning up the ORACLE_HOME, wherever it is.
    $ENV{ORACLE_HOME} = $discovered_ORACLE_HOME;
    lib_verbose_print(9502, "Location of Oracle Home is '%s' " .
                      "as determined from the location of the Oracle " . 
                      "library files", 
                      $ORACLE_HOME);
  }
  $ORACLE_HOME = $ENV{ORACLE_HOME};
  lib_trace( 9182, "Variable '%s' has value '%s'", "ORACLE_HOME", "$ORACLE_HOME");
  lib_trace( 9177, "Return from '%s'", "get ora home");
}

sub usage
{
  my ($sub_command, $abort) = @_;

  lib_trace( 9176, "Entering '%s'", "usage");
  if ($sub_command eq "install")
  {
    lib_error_print(9161, " acfsroot install: Install ADVM/ACFS components.");

    lib_error_print(9185, " %s [-h] [-s | -v | -t <0,1,2>] [-l <directory>]", 
		    "Usage: acfsroot install");
    lib_error_print(9132, 
		    "        [-h]             - print help/usage information");
    lib_error_print(9131,
		    "        [-s]             - silent mode" .   
		    " (error messages only)");
    lib_error_print(9159,
		    "        [-v]             - verbose mode");
    lib_error_print(9332, 
		    "        [-l <directory>] - location of the" .   
		    " installation directory");
    lib_error_print(9189, 
                    "        [-t <0,1,2> ]    - trace level");    
    
  }
  elsif ($sub_command eq "uninstall")
  {
    lib_error_print(9162, " acfsroot uninstall: Uninstall ADVM/ACFS" .
		    " components.");
    lib_error_print(9186,
                     " Usage: acfsroot uninstall [-h] [-s | -v | -t <0,1,2>]");
    lib_error_print(9132, 
		    "        [-h]             - print help/usage information");
    lib_error_print(9131,
		    "        [-s]             - silent mode" .   
		    " (error messages only)");
    lib_error_print(9159,
		    "        [-v]             - verbose mode");
    lib_error_print(9387, 
		    "        [-p]             - preserve tunable parameters");
    lib_error_print(9189,
                    "        [-t <0,1,2> ]    - trace level");

  }
  elsif ($sub_command eq "version_check")
  {
    lib_error_print(9163, " acfsroot version_check: Check ADVM/ACFS version.");
    lib_error_print(9187, 
	    " Usage: acfsroot version_check [-h] [-t <0,1,2>] [-l <location>]");
    lib_error_print(9132, 
		    "        [-h]             - print help/usage information");
    lib_error_print(9332, 
		    "        [-l <location>]  - location of the" .   
		    " distribution files");
    lib_error_print(9333, 
		    "                           (if not the default" .
		    " location)");
    lib_error_print(9335, 
		    "        [-k <version>]   - install kernel version" .
		    " number");
    lib_error_print(9336, 
		    "                           (if not the current kernel" . 
		    " version)");
    lib_error_print(9189,
                    "        [-t <0,1,2> ]    - trace level");

  }
  elsif ($sub_command eq "enable")
  {
    lib_error_print(9164, " acfsroot enable: Enable ADVM/ACFS CRS resources.");
    lib_error_print(9184, " %s [-h] [-s | -v | -t <0,1,2>]",  
		    "Usage: acfsroot enable");
    lib_error_print(9132, 
		    "        [-h]             - print help/usage information");
    lib_error_print(9131,
		    "        [-s]             - silent mode" .   
		    " (error messages only)");
    lib_error_print(9159,
		    "        [-v]             - verbose mode");
    lib_error_print(9189,
                    "        [-t <0,1,2> ]    - trace level");

  }
  elsif ($sub_command eq "disable")
  {
    lib_error_print(9165," acfsroot disable: Disable ADVM/ACFS CRS resources.");
    lib_error_print(9184, " %s [-h] [-s | -v | -t <0,1,2>]",  
		    "Usage: acfsroot disable");
    lib_error_print(9132, 
		    "        [-h]             - print help/usage information");
    lib_error_print(9131,
		    "        [-s]             - silent mode" .   
		    " (error messages only)");
    lib_error_print(9159,
		    "        [-v]             - verbose mode");
    lib_error_print(9189,
                    "        [-t <0,1,2> ]    - trace level");
  }
  else
  {
    lib_error_print(9185, " %s [-h] [-s | -v | -t <0,1,2>] [-l <directory>]", 
		    "Usage: acfsroot install");
    lib_error_print(9186,
                     " Usage: acfsroot uninstall [-h] [-s | -v | -t <0,1,2>]");
    lib_error_print(9187, 
	    " Usage: acfsroot version_check [-h] [-t <0,1,2>] [-l <location>]");
    lib_error_print(9184, " %s [-h] [-s | -v | -t <0,1,2>]",
                                                     "Usage: acfsroot enable");
    lib_error_print(9184, " %s [-h] [-s | -v | -t <0,1,2>]",
                                                     "Usage: acfsroot disable");
  }

  lib_trace( 9177, "Return from '%s'", "usage");

  if ($abort)
  {
    exit USM_FAIL;
  }
} # end usage

# A function for error path testing; returns 0 if we are not testing an error path
sub testFailMode
{
  lib_trace( 9176, "Entering '%s'", "fail mode");
  if (defined($ENV{ADE_VIEW_ROOT}) && defined($ENV{_ORA_ACFSROOT_TEST}))
  {
    # 1 = Simulates failure during unload of drivers
    # 2 = Simulates failure during load of drivers
    lib_trace( 9178, "Return code = %s", "$ENV{_ORA_ACFSROOT_TEST}");
    lib_trace( 9177, "Return from '%s'", "fail mode");
    return ($ENV{_ORA_ACFSROOT_TEST});
  }
  lib_trace( 9178, "Return code = %s", "0");
  lib_trace( 9177, "Return from '%s'", "fail mode");
  return 0;
}

main();

