#!/usr/bin/perl ######################################################################### # # backup_view.pl # # Description: # This script will copy all checkedout files from local views to a share # on the network that is backed up. This script only runs on Windows. # ######################################################################### use File::Copy; $usage = "Usage:\n" . "\tbackup_view.pl\n" . "\tbackup_view.pl -h[elp]"; # OS that we're executing from $OS = (eval{Win32::IsWinNT();},$@) ? "UNIX" : "NT"; # Get time and date ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); $date = sprintf "%04d%02d%02d%02d%02d\n",1900+$year,$mon+1,$mday,$hour,$min; chomp($date); # Replace this with your location for backup of checkedout files $BACKUP_DIR = "//127.0.0.1/island/pub/backup_view/$date"; if ($OS eq "NT") { $ATRIAHOME = $ENV{"ATRIA_HOME"} || 'C:/ibm/RationalSDLC/ClearCase'; $CT = "$ATRIAHOME/bin/cleartool.exe"; (-x $CT) || die "Cannot find an executable cleartool"; $CT = "\"$CT\""; $HOSTNAME = $ENV{"COMPUTERNAME"}; $REG = "reg"; $MVFS_DRIVE = "M"; } else { $ATRIAHOME = "/opt/rational/clearcase"; $CT = "$ATRIAHOME/bin/cleartool"; (-x $CT) || die "Cannot find an executable cleartool"; $HOSTNAME = `hostname`; } # Process arguments passed into the script while ($_ = shift @ARGV) { if (/^-h/) { print("$usage\n"); exit 0; } if (/^-/) { print("Invalid switch '$_'\n"); exit 1 } else { printf("Invalid argument '$_'\n"); exit 1 } } ################## # FIND LOCAL VIEWS ################## @local_views = `$CT lsview -s -host $HOSTNAME`; ########################################## # DETERMINE IF VIEW IS DYNAMIC OR SNAPSHOT ########################################## # Put list of dynamic and snapshot views into different arrays foreach $_ (@local_views) { chomp $_; @lsview_output = `$CT lsview -l $_`; @view_attributes = grep(/View attributes/,@lsview_output); if ( grep(/snapshot/,@view_attributes) ) { push (@snapshot_views, $_); } else { push (@dynamic_views, $_); } } ##################################################### # SNAP: GET VIEW ROOT FROM REGISTRY AND MATCH TO UUID ##################################################### # Get view root information from registry @workspaces_registry_output = `$REG query HKEY_CURRENT_USER\\Software\\Atria\\ClearCase\\CurrentVersion\\Workspaces`; @workspaces_registry_output_data = grep(/REG_SZ/,@workspaces_registry_output); # Put list of view roots into view_roots array foreach $_ (@workspaces_registry_output_data) { ($junk,$view_root,$junk,$junk) = split(/\s+/,$_); push(@view_roots,$view_root); } # Get the uuid for each view root from view's view.dat file foreach $_ (@view_roots) { @split_view_root = split(/[\\\/]/, $_); $joined_view_root = join("/", @split_view_root); # Use forward slash in path if (-f "$joined_view_root/view.dat") { open (VIEW_DAT_FILE, "$joined_view_root/view.dat") || die "ERROR: could not open the view.dat file"; $view_dat_contents = ; close(VIEW_DAT_FILE); ($junk,$view_uuid) = split(/view_uuid:/,$view_dat_contents); $item = { 'VIEW_ROOT' => $joined_view_root, 'VIEW_UUID' => $view_uuid }; push (@VIEW_ROOT_UUID_LIST, $item); } } ############################################################### # SNAP: DETERMINE SNAPSHOT VIEW ROOT FOR EACH SNAPSHOT VIEW TAG # FIND CHECKOUTS AND COPY FILES TO ANOTHER DIRECTORY ############################################################### foreach $_ (@snapshot_views) { @lsview_output = `$CT lsview -l $_`; ($snap_view_uuid) = grep(/View uuid:/,@lsview_output); chomp($snap_view_uuid); ($junk,$snap_view_uuid) = split(/View uuid:\s+/,$snap_view_uuid); # Convert to same format as in view.dat file (w/o : and . chars) @split_snap_view_uuid = split(/[.:]/,$snap_view_uuid); $snap_view_uuid = join("", @split_snap_view_uuid); foreach $view_root_uuid (@VIEW_ROOT_UUID_LIST) { if ($snap_view_uuid eq $view_root_uuid->{'VIEW_UUID'}) { @dir_list = (); # Find list of directories in view root opendir(DIR, $view_root_uuid->{'VIEW_ROOT'}); while (defined($child = readdir(DIR))) { if ((-d "$view_root_uuid->{'VIEW_ROOT'}/$child") && ($child ne ".") && ($child ne "..")) { push(@dir_list, "$view_root_uuid->{'VIEW_ROOT'}/$child"); } } closedir(DIR); $list_of_dirs = join(" ", @dir_list); chomp($list_of_dirs); $view_root_uuid->{'VIEW_ROOT'} =~ /(.*)[\\\/](.*)/; $view_dir=$1; $view_name=$2; print ("\nProcessing snapshot view: $view_name ...\n"); # Find checkouts @checkouts = `$CT lsco -all -s -cview $list_of_dirs`; # For each checkout, copy the file to the backed up directory foreach $_ (@checkouts) { chomp($_); if (! -d $_) { @split_checkedout_file = split(/[\\\/]/, $_); $joined_checkedout_file = join("/", @split_checkedout_file); $joined_checkedout_file =~ /(.*)[\\\/](.*)/; # $1 is path up to file, $2 is checkedout file ($junk,$path_to_file) = split(/$view_dir/, $1); # $path_to_file is path starting with view root dir rmkdir ("$BACKUP_DIR$path_to_file"); # Recursive mkdir $newfile = "$BACKUP_DIR$path_to_file/$2"; print(" Copying $joined_checkedout_file to $newfile\n"); copy($joined_checkedout_file,$newfile) or die "File cannot be copied."; } } } } } ############################################################### # DYN: FIND CHECKOUTS AND COPY FILES TO THE BACKED UP DIRECTORY ############################################################### foreach $_ (@dynamic_views) { print ("\nProcessing dynamic view: $_ ...\n"); # Find checkouts `$CT mount -a`; `$CT startview $_`; chdir("${MVFS_DRIVE}:/$_"); @checkouts = `$CT lsco -avobs -cview -s`; # For each checkout, copy the file to the backed up directory foreach $_ (@checkouts) { chomp($_); if (! -d $_) { @split_checkedout_file = split(/[\\\/]/, $_); $joined_checkedout_file = join("/", @split_checkedout_file); # Use forward slash in path $joined_checkedout_file =~ /(.*)[\\\/](.*)/; # $1 is path up to file, $2 is checkedout file ($junk,$path_to_file) = split(/${MVFS_DRIVE}:/, $1); # $path_to_file is path without the M: rmkdir ("$BACKUP_DIR$path_to_file"); # Recursive mkdir $newfile = "$BACKUP_DIR$path_to_file/$2"; print(" Copying $joined_checkedout_file to $newfile\n"); copy($joined_checkedout_file,$newfile) or die "File cannot be copied."; } } } ############################ # RECURSIVE MKDIR SUBROUTINE ############################ sub rmkdir { my($tpath) = @_; my($dir, $accum); foreach $dir (split(/\//, $tpath)) { $accum = "$accum$dir/"; if ($dir ne "") { if (! -d "$accum") { mkdir $accum; } } } }