#!/usr/bin/perl # TP synchronisation de fichiers en perl # # Question 5 # # Antoine Miné # 26/01/2007 # ceci n'a pas changé depuis mirroir4.pl use File::Copy; $doit = 0; foreach (@ARGV) { if ($_ eq "--doit") { $doit = 1; } elsif (!defined($dirB)) { $dirB = $_; } elsif (!defined($dirA)) { $dirA = $_; } else { die "argument $_ en trop"; } } die "utilisation: $0 [--doit] repertoire-courant repertoire-archive" unless defined($dirA) && defined($dirB); # la signature doit maintenant tenir compte des méta-données sub parcours { my $dir = shift; opendir(DIR,"$root/$dir") or return; my @files = readdir(DIR) or return; closedir(DIR); foreach (@files) { next if /^\.\.?$/; next if /^\.etat$/; # on ignore le fichier .etat ! $filename = "$dir/$_"; $fullfilename = "$root/$filename"; if (-d $fullfilename) { parcours($filename); } elsif (-f $fullfilename) { $result = `sha1sum "$fullfilename"`; chomp $result; $result =~ s/ .*$//; # on récupère une partie des informations renvoyées par stat, # et on ignore (undef) le reste ( undef , undef ,$mode, undef, $uid, $gid, undef, undef, $atime, $mtime, undef, undef, undef ) = stat($fullfilename); # signature étendue par les méta-données $result = "$result-$mode-$uid-$gid-$atime-$mtime"; $table{$filename} = $result; } } } # ceci n'a pas changé depuis mirroir4.pl sub sauvegarde { open(ETAT,">$root/.etat") or die "echec d'écriture de $root/.etat ($!)"; for (keys %table) { print ETAT "$table{$_} $_\n"; } close(ETAT); } sub charge { open(ETAT,"$root/.etat") or die "echec de lecture de $root/.etat ($!)"; while () { ($signature,$fichier) = /^([^ ]*) (.*)$/; $table{$fichier} = $signature; } close(ETAT); } $root = $dirA; %table = (); if (-f "$root/.etat") { charge(); } else { parcours("."); } %tableA = %table; $root = $dirB; %table = (); parcours("."); %tableB = %table; for $i (keys %tableB) { next if defined($tableA{$i}) && $tableA{$i} eq $tableB{$i}; $fileA = "$dirA/$i"; $fileB = "$dirB/$i"; print "copie $fileB => $fileA\n"; if ($doit) { # extrait la partie SHA1 de la signature en ignorant les méta-données ($shaA) = $tableA{$i} =~ /([^-]*)-/; ($shaB) = $tableB{$i} =~ /([^-]*)-/; # copie seulement si le SHA1 a changé if ($shaA ne $shaB) { copy($fileB,$fileA) or warn "échec de la copie de $fileB vers $fileA ($!)"; } # (re)lecture des méta-données de $fileB # (on pourrait aussi l'extraire de la signature...) ( undef , undef ,$mode, undef, $uid, $gid, undef, undef, $atime, $mtime, undef, undef, undef ) = stat($fileB); # mise à jour des méta-données de $fileA chmod($mode, $fileA) or warn "échec de modification des droits d'accès de $fileA ($!)"; chown($uid, $gid, $fileA) or warn "échec de modification du propriétaire de $fileA ($!)"; utime($atime, $mtime, $fileA) or warn "échec de modification des dates de $fileA ($!)"; } } # ceci n'a pas changé depuis mirroir4.pl for (keys %tableA) { next if defined($tableB{$_}); $file = "$dirA/$_"; print "détruit $file\n"; if ($doit) { unlink "$file" or warn "échec de la destruction de $file ($!)"; } } if ($doit) { %table = %tableB; $root = $dirA; sauvegarde(); }