#!/usr/bin/perl -w # # Script used to find symlinks and record their values # before importing the directory into cvs. # After a cvs co is done the relink sub routine # can be run to re-establish the original links # Harry Hoffman use strict; use diagnostics; use File::Find; use File::Basename; use Getopt::Long; use Cwd; use vars qw($opt_h $opt_d $opt_o $opt_f $opt_r); GetOptions('help|usage' => \$opt_h, "directory=s" => \$opt_d, "outfile|write=s" => \$opt_o, 'findlinks' => \$opt_f, 'relink' => \$opt_r ); if ($opt_f && $opt_o) { findlinks(); } elsif ($opt_r && $opt_o) { relink(); } else { usage(); } sub usage { my $name = $0; print << "EOF"; Usage: $name -h Usage: $name --findlinks -d -o Usage: $name --relink -o EOF exit(0); } sub findlinks { # Ok, there has got to be a better way to do this but it solves the # problem of supplying a relative path to the "-d" option. my $rundir = getcwd; chdir "$opt_d" or die "Can't chdir to $opt_d, $!\n"; my $dir = getcwd; open(LINKS, ">$rundir/$opt_o") or die "Can't open LINKS, $!\n"; find sub { return unless -l; my $symlink = readlink "$File::Find::name"; print LINKS "$symlink $File::Find::name\n"; }, "$dir"; close(LINKS) or die "Can't close LINKS, $!\n"; } sub relink { open(LINKS, "$opt_o") or die "Can't open $opt_o, $!\n"; while() { chomp; # We report on proc links but we won't actually relink here # for fear of screwing up a live system. next if /.*proc\/.*/; my($symlink,$file) = split / /; my $pdir = dirname("$file"); # We need to handle absolute, relative, and semi-absolute links. # i.e. /mnt/test /var/test2, /mnt/test test, /mnt/test ../var/test # I don't know if a regexp or a chdir is quicker??? #if ($symlink =~ /^\.\..*|^[^\/].*/) { # chdir("$pdir") or die "Can't chdir to $pdir: $!\n"; #} chdir("$pdir") or die "Can't chdir to $pdir: $!\n"; my $symlink_worked = eval { symlink("$symlink","$file") }; if ($symlink_worked == 0) { print STDOUT "Failed to link $symlink to $file\n"; } } close(LINKS) or die "Can't close $opt_o, $!\n"; }