#!/usr/local/bin/perl
# 
# $Header: esaUtils.pl 20-dec-2005.18:34:51 dsukhwal Exp $
#
# esaUtils.pl
# 
# Copyright (c) 2004, 2005, Oracle. All rights reserved.  
#
#    NAME
#      esaUtils.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    dsukhwal    12/20/05 - not print if file_owner returns -1 
#    dsukhwal    08/25/05 - remove check_512char parentheses 
#    dkjain      08/18/05 - Correct return val of file_owner 
#    dsukhwal    06/30/05 - support flood control for all policies 
#    dsukhwal    05/25/05 - grabtrans 'dsukhwal_bug4369815' 
#    dsukhwal    05/18/05 - remove unused items 
#    dsukhwal    05/12/05 - support limit number of rows 
#    dsukhwal    05/03/05 - add windows utilitiess 
#    dsukhwal    02/15/05 - file_perm in exceptional cases 
#    dsukhwal    12/15/04 - graceful error handling 
#    dsukhwal    01/12/05 - permissions in octal 
#    dkjain      12/25/04 - Adding check_permission 
#    dsukhwal    12/13/04 - Fix case issues in utility scripts (bugs 4060138 and 4054953)
#    dkjain      11/26/04 - Fix Bug-4031882 
#    dsukhwal    11/25/04 - change file path format exceeding 64 chars 
#    dkjain      11/23/04 - Bug-3999014
#    dkjain      10/31/04 - Bug-3977629
#    dkjain      10/08/04 - dkjain_esa_impl_init
#    dkjain      10/08/04 - Creation
# 
 use File::stat; 
 use File::Find;
 use File::Basename;
  if($^O eq "MSWin32"){
    require "$ENV{EMDROOT}/sysman/admin/scripts/esaWin32Util.pl";
  }

 my $err="" ;

##############$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$####################
 $globalProperty ;
 $permString = 0 ;
 $ownerName = 0 ;
 sub util_print{
   my $dir = shift;
   if($permString){
    printf "em_result=$globalProperty|%03o|$dir\n",$permString ; 
   }
   elsif($ownerName){
    print "em_result=$globalProperty|$ownerName|$dir\n" ; 
   }
   else{
    print "em_result=$globalProperty|$dir\n" ; 
   }
 }
##############$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$####################

#####################################################################
 sub comma_separated_files{
 #first argument is the list of files separated by commas. Second argument is mask(zero if file owners are required
 #non-zero if permissions are required). If mask is zero, third argument is interpreted as oracleHomeOwner, and fourth as 
 #maxRows. If mask is non-zero, third argument is maxRows. Returns the number of lines printed.
  #my ($commaSepFilesList,$mask,$oracleHomeOwner,$maxRows) = @_ ; When maxRows is -1, which means we have to push all the 
  #rows, the splice function will not be called, causing no limit to be applied
  my $commaSepFilesList = shift;
  my $mask = shift;
  my $maxRows;
  my $oracleHomeOwner;
  if($mask){
    $maxRows = shift;
  }
  else{
    $oracleHomeOwner = shift;
    $maxRows = shift;
  }
  #print "em_result=csf|commaSepFilesList=$commaSepFilesList;msk=$mask;maxRows=$maxRows;oracleHomeOwner=$oracleHomeOwner\n";
  my $retMode ;
  my $file ;
  my @filesList = split(/, /,$commaSepFilesList);
  @filesList = uniq_array(@filesList);#remove duplicate and blank entries
  if( defined($maxRows) && ($maxRows >= 0) ){
    splice(@filesList, $maxRows);
  }#keep at most  maxRows entries
  my $rwxOther ;
  my $numRows = 0;
  
  foreach $file (@filesList)
  {
   if($mask){
    $retMode = file_perm($file);
    if($retMode >= 0){
        $retMode = $retMode & 0777;
        $rwxOther = $retMode & $mask ;
        if($rwxOther){
            #$permString = rwx_string($retMode);
            $permString = $retMode ;
            $file = check_512char($file);
            util_print($file); 
        }
    }
    #else{}  #file_perm failed
   }
   else{
    $permString = 0;
    $ownerName = file_owner($file) ;  
    #print "em_result=csfOwn|$ownerName|$oracleHomeOwner\n";
    if(($ownerName ne "")&&($ownerName ne $oracleHomeOwner)&&($ownerName != -1)){
       $file = check_512char($file); 
       util_print($file); 
    }
   } 
  } 
 return scalar @filesList;
 }
######################################################################
# sub ret_file_name{
  #my $filePath = shift ;
  #my @dirList ;
  #my $lastComponent ;
  
 # $filePath = check_512char($filePath);
  #return $filePath ;
  #if($^O =~ "linux"){ 
  # @dirList = split('/',$filePath) ;
  # $lastComponent = @dirList ;
  # if($lastComponent == 0){
  #  return ;
  # }
  # else{
  #  return $dirList[$lastComponent-1] ; 
  # }
  #}
  #else { Code for Window OS}
#}
#####################################################################

 sub check_permissions {
  my ($mode,$mask) = @_ ;
  my $rwx = $mode & $mask ;
  if($rwx)
  { return 1 ; }
  else 
  { return 0 ; }
 }

# This would return File Perm Mode, For an Example 0754. Returns -1 in case of any failure. Failure can be detected in the error variable
#In Future make this function working for Window OS also : Done
sub file_perm {
   my $fpath = shift ;
   my $info ;
   if($^O =~ "linux"){
    $info=stat($fpath) ;
    if($info){
     return $info->mode; # This field contain file mode info
    }
    else{
        warn "Could not get file permission for $fpath";
        return -1;
    }
   }
   elsif($^O eq "MSWin32"){
    return check_512char(win32_file_perm($fpath));
    #in case of failure,  win32_file_perm returns -1 and so will file_perm
   }
}


#This is to return the owner name as string, of the fpath 
#This has been modified to make it work for Window also
sub file_owner{
  my $fileName = shift ;
  if($^O =~ "linux"){ 
     if ($fileName eq $err) 
     {
         print "File Name Passed To The function Was A Null String \n"; 	
         return ""; 	
     } 
     my  $uid =file_owner_uid($fileName) ;
     if($uid == -1){
        return "";
     }
     else{
        my  $name  = getpwuid($uid); #This would return Name string of the corresponding UID
        return $name ;
     }
  }
  elsif($^O eq "MSWin32"){
    return win32_file_owner($fileName);
  }
  else{
    #code for systems neither mswin32, nor linux
  }
}
    


#This is to return UID for a given file Fpath
sub file_owner_uid {
   my $fileName = shift;	
   my $info=stat($fileName);
   if($info)
   {
    return $info->uid ;
   }
   return -1 ;
 }

# This is to return file type whether fpath is Dir or File
 sub file_type {
   my $fileName = shift ;
   eval{
       my $info=stat($fileName) or die "Could not get filetype of $fileName";
       return "f" unless -d $fileName ;
       return "d" unless -f $fileName ;
   };
 }

 sub rwx_string{
 my $mode = shift ;
 my $permission;

 my $read = "r" ;
 my $write = "w" ;
 my $exe = "x" ;

 my $owner_r = $mode & 0400 ; 
 my $owner_w = $mode & 0200 ;
 my $owner_x = $mode & 0100   ;  

 my $group_r = $mode & 0040 ; 
 my $group_w = $mode & 0020 ;
 my $group_x = $mode & 0010   ;  

 my $other_r = $mode & 0004 ; 
 my $other_w = $mode & 0002 ;
 my $other_x = $mode & 0001 ;  


 if($owner_r)
 { $permission = qq($permission$read); }
 else
 { $permission = qq($permission-); }

 if($owner_w)
 { $permission = qq($permission$write); }
 else
 { $permission = qq($permission-); }
 
 if($owner_x)
 { $permission = qq($permission$exe); }
 else
 { $permission = qq($permission-); }
 
 
 if($group_r)
 { $permission = qq($permission$read); }
 else
 { $permission = qq($permission-); }
 
 if($group_w)
 { $permission = qq($permission$write); }
 else
 { $permission = qq($permission-); }

 if($group_x)
 { $permission = qq($permission$exe); }
 else
 { $permission = qq($permission-); }

 if($other_r)
 { $permission = qq($permission$read); }
 else
 { $permission = qq($permission-); }

 if($other_w)
 { $permission = qq($permission$write); }
 else
 { $permission = qq($permission-); }

 if($other_x)
 { $permission = qq($permission$exe); }
 else
 { $permission = qq($permission-); }

 return $permission ;
}

sub uniq_array#takes an array as input, and returns another array with unique entries as output. Also removes blank entries
{
    my @paramValArray = @_;
    my $item;my @uniq;
    my %seen = ();
    foreach $item (@paramValArray)
    {
        if($item eq "")
        {
            $seen{$item}++;
        }
        else 
        {
            push(@uniq,$item) unless $seen{$item}++;
        }
    }
    return @uniq;
}

sub check_512char{
   my $fpath = shift ;
   my $last509char ;
   my $len = length($fpath);
   if($len > 512){
      $last509char = substr($fpath,($len-509));
      $fpath = qq(...$last509char);
   }
   return $fpath ;
}
sub compareNegInf{
#first argument is the number of rows already printed. Second argument is the maximum number of rows to be printed.
#Compares the numbers, considering -1 to be infinite. If more rows can be printed, returns 1, else returns 0
    my $numRows = shift;
    my $maxRows = shift;
    if($maxRows == -1){
        return 1;
    }
    elsif($numRows < $maxRows){
        return 1;
    }
    else{
        return 0;
    }
}

sub compareOwner{
#first argument is the property to be printed with em_result
#second argument is the maximum number of em_result rows to be printed 
#takes two filenames as third and fourth arguments. Returns 1 if their 
#owners are the same, 0 if their owners are not same
#returns -1 in case of any errors(file not existing, not argument given etc.
#if there are only three arguments, second file is taken to be the $ENV{'ORACLE_HOME'}
#also prints an em_result entry with the owner of the first file
#works with both mswin32 and linux
    my $prop = shift;
    my $maxRows = shift;
    if(!compareNegInf(0,$maxRows)){
        return;
    }
    my $file1 = shift;
    my $file2 = shift;
    if(!defined($prop)){
        return -1;
    }
    if(!defined($file1)){
        return -1;
    }
    if(!defined($file2)){
        $file2 = $ENV{'ORACLE_HOME'};
    }
    if($^O eq "MSWin32"){
        my $owner1 = win32_file_owner($file1);
        if($owner1 == -1){return -1;}
        my $owner2 = win32_file_owner($file2);
        if($owner2 == -1){return -1;}
        if($owner2 eq $owner1){
            return 1;
        }
        else{
            print "em_result=$prop|$file1|$owner1\n";
            return 0;
        }
    }
    elsif($^O eq "linux"){
        my $owner_id1 = file_owner_uid($file1);
        if($owner_id1 == -1){return -1;}
        my $owner_id2 = file_owner_uid($file2);
        if($owner_id2 == -1){return -1;}
        if($owner_id2 == $owner_id1){
            return 1;
        }
        else{
            my $ownerName = getpwuid($owner_id1);
            print "em_result=$prop|$file1|$ownerName\n";
            return 0;
        }
    }
}
 
 1 ;
