# # $Header: rfsGetFileList.pl 06-feb-2006.12:38:10 sreddy Exp $ # # rfsGetFileList.pl # # Copyright (c) 2004, 2006, Oracle. All rights reserved. # # NAME # rfsGetFileList.pl - # # DESCRIPTION # Perl script to get file list for Remote File Selector Page # # NOTES # # # MODIFIED (MM/DD/YY) # sreddy 02/06/06 - Backport sreddy_bug-4968435 from main # ajere 12/10/05 - XbranchMerge ajere_bug-4779290 from main # ajere 04/14/05 - Add interpretPattern subroutine # ajere 01/31/05 - Windows: Get contents starting from My Computer # ajere 01/05/05 - Add timeout # ajere 10/05/04 - Support search patterns *, % and _ # ajere 07/02/04 - Creation # require "emd_common.pl"; use strict; #Global variables my $windowsOsCmd = "cmd"; my $winRoot = "MC"; my $unixOsCmd = "/bin/sh"; my $timeout = 3; #Subroutine declarations sub getFileList(); sub getFileSeparator($); sub getPermissions($); sub readOpenedDir($$$); sub getFileDetails($$$$\@); sub interpretPattern($); ################################################### # getFileList() # Get the file list in a specified directory # Last line contains result status : # 0 - OK # 1 - There are more files than maxFiles returned # 2 - Operation timed out ################################################### sub getFileList() { my $osCmd = $ARGV[0]; my $dirName = $ARGV[1]; my $fetchFileType = $ARGV[2]; my $maxFiles = $ARGV[3]; my $searchPattern = $ARGV[4]; #If the directory is null, return if ($dirName eq '') { EMD_PERL_ERROR("[rfsGetFileList.pl] Input directory is empty!\n"); exit 1; } #For Windows OS, execute exec_commonenv.bat if mount_shares.bat #and unmount_shares.bat files exist if (($osCmd eq $windowsOsCmd) && !defined($ENV{EM_AGENT_COMMONENV_BAT_EXEC}) && (-e "$ENV{EMDROOT}/bin/mount_shares.bat") && (-e "$ENV{EMDROOT}/bin/unmount_shares.bat")) { #save STDERR into STDERZR_ORIG. Upon failure, skip exec_commonenv.bat step if (open (STDERR_ORIG, ">&STDERR")) { #send STDERR to null device. Upon failure, skip exec_commonenv.bat step if (open (STDERR, ">/dev/null")) { my $beginToken="BEGIN_REMOTE_OP_RESULT_SET_AFTER_COMMONENV_BAT"; my $endToken="END_REMOTE_OP_RESULT_SET_AFTER_COMMONENV_BAT"; my $beginTokenFound=0; my $line; #Batch file exec_commonenv.bat sets EM_AGENT_COMMONENV_BAT_EXEC and #call this script again after network shares from mount_shares.bat #are mounted. This block won't get executed then and the array #scriptResult will contain actual output within start and end tokens. my @scriptResult=`$ENV{EMDROOT}\\bin\\exec_commonenv.bat rfsGetFileList.pl @ARGV`; #restore STDERR to STDERR_ORIG close(STDERR); open (STDERR, ">&STDERR_ORIG") or EMD_PERL_ERROR("rfsGetFileList.pl: Failed to restore STDERR"); #Note: There is no good reason why the above open will fail. Upon failure #there is no need to exit since result will be sent on STDOUT anyways #Extract actual output of this script chomp @scriptResult; foreach $line (@scriptResult) { last if ($line =~ $endToken); print "$line\n" if ($beginTokenFound eq 1); $beginTokenFound=1 if ($line =~ $beginToken); } exit 0; } else { EMD_PERL_ERROR("rfsGetFileList.pl: Failed to redirect STDERR to null device"); } } else { EMD_PERL_ERROR("rfsGetFileList.pl: Failed to save STDERR into STDERR_ORIG"); } } #Defaults if($maxFiles eq '') { $maxFiles = 500; } #Variables my $dirHandle; my @allFiles = (); my $fileSeparator = ""; my @outFileList = (); #For Windows OS: Get available drives, if started from My Computer if (($osCmd eq $windowsOsCmd) && ($dirName eq $winRoot)) { my $line = ""; my $drive = ""; my $driveSize = ""; my $oneRow = ""; my $tokenSeparator = "\t"; my @driveList = (); #Bug 4779290 fix - Following will return all drives, including network drives $ENV{EM_MONITOR_ALL_DISKS} = "TRUE"; my $nmupmOut = `$ENV{EMDROOT}\\bin\\nmupm filesystems`; #print "nmupm drive list = $nmupmOut\n"; #Clean up invalid entries @driveList = cleanUpDriveListNT($nmupmOut); #print "cleaned up drive list = @driveList\n"; #End of bug 4779290 fix for $line (@driveList) { $drive = (split /=/, (split /\|/, $line)[0])[1]; #Hard drive size in KB $driveSize = (split /\|/, $line)[1]*1024; push(@outFileList, join($tokenSeparator, ($drive, $driveSize, "\n"))); } return @outFileList; } #All other Windows directories and all non-Windows directories #Append the directory with separator, if not done already $fileSeparator = getFileSeparator($osCmd); if($dirName !~ /$fileSeparator$/) { $dirName .= $fileSeparator; } #Open the directory for reading if (!opendir(dirHandle, $dirName)) { EMD_PERL_ERROR("[rfsGetFileList.pl] Unable to open the directory $dirName for reading!\n"); exit 1; } #print "searchPattern = $searchPattern\n"; #Escape non-alphanumeric chars, [A-Za-z_0-9] $searchPattern = quotemeta($searchPattern); $searchPattern = interpretPattern($searchPattern); #print "searchPattern = $searchPattern\n"; #Read the directory contents @allFiles = readOpenedDir($dirHandle, $osCmd, $searchPattern); #Check for timeout if($allFiles[0] =~ /Timed out/) { $outFileList[0] = "2\n"; #Close the directory closedir(dirHandle); return @outFileList; } #Get detailed info for each file @outFileList = getFileDetails($osCmd, $dirName, $fetchFileType, $maxFiles, @allFiles); #Close the directory closedir(dirHandle); #print "@allFiles\n"; #print "@outFileList"; return @outFileList; } ############################################# # getFileSeparator() # Get the file separator based on the OS - # / for UNIX flavors and \ for Windows ############################################# sub getFileSeparator($) { my $fileSeparator = "/"; if($_[0] eq $windowsOsCmd) { $fileSeparator = "\\"; } return $fileSeparator; } ############################################# # getPermissions() # Get the file permissions in a UNIX format ############################################# sub getPermissions($) { my @permArr = (); my $permissions = unpack("B32", pack("N", shift)); $permissions =~ s/^0+(?=\d)//; # otherwise we'll get leading zeros #Replace 0 by - $permissions =~ s/0/-/g; #Parse remaining bits @permArr = split //, $permissions; for(my $i=0; $i< @permArr.length; ++$i) { if((($i==0)||($i==3)||($i==6))&&(@permArr[$i]==1)) { @permArr[$i] = 'r'; } if((($i==1)||($i==4)||($i==7))&&(@permArr[$i]==1)) { @permArr[$i] = 'w'; } if((($i==2)||($i==5)||($i==8))&&(@permArr[$i]==1)) { @permArr[$i] = 'x'; } } return join "", @permArr; } ############################################# # readOpenedDir() # Get files from opened directory ############################################# sub readOpenedDir($$$) { my @allFiles = (); my $dirHandle = $_[0]; my $osCmd = $_[1]; my $searchPattern = $_[2]; #Timeout mechanism for UNIX only if($osCmd eq $unixOsCmd) { #UNIX OS #Register to receive alarm $SIG{ALRM} = sub { #Reset alarm alarm 0; #Break die "Timed out"; }; eval { #Activate alarm alarm ($timeout); #Read contents of the directory @allFiles = grep(/$searchPattern/, readdir(dirHandle)); #Reset alarm alarm 0; }; #Opertion timed out! if($@ =~ /Timed out/) { @allFiles = $@; } } else { #Windows OS #Read contents of the directory @allFiles = grep(/$searchPattern/, readdir(dirHandle)); } return @allFiles; } ########################### # getFileDetails() # Get all the file details ########################### sub getFileDetails($$$$\@) { #Input params my $osCmd = $_[0]; my $dirName = $_[1]; my $fetchFileType = $_[2]; my $maxFiles = $_[3]; my ($allFilesRef) = @_[4]; my @allFiles = @{$allFilesRef}; my @outFileList = (); my $oneRow = ""; my $fileCount = 0; my @fileDetails = (); my $tokenSeparator = "\t"; #Table columns my $name = ""; my $permissions = ""; my $owner = ""; my $group = ""; my $size = ""; my $lastModified = ""; for $name (@allFiles) { #Skip directories . and .. next if(($name eq ".") || ($name eq "..")); #Skip based on on fetchFileType if($fetchFileType eq "RFS_DIRS") { #Skip files next if(!(-d $dirName.$name)); } #Get all details about this file @fileDetails = stat($dirName.$name); #Permissions if(-d $dirName.$name) { $permissions = 'd'; } else { $permissions = '-'; } $permissions .= getPermissions($fileDetails[2] & 0777); #Owner if($osCmd eq $unixOsCmd) { #UNIX OS $owner = getpwuid($fileDetails[4]); } else { #Windows OS $owner = $fileDetails[4]; } #Group if($osCmd eq $unixOsCmd) { #UNIX OS $group = getgrgid($fileDetails[5]); } else { #Windows OS $group = $fileDetails[5]; } #Size $size = $fileDetails[7]; #Last modified time (milliseconds) $lastModified = $fileDetails[9]*1000; $oneRow = join($tokenSeparator, ($name, $permissions, $owner, $group, $size, $lastModified, "\n")); #Store for output push(@outFileList, $oneRow); ++$fileCount; #Exit the loop, if maxFiles has been reached last if $fileCount >= $maxFiles; } #Last line always tells whether returning with less than maxFiles if($fileCount >= $maxFiles) { push(@outFileList, "1\n"); } else { push(@outFileList, "0\n"); } return @outFileList; } ############################################################################# #---------------------sub interpretPattern----------------------------------- # # It does following conversions # empty string => .* # \\\* ==> * ## added for rfs # \\\% ==> % # \\\\ ==> \ # \\_ ==> _ # \\[!_] ==> \\[!_] # \* ==> .* ## added for rfs # \% ==> .* # _ ==> . ############################################################################# sub interpretPattern($) { my $pattern1 = shift @_; my $intpString = ""; my @pattern = split("",$pattern1); return ".*" if($pattern1 eq ""); while(@pattern) { my $char1 = shift @pattern; if($char1 eq "_") { $intpString = $intpString."."; #converting _ to . } elsif( $char1 eq "\\") { my $char2 = shift @pattern; if( $char2 eq "%") { $intpString = $intpString.".*"; #converting \% to .* } elsif( $char2 eq "*" ) { $intpString = $intpString.".*"; #converting \* to .* } elsif( $char2 eq "\\" ) { my $char3 = shift @pattern; if( $char3 eq "_" ) { $intpString = $intpString."_"; #converting \\_ to _ } elsif( $char3 eq "\\" ) { my $char4 = shift @pattern; if( $char4 eq "%" ) { $intpString = $intpString."%"; #converting \\\% to % } elsif($char4 eq "*") { $intpString = $intpString."\\*"; #converting \\\* to \* } elsif($char4 eq "\\") { $intpString = $intpString."\\"; #converting \\\\ to \ } else { $intpString = $intpString."\\\\\\$char4"; } } else { $intpString = $intpString."\\\\$char3"; } } else { $intpString = $intpString."\\$char2"; } } else { $intpString = $intpString."$char1"; } } #end while return $intpString; }#end sub ################################################################## # cleanUpDriveListNT() # Clean up invalid entries received from nmupm filesystems command ################################################################## sub cleanUpDriveListNT($) { my $nmupmOut = shift @_; my @nmupmOutArr = split("\n", $nmupmOut); my @driveList = (); my $line = ""; my $tokenSeparator = ""; for $line (@nmupmOutArr) { chomp($line); if($line =~ /em_result/) { push(@driveList, join($tokenSeparator, ($line, "\n"))); } } return @driveList; } #For Windows OS only if ($ARGV[0] eq $windowsOsCmd && defined($ENV{EM_AGENT_COMMONENV_BAT_EXEC})) { my @outFileList = getFileList(); print "@outFileList"; } return 1;