# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. # # NAME # asmcmdpasswd - ASM CoMmanD line interface for shared password file # operations # # DESCRIPTION # This module handles the shared password file operations like create, # move, copy, delete the password file, get and set the password # file location.y # # MODIFIED (MM/DD/YY) # apfwkr 07/02/17 - Backport anovelo_bug-21159907 from main # prabbala 12/01/16 - Backport prabbala_bug-19777340 from main # anovelo 01/17/17 - 21159907: Disallow duplicate password files # prabbala 09/15/16 - bug19777340: send dbuniquename to KFPKG in pwcopy # yilhu 07/19/16 - 24309216: Add anchor for start of line when parsing # diguzman 05/30/16 - 19654070: Little change at _no_instance_cmd routine # moreddy 05/30/16 - 21168520: fix pwdelete --dbuniquename # anovelo 03/08/16 - 21894027: Update format for orapwd # dacavazo 01/18/16 - 22458930: fix undefined array value in pwdelete # dacavazo 12/07/15 - 22223809: undef function before dl_find_symbol # bhshanmu 07/26/15 - bhshanmu_perl_522_changes_for_rdbms # prabbala 01/30/15 - 20101171: use asmcmdshare_runcmd to capture cmd o/p # prabbala 11/25/14 - bug19512500: use asmcmdshare_runcmd to capture shell # command output # pvenkatr 07/05/13 - Bug 14014671: Reverse lookup API integration. # pvenkatr 02/01/13 - using asmcmdshare_filter_invisible_cmds # adileepk 05/08/12 - Fix for bug-14000743. # adileepk 04/18/12 - Fix for bug-13964420. # adileepk 03/15/12 - Fix for bug-13827285. # ssonawan 03/08/12 - Bug 13050833: replace 'extended' by 'format' # adileepk 01/31/12 - Fix for bug-13574607. # adileepk 12/01/11 - Fix for bug-13450576. Adding pwget & pwset # commands. # adileepk 01/10/11 - Creation # ############################################################################# # ############################ Functions List ################################# # # Top Level Command Processing Routines # asmcmdpasswd_init # asmcmdpasswd_process_cmd # asmcmdpasswd_process_pwcreate # asmcmdpasswd_process_pwcopy # asmcmdpasswd_process_pwdelete # asmcmdpasswd_process_pwmove # asmcmdpasswd_process_pwset # asmcmdpasswd_process_pwget # asmcmdpasswd_process_help # # Error Routines # asmcmdpasswd_syntax_error # # Help Routines # asmcmdpasswd_get_asmcmd_cmds # # Misc Utility Routines # asmcmdpasswd_get_res_list ############################################################################# package asmcmdpasswd; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(asmcmdpasswd_init ); use strict; use Getopt::Std; use asmcmdglobal; use asmcmdshare; use asmcmdparser; use asmcmdbase; ####################### ASMCMDPASSWD Global Constants ###################### ####################### ASMCMDPASSWD Global Variables ###################### my (%asmcmdpasswd_cmds) = (pwcreate => { }, pwcopy => { }, pwmove => { }, pwdelete => { }, pwset => { }, pwget => { }, ); my ($PLSQL_NUMBER) = 22; my ($PLSQL_PWFILE) = 28; sub is_asmcmd { return 1; } ######## # NAME # asmcmdpasswd_init # # DESCRIPTION # This function initializes the asmcmdpasswd module. # # PARAMETERS # None # # RETURNS # Null # # NOTES # Only asmcmdcore_main() calls this routine. ######## sub init { # All of the arrays defined in the asmcmdglobal module must be # initialized here. Otherwise, an internal error will result. push (@asmcmdglobal_command_callbacks, \&asmcmdpasswd_process_cmd); push (@asmcmdglobal_help_callbacks, \&asmcmdpasswd_process_help); push (@asmcmdglobal_command_list_callbacks, \&asmcmdpasswd_get_asmcmd_cmds); push (@asmcmdglobal_is_command_callbacks, \&asmcmdpasswd_is_cmd); push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdpasswd_is_wildcard_cmd); push (@asmcmdglobal_syntax_error_callbacks, \&asmcmdpasswd_syntax_error); push (@asmcmdglobal_no_instance_callbacks, \&asmcmdpasswd_is_no_instance_cmd); %asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdpasswd_cmds); #Perform ASMCMD consistency check if enabled if ($asmcmdglobal_hash{'consistchk'} eq 'y') { if (!asmcmdshare_check_option_consistency(%asmcmdpasswd_cmds)) { exit 1; } } } ######## # NAME # asmcmdpasswd_process_cmd # # DESCRIPTION # This routine calls the appropriate routine to process the command # specified by $asmcmdglobal_hash{'cmd'}. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # 1 if command is found in the asmcmdpasswd module; 0 if not. # # NOTES # Only asmcmdcore_shell() calls this routine. ######## sub asmcmdpasswd_process_cmd { my ($dbh) = @_; my ($succ) = 0; my ($result); # Get current command from global value, which is set by # asmcmdpasswd_parse_asmcmd_args()and by asmcmdcore_shell(). my ($cmd) = $asmcmdglobal_hash{'cmd'}; # Declare and initialize hash of function pointers, each designating a # routine that processes an ASMCMDTEMPLATE command. my (%cmdhash) = ( pwcreate => \&asmcmdpasswd_process_pwcreate, pwcopy => \&asmcmdpasswd_process_pwcopy, pwmove => \&asmcmdpasswd_process_pwmove, pwdelete => \&asmcmdpasswd_process_pwdelete, pwset => \&asmcmdpasswd_process_pwset, pwget => \&asmcmdpasswd_process_pwget, ); if (defined ( $cmdhash{ $cmd } )) { # If user specifies a known command, then call routine to process it. # $result = $cmdhash{ $cmd }->($dbh); $succ = 1; } return $succ; } ######## # NAME # asmcmdpasswd_process_help # # DESCRIPTION # This function is the help function for the ASMCMDPASSWD module. # # PARAMETERS # command (IN) - display the help message for this command. # # RETURNS # 1 if command found; 0 otherwise. ######## sub asmcmdpasswd_process_help { my ($command) = shift; # User-specified argument; show help on $cmd. # my ($desc); # Command description for $cmd. # my ($succ) = 0; # 1 if command found, 0 otherwise. # if (asmcmdpasswd_is_cmd ($command)) { # User specified a command name to look up. # $desc = asmcmdshare_get_help_desc($command); asmcmdshare_print "$desc\n"; $succ = 1; } return $succ; } ######## # NAME # asmcmdpasswd_is_cmd # # DESCRIPTION # This routine checks if a user-entered command is one of the known # ASMCMD internal commands that belong to the ASMCMDPASSWD module. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # True if $arg is one of the known commands, false otherwise. ######## sub asmcmdpasswd_is_cmd { my ($arg) = shift; return defined ( $asmcmdpasswd_cmds{ $arg } ); } ######## # NAME # asmcmdpasswd_is_wildcard_cmd # # DESCRIPTION # This routine determines if an ASMCMDPASSWD command allows the use # of wild cards. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # True if $arg is a command that can take wildcards as part of its argument, # false otherwise. ######## sub asmcmdpasswd_is_wildcard_cmd { my ($arg) = shift; return defined ($asmcmdpasswd_cmds{ $arg }) && (asmcmdshare_get_cmd_wildcard($arg) eq "true" ) ; } ######## # NAME # asmcmdpasswd_is_no_instance_cmd # # DESCRIPTION # This routine determines if a command can run without an ASM instance. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # 1 if $arg is a command that can run without an ASM instance or it does not # belong to this module # 0 if $arg is a command that needs to connect to an ASM instance # -1 if $arg is a command that may use an ASM instance. # # NOTES # The asmcmdpasswd module currently supports no command that can run # without an ASM instance. ######## sub asmcmdpasswd_is_no_instance_cmd { my ($arg) = shift; my ($rc); return 1 unless defined($asmcmdpasswd_cmds{$arg}); $rc = asmcmdshare_get_cmd_noinst($arg); if ($rc eq "true") { return 1; } elsif ($rc eq "undef") { return -1; } return 0; } ######## # NAME # asmcmdpasswd_parse_int_args # # DESCRIPTION # This routine parses the arguments for flag options for ASMCMDPASSWD # internal commands. # # PARAMETERS # cmd (IN) - user-entered command name string. # args_ref (OUT) - hash of user-specified flag options for a command, # populated by asmcmdparser. # # RETURNS # Zero on success; undefined on error. # # NOTES # $cmd must already be verified as a valid ASMCMDPASSWD internal command. ######## sub asmcmdpasswd_parse_int_args { my ($cmd, $args_ref) = @_; my (@string); my ($key); #include deprecated options if any if ($asmcmdglobal_deprecated_options{ $cmd }) { foreach my $key(keys %{$asmcmdglobal_deprecated_options{ $cmd }}) { push(@string, $asmcmdglobal_deprecated_options{$cmd}{$key}[0]); } } # Use asmcmdparser_parse_issued_command() from the asmcmdparser package to # parse arguments for internal commands. These arguments are stored in @ARGV if (!asmcmdparser_parse_issued_command($cmd, $args_ref,\@string)) { # Print correct command format if syntax error. # asmcmdpasswd_syntax_error($cmd); return undef; } return 0; } ######## # NAME # asmcmdpasswd_syntax_error # # DESCRIPTION # This function prints the correct syntax for a command to STDERR, used # when there is a syntax error. This function is responsible for # only ASMCMDPASSWD commands. # # PARAMETERS # cmd (IN) - user-entered command name string. # # RETURNS # 1 if the command belongs to this module; 0 if command not found. # # NOTES # These errors are user-errors and not internal errors. They are of type # record, not signal. # # Functions in this module can call this function directly, without # calling the asmcmdshare::asmcmdshare_syntax_error equivalent. The # latter is used only by the asmcmdcore module. ######## sub asmcmdpasswd_syntax_error { my ($cmd) = shift; my ($cmd_syntax); # Correct syntax for $cmd. # my ($succ) = 0; #display syntax only for commands in this module. if (asmcmdpasswd_is_cmd($cmd)) { $cmd_syntax = asmcmdshare_get_help_syntax($cmd); # Get syntax for $cmd. # $cmd_syntax = asmcmdshare_trim_str ($cmd_syntax); # Trim blank spaces # if (defined ($cmd_syntax)) { asmcmdshare_printstderr 'usage: ' . $cmd_syntax . "\n"; asmcmdshare_printstderr 'help: help ' . $cmd . "\n"; $succ = 1; } if ($asmcmdglobal_hash{'mode'} eq 'n') { $asmcmdglobal_hash{'e'} = -1; } } return $succ; } ######## # NAME # asmcmdpasswd_get_asmcmd_cmds # # DESCRIPTION # This routine constructs a string that contains a list of the names of all # ASMCMD internal commands and returns this string. # # PARAMETERS # None. # # RETURNS # A string contain a list of the names of all ASMCMD internal commands. # # NOTES # Used by the help command and by the error command when the user enters # an invalid internal command. # # IMPORTANT: the commands names must be preceded by eight (8) spaces of # indention! This formatting is mandatory. ######## sub asmcmdpasswd_get_asmcmd_cmds { return asmcmdshare_filter_invisible_cmds(%asmcmdpasswd_cmds); } ######## # NAME # asmcmdpasswd_get_res_list # # DESCRIPTION # To find a list of resources associated with the given password file # # PARAMETERS # $filepath - full path name of password file # # RETURNS # @reslist - list of resource names associated with the given passwd file # ######## sub asmcmdpasswd_get_res_list { my ($filepath) = shift ; my (@reslist, $hasres, $ret); my ($cdet); my ($lib) = $asmcmdglobal_hash{'asmperl'}; undef &ASMCMDkgfPWFileGetRes; $cdet = DynaLoader::dl_find_symbol($lib, "XS_ASMCMDCLNT_kgfPWFileGetRes"); DynaLoader::dl_install_xsub("ASMCMDkgfPWFileGetRes", $cdet); ($ret, $hasres, @reslist) = ASMCMDkgfPWFileGetRes( $filepath, ''); if ($ret != 0 ) { asmcmdshare_trace (3, "NOTE:Get CRS Resource List failed for $filepath err $ret\n", 'n', 'y'); die "Error: GetResource List failed for $filepath ret $ret\n"; } # if no resources returned make sure the reslist is empty. if ($hasres == 0 ) { @reslist = (); # empty the resource list } return @reslist; } ######## # NAME # asmcmdpasswd_process_pwcreate # # DESCRIPTION # This function processes the asmcmd command pwcreate. # This function calls orapwd internally to create the pasword file, and uses # srvctl to update the CRSD resource. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdpasswd_process_cmd() calls this function. # ######## sub asmcmdpasswd_process_pwcreate { my ($dbh) = shift; my ($format) = undef; my ($force) = 0; my (%args); my ($dbuniquename, $asm); my ($filepath, $filename, $syspassword); my (@eargs); my ($alias, %norm); my @buf; # Buffer to hold command output. my $ret = asmcmdpasswd_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); $dbuniquename = $args{'dbuniquename'} if defined $args{'dbuniquename'}; $asm = $args{'asm'} if defined $args{'asm'}; $format = $args{'format'} if defined $args{'format'}; $force = 1 if (defined($args{'f'})); ($filepath, $syspassword) = @{$args{'pwcreate'}}; %norm = asmcmdpasswd_normalized_files(\$dbh, undef, $filepath); if (!$norm{'dest_success'}) { asmcmdshare_error_msg(9455, undef); return; } $filepath = $norm{'dest_filepath'}; if ($filepath !~ m/^\+/) { #Error, password file should be located on a diskgroup # and the name of the disk group should be preceded by a '+' symbol. asmcmdshare_error_msg(9455, undef); return; } if (defined($format) && $format !~ m/^12(.2)?$/) { asmcmdshare_error_msg(9464, undef); return; } # # ORAPWD internally checks for resource name associated with given password # file, and multiple resources using the given password file, or if given # password file exists, and action based on "force" specified or not. # my (@patharr) = ("$ENV{'ORACLE_HOME'}/bin/", "$ENV{'ORACLE_HOME'}/rdbms/bin/"); my ($opt); # dbuniquename $opt = "file=$filepath dbuniquename=$dbuniquename". " password=$syspassword" if (defined($dbuniquename)); # asm $opt = "file=$filepath asm=y". " password=$syspassword" if (defined($asm)); # force option $opt = $opt . " force=y" if ($force == 1); # format option $opt = $opt . " format=$format" if (defined($format)); my $errorflag = 'n'; @buf = asmcmdshare_execute_tool ("orapwd", ".exe", $opt, \@patharr); $errorflag = 'y' if ($@ ne ''); foreach(@buf) { chomp $_; $errorflag = 'y' if ($_ =~ /[A-Z]+-[0-9]+\s*:/); # If an error is detected asmcmdshare_trace(3, "$_", 'y', 'y') if ($errorflag eq 'y'); } if ($errorflag eq 'y') { asmcmdshare_error_msg(9454, undef); } else { asmcmdshare_trace(3, "The Password file was created successfuly by " . "ASMCMD through an internal call to orapwd.",'y','n'); } return; } ######## # NAME # asmcmdpasswd_process_pwcopy # # DESCRIPTION # This top-level routine processes the pwcopy command. # This function calls the core function of the ASMCMD cp command # to copy the password file from the source to the destination. # It then uses srvctl to update the CRSD resource with the new location of # the password if and only if the user specifies either the '--asm' or # '--dbuniquename' option. # # PARAMETERS # dbh (IN) - initialize database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdpasswd_process_cmd() calls this routine. ######## sub asmcmdpasswd_process_pwcopy { my ($dbh) = shift; # local auto-variables # my (%args); # cmd args # my (@eargs); my ($ret); my ($copy_success_hash); # A reference to a hash of src and dest files # # that were successfully copied # my ($copy_success) = 0; # Flag to indicate whether the copy was # # successful or not # my (%norm); # See asmcmdshare_normalize_path() return value comments. # my ($force) = 0; my ($dbuniquename) = undef; my ($asm) = undef; my ($src_filepath, $dest_filepath); my ($passwordfile_loc) = ""; $ret = asmcmdbase_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); # check for the force option $force = 1 if (defined($args{'f'})); # check for the dbuniquename option. if (defined($args{'asm'})) { $dbuniquename = "ASM"; $asm = 1; } elsif (defined($args{'dbuniquename'})) { $dbuniquename = $args{'dbuniquename'}; } ($src_filepath, $dest_filepath) = @{$args{'pwcopy'}}; %norm = asmcmdpasswd_normalized_files(\$dbh, $src_filepath, $dest_filepath); if (!$norm{'src_success'} || !$norm{'dest_success'}) { return; } $src_filepath = $norm{'src_filepath'}; $dest_filepath = $norm{'dest_filepath'}; ###### -If OS -> OS- ###### if ($src_filepath !~ m/^\+/ && $dest_filepath !~ m/^\+/) { #Error out, OS -> OS not supported asmcmdshare_error_msg(9458, undef); return; } ###### -If DG -> same DG- ###### if ($src_filepath =~ m/^\+/ && $dest_filepath =~ m/^\+/ && $norm{'src_DG'} == $norm{'dest_DG'}) { #Error out, DG -> same DG not supported asmcmdshare_error_msg(9459, undef); return; } ###### -If destination is OS CRS Resource cannot be updated ###### ###### Only if $asm or $dbuniquename specified ###### if ((defined($asm) || defined($dbuniquename)) && ($dest_filepath !~ m/^\+/)) { asmcmdshare_error_msg (9456, undef); return; } if (defined($dbuniquename) || defined($asm)) { $ret = asmcmdpasswd_get_pwfile ($asm, $dbuniquename, \$passwordfile_loc); if ($ret && ($passwordfile_loc ne "" )) { # The resource has already a password file associated with it. if ($force == 0) { push (@eargs, $passwordfile_loc); push (@eargs, 'asm') if defined($asm); push (@eargs, $dbuniquename) if defined($dbuniquename); asmcmdshare_error_msg(8028, \@eargs); return; } else { $ret = asmcmdpasswd_set_pwfile ($asm, $dbuniquename, ""); } } } ###### -Copy the password file- ###### ${$args{'pwcopy'}}[0] = $src_filepath; ${$args{'pwcopy'}}[1] = $dest_filepath; # copy the arguments for pwcopy so asmcmdbase_cp_core will process it # correctly. @{$args{'cp'}} = @{$args{'pwcopy'}}; # set the dbuniquename, if specified if (defined($dbuniquename)) { $asmcmdglobal_hash{'dbuniquename'} = $dbuniquename; asmcmdshare_trace(3, "dbuniquename is $asmcmdglobal_hash{'dbuniquename'}", 'y', 'n'); } # executes the core code of ASMCMD cp command to copy the password file to # the destination $copy_success_hash = asmcmdbase_cp_core($dbh, %args); while ( my ($key, $value) = each(%$copy_success_hash) ) { # get the absolute path of src file and dest file $src_filepath = $key; $dest_filepath = $value; $copy_success++; } ###### -Check that copy succeeded- ###### if (!$copy_success) { # Proceed no further. Error message would have been displayed at the cp # level. return; } asmcmdshare_trace(3, "The password file $src_filepath was copied " . "successfully by ASMCMD to $dest_filepath", 'y', 'n'); ###### -Update the CRS resource if necessary- ###### # Attempt to update the CRS resource with the new location of the password # file if and only if the user specifies either the '--asm' or # '--dbuniquename' option, and the destination file is on an ASM DG. if ((defined $args{'asm'} || defined $args{'dbuniquename'}) && $copy_success == 1) { # The dest_filepath here will be on DG only. asmcmdpasswd_set_pwfile ($asm, $dbuniquename, $dest_filepath); } return; } ######## # NAME # asmcmdpasswd_process_pwmove # # DESCRIPTION # This top-level routine processes the pwmove command. # This function calls the core function of the ASMCMD cp command # to copy the password file from the source to the destination. # Then deletes the original file from the source path. # It then uses srvctl to update the CRSD resource with the new location of # the password file. # # PARAMETERS # dbh (IN) - initialize database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdpasswd_process_cmd() calls this routine. ######## sub asmcmdpasswd_process_pwmove { my ($dbh) = shift; # local auto-variables # my (%args); # cmd args # my (@eargs); my ($ret); my @buf = (); my ($copy_success_hash); # A reference to a hash of src and dest files # # that were successfully copied # my ($copy_success) = 0; # Flag to indicate whether the copy was # # successful or not # my (%norm); # See asmcmdshare_normalize_path() return value comments. # my ($alias_path); # User-entered raw path for deletion. # my ($alias_name); # Alias name of a path. # my ($is_dir); # Flag: 'Y' if alias is a directory; 'N' otherwise. # my ($gnum); # Group number. # my ($gname); # Group name. # my ($par_id); # Parent ID of an alias. # my ($spprserr) = 0; # Whether to suppress errors on normalization. # my ($i); # Iteration variable for for() loops. # my (@entries); my ($dbuniquename) = undef; my ($asm) = undef; my ($force) = 0 ; my ($src_filepath, $dest_filepath); my ($passwordfile_loc); my ($sqlstmt, $sth, $row); my (@src_aliases) = (); my (@reslist); # get option parameters $ret = asmcmdbase_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); $dbuniquename = $args{'dbuniquename'} if defined $args{'dbuniquename'}; $asm = 1 if defined $args{'asm'}; $force = 1 if (defined ($args{'f'})); ($src_filepath, $dest_filepath) = @{$args{'pwmove'}}; if (defined($dbuniquename) || defined ($asm) ) { $ret = asmcmdpasswd_get_pwfile ($asm, $dbuniquename, \$passwordfile_loc); if ((defined ($ret) && ($ret == 1)) && (defined ($passwordfile_loc) && (length($passwordfile_loc) > 0 )) && ($force == 0 )) { push (@eargs, $passwordfile_loc); push (@eargs, 'asm') if defined($asm); push (@eargs, $dbuniquename) if defined($dbuniquename); asmcmdshare_error_msg (8028, \@eargs); return ; } # remove the resource value. asmcmdpasswd_set_pwfile ($asm, $dbuniquename, ""); } %norm = asmcmdpasswd_normalized_files(\$dbh, $src_filepath, $dest_filepath); # If normalization failed, then return. Errors would have been printed by # normalization routine. if (!$norm{'src_success'} || !$norm{'dest_success'}) { return; } $src_filepath = $norm{'src_filepath'}; $dest_filepath = $norm{'dest_filepath'}; ######- Find all aliases for this src file -###### if ($norm{'src_onDG'}) { $src_filepath =~ m/[\\\/]+([^\\\/]+)$/; $alias_name = $1; my @info = (); my ($file_number); #retreive the unique file number given the parent_id,reference_id, #group_number and filename asmcmdshare_get_subdirs($dbh, \@info, $norm{'src_DG'}, $norm{'src_reference_index'}, $norm{'parent_index'}, $alias_name, undef, 0, 0); $file_number = $info[0]->{'file_number'}; # Find the SYS alias. $alias_name = asmcmdbase_get_alias_path($dbh, $norm{'src_DG'}, $file_number, 'Y'); push(@src_aliases, $alias_name); # Find the USER created alias. $alias_name = asmcmdbase_get_alias_path($dbh, $norm{'src_DG'}, $file_number, 'N'); push(@src_aliases, $alias_name); } ###### -If OS -> OS- ###### if ($src_filepath !~ m/^\+/ && $dest_filepath !~ m/^\+/) { #Error out, OS -> OS not supported asmcmdshare_error_msg(9458, undef); return; } ###### -If DG -> same DG- ###### if ($src_filepath =~ m/^\+/ && $dest_filepath =~ m/^\+/ && $norm{'src_DG'} == $norm{'dest_DG'}) { #Error out, DG -> same DG not supported asmcmdshare_error_msg(9459, undef); return; } ###### If the destination file is on OS, res can not be updated ####### ###### Only if $asm or $dbuniquename specified ####### if ((defined($asm) || defined($dbuniquename)) && ($dest_filepath !~ m/^\+/)) { asmcmdshare_error_msg (9456, undef); return; } # get the resource(s) associated with given source password file name @reslist = asmcmdpasswd_get_res_list ($src_filepath); # if shared by more than one resource - can't move, bail out. if ($#reslist > 1) { @eargs = ($src_filepath); asmcmdshare_error_msg (8026, \@eargs); return; } # if only one resource and not matching given res - can't move, bail out if (($#reslist == 1) && !((defined($asm) && ($reslist[0] eq "ora.asm")) || (defined($dbuniquename) && ($reslist[0] eq "db.$dbuniquename.db")))) { @eargs = ($src_filepath); asmcmdshare_error_msg (8026, \@eargs); return; } ###### -Copy the password file- ###### ${$args{'pwmove'}}[0] = $src_filepath; ${$args{'pwmove'}}[1] = $dest_filepath; # copy the arguments for pwmove so asmcmdbase_cp_core will process it # correctly. @{$args{'cp'}} = @{$args{'pwmove'}}; # executes the core code of ASMCMD cp command to copy the password file to # the destination. $copy_success_hash = asmcmdbase_cp_core($dbh, %args); while ( my ($key, $value) = each(%$copy_success_hash) ) { # get the absolute path of src file and dest file $src_filepath = $key; $dest_filepath = $value; $copy_success++; } ###### -Check that copy succeeded- ###### if (!$copy_success) { # Proceed no further. Error message would have been displayed at the copy # level. return; } # Reconnect to instance since dbh handle would become useless after the copy asmcmdbase_disconnect($dbh) if defined ($dbh); $dbh = asmcmdbase_connect(undef); ###### -Delete the src file- ###### if ($src_filepath =~ m/^\+/) # If the src file was on a DG, use sql query to # drop the file { $alias_path = $src_filepath; %norm = asmcmdshare_normalize_path($dbh, $alias_path, $spprserr, \$ret); # Error if normalization failed/ password file does not exist if ($ret != 0) { @eargs = ($alias_path); asmcmdshare_error_msg(9452, \@eargs); return; } # Remove one entry at a time, if $alias_path contains '*' and has multiple # password file matches. for ($i = 0; $i < @{ $norm{'path'} }; $i++) { $alias_name = $alias_path = $norm{'path'}->[$i]; $alias_name =~ s,.*/([^/]+)$,$1,; # Get last level of path for name.# $par_id = $norm{'par_id'}->[$i]; $gnum = $norm{'gnum'}->[$i]; # If parent index is -1, then the directory must be a diskgroup or '+'; # thus we cannot remove it. if ($par_id != -1) { asmcmdshare_get_subdirs($dbh, \@entries, $gnum, undef, $par_id, $alias_name, undef, 0, 0); $is_dir = $entries[$i]->{'alias_directory'}; $gname = asmcmdshare_get_gname_from_gnum ($dbh, $gnum); # Run SQL to remove an entry. asmcmdbase_rm_sql($dbh, $gname, $alias_path, $is_dir); } } } else # If the src file is on OS filesystem, use system command to remove it { $ret = 0; eval { $ret = unlink("$src_filepath"); }; if ($@ || !defined($ret) || !$ret) { # Warn, no need to error out asmcmdshare_print("Couldn't delete $src_filepath from OS filesystem\n"); } } asmcmdshare_trace(3, "The password file $src_filepath was moved " . "successfuly by ASMCMD to $dest_filepath", 'y', 'n'); ####### -Now update the CRS resource if necessary- ###### # Attempt to update the CRS resource with the new location of the password # file if and only if the user specifies either the '--asm' or # '--dbuniquename' option, and the destination file is on an ASM DG. if ((defined $args{'asm'} || defined $args{'dbuniquename'}) && $copy_success == 1) { # $dest_filepath will be on DG here. asmcmdpasswd_set_pwfile ($asm, $dbuniquename, $dest_filepath); } return; } ######## # NAME # asmcmdpasswd_process_pwdelete # # DESCRIPTION # This top-level routine processes the pwdelete command. # This function removes the password file from the specified location # and updates the CRSD resource. # # PARAMETERS # dbh (IN) - initialize database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdpasswd_process_cmd() calls this routine. ######## sub asmcmdpasswd_process_pwdelete { my ($dbh) = shift; my (%args); # Argument hash used by asmcmdparser. # my (%norm); # See asmcmdshare_normalize_path() return value comments. # my ($ret); # asmcmdbase_parse_int_args() return value. # my ($dbuniquename); my ($asm); my ($force) = 0 ; my ($alias_name, $filepath, $filetype); my @buf; # Buffer to hold command output. # my (@eargs); my (@reslist); $ret = asmcmdpasswd_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); $dbuniquename = $args{'dbuniquename'} if defined $args{'dbuniquename'}; $asm = 1 if defined $args{'asm'}; $force = 1 if defined ($args{'f'}); ($filepath) = @{$args{'pwdelete'}} if defined $args{'pwdelete'}; if (defined($args{'dbuniquename'}) || defined ($args{'asm'})) { $ret = asmcmdpasswd_get_pwfile ($asm, $dbuniquename, \$filepath); } elsif (defined $filepath) { %norm = asmcmdpasswd_normalized_files(\$dbh, $filepath, undef); if (!$norm{'src_success'}) { return; } $filepath = $norm{'src_filepath'}; } # # ORAPWD utility handles the clearing of resource name of given password # and checking if more than one resources are using sceanrio. # ######- Find all aliases for this src file -###### $filepath = $norm{'src_filepath'}; ###### -Delete the file- ###### if (defined $args{'dbuniquename'} || defined $args{'asm'} || (@{$args{'pwdelete'}} && $filepath =~ /^\+/)) # If the src file was on a DG, use orapwd to drop the file { my (@patharr) = ("$ENV{'ORACLE_HOME'}/bin/", "$ENV{'ORACLE_HOME'}/rdbms/bin/"); my $opt; #dbuniquename $opt = "delete=y dbuniquename=$dbuniquename" if (defined($dbuniquename)); #asm $opt = "delete=y asm=y" if (defined($asm)); # if file name is provided $opt = "delete=y file=$filepath" if defined($filepath); # force $opt = "$opt". " force=y" if ($force == 1); my $errorflag = 'n'; @buf = asmcmdshare_execute_tool ("orapwd", ".exe", $opt, \@patharr); $errorflag = 'y' if ($@ ne ''); foreach(@buf) { chomp $_; $errorflag = 'y' if ($_ =~ /[A-Z]+-[0-9]+\s*:/); # If an error is found asmcmdshare_trace(3, "$_", 'y', 'y') if ($errorflag eq 'y'); } if ($errorflag eq 'y') { asmcmdshare_error_msg(9462, undef); } else { asmcmdshare_trace(3, "The Password file was deleted successfuly by " . "ASMCMD through an internal call to orapwd.", 'y', 'n'); } } else # If the src file is on OS filesystem, use system command to remove it { $ret = 0; eval { $ret = unlink("$filepath"); }; if ($@ || !defined($ret) || !$ret) { # Warn, no need to error out asmcmdshare_print("Couldn't delete $filepath from OS filesystem\n"); return; } else { asmcmdshare_trace(3, "The password file $filepath was deleted " . "successfuly by ASMCMD", 'y', 'n'); } } return; } ######## # NAME # asmcmdpasswd_process_pwset # # DESCRIPTION # This top-level routine processes the pwset command. # This function sets the location of the password file associated with and # ASM or a DB instance on the CRS resource. # # PARAMETERS # dbh (IN) - initialize database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdpasswd_process_cmd() calls this routine. ######## sub asmcmdpasswd_process_pwset { my $dbh = shift; my %args; # Argument hash used by asmcmdparser. # my $ret; # asmcmdbase_parse_int_args() return value. # my @eargs; my $dbuniquename; my $asm; my $force = 0 ; my %norm; my $srvctl; my $srvctlcommand; # For executing the srvctl command. # my @buf = (); # Buffer to hold command output. # my @reslist; my $filepath; $ret = asmcmdpasswd_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); $dbuniquename = ""; $dbuniquename = $args{'dbuniquename'} if defined $args{'dbuniquename'}; $asm = 1 if defined $args{'asm'}; $force = 1 if defined $args{'f'}; if (defined($dbuniquename) || defined ($asm)) { $ret = asmcmdpasswd_get_pwfile ($asm, $dbuniquename, \$filepath); if (defined($ret) && ($ret == 1) && ($filepath ne "" && $filepath ne $args{'pwset'})) { if ($force == 0 ) { push (@eargs, $filepath); push (@eargs, 'asm') if defined ($asm); push (@eargs, $dbuniquename) if defined ($dbuniquename); # ASMCMD-8028 "Password file '%s' is associated with '%s' already. Use # the force option." asmcmdshare_error_msg (8028, \@eargs); return ; } } } ($filepath) = @{$args{'pwset'}}; if (!defined $filepath || $filepath eq '""' || $filepath eq "''") { $filepath = ""; } if ($filepath ne "") { %norm = asmcmdpasswd_normalized_files(\$dbh, $filepath, undef); if (!$norm{'src_success'}) { return; } $filepath = $norm{'src_filepath'}; if (!($filepath =~ m/^\+/)) { # ASMCMD-9456 "password file should be located on an ASM disk group" asmcmdshare_error_msg(9456, undef); return; } # Bug21159907: Check if the password file has been already set for another # resource, but only if the force option is not set. @reslist = asmcmdpasswd_get_res_list($filepath); if (scalar @reslist > 0 && !$force) { @eargs = $filepath; # ASMCMD-8026 Password file '%s' is in use. Use the force option. asmcmdshare_error_msg(8026, \@eargs); return; } } asmcmdpasswd_set_pwfile($asm, $dbuniquename, $filepath); return; } ######## # NAME # asmcmdpasswd_process_pwget # # DESCRIPTION # This top-level routine processes the pwget command. # This function retrieves the location of the password file associated with # and ASM or a DB instance from the CRS resource. # # PARAMETERS # dbh (IN) - initialize database handle, must be non-null. # # RETURNS # Null. # # NOTES # Only asmcmdpasswd_process_cmd() calls this routine. ######## sub asmcmdpasswd_process_pwget { my ($dbh) = shift; my (%args); # Argument hash used by asmcmdparser. # my ($ret); # asmcmdbase_parse_int_args() return value. # my (@eargs); my ($dbuniquename,$asm); my ($passwordfile_loc) = ""; $ret = asmcmdpasswd_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); $dbuniquename = $args{'dbuniquename'} if defined $args{'dbuniquename'}; $asm = 1 if defined $args{'asm'}; $ret = asmcmdpasswd_get_pwfile($asm, $dbuniquename, \$passwordfile_loc); if ($ret) { if ($passwordfile_loc eq "") { if ($asm) { asmcmdshare_print("Password file location has not been set for " . "ASM instance\n"); } else { asmcmdshare_print("Password file location has not been set for " . "DB instance\n"); } } else { asmcmdshare_print("$passwordfile_loc\n"); } } return; } ######## # NAME # asmcmdpasswd_set_pwfile # # DESCRIPTION # This function sets the password file location on the corresponding CRS # resource. # # PARAMETERS # asm (IN) - Whether an ASM or a DB resource is to be updated # dbuniquename (IN) - The dbuniquename, used only if asm is 0 # passwordfile_loc (IN) - The new location of the password file # to be set on CRS. # # RETURNS # 0 on failure # 1 on success # # NOTES # Assumes $passwordfile_loc is a valid path and the file is on DG # ######## sub asmcmdpasswd_set_pwfile { my ($asm) = shift; my ($dbuniquename) = shift; my ($passwordfile_loc) = shift; my ($ret) = 0; my ($srvctl, $srvctlcommand); my (@eargs) = (); my ($errorflag) = 'n'; my (@buf) = (); $srvctl = "$ENV{'ORACLE_HOME'}/bin/srvctl"; #Path in Win is ORACLE_HOME/bin/srvctl.bat $srvctl .= ".bat" if ($^O =~ /win/i); # Make sure the srvctl binary exists and can be executed. if (! -x $srvctl) { #If not, try at a second locaction. $srvctl = "$ENV{'ORACLE_HOME'}/srvm/bin/srvctl"; #path in Win is ORACLE_HOME/bin/srvctl.bat $srvctl .= ".bat" if ($^O =~ /win/i); if (! -x $srvctl) { @eargs = ($srvctl); asmcmdshare_error_msg(8316, \@eargs); return $ret; } } #untaint srvctl $srvctl =~ /([^\n^\r^\t]+)/; $srvctl = $1; if ($asm) { $srvctlcommand = "$srvctl modify asm -pwfile $passwordfile_loc"; } else { $srvctlcommand = "$srvctl modify database " . "-db $dbuniquename " . "-pwfile $passwordfile_loc"; } if (!asmcmdshare_runcmd("$srvctlcommand", \@buf, 1, 1)) { # command succeeded foreach(@buf) { chomp $_; $errorflag = 'y' if ($_ =~ /[A-Z]+-[0-9]+\s*:/);# If an error is detected asmcmdshare_trace(3, "$_", 'y', 'y') if ($errorflag eq 'y'); } } else { $errorflag = 'y'; } if ($errorflag eq 'y') { asmcmdshare_error_msg(9453, undef); return 0; } return 1; } ######## # NAME # asmcmdpasswd_get_pwfile # # DESCRIPTION # This function retrieves the password file location from the corresponding # CRS resource. # # PARAMETERS # asm (IN) - Whether the instance is an ASM or a DB # dbuniquename (IN) - The dbuniquenmae, used only if asm is 0 # pfile_loc_ref (IN) - Reference to the variable where the retrieved path # is to be stored. # # RETURNS # 0 on failure # 1 on success # # NOTES # ######## sub asmcmdpasswd_get_pwfile { my ($asm) = shift; my ($dbuniquename) = shift; my ($pfile_loc_ref) = shift; my ($srvctl, $srvctlcommand); my ($errorflag) = 'n'; my (@eargs) = (); my (@buf) = (); my ($ret) = 0; $srvctl = "$ENV{'ORACLE_HOME'}/bin/srvctl"; #Path in Win is ORACLE_HOME/bin/srvctl.bat $srvctl .= ".bat" if ($^O =~ /win/i); # Make sure the srvctl binary exists and can be executed. if (! -x $srvctl) { #If not, try at a second locaction. $srvctl = "$ENV{'ORACLE_HOME'}/srvm/bin/srvctl"; #path in Win is ORACLE_HOME/bin/srvctl.bat $srvctl .= ".bat" if ($^O =~ /win/i); if (! -x $srvctl) { @eargs = ($srvctl); asmcmdshare_error_msg(8316, \@eargs); return $ret; } } #untaint srvctl $srvctl =~ /([^\n^\r^\t]+)/; $srvctl = $1; if ($asm) { $srvctlcommand = "$srvctl config asm"; } else { $srvctlcommand = "$srvctl config database -db $dbuniquename"; } if (asmcmdshare_runcmd("$srvctlcommand", \@buf, 1, 1)) { $errorflag = 'y'; } foreach (@buf) { chomp $_; $errorflag = 'y' if ($_ =~ /[A-Z]+-[0-9]+\s*:/ && # If an error is detected $_ !~ /PRCA-1032 : ASM listener LISTENER does not exist/); asmcmdshare_trace(3, "$_", 'y', 'y') if ($errorflag eq 'y'); # Bug 24308847: Add the anchor for start of line to differentiate the lines # containing Password file and Backup of Password file when parsing output if ($errorflag eq 'n' && $_ =~ /^Password file: (.*)$/) { if (defined $1) { $$pfile_loc_ref = $1; } else { $$pfile_loc_ref = ""; } $ret = 1; } } if ($errorflag eq 'y') { asmcmdshare_error_msg(9457, undef); } else { $ret = 1; } return $ret; } ######## # NAME # asmcmdpasswd_file_type # # DESCRIPTION # This function retrieves the file type for a given file # # PARAMETERS # dbh_ref (IN) - reference to the dbh handle # fileName (IN) - The complete path to the file for which file type # is to be found out # fileType_ref (IN) - Reference to the variable where the retrived file # type is to be stored. # # RETURNS # 0 on failure # 1 on success # # NOTES # Assumes the path is a complete path and file exists. # ######## sub asmcmdpasswd_file_type { my ($fileName, $fileType_ref, $fileSz, $blkSz); my ($stmt, $dbh, $dbh_ref, $ret); my ($return_status) = 0; $dbh_ref = shift; $dbh = $$dbh_ref; $fileName = shift; $fileType_ref = shift; # get file information, block size, file size, file type $stmt = $dbh->prepare(q{ begin dbms_diskgroup.getfileattr(:fileName, :fileType, :fileSz, :blkSz); end; }); # Bind input parameters # $stmt->bind_param( ":fileName", $fileName ); # Bind ouput params # $stmt->bind_param_inout( ":fileType", $fileType_ref, $PLSQL_NUMBER); $stmt->bind_param_inout( ":fileSz", \$fileSz, $PLSQL_NUMBER); $stmt->bind_param_inout( ":blkSz", \$blkSz, $PLSQL_NUMBER); $ret = $stmt->execute(); if (!defined ($ret) && ($asmcmdglobal_hash{'mode'} eq 'n')) { $asmcmdglobal_hash{'e'} = -1; } if (!defined $$fileType_ref || $$fileType_ref < 1 ) { my (@eargs) = ($fileName); asmcmdshare_error_msg(8012, \@eargs); asmcmdshare_trace(1, $DBI::errstr, 'y', 'y') unless defined ($ret); asmcmdshare_error_msg(9461, \@eargs); } else { # Call was a success; $return_status = 1; } # reconnect asmcmdbase_disconnect($dbh) if defined ($dbh); #undef since we connect to local asm instance $$dbh_ref = asmcmdbase_connect(undef); return $return_status; } ######## # NAME # asmcmdpasswd_normalized_files # # DESCRIPTION # This function returns the full expanded path for a given destination, # OS or on on DG. # # PARAMETERS # dbh_ref (IN/OUT) - Reference to initialized database handle, must be # non-null. # src_filepath (IN) - src file path to be normalized # dest_filepath(IN) - the dest file path passed to the command by user. # Can be a directory path or partial path or which # may or may not contain the target filename. # # RETURNS # %return_hash (OUT) - Hash of values # $return_hash{'src_filepath'} = normalized $src_filepath # $return_hash{'src_success'} = status of normalization for src file # $return_hash{'src_exists'} = whether the src file exists # $return_hash{'src_onDG'} = whether the src file is on DG or on OS # $return_hash{'src_DG'} = if the src file is on DG, the DG num # $return_hash{'dest_filepath'} = normalized $dest_filepath; # $return_hash{'dest_success'} = status of normalization for dest file # $return_hash{'dest_exists'} = whether the dest directorystructure exists # $return_hash{'dest_onDG'} = whether the dest file is on DG or on OS # $return_hash{'dest_DG'} = if the dest file is on DG, the DG num # # NOTES # Assumes the reference to dbh handle is a valid and non-null # ######## # Assumes the src_fileapth is a full path containing the filename at the end sub asmcmdpasswd_normalized_files { my ($dbh_ref) = shift; my ($src_filepath) = shift; my ($dest_filepath) = shift; my ($src_filename, $src_filetype, $ret); my ($dir_path, $filename); my (@eargs, @paths, @ref_ids, @par_ids, @entry_list, @dg_nums, $name); my ($dbh) = $$dbh_ref; my %norm; my %return_hash; $return_hash{'src_reference_index'} = -1; $return_hash{'src_parent_index'} = -1; $return_hash{'src_filepath'} = $src_filepath; $return_hash{'src_success'} = 0; $return_hash{'src_exists'} = 0; $return_hash{'src_onDG'} = 0; $return_hash{'src_DG'} = -1; $return_hash{'dest_filepath'} = $dest_filepath; $return_hash{'dest_success'} = 0; $return_hash{'dest_exists'} = 0; # The directory structure exists $return_hash{'dest_onDG'} = 0; $return_hash{'dest_DG'} = -1; if (defined $src_filepath && $src_filepath ne "") { ###### -Normalize file- ###### # criteria: if it is an OS file, has to be full path, # otherwise it will be treated as a relative path # in the ASM context # if path doesn't start with '/', then it is an ASM relative path # every OS path must be absolute. if ( ($src_filepath !~ /^[a-z]:/i) && ($src_filepath !~ m'^[/\\\\]')) { $return_hash{'src_onDG'} = 1; # ASM file case # if source file name is not an an absolute OS path, assume it is an ASM # DG path and complete it %norm = asmcmdshare_normalize_path($$dbh_ref, $src_filepath, 0, \$ret); if ( $ret != 0 ) { @eargs = ($src_filepath); asmcmdshare_error_msg(9452, \@eargs); } else { $return_hash{'src_exists'} = 1; $return_hash{'src_filepath'} = $norm{'path'}->[0]; $return_hash{'src_DG'} = $norm{'gnum'}->[0]; $return_hash{'src_parent_index'} = $norm{'par_id'}->[0]; $return_hash{'src_reference_index'} = $norm{'ref_id'}->[0]; ###### -Check that the file is a password file- ###### if (asmcmdpasswd_file_type($dbh_ref, $norm{'path'}->[0], \$src_filetype)) { if ($src_filetype == $PLSQL_PWFILE) { @return_hash{keys %norm} = values %norm; $return_hash{'src_success'} = 1; } else { # pw* commands can only be used to operate on password file # commands @eargs = ($asmcmdglobal_hash{'cmd'}); asmcmdshare_error_msg(9460, \@eargs); } } } } else { # Assume the path is a full path to a file on the OS filesystem $return_hash{'src_onDG'} = 0; # If the path is simply a directory if (-d $src_filepath) { @eargs = ($src_filepath); asmcmdshare_error_msg(9452, \@eargs); $return_hash{'src_exists'} = 1; $return_hash{'src_success'}= 0; } # If the path is an existing filename elsif (-e $src_filepath) { $return_hash{'src_exists'} = 1; $return_hash{'src_success'}= 1; } # Else, the path is invalid else { @eargs = ($src_filepath); asmcmdshare_error_msg(9452, \@eargs); $return_hash{'src_exists'} = 0; $return_hash{'src_success'}= 0; } } return %return_hash if (!$return_hash{'src_success'}); } if (defined $dest_filepath && $dest_filepath ne "") { $src_filepath = $return_hash{'src_filepath'}; $src_filepath = "" if (!defined $src_filepath); $src_filepath =~ m/[\\\/]+([^\\\/]+)$/; $src_filename = $1; ###### -Normalize destination file- ###### if ( ($dest_filepath !~ /^[a-z]:/i) && ($dest_filepath !~ m'^[/\\\\]')) { $return_hash{'dest_onDG'} = 1; $return_hash{'dest_DG'} = -1; # Make the path absolute. $dest_filepath = asmcmdshare_make_absolute($dest_filepath); # Separate out the filename,if any, and the directory path $filename = ""; $dir_path = $dest_filepath; # If the $dest_filepath is of the form +diskgroup/path/to/filename if ($dest_filepath =~ m/[\\\/]+([^\\\/]+)$/) { $filename = $1 if defined $1; if ($filename ne "") { $dest_filepath =~ m/(.*)$filename$/; $dir_path = $1; } } # ASM file case # if source file name is not an an absolute OS path nor ASM path, # assume it is ASM and complete it %norm = asmcmdshare_normalize_path($$dbh_ref, $dest_filepath, 1, \$ret); if ( $ret == 0 ) { $dest_filepath = $norm{'path'}->[0]; @paths = @{ $norm{'path'} }; @ref_ids = @{ $norm{'ref_id'} }; @par_ids = @{ $norm{'par_id'} }; @dg_nums = @{ $norm{'gnum'} }; $name = $paths[0]; $name =~ s,.*/(.*)$,$1,; asmcmdshare_get_subdirs($$dbh_ref, \@entry_list, $dg_nums[0], $ref_ids[0], $par_ids[0], $name, undef, 0, 1); if ( ($ref_ids[0] == $dg_nums[0] << 24 ) || $entry_list[0]->{'alias_directory'} eq 'Y') { if ($filename eq "") { if (defined $src_filename) { $norm{'path'}->[0] = $norm{'path'}->[0] . '/' . $src_filename; } else { $norm{'path'}->[0] = $norm{'path'}->[0] . '/'; } } else { $norm{'path'}->[0] = $norm{'path'}->[0] . '/' . $filename; } $return_hash{'dest_exists'} = 1; $return_hash{'dest_filepath'} = $norm{'path'}->[0]; $return_hash{'dest_success'} = 1; $return_hash{'dest_DG'} = $norm{'gnum'}->[0]; } elsif ( $entry_list[0]->{'alias_directory'} eq 'N' ) { $return_hash{'dest_exists'} = 1; $return_hash{'dest_filepath'} = $norm{'path'}->[0]; $return_hash{'dest_success'} = 1; $return_hash{'dest_DG'} = $norm{'gnum'}; } else { $return_hash{'dest_exists'} = 0; $return_hash{'dest_success'} = 0; @eargs = ($norm{'path'}->[0]); asmcmdshare_error_msg(8014, \@eargs); } } else { $return_hash{'dest_exists'} = 0; $return_hash{'dest_success'} = 1; # given destination file does not exist, but is not an error # in case of pwcreate command. } asmcmdbase_disconnect($$dbh_ref) if defined ($$dbh_ref); $$dbh_ref = asmcmdbase_connect(undef); } # Path is an OS filesystem path else { $return_hash{'dest_onDG'} = 0; # If the path is a directory if ( -d $dest_filepath ) { # Remove trailing '/' or '\' $dest_filepath =~ s/[\/\\]$//; if (defined $src_filename) { $return_hash{'dest_filepath'} = $dest_filepath . '/'. $src_filename; if ( -e $return_hash{'dest_filepath'}) { $return_hash{'dest_exists'} = 1; $return_hash{'dest_success'} = 1; } } else { $return_hash{'dest_filepath'} = $dest_filepath . '/'; } $return_hash{'dest_exists'} = 1; $return_hash{'dest_success'} = 1; } # If the path is a file elsif ( -e $dest_filepath ) { $return_hash{'dest_filepath'} = $dest_filepath; $return_hash{'dest_exists'} = 1; $return_hash{'dest_success'} = 1; } else #$dest_filepath is NOT a dir and $dest_filepath does not exist { $filename = ""; # Extract the filename from the path - everything after the last # '\' or '/'. Store it in $filename, if there is any filename. $dest_filepath =~ m/[\\\/]+([^\\\/]+)$/; $filename = $1 if defined $1; if ($filename ne "") { # Extract the parent directory path $dest_filepath =~ m/(.*)$filename$/; $dir_path = $1; # If the parent directory doesn't exist, then path is invalid if (-d $dir_path) { $return_hash{'dest_success'} = 1; $return_hash{'dest_exists'} = 1; $return_hash{'dest_filepath'}= $dest_filepath } } @eargs = ($dest_filepath); asmcmdshare_error_msg(8005, \@eargs) if $return_hash{'dest_success'} == 0; } } } return %return_hash; } 1;