Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

* various FTP fixes

* added more shell escaping to bin/BackupPC_archiveHost

* updates to FTP conf/config.pl comments

* minor path change to configure.pl
  • Loading branch information...
commit fb14ecbce30175cec1dc6942dbb281ea8efac345 1 parent 0e6be99
cbarratt authored
3  ChangeLog
@@ -75,7 +75,8 @@
75 75
76 76 * Modified bin/BackupPC_archiveHost to shell escape the output file
77 77 name. That allows it to contain spaces and other special characters.
78   - Requested by Toni Van Remortel.
  78 + Requested by Toni Van Remortel. Also updated bin/BackupPC_archiveHost
  79 + to shell escape and check other arguments.
79 80
80 81 * Added $Conf{CmdQueueNice} to specify nice level for command queue
81 82 commands (eg: BackupPC_link and BackupPC_nightly). Suggested by
16 bin/BackupPC_archiveHost
... ... @@ -1,4 +1,4 @@
1   -#!/bin/perl
  1 +#!/usr/bin/perl
2 2 #=============================================================
3 3 #
4 4 # BackupPC_archiveHost: Archive files for a single host
@@ -38,7 +38,7 @@
38 38 #
39 39 #========================================================================
40 40 #
41   -# Version 3.1.0, released 25 Nov 2007.
  41 +# Version 3.2.0beta0, released 29 Mar 2009.
42 42 #
43 43 # See http://backuppc.sourceforge.net.
44 44 #
@@ -77,6 +77,10 @@ die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
77 77 # Make sure the specified programs are executable
78 78 #
79 79 foreach my $prog ( ($tarCreate, $compPath, $splitPath, $parPath) ) {
  80 + if ( $prog =~ /[][;&()<>{}|^\n\r\t *\$\\'"`?]/ ) {
  81 + print("Error: executable path $prog contains suspicious characters\n");
  82 + exit(1);
  83 + }
80 84 next if ( $prog eq "" || -x $prog );
81 85 print("Error: $prog is not an executable program\n");
82 86 exit(1);
@@ -88,6 +92,10 @@ my $mesg = "Writing tar archive for host $host, backup #$bkupNum";
88 92 #
89 93 $share = $bpc->shellEscape($share);
90 94 $host = $bpc->shellEscape($host);
  95 +$bkupNum = $bpc->shellEscape($bkupNum);
  96 +$fileExt = $bpc->shellEscape($fileExt);
  97 +$splitSize = $bpc->shellEscape($splitSize);
  98 +$parfile = $bpc->shellEscape($parfile);
91 99 my $outLocE = $bpc->shellEscape($outLoc);
92 100
93 101 #
@@ -114,7 +122,7 @@ if ( -b $outLoc || -c $outLoc || -f $outLoc ) {
114 122 # Output file is a device or a regular file, so don't use split
115 123 #
116 124 $cmd .= ">> $outLocE";
117   - $mesg .= " to $outLocE";
  125 + $mesg .= " to $outLoc";
118 126 } else {
119 127 mkpath($outLoc) if ( !-d $outLoc );
120 128 if ( !-d $outLoc ) {
@@ -146,7 +154,7 @@ if ( $ret ) {
146 154 # ie: not a tape device).
147 155 #
148 156 if ( -d $outLoc && -x $parPath ) {
149   - if ( $parfile != 0 ) {
  157 + if ( length($parfile) ) {
150 158 print("Running $parPath to create parity files\n");
151 159 my $parCmd = "$parPath c -r$parfile $outLocE/$host.$bkupNum.tar$fileExt.par2 $outLocE/$host.$bkupNum.tar$fileExt*";
152 160 $ret = system($parCmd);
35 conf/config.pl
@@ -717,6 +717,12 @@
717 717 # Users report that for smbclient you should specify a directory
718 718 # followed by "/*", eg: "/proc/*", instead of just "/proc".
719 719 #
  720 +# FTP servers are traversed recursively so excluding directories will
  721 +# also exclude its contents. You can use the wildcard characters "*"
  722 +# and "?" to define files for inclusion and exclusion. Both
  723 +# attributes $Conf{BackupFilesOnly} and $Conf{BackupFilesExclude} can
  724 +# be defined for the same share.
  725 +#
720 726 # If a hash is used, a special key "*" means it applies to all
721 727 # shares that don't have a specific entry.
722 728 #
@@ -1384,12 +1390,33 @@
1384 1390 # (can be overwritten in the per-PC log file)
1385 1391 ##########################################################################
1386 1392 #
1387   -# Name of the host share that is backed up when using FTP. This can be a
  1393 +# Which host directories to backup when using FTP. This can be a
1388 1394 # string or an array of strings if there are multiple shares per host.
1389   -# Examples:
1390 1395 #
1391   -# $Conf{FtpShareName} = 'c'; # backup 'c' share
1392   -# $Conf{FtpShareName} = ['c', 'd']; # backup 'c' and 'd' shares
  1396 +# This value must be specified in one of two ways: either as a
  1397 +# subdirectory of the 'share root' on the server, or as the absolute
  1398 +# path of the directory.
  1399 +#
  1400 +# In the following example, if the directory /home/username is the
  1401 +# root share of the ftp server with the given username, the following
  1402 +# two values will back up the same directory:
  1403 +#
  1404 +# $Conf{FtpShareName} = 'www'; # www directory
  1405 +# $Conf{FtpShareName} = '/home/username/www'; # same directory
  1406 +#
  1407 +# Path resolution is not supported; i.e.; you may not have an ftp
  1408 +# share path defined as '../otheruser' or '~/games'.
  1409 +#
  1410 +# Multiple shares may also be specified, as with other protocols:
  1411 +#
  1412 +# $Conf{FtpShareName} = [ 'www',
  1413 +# 'bin',
  1414 +# 'config' ];
  1415 +#
  1416 +# Note also that you can also use $Conf{BackupFilesOnly} to specify
  1417 +# a specific list of directories to backup. It's more efficient to
  1418 +# use this option instead of $Conf{FtpShareName} since a new tar is
  1419 +# run for each entry in $Conf{FtpShareName}.
1393 1420 #
1394 1421 # This setting only matters if $Conf{XferMethod} = 'ftp'.
1395 1422 #
2  configure.pl
@@ -266,7 +266,7 @@
266 266 foreach my $prog ( sort(keys(%Programs)) ) {
267 267 my $path;
268 268 foreach my $subProg ( split(/\//, $prog) ) {
269   - $path = FindProgram("$ENV{PATH}:/bin:/usr/bin:/sbin:/usr/sbin",
  269 + $path = FindProgram("$ENV{PATH}:/usr/bin:/bin:/sbin:/usr/sbin",
270 270 $subProg) if ( !length($path) );
271 271 }
272 272 $Conf{$Programs{$prog}} = $path if ( !length($Conf{$Programs{$prog}}) );
91 lib/BackupPC/Xfer/Ftp.pm
@@ -168,7 +168,7 @@ sub start
168 168 # Convert the encoding type of the names if at all possible
169 169 #
170 170 from_to( $args->{shareName}, "utf8", $conf->{ClientCharset} )
171   - if ( $conf->{ClientCharset} ne "" );
  171 + if ( $conf->{ClientCharset} ne "" );
172 172
173 173 #
174 174 # Collect FTP configuration arguments and translate them for
@@ -187,7 +187,7 @@ sub start
187 187 : Net::FTP->new(%$args);
188 188 };
189 189 if ($@) {
190   - $t->{_errStr} = "Can't open connection to $args->{Host}: $!";
  190 + $t->{_errStr} = "Can't open connection to $args->{host}: $!";
191 191 $t->{xferErrCnt}++;
192 192 return;
193 193 }
@@ -198,7 +198,7 @@ sub start
198 198 undef $@;
199 199 eval { $t->{ftp}->login( $conf->{FtpUserName}, $conf->{FtpPasswd} ); };
200 200 if ( $@ ) {
201   - $t->{_errStr} = "Can't login to $args->{Host}: $!";
  201 + $t->{_errStr} = "Can't login to $args->{host}: $!";
202 202 $t->{xferErrCnt}++;
203 203 return;
204 204 }
@@ -207,7 +207,7 @@ sub start
207 207 eval { $t->{ftp}->binary(); };
208 208 if ($@) {
209 209 $t->{_errStr} =
210   - "Can't enable binary transfer mode to $args->{Host}: $!";
  210 + "Can't enable binary transfer mode to $args->{host}: $!";
211 211 $t->{xferErrCnt}++;
212 212 return;
213 213 }
@@ -234,18 +234,20 @@ sub start
234 234 # log the beginning of action based on type
235 235 #
236 236 if ( $t->{type} eq 'restore' ) {
237   - $logMsg = "restore started on directory $t->{shareName}";
  237 + $logMsg = "ftp restore for host $t->{host} started on directory "
  238 + . "$t->{shareName}\n";
238 239
239 240 } elsif ( $t->{type} eq 'full' ) {
240   - $logMsg = "full backup started on directory $t->{shareName}";
  241 + $logMsg = "ftp full backup for host $t->{host} started on directory "
  242 + . "$t->{shareName}\n";
241 243
242 244 } elsif ( $t->{type} eq 'incr' ) {
243   -
244 245 $incrDate = $bpc->timeStamp( $t->{incrBaseTime} - 3600, 1 );
245   - $logMsg = "incremental backup started back to $incrDate" .
246   - " (backup #$t->{incrBaseBkupNum}) for directory" . "
247   - $t->{shareName}";
  246 + $logMsg = "ftp incremental backup for $t->{host} started back to "
  247 + . "$incrDate (backup #$t->{incrBaseBkupNum}) for directory "
  248 + . "$t->{shareName}\n";
248 249 }
  250 + $t->logWrite($logMsg, 1);
249 251
250 252 #
251 253 # call the recursive function based on the type of action
@@ -253,17 +255,17 @@ sub start
253 255 if ( $t->{type} eq 'restore' ) {
254 256
255 257 $t->restore();
256   - $logMsg = "Restore of $args->{Host} complete";
  258 + $logMsg = "Restore of $t->{host} complete";
257 259
258 260 } elsif ( $t->{type} eq 'incr' ) {
259 261
260 262 $t->backup();
261   - $logMsg = "Incremental backup of $args->{Host} complete";
  263 + $logMsg = "Incremental backup of $t->{host} complete";
262 264
263 265 } elsif ( $t->{type} eq 'full' ) {
264 266
265 267 $t->backup();
266   - $logMsg = "Full backup of $args->{Host} complete";
  268 + $logMsg = "Full backup of $t->{host} complete";
267 269 }
268 270
269 271 delete $t->{_errStr};
@@ -297,8 +299,8 @@ sub run
297 299 return ( $t->{fileCnt}, $t->{byteCnt}, 0, 0 );
298 300
299 301 } else {
300   - return \( $tarErrs, $nFilesExist, $sizeExist,
301   - $sizeExistCom, $nFilesTotal, $sizeTotal );
  302 + return ( $tarErrs, $nFilesExist, $sizeExist,
  303 + $sizeExistCom, $nFilesTotal, $sizeTotal );
302 304 }
303 305 }
304 306
@@ -587,7 +589,8 @@ sub remotels
587 589 };
588 590
589 591 $f->{utf8name} = $f->{name};
590   - from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" );
  592 + from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" )
  593 + if ( $conf->{ClientCharset} ne "" );
591 594
592 595 $f->{fullName} = "$t->{sharePath}/$path/$f->{name}";
593 596 $f->{fullName} =~ s/\/+/\//g;
@@ -709,7 +712,8 @@ sub handleSymFile
709 712 };
710 713
711 714 $f->{utf8name} = $fSym->{name};
712   - from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" );
  715 + from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" )
  716 + if ( $conf->{ClientCharset} ne "" );
713 717
714 718 $f->{relPath} = $fSym->{relPath};
715 719 $f->{fullName} = "$t->{shareName}/$fSym->{relPath}/$fSym->{name}";
@@ -755,7 +759,7 @@ sub handleDir
755 759 }
756 760 }
757 761
758   - $attrib = BackupPC::Attrib->new( { compress => $t->{Compress} } );
  762 + $attrib = BackupPC::Attrib->new( { compress => $t->{compress} } );
759 763 $remoteDir = $t->remotels( $dir->{relPath} );
760 764
761 765 if ( $t->{type} eq "incr" ) {
@@ -828,7 +832,7 @@ sub handleDir
828 832 my $data = $attrib->writeData();
829 833
830 834 $poolWrite = BackupPC::PoolWrite->new( $bpc, $fileName, length($data),
831   - $t->{Compress} );
  835 + $t->{compress} );
832 836 $poolWrite->write( \$data );
833 837 ( $exists, $digest, $outSize, $errs ) = $poolWrite->close();
834 838
@@ -867,13 +871,12 @@ sub handleFile
867 871 }
868 872
869 873 my $attribInfo = {
870   - type => BPC_FTYPE_FILE,
871   - mode => $f->{mode},
872   - uid => undef, # unsupported
873   - gid => undef, # unsupported
874   - size => $f->{size},
875   - mtime => $f->{mtime},
876   - };
  874 + %$f,
  875 + type => BPC_FTYPE_FILE,
  876 + uid => undef, # unsupported
  877 + gid => undef, # unsupported
  878 + };
  879 + delete $attribInfo->{utf8name}; # unused value
877 880
878 881 #
879 882 # If this is a full backup or the file has changed on the host,
@@ -882,15 +885,15 @@ sub handleFile
882 885 undef $@;
883 886 eval { tie ( *FTP, 'Net::FTP::RetrHandle', $ftp, $f->{fullName} ); };
884 887 if ( !*FTP || $@ ) {
885   - $t->handleFileAction( "fail", $attribInfo );
  888 + $t->logFileAction( "fail", $f->{utf8name}, $attribInfo );
886 889 $t->{xferBadFileCnt}++;
887 890 $stats->{errCnt}++;
888 891 return;
889 892 }
890 893
891   - $poolFile = $OutDir . "/" . $bpc->fileNameMangle( $f->{name} );
892   - $poolWrite = BackupPC::PoolWrite->new( $bpc, $poolFile, $f->{size},
893   - $bpc->{xfer}{compress} );
  894 + $poolFile = $OutDir . "/" . $bpc->fileNameMangle( $f->{name} );
  895 + $poolWrite = BackupPC::PoolWrite->new( $bpc, $poolFile, $f->{size},
  896 + $t->{compress} );
894 897
895 898 $localSize = 0;
896 899
@@ -916,7 +919,7 @@ sub handleFile
916 919 #
917 920 if ( $localSize != $f->{size} ) {
918 921 $t->logFileAction( "fail", $f->{utf8name}, $attribInfo );
919   - unklink($poolFile);
  922 + unlink($poolFile);
920 923 $stats->{xferBadFileCnt}++;
921 924 $stats->{errCnt}++;
922 925 return;
@@ -928,7 +931,12 @@ sub handleFile
928 931 $attrib->set( $f->{utf8name}, $attribInfo );
929 932 $t->logFileAction( $exists ? "pool" : "create",
930 933 $f->{utf8name}, $attribInfo );
931   - print $newFilesFH "$digest $f->{size} $poolFile\n" unless $exists;
  934 +
  935 + my $relPoolFile = $bpc->fileNameEltMangle( $t->{shareName} )
  936 + . "/"
  937 + . $bpc->fileNameMangle($attribInfo->{relPath});
  938 +
  939 + print $newFilesFH "$digest $f->{size} $relPoolFile\n" unless $exists;
932 940
933 941 #
934 942 # Cumulate the stats
@@ -955,12 +963,13 @@ sub incrFileExistCheck
955 963 my $view = $t->{view};
956 964
957 965 my $oldAttribInfo = $view->fileAttrib( $t->{incrBaseBkupNum},
958   - $t->{shareName}, $f->{relPath} );
  966 + $t->{shareName}, "/" . $f->{relPath} );
959 967
960   - #print STDERR "*" x 50 . "\n";
961   - #print STDERR "Old data:\n" . Dumper($oldAttribInfo);
962   - #print STDERR "New data:\n" . Dumper($f);
963   - #print STDERR "$f->{fullName}: $oldAttribInfo->{mtime} ?= $f->{mtime}, $oldAttribInfo->{size} ?= $f->{size}\n";
  968 + ##$t->logWrite( "Old attrib:\n" . Dumper($oldAttribInfo), 1 );
  969 + ##$t->logWrite( "New attrib:\n" . Dumper($f), 1 );
  970 + ##$t->logWrite( sprintf("%s: mtime %d vs %d, size %d vs %d\n", $f->{fullName},
  971 + ## $oldAttribInfo->{mtime}, $f->{mtime},
  972 + ## $oldAttribInfo->{size}, $f->{size}), 1);
964 973
965 974 return ( $oldAttribInfo->{mtime} == $f->{mtime}
966 975 && $oldAttribInfo->{size} == $f->{size} );
@@ -983,9 +992,11 @@ sub logFileAction
983 992 $name = "." if ( $name eq "" );
984 993 $owner = "-/-" if ( $owner eq "/" );
985 994
986   - my $fileAction = sprintf( " %-6s %1s%4o %9s %11.0f %s\n",
987   - $action, $type, $attrib->{mode} & 07777,
988   - $owner, $attrib->{size}, $name );
  995 + my $fileAction = sprintf(
  996 + " %-6s %1s%4o %9s %11.0f %s\n",
  997 + $action, $type, $attrib->{mode} & 07777,
  998 + $owner, $attrib->{size}, $attrib->{relPath}
  999 + );
989 1000
990 1001 return $t->logWrite( $fileAction, 1 );
991 1002 }

0 comments on commit fb14ecb

Please sign in to comment.
Something went wrong with that request. Please try again.