#!/usr/bin/perl
#
# Copyright (c) 2006 Zmanda Inc.  All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
#
# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
#
#

package ZRM::SnapshotCommon;

use strict;
use warnings;
use Getopt::Long;
use File::Basename;
use File::Path;
use File::Spec::Functions;
use File::Temp qw/ :POSIX /;

require Exporter;

use vars qw(@ISA @EXPORT_OK);
our @ISA = qw(Exporter);
our @EXPORT = qw($DF $MOUNT $UMOUNT $SUDO $snap_error $action %opt %config $exitIfRemote &printAndDie &removeExtraSlashesFromPath &getIfLink &getRelativeCopyDir &getFileOwnershipAndPermissions &readConfFile &parseConfFile &getCommonDetails &getInputs &checkIfRemote &initSnapshotPlugin);

$ENV{"PATH"}="/usr/local/bin:/opt/csw/bin:/bin:/usr/bin:/sbin:/usr/sbin";

our $DF="df -PT";
our $MOUNT="mount";
our $UMOUNT="umount";
our $SUDO="sudo";

our $exitIfRemote = 1;
our $action;
our %opt;
our %config;
our $snap_error = 0;

sub printAndDie()
{
	print STDERR "$_[0]\n";
	$snap_error = 1;
	if( $action ne "verify-config" ){
		exit( $snap_error );
	}
}

#$_[0] path from which to remove extra slashes
sub removeExtraSlashesFromPath()
{
        my $dir = $_[0];
	$dir =~ s'//+'/'g;
        return $dir;
}

#Will return the link directory if it is a link
#$_[0] directory path
#$_[1] remaining path
sub getIfLink()
{
	my $rem;
	if( ! defined $_[1] ){
		$rem = "";
	}else{
		$rem = $_[1];
	}
	my $t = $_[0];
	if( $t eq "" || $t eq "/" ){
		$rem = "/".$rem;
		return $rem;
	}
	my $r = readlink($t);
	if( defined $r ){
		if( !($r =~ /^\//) ){
			my $b = dirname($t);
			$r = $b."/".$r;
		}
		$t = $r;
		if( $rem ne "" ){
			$t .= "/".$rem;
		}
		$rem = "";
	}
	my $b = basename( $t );
	my $d = dirname( $t );
	if( $rem ne "" ){
		$rem = $b."/".$rem;
	}else{
		$rem = $b;
	}
	return &getIfLink( $d, $rem );
}

#This function will return the relative path from the mount point
#Not relevant on windows
#$_[0] is full path to db
#$_[1] is mnt pnt
sub getRelativeCopyDir()
{
        my $y = &getIfLink( $_[0] );
        if( !$y ) {
                $y = $_[0];
        }

        $y=~/$_[1]/;

        my $z=$';
        if($z){
                return $z;
        }
}

# $_[0] file/dir
sub getFileOwnershipAndPermissions()
{
        my ($sdev,$sino,$smode,$snlink,$suid,$sgid,$srdev,$ssize,
                        $satime,$smtime,$sctime,$sblksize,$sblocks)
                        = stat( $_[0] );
	return "$smode;$suid;$sgid";
}


# $_[0] file to read
sub readConfFile()
{
	my $fileName = $_[0];
	my $oo = $_[1];
        unless( open( FH, "$fileName" ) ){
                die "Unable to open config file. This should only meant to be in
voked from mysql-zrm\n";
        }
        my @tmparr = <FH>;
        close( FH );
        chomp( @tmparr );
        foreach( @tmparr ){
		if( $_ eq "" ){
			next;
		}
                my @v = split( /=/, $_ );
                my $v1 = shift @v;
                my $v2 = join( "=", @v );
		$oo->{$v1}=$v2;
        }
}

#Read the config file
# This reads the conf file that is prepared by mysql-zrm.
# Please note this does not do any validation of the config file
# pointed to by $ZRM_CONF in the enviornment
sub parseConfFile()
{
	&readConfFile( $ENV{'ZRM_CONF'}, \%config );
	
}

# $_[0] directory name
# $_[1] snapshot name
# $_[2] mnt point
sub getCommonDetails()
{
	#my $tmp = File::Spec->tmpdir();
	my $d = $_[0];
	my $m = $_[2];
	if( $d ne "/" ){
		$d =~ s/\/$//;
	}
	if( $m ne "/" ){
		$m =~ s/\/$//;
	}
	my $link = &getRelativeCopyDir( $d, $m );
	my $perms = &getFileOwnershipAndPermissions( $d );
	#my $str = "snapshot-mount-point=$tmp/$_[1]\n";
	my $str = "snapshot-mount-point=$_[1]\n";
	$str .= "relative-copy-dir=$link;$perms\n";
	return $str;
}

# Parses the command line for all of the snapshot parameters
sub getInputs()
{
	my $ret = GetOptions( \%opt, 
			"action=s",
			"directory=s", 
			"host=s",
			"sname=s",
			"dev=s",
			"device-mount-point=s",
			"fstype=s",
			"size=s",
			"emc-host=s",
			@_
	       		);
	
	if( !defined $opt{"action"} ){
		&printAndDie( "Please input action to be performed using --action option" );
	}
	$action = $opt{"action"};
}

#@_ list of parameters that this plugin is specifically interested in
sub checkIfRemote()
{
	if( !defined $opt{'host'} ){
		return;
	}
	my $confname = $ENV{'ZRM_CONF'}.".rmot";
	open TMP, ">$confname";
	my @data = @_;
	foreach( @data ){
		if( defined $config{$_} ){
			print TMP "$_\n";
		}
	}
	close TMP;
	$ENV{'SNAPSHOT_CONF'} = $confname;
	my $optString = "";
	foreach( keys%opt ){
		if( $_ ne "host" ){
			$optString .= "--$_=$opt{$_} ";
		}
	}
	my $cmd = $config{"copy-plugin"};
	my @params;
	push @params, "--snapshot-command";
	push @params, "--host";
	push @params, $opt{"host"};
	push @params, "--snapshot-parameters";
	push @params, "$optString";
	my $r = system( $cmd, @params );
	unlink( $confname );
	if( $r != 0 ){
		if( !defined $ENV{'ZRM_NO_ERROR'} ){
			&printAndDie( "copy-plugin returned error\n" );		
		}else{
			&printAndDie( "\n" );
		}
	}
	if( $exitIfRemote == 1 ){
		exit(0);
	}
}

# initializes the snapshot plugin and if host is specified 
# executes remotly and exits
sub initSnapshotPlugin()
{
	&getInputs();
	&parseConfFile();
	&checkIfRemote(@_);
}

1;
