diff --git a/lib/BackRest/File.pm b/lib/BackRest/File.pm index 251e2d65a..6d091cfc5 100644 --- a/lib/BackRest/File.pm +++ b/lib/BackRest/File.pm @@ -687,6 +687,123 @@ sub exists return true; } +#################################################################################################################################### +# REMOVE +#################################################################################################################################### +sub remove +{ + my $self = shift; + my $strPathType = shift; + my $strPath = shift; + my $bTemp = shift; + my $bIgnoreMissing = shift; + + # Set defaults + $bIgnoreMissing = defined($bIgnoreMissing) ? $bIgnoreMissing : true; + + # Set operation variables + my $strPathOp = $self->path_get($strPathType, $strPath, $bTemp); + my $bRemoved = true; + + # Set operation and debug strings + my $strOperation = OP_FILE_EXISTS; + my $strDebug = "${strPathType}:${strPathOp}"; + &log(DEBUG, "${strOperation}: ${strDebug}"); + + # Run remotely + if ($self->is_remote($strPathType)) + { + confess &log(ASSERT, "${strDebug}: remote operation not supported"); + } + # Run locally + else + { + if (unlink($strPathOp) != 1) + { + $bRemoved = false; + + my $strError = "${strPathOp} could not be removed: " . $!; + my $iErrorCode = COMMAND_ERR_PATH_READ; + + if (!$self->exists($strPathType, $strPath)) + { + $strError = "${strPathOp} does not exist"; + $iErrorCode = COMMAND_ERR_PATH_MISSING; + } + + if (!($iErrorCode == COMMAND_ERR_PATH_MISSING && $bIgnoreMissing)) + { + if ($strPathType eq PATH_ABSOLUTE) + { + confess &log(ERROR, $strError, $iErrorCode); + } + + confess &log(ERROR, "${strDebug}: " . $strError); + } + } + } + + return $bRemoved; +} + +#################################################################################################################################### +# HASH +#################################################################################################################################### +sub hash +{ + my $self = shift; + my $strPathType = shift; + my $strFile = shift; + my $strHashType = shift; + + # Set operation variables + my $strFileOp = $self->path_get($strPathType, $strFile); + my $strHash; + + # Set operation and debug strings + my $strOperation = OP_FILE_HASH; + my $strDebug = "${strPathType}:${strFileOp}"; + &log(DEBUG, "${strOperation}: ${strDebug}"); + + if ($self->is_remote($strPathType)) + { + confess &log(ASSERT, "${strDebug}: remote operation not supported"); + } + else + { + my $hFile; + + if (!open($hFile, "<", $strFileOp)) + { + my $strError = "${strFileOp} could not be read" . $!; + my $iErrorCode = 2; + + if (!$self->exists($strPathType, $strFile)) + { + $strError = "${strFileOp} does not exist"; + $iErrorCode = 1; + } + + if ($strPathType eq PATH_ABSOLUTE) + { + confess &log(ERROR, $strError, $iErrorCode); + } + + confess &log(ERROR, "${strDebug}: " . $strError); + } + + my $oSHA = Digest::SHA->new(defined($strHashType) ? $strHashType : 'sha1'); + + $oSHA->addfile($hFile); + + close($hFile); + + $strHash = $oSHA->hexdigest(); + } + + return $strHash; +} + #################################################################################################################################### # LIST #################################################################################################################################### @@ -1249,146 +1366,5 @@ sub copy return true; } -#################################################################################################################################### -# HASH -#################################################################################################################################### -sub hash -{ - my $self = shift; - my $strPathType = shift; - my $strFile = shift; - my $strHashType = shift; - - # For now this operation is not supported remotely. Not currently needed. - my $strHash; - my $strErrorPrefix = "File->hash"; - my $bRemote = $self->is_remote($strPathType); - my $strPath = $self->path_get($strPathType, $strFile); - - &log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPath}"); - - if ($bRemote) - { - # Run remotely - my $oSSH = $self->remote_get($strPathType); - my $strOutput = $oSSH->capture($self->{strCommand} . " hash ${strPath}"); - - # Capture any errors - if ($oSSH->error) - { - confess &log(ERROR, "${strErrorPrefix} remote: " . (defined($strOutput) ? $strOutput : $oSSH->error)); - } - - $strHash = $strOutput; - } - else - { - my $hFile; - - if (!open($hFile, "<", $strPath)) - { - my $strError = "${strPath} could not be read" . $!; - my $iErrorCode = 2; - - unless (-e $strPath) - { - $strError = "${strPath} does not exist"; - $iErrorCode = 1; - } - - if ($strPathType eq PATH_ABSOLUTE) - { - print $strError; - exit ($iErrorCode); - } - - confess &log(ERROR, "${strErrorPrefix}: " . $strError); - } - - my $oSHA = Digest::SHA->new(defined($strHashType) ? $strHashType : 'sha1'); - - $oSHA->addfile($hFile); - - close($hFile); - - $strHash = $oSHA->hexdigest(); - } - - return $strHash; -} - -#################################################################################################################################### -# REMOVE -#################################################################################################################################### -sub remove -{ - my $self = shift; - my $strPathType = shift; - my $strPath = shift; - my $bTemp = shift; - my $bIgnoreMissing = shift; - - if (!defined($bIgnoreMissing)) - { - $bIgnoreMissing = true; - } - - # Get the root path for the manifest - my $bRemoved = true; - my $strErrorPrefix = "File->remove"; - my $bRemote = $self->is_remote($strPathType); - my $strPathOp = $self->path_get($strPathType, $strPath, $bTemp); - - &log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPathOp}"); - - # Run remotely - if ($bRemote) - { - # Build the command - my $strCommand = $self->{strCommand} . ($bIgnoreMissing ? " --ignore-missing" : "") . " remove ${strPathOp}"; - - # Run it remotely - my $oSSH = $self->remote_get($strPathType); - my $strOutput = $oSSH->capture($strCommand); - - if ($oSSH->error) - { - confess &log(ERROR, "${strErrorPrefix} remote (${strCommand}): " . (defined($strOutput) ? $strOutput : $oSSH->error)); - } - - $bRemoved = $strOutput eq "Y"; - } - # Run locally - else - { - if (unlink($strPathOp) != 1) - { - $bRemoved = false; - - if (-e $strPathOp || !$bIgnoreMissing) - { - my $strError = "${strPathOp} could not be removed: " . $!; - my $iErrorCode = 2; - - unless (-e $strPathOp) - { - $strError = "${strPathOp} does not exist"; - $iErrorCode = 1; - } - - if ($strPathType eq PATH_ABSOLUTE) - { - print $strError; - exit ($iErrorCode); - } - - confess &log(ERROR, "${strErrorPrefix}: " . $strError); - } - } - } - - return $bRemoved; -} - no Moose; __PACKAGE__->meta->make_immutable; diff --git a/test/lib/BackRestTest/FileTest.pm b/test/lib/BackRestTest/FileTest.pm index a0d7d288e..76f141389 100755 --- a/test/lib/BackRestTest/FileTest.pm +++ b/test/lib/BackRestTest/FileTest.pm @@ -46,7 +46,7 @@ sub BackRestFileTestSetup # Remove the test directory system("rm -rf ${strTestPath}") == 0 or die 'unable to drop test path'; - if (defined($bDropOnly) || !$bDropOnly) + if (!defined($bDropOnly) || !$bDropOnly) { # Create the test directory mkdir($strTestPath, oct("0770")) or confess "Unable to create test directory"; @@ -700,139 +700,191 @@ sub BackRestFileTest #------------------------------------------------------------------------------------------------------------------------------- # Test remove() #------------------------------------------------------------------------------------------------------------------------------- - # if ($strTest eq 'all' || $strTest eq 'remove') - # { - # $iRun = 0; - # - # &log(INFO, "--------------------------------------------------------------------------------"); - # &log(INFO, "Test File->remove()\n"); - # - # for (my $bRemote = 0; $bRemote <= 1; $bRemote++) - # { - # my $strHost = $bRemote ? "127.0.0.1" : undef; - # my $strUser = $bRemote ? "dsteele" : undef; - # - # my $oFile = BackRest::File->new - # ( - # strStanza => $strStanza, - # bNoCompression => true, - # strCommand => ${strCommand}, - # strBackupClusterPath => ${strTestPath}, - # strBackupPath => ${strTestPath}, - # strBackupHost => $bRemote ? $strHost : undef, - # strBackupUser => $bRemote ? $strUser : undef - # ); - # - # # Loop through exists - # for (my $bExists = 0; $bExists <= 1; $bExists++) - # { - # # Loop through temp - # for (my $bTemp = 0; $bTemp <= 1; $bTemp++) - # { - # # Loop through ignore missing - # for (my $bIgnoreMissing = 0; $bIgnoreMissing <= 1; $bIgnoreMissing++) - # { - # $iRun++; - # - # &log(INFO, "run ${iRun} - " . - # "remote ${bRemote}, exists ${bExists}, temp ${bTemp}, ignore missing ${bIgnoreMissing}"); - # - # # Drop the old test directory and create a new one - # system("rm -rf test"); - # system("mkdir test") == 0 or confess "Unable to create test directory"; - # - # my $strFile = "${strTestPath}/test.txt"; - # - # if ($bExists) - # { - # system("echo 'TESTDATA' > ${strFile}" . ($bTemp ? ".backrest.tmp" : "")); - # } - # - # # Execute in eval in case of error - # eval - # { - # if ($oFile->remove(PATH_BACKUP_ABSOLUTE, $strFile, $bTemp, $bIgnoreMissing) != $bExists) - # { - # confess "hash did not match expected"; - # } - # }; - # - # if ($@ && $bExists) - # { - # confess "error raised: " . $@ . "\n"; - # } - # - # if (-e ($strFile . ($bTemp ? ".backrest.tmp" : ""))) - # { - # confess "file still exists"; - # } - # } - # } - # } - # } - # } + if ($strTest eq 'all' || $strTest eq 'remove') + { + $iRun = 0; + + &log(INFO, "--------------------------------------------------------------------------------"); + &log(INFO, "Test File->remove()\n"); + + for (my $bRemote = 0; $bRemote <= 1; $bRemote++) + { + my $oFile = BackRest::File->new + ( + strStanza => $strStanza, + strBackupClusterPath => ${strTestPath}, + strBackupPath => ${strTestPath}, + strRemote => $bRemote ? 'backup' : undef, + oRemote => $bRemote ? $oRemote : undef + ); + + # Loop through exists + for (my $bError = 0; $bError <= 1; $bError++) + { + # Loop through exists + for (my $bExists = 0; $bExists <= 1; $bExists++) + { + # Loop through temp + for (my $bTemp = 0; $bTemp <= 1; $bTemp++) + { + # Loop through ignore missing + for (my $bIgnoreMissing = 0; $bIgnoreMissing <= 1; $bIgnoreMissing++) + { + $iRun++; + + &log(INFO, "run ${iRun} - " . + "remote ${bRemote}, error = $bError, exists ${bExists}, temp ${bTemp} " . + ", ignore missing ${bIgnoreMissing}"); + + # Setup test directory + BackRestFileTestSetup($bError); + + my $strFile = "${strTestPath}/test.txt"; + + if ($bError) + { + $strFile = "${strTestPath}/private/test.txt" + } + elsif (!$bExists) + { + $strFile = "${strTestPath}/private/error.txt" + } + else + { + system("echo 'TESTDATA' > ${strFile}" . ($bTemp ? ".backrest.tmp" : "")); + } + + # Execute in eval in case of error + my $bRemoved; + + eval + { + $bRemoved = $oFile->remove(PATH_BACKUP_ABSOLUTE, $strFile, $bTemp, $bIgnoreMissing); + }; + + if ($@) + { + if ($bError || $bRemote) + { + next; + } + + if (!$bExists && !$bIgnoreMissing) + { + next; + } + + confess "unexpected error raised: " . $@; + } + + if ($bError || $bRemote) + { + confess 'error should have been returned'; + } + + if (!$bRemoved) + { + if (!$bExists && $bIgnoreMissing) + { + next; + } + + confess 'remove returned false, but something should have been removed'; + } + + if (-e ($strFile . ($bTemp ? ".backrest.tmp" : ""))) + { + confess "file still exists"; + } + } + } + } + } + } + } #------------------------------------------------------------------------------------------------------------------------------- # Test hash() #------------------------------------------------------------------------------------------------------------------------------- - # if ($strTest eq 'all' || $strTest eq 'hash') - # { - # $iRun = 0; - # - # &log(INFO, "--------------------------------------------------------------------------------"); - # &log(INFO, "test File->hash()\n"); - # - # for (my $bRemote = 0; $bRemote <= 1; $bRemote++) - # { - # my $oFile = BackRest::File->new - # ( - # strStanza => $strStanza, - # bNoCompression => true, - # strCommand => $strCommand, - # strBackupClusterPath => ${strTestPath}, - # strBackupPath => ${strTestPath}, - # strBackupHost => $bRemote ? $strHost : undef, - # strBackupUser => $bRemote ? $strUser : undef - # ); - # - # # Loop through exists - # for (my $bExists = 0; $bExists <= 1; $bExists++) - # { - # $iRun++; - # - # &log(INFO, "run ${iRun} - " . - # "remote $bRemote, exists $bExists"); - # - # # Drop the old test directory and create a new one - # system("rm -rf test"); - # system("mkdir test") == 0 or confess "Unable to create test directory"; - # - # my $strFile = "${strTestPath}/test.txt"; - # - # if ($bExists) - # { - # system("echo 'TESTDATA' > ${strFile}"); - # } - # - # # Execute in eval in case of error - # eval - # { - # if ($oFile->hash(PATH_BACKUP_ABSOLUTE, $strFile) ne '06364afe79d801433188262478a76d19777ef351') - # { - # confess "incorrect hash returned"; - # } - # }; - # - # if ($@) - # { - # if ($bExists) - # { - # confess "error raised: " . $@ . "\n"; - # } - # } - # } - # } - # } + if ($strTest eq 'all' || $strTest eq 'hash') + { + $iRun = 0; + + &log(INFO, "--------------------------------------------------------------------------------"); + &log(INFO, "test File->hash()\n"); + + for (my $bRemote = 0; $bRemote <= 1; $bRemote++) + { + my $oFile = BackRest::File->new + ( + strStanza => $strStanza, + strBackupClusterPath => ${strTestPath}, + strBackupPath => ${strTestPath}, + strRemote => $bRemote ? 'backup' : undef, + oRemote => $bRemote ? $oRemote : undef + ); + + # Loop through error + for (my $bError = 0; $bError <= 1; $bError++) + { + # Loop through exists + for (my $bExists = 0; $bExists <= 1; $bExists++) + { + $iRun++; + + &log(INFO, "run ${iRun} - " . + "remote $bRemote, error $bError, exists $bExists"); + + # Setup test directory + BackRestFileTestSetup($bError); + + my $strFile = "${strTestPath}/test.txt"; + + if ($bError) + { + $strFile = "${strTestPath}/private/test.txt"; + } + elsif (!$bExists) + { + $strFile = "${strTestPath}/error.txt"; + } + else + { + system("echo 'TESTDATA' > ${strFile}"); + } + + # Execute in eval in case of error + my $strHash; + my $bErrorExpected = !$bExists || $bError || $bRemote; + + eval + { + $strHash = $oFile->hash(PATH_BACKUP_ABSOLUTE, $strFile) + }; + + if ($@) + { + if ($bErrorExpected) + { + next; + } + + confess "unexpected error raised: " . $@; + } + + if ($bErrorExpected) + { + confess "error was expected"; + } + + if ($strHash ne '06364afe79d801433188262478a76d19777ef351') + { + confess 'hashes do not match'; + } + } + } + } + } #------------------------------------------------------------------------------------------------------------------------------- # Test exists() @@ -1096,6 +1148,8 @@ sub BackRestFileTest } } } + + BackRestFileTestSetup(false, true); } 1; \ No newline at end of file