* Support for rsync and rsyncd. Changes to BackupPC_dump and new
[BackupPC.git] / bin / BackupPC_zipCreate
index d51a21f..4fa7f4a 100755 (executable)
 #
 #========================================================================
 #
-# Version 1.5.0, released 2 Aug 2002.
+# Version 1.6.0_CVS, released 10 Dec 2002.
 #
 # See http://backuppc.sourceforge.net.
 #
 #========================================================================
 
 use strict;
-use lib "__INSTALLDIR__/lib";
+use lib "/usr/local/BackupPC/lib";
 use Archive::Zip qw(:ERROR_CODES);
 use File::Path;
 use Getopt::Std;
@@ -67,6 +67,7 @@ use BackupPC::Lib;
 use BackupPC::Attrib qw(:all);
 use BackupPC::FileZIO;
 use BackupPC::Zip::FileMember;
+use BackupPC::View;
 
 die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
 my $TopDir = $bpc->TopDir();
@@ -94,7 +95,6 @@ if ( $opts{n} !~ /^(\d+)$/ ) {
     exit(1);
 }
 my $Num = $opts{n};
-
 $opts{c} = 0 if ( $opts{c} eq "" );
 if ( $opts{c} !~ /^(\d+)$/ ) {
     print(STDERR "$0: invalid compression level '$opts{c}'. 0=none, 9=max\n");
@@ -103,7 +103,7 @@ if ( $opts{c} !~ /^(\d+)$/ ) {
 my $compLevel = $opts{c};
 
 my @Backups = $bpc->BackupInfoRead($Host);
-my($Compress, $Mangle, $CompressF, $MangleF, $NumF, $i);
+my($i);
 my $FileCnt = 0;
 my $ByteCnt = 0;
 my $DirCnt = 0;
@@ -111,22 +111,7 @@ my $SpecialCnt = 0;
 my $ErrorCnt = 0;
 
 for ( $i = 0 ; $i < @Backups ; $i++ ) {
-    if ( !$Backups[$i]{noFill} ) {
-        #
-        # Remember the most recent filled backup
-        #
-        $NumF      = $Backups[$i]{num};
-        $MangleF   = $Backups[$i]{mangle};
-        $CompressF = $Backups[$i]{compress};
-    }
-    next if ( $Backups[$i]{num} != $Num );
-    $Compress = $Backups[$i]{compress};
-    $Mangle   = $Backups[$i]{mangle};
-    if ( !$Backups[$i]{noFill} ) {
-        # no need to back-fill a filled backup
-        $NumF = $MangleF = $CompressF = undef;
-    }
-    last;
+    last if ( $Backups[$i]{num} == $Num );
 }
 if ( $i >= @Backups ) {
     print(STDERR "$0: bad backup number $Num for host $Host\n");
@@ -139,11 +124,7 @@ if ( $opts{s} !~ /^([\w\s\.\/\$-]+)$/ ) {
     print(STDERR "$0: bad share name '$opts{s}'\n");
     exit(1);
 }
-my $ShareNameOrig = $opts{s};
-my $ShareName  = $Mangle  ? $bpc->fileNameEltMangle($ShareNameOrig)
-                          : $ShareNameOrig;
-my $ShareNameF = $MangleF ? $bpc->fileNameEltMangle($ShareNameOrig)
-                          : $ShareNameOrig;
+my $ShareName = $opts{s};
 
 my $BufSize    = 1048576;     # 1MB or 2^20
 my(%UidCache, %GidCache);
@@ -159,38 +140,16 @@ foreach my $dir ( @ARGV ) {
 sub archiveWrite
 {
     my($zipfh, $dir, $zipPathOverride) = @_;
+
+    my $view = BackupPC::View->new($bpc, $Host, \@Backups);
+
     if ( $dir =~ m{(^|/)\.\.(/|$)} || $dir !~ /^(.*)$/ ) {
         print(STDERR "$0: bad directory '$dir'\n");
        $ErrorCnt++;
-        next;
-    }
-    (my $DirOrig  = $1) =~ s{/+$}{};
-    $DirOrig      =~ s{^\.?/+}{};
-    my($Dir, $DirF, $FullPath, $FullPathF);
-    if ( $DirOrig eq "" ) {
-        $Dir = $DirF = "";
-        $FullPath  = "$TopDir/pc/$Host/$Num/$ShareName";
-        $FullPathF = "$TopDir/pc/$Host/$NumF/$ShareNameF"
-                                            if ( defined($NumF) );
-    } else {
-        $Dir       = $Mangle  ? $bpc->fileNameMangle($DirOrig) : $DirOrig;
-        $DirF      = $MangleF ? $bpc->fileNameMangle($DirOrig) : $DirOrig;
-        $FullPath  = "$TopDir/pc/$Host/$Num/$ShareName/$Dir";
-        $FullPathF = "$TopDir/pc/$Host/$NumF/$ShareNameF/$DirF"
-                                            if ( defined($NumF) );
-    }
-    if ( -f $FullPath ) {
-        ZipWriteFile($zipfh, $FullPath, $Mangle, $Compress, $zipPathOverride);
-    } elsif ( -d $FullPath || (defined($NumF) && -d $FullPathF) ) {
-        MergeFind($zipfh, $FullPath, $FullPathF);
-    } elsif ( defined($NumF) && -f $FullPathF ) {
-        ZipWriteFile($zipfh, $FullPathF, $MangleF, $CompressF,
-                                                  $zipPathOverride);
-    } else {
-        print(STDERR "$0: $Host, backup $Num, doesn't have a directory or file"
-                   . " $ShareNameOrig/$DirOrig\n");
-       $ErrorCnt++;
+        return;
     }
+    $view->find($Num, $ShareName, $dir, 0, \&ZipWriteFile,
+                $zipfh, $zipPathOverride);
 }
 
 # Create Zip file
@@ -231,63 +190,11 @@ my $AttrDir;
 
 sub ZipWriteFile
 {
-    my($zipfh, $fullName, $mangle, $compress, $zipPathOverride) = @_;
-    my($tarPath);
+    my($hdr, $zipfh, $zipPathOverride) = @_;
 
-    if ( $fullName =~ m{^\Q$TopDir/pc/$Host/$Num/$ShareName\E(.*)}
-        || (defined($NumF)
-            && $fullName =~ m{^\Q$TopDir/pc/$Host/$NumF/$ShareNameF\E(.*)}) ) {
-        $tarPath = $mangle ? $bpc->fileNameUnmangle($1) : $1;
-    } else {
-        print(STDERR "Unexpected file name from find: $fullName\n");
-        return;
-    }
+    my $tarPath = $hdr->{relPath};
     $tarPath = $zipPathOverride if ( defined($zipPathOverride) );
-    (my $dir = $fullName) =~ s{/([^/]*)$}{};
-    my $fileName = $mangle ? $bpc->fileNameUnmangle($1) : $1;
-    if ( $mangle && $AttrDir ne $dir ) {
-        $AttrDir = $dir;
-       $Attr = BackupPC::Attrib->new({ compress => $compress });
-       if ( -f $Attr->fileName($dir) && !$Attr->read($dir) ) {
-            print(STDERR "Can't read attribute file in $dir\n");
-            $ErrorCnt++;
-           $Attr = undef;
-       }
-    }
-    my $hdr = $Attr->get($fileName) if ( defined($Attr) );
-    if ( !defined($hdr) ) {
-        #
-        # No attributes.  Must be an old style backup.  Reconstruct
-        # what we can.  Painful part is computing the size if compression
-        # is on: only method is to uncompress the file.
-        #
-        my @s = stat($fullName);
-        $hdr = {
-            type  => -d _ ? BPC_FTYPE_DIR : BPC_FTYPE_FILE,
-            mode  => $s[2],
-            uid   => $s[4],
-            gid   => $s[5],
-            size  => -f _ ? $s[7] : 0,
-            mtime => $s[9],
-        };
-        if ( $compress && -f _ ) {
-            #
-            # Compute the correct size by reading the whole file
-            #
-            my $f = BackupPC::FileZIO->open($fullName, 0, $compress);
-            if ( !defined($f) ) {
-                print(STDERR "Unable to open file $fullName\n");
-               $ErrorCnt++;
-                return;
-            }
-            my($data, $size);
-            while ( $f->read(\$data, $BufSize) > 0 ) {
-                $size += length($data);
-            }
-            $f->close;
-            $hdr->{size} = $size;
-        }
-    }
+
     if ( defined($PathRemove)
             && substr($tarPath, 0, length($PathRemove)) eq $PathRemove ) {
         substr($tarPath, 0, length($PathRemove)) = $PathAdd;
@@ -295,6 +202,7 @@ sub ZipWriteFile
     $tarPath = "./" . $tarPath if ( $tarPath !~ /^\.\// );
     $tarPath =~ s{//+}{/}g;
     $hdr->{name} = $tarPath;
+
     my $zipmember; # Container to hold the file/directory to zip.
 
     if ( $hdr->{type} == BPC_FTYPE_DIR ) {
@@ -309,10 +217,10 @@ sub ZipWriteFile
         # Regular file: write the header and file
         #
         $zipmember = BackupPC::Zip::FileMember->newFromFileNamed(
-                                           $fullName,
+                                           $hdr->{fullPath},
                                            $hdr->{name},
                                            $hdr->{size},
-                                           $compress
+                                           $hdr->{compress}
                                    );
        $FileCnt++;
        $ByteCnt += $hdr->{size};
@@ -323,9 +231,9 @@ sub ZipWriteFile
         #
        # Start by reading the contents of the link.
        #
-        my $f = BackupPC::FileZIO->open($fullName, 0, $compress);
+        my $f = BackupPC::FileZIO->open($hdr->{fullPath}, 0, $hdr->{compress});
         if ( !defined($f) ) {
-            print(STDERR "Unable to open file $fullName\n");
+            print(STDERR "Unable to open file $hdr->{fullPath}\n");
             $ErrorCnt++;
            return;
         }
@@ -375,63 +283,3 @@ sub ZipWriteFile
     # Finally Zip the member
     $zipfh->addMember($zipmember);
 }
-
-#
-# Does a recursive find of $dir, filling in from the (filled dump)
-# directory $dirF.  Handles the cases where $dir and $dirF might
-# or might not be mangled etc.
-#
-sub MergeFind
-{
-    my($zipfh, $dir, $dirF) = @_;
-
-    my(@Dir, $fLast);
-    if ( -d $dir ) {
-        ZipWriteFile($zipfh, $dir, $Mangle, $Compress);
-    } elsif ( -d $dirF ) {
-        ZipWriteFile($zipfh, $dirF, $MangleF, $CompressF);
-    }
-    if ( opendir(DIR, $dir) ) {
-        @Dir = readdir(DIR);
-        closedir(DIR);
-    }
-    if ( defined($NumF) && opendir(DIR, $dirF) ) {
-        if ( $Mangle == $MangleF ) {
-            @Dir = (@Dir, readdir(DIR));
-        } else {
-            foreach my $f ( readdir(DIR) ) {
-                if ( $Mangle ) {
-                    push(@Dir, $bpc->fileNameMangle($f));
-                } else {
-                    push(@Dir, $bpc->fileNameUnmangle($f));
-                }
-            }
-        }
-    }
-    foreach my $f ( sort({$a cmp $b} @Dir) ) {
-        next if ( $f eq "." || $f eq ".."
-               || $f eq $fLast || ($Mangle && $f eq "attrib") );
-        $fLast = $f;
-        my($fF) = $f;
-        if ( $Mangle != $MangleF ) {
-            $fF = $Mangle ? $bpc->fileNameUnmangle($f)
-                          : $bpc->fileNameMangle($f);
-        }
-        if ( -e "$dir/$f" ) {
-            if ( -d "$dir/$f" ) {
-                MergeFind($zipfh, "$dir/$f", "$dirF/$fF");
-            } else {
-                ZipWriteFile($zipfh, "$dir/$f", $Mangle, $Compress);
-            }
-        } elsif ( -e "$dirF/$fF" ) {
-            if ( -d "$dirF/$fF" ) {
-                MergeFind($zipfh, "$dir/$f", "$dirF/$fF");
-            } else {
-                ZipWriteFile($zipfh, "$dirF/$fF", $MangleF, $CompressF);
-            }
-        } else {
-            print(STDERR "$0: Botch on $dir, $dirF, $f, $fF\n");
-            $ErrorCnt++;
-        }
-    }
-}