X-Git-Url: http://git.rot13.org/?p=BackupPC.git;a=blobdiff_plain;f=bin%2FBackupPC_tarExtract;h=af9b298bef4b4bf55bcc2138a34e5f19f0c47a07;hp=5c10cace3c48f33f7da59f826b88c93fa752fce5;hb=fda25dc88a63ccac1c80efa2e4994bf0725ca9b7;hpb=ce708288691ba7dd95a8dac7a468bc0e4c1d6588 diff --git a/bin/BackupPC_tarExtract b/bin/BackupPC_tarExtract index 5c10cac..af9b298 100755 --- a/bin/BackupPC_tarExtract +++ b/bin/BackupPC_tarExtract @@ -9,7 +9,7 @@ # Craig Barratt # # COPYRIGHT -# Copyright (C) 2001-2003 Craig Barratt +# Copyright (C) 2001-2007 Craig Barratt # # 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 @@ -27,7 +27,7 @@ # #======================================================================== # -# Version 2.1.0beta0, released 20 Mar 2004. +# Version 3.1.0, released 25 Nov 2007. # # See http://backuppc.sourceforge.net. # @@ -36,6 +36,7 @@ use strict; no utf8; use lib "/usr/local/BackupPC/lib"; +use Encode qw/from_to/; use BackupPC::Lib; use BackupPC::Attrib qw(:all); use BackupPC::FileZIO; @@ -58,11 +59,11 @@ if ( $ARGV[0] !~ /^([\w\.\s-]+)$/ ) { exit(1); } my $client = $1; -if ( $ARGV[1] !~ /^([\w\s\.\/\$-]+)$/ ) { +if ( $ARGV[1] =~ m{(^|/)\.\.(/|$)} ) { print("$0: bad share name '$ARGV[1]'\n"); exit(1); } -my $ShareNameUM = $1; +my $ShareNameUM = $1 if ( $ARGV[1] =~ /(.*)/ ); my $ShareName = $bpc->fileNameEltMangle($ShareNameUM); if ( $ARGV[2] !~ /^(\d+)$/ ) { print("$0: bad compress level '$ARGV[2]'\n"); @@ -101,7 +102,7 @@ $SIG{TTIN} = \&catch_signal; # Copyright 1998 Stephen Zander. All rights reserved. # my $tar_unpack_header - = 'Z100 A8 A8 A8 A12 A12 A8 A1 Z100 A6 A2 Z32 Z32 A8 A8 A155 x12'; + = 'Z100 A8 A8 A8 a12 A12 A8 A1 Z100 A6 A2 Z32 Z32 A8 A8 A155 x12'; my $tar_header_length = 512; my $BufSize = 1048576; # 1MB or 2^20 @@ -115,6 +116,7 @@ my $ExistFileSize = 0; my $ExistFileCompSize = 0; my $TotalFileCnt = 0; my $TotalFileSize = 0; +my $TarReadHdrCnt = 0; sub TarRead { @@ -128,6 +130,7 @@ sub TarRead substr($data, $numBytes, $totBytes - $numBytes), $totBytes - $numBytes); if ( $newBytes <= 0 ) { + return if ( $TarReadHdrCnt == 1 ); # empty tar file ok print("Unexpected end of tar archive (tot = $totBytes," . " num = $numBytes, posn = " . sysseek($fh, 0, 1) . ")\n"); $Abort = 1; @@ -144,6 +147,7 @@ sub TarReadHeader { my($fh) = @_; + $TarReadHdrCnt++; return $1 if ( TarRead($fh, $tar_header_length) =~ /(.*)/s ); return; } @@ -247,8 +251,19 @@ sub TarReadFileInfo $name, $mode, $size, $type) if ( $Conf{XferLogLevel} >= 3 ); $name = $longName if ( defined($longName) ); $linkname = $longLink if ( defined($longLink) ); + + # + # Map client charset encodings to utf8 + # + # printf("File $name (hex: %s)\n", unpack("H*", $name)); + if ( $Conf{ClientCharset} ne "" ) { + from_to($name, $Conf{ClientCharset}, "utf8"); + from_to($linkname, $Conf{ClientCharset}, "utf8"); + } + # printf("File now $name (hex: %s)\n", unpack("H*", $name)); + $name =~ s{^\./+}{}; - $name =~ s{/+$}{}; + $name =~ s{/+\.?$}{}; $name =~ s{//+}{/}g; return { name => $name, @@ -310,6 +325,7 @@ sub TarReadFile # my($nRead); #print("Reading $f->{name}, $f->{size} bytes, type $f->{type}\n"); + pathCreate($dir, "$OutDir/$ShareName/$f->{mangleName}", $f); my $poolWrite = BackupPC::PoolWrite->new($bpc, "$OutDir/$ShareName/$f->{mangleName}", $f->{size}, $Compress); @@ -347,6 +363,7 @@ sub TarReadFile # a plain file. # $f->{size} = length($f->{linkname}); + pathCreate($dir, "$OutDir/$ShareName/$f->{mangleName}", $f); my $poolWrite = BackupPC::PoolWrite->new($bpc, "$OutDir/$ShareName/$f->{mangleName}", $f->{size}, $Compress); @@ -364,6 +381,7 @@ sub TarReadFile # contents. # $f->{size} = length($f->{linkname}); + pathCreate($dir, "$OutDir/$ShareName/$f->{mangleName}", $f); my $poolWrite = BackupPC::PoolWrite->new($bpc, "$OutDir/$ShareName/$f->{mangleName}", $f->{size}, $Compress); @@ -387,6 +405,7 @@ sub TarReadFile } else { $data = "$f->{devmajor},$f->{devminor}"; } + pathCreate($dir, "$OutDir/$ShareName/$f->{mangleName}", $f); my $poolWrite = BackupPC::PoolWrite->new($bpc, "$OutDir/$ShareName/$f->{mangleName}", length($data), $Compress); @@ -423,26 +442,30 @@ sub attributeWrite my $poolWrite = BackupPC::PoolWrite->new($bpc, $fileName, length($data), $Compress); $poolWrite->write(\$data); - processClose($poolWrite, $Attrib{$d}->fileName($d), length($data)); + processClose($poolWrite, $Attrib{$d}->fileName($d), length($data), 1); } delete($Attrib{$d}); } sub processClose { - my($poolWrite, $fileName, $origSize) = @_; + my($poolWrite, $fileName, $origSize, $noStats) = @_; my($exists, $digest, $outSize, $errs) = $poolWrite->close; if ( @$errs ) { print(join("", @$errs)); $Errors += @$errs; } - $TotalFileCnt++; - $TotalFileSize += $origSize; + if ( !$noStats ) { + $TotalFileCnt++; + $TotalFileSize += $origSize; + } if ( $exists ) { - $ExistFileCnt++; - $ExistFileSize += $origSize; - $ExistFileCompSize += $outSize; + if ( !$noStats ) { + $ExistFileCnt++; + $ExistFileSize += $origSize; + $ExistFileCompSize += $outSize; + } } elsif ( $outSize > 0 ) { print(NEW_FILES "$digest $origSize $fileName\n"); } @@ -471,6 +494,36 @@ sub logFileAction $name); } +# +# Create the parent directory of $file if necessary +# +sub pathCreate +{ + my($dir, $fullPath, $f) = @_; + + # + # Get parent directory of each of $dir and $fullPath + # + # print("pathCreate: dir = $dir, fullPath = $fullPath\n"); + $dir =~ s{/([^/]*)$}{}; + my $file = $bpc->fileNameUnmangle($1); + $fullPath =~ s{/[^/]*$}{}; + return if ( -d $fullPath || $file eq "" ); + unlink($fullPath) if ( -e $fullPath ); + mkpath($fullPath, 0, 0777); + $Attrib{$dir} = BackupPC::Attrib->new({ compress => $Compress }) + if ( !defined($Attrib{$dir}) ); + # print("pathCreate: adding file = $file to dir = $dir\n"); + $Attrib{$dir}->set($file, { + type => BPC_FTYPE_DIR, + mode => 0755, + uid => $f->{uid}, + gid => $f->{gid}, + size => 0, + mtime => 0, + }); +} + sub catch_signal { my $sigName = shift;