#! /usr/local/ARCH/alpha5/bin/perl use strict; use warnings; use Net::FTP; use Getopt::Std; my $CONF=$ENV{"HOME"}."/.fsync.rc"; my $LOGFILE=$ENV{"HOME"}."/.fsync.log"; #print $CONF; #test de la presence du fichier de conf if ( ! -e $CONF ) { open(F,">$CONF") or die "can't create configuration file $CONF: $!\n"; close(F); } # ajout de parametres dans fichier de configuration if ( $#ARGV != -1 ) { my %options=(); if ( ! getopts("au:p:h:d:f:",\%options) ) { ArgError(); } if ( ! defined $options{a} ) { ArgError(); } my $user = $options{u} if defined $options{u}; my $host = $options{h} if defined $options{h}; my $localdir = $options{d} if defined $options{d}; my $passwd = $options{p} if defined $options{p}; my $remotedir = $options{f} if defined $options{f}; # on ecrit la conf dans le fichier open(F,">>$CONF") or die "can't open configuration file $CONF: $!\n"; print F "$user|$passwd|$host|$remotedir|$localdir\n"; close(F); exit(1); } # lancement de la synchronisation entre les repertoires if ( $#ARGV == -1 ) { open(LOG,">>$LOGFILE") or die "can't open log file $LOGFILE: $!\n"; open(F,$CONF) or die "can't open configuration file $CONF: $!\n"; while () { my @local=(); my $user=""; my $passwd=""; my $host=""; my $remotedir=""; my $localdir=""; if ( m/(.*)\|(.*)\|(.*)\|(.*)\|(.*)$/ ) { $user=$1; $passwd=$2; $host=$3; $remotedir=$4; $localdir=$5; @local=getlocal($localdir); print LOG localtime()." Sync ( $localdir )...\n"; } print LOG localtime()." Connect to $host...\n"; # recupere les informations sur les fichiers sur l'hote my @remote=getremote($user,$passwd,$host,$remotedir); # quels sont les fichiers a transferer sur l'hote (absent sur l'hote) my @totransfert=comparedir(\@local,\@remote); # quels sont les fichiers a enlever sur l'hote (absent en local) my @todelete=comparedirrm(\@local,\@remote); # demarrage des modifications print LOG localtime()." User:$user...\n"; print LOG localtime()." Directory:$remotedir...\n"; # a transferer foreach my $transfert (@totransfert) { my $starttime=time(); my $connect = Net::FTP -> new( $host,Debug=>0,Passive=>1,Port=>21 ) or die "$!\n"; $connect->login($user,$passwd) or die "can't connect to host $host : $!\n"; my $rdir=$transfert->{'path'}; $rdir=~s/$localdir/$remotedir/; $connect->cwd($rdir) or die $connect->message; $connect->put($transfert->{'path'}."/".$transfert->{'file'}) or die $connect->message; my $endtime=time(); print LOG localtime()." Put ".$transfert->{'file'}.":".$rdir." (in ".($endtime - $starttime)." seconds)\n"; $connect->quit; } # a enlever foreach my $delete (@todelete) { my $starttime=time(); my $connect = Net::FTP -> new( $host,Debug=>0,Passive=>1,Port=>21 ) or die "$!\n"; $connect->login($user,$passwd) or die "can't connect to host $host : $!\n"; my $rdir= $delete->{'path'}; $connect->cwd($rdir) or die $connect->message; my $endtime=time(); $connect->delete($delete->{'file'}) or die $connect->message; print LOG localtime()." Del ".$delete->{'file'}.":".$rdir." (in ".($endtime - $starttime)." seconds)\n"; $connect->quit; } } close(F); print LOG localtime()." End...\n"; close(LOG); } sub comparedirrm { my ($local,$remote)=@_; my @compare=(); foreach my $e (@$remote) { if ( ! fileisin($local,$e->{'file'}) ) { my %transfert=(); $transfert{'file'}= $e->{'file'}; $transfert{'path'}= $e->{'path'}; push (@compare,\%transfert); } } return (@compare); } sub comparedir { my ($local,$remote)=@_; my @compare=(); foreach my $e (@$local) { if ( ! fileisin($remote,$e->{'file'}) ) { my %transfert=(); $transfert{'file'}=$e->{'file'}; $transfert{'path'}=$e->{'path'}; push (@compare,\%transfert); } elsif ( ! samesize($remote,$e->{'file'},$e->{'size'}) ) { my %transfert=(); $transfert{'file'}=$e->{'file'}; $transfert{'path'}=$e->{'path'}; push (@compare,\%transfert); } } return(@compare); } sub samesize { my ($remote,$file,$size)=@_; my $ret=0; foreach my $e (@$remote) { if ($e->{'file'} eq $file ) { if ( $e->{'size'} != $size ) { return (0); } else { return (1); } } } return ($ret); } sub fileisin { my ($remote,$file)=@_; my $ret=0; foreach my $e (@$remote) { if ($e->{'file'} eq $file ) { return (1); } } return($ret); } sub getremote { my ($user,$passwd,$host,$remotedir)=@_; my @remote=(); my $connect = Net::FTP -> new( $host,Debug=>0,Passive=>1,Port=>21 ) or die "$!\n"; $connect->login($user,$passwd) or die "can't connect to host $host : $!\n"; $connect->cwd($remotedir) or die $connect->message; my @r=$connect->dir; $connect->quit; foreach my $line (@r) { my %file=(); my @res=split(/\s+/,$line); my $name=$res[8]; if ( $#res > 8 ) { for (my $i=9 ;$i<=$#res;$i++) { $name.=" ".$res[$i]; } } if ( $name !~ /^\./ ) { if ( $line !~ /^d/ ) { $file{'size'}=$res[4]; $file{'path'}=$remotedir; $file{'file'}=$name; push (@remote,\%file); } else { my @temp=getremote($user,$passwd,$host,$remotedir."/".$name); @remote = (@remote,@temp); } } } return (@remote); } sub printarrayhash { my (@array)=@_; print $#array."\n"; for my $e (@array) { print $e->{'file'}." ".$e->{'size'}." ".$e->{'path'}."\n"; } } sub getlocal { my ($path)=@_; my @local=(); opendir(D,$path) or die "can't open directory $path : $!\n"; my @node = grep {! /^\./ } readdir(D); foreach ( @node ) { if ( -d $path."/".$_ ) { my @temp=getlocal($path."/".$_); @local = (@local,@temp) ; } else { my %file=(); $file{'file'}=$_; $file{'size'}=-s $path."/".$_; $file{'path'}=$path; push(@local,\%file); } } closedir(D); return(@local); } sub Usage { my $PROG="fsync"; print STDERR "Usage : \nTo add a directory : $PROG -a -u USER -p PASSWD -h REMOTEHOST -d LOCALDIRECTORY -f REMOTEDIRECTORY\n"; print "To verify the synchronisation in your configuration, just launch the program : $PROG\n"; } sub ArgError { print STDERR "Argument Error \n"; Usage(); exit(-1); }