MINI MINI MANI MO

Path : /opt/oracle/product/18c/dbhomeXE/lib/
File Upload :
Current File : //opt/oracle/product/18c/dbhomeXE/lib/osds_afdroot.pm

# 
#
# osds_afdroot.pm
# 
# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
#
#
#    NAME
#      osds_afdroot.pm - Linux OSD component of afdroot.
#
#    DESCRIPTION
#      Purpose
#          Install/uninstall AFD components.
#
#    NOTES
#      All user visible output should be done in the common code.
#      this will ensure a consistent look and feel across all platforms.
#
#

use strict;
package osds_afdroot;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
                 osds_afd_initialize
                 osds_afd_install_from_distribution_files
                 osds_afd_search_for_distribution_files
                 osds_load_and_verify_afd_state
                 osds_afd_uninstall
                 osds_afd_fix_wrapper_scripts
                 osds_afd_get_kernel_version
                 $MEDIA_FOUND
                 $ORACLE_HOME
                 $AFD_DFLT_DRV_LOC
                 $AFD_DFLT_DSK_STR
                 );

use acfslib;
use osds_afdlib;
use osds_unix_linux_afdlib;
use afdlib;
use osds_acfslib;
use osds_acfsroot;

our ($ORACLE_HOME) = $ENV{ORACLE_HOME}; 
# AFD configuration file. This has to be same as
# configl file in usm/src/tools/asmboot/lin/safdoot.h 

my  ($SHIPHOME_BASE_DIR) = "$ORACLE_HOME/usm/install";
our ($USM_DFLT_CMD_LOC)  = "$SHIPHOME_BASE_DIR/cmds/bin"; # cmds media loc
our ($AFD_DFLT_DRV_LOC);                        # location of the drivers media
my  ($MINUS_L_DRIVER_LOC);
our ($MEDIA_FOUND) = '';                        # path name to media
                                                # used for version_check

#default AFD discovery string
our ($AFD_DFLT_DSK_STR) = "afd_diskstring='/dev/loop*'";

my ($ARCH)    = `uname -i`;                     # Machine architecture - i386
chomp($ARCH);
my ($UNAME_R) = `uname -r`;
chomp($UNAME_R);

my ($no_init) = "";
$no_init = `/sbin/weak-modules -h | grep ^'--no-init'` if machine_is_RH();
chomp($no_init);

# We do not install/uninstall the commands destined for ORACLE_HOME - that
# is now done by the mapfiles during Oracle install/uninstall. We use
# <XXX>_COMPONENTS only to verify that the commands exist in their
# installed location.
# The exception are the commands destined to live in /sbin. Since OUI
# won't have permissions to copy these commands directly, we do it here.
my ($SBIN_DIR)         = "/sbin";
my ($OH_BIN_DIR)       = "$ORACLE_HOME/bin"; 
my ($OH_LIB_DIR)       = "$ORACLE_HOME/lib"; 
my ($MESG_DST_DIR)     = "$ORACLE_HOME/usm/mesg";
my ($USM_PUB_DST_DIR)  = "$ORACLE_HOME/usm/public"; 
my ($CMDS_SRC_DIR)     = "$SHIPHOME_BASE_DIR/cmds/bin"; 
my ($MESG_SRC_DIR)     = "$SHIPHOME_BASE_DIR/../mesg"; 
my ($USM_LIB_SRC_DIR)  = "$SHIPHOME_BASE_DIR/../lib"; 
my ($USM_PUB_SRC_DIR)  = "$SHIPHOME_BASE_DIR/../public"; 

# AFD Library name
my ($LIBAFD)           = "libafd18.so";
my ($LIBAFD_BASENAME)  = "libafd";

my (@SBIN_COMPONENTS) = (
     "afdboot",
);

my (@OH_BIN_COMPONENTS) = (
     "$OH_BIN_DIR/afdroot",      "$OH_BIN_DIR/afdload",
     "$OH_BIN_DIR/afdtool",      "$OH_BIN_DIR/afdtool.bin",
     "$OH_BIN_DIR/afddriverstate",
);

my (@OH_LIB_COMPONENTS) = (
     "$OH_LIB_DIR/afdtoolsdriver.sh", "$OH_LIB_DIR/afdlib.pm",
     "$OH_LIB_DIR/afdroot.pl",        "$OH_LIB_DIR/osds_afdroot.pm",
     "$OH_LIB_DIR/afdload.pl",        "$OH_LIB_DIR/osds_afdload.pm",
     "$OH_LIB_DIR/afddriverstate.pl", "$OH_LIB_DIR/osds_afddriverstate.pm",
     "$OH_LIB_DIR/osds_afdlib.pm",    "$OH_LIB_DIR/osds_unix_linux_afdlib.pm",
     "$OH_LIB_DIR/$LIBAFD"
);

my (@MESG_COMPONENTS) = (
     "$MESG_DST_DIR/afdus.msb",
);

my (@OH_COMPONENTS) = (@OH_BIN_COMPONENTS, @OH_LIB_COMPONENTS);

my ($DRIVER_DIR);              # installed driver location 
my ($minus_l_specified) = 0;   # Alternate install location specified by user.

# set by osds_afd_search_for_distribution_files() and
# consumed by osds_afd_install_from_distribution_files() 
my ($OIP_PATH, $GPL_PATH);

# make sure that /sbin is in the PATH - that's where modprobe lives
$ENV{PATH} .= ':/sbin';

my ($ASMADMIN);                          # ASM admin group name
my ($KVER);                              # kernel version being installed

# osds_afd_initialize
#
# Perform OSD initialization.
#   Set AFD_DFLT_DRV_LOC - the location of the AFD installation driver media.
#   We deduce the location of the other components from there.
#
sub osds_afd_initialize
{
  my ($install_kver, $sub_command) = @_;
  my ($vendor);
  my ($type);

  if (!defined($install_kver))
  {
    # use the current kernel version
    $KVER = $UNAME_R;
  }
  else
  {
    # use the specified kernel version
    # TODO we'll want to do some sanity checking here.
    $KVER = $install_kver;
  }

  # we have already verified that we have a valid Linix type
  $type = lib_osds_get_os_type();

  $vendor = lib_osds_get_linux_vendor();

  # For "afddriverstate supported" command, we don't need to know
  # asmadmin name, and we can get some errors running the command
  # We skip this part for supported (#26792302)
  if ($sub_command ne "supported")
  {
    # Get the name of the ASM adminisrator
    $ASMADMIN = lib_get_asm_admin_name();
  }

  if (!((defined($ORACLE_HOME)) && (-e "$ORACLE_HOME/lib/afdroot.pl"))) 
  {
    lib_error_print(9389,
    "ORACLE_HOME is not set to the location of the Grid Infrastructure home.");
    return USM_TRANSIENT_FAIL;
  }

  # AFD is not supported in a LXC environment
  # LXC is sharing the Kernel with the Host OS
  # Inserting new modules is not allowed

  if ( acfslib::lib_is_local_container() )
  {
    lib_error_print(9430,
      "AFD is not supported on this OS configuration: '%s'", "Linux Container");
    return USM_NOT_SUPPORTED;
  }

  # /sbin/weak-modules depends on /boot being accessible and the 
  # symvers-<kernel_version> file being present.
  if (!osds_symvers_exists($KVER))
  {
    # error messages generated by osds_symvers_exists().
    return USM_TRANSIENT_FAIL;
  }

  # default media location - over-ride with the -l option
  my ($base) = $SHIPHOME_BASE_DIR;
  $AFD_DFLT_DRV_LOC = get_install_home_from_base($base, $type, $ARCH, $KVER);

  if ($AFD_DFLT_DRV_LOC eq osds_acfsroot::KABI_NOT_SUPPORTED) {
    return USM_NOT_SUPPORTED;
  }

  return USM_SUCCESS;
}

# osds_afd_install_from_distribution_files
#
# Install the AFD components from the specified distribution files
# The files have already been validated by the time we get here
# by osds_afd_search_for_distribution_files(). Also, any previous USM installation
# will have been removed.
#
use File::Path;
sub osds_afd_install_from_distribution_files
{
  my ($component);                 # curent component being installed
  my ($command);                   # current command being executed by system()
  my ($ret) = 0;                   # return of individual copy commands
  my ($return_code) = USM_SUCCESS;

  # install drivers
  # the drivers have been verified to exist so the copy will not fail
  if (! -d $DRIVER_DIR)
  {
    mkpath($DRIVER_DIR, 0, 0755);
  }

  # Print the location of the driver files
  lib_verbose_print (626, "AFD driver media location is '%s'", $OIP_PATH);
 
  if ($minus_l_specified)
  {
    # Normally, the ORACLE_HOME/{bin,lib} components are installed via the
    # mapfiles. But, when the user specifies an alternate location via the
    # '-l' option on the command line, we need to install the alternate 
    # OH/{bin,lib} files also. The OH commands are, conveniently located
    # with the sbin commands.
    #
    # If we are replacing existing files, we want to preserve the original
    # file attributes.

    foreach $component (@OH_COMPONENTS) 
    {
      my (@array) = split /\//, $component;
      my ($file) = $array[-1];
      my ($target) = "$component";
      my ($source);
      my ($have_orig);
      my ($uid, $gid);

      if ($component =~ /$LIBAFD/)
      {
        $source = "$USM_LIB_SRC_DIR/$file";
      }
      else
      {
        $source = "$CMDS_SRC_DIR/$file";
      }
      
      $have_orig = 0;

      if (-e $target)
      {
        use constant UID  => 4;
        use constant GID  => 5;
 
        $have_orig = 1;

        # get the owner/group of the original file
        if(($uid, $gid) = (stat($target))[UID,GID]){}
      }

      lib_verbose_print (9504, "Copying file '%s' to the path '%s'", 
                         $source, $target);
     
      unlink ("${target}/${LIBAFD}") if ($component =~ /$LIBAFD/ &&
                                         -e "${target}/${LIBAFD}"); 
      $ret = system ("cp $source $target");
      $return_code = USM_FAIL if $ret;
      if (($target =~ /\/bin\//) || ($component =~ /afdtoolsdriver.sh/))
      {
        system("chmod 0755 $target");
      }
      else # lib
      {
        system("chmod 0644 $target");
      }

      if ($have_orig)
      {
        chown $uid, $gid, $target;
      }
    }

    foreach $component (@MESG_COMPONENTS) 
    {
      my (@array) = split /\//, $component;
      my ($file) = $array[-1];
      my ($target) = $component;
      my ($source) = "$MESG_SRC_DIR/$file";
      
      lib_verbose_print (9504, "Copying file '%s' to the path '%s'", 
                            $source, $target);
    
      $ret = system ("cp $source $target");
      $return_code = USM_FAIL if $ret;
    }

    # Copy the drivers and system commands to the install area so that
    # subsequent "afdroot install"s will get the patched bits should
    # the user forget to use the -l option. It also allows us to compare
    # checksums on the drivers in the "install" area to the "installed"
    # area at load time. This will catch situations where users installed
    # new bits but did run "afdroot install".

    foreach $component (@AFD_DRIVER_COMPONENTS) 
    {
      my (@array) = split /\//, $component;
      my ($file) = $array[-1];
      my ($source) = "$MINUS_L_DRIVER_LOC/$component";
      my ($target) = "$AFD_DFLT_DRV_LOC/$file";
      
      lib_verbose_print (9504, "Copying file '%s' to the path '%s'", 
                        $source, $target);

      $ret = system ("cp $source $target");
      $return_code = USM_FAIL if $ret;
    }

    foreach $component (@SBIN_COMPONENTS)
    {
      my ($cmd_install_area) = "$ORACLE_HOME/bin";
      my (@array) = split /\//, $component;
      my ($file) = $array[-1];
      my ($source) = "$CMDS_SRC_DIR/$component";
      my ($target) = "$cmd_install_area/$file";
      my ($uid, $gid);

      lib_verbose_print (9504, "Copying file '%s' to the path '%s'",
                            $source, $target);

      ($uid, $gid) = (stat($target))[UID,GID];

      $ret = system ("cp $source $target");
      $return_code = USM_FAIL if $ret;

      $ret = chmod 0755, $target;
      if ($ret != 1)
      {
        # Warn only
        lib_inform_print(9347, "Unable to set permissions (octal %s) on: '%s'.",
                                0755, $target);
      }

      $ret = chown $uid, $gid, $target;
      if ($ret != 1)
      {
        # Warn only
        lib_inform_print(9426,
                    "unable to set the file attributes for file '%s'", $target);
      }
    }
  }
  
  #
  # Copy to system paths ...after patching the home
  #
  foreach my $component (@AFD_DRIVER_COMPONENTS)
  {
    my ($source) = "$OIP_PATH/$component";
    my ($target) = "$DRIVER_DIR/$component";

    lib_verbose_print (9504, "Copying file '%s' to the path '%s'", 
                       $source, $target);

    $command = "cp $source $target";
    $ret = system ($command);
    $return_code = USM_FAIL if $ret;
  }

  foreach $component (@SBIN_COMPONENTS)
  {
    my ($source) = "$OH_BIN_DIR/$component";
    my ($target) = "$SBIN_DIR/$component";

    lib_verbose_print (9504, "Copying file '%s' to the path '%s'",
                          $source, $target);

    $ret = system ("cp $source $target");
    $return_code = USM_FAIL if $ret;
    system("chmod 0755 $target");
  }

  return $return_code;
} # end osds_afd_install_from_distribution_files

# osds_afd_search_for_distribution_files
#
# Search the media location(s) specified by the user for valid components
#
sub osds_afd_search_for_distribution_files
{
  my ($kernel_install_files_loc) = @_;
  my (@install_loc_array);
  my ($cur_loc);              # current location (directory) being examined
  my ($component);            # current component (cmd/driver) being examined
  my ($components_found) = "";# list of components detected
  my ($components_missing) = 0; # set if one or more components are AWOL
  my ($ret_code) = USM_SUCCESS;

  # $kernel_install_files_loc is where the drivers and drivers related files
  # live. - as of 11.2.0.3 and later, the commands are shipped in a separate
  # directory.

  if (!defined($kernel_install_files_loc))
  {
     return USM_FAIL;
  }

  # Look to see if an alternate location for the distribution was specified.
  if ($kernel_install_files_loc ne $AFD_DFLT_DRV_LOC)
  {
    # -l option specified (we know that the path is fully qualified).
    $minus_l_specified = 1;

    # $kernel_install_files_loc is a misnomer for -l within this 'if clause',
    # where it's really the the directory path up to and including "install" -
    # but, what the heck. Once out of this clause, it really will mean the
    # location of the kernel drivers.

    # We use "install" as our starting point for finding our bits
    # so it had better be there.
    if (!($kernel_install_files_loc =~ /install$/))
    {
      # Error message generated by caller
      return USM_TRANSIENT_FAIL;
    }

    # We have the "base" path, up to "install".
    # It's time to find where the drivers are relative to that base.

    my (@path_array) = split ("/", $AFD_DFLT_DRV_LOC);
    my ($last_element) = $#path_array;
    my ($driver_relative_path) = "";
    my ($i);
 
    for ($i = 1; $i <= $last_element; $i++)
    {
      # strip off all array elements of out default "base" location. What's 
      # left will be the parts of the driver relative path.
      my ($element) = shift(@path_array);
      if ($element eq "install")
      {
        last;
      }
    }
  
    # Now assemble the driver relative path.
    $last_element = $#path_array;
    for ($i = 0; $i <= $last_element; $i++)
    {
      $driver_relative_path .= "$path_array[$i]/";
    }
    # We now know where the drivers and commands live in the '-l' location.
    $CMDS_SRC_DIR = "$kernel_install_files_loc/cmds/bin";
    $MESG_SRC_DIR = "$kernel_install_files_loc/../mesg";
    $USM_LIB_SRC_DIR = "$kernel_install_files_loc/../lib";
    $USM_PUB_SRC_DIR = "$kernel_install_files_loc/../public";
    $MINUS_L_DRIVER_LOC = "$kernel_install_files_loc/$driver_relative_path";
    $kernel_install_files_loc = $MINUS_L_DRIVER_LOC;
  }

  @install_loc_array = split(/,/, $kernel_install_files_loc);

  # We need to uncompress driver files first
  lib_uncompress_all_driver_files($kernel_install_files_loc);
 
  foreach $cur_loc (@install_loc_array)
  {
    if (! -d $cur_loc)
    {
      # location (directory) does not exist
      next;
    }
    # test that all of our expected components exist in the distribution

    # search for OIP components
    foreach $component ($AFD_DRIVER_COMPONENTS[AFD_IDX],
                       )
    {
      my ($target) = $cur_loc . "/" . $component;
      if (-e $target)
      {
        $components_found .= " $component";
        $OIP_PATH = $cur_loc;
#       if (! ($MEDIA_FOUND =~ m/OIP/))
#       {
#         # $MEDIA_FOUND is used by the version_check sub-command
#         $MEDIA_FOUND .= "OIP components: $OIP_PATH\n";
#       }
      }
      else
      {
        lib_error_print(9320, "Missing file: '%s'.", $target);
        $components_missing = 1;
      }
    }
  }

  if (defined($OIP_PATH))
  {
    $MEDIA_FOUND = "$OIP_PATH\n";
  }
  else
  {
    $MEDIA_FOUND = "";
  }

  # verify that we have all that we need
  if ($components_missing)
  {
    return USM_FAIL;
  }

  foreach $component (@AFD_DRIVER_COMPONENTS)
  {
    if (!($components_found =~ m/$component/))
    {
      lib_error_print(9320, "Missing file: '%s'.", $component);
      $ret_code = USM_FAIL;
    }
  }

  if (!defined($OIP_PATH))
  {
    return USM_FAIL;
  }

  # We found drivers, now find where they will be installed.
  $DRIVER_DIR = get_afd_driver_dir($OIP_PATH);

  foreach $component (@SBIN_COMPONENTS)
  {
    if ($minus_l_specified)
    {
      if (! -e "$CMDS_SRC_DIR/$component")
      {
        lib_error_print(9320,"Missing file: '%s'.","$CMDS_SRC_DIR/$component");
        $ret_code = USM_FAIL;
      }
    }
    else
    {
      if (! -e "$OH_BIN_DIR/$component")
      {
        lib_error_print(9320,"Missing file: '%s'.","$OH_BIN_DIR/$component");
        $ret_code = USM_FAIL;
      }
    }
  }

  foreach $component (@OH_COMPONENTS, @MESG_COMPONENTS)
  {
    my ($source);

    if ($minus_l_specified)
    {
      my (@array) = split /\//, $component;
      my ($file) = $array[-1];
      $source = "$CMDS_SRC_DIR/$file";

      if ($component =~ /$LIBAFD/)
      {
        # Special case libafd as it lives apart from the other commands.
        $source = "$USM_LIB_SRC_DIR/$file";
      }
      elsif ($component =~ /msb$/)
      {
        # Special case msg files as it lives apart from the other commands.
        $source = "$MESG_SRC_DIR/$file";
      }
    }
    else
    {
      $source = $component;
    }

    if (! -e $source) 
    {
      lib_error_print(9320, "Missing file: '%s'.", $source);
      $ret_code = USM_FAIL;
    }
  }

  return $ret_code;
} # end osds_afd_search_for_distribution_files

# osds_load_and_verify_afd_state
#
# We unconditionally create the AFD udev permissions file
# If the install was for the current kernel version, we load the drivers
# and test to see that the expected /dev entries get created.
#
use File::Copy;
sub osds_load_and_verify_afd_state
{
  my ($no_load) = @_;
  my ($driver);                            # currently loaded driver
  my ($return_val);
  my ($udev_perm_file);
  my ($asmuser) = acfslib::getParam("ORACLE_OWNER");

  lib_inform_print (9321, "Creating udev for AFD.");
  lib_osds_afd_create_udev($ASMADMIN);

  # Make sure that all drivers are in place and can be loaded
  my ($component);
  my ($fail) = USM_SUCCESS;
  my ($result);

  foreach $component (@AFD_DRIVER_COMPONENTS)
  {
    if (! -e "$DRIVER_DIR/$component")
    {
      lib_error_print(9320, "Missing file: '%s'.", "$DRIVER_DIR/$component");
      $fail = USM_FAIL;
    }
  }
 
  if ($fail != USM_SUCCESS)
  {
     return $fail;
  }

  # create the driver dependencies
  lib_inform_print(9323,
                   "Creating module dependencies - this may take some time.");

  if (machine_is_RH() || machine_is_SLES())
  {
    my ($moved_dep) = 0;
    my ($driver_list);
    foreach $component (@AFD_DRIVER_COMPONENTS)
    {
      $driver_list .= "$DRIVER_DIR/$component\n";
    }
    if (-e "/lib/modules/$KVER/modules.dep")
    {
      move("/lib/modules/$KVER/modules.dep", "/tmp/modules.dep");
      $moved_dep = 1;
    }
    $return_val = system("depmod -v $KVER > /dev/null");
    if (($return_val != 0) && $moved_dep)
    {
      # depmod failed - restore the original
      move("/tmp/modules.dep", "/lib/modules/$KVER/modules.dep");
    }

    if (machine_is_RH())
    {
      my ($print_header) = 1;
      my ($cmd) = "echo \"$driver_list\" | /sbin/weak-modules $no_init" . 
                  " --add-modules $KVER 2>&1 |";
      open (MOD, $cmd);
      while (<MOD>)
      {
        if ($_ =~ /^WARNING:/)
        {
          next;
        }
	if ($print_header)
	{
	  lib_print_cmd_header($cmd);
	  $print_header = 0;
        }
        lib_inform_print (9999, "$_");
      }
      close (MOD);
    }
  }

  # see comments at the head of the routine
   osds_afd_fix_wrapper_scripts();

  if ($no_load)
  {
    # We're installing AFD for another kernel version - do not attempt to
    # load the drivers. The presumed scenario is that the user wants to
    # install AFD for an about to be upgraded kernel. This way, AFD can
    # be up and running upon reboot. Dunno if anyone will ever use this.
    lib_inform_print(9324, "Alternate drivers installed.");
    lib_inform_print(9325, 
                 "    Driver operating system kernel version = %s.", $UNAME_R);
    lib_inform_print(9326, "    Driver Oracle version = %s.", $KVER);
  }
  else
  {
    # Load the AFD drivers
    $return_val = lib_load_afd_drivers();
    if ($return_val != USM_SUCCESS)
    {
      # lib_load_afd_drivers() will print the specific error(s), if any;
      return $return_val;
    }

    # Copy libafd18.so to the required location. 
    lib_osds_afd_copy_library(); 

    # Post driver load, create /dev/oracleafd/disks
    $return_val = lib_afd_post_load_setup();
    if ($return_val != USM_SUCCESS)
    {
      # lib_afd_post_load_setup() will print the specific error, if any;
      return $return_val;
    }

    #
    # afd.conf is generated from HAS ROOT SCRIPTS
    # Please osd_setup() in crsutils.pm
    #
  }

  return USM_SUCCESS;
} # end osds_load_and_verify_afd_state

# osds_afd_uninstall
#
# remove the AFD components.
#
# 
use File::Basename;
use File::Find;
sub osds_afd_uninstall
{
  my (undef, $preserve) = @_;
  my ($return_code) = USM_SUCCESS;       # Assume success
  my ($component);
  my ($usm_perm_file);
  my ($whatbit);
  my ($target);

  if (!$preserve)
  {
    my $ret;
  }

  # SLES udev rules work the same as RH5
  if (machine_is_RH() || machine_is_SLES())
  {
    $usm_perm_file = lib_osds_get_afd_udev_rules_file();
    # remove the udev USM premissions file
    if (-e $usm_perm_file)
    {
      if (! unlink $usm_perm_file)
      {
        lib_inform_print(9348, "Unable to remove '%s'.", $usm_perm_file);
        $return_code = USM_TRANSIENT_FAIL;
      }
    }
  }

  # Guarantee that we're not in one of the usm directories about to be nuked.
  chdir "/";

  # Remove AFD drivers from and any *empty* sub-directories we would have 
  # created at install time (e.g., /lib/modules/2.6.18-8.el5/extra/oracle)
  open (CHECK, "find /lib/modules  2> /dev/null |");
  while (<CHECK>)
  {
    my ($driver) = split;

    if (($driver =~ m/\/oracle\/oracleafd.ko/) )
    {
      # Remove the driver
      if (! unlink $driver)
      {
        lib_inform_print(9348, "Unable to remove '%s'.", $driver);
        $return_code = USM_TRANSIENT_FAIL;
      }

      # Remove the base directories but only if empty
      my (undef, $lib, $modules, $kver) = split (/\//, $driver);
      my $subdir = "/$lib/$modules/$kver";
      finddepth(sub{rmdir}, $subdir);
    }
  }
  close(CHECK);

  system("depmod  > /dev/null");

  # Delete /dev/oracleafd/disks
  lib_afd_delete_oracleafd_disks();
 
  # Remove /dev/oracleafd and it's contents.
  # By now device /dev/oracleafd/admin is deleted and deleted all the links to 
  # disks in the /dev/oracleafd/disks dir, so we can remove /dev/oracleafd
  my $subdir = "/dev/oracleafd/";
  if(-e $subdir)
  { 
    find({wanted=>sub{rmdir}, bydepth=>1}, $subdir);
    rmdir $subdir;
  }

  # Target should be of the type
  # /opt/oracle/extapi/[32,64]/{API}/{VENDOR}/{VERSION}/lib<apiname>.<ext>
  #
  $whatbit = `grep flags /proc/cpuinfo`;
  if($whatbit =~ /lm/)
  {
    $target = "/opt/oracle/extapi/64/asm/orcl/1";
  }
  elsif($whatbit =~ /tm/)
  {
    $target = "/opt/oracle/extapi/32/asm/orcl/1";
  }

  # Remove libafd*.so from $target
  my $file;  # place holder for the file to be removed
  my @files = glob("$target/$LIBAFD_BASENAME" . "*.so");
  foreach $file(@files) 
  {
    unlink($file);
  }

  # Remove dir /opt/oracle/extapi/64/asm only if empty
  my (undef,$opt,$oracle,$extapi,$bit,$asm,undef,undef,undef) =
                                                  split (/\//, $target);
  $subdir = "/$opt/$oracle/$extapi/$bit/$asm/";
  if(-e $subdir)
  { 
    finddepth(sub{rmdir}, $subdir);
    rmdir $subdir;
  }

  foreach $component (@SBIN_COMPONENTS)
  {
    my ($command) = "$SBIN_DIR/$component";

    if ((-e $command) && (! unlink $command))
    {
      lib_inform_print(9348, "Unable to remove '%s'.", $command);
      $return_code = USM_TRANSIENT_FAIL;
    }
  }

  #
  # HAS ROOT SCRIPT related actions are not done here 
  #

  return $return_code;
} # end osds_afd_uninstall


# osds_afd_fix_wrapper_scripts
#
# We need to resolve %ORA_CRS_HOME% in the command wrapper scripts.
sub osds_afd_fix_wrapper_scripts
{
  my (@progs) = (
      "$OH_BIN_DIR/afdload",
      "$OH_BIN_DIR/afddriverstate",
      "$OH_BIN_DIR/afdtool",
                );
  my ($prog);
  my ($line);
  my (@buffer);

  foreach $prog (@progs)
  {
    my ($read_index, $write_index);

    $read_index = 0;
    open READ, "<$prog" or next;
    while ($line = <READ>)
    {
      if ($line =~ m/^ORA_CRS_HOME/)
      {
         $line = "ORA_CRS_HOME=$ORACLE_HOME\n";
      }
      $buffer[$read_index++] = $line;
    }
    close (READ);

    $write_index = 0;
    open WRITE, ">$prog" or next;
    while($write_index < $read_index)
    {
      print WRITE "$buffer[$write_index++]";
    }
    close (WRITE);
  }
}
# end osds_afd_fix_wrapper_scripts


###############################
# internal "static" functions #
###############################

# get_afd_driver_dir
#
# return the directory where the AFD drivers will be installed.
#
sub get_afd_driver_dir
{
  my ($path) = @_;

  if (machine_is_RH() || machine_is_SLES())
  {
    my ($driver_build_version); # version that the driver was linked for.
    my ($vermagic);
    my (@tmp_array);

    # pick the afd driver - any KA driver would do.
    open MODINFO , "modinfo $path/$AFD_DRIVER_COMPONENTS[AFD_IDX] |";

    while (<MODINFO>)
    {
      if ($_ =~ /^vermagic/)
      {
        $vermagic = $_;
      }
    }
    close (MODINFO);

    if (defined($vermagic))
    {
      # Get the version number from the modinfo vermagic line. It looks like:
      # vermagic:   2.6.18-8.el5PAE SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1
      $vermagic =~ s/vermagic://;
      $vermagic =~ s/^\s+//g;
      @tmp_array = split(/ /, $vermagic);
      $driver_build_version = $tmp_array[0];
    }
    else
    {
      # Use the current kernel version if we can't get vermagic
      lib_inform_print(9343, "Unable to retrieve OS kernel version from " .
                             "module %s.", "$path/$AFD_DRIVER_COMPONENTS[AFD_IDX]");
      $driver_build_version = $UNAME_R;
    }

    return "/lib/modules/$driver_build_version/extra/oracle";
  }
} #end get_afd_driver_dir

# osds_afd_get_kernel_version
#
sub osds_afd_get_kernel_version
{
  if (machine_is_supported_linux())
  {
    return $KVER;
  }

  lib_error_print(9319,
         "Unknown operating system kernel version '%s' detected.", $KVER);

  return USM_FAIL;
} # end osds_afd_get_kernel_version

1;

OHA YOOOO