#!/usr/bin/perl
# restore files from a tape created using mdump
#
# usage:	mrestore [options] path path...
#
# Options:
#	-f dev	tape device		default back:/dev/nrst24
#	-e	eject tape when finish	default no eject
#	-l	list contents only
#
# The path should be in the form of host:path. If host is omitted,
# the local host name is assumed
# 
# Multiple path can be given in any order. mrestore will sort the 
# pathes to suite the order 
#
# 
# mrestore uses hostname, rsh, dd, mt, restore. Make sure the path include all directories on
# all systems you want to do backup
# On SunOS 4.1.3, restore is in /usr/etc
# On Linux RedHat 5.1, restore is in /sbin. 
# Add other directory to suite your needs

$ENV{'PATH'} = '/bin:/usr/etc:/sbin:/usr/bin:/usr/ucb';

#default options
$opt_f		= "back:/dev/nrst24";
$opt_i		= 1;
$opt_l		= 0;
$magic		= 	'###mdump###';

chop( $localhost = `hostname` );

$localhost || die "Unable to determine the local host name: $!\n";

# get the options
use Getopt::Std;
&getopts('fedl');

$opt_f =~ s/^$localhost://;
$opt_f =~ s/^localhost://;

# collect path to restore

while( $path = shift @ARGV )
{
	$host = '';
	($host, $path) = split(':',$path) if $path =~ /:/;
	$host || ($host = $localhost);
	$paths{"$host:$path"} = 1;
}

@paths = keys %paths;
$| = 1;
$opt_l || @paths || die "No file or directory to restore\n";


# decide the dump device name and host
($dump_host, $dump_dev) = split(':', $opt_f);
$dump_dev || do { $dump_dev = $dump_host; $dump_host = "localhost"; };
($dump_dev && $dump_host) || die "Please supply dump device using -f option\n";
$dump_host eq $localhost && ($dump_host = 'localhost');

print "Restore device: $dump_dev on $dump_host\n" if $opt_d;

$opt_d && print join("\n\t", 'Restoring:',@paths), "\n";


# decide the mt command
$mt = "mt -f $dump_dev";
$mt = "rsh $dump_host $mt" unless $dump_host eq 'localhost';

# rewind the tape
do_system("$mt rewind");

# decide the dd command to use
$dd = "dd";
$dd = "rsh $dump_host $dd" unless $dump_host eq 'localhost';

# get the configuration information stored at the beginning of the tape

open( DD, " $dd if=$dump_dev|" ) || die "Cannot run $dd: $!\n";
$conf = <DD>;
if( $conf !~ /^$magic/ )
{
	close DD;
	print "The tape may not be a mdump tape\nQuiting\n";
	system("$mt offline");
	exit;
}

@filesys = ();
while(<DD>)
{
	/;/ || next;
	push( @filesys, split(';', $_ ) );
}
close DD;

print join("\n\t", "File systems on the tape:", @filesys), "\n" if ($opt_d || $opt_l);

if($opt_l)
{
	do_system("$mt rewind");
	exit;
}

	
# sort out the order of requests

foreach $p ( @paths )
{
	my($last) = ();
	foreach $fs ( @filesys )
	{
		if( $p =~ /^$fs/ )
		{
			$last && ($fs !~ /^$last/ )  && next;
			# if the last one used is shorter than the current one
			# use the current one
			$order{$last} && delete $order{$last};
			$order{$fs} = $p;
			$last = $fs;
		}
	}

}

if( %order )
{
	print "In the order:\n" if $opt_d;
	$curpos = 1;
	foreach $fs ( @filesys )
	{
		$opt_d && $order{$fs} && print "\t", $order{$fs}, "\n";
	}
}

$curpos = 1;
$fspos  = 1;

$opt_i && ($opt_i = 'i');

foreach $fs ( @filesys )
{
	$order{$fs} || next;
	$move = $fspos - $curpos;
	next if $move < 0;
	print "Restoring from $fs at segment $fspos\n";
	do_system("$mt fsf $move") if $move > 0;
	do_system("restore -f$opt_i $opt_f");
	$curpos = $fspos;
}
continue 
{
	$fspos++;
}

sub do_system {
	my($cmd) = @_;

	print "$cmd ...." if $opt_d;
	my($system) = system($cmd);
	print "successed\n" if $system == 0 && $opt_d;
	print "failed\n" if $system && $opt_d;
}


