diff options
Diffstat (limited to 'lib/backupclient')
-rw-r--r-- | lib/backupclient/BackupClientCryptoKeys.cpp | 52 | ||||
-rw-r--r-- | lib/backupclient/BackupClientCryptoKeys.h | 2 | ||||
-rw-r--r-- | lib/backupclient/BackupClientFileAttributes.cpp | 64 | ||||
-rw-r--r-- | lib/backupclient/BackupClientFileAttributes.h | 8 | ||||
-rw-r--r-- | lib/backupclient/BackupClientRestore.cpp | 289 | ||||
-rw-r--r-- | lib/backupclient/BackupClientRestore.h | 19 | ||||
-rw-r--r-- | lib/backupclient/BackupDaemonConfigVerify.cpp | 97 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFile.cpp | 27 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFile.h | 17 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFileDiff.cpp | 69 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFileEncodeStream.cpp | 69 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFileEncodeStream.h | 10 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFilename.cpp | 32 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFilename.h | 24 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreFilenameClear.cpp | 23 | ||||
-rw-r--r-- | lib/backupclient/BackupStoreObjectDump.cpp | 21 | ||||
-rw-r--r-- | lib/backupclient/RunStatusProvider.h | 29 |
17 files changed, 606 insertions, 246 deletions
diff --git a/lib/backupclient/BackupClientCryptoKeys.cpp b/lib/backupclient/BackupClientCryptoKeys.cpp index 46b77f0a..7a8da7ba 100644 --- a/lib/backupclient/BackupClientCryptoKeys.cpp +++ b/lib/backupclient/BackupClientCryptoKeys.cpp @@ -28,40 +28,58 @@ // Created: 1/12/03 // // -------------------------------------------------------------------------- -void BackupClientCryptoKeys_Setup(const char *KeyMaterialFilename) +void BackupClientCryptoKeys_Setup(const std::string& rKeyMaterialFilename) { // Read in the key material unsigned char KeyMaterial[BACKUPCRYPTOKEYS_FILE_SIZE]; // Open the file - FileStream file(KeyMaterialFilename); + FileStream file(rKeyMaterialFilename); + // Read in data if(!file.ReadFullBuffer(KeyMaterial, BACKUPCRYPTOKEYS_FILE_SIZE, 0)) { THROW_EXCEPTION(BackupStoreException, CouldntLoadClientKeyMaterial) } - // Tell the filename how to encrypt - BackupStoreFilenameClear::SetBlowfishKey(KeyMaterial + BACKUPCRYPTOKEYS_FILENAME_KEY_START, BACKUPCRYPTOKEYS_FILENAME_KEY_LENGTH, - KeyMaterial + BACKUPCRYPTOKEYS_FILENAME_IV_START, BACKUPCRYPTOKEYS_FILENAME_IV_LENGTH); - BackupStoreFilenameClear::SetEncodingMethod(BackupStoreFilename::Encoding_Blowfish); + // Setup keys and encoding method for filename encryption + BackupStoreFilenameClear::SetBlowfishKey( + KeyMaterial + BACKUPCRYPTOKEYS_FILENAME_KEY_START, + BACKUPCRYPTOKEYS_FILENAME_KEY_LENGTH, + KeyMaterial + BACKUPCRYPTOKEYS_FILENAME_IV_START, + BACKUPCRYPTOKEYS_FILENAME_IV_LENGTH); + BackupStoreFilenameClear::SetEncodingMethod( + BackupStoreFilename::Encoding_Blowfish); + + // Setup key for attributes encryption + BackupClientFileAttributes::SetBlowfishKey( + KeyMaterial + BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_START, + BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_LENGTH); + + // Setup secret for attribute hashing + BackupClientFileAttributes::SetAttributeHashSecret( + KeyMaterial + BACKUPCRYPTOKEYS_ATTRIBUTE_HASH_SECRET_START, + BACKUPCRYPTOKEYS_ATTRIBUTE_HASH_SECRET_LENGTH); - // Tell the attributes how to encrypt - BackupClientFileAttributes::SetBlowfishKey(KeyMaterial + BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_START, BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_LENGTH); - // and the secret for hashing - BackupClientFileAttributes::SetAttributeHashSecret(KeyMaterial + BACKUPCRYPTOKEYS_ATTRIBUTE_HASH_SECRET_START, BACKUPCRYPTOKEYS_ATTRIBUTE_HASH_SECRET_LENGTH); + // Setup keys for file data encryption + BackupStoreFile::SetBlowfishKeys( + KeyMaterial + BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_START, + BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_LENGTH, + KeyMaterial + BACKUPCRYPTOKEYS_FILE_BLOCK_ENTRY_KEY_START, + BACKUPCRYPTOKEYS_FILE_BLOCK_ENTRY_KEY_LENGTH); - // Tell the files how to encrypt - BackupStoreFile::SetBlowfishKeys(KeyMaterial + BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_START, BACKUPCRYPTOKEYS_ATTRIBUTES_KEY_LENGTH, - KeyMaterial + BACKUPCRYPTOKEYS_FILE_BLOCK_ENTRY_KEY_START, BACKUPCRYPTOKEYS_FILE_BLOCK_ENTRY_KEY_LENGTH); #ifndef HAVE_OLD_SSL // Use AES where available - BackupStoreFile::SetAESKey(KeyMaterial + BACKUPCRYPTOKEYS_FILE_AES_KEY_START, BACKUPCRYPTOKEYS_FILE_AES_KEY_LENGTH); + BackupStoreFile::SetAESKey( + KeyMaterial + BACKUPCRYPTOKEYS_FILE_AES_KEY_START, + BACKUPCRYPTOKEYS_FILE_AES_KEY_LENGTH); #endif // Wipe the key material from memory - ::memset(KeyMaterial, 0, BACKUPCRYPTOKEYS_FILE_SIZE); + #ifdef _MSC_VER // not defined on MinGW + SecureZeroMemory(KeyMaterial, BACKUPCRYPTOKEYS_FILE_SIZE); + #else + ::memset(KeyMaterial, 0, BACKUPCRYPTOKEYS_FILE_SIZE); + #endif } - - diff --git a/lib/backupclient/BackupClientCryptoKeys.h b/lib/backupclient/BackupClientCryptoKeys.h index 5e3a7df2..f40e2e03 100644 --- a/lib/backupclient/BackupClientCryptoKeys.h +++ b/lib/backupclient/BackupClientCryptoKeys.h @@ -49,7 +49,7 @@ #define BACKUPCRYPTOKEYS_FILE_AES_KEY_LENGTH 32 -void BackupClientCryptoKeys_Setup(const char *KeyMaterialFilename); +void BackupClientCryptoKeys_Setup(const std::string& rKeyMaterialFilename); #endif // BACKUPCLIENTCRYTOKEYS__H diff --git a/lib/backupclient/BackupClientFileAttributes.cpp b/lib/backupclient/BackupClientFileAttributes.cpp index 3ffeb189..bb17d41f 100644 --- a/lib/backupclient/BackupClientFileAttributes.cpp +++ b/lib/backupclient/BackupClientFileAttributes.cpp @@ -15,11 +15,14 @@ #include <sys/types.h> #include <sys/stat.h> -#include <string.h> +#include <errno.h> #include <limits.h> + #include <algorithm> +#include <cstring> #include <new> #include <vector> + #ifdef HAVE_SYS_XATTR_H #include <cerrno> #include <sys/xattr.h> @@ -299,9 +302,11 @@ void BackupClientFileAttributes::ReadAttributes(const char *Filename, bool ZeroM StreamableMemBlock *pnewAttr = 0; try { - struct stat st; - if(::lstat(Filename, &st) != 0) + EMU_STRUCT_STAT st; + if(EMU_LSTAT(Filename, &st) != 0) { + BOX_LOG_SYS_ERROR("Failed to stat file: '" << + Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError) } @@ -390,7 +395,7 @@ void BackupClientFileAttributes::ReadAttributes(const char *Filename, bool ZeroM // Created: 2003/10/07 // // -------------------------------------------------------------------------- -void BackupClientFileAttributes::FillAttributes(StreamableMemBlock &outputBlock, const char *Filename, struct stat &st, bool ZeroModificationTimes) +void BackupClientFileAttributes::FillAttributes(StreamableMemBlock &outputBlock, const char *Filename, EMU_STRUCT_STAT &st, bool ZeroModificationTimes) { outputBlock.ResizeBlock(sizeof(attr_StreamFormat)); attr_StreamFormat *pattr = (attr_StreamFormat*)outputBlock.GetBuffer(); @@ -439,6 +444,7 @@ void BackupClientFileAttributes::FillAttributesLink(StreamableMemBlock &outputBl int linkedToSize = ::readlink(Filename, linkedTo, PATH_MAX); if(linkedToSize == -1) { + BOX_LOG_SYS_ERROR("Failed to readlink '" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError); } @@ -463,7 +469,7 @@ void BackupClientFileAttributes::FillAttributesLink(StreamableMemBlock &outputBl void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBlock, const char *Filename) { #ifdef HAVE_SYS_XATTR_H - int listBufferSize = 1000; + int listBufferSize = 10000; char* list = new char[listBufferSize]; try @@ -529,6 +535,9 @@ void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBloc int valueSize = ::lgetxattr(Filename, attrKey.c_str(), 0, 0); if(valueSize<0) { + BOX_LOG_SYS_ERROR("Failed to get " + "extended attributes size " + "for '" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError); } @@ -544,6 +553,9 @@ void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBloc valueSize = ::lgetxattr(Filename, attrKey.c_str(), buffer+xattrSize, xattrBufferSize-xattrSize); if(valueSize<0) { + BOX_LOG_SYS_ERROR("Failed to get " + "extended attributes for " + "'" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError); } xattrSize += valueSize; @@ -559,9 +571,25 @@ void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBloc outputBlock.ResizeBlock(xattrSize); } - else if(listSize<0 && errno!=EOPNOTSUPP && errno!=EACCES) + else if(listSize<0) { - THROW_EXCEPTION(CommonException, OSFileError); + if(errno == EOPNOTSUPP || errno == EACCES) + { + // fail silently + } + else if(errno == ERANGE) + { + BOX_ERROR("Failed to list extended " + "attributes of '" << Filename << "': " + "buffer too small, not backed up"); + } + else + { + BOX_LOG_SYS_ERROR("Failed to list extended " + "attributes of '" << Filename << "', " + "not backed up"); + THROW_EXCEPTION(CommonException, OSFileError); + } } } catch(...) @@ -638,6 +666,8 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename, ::unlink(Filename); if(::symlink((char*)(pattr + 1), Filename) != 0) { + BOX_LOG_SYS_ERROR("Failed to symlink '" << Filename << + "' to '" << (char*)(pattr + 1) << "'"); THROW_EXCEPTION(CommonException, OSFileError) } #endif @@ -655,12 +685,18 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename, // Not a link, use normal chown if(::chown(Filename, ntohl(pattr->UID), ntohl(pattr->GID)) != 0) { + BOX_LOG_SYS_ERROR("Failed to change " + "owner of file " + "'" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError) } } #else - if(::lchown(Filename, ntohl(pattr->UID), ntohl(pattr->GID)) != 0) // use the version which sets things on symlinks + // use the version which sets things on symlinks + if(::lchown(Filename, ntohl(pattr->UID), ntohl(pattr->GID)) != 0) { + BOX_LOG_SYS_ERROR("Failed to change owner of " + "symbolic link '" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError) } #endif @@ -705,6 +741,8 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename, // Try to apply if(::utimes(Filename, times) != 0) { + BOX_LOG_SYS_ERROR("Failed to change times of " + "file '" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError) } } @@ -715,8 +753,12 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename, } // Apply everything else... (allowable mode flags only) - if(::chmod(Filename, mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX)) != 0) // mode must be done last (think setuid) + // Mode must be done last (think setuid) + if(::chmod(Filename, mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID + | S_ISGID | S_ISVTX)) != 0) { + BOX_LOG_SYS_ERROR("Failed to change permissions of file " + "'" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError) } } @@ -831,6 +873,8 @@ void BackupClientFileAttributes::WriteExtendedAttr(const char *Filename, int xat // FIXME: Warn on EOPNOTSUPP if(::lsetxattr(Filename, key, buffer+xattrOffset, valueSize, 0)!=0 && errno!=EOPNOTSUPP) { + BOX_LOG_SYS_ERROR("Failed to set extended attributes " + "on file '" << Filename << "'"); THROW_EXCEPTION(CommonException, OSFileError); } @@ -993,7 +1037,7 @@ void BackupClientFileAttributes::SetAttributeHashSecret(const void *pSecret, int // Created: 25/4/04 // // -------------------------------------------------------------------------- -uint64_t BackupClientFileAttributes::GenerateAttributeHash(struct stat &st, const std::string &filename, const std::string &leafname) +uint64_t BackupClientFileAttributes::GenerateAttributeHash(EMU_STRUCT_STAT &st, const std::string &filename, const std::string &leafname) { if(sAttributeHashSecretLength == 0) { diff --git a/lib/backupclient/BackupClientFileAttributes.h b/lib/backupclient/BackupClientFileAttributes.h index fa56ff65..b32c14dd 100644 --- a/lib/backupclient/BackupClientFileAttributes.h +++ b/lib/backupclient/BackupClientFileAttributes.h @@ -15,7 +15,7 @@ #include "StreamableMemBlock.h" #include "BoxTime.h" -struct stat; +EMU_STRUCT_STAT; // declaration // -------------------------------------------------------------------------- // @@ -53,11 +53,13 @@ public: static void SetBlowfishKey(const void *pKey, int KeyLength); static void SetAttributeHashSecret(const void *pSecret, int SecretLength); - static uint64_t GenerateAttributeHash(struct stat &st, const std::string &filename, const std::string &leafname); + static uint64_t GenerateAttributeHash(EMU_STRUCT_STAT &st, const std::string &filename, const std::string &leafname); static void FillExtendedAttr(StreamableMemBlock &outputBlock, const char *Filename); private: - static void FillAttributes(StreamableMemBlock &outputBlock, const char *Filename, struct stat &st, bool ZeroModificationTimes); + static void FillAttributes(StreamableMemBlock &outputBlock, + const char *Filename, EMU_STRUCT_STAT &st, + bool ZeroModificationTimes); static void FillAttributesLink(StreamableMemBlock &outputBlock, const char *Filename, struct stat &st); void WriteExtendedAttr(const char *Filename, int xattrOffset) const; diff --git a/lib/backupclient/BackupClientRestore.cpp b/lib/backupclient/BackupClientRestore.cpp index b5a54964..b1c5cd0f 100644 --- a/lib/backupclient/BackupClientRestore.cpp +++ b/lib/backupclient/BackupClientRestore.cpp @@ -193,6 +193,8 @@ typedef struct { bool PrintDots; bool RestoreDeleted; + bool ContinueAfterErrors; + bool ContinuedAfterError; std::string mRestoreResumeInfoFilename; RestoreResumeInfo mResumeInfo; } RestoreParams; @@ -202,20 +204,26 @@ typedef struct // -------------------------------------------------------------------------- // // Function -// Name: BackupClientRestoreDir(BackupProtocolClient &, int64_t, const char *, bool) +// Name: BackupClientRestoreDir(BackupProtocolClient &, +// int64_t, const char *, bool) // Purpose: Restore a directory // Created: 23/11/03 // // -------------------------------------------------------------------------- -static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t DirectoryID, std::string &rLocalDirectoryName, +static int BackupClientRestoreDir(BackupProtocolClient &rConnection, + int64_t DirectoryID, std::string &rLocalDirectoryName, RestoreParams &Params, RestoreResumeInfo &rLevel) { - // If we're resuming... check that we haven't got a next level to look at + // If we're resuming... check that we haven't got a next level to + // look at if(rLevel.mpNextLevel != 0) { // Recurse immediately - std::string localDirname(rLocalDirectoryName + DIRECTORY_SEPARATOR_ASCHAR + rLevel.mNextLevelLocalName); - BackupClientRestoreDir(rConnection, rLevel.mNextLevelID, localDirname, Params, *rLevel.mpNextLevel); + std::string localDirname(rLocalDirectoryName + + DIRECTORY_SEPARATOR_ASCHAR + + rLevel.mNextLevelLocalName); + BackupClientRestoreDir(rConnection, rLevel.mNextLevelID, + localDirname, Params, *rLevel.mpNextLevel); // Add it to the list of done itmes rLevel.mRestoredObjects.insert(rLevel.mNextLevelID); @@ -259,22 +267,23 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir break; case ObjectExists_File: { - // File exists with this name, which is fun. Get rid of it. + // File exists with this name, which is fun. + // Get rid of it. BOX_WARNING("File present with name '" << - rLocalDirectoryName << "', removing " << + rLocalDirectoryName << "', removing " "out of the way of restored directory. " "Use specific restore with ID to " "restore this object."); if(::unlink(rLocalDirectoryName.c_str()) != 0) { - BOX_ERROR("Failed to delete file " << - rLocalDirectoryName << ": " << - strerror(errno)); + BOX_LOG_SYS_ERROR("Failed to delete " + "file '" << + rLocalDirectoryName << "'"); return Restore_UnknownError; } BOX_TRACE("In restore, directory name " - "collision with file " << - rLocalDirectoryName); + "collision with file '" << + rLocalDirectoryName << "'"); } break; case ObjectExists_NoObject: @@ -378,10 +387,17 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir exists == ObjectExists_File) && ::mkdir(rLocalDirectoryName.c_str(), S_IRWXU) != 0) { - BOX_ERROR("Failed to create directory '" << - rLocalDirectoryName << "': " << - strerror(errno)); - return Restore_UnknownError; + BOX_LOG_SYS_ERROR("Failed to create directory '" << + rLocalDirectoryName << "'"); + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } // Save the restore info, in case it's needed later @@ -394,23 +410,39 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir BOX_ERROR("Failed to save resume info file '" << Params.mRestoreResumeInfoFilename << "': " << e.what()); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } catch(...) { BOX_ERROR("Failed to save resume info file '" << Params.mRestoreResumeInfoFilename << "': unknown error"); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } // Fetch the directory listing from the server -- getting a // list of files which is appropriate to the restore type rConnection.QueryListDirectory( - DirectoryID, - Params.RestoreDeleted?(BackupProtocolClientListDirectory::Flags_Deleted):(BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING), - BackupProtocolClientListDirectory::Flags_OldVersion | (Params.RestoreDeleted?(0):(BackupProtocolClientListDirectory::Flags_Deleted)), - true /* want attributes */); + DirectoryID, + Params.RestoreDeleted?(BackupProtocolClientListDirectory::Flags_Deleted):(BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING), + BackupProtocolClientListDirectory::Flags_OldVersion | (Params.RestoreDeleted?(0):(BackupProtocolClientListDirectory::Flags_Deleted)), + true /* want attributes */); // Retrieve the directory from the stream following BackupStoreDirectory dir; @@ -429,13 +461,29 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir { BOX_ERROR("Failed to restore attributes for '" << rLocalDirectoryName << "': " << e.what()); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } catch(...) { BOX_ERROR("Failed to restore attributes for '" << rLocalDirectoryName << "': unknown error"); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } int64_t bytesWrittenSinceLastRestoreInfoSave = 0; @@ -444,35 +492,51 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir { BackupStoreDirectory::Iterator i(dir); BackupStoreDirectory::Entry *en = 0; - while((en = i.Next(BackupStoreDirectory::Entry::Flags_File)) != 0) + while((en = i.Next(BackupStoreDirectory::Entry::Flags_File)) + != 0) { // Check ID hasn't already been done - if(rLevel.mRestoredObjects.find(en->GetObjectID()) == rLevel.mRestoredObjects.end()) + if(rLevel.mRestoredObjects.find(en->GetObjectID()) + == rLevel.mRestoredObjects.end()) { // Local name BackupStoreFilenameClear nm(en->GetName()); - std::string localFilename(rLocalDirectoryName + DIRECTORY_SEPARATOR_ASCHAR + nm.GetClearFilename()); + std::string localFilename(rLocalDirectoryName + + DIRECTORY_SEPARATOR_ASCHAR + + nm.GetClearFilename()); // Unlink anything which already exists: // For resuming restores, we can't overwrite // files already there. - if(ObjectExists(localFilename) != ObjectExists_NoObject && + if(ObjectExists(localFilename) + != ObjectExists_NoObject && ::unlink(localFilename.c_str()) != 0) { - BOX_ERROR("Failed to delete file '" << - localFilename << "': " << - strerror(errno)); - return Restore_UnknownError; + BOX_LOG_SYS_ERROR("Failed to delete " + "file '" << localFilename << + "'"); + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } // Request it from the store - rConnection.QueryGetFile(DirectoryID, en->GetObjectID()); + rConnection.QueryGetFile(DirectoryID, + en->GetObjectID()); // Stream containing encoded file - std::auto_ptr<IOStream> objectStream(rConnection.ReceiveStream()); + std::auto_ptr<IOStream> objectStream( + rConnection.ReceiveStream()); - // Decode the file -- need to do different things depending on whether - // the directory entry has additional attributes + // Decode the file -- need to do different + // things depending on whether the directory + // entry has additional attributes try { if(en->HasAttributes()) @@ -493,14 +557,30 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir BOX_ERROR("Failed to restore file '" << localFilename << "': " << e.what()); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } catch(...) { BOX_ERROR("Failed to restore file '" << localFilename << "': unknown error"); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } // Progress display? @@ -515,7 +595,7 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir // Save restore info? int64_t fileSize; - int exists; + bool exists = false; try { @@ -531,7 +611,15 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir "whether file exists: '" << localFilename << "': " << e.what()); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } catch(...) { @@ -539,17 +627,27 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir "whether file exists: '" << localFilename << "': " "unknown error"); - return Restore_UnknownError; + + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } if(exists) { // File exists... - bytesWrittenSinceLastRestoreInfoSave += fileSize; + bytesWrittenSinceLastRestoreInfoSave + += fileSize; if(bytesWrittenSinceLastRestoreInfoSave > MAX_BYTES_WRITTEN_BETWEEN_RESTORE_INFO_SAVES) { - // Save the restore info, in case it's needed later + // Save the restore info, in + // case it's needed later try { Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename); @@ -590,14 +688,28 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir BOX_ERROR("Failed to save resume info file '" << Params.mRestoreResumeInfoFilename << "': " << e.what()); - return Restore_UnknownError; + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } catch(...) { BOX_ERROR("Failed to save resume info file '" << Params.mRestoreResumeInfoFilename << "': unknown error"); - return Restore_UnknownError; + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } bytesWrittenSinceLastRestoreInfoSave = 0; @@ -608,17 +720,23 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir { BackupStoreDirectory::Iterator i(dir); BackupStoreDirectory::Entry *en = 0; - while((en = i.Next(BackupStoreDirectory::Entry::Flags_Dir)) != 0) + while((en = i.Next(BackupStoreDirectory::Entry::Flags_Dir)) + != 0) { // Check ID hasn't already been done - if(rLevel.mRestoredObjects.find(en->GetObjectID()) == rLevel.mRestoredObjects.end()) + if(rLevel.mRestoredObjects.find(en->GetObjectID()) + == rLevel.mRestoredObjects.end()) { // Local name BackupStoreFilenameClear nm(en->GetName()); - std::string localDirname(rLocalDirectoryName + DIRECTORY_SEPARATOR_ASCHAR + nm.GetClearFilename()); + std::string localDirname(rLocalDirectoryName + + DIRECTORY_SEPARATOR_ASCHAR + + nm.GetClearFilename()); // Add the level for the next entry - RestoreResumeInfo &rnextLevel(rLevel.AddLevel(en->GetObjectID(), nm.GetClearFilename())); + RestoreResumeInfo &rnextLevel( + rLevel.AddLevel(en->GetObjectID(), + nm.GetClearFilename())); // Recurse int result = BackupClientRestoreDir( @@ -648,13 +766,27 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir { BOX_ERROR("Failed to restore attributes for '" << rLocalDirectoryName << "': " << e.what()); - return Restore_UnknownError; + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } catch(...) { BOX_ERROR("Failed to restore attributes for '" << rLocalDirectoryName << "': unknown error"); - return Restore_UnknownError; + if (Params.ContinueAfterErrors) + { + Params.ContinuedAfterError = true; + } + else + { + return Restore_UnknownError; + } } return Restore_Complete; @@ -664,33 +796,45 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Dir // -------------------------------------------------------------------------- // // Function -// Name: BackupClientRestore(BackupProtocolClient &, int64_t, const char *, bool, bool) -// Purpose: Restore a directory on the server to a local directory on the disc. -// -// The local directory must not already exist. +// Name: BackupClientRestore(BackupProtocolClient &, int64_t, +// const char *, bool, bool, bool, bool, bool) +// Purpose: Restore a directory on the server to a local +// directory on the disc. The local directory must not +// already exist. // -// If a restore is aborted for any reason, then it may be resumed if -// Resume == true. If Resume == false and resumption is possible, then -// Restore_ResumePossible is returned. +// If a restore is aborted for any reason, then it may +// be resumed if Resume == true. If Resume == false +// and resumption is possible, then +// Restore_ResumePossible is returned. // -// Set RestoreDeleted to restore a deleted directory. This may not give the -// directory structure when it was deleted, because files may have been deleted -// within it before it was deleted. +// Set RestoreDeleted to restore a deleted directory. +// This may not give the directory structure when it +// was deleted, because files may have been deleted +// within it before it was deleted. // -// Returns Restore_TargetExists if the target directory exists, but -// there is no restore possible. (Won't attempt to overwrite things.) +// Returns Restore_TargetExists if the target +// directory exists, but there is no restore possible. +// (Won't attempt to overwrite things.) // -// Returns Restore_Complete on success. (Exceptions on error.) +// Returns Restore_Complete on success. (Exceptions +// on error, unless ContinueAfterError is true and +// the error is recoverable, in which case it returns +// Restore_CompleteWithErrors) // Created: 23/11/03 // // -------------------------------------------------------------------------- -int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, const char *LocalDirectoryName, - bool PrintDots, bool RestoreDeleted, bool UndeleteAfterRestoreDeleted, bool Resume) +int BackupClientRestore(BackupProtocolClient &rConnection, + int64_t DirectoryID, const char *LocalDirectoryName, + bool PrintDots, bool RestoreDeleted, + bool UndeleteAfterRestoreDeleted, bool Resume, + bool ContinueAfterErrors) { // Parameter block RestoreParams params; params.PrintDots = PrintDots; params.RestoreDeleted = RestoreDeleted; + params.ContinueAfterErrors = ContinueAfterErrors; + params.ContinuedAfterError = false; params.mRestoreResumeInfoFilename = LocalDirectoryName; params.mRestoreResumeInfoFilename += ".boxbackupresume"; @@ -699,12 +843,13 @@ int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, // Does any resumption information exist? bool doingResume = false; - if(FileExists(params.mRestoreResumeInfoFilename.c_str()) && targetExistance == ObjectExists_Dir) + if(FileExists(params.mRestoreResumeInfoFilename.c_str()) && + targetExistance == ObjectExists_Dir) { if(!Resume) { - // Caller didn't specify that resume should be done, so refuse to do it - // but say why. + // Caller didn't specify that resume should be done, + // so refuse to do it but say why. return Restore_ResumePossible; } @@ -752,9 +897,7 @@ int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, // Delete the resume information file ::unlink(params.mRestoreResumeInfoFilename.c_str()); - return Restore_Complete; + return params.ContinuedAfterError ? Restore_CompleteWithErrors + : Restore_Complete; } - - - diff --git a/lib/backupclient/BackupClientRestore.h b/lib/backupclient/BackupClientRestore.h index f7724030..7e492238 100644 --- a/lib/backupclient/BackupClientRestore.h +++ b/lib/backupclient/BackupClientRestore.h @@ -15,14 +15,21 @@ class BackupProtocolClient; enum { Restore_Complete = 0, - Restore_ResumePossible = 1, - Restore_TargetExists = 2, - Restore_TargetPathNotFound = 3, - Restore_UnknownError = 4, + Restore_ResumePossible, + Restore_TargetExists, + Restore_TargetPathNotFound, + Restore_UnknownError, + Restore_CompleteWithErrors, }; -int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, const char *LocalDirectoryName, - bool PrintDots = false, bool RestoreDeleted = false, bool UndeleteAfterRestoreDeleted = false, bool Resume = false); +int BackupClientRestore(BackupProtocolClient &rConnection, + int64_t DirectoryID, + const char *LocalDirectoryName, + bool PrintDots = false, + bool RestoreDeleted = false, + bool UndeleteAfterRestoreDeleted = false, + bool Resume = false, + bool ContinueAfterErrors = false); #endif // BACKUPSCLIENTRESTORE__H diff --git a/lib/backupclient/BackupDaemonConfigVerify.cpp b/lib/backupclient/BackupDaemonConfigVerify.cpp index 61033b5b..e70ba865 100644 --- a/lib/backupclient/BackupDaemonConfigVerify.cpp +++ b/lib/backupclient/BackupDaemonConfigVerify.cpp @@ -17,15 +17,15 @@ static const ConfigurationVerifyKey backuplocationkeys[] = { - {"ExcludeFile", 0, ConfigTest_MultiValueAllowed, 0}, - {"ExcludeFilesRegex", 0, ConfigTest_MultiValueAllowed, 0}, - {"ExcludeDir", 0, ConfigTest_MultiValueAllowed, 0}, - {"ExcludeDirsRegex", 0, ConfigTest_MultiValueAllowed, 0}, - {"AlwaysIncludeFile", 0, ConfigTest_MultiValueAllowed, 0}, - {"AlwaysIncludeFilesRegex", 0, ConfigTest_MultiValueAllowed, 0}, - {"AlwaysIncludeDir", 0, ConfigTest_MultiValueAllowed, 0}, - {"AlwaysIncludeDirsRegex", 0, ConfigTest_MultiValueAllowed, 0}, - {"Path", 0, ConfigTest_Exists | ConfigTest_LastEntry, 0} + ConfigurationVerifyKey("ExcludeFile", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("ExcludeFilesRegex", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("ExcludeDir", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("ExcludeDirsRegex", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("AlwaysIncludeFile", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("AlwaysIncludeFilesRegex", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("AlwaysIncludeDir", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("AlwaysIncludeDirsRegex", ConfigTest_MultiValueAllowed), + ConfigurationVerifyKey("Path", ConfigTest_Exists | ConfigTest_LastEntry) }; static const ConfigurationVerify backuplocations[] = @@ -64,39 +64,62 @@ static const ConfigurationVerify verifyserver[] = static const ConfigurationVerifyKey verifyrootkeys[] = { - {"AccountNumber", 0, ConfigTest_Exists | ConfigTest_IsInt, 0}, - - {"UpdateStoreInterval", 0, ConfigTest_Exists | ConfigTest_IsInt, 0}, - {"MinimumFileAge", 0, ConfigTest_Exists | ConfigTest_IsInt, 0}, - {"MaxUploadWait", 0, ConfigTest_Exists | ConfigTest_IsInt, 0}, - {"MaxFileTimeInFuture", "172800", ConfigTest_IsInt, 0}, // file is uploaded if the file is this much in the future (2 days default) - - {"AutomaticBackup", "yes", ConfigTest_IsBool, 0}, + ConfigurationVerifyKey("AccountNumber", + ConfigTest_Exists | ConfigTest_IsInt), + ConfigurationVerifyKey("UpdateStoreInterval", + ConfigTest_Exists | ConfigTest_IsInt), + ConfigurationVerifyKey("MinimumFileAge", + ConfigTest_Exists | ConfigTest_IsInt), + ConfigurationVerifyKey("MaxUploadWait", + ConfigTest_Exists | ConfigTest_IsInt), + ConfigurationVerifyKey("MaxFileTimeInFuture", ConfigTest_IsInt, 172800), + // file is uploaded if the file is this much in the future + // (2 days default) + ConfigurationVerifyKey("AutomaticBackup", ConfigTest_IsBool, true), - {"SyncAllowScript", 0, 0, 0}, // optional script to run to see if the sync should be started now - // return "now" if it's allowed, or a number of seconds if it's not + ConfigurationVerifyKey("SyncAllowScript", 0), + // script that returns "now" if backup is allowed now, or a number + // of seconds to wait before trying again if not - {"MaximumDiffingTime", 0, ConfigTest_IsInt, 0}, - {"DeleteRedundantLocationsAfter", "172800", ConfigTest_IsInt, 0}, + ConfigurationVerifyKey("MaximumDiffingTime", ConfigTest_IsInt), + ConfigurationVerifyKey("DeleteRedundantLocationsAfter", + ConfigTest_IsInt, 172800), - {"FileTrackingSizeThreshold", 0, ConfigTest_Exists | ConfigTest_IsInt, 0}, - {"DiffingUploadSizeThreshold", 0, ConfigTest_Exists | ConfigTest_IsInt, 0}, - {"StoreHostname", 0, ConfigTest_Exists, 0}, - {"ExtendedLogging", "no", ConfigTest_IsBool, 0}, // extended log to syslog - {"ExtendedLogFile", NULL, 0, 0}, // extended log to a file - {"LogAllFileAccess", "no", ConfigTest_IsBool, 0}, + ConfigurationVerifyKey("FileTrackingSizeThreshold", + ConfigTest_Exists | ConfigTest_IsInt), + ConfigurationVerifyKey("DiffingUploadSizeThreshold", + ConfigTest_Exists | ConfigTest_IsInt), + ConfigurationVerifyKey("StoreHostname", ConfigTest_Exists), + ConfigurationVerifyKey("StorePort", ConfigTest_IsInt, + BOX_PORT_BBSTORED), + ConfigurationVerifyKey("ExtendedLogging", ConfigTest_IsBool, false), + // extended log to syslog + ConfigurationVerifyKey("ExtendedLogFile", 0), + // extended log to a file + ConfigurationVerifyKey("LogAllFileAccess", ConfigTest_IsBool, false), + // enable logging reasons why each file is backed up or not + ConfigurationVerifyKey("LogFile", 0), + // enable logging to a file + ConfigurationVerifyKey("LogFileLevel", 0), + // set the level of verbosity of file logging + ConfigurationVerifyKey("CommandSocket", 0), + // not compulsory to have this + ConfigurationVerifyKey("KeepAliveTime", ConfigTest_IsInt), + ConfigurationVerifyKey("StoreObjectInfoFile", 0), + // optional - {"CommandSocket", 0, 0, 0}, // not compulsory to have this - {"KeepAliveTime", 0, ConfigTest_IsInt, 0}, // optional - {"StoreObjectInfoFile", 0, 0, 0}, // optional - - {"NotifyScript", 0, 0, 0}, // optional script to run when backup needs attention, eg store full + ConfigurationVerifyKey("NotifyScript", 0), + // optional script to run when backup needs attention, eg store full - {"CertificateFile", 0, ConfigTest_Exists, 0}, - {"PrivateKeyFile", 0, ConfigTest_Exists, 0}, - {"TrustedCAsFile", 0, ConfigTest_Exists, 0}, - {"KeysFile", 0, ConfigTest_Exists, 0}, - {"DataDirectory", 0, ConfigTest_Exists | ConfigTest_LastEntry, 0} + ConfigurationVerifyKey("NotifyAlways", ConfigTest_IsBool, false), + // option to disable the suppression of duplicate notifications + + ConfigurationVerifyKey("CertificateFile", ConfigTest_Exists), + ConfigurationVerifyKey("PrivateKeyFile", ConfigTest_Exists), + ConfigurationVerifyKey("TrustedCAsFile", ConfigTest_Exists), + ConfigurationVerifyKey("KeysFile", ConfigTest_Exists), + ConfigurationVerifyKey("DataDirectory", + ConfigTest_Exists | ConfigTest_LastEntry), }; const ConfigurationVerify BackupDaemonConfigVerify = diff --git a/lib/backupclient/BackupStoreFile.cpp b/lib/backupclient/BackupStoreFile.cpp index 7e93d59d..27e12bc8 100644 --- a/lib/backupclient/BackupStoreFile.cpp +++ b/lib/backupclient/BackupStoreFile.cpp @@ -65,22 +65,27 @@ BackupStoreFileStats BackupStoreFile::msStats = {0,0,0}; // Function // Name: BackupStoreFile::EncodeFile(IOStream &, IOStream &) // Purpose: Encode a file into something for storing on file server. -// Requires a real filename so full info can be stored. +// Requires a real filename so full info can be stored. // -// Returns a stream. Most of the work is done by the stream -// when data is actually requested -- the file will be held -// open until the stream is deleted or the file finished. +// Returns a stream. Most of the work is done by the stream +// when data is actually requested -- the file will be held +// open until the stream is deleted or the file finished. // Created: 2003/08/28 // // -------------------------------------------------------------------------- -std::auto_ptr<IOStream> BackupStoreFile::EncodeFile(const char *Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime) +std::auto_ptr<IOStream> BackupStoreFile::EncodeFile(const char *Filename, + int64_t ContainerID, const BackupStoreFilename &rStoreFilename, + int64_t *pModificationTime, ReadLoggingStream::Logger* pLogger, + RunStatusProvider* pRunStatusProvider) { // Create the stream std::auto_ptr<IOStream> stream(new BackupStoreFileEncodeStream); // Do the initial setup - ((BackupStoreFileEncodeStream*)stream.get())->Setup(Filename, 0 /* no recipe, just encode */, - ContainerID, rStoreFilename, pModificationTime); + ((BackupStoreFileEncodeStream*)stream.get())->Setup(Filename, + 0 /* no recipe, just encode */, + ContainerID, rStoreFilename, pModificationTime, pLogger, + pRunStatusProvider); // Return the stream for the caller return stream; @@ -267,8 +272,8 @@ bool BackupStoreFile::VerifyEncodedFileFormat(IOStream &rFile, int64_t *pDiffFro void BackupStoreFile::DecodeFile(IOStream &rEncodedFile, const char *DecodedFilename, int Timeout, const BackupClientFileAttributes *pAlterativeAttr) { // Does file exist? - struct stat st; - if(::stat(DecodedFilename, &st) == 0) + EMU_STRUCT_STAT st; + if(EMU_STAT(DecodedFilename, &st) == 0) { THROW_EXCEPTION(BackupStoreException, OutputFileAlreadyExists) } @@ -1255,8 +1260,8 @@ bool BackupStoreFile::CompareFileContentsAgainstBlockIndex(const char *Filename, // is it a symlink? bool sourceIsSymlink = false; { - struct stat st; - if(::lstat(Filename, &st) == -1) + EMU_STRUCT_STAT st; + if(EMU_LSTAT(Filename, &st) == -1) { THROW_EXCEPTION(CommonException, OSFileError) } diff --git a/lib/backupclient/BackupStoreFile.h b/lib/backupclient/BackupStoreFile.h index 3ee5ddb0..f38cd821 100644 --- a/lib/backupclient/BackupStoreFile.h +++ b/lib/backupclient/BackupStoreFile.h @@ -10,11 +10,14 @@ #ifndef BACKUPSTOREFILE__H #define BACKUPSTOREFILE__H -#include "IOStream.h" +#include <cstdlib> +#include <memory> + #include "BackupClientFileAttributes.h" #include "BackupStoreFilename.h" - -#include <memory> +#include "IOStream.h" +#include "ReadLoggingStream.h" +#include "RunStatusProvider.h" typedef struct { @@ -114,7 +117,11 @@ public: // Main interface - static std::auto_ptr<IOStream> EncodeFile(const char *Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime = 0); + static std::auto_ptr<IOStream> EncodeFile(const char *Filename, + int64_t ContainerID, const BackupStoreFilename &rStoreFilename, + int64_t *pModificationTime = 0, + ReadLoggingStream::Logger* pLogger = NULL, + RunStatusProvider* pRunStatusProvider = NULL); static std::auto_ptr<IOStream> EncodeFileDiff ( const char *Filename, int64_t ContainerID, @@ -207,7 +214,7 @@ public: static BackupStoreFileStats msStats; // For debug -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD static bool TraceDetailsOfDiffProcess; #endif diff --git a/lib/backupclient/BackupStoreFileDiff.cpp b/lib/backupclient/BackupStoreFileDiff.cpp index f7842a0b..e9da1ee7 100644 --- a/lib/backupclient/BackupStoreFileDiff.cpp +++ b/lib/backupclient/BackupStoreFileDiff.cpp @@ -9,6 +9,8 @@ #include "Box.h" +#include <string.h> + #include <new> #include <map> @@ -38,7 +40,7 @@ using namespace BackupStoreFileCreation; // By default, don't trace out details of the diff as we go along -- would fill up logs significantly. // But it's useful for the test. -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD bool BackupStoreFile::TraceDetailsOfDiffProcess = false; #endif @@ -128,8 +130,8 @@ std::auto_ptr<IOStream> BackupStoreFile::EncodeFileDiff { // Is it a symlink? { - struct stat st; - if(::lstat(Filename, &st) != 0) + EMU_STRUCT_STAT st; + if(EMU_LSTAT(Filename, &st) != 0) { THROW_EXCEPTION(CommonException, OSFileError) } @@ -149,7 +151,7 @@ std::auto_ptr<IOStream> BackupStoreFile::EncodeFileDiff int64_t blocksInIndex = 0; bool canDiffFromThis = false; LoadIndex(rDiffFromBlockIndex, DiffFromObjectID, &pindex, blocksInIndex, Timeout, canDiffFromThis); - //TRACE1("Diff: Blocks in index: %lld\n", blocksInIndex); + // BOX_TRACE("Diff: Blocks in index: " << blocksInIndex); if(!canDiffFromThis) { @@ -434,12 +436,14 @@ static void FindMostUsedSizes(BlocksAvailableEntry *pIndex, int64_t NumBlocks, i } // trace the size table in debug builds -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD if(BackupStoreFile::TraceDetailsOfDiffProcess) { for(int t = 0; t < BACKUP_FILE_DIFF_MAX_BLOCK_SIZES; ++t) { - TRACE3("Diff block size %d: %d (count = %lld)\n", t, Sizes[t], sizeCounts[t]); + BOX_TRACE("Diff block size " << t << ": " << + Sizes[t] << " (count = " << + sizeCounts[t] << ")"); } } #endif @@ -459,11 +463,12 @@ static void SearchForMatchingBlocks(IOStream &rFile, std::map<int64_t, int64_t> BlocksAvailableEntry *pIndex, int64_t NumBlocks, int32_t Sizes[BACKUP_FILE_DIFF_MAX_BLOCK_SIZES], DiffTimer *pDiffTimer) { - Timer maximumDiffingTime(0); + Timer maximumDiffingTime(0, "MaximumDiffingTime"); if(pDiffTimer && pDiffTimer->IsManaged()) { - maximumDiffingTime = Timer(pDiffTimer->GetMaximumDiffingTime()); + maximumDiffingTime = Timer(pDiffTimer->GetMaximumDiffingTime(), + "MaximumDiffingTime"); } std::map<int64_t, int32_t> goodnessOfFit; @@ -626,7 +631,7 @@ static void SearchForMatchingBlocks(IOStream &rFile, std::map<int64_t, int64_t> // Block matched, roll the checksum forward to the next block without doing // any more comparisons, because these are pointless (as any more matches will be ignored when - // the receipe is generated) and just take up valuable processor time. Edge cases are + // the recipe is generated) and just take up valuable processor time. Edge cases are // especially nasty, using huge amounts of time and memory. int skip = Sizes[s]; if(offset < bytesInEndings && skip > 0) @@ -723,7 +728,7 @@ static void SearchForMatchingBlocks(IOStream &rFile, std::map<int64_t, int64_t> throw; } -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD if(BackupStoreFile::TraceDetailsOfDiffProcess) { // Trace out the found blocks in debug mode @@ -774,7 +779,7 @@ static void SetupHashTable(BlocksAvailableEntry *pIndex, int64_t NumBlocks, int3 // Already present in table? if(pHashTable[hash] != 0) { - //TRACE1("Another hash entry for %d found\n", hash); + //BOX_TRACE("Another hash entry for " << hash << " found"); // Yes -- need to set the pointer in this entry to the current entry to build the linked list pIndex[b].mpNextInHashList = pHashTable[hash]; } @@ -805,7 +810,7 @@ static bool SecondStageMatch(BlocksAvailableEntry *pFirstInHashList, RollingChec ASSERT(pFirstInHashList != 0); ASSERT(pIndex != 0); -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD uint16_t DEBUG_Hash = fastSum.GetComponentForHashing(); #endif uint32_t Checksum = fastSum.GetChecksum(); @@ -840,17 +845,19 @@ static bool SecondStageMatch(BlocksAvailableEntry *pFirstInHashList, RollingChec // Then go through the entries in the hash list, comparing with the strong digest calculated scan = pFirstInHashList; - //TRACE0("second stage match\n"); + //BOX_TRACE("second stage match"); while(scan != 0) { - //TRACE3("scan size %d, block size %d, hash %d\n", scan->mSize, BlockSize, Hash); + //BOX_TRACE("scan size " << scan->mSize << + // ", block size " << BlockSize << + // ", hash " << Hash); ASSERT(scan->mSize == BlockSize); ASSERT(RollingChecksum::ExtractHashingComponent(scan->mWeakChecksum) == DEBUG_Hash); // Compare? if(strong.DigestMatches(scan->mStrongChecksum)) { - //TRACE0("Match!\n"); + //BOX_TRACE("Match!\n"); // Found! Add to list of found blocks... int64_t fileOffset = (FileBlockNumber * BlockSize) + Offset; int64_t blockIndex = (scan - pIndex); // pointer arthmitic is frowned upon. But most efficient way of doing it here -- alternative is to use more memory @@ -909,10 +916,11 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA instruction.mSpaceBefore = SizeOfInputFile; rRecipe.push_back(instruction); - #ifndef NDEBUG + #ifndef BOX_RELEASE_BUILD if(BackupStoreFile::TraceDetailsOfDiffProcess) { - TRACE1("Diff: Default recipe generated, %lld bytes of file\n", SizeOfInputFile); + BOX_TRACE("Diff: Default recipe generated, " << + SizeOfInputFile << " bytes of file"); } #endif @@ -928,7 +936,7 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA ASSERT(i != rFoundBlocks.end()); // check logic // Counting for debug tracing -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD int64_t debug_NewBytesFound = 0; int64_t debug_OldBlocksUsed = 0; #endif @@ -955,7 +963,7 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA instruction.mSpaceBefore = i->first - loc; // Move location forward to match loc += instruction.mSpaceBefore; -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD debug_NewBytesFound += instruction.mSpaceBefore; #endif } @@ -981,7 +989,7 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA instruction.mBlocks += 1; } -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD debug_OldBlocksUsed++; #endif @@ -997,18 +1005,22 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA { RESET_INSTRUCTION instruction.mSpaceBefore = SizeOfInputFile - loc; -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD debug_NewBytesFound += instruction.mSpaceBefore; #endif rRecipe.push_back(instruction); } // dump out the recipe -#ifndef NDEBUG - TRACE2("Diff: %lld new bytes found, %lld old blocks used\n", debug_NewBytesFound, debug_OldBlocksUsed); +#ifndef BOX_RELEASE_BUILD + BOX_TRACE("Diff: " << + debug_NewBytesFound << " new bytes found, " << + debug_OldBlocksUsed << " old blocks used"); if(BackupStoreFile::TraceDetailsOfDiffProcess) { - TRACE1("Diff: Recipe generated (size %d)\n======== ========= ========\nSpace b4 FirstBlk NumBlks\n", rRecipe.size()); + BOX_TRACE("Diff: Recipe generated (size " << rRecipe.size()); + BOX_TRACE("======== ========= ========"); + BOX_TRACE("Space b4 FirstBlk NumBlks"); { for(unsigned int e = 0; e < rRecipe.size(); ++e) { @@ -1018,10 +1030,15 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA #else sprintf(b, "%8lld", (int64_t)(rRecipe[e].mpStartBlock - pIndex)); #endif - TRACE3("%8lld %s %8lld\n", rRecipe[e].mSpaceBefore, (rRecipe[e].mpStartBlock == 0)?" -":b, (int64_t)rRecipe[e].mBlocks); + BOX_TRACE(std::setw(8) << + rRecipe[e].mSpaceBefore << + " " << + ((rRecipe[e].mpStartBlock == 0)?" -":b) << + " " << std::setw(8) << + rRecipe[e].mBlocks); } } - TRACE0("======== ========= ========\n"); + BOX_TRACE("======== ========= ========"); } #endif } diff --git a/lib/backupclient/BackupStoreFileEncodeStream.cpp b/lib/backupclient/BackupStoreFileEncodeStream.cpp index 423c11a3..b2d44697 100644 --- a/lib/backupclient/BackupStoreFileEncodeStream.cpp +++ b/lib/backupclient/BackupStoreFileEncodeStream.cpp @@ -9,18 +9,20 @@ #include "Box.h" -#include "BackupStoreFileEncodeStream.h" +#include <string.h> + +#include "BackupClientFileAttributes.h" +#include "BackupStoreConstants.h" +#include "BackupStoreException.h" #include "BackupStoreFile.h" -#include "BackupStoreFileWire.h" #include "BackupStoreFileCryptVar.h" +#include "BackupStoreFileEncodeStream.h" +#include "BackupStoreFileWire.h" #include "BackupStoreObjectMagic.h" -#include "BackupStoreException.h" -#include "BackupStoreConstants.h" #include "BoxTime.h" -#include "BackupClientFileAttributes.h" #include "FileStream.h" -#include "RollingChecksum.h" #include "Random.h" +#include "RollingChecksum.h" #include "MemLeakFindOn.h" @@ -39,6 +41,7 @@ BackupStoreFileEncodeStream::BackupStoreFileEncodeStream() : mpRecipe(0), mpFile(0), mpLogging(0), + mpRunStatusProvider(NULL), mStatus(Status_Header), mSendData(true), mTotalBlocks(0), @@ -105,8 +108,11 @@ BackupStoreFileEncodeStream::~BackupStoreFileEncodeStream() // Created: 8/12/03 // // -------------------------------------------------------------------------- -void BackupStoreFileEncodeStream::Setup(const char *Filename, BackupStoreFileEncodeStream::Recipe *pRecipe, - int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime) +void BackupStoreFileEncodeStream::Setup(const char *Filename, + BackupStoreFileEncodeStream::Recipe *pRecipe, + int64_t ContainerID, const BackupStoreFilename &rStoreFilename, + int64_t *pModificationTime, ReadLoggingStream::Logger* pLogger, + RunStatusProvider* pRunStatusProvider) { // Pointer to a blank recipe which we might create BackupStoreFileEncodeStream::Recipe *pblankRecipe = 0; @@ -126,9 +132,9 @@ void BackupStoreFileEncodeStream::Setup(const char *Filename, BackupStoreFileEnc pblankRecipe = new BackupStoreFileEncodeStream::Recipe(0, 0); BackupStoreFileEncodeStream::RecipeInstruction instruction; - instruction.mSpaceBefore = fileSize; // whole file - instruction.mBlocks = 0; // no blocks - instruction.mpStartBlock = 0; // no block + instruction.mSpaceBefore = fileSize; // whole file + instruction.mBlocks = 0; // no blocks + instruction.mpStartBlock = 0; // no block pblankRecipe->push_back(instruction); pRecipe = pblankRecipe; @@ -208,8 +214,18 @@ void BackupStoreFileEncodeStream::Setup(const char *Filename, BackupStoreFileEnc // Open the file mpFile = new FileStream(Filename); - // Create logging stream - mpLogging = new ReadLoggingStream(*mpFile); + if (pLogger) + { + // Create logging stream + mpLogging = new ReadLoggingStream(*mpFile, + *pLogger); + } + else + { + // re-use FileStream instead + mpLogging = mpFile; + mpFile = NULL; + } // Work out the largest possible block required for the encoded data mAllocatedBufferSize = BackupStoreFile::MaxBlockSizeForChunkSize(maxBlockClearSize); @@ -220,7 +236,7 @@ void BackupStoreFileEncodeStream::Setup(const char *Filename, BackupStoreFileEnc { throw std::bad_alloc(); } -#ifndef NDEBUG +#ifndef BOX_RELEASE_BUILD // In debug builds, make sure that the reallocation code is exercised. mEncodedBuffer.Allocate(mAllocatedBufferSize / 4); #else @@ -257,6 +273,8 @@ void BackupStoreFileEncodeStream::Setup(const char *Filename, BackupStoreFileEnc } throw; } + + mpRunStatusProvider = pRunStatusProvider; } @@ -314,6 +332,11 @@ int BackupStoreFileEncodeStream::Read(void *pBuffer, int NBytes, int Timeout) { return 0; } + + if(mpRunStatusProvider && mpRunStatusProvider->StopRun()) + { + THROW_EXCEPTION(BackupStoreException, SignalReceived); + } int bytesToRead = NBytes; uint8_t *buffer = (uint8_t*)pBuffer; @@ -529,22 +552,25 @@ void BackupStoreFileEncodeStream::EncodeCurrentBlock() ASSERT(blockRawSize < mAllocatedBufferSize); // Check file open - if(mpFile == 0 || mpLogging == 0) + if(mpLogging == 0) { // File should be open, but isn't. So logical error. THROW_EXCEPTION(BackupStoreException, Internal) } // Read the data in - if(!mpLogging->ReadFullBuffer(mpRawBuffer, blockRawSize, 0 /* not interested in size if failure */)) + if(!mpLogging->ReadFullBuffer(mpRawBuffer, blockRawSize, + 0 /* not interested in size if failure */)) { - // TODO: Do something more intelligent, and abort this upload because the file - // has changed - THROW_EXCEPTION(BackupStoreException, Temp_FileEncodeStreamDidntReadBuffer) + // TODO: Do something more intelligent, and abort + // this upload because the file has changed. + THROW_EXCEPTION(BackupStoreException, + Temp_FileEncodeStreamDidntReadBuffer) } // Encode it - mCurrentBlockEncodedSize = BackupStoreFile::EncodeChunk(mpRawBuffer, blockRawSize, mEncodedBuffer); + mCurrentBlockEncodedSize = BackupStoreFile::EncodeChunk(mpRawBuffer, + blockRawSize, mEncodedBuffer); //TRACE2("Encode: Encoded size of block %d is %d\n", (int32_t)mCurrentBlock, (int32_t)mCurrentBlockEncodedSize); @@ -555,7 +581,8 @@ void BackupStoreFileEncodeStream::EncodeCurrentBlock() strongChecksum.Finish(); // Add entry to the index - StoreBlockIndexEntry(mCurrentBlockEncodedSize, blockRawSize, weakChecksum.GetChecksum(), strongChecksum.DigestAsData()); + StoreBlockIndexEntry(mCurrentBlockEncodedSize, blockRawSize, + weakChecksum.GetChecksum(), strongChecksum.DigestAsData()); // Set vars to reading this block mPositionInCurrentBlock = 0; diff --git a/lib/backupclient/BackupStoreFileEncodeStream.h b/lib/backupclient/BackupStoreFileEncodeStream.h index fb5d0851..c5fa780a 100644 --- a/lib/backupclient/BackupStoreFileEncodeStream.h +++ b/lib/backupclient/BackupStoreFileEncodeStream.h @@ -18,6 +18,7 @@ #include "MD5Digest.h" #include "BackupStoreFile.h" #include "ReadLoggingStream.h" +#include "RunStatusProvider.h" namespace BackupStoreFileCreation { @@ -74,7 +75,11 @@ public: int64_t mOtherFileID; }; - void Setup(const char *Filename, Recipe *pRecipe, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime); + void Setup(const char *Filename, Recipe *pRecipe, int64_t ContainerID, + const BackupStoreFilename &rStoreFilename, + int64_t *pModificationTime, + ReadLoggingStream::Logger* pLogger = NULL, + RunStatusProvider* pRunStatusProvider = NULL); virtual int Read(void *pBuffer, int NBytes, int Timeout); virtual void Write(const void *pBuffer, int NBytes); @@ -101,7 +106,8 @@ private: Recipe *mpRecipe; IOStream *mpFile; // source file CollectInBufferStream mData; // buffer for header and index entries - ReadLoggingStream *mpLogging; + IOStream *mpLogging; + RunStatusProvider* mpRunStatusProvider; int mStatus; bool mSendData; // true if there's file data to send (ie not a symlink) int64_t mTotalBlocks; // Total number of blocks in the file diff --git a/lib/backupclient/BackupStoreFilename.cpp b/lib/backupclient/BackupStoreFilename.cpp index fbfe3313..72cd1acd 100644 --- a/lib/backupclient/BackupStoreFilename.cpp +++ b/lib/backupclient/BackupStoreFilename.cpp @@ -37,7 +37,7 @@ BackupStoreFilename::BackupStoreFilename() // // -------------------------------------------------------------------------- BackupStoreFilename::BackupStoreFilename(const BackupStoreFilename &rToCopy) - : BackupStoreFilename_base(rToCopy) + : mEncryptedName(rToCopy.mEncryptedName) { } @@ -65,7 +65,7 @@ bool BackupStoreFilename::CheckValid(bool ExceptionIfInvalid) const { bool ok = true; - if(size() < 2) + if(mEncryptedName.size() < 2) { // Isn't long enough to have a header ok = false; @@ -73,14 +73,14 @@ bool BackupStoreFilename::CheckValid(bool ExceptionIfInvalid) const else { // Check size is consistent - unsigned int dsize = BACKUPSTOREFILENAME_GET_SIZE(*this); - if(dsize != size()) + unsigned int dsize = BACKUPSTOREFILENAME_GET_SIZE(this->mEncryptedName); + if(dsize != mEncryptedName.size()) { ok = false; } // And encoding is an accepted value - unsigned int encoding = BACKUPSTOREFILENAME_GET_ENCODING(*this); + unsigned int encoding = BACKUPSTOREFILENAME_GET_ENCODING(this->mEncryptedName); if(encoding < Encoding_Min || encoding > Encoding_Max) { ok = false; @@ -119,8 +119,8 @@ void BackupStoreFilename::ReadFromProtocol(Protocol &rProtocol) rProtocol.Read(data, dsize - 2); // assign to this string, storing the header and the extra data - assign(hdr, 2); - append(data.c_str(), data.size()); + mEncryptedName.assign(hdr, 2); + mEncryptedName.append(data.c_str(), data.size()); // Check it CheckValid(); @@ -141,7 +141,7 @@ void BackupStoreFilename::WriteToProtocol(Protocol &rProtocol) const { CheckValid(); - rProtocol.Write(c_str(), size()); + rProtocol.Write(mEncryptedName.c_str(), mEncryptedName.size()); } // -------------------------------------------------------------------------- @@ -177,7 +177,7 @@ void BackupStoreFilename::ReadFromStream(IOStream &rStream, int Timeout) buf[0] = hdr[0]; buf[1] = hdr[1]; // assign to this string, storing the header and the extra data - assign(buf, dsize); + mEncryptedName.assign(buf, dsize); } else { @@ -194,7 +194,7 @@ void BackupStoreFilename::ReadFromStream(IOStream &rStream, int Timeout) data[0] = hdr[0]; data[1] = hdr[1]; // assign to this string, storing the header and the extra data - assign(data, dsize); + mEncryptedName.assign(data, dsize); } // Check it @@ -216,7 +216,7 @@ void BackupStoreFilename::WriteToStream(IOStream &rStream) const { CheckValid(); - rStream.Write(c_str(), size()); + rStream.Write(mEncryptedName.c_str(), mEncryptedName.size()); } // -------------------------------------------------------------------------- @@ -242,7 +242,8 @@ void BackupStoreFilename::EncodedFilenameChanged() // -------------------------------------------------------------------------- bool BackupStoreFilename::IsEncrypted() const { - return BACKUPSTOREFILENAME_GET_ENCODING(*this) != Encoding_Clear; + return BACKUPSTOREFILENAME_GET_ENCODING(this->mEncryptedName) != + Encoding_Clear; } @@ -250,8 +251,9 @@ bool BackupStoreFilename::IsEncrypted() const // // Function // Name: BackupStoreFilename::SetAsClearFilename(const char *) -// Purpose: Sets this object to be a valid filename, but with a filename in the clear. -// Used on the server to create filenames when there's no way of encrypting it. +// Purpose: Sets this object to be a valid filename, but with a +// filename in the clear. Used on the server to create +// filenames when there's no way of encrypting it. // Created: 22/4/04 // // -------------------------------------------------------------------------- @@ -268,7 +270,7 @@ void BackupStoreFilename::SetAsClearFilename(const char *Clear) ASSERT(encoded.size() == toEncode.size() + 2); // Store the encoded string - assign(encoded); + mEncryptedName.assign(encoded); // Stuff which must be done EncodedFilenameChanged(); diff --git a/lib/backupclient/BackupStoreFilename.h b/lib/backupclient/BackupStoreFilename.h index a7b6c437..80db9516 100644 --- a/lib/backupclient/BackupStoreFilename.h +++ b/lib/backupclient/BackupStoreFilename.h @@ -40,8 +40,11 @@ class IOStream; // Created: 2003/08/26 // // -------------------------------------------------------------------------- -class BackupStoreFilename : public BackupStoreFilename_base +class BackupStoreFilename /* : public BackupStoreFilename_base */ { +private: + std::string mEncryptedName; + public: BackupStoreFilename(); BackupStoreFilename(const BackupStoreFilename &rToCopy); @@ -71,8 +74,27 @@ public: Encoding_Max = 2 }; + const std::string& GetEncodedFilename() const + { + return mEncryptedName; + } + + bool operator==(const BackupStoreFilename& rOther) const + { + return mEncryptedName == rOther.mEncryptedName; + } + + bool operator!=(const BackupStoreFilename& rOther) const + { + return mEncryptedName != rOther.mEncryptedName; + } + protected: virtual void EncodedFilenameChanged(); + void SetEncodedFilename(const std::string &rEncoded) + { + mEncryptedName = rEncoded; + } }; // On the wire utilities for class and derived class diff --git a/lib/backupclient/BackupStoreFilenameClear.cpp b/lib/backupclient/BackupStoreFilenameClear.cpp index 9114fdd1..e529d8d3 100644 --- a/lib/backupclient/BackupStoreFilenameClear.cpp +++ b/lib/backupclient/BackupStoreFilenameClear.cpp @@ -160,15 +160,17 @@ void BackupStoreFilenameClear::MakeClearAvailable() const CheckValid(); // Decode the header - int size = BACKUPSTOREFILENAME_GET_SIZE(*this); - int encoding = BACKUPSTOREFILENAME_GET_ENCODING(*this); + int size = BACKUPSTOREFILENAME_GET_SIZE(GetEncodedFilename()); + int encoding = BACKUPSTOREFILENAME_GET_ENCODING(GetEncodedFilename()); // Decode based on encoding given in the header switch(encoding) { case Encoding_Clear: - TRACE0("**** BackupStoreFilename encoded with Clear encoding ****\n"); - mClearFilename.assign(c_str() + 2, size - 2); + BOX_TRACE("**** BackupStoreFilename encoded with " + "Clear encoding ****"); + mClearFilename.assign(GetEncodedFilename().c_str() + 2, + size - 2); break; case Encoding_Blowfish: @@ -193,7 +195,8 @@ static void EnsureEncDecBufferSize(int BufSize) if(spEncDecBuffer == 0) { #ifndef WIN32 - TRACE1("Allocating filename encoding/decoding buffer with size %d\n", BufSize); + BOX_TRACE("Allocating filename encoding/decoding buffer " + "with size " << BufSize); #endif spEncDecBuffer = new MemoryBlockGuard<uint8_t *>(BufSize); MEMLEAKFINDER_NOT_A_LEAK(spEncDecBuffer); @@ -242,7 +245,7 @@ void BackupStoreFilenameClear::EncryptClear(const std::string &rToEncode, Cipher BACKUPSTOREFILENAME_MAKE_HDR(buffer, encSize, StoreAsEncoding); // Store the encoded string - assign((char*)buffer, encSize); + SetEncodedFilename(std::string((char*)buffer, encSize)); } @@ -256,8 +259,10 @@ void BackupStoreFilenameClear::EncryptClear(const std::string &rToEncode, Cipher // -------------------------------------------------------------------------- void BackupStoreFilenameClear::DecryptEncoded(CipherContext &rCipherContext) const { + const std::string& rEncoded = GetEncodedFilename(); + // Work out max size - int maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(size()) + 4; + int maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(rEncoded.size()) + 4; // Make sure encode/decode buffer has enough space EnsureEncDecBufferSize(maxOutSize); @@ -266,8 +271,8 @@ void BackupStoreFilenameClear::DecryptEncoded(CipherContext &rCipherContext) con uint8_t *buffer = *spEncDecBuffer; // Decrypt - const char *str = c_str() + 2; - int sizeOut = rCipherContext.TransformBlock(buffer, sEncDecBufferSize, str, size() - 2); + const char *str = rEncoded.c_str() + 2; + int sizeOut = rCipherContext.TransformBlock(buffer, sEncDecBufferSize, str, rEncoded.size() - 2); // Assign to this mClearFilename.assign((char*)buffer, sizeOut); diff --git a/lib/backupclient/BackupStoreObjectDump.cpp b/lib/backupclient/BackupStoreObjectDump.cpp index d3d9cc17..654317c1 100644 --- a/lib/backupclient/BackupStoreObjectDump.cpp +++ b/lib/backupclient/BackupStoreObjectDump.cpp @@ -47,7 +47,7 @@ static void OutputLine(FILE *file, bool ToTrace, const char *format, ...) } if(ToTrace) { - TRACE1("%s", text); + BOX_TRACE(text); } } @@ -70,7 +70,7 @@ void BackupStoreDirectory::Dump(void *clibFileHandle, bool ToTrace) mAttributesModTime, mAttributes.GetSize()); // So repeated filenames can be illustrated, even though they can't be decoded - std::map<BackupStoreFilename, int> nameNum; + std::map<std::string, int> nameNum; int nameNumI = 0; // Dump items @@ -78,7 +78,7 @@ void BackupStoreDirectory::Dump(void *clibFileHandle, bool ToTrace) for(std::vector<Entry*>::const_iterator i(mEntries.begin()); i != mEntries.end(); ++i) { // Choose file name index number for this file - std::map<BackupStoreFilename, int>::iterator nn(nameNum.find((*i)->GetName())); + std::map<std::string, int>::iterator nn(nameNum.find((*i)->GetName().GetEncodedFilename())); int ni = nameNumI; if(nn != nameNum.end()) { @@ -86,7 +86,7 @@ void BackupStoreDirectory::Dump(void *clibFileHandle, bool ToTrace) } else { - nameNum[(*i)->GetName()] = nameNumI; + nameNum[(*i)->GetName().GetEncodedFilename()] = nameNumI; ++nameNumI; } @@ -124,7 +124,7 @@ void BackupStoreDirectory::Dump(void *clibFileHandle, bool ToTrace) (*i)->GetSizeInBlocks(), (*i)->GetAttributesHash(), (*i)->GetAttributes().GetSize(), - (*i)->GetName().size(), + (*i)->GetName().GetEncodedFilename().size(), ni, ((f & BackupStoreDirectory::Entry::Flags_File)?" file":""), ((f & BackupStoreDirectory::Entry::Flags_Dir)?" dir":""), @@ -173,7 +173,8 @@ void BackupStoreFile::DumpFile(void *clibFileHandle, bool ToTrace, IOStream &rFi // Read the next two objects BackupStoreFilename fn; fn.ReadFromStream(rFile, IOStream::TimeOutInfinite); - OutputLine(file, ToTrace, "Filename size: %d\n", fn.size()); + OutputLine(file, ToTrace, "Filename size: %d\n", + fn.GetEncodedFilename().size()); BackupClientFileAttributes attr; attr.ReadFromStream(rFile, IOStream::TimeOutInfinite); @@ -211,14 +212,16 @@ void BackupStoreFile::DumpFile(void *clibFileHandle, bool ToTrace, IOStream &rFi if(s > 0) { nnew++; - TRACE2("%8lld this s=%8lld\n", b, s); + BOX_TRACE(std::setw(8) << b << " this s=" << + std::setw(8) << s); } else { nold++; - TRACE2("%8lld other i=%8lld\n", b, 0 - s); + BOX_TRACE(std::setw(8) << b << " other i=" << + std::setw(8) << 0 - s); } } - TRACE0("======== ===== ==========\n"); + BOX_TRACE("======== ===== =========="); } diff --git a/lib/backupclient/RunStatusProvider.h b/lib/backupclient/RunStatusProvider.h new file mode 100644 index 00000000..89f361ca --- /dev/null +++ b/lib/backupclient/RunStatusProvider.h @@ -0,0 +1,29 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: RunStatusProvider.h +// Purpose: Declares the RunStatusProvider interface. +// Created: 2008/08/14 +// +// -------------------------------------------------------------------------- + +#ifndef RUNSTATUSPROVIDER__H +#define RUNSTATUSPROVIDER__H + +// -------------------------------------------------------------------------- +// +// Class +// Name: RunStatusProvider +// Purpose: Provides a StopRun() method which returns true if +// the current backup should be halted. +// Created: 2005/11/15 +// +// -------------------------------------------------------------------------- +class RunStatusProvider +{ + public: + virtual ~RunStatusProvider() { } + virtual bool StopRun() = 0; +}; + +#endif // RUNSTATUSPROVIDER__H |