From 2a2b302fd64a263fe37b46f6e926001cbca3e251 Mon Sep 17 00:00:00 2001 From: sgpinkus Date: Tue, 8 Jun 2021 18:58:22 +1000 Subject: [PATCH] Fix regression in 262 (#283) * Remove unused sub add_slashdot_if_root(). * Revert changes from #262 (rm -rf failure case on abnormal termination). Add replacement fix. * Rm redundant backup dest mangling in validate_config_file(). --- rsnapshot-program.pl | 61 ++++++++++---------------------------------- 1 file changed, 13 insertions(+), 48 deletions(-) diff --git a/rsnapshot-program.pl b/rsnapshot-program.pl index ec1adb05..0aacae84 100755 --- a/rsnapshot-program.pl +++ b/rsnapshot-program.pl @@ -1109,7 +1109,7 @@ sub parse_config_file { # remember src/dest my %hash; $hash{'src'} = $src; - $hash{'dest'} = $dest; + $hash{'dest'} = normalize_dest_file_path_part($dest); if (defined($opts_ref)) { $hash{'opts'} = $opts_ref; } @@ -1173,7 +1173,7 @@ sub parse_config_file { } $hash{'script'} = $full_script; - $hash{'dest'} = $dest; + $hash{'dest'} = normalize_dest_file_path_part($dest); $line_syntax_ok = 1; @@ -1677,21 +1677,14 @@ sub validate_config_file { # skip for backup_exec since it uses no destination next if (defined($$bp_ref{'cmd'})); - my $tmp_dest_path = $$bp_ref{'dest'}; - - # normalize multiple slashes, and strip trailing slash - # FIXME: Decide whether to allow an empty destination path, and reject or handle such paths accordingly. - $tmp_dest_path =~ s/\/+/\//g; - $tmp_dest_path =~ s/\/$//; - # backup if (defined($$bp_ref{'src'})) { - push(@backup_dest, $tmp_dest_path); + push(@backup_dest, $$bp_ref{'dest'}); # backup_script } elsif (defined($$bp_ref{'script'})) { - push(@backup_script_dest, $tmp_dest_path); + push(@backup_script_dest, $$bp_ref{'dest'}); } @@ -3051,16 +3044,15 @@ sub remove_trailing_slash { } # accepts string -# returns /. if passed /, returns input otherwise -# this is to work around a bug in some versions of rsync -sub add_slashdot_if_root { - my $str = shift(@_); - - if ($str eq '/') { - return '/.'; - } - - return ($str); +# partially normalizes file path intended to be prefixed with some other path (such as backup dest) +# does not handle symlinks or '..' +sub normalize_dest_file_path_part { + my $str = shift(@_); + # it's not a trailing slash if it's the root filesystem + if ($str eq '/') { return ($str); } + $str =~ s/^\.\/|\/.\/|\.$/\//g; + $str =~ s/\/+/\//g; + return ($str); } # accepts the interval (cmd) to run against @@ -5252,19 +5244,6 @@ sub rm_rf { # make sure we were passed an argument if (!defined($path)) { return (0); } - # added by Matthew Jurgens as part of the fix for rm -rf failing when the path contains ./ - # make sure $path does not contain ./ at the end since this makes rm -rf fail - # however the side effect of doing this is that we also remove the directory so we will have to create it later - # we could have added a * at the end so we had something like rm -rf PATH/* but probably safer not to use the * - $path=~s{/\./?$}{}; - # in order to recreate the directory we will want to take a look at it before we remove it - my $st = lstat("$path"); - if (!defined($st)) { - print_err("Could not lstat(\"$path\")", 2); - return(0); - } - # end addition - # extra bonus safety feature! # confirm that whatever we're deleting must be inside the snapshot_root if (index($path, $config_vars{'snapshot_root'}) != 0) { @@ -5285,20 +5264,6 @@ sub rm_rf { $result = rmtree("$path", 0, 0); } - # added by Matthew Jurgens as part of the fix for rm -rf failing when the path contains ./ - # make sure the directory is still in place - # if you cannot create this directory and this rm is part of a rollback which uses cp -al, then the cp -al will fail shortly after - # MKDIR DEST (AND SET MODE) - if (defined($st)) { - # create the directory - $result = mkdir("$path", $st->mode); - if ( ! $result ) { - print_err("Warning! Could not mkdir(\"$path\", $st->mode);", 2); - return(0); - } - } - # end addition - return ($result); }