mirror of https://github.com/vitalif/zbackup
Initial support for backup exchange
Bundle and index exchange is under development yetmaster
parent
55b9486473
commit
3cee914399
|
@ -1,12 +1,48 @@
|
|||
// Part of ZBackup. Licensed under GNU GPLv2 or later
|
||||
|
||||
#include "storage_info_file.hh"
|
||||
#include "backup_exchanger.hh"
|
||||
#include "dir.hh"
|
||||
#include "debug.hh"
|
||||
|
||||
namespace BackupExchanger {
|
||||
|
||||
BackupExchanger::BackupExchanger( )
|
||||
vector< string > recreateDirectories( string const & src, string const & dst, string const & relaPath )
|
||||
{
|
||||
vector< string > files;
|
||||
|
||||
}
|
||||
Dir::Listing lst ( Dir::addPath( src, relaPath ) );
|
||||
|
||||
Dir::Entry entry;
|
||||
|
||||
while ( lst.getNext( entry ) )
|
||||
{
|
||||
string curRelaPath ( relaPath );
|
||||
if ( curRelaPath.empty() )
|
||||
curRelaPath.assign( entry.getFileName() );
|
||||
else
|
||||
curRelaPath.assign( Dir::addPath( relaPath, entry.getFileName() ) );
|
||||
|
||||
if ( entry.isDir() )
|
||||
{
|
||||
verbosePrintf( "Found directory %s...\n", curRelaPath.c_str() );
|
||||
string srcFullPath ( Dir::addPath( src, curRelaPath ) );
|
||||
string dstFullPath ( Dir::addPath( dst, curRelaPath ) );
|
||||
if ( !Dir::exists( dstFullPath.c_str() ) )
|
||||
{
|
||||
verbosePrintf( "Directory %s not found in destination, creating...\n",
|
||||
curRelaPath.c_str() );
|
||||
Dir::create( dstFullPath.c_str() );
|
||||
}
|
||||
vector< string > subFiles ( recreateDirectories( src, dst, curRelaPath ) );
|
||||
files.insert( files.end(), subFiles.begin(), subFiles.end() );
|
||||
}
|
||||
else
|
||||
{
|
||||
verbosePrintf( "Found file %s...\n", curRelaPath.c_str() );
|
||||
files.push_back( curRelaPath );
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
// Part of ZBackup. Licensed under GNU GPLv2 or later
|
||||
|
||||
#ifndef EXCHANGE_HH_INCLUDED__
|
||||
#define EXCHANGE_HH_INCLUDED__
|
||||
#ifndef BACKUP_EXCHANGER_HH_INCLUDED__
|
||||
#define BACKUP_EXCHANGER_HH_INCLUDED__
|
||||
|
||||
#include <bitset>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace BackupExchanger {
|
||||
|
||||
|
@ -19,6 +20,8 @@ enum {
|
|||
Flags
|
||||
};
|
||||
|
||||
/// Recreate source directory structure in destination
|
||||
vector< string > recreateDirectories( string const & src, string const & dst, string const & relaPath = std::string() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -66,11 +66,12 @@ void ChunkIndex::loadIndex()
|
|||
}
|
||||
|
||||
ChunkIndex::ChunkIndex( EncryptionKey const & key, TmpMgr & tmpMgr,
|
||||
string const & indexPath ):
|
||||
string const & indexPath, bool prohibitChunkIndexLoading ):
|
||||
key( key ), tmpMgr( tmpMgr ), indexPath( indexPath ), storage( 65536, 1 ),
|
||||
lastBundleId( NULL )
|
||||
{
|
||||
loadIndex();
|
||||
if ( !prohibitChunkIndexLoading )
|
||||
loadIndex();
|
||||
}
|
||||
|
||||
Bundle::Id const * ChunkIndex::findChunk( ChunkId::RollingHashPart rollingHash,
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
DEF_EX( Ex, "Chunk index exception", std::exception )
|
||||
DEF_EX( exIncorrectChunkIdSize, "Incorrect chunk id size encountered", Ex )
|
||||
|
||||
ChunkIndex( EncryptionKey const &, TmpMgr &, string const & indexPath );
|
||||
ChunkIndex( EncryptionKey const &, TmpMgr &, string const & indexPath, bool prohibitChunkIndexLoading );
|
||||
|
||||
struct ChunkInfoInterface
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "endian.hh"
|
||||
#include "page_size.hh"
|
||||
#include "random.hh"
|
||||
#include "debug.hh"
|
||||
|
||||
namespace EncryptedFile {
|
||||
|
||||
|
@ -22,6 +23,7 @@ InputStream::InputStream( char const * fileName, EncryptionKey const & key,
|
|||
buffer( std::max( getPageSize(), ( unsigned ) BlockSize * 2 ) ),
|
||||
fill( 0 ), remainder( 0 ), backedUp( false )
|
||||
{
|
||||
dPrintf( "encrypted fileName: %s\n", fileName );
|
||||
if ( key.hasKey() )
|
||||
{
|
||||
memcpy( iv, iv_, sizeof( iv ) );
|
||||
|
|
99
zbackup.cc
99
zbackup.cc
|
@ -24,10 +24,10 @@
|
|||
#include "sptr.hh"
|
||||
#include "storage_info_file.hh"
|
||||
#include "zbackup.hh"
|
||||
#include "backup_exchanger.hh"
|
||||
|
||||
using std::vector;
|
||||
using std::bitset;
|
||||
using std::iterator;
|
||||
|
||||
Paths::Paths( string const & storageDir ): storageDir( storageDir )
|
||||
{
|
||||
|
@ -63,7 +63,17 @@ ZBackupBase::ZBackupBase( string const & storageDir, string const & password ):
|
|||
encryptionkey( password, storageInfo.has_encryption_key() ?
|
||||
&storageInfo.encryption_key() : 0 ),
|
||||
tmpMgr( getTmpPath() ),
|
||||
chunkIndex( encryptionkey, tmpMgr, getIndexPath() )
|
||||
chunkIndex( encryptionkey, tmpMgr, getIndexPath(), false )
|
||||
{
|
||||
}
|
||||
|
||||
ZBackupBase::ZBackupBase( string const & storageDir, string const & password,
|
||||
bool prohibitChunkIndexLoading ):
|
||||
Paths( storageDir ), storageInfo( loadStorageInfo() ),
|
||||
encryptionkey( password, storageInfo.has_encryption_key() ?
|
||||
&storageInfo.encryption_key() : 0 ),
|
||||
tmpMgr( getTmpPath() ),
|
||||
chunkIndex( encryptionkey, tmpMgr, getIndexPath(), prohibitChunkIndexLoading )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -112,10 +122,13 @@ void ZBackupBase::initStorage( string const & storageDir,
|
|||
}
|
||||
|
||||
string ZBackupBase::deriveStorageDirFromBackupsFile( string const &
|
||||
backupsFile )
|
||||
backupsFile, bool allowOutside )
|
||||
{
|
||||
// TODO: handle cases when there's a backup/ folder within the backup/ folder
|
||||
// correctly
|
||||
if ( allowOutside )
|
||||
return Dir::getRealPath( backupsFile );
|
||||
|
||||
string realPath = Dir::getRealPath( Dir::getDirName( backupsFile ) );
|
||||
size_t pos;
|
||||
if ( realPath.size() >= 8 && strcmp( realPath.c_str() + realPath.size() - 8,
|
||||
|
@ -299,12 +312,59 @@ void ZRestore::restoreToStdin( string const & inputFileName )
|
|||
|
||||
ZExchange::ZExchange( string const & srcStorageDir, string const & srcPassword,
|
||||
string const & dstStorageDir, string const & dstPassword,
|
||||
bitset< BackupExchanger::Flags > const & exchange )
|
||||
bool prohibitChunkIndexLoading ):
|
||||
srcZBackupBase( srcStorageDir, srcPassword, prohibitChunkIndexLoading ),
|
||||
dstZBackupBase( dstStorageDir, dstPassword, prohibitChunkIndexLoading )
|
||||
{
|
||||
}
|
||||
|
||||
void ZExchange::exchange()
|
||||
void ZExchange::exchange( string const & srcPath, string const & dstPath,
|
||||
bitset< BackupExchanger::Flags > const & exchange )
|
||||
{
|
||||
if ( exchange.test( BackupExchanger::backups ) )
|
||||
{
|
||||
BackupInfo backupInfo;
|
||||
|
||||
verbosePrintf( "Searching for backups...\n" );
|
||||
vector< string > backups = BackupExchanger::recreateDirectories(
|
||||
srcZBackupBase.getBackupsPath(), dstZBackupBase.getBackupsPath() );
|
||||
|
||||
for ( std::vector< string >::iterator it = backups.begin(); it != backups.end(); ++it )
|
||||
{
|
||||
verbosePrintf( "Processing backup file %s... ", it->c_str() );
|
||||
string outputFileName ( Dir::addPath( dstZBackupBase.getBackupsPath(), *it ) );
|
||||
if ( !File::exists( outputFileName ) )
|
||||
{
|
||||
BackupFile::load( Dir::addPath( srcZBackupBase.getBackupsPath(), *it ), srcZBackupBase.encryptionkey, backupInfo );
|
||||
sptr< TemporaryFile > tmpFile = dstZBackupBase.tmpMgr.makeTemporaryFile();
|
||||
BackupFile::save( tmpFile->getFileName(), dstZBackupBase.encryptionkey, backupInfo );
|
||||
tmpFile->moveOverTo( outputFileName );
|
||||
verbosePrintf( "done.\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
verbosePrintf( "file exists - skipped.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
verbosePrintf( "Backup exchange completed.\n" );
|
||||
}
|
||||
|
||||
if ( exchange.test( BackupExchanger::bundles ) )
|
||||
{
|
||||
verbosePrintf( "Searching for bundles...\n" );
|
||||
verbosePrintf( "NOT IMPLEMENTED!\n" );
|
||||
|
||||
verbosePrintf( "Bundle exchange completed.\n" );
|
||||
}
|
||||
|
||||
if ( exchange.test( BackupExchanger::index ) )
|
||||
{
|
||||
verbosePrintf( "Searching for indicies...\n" );
|
||||
verbosePrintf( "NOT IMPLEMENTED!\n" );
|
||||
|
||||
verbosePrintf( "Index exchange completed.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
DEF_EX( exExchangeWithLessThanTwoKeys, "Specify password flag (--non-encrypted or --password-file)"
|
||||
|
@ -361,7 +421,7 @@ int main( int argc, char *argv[] )
|
|||
exchange.set( BackupExchanger::index );
|
||||
else
|
||||
{
|
||||
fprintf( stderr, "Invalid exchange value specified: %s. "
|
||||
fprintf( stderr, "Invalid exchange value specified: %s\n"
|
||||
"Must be one of the following: backups, bundles, index\n",
|
||||
exchangeValue );
|
||||
return EXIT_FAILURE;
|
||||
|
@ -420,7 +480,11 @@ int main( int argc, char *argv[] )
|
|||
args.push_back( argv[ x ] );
|
||||
}
|
||||
|
||||
if ( args.size() < 1 )
|
||||
if ( args.size() < 1 ||
|
||||
( args.size() == 1 &&
|
||||
( strcmp( args[ 0 ], "-h" ) == 0 || strcmp( args[ 0 ], "--help" ) == 0 )
|
||||
)
|
||||
)
|
||||
{
|
||||
fprintf( stderr,
|
||||
"ZBackup, a versatile deduplicating backup tool, version 1.2\n"
|
||||
|
@ -437,6 +501,7 @@ int main( int argc, char *argv[] )
|
|||
" --cache-size <number> MB (default is %zu)\n"
|
||||
" --exchange [backups|bundles|index] (can be\n"
|
||||
" specified multiple times)\n"
|
||||
" --help|-h show this message\n"
|
||||
" Commands:\n"
|
||||
" init <storage path> - initializes new storage;\n"
|
||||
" backup <backup file name> - performs a backup from stdin;\n"
|
||||
|
@ -518,23 +583,25 @@ int main( int argc, char *argv[] )
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
string src, dst = 0;
|
||||
int src, dst;
|
||||
if ( strcmp( args[ 0 ], "export" ) == 0 )
|
||||
{
|
||||
src = args[ 1 ];
|
||||
dst = args[ 2 ];
|
||||
src = 1;
|
||||
dst = 2;
|
||||
}
|
||||
else
|
||||
if ( strcmp( args[ 0 ], "import" ) == 0 )
|
||||
{
|
||||
src = args[ 2 ];
|
||||
dst = args[ 1 ];
|
||||
src = 2;
|
||||
dst = 1;
|
||||
}
|
||||
dPrintf( "%s src: %s\n", args[ 0 ], args[ src ] );
|
||||
dPrintf( "%s dst: %s\n", args[ 0 ], args[ dst ] );
|
||||
|
||||
ZExchange ze( ZBackup::deriveStorageDirFromBackupsFile( src ), passwords[ 0 ],
|
||||
ZBackup::deriveStorageDirFromBackupsFile( dst ), passwords[ 1 ],
|
||||
exchange );
|
||||
ze.exchange();
|
||||
ZExchange ze( ZBackupBase::deriveStorageDirFromBackupsFile( args[ src ], true ), passwords[ src - 1 ],
|
||||
ZBackupBase::deriveStorageDirFromBackupsFile( args[ dst ], true ), passwords[ dst - 1 ],
|
||||
true );
|
||||
ze.exchange( args[ src ], args[ dst ], exchange );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
14
zbackup.hh
14
zbackup.hh
|
@ -38,7 +38,7 @@ struct Paths
|
|||
string getBackupsPath();
|
||||
};
|
||||
|
||||
class ZBackupBase: protected Paths
|
||||
class ZBackupBase: public Paths
|
||||
{
|
||||
public:
|
||||
DEF_EX( Ex, "ZBackup exception", std::exception )
|
||||
|
@ -54,6 +54,7 @@ public:
|
|||
|
||||
/// Opens the storage
|
||||
ZBackupBase( string const & storageDir, string const & password );
|
||||
ZBackupBase( string const & storageDir, string const & password, bool prohibitChunkIndexLoading );
|
||||
|
||||
/// Creates new storage
|
||||
static void initStorage( string const & storageDir, string const & password,
|
||||
|
@ -61,13 +62,13 @@ public:
|
|||
|
||||
/// For a given file within the backups/ dir in the storage, returns its
|
||||
/// storage dir or throws an exception
|
||||
static string deriveStorageDirFromBackupsFile( string const & backupsFile );
|
||||
static string deriveStorageDirFromBackupsFile( string const & backupsFile, bool allowOutside = false );
|
||||
|
||||
protected:
|
||||
StorageInfo storageInfo;
|
||||
EncryptionKey encryptionkey;
|
||||
TmpMgr tmpMgr;
|
||||
ChunkIndex chunkIndex;
|
||||
protected:
|
||||
|
||||
private:
|
||||
StorageInfo loadStorageInfo();
|
||||
|
@ -99,13 +100,16 @@ public:
|
|||
|
||||
class ZExchange
|
||||
{
|
||||
ZBackupBase srcZBackupBase;
|
||||
ZBackupBase dstZBackupBase;
|
||||
|
||||
public:
|
||||
ZExchange( string const & srcStorageDir, string const & srcPassword,
|
||||
string const & dstStorageDir, string const & dstPassword,
|
||||
bitset< BackupExchanger::Flags > const & exchange );
|
||||
bool prohibitChunkIndexLoading );
|
||||
|
||||
/// Exchanges the data between storages
|
||||
void exchange();
|
||||
void exchange( string const & srcFileName, string const & dstFileName, bitset< BackupExchanger::Flags > const & exchange );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue