This module can be used to extract the given backup to the local system.
I use this to nightly extract the latest backup's from the backup pool for clients to easily access the last known state.
-- Best regards, N. van IJzendoorn <http://www.engineering-spirit.nl/> Engineering Spirit Angstelkade 2a-1.11, 3631 NA Nieuwersluis The Netherlands tel: (+31)85-2733461 <skype:+31852733461?call>www.engineering-spirit.nl <http://www.engineering-spirit.nl/> skype:engineering-spirit.nl <skype:engineering-spirit.nl?call>
#!/opt/bin/perl #============================================================= -*-perl-*- # # BackupPC_extract: create an uncompressed dump of the backup # # DESCRIPTION # # Usage: BackupPC_extract [options] files/directories... # # Flags: # Required options: # -h host host from which you want to rebuild the directory # -n dumpNum dump number from which the rebuild is created # A negative number means relative to the end (eg -1 # means the most recent dump, -2 2nd most recent etc). # -s shareName share name from which the rebuild # # Other options: # -t print summary totals ## -r pathRemove path prefix that will be replaced with pathAdd ## -p pathAdd new path prefix # -e charset charset for encoding file names (default: cp1252) # # AUTHOR # Nick van IJzendoorn <dipswi...@ownage4u.nl> # Based on Backup_zipCreate by Guillaume Filion <g...@users.sourceforge.net> # Based on Backup_tarCreate by Craig Barratt <cbarr...@users.sourceforge.net> # # COPYRIGHT # Copyright (C) 2002-2009 Craig Barratt and Guillaume Filion # and Nick van IJzendoorn # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, o # (at your option) any later version. # # 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 # #======================================================================== # # # See http://backuppc.sourceforge.net. # #======================================================================== use strict; no utf8; use lib "/opt/local/backuppc/lib"; use File::Path; use Getopt::Std; use Encode qw/from_to/; use IO::Handle; use BackupPC::Lib; use BackupPC::Attrib qw(:all); use BackupPC::FileZIO; use BackupPC::View; die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) ); my $TopDir = $bpc->TopDir(); my $BinDir = $bpc->BinDir(); my %Conf = $bpc->Conf(); my %opts; if ( !getopts("te:h:n:p:r:s:", \%opts) || @ARGV < 1 ) { print STDERR <<EOF; usage: $0 [options] files/directories... Required options: -h host host from which you want to rebuild the directory -n dumpNum dump number from which the rebuild is created A negative number means relative to the end (eg -1 means the most recent dump, -2 2nd most recent etc). -s shareName share name from which the rebuild Other options: -t print summary totals # -r pathRemove path prefix that will be replaced with pathAdd # -p pathAdd new path prefix -e charset charset for encoding file names (default: cp1252) EOF exit(1); } if ( $opts{h} !~ /^([\w\.\s-]+)$/ || $opts{h} =~ m{(^|/)\.\.(/|$)} ) { print(STDERR "$0: bad host name '$opts{h}'\n"); exit(1); } my $Host = $opts{h}; if ( $opts{n} !~ /^(-?\d+)$/ ) { print(STDERR "$0: bad dump number '$opts{n}'\n"); exit(1); } my $Num = $opts{n}; my @Backups = $bpc->BackupInfoRead($Host); my $FileCnt = 0; my $ByteCnt = 0; my $DirCnt = 0; my $SpecialCnt = 0; my $ErrorCnt = 0; my $i; $Num = $Backups[@Backups + $Num]{num} if ( -@Backups <= $Num && $Num < 0 ); for ( $i = 0 ; $i < @Backups ; $i++ ) { last if ( $Backups[$i]{num} == $Num ); } if ( $i >= @Backups ) { print(STDERR "$0: bad backup number $Num for host $Host\n"); exit(1); } my $Charset = "cp1252"; $Charset = $opts{e} if ( $opts{e} ne "" ); my $PathRemove = $1 if ( $opts{r} =~ /(.+)/ ); my $PathAdd = $1 if ( $opts{p} =~ /(.+)/ ); if ( $opts{s} =~ m{(^|/)\.\.(/|$)} ) { print(STDERR "$0: bad share name '$opts{s}'\n"); exit(1); } my $ShareName = $opts{s}; my $BufSize = 1048576; # 1MB or 2^20 my(%UidCache, %GidCache); my $fh = new IO::Handle; $fh->fdopen(fileno(STDOUT),"w"); binmode(STDOUT); foreach my $dir ( @ARGV ) { exportBackup($dir); } sub exportBackup { my($dir, $pathOverride) = @_; my $view = BackupPC::View->new($bpc, $Host, \@Backups); if ( $dir =~ m{(^|/)\.\.(/|$)} || $dir !~ /^(.*)$/ ) { print(STDERR "$0: bad directory '$dir'\n"); $ErrorCnt++; return; } $dir = "/" if ( $dir eq "." ); $view->find($Num, $ShareName, $dir, 0, \&exportFiles, $pathOverride); } # # print out totals if requested # if ( $opts{t} ) { print STDERR "Done: $FileCnt files, $ByteCnt bytes, $DirCnt dirs,", " $SpecialCnt specials ignored, $ErrorCnt errors\n"; } exit(0); ########################################################################### # Subroutines ########################################################################### sub UidLookup { my($uid) = @_; $UidCache{$uid} = (getpwuid($uid))[0] if ( !exists($UidCache{$uid}) ); return $UidCache{$uid}; } sub GidLookup { my($gid) = @_; $GidCache{$gid} = (getgrgid($gid))[0] if ( !exists($GidCache{$gid}) ); return $GidCache{$gid}; } my $Attr; my $AttrDir; sub exportFiles { my($hdr, $pathOverride) = @_; my $tarPath = $hdr->{relPath}; $tarPath = $pathOverride if ( defined($pathOverride) ); if ( defined($PathRemove) && substr($tarPath, 0, length($PathRemove)) eq $PathRemove ) { substr($tarPath, 0, length($PathRemove)) = $PathAdd; } $tarPath = $1 if ( $tarPath =~ m{^\.?/+(.*)} ); $tarPath =~ s{//+}{/}g; $hdr->{name} = $tarPath; return if ( $tarPath eq "." || $tarPath eq "./" || $tarPath eq "" ); if ( $hdr->{type} == BPC_FTYPE_DIR ) { # # Directory: just make a directory # $hdr->{name} .= "/" if ( $hdr->{name} !~ m{/$} ); from_to($hdr->{name}, "utf8", $Charset) if ( $Charset ne "" ); mkdir($hdr->{name}); $DirCnt++; } elsif ( $hdr->{type} == BPC_FTYPE_FILE ) { # # Regular file: open the file and write to the file # from_to($hdr->{name}, "utf8", $Charset) if ( $Charset ne "" ); my $f = BackupPC::FileZIO->open($hdr->{fullPath}, 0, $hdr->{compress}); if (!defined($f)) { print(STDERR "Unable to open file $hdr->{fullPath}\n"); $ErrorCnt++; return; } open(out, ">$hdr->{name}") or return; binmode out; my $data; while ($f->read(\$data, $BufSize) > 0 and print(out $data)) { } $f->close; close(out); $FileCnt++; $ByteCnt += $hdr->{size}; } elsif ( $hdr->{type} == BPC_FTYPE_HARDLINK ) { # # Hardlink file: create a hardlink # link($hdr->{fullPath}, $hdr->{name}); } elsif ( $hdr->{type} == BPC_FTYPE_SYMLINK ) { # # Symlink: create a symlink # symlink($hdr->{fullPath}, $hdr->{name}); $SpecialCnt++; } elsif ( $hdr->{type} == BPC_FTYPE_CHARDEV || $hdr->{type} == BPC_FTYPE_BLOCKDEV || $hdr->{type} == BPC_FTYPE_FIFO ) { # # Don't care... # $SpecialCnt++; } else { print(STDERR "Got unknown type $hdr->{type} for $hdr->{name}\n"); $ErrorCnt++; } my $mtime = $hdr->{mtime}; utime($mtime, $mtime, $hdr->{name}); chmod($hdr->{mode}, $hdr->{name}); chown($hdr->{uid}, $hdr->{gid}, $hdr->{name}); }
------------------------------------------------------------------------------ New Year. New Location. New Benefits. New Data Center in Ashburn, VA. GigeNET is offering a free month of service with a new server in Ashburn. Choose from 2 high performing configs, both with 100TB of bandwidth. Higher redundancy.Lower latency.Increased capacity.Completely compliant. http://p.sf.net/sfu/gigenet
_______________________________________________ BackupPC-devel mailing list BackupPC-devel@lists.sourceforge.net List: https://lists.sourceforge.net/lists/listinfo/backuppc-devel Wiki: http://backuppc.wiki.sourceforge.net Project: http://backuppc.sourceforge.net/