mirror of https://github.com/vitalif/zbackup
175 lines
4.6 KiB
C++
175 lines
4.6 KiB
C++
// Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> and ZBackup contributors, see CONTRIBUTORS
|
|
// Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE
|
|
|
|
#include <stdlib.h>
|
|
#include "../../encrypted_file.hh"
|
|
#include "../../encryption_key.hh"
|
|
#include "../../random.hh"
|
|
#include "../../tmp_mgr.hh"
|
|
#include "../../check.hh"
|
|
#include "../../adler32.hh"
|
|
|
|
char rnd[ 16384 ];
|
|
|
|
Adler32::Value adler( int sz )
|
|
{
|
|
Adler32 a;
|
|
a.add( rnd, sz );
|
|
return a.result();
|
|
}
|
|
|
|
void readAndWrite( EncryptionKey const & key, bool writeBackups,
|
|
bool readBackups, bool readSkips )
|
|
{
|
|
TmpMgr tmpMgr( "/dev/shm" );
|
|
|
|
sptr< TemporaryFile > tempFile = tmpMgr.makeTemporaryFile();
|
|
|
|
int fileSize = rand() % ( sizeof( rnd ) + 1 );
|
|
|
|
fprintf( stderr, "Run with %d bytes, %s%s%s%sfile %s...\n", fileSize,
|
|
key.hasKey() ? "" : "no encryption, ",
|
|
writeBackups ? "write backups, " : "",
|
|
readBackups ? "read backups, " : "",
|
|
readSkips ? "read skips, " : "",
|
|
tempFile->getFileName().c_str() );
|
|
|
|
char iv[ Encryption::IvSize ];
|
|
|
|
Random::genaratePseudo( iv, sizeof( iv ) );
|
|
|
|
// Write
|
|
{
|
|
EncryptedFile::OutputStream out( tempFile->getFileName().c_str(), key, iv );
|
|
|
|
char const * next = rnd;
|
|
|
|
int avail = 0;
|
|
for ( int left = fileSize; left; )
|
|
{
|
|
CHECK( out.ByteCount() == fileSize - left, "Incorrect bytecount in the "
|
|
"middle of writing" );
|
|
void * data;
|
|
CHECK( out.Next( &data, &avail ), "out.Next() returned false" );
|
|
CHECK( avail > 0, "out.Next() returned zero size" );
|
|
|
|
bool doBackup = writeBackups && ( rand() & 1 );
|
|
int backup;
|
|
if ( doBackup )
|
|
{
|
|
backup = rand() % ( avail + 1 );
|
|
// Make sure we don't back up and then need to back up again to finish
|
|
// the write
|
|
if ( avail > left )
|
|
backup = avail - left;
|
|
avail -= backup;
|
|
}
|
|
|
|
int toWrite = avail > left ? left : avail;
|
|
memcpy( data, next, toWrite );
|
|
|
|
if ( doBackup )
|
|
out.BackUp( backup );
|
|
|
|
next += toWrite;
|
|
left -= toWrite;
|
|
avail -= toWrite;
|
|
|
|
if ( !avail && ( rand() & 1 ) )
|
|
{
|
|
CHECK( adler( next - rnd ) == out.getAdler32(),
|
|
"bad adler32 in the middle of writing" );
|
|
}
|
|
}
|
|
|
|
if ( avail || ( rand() & 1 ) )
|
|
out.BackUp( avail );
|
|
|
|
CHECK( out.ByteCount() == fileSize, "Incorrect bytecount after writing" );
|
|
|
|
if ( rand() & 1 )
|
|
{
|
|
CHECK( adler( fileSize ) == out.getAdler32(),
|
|
"bad adler32 of the written file" );
|
|
}
|
|
}
|
|
|
|
// Read back
|
|
{
|
|
EncryptedFile::InputStream in( tempFile->getFileName().c_str(), key, iv );
|
|
|
|
char const * next = rnd;
|
|
|
|
void const * data;
|
|
int avail = 0;
|
|
for ( int left = fileSize; left; )
|
|
{
|
|
if ( readSkips && ( rand() & 1 ) )
|
|
{
|
|
int toSkip = rand() % ( left + 1 );
|
|
in.Skip( toSkip );
|
|
next += toSkip;
|
|
left -= toSkip;
|
|
avail = 0;
|
|
continue;
|
|
}
|
|
|
|
CHECK( in.ByteCount() == fileSize - left, "Incorrect bytecount in the "
|
|
"middle of reading" );
|
|
CHECK( in.Next( &data, &avail ), "file ended while %d were still left",
|
|
left );
|
|
CHECK( avail > 0, "in.Next() returned zero size" );
|
|
|
|
bool doBackup = readBackups && ( rand() & 1 );
|
|
int backup;
|
|
if ( doBackup )
|
|
{
|
|
backup = rand() % ( avail + 1 );
|
|
avail -= backup;
|
|
}
|
|
|
|
int toRead = avail > left ? left : avail;
|
|
|
|
CHECK( memcmp( next, data, toRead ) == 0, "Different bytes read than "
|
|
"expected at offset %d", int( next - rnd ) );
|
|
|
|
if ( doBackup )
|
|
in.BackUp( backup );
|
|
|
|
next += toRead;
|
|
left -= toRead;
|
|
avail -= toRead;
|
|
|
|
if ( !avail && ( rand() & 1 ) )
|
|
{
|
|
CHECK( adler( next - rnd ) == in.getAdler32(),
|
|
"bad adler32 in the middle of the reading" );
|
|
}
|
|
}
|
|
|
|
CHECK( in.ByteCount() == fileSize, "Incorrect bytecount after reading" );
|
|
|
|
CHECK( !avail, "at least %d bytes still available", avail );
|
|
CHECK( !in.Next( &data, &avail ), "file should have ended but resulted in "
|
|
"%d more bytes", avail );
|
|
if ( rand() & 1 )
|
|
{
|
|
CHECK( adler( fileSize ) == in.getAdler32(),
|
|
"bad adler32 of the read file" );
|
|
}
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
Random::genaratePseudo( rnd, sizeof( rnd ) );
|
|
EncryptionKeyInfo keyInfo;
|
|
EncryptionKey::generate( "blah", keyInfo );
|
|
EncryptionKey key( "blah", &keyInfo );
|
|
EncryptionKey noKey( std::string(), NULL );
|
|
|
|
for ( size_t iteration = 100000; iteration--; )
|
|
readAndWrite( ( rand() & 1 ) ? key : noKey, rand() & 1, rand() & 1,
|
|
rand() & 1 );
|
|
}
|