summaryrefslogtreecommitdiff
path: root/lib/backupclient
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2007-09-19 21:58:24 +0000
committerChris Wilson <chris+github@qwirx.com>2007-09-19 21:58:24 +0000
commit867fbf737760a7764f6095a1b9b7554047c47eb3 (patch)
tree1bc17e74cfef9352857f62b3ee842fa95a8547a4 /lib/backupclient
parent41f3230a75e965254ab47e3609f68c8634266d37 (diff)
parent2ff87143551e6882c90ceaba940a34779b922882 (diff)
Replace trunk with chris/merge.
Diffstat (limited to 'lib/backupclient')
-rw-r--r--lib/backupclient/BackupClientFileAttributes.cpp23
-rw-r--r--lib/backupclient/BackupClientFileAttributes.h3
-rw-r--r--lib/backupclient/BackupClientRestore.cpp350
-rw-r--r--lib/backupclient/BackupClientRestore.h4
-rw-r--r--lib/backupclient/BackupDaemonConfigVerify.cpp4
-rw-r--r--lib/backupclient/BackupStoreDirectory.cpp5
-rw-r--r--lib/backupclient/BackupStoreFile.cpp27
-rw-r--r--lib/backupclient/BackupStoreFile.h9
-rw-r--r--lib/backupclient/BackupStoreFileDiff.cpp69
-rw-r--r--lib/backupclient/BackupStoreFileEncodeStream.cpp19
-rw-r--r--lib/backupclient/BackupStoreFileEncodeStream.h2
-rw-r--r--lib/backupclient/BackupStoreFilenameClear.cpp7
12 files changed, 404 insertions, 118 deletions
diff --git a/lib/backupclient/BackupClientFileAttributes.cpp b/lib/backupclient/BackupClientFileAttributes.cpp
index ba65d57a..925d1620 100644
--- a/lib/backupclient/BackupClientFileAttributes.cpp
+++ b/lib/backupclient/BackupClientFileAttributes.cpp
@@ -344,8 +344,8 @@ void BackupClientFileAttributes::ReadAttributes(const char *Filename, bool ZeroM
// to be true (still aborts), but it can at least hold 2^32.
if (winTime >= 0x100000000LL || _gmtime64(&winTime) == 0)
{
- ::syslog(LOG_ERR, "Invalid Modification Time "
- "caught for file: %s", Filename);
+ BOX_ERROR("Invalid Modification Time caught for "
+ "file: '" << Filename << "'");
pattr->ModificationTime = 0;
}
@@ -355,8 +355,8 @@ void BackupClientFileAttributes::ReadAttributes(const char *Filename, bool ZeroM
if (winTime > 0x100000000LL || _gmtime64(&winTime) == 0)
{
- ::syslog(LOG_ERR, "Invalid Attribute Modification "
- "Time caught for file: %s", Filename);
+ BOX_ERROR("Invalid Attribute Modification Time "
+ "caught for file: '" << Filename << "'");
pattr->AttrModificationTime = 0;
}
#endif
@@ -578,7 +578,8 @@ void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBloc
// Created: 2003/10/07
//
// --------------------------------------------------------------------------
-void BackupClientFileAttributes::WriteAttributes(const char *Filename) const
+void BackupClientFileAttributes::WriteAttributes(const char *Filename,
+ bool MakeUserWritable) const
{
// Got something loaded
if(GetSize() <= 0)
@@ -626,9 +627,8 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename) const
}
#ifdef WIN32
- ::syslog(LOG_WARNING,
- "Cannot create symbolic links on Windows: %s",
- Filename);
+ BOX_WARNING("Cannot create symbolic links on Windows: '" <<
+ Filename << "'");
#else
// Make a symlink, first deleting anything in the way
::unlink(Filename);
@@ -704,7 +704,12 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename) const
THROW_EXCEPTION(CommonException, OSFileError)
}
}
-
+
+ if (MakeUserWritable)
+ {
+ mode |= S_IRWXU;
+ }
+
// 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)
{
diff --git a/lib/backupclient/BackupClientFileAttributes.h b/lib/backupclient/BackupClientFileAttributes.h
index 62ba2184..fa56ff65 100644
--- a/lib/backupclient/BackupClientFileAttributes.h
+++ b/lib/backupclient/BackupClientFileAttributes.h
@@ -45,7 +45,8 @@ public:
void ReadAttributes(const char *Filename, bool ZeroModificationTimes = false,
box_time_t *pModTime = 0, box_time_t *pAttrModTime = 0, int64_t *pFileSize = 0,
InodeRefType *pInodeNumber = 0, bool *pHasMultipleLinks = 0);
- void WriteAttributes(const char *Filename) const;
+ void WriteAttributes(const char *Filename,
+ bool MakeUserWritable = false) const;
bool IsSymLink() const;
diff --git a/lib/backupclient/BackupClientRestore.cpp b/lib/backupclient/BackupClientRestore.cpp
index fbb4ee47..3c03c87c 100644
--- a/lib/backupclient/BackupClientRestore.cpp
+++ b/lib/backupclient/BackupClientRestore.cpp
@@ -19,6 +19,7 @@
#include <set>
#include <limits.h>
#include <stdio.h>
+#include <errno.h>
#include "BackupClientRestore.h"
#include "autogen_BackupProtocolClient.h"
@@ -206,7 +207,7 @@ typedef struct
// Created: 23/11/03
//
// --------------------------------------------------------------------------
-static void 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
@@ -223,11 +224,35 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
rLevel.RemoveLevel();
}
- // Save the resumption information
- Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
+ // Create the local directory, if not already done.
+ // Path and owner set later, just use restrictive owner mode.
- // Create the local directory (if not already done) -- path and owner set later, just use restrictive owner mode
- switch(ObjectExists(rLocalDirectoryName.c_str()))
+ int exists;
+
+ try
+ {
+ exists = ObjectExists(rLocalDirectoryName.c_str());
+ }
+ catch (BoxException &e)
+ {
+ BOX_ERROR("Failed to check existence for " <<
+ rLocalDirectoryName << ": " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to check existence for " <<
+ rLocalDirectoryName << ": " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to check existence for " <<
+ rLocalDirectoryName << ": unknown error");
+ return Restore_UnknownError;
+ }
+
+ switch(exists)
{
case ObjectExists_Dir:
// Do nothing
@@ -235,26 +260,152 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
case ObjectExists_File:
{
// File exists with this name, which is fun. Get rid of it.
- ::printf("WARNING: File present with name '%s', removing out of the way of restored directory. Use specific restore with ID to restore this object.", rLocalDirectoryName.c_str());
+ BOX_WARNING("File present with name '" <<
+ rLocalDirectoryName << "', removing " <<
+ "out of the way of restored directory. "
+ "Use specific restore with ID to "
+ "restore this object.");
if(::unlink(rLocalDirectoryName.c_str()) != 0)
{
- THROW_EXCEPTION(CommonException, OSFileError);
+ BOX_ERROR("Failed to delete file " <<
+ rLocalDirectoryName << ": " <<
+ strerror(errno));
+ return Restore_UnknownError;
}
- TRACE1("In restore, directory name collision with file %s", rLocalDirectoryName.c_str());
+ BOX_TRACE("In restore, directory name "
+ "collision with file " <<
+ rLocalDirectoryName);
}
- // follow through to... (no break)
+ break;
case ObjectExists_NoObject:
- if(::mkdir(rLocalDirectoryName.c_str(), S_IRWXU) != 0)
- {
- THROW_EXCEPTION(CommonException, OSFileError);
- }
+ // we'll create it in a second, after checking
+ // whether the parent directory exists
break;
default:
ASSERT(false);
break;
}
-
- // Fetch the directory listing from the server -- getting a list of files which is approparite to the restore type
+
+ std::string parentDirectoryName(rLocalDirectoryName);
+ if(parentDirectoryName[parentDirectoryName.size() - 1] ==
+ DIRECTORY_SEPARATOR_ASCHAR)
+ {
+ parentDirectoryName.resize(parentDirectoryName.size() - 1);
+ }
+
+ size_t lastSlash = parentDirectoryName.rfind(DIRECTORY_SEPARATOR_ASCHAR);
+
+ if(lastSlash == std::string::npos)
+ {
+ // might be a forward slash separator,
+ // especially in the unit tests!
+ lastSlash = parentDirectoryName.rfind('/');
+ }
+
+ if(lastSlash != std::string::npos)
+ {
+ // the target directory is a deep path, remove the last
+ // directory name and check that the resulting parent
+ // exists, otherwise the restore should fail.
+ parentDirectoryName.resize(lastSlash);
+
+ #ifdef WIN32
+ // if the path is a drive letter, then we need to
+ // add a a backslash to query the root directory.
+ if (lastSlash == 2 && parentDirectoryName[1] == ':')
+ {
+ parentDirectoryName += '\\';
+ }
+ else if (lastSlash == 0)
+ {
+ parentDirectoryName += '\\';
+ }
+ #endif
+
+ int parentExists;
+
+ try
+ {
+ parentExists = ObjectExists(parentDirectoryName.c_str());
+ }
+ catch (BoxException &e)
+ {
+ BOX_ERROR("Failed to check existence for " <<
+ parentDirectoryName << ": " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to check existence for " <<
+ parentDirectoryName << ": " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to check existence for " <<
+ parentDirectoryName << ": unknown error");
+ return Restore_UnknownError;
+ }
+
+ switch(parentExists)
+ {
+ case ObjectExists_Dir:
+ // this is fine, do nothing
+ break;
+
+ case ObjectExists_File:
+ BOX_ERROR("Failed to restore: '" <<
+ parentDirectoryName << "' "
+ "is a file, but should be a "
+ "directory.");
+ return Restore_TargetPathNotFound;
+
+ case ObjectExists_NoObject:
+ BOX_ERROR("Failed to restore: parent '" <<
+ parentDirectoryName << "' of target "
+ "directory does not exist.");
+ return Restore_TargetPathNotFound;
+
+ default:
+ BOX_ERROR("Failed to restore: unknown "
+ "result from ObjectExists('" <<
+ parentDirectoryName << "')");
+ return Restore_UnknownError;
+ }
+ }
+
+ if((exists == ObjectExists_NoObject ||
+ exists == ObjectExists_File) &&
+ ::mkdir(rLocalDirectoryName.c_str(), S_IRWXU) != 0)
+ {
+ BOX_ERROR("Failed to create directory '" <<
+ rLocalDirectoryName << "': " <<
+ strerror(errno));
+ return Restore_UnknownError;
+ }
+
+ // Save the restore info, in case it's needed later
+ try
+ {
+ Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to save resume info file '" <<
+ Params.mRestoreResumeInfoFilename << "': " <<
+ e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to save resume info file '" <<
+ Params.mRestoreResumeInfoFilename <<
+ "': unknown error");
+ 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),
@@ -269,7 +420,23 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
// Apply attributes to the directory
const StreamableMemBlock &dirAttrBlock(dir.GetAttributes());
BackupClientFileAttributes dirAttr(dirAttrBlock);
- dirAttr.WriteAttributes(rLocalDirectoryName.c_str());
+
+ try
+ {
+ dirAttr.WriteAttributes(rLocalDirectoryName.c_str(), true);
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to restore attributes for '" <<
+ rLocalDirectoryName << "': " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to restore attributes for '" <<
+ rLocalDirectoryName << "': unknown error");
+ return Restore_UnknownError;
+ }
int64_t bytesWrittenSinceLastRestoreInfoSave = 0;
@@ -287,7 +454,13 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
std::string localFilename(rLocalDirectoryName + DIRECTORY_SEPARATOR_ASCHAR + nm.GetClearFilename());
// Unlink anything which already exists -- for resuming restores, we can't overwrite files already there.
- ::unlink(localFilename.c_str());
+ if(::unlink(localFilename.c_str()) == 0)
+ {
+ BOX_ERROR("Failed to delete file '" <<
+ localFilename << "': " <<
+ strerror(errno));
+ return Restore_UnknownError;
+ }
// Request it from the store
rConnection.QueryGetFile(DirectoryID, en->GetObjectID());
@@ -297,17 +470,34 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
// Decode the file -- need to do different things depending on whether
// the directory entry has additional attributes
- if(en->HasAttributes())
+ try
{
- // Use these attributes
- const StreamableMemBlock &storeAttr(en->GetAttributes());
- BackupClientFileAttributes attr(storeAttr);
- BackupStoreFile::DecodeFile(*objectStream, localFilename.c_str(), rConnection.GetTimeout(), &attr);
+ if(en->HasAttributes())
+ {
+ // Use these attributes
+ const StreamableMemBlock &storeAttr(en->GetAttributes());
+ BackupClientFileAttributes attr(storeAttr);
+ BackupStoreFile::DecodeFile(*objectStream, localFilename.c_str(), rConnection.GetTimeout(), &attr);
+ }
+ else
+ {
+ // Use attributes stored in file
+ BackupStoreFile::DecodeFile(*objectStream, localFilename.c_str(), rConnection.GetTimeout());
+ }
}
- else
+ catch(std::exception &e)
{
- // Use attributes stored in file
- BackupStoreFile::DecodeFile(*objectStream, localFilename.c_str(), rConnection.GetTimeout());
+ BOX_ERROR("Failed to restore file '" <<
+ localFilename << "': " <<
+ e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to restore file '" <<
+ localFilename <<
+ "': unknown error");
+ return Restore_UnknownError;
}
// Progress display?
@@ -322,7 +512,34 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
// Save restore info?
int64_t fileSize;
- if(FileExists(localFilename.c_str(), &fileSize, true /* treat links as not existing */))
+ int exists;
+
+ try
+ {
+ exists = FileExists(
+ localFilename.c_str(),
+ &fileSize,
+ true /* treat links as not
+ existing */);
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to determine "
+ "whether file exists: '" <<
+ localFilename << "': " <<
+ e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to determine "
+ "whether file exists: '" <<
+ localFilename << "': "
+ "unknown error");
+ return Restore_UnknownError;
+ }
+
+ if(exists)
{
// File exists...
bytesWrittenSinceLastRestoreInfoSave += fileSize;
@@ -330,7 +547,25 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
if(bytesWrittenSinceLastRestoreInfoSave > MAX_BYTES_WRITTEN_BETWEEN_RESTORE_INFO_SAVES)
{
// Save the restore info, in case it's needed later
- Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
+ try
+ {
+ Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to save resume info file '" <<
+ Params.mRestoreResumeInfoFilename <<
+ "': " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to save resume info file '" <<
+ Params.mRestoreResumeInfoFilename <<
+ "': unknown error");
+ return Restore_UnknownError;
+ }
+
bytesWrittenSinceLastRestoreInfoSave = 0;
}
}
@@ -342,12 +577,31 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
if(bytesWrittenSinceLastRestoreInfoSave != 0)
{
// Save the restore info, in case it's needed later
- Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
+ try
+ {
+ Params.mResumeInfo.Save(
+ Params.mRestoreResumeInfoFilename);
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to save resume info file '" <<
+ Params.mRestoreResumeInfoFilename << "': " <<
+ e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to save resume info file '" <<
+ Params.mRestoreResumeInfoFilename <<
+ "': unknown error");
+ return Restore_UnknownError;
+ }
+
bytesWrittenSinceLastRestoreInfoSave = 0;
}
- // Recuse to directories
+ // Recurse to directories
{
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en = 0;
@@ -364,7 +618,14 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
RestoreResumeInfo &rnextLevel(rLevel.AddLevel(en->GetObjectID(), nm.GetClearFilename()));
// Recurse
- BackupClientRestoreDir(rConnection, en->GetObjectID(), localDirname, Params, rnextLevel);
+ int result = BackupClientRestoreDir(
+ rConnection, en->GetObjectID(),
+ localDirname, Params, rnextLevel);
+
+ if (result != Restore_Complete)
+ {
+ return result;
+ }
// Remove the level for the above call
rLevel.RemoveLevel();
@@ -373,7 +634,27 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
rLevel.mRestoredObjects.insert(en->GetObjectID());
}
}
- }
+ }
+
+ // now remove the user writable flag, if we added it earlier
+ try
+ {
+ dirAttr.WriteAttributes(rLocalDirectoryName.c_str(), false);
+ }
+ catch(std::exception &e)
+ {
+ BOX_ERROR("Failed to restore attributes for '" <<
+ rLocalDirectoryName << "': " << e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ BOX_ERROR("Failed to restore attributes for '" <<
+ rLocalDirectoryName << "': unknown error");
+ return Restore_UnknownError;
+ }
+
+ return Restore_Complete;
}
@@ -444,7 +725,12 @@ int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID,
// Restore the directory
std::string localName(LocalDirectoryName);
- BackupClientRestoreDir(rConnection, DirectoryID, localName, params, params.mResumeInfo);
+ int result = BackupClientRestoreDir(rConnection, DirectoryID,
+ localName, params, params.mResumeInfo);
+ if (result != Restore_Complete)
+ {
+ return result;
+ }
// Undelete the directory on the server?
if(RestoreDeleted && UndeleteAfterRestoreDeleted)
diff --git a/lib/backupclient/BackupClientRestore.h b/lib/backupclient/BackupClientRestore.h
index 4b382771..f7724030 100644
--- a/lib/backupclient/BackupClientRestore.h
+++ b/lib/backupclient/BackupClientRestore.h
@@ -16,7 +16,9 @@ enum
{
Restore_Complete = 0,
Restore_ResumePossible = 1,
- Restore_TargetExists = 2
+ Restore_TargetExists = 2,
+ Restore_TargetPathNotFound = 3,
+ Restore_UnknownError = 4,
};
int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, const char *LocalDirectoryName,
diff --git a/lib/backupclient/BackupDaemonConfigVerify.cpp b/lib/backupclient/BackupDaemonConfigVerify.cpp
index 89ad4d54..9000ec6d 100644
--- a/lib/backupclient/BackupDaemonConfigVerify.cpp
+++ b/lib/backupclient/BackupDaemonConfigVerify.cpp
@@ -81,7 +81,9 @@ static const ConfigurationVerifyKey verifyrootkeys[] =
{"FileTrackingSizeThreshold", 0, ConfigTest_Exists | ConfigTest_IsInt, 0},
{"DiffingUploadSizeThreshold", 0, ConfigTest_Exists | ConfigTest_IsInt, 0},
{"StoreHostname", 0, ConfigTest_Exists, 0},
- {"ExtendedLogging", "no", ConfigTest_IsBool, 0}, // make value "yes" to enable in config file
+ {"ExtendedLogging", "no", ConfigTest_IsBool, 0}, // extended log to syslog
+ {"ExtendedLogFile", NULL, 0, 0}, // extended log to a file
+ {"LogAllFileAccess", "no", ConfigTest_IsBool, 0},
{"CommandSocket", 0, 0, 0}, // not compulsory to have this
{"KeepAliveTime", 0, ConfigTest_IsInt, 0}, // optional
diff --git a/lib/backupclient/BackupStoreDirectory.cpp b/lib/backupclient/BackupStoreDirectory.cpp
index 61e6461d..0d06da34 100644
--- a/lib/backupclient/BackupStoreDirectory.cpp
+++ b/lib/backupclient/BackupStoreDirectory.cpp
@@ -149,6 +149,11 @@ void BackupStoreDirectory::ReadFromStream(IOStream &rStream, int Timeout)
int count = ntohl(hdr.mNumEntries);
// Clear existing list
+ for(std::vector<Entry*>::iterator i = mEntries.begin();
+ i != mEntries.end(); i++)
+ {
+ delete (*i);
+ }
mEntries.clear();
// Read them in!
diff --git a/lib/backupclient/BackupStoreFile.cpp b/lib/backupclient/BackupStoreFile.cpp
index 278bf50a..7e93d59d 100644
--- a/lib/backupclient/BackupStoreFile.cpp
+++ b/lib/backupclient/BackupStoreFile.cpp
@@ -17,10 +17,8 @@
#include <string.h>
#include <new>
#include <string.h>
+
#ifndef BOX_DISABLE_BACKWARDS_COMPATIBILITY_BACKUPSTOREFILE
- #ifndef WIN32
- #include <syslog.h>
- #endif
#include <stdio.h>
#endif
@@ -46,6 +44,7 @@
#include "ReadGatherStream.h"
#include "Random.h"
#include "BackupStoreFileEncodeStream.h"
+#include "Logging.h"
#include "MemLeakFindOn.h"
@@ -291,6 +290,20 @@ void BackupStoreFile::DecodeFile(IOStream &rEncodedFile, const char *DecodedFile
}
out.Close();
+
+ // The stream might have uncertain size, in which case
+ // we need to drain it to get the
+ // Protocol::ProtocolStreamHeader_EndOfStream byte
+ // out of our connection stream.
+ char buffer[1];
+ int drained = rEncodedFile.Read(buffer, 1);
+
+ // The Read will return 0 if we are actually at the end
+ // of the stream, but some tests decode files directly,
+ // in which case we are actually positioned at the start
+ // of the block index. I hope that reading an extra byte
+ // doesn't hurt!
+ // ASSERT(drained == 0);
// Write the attributes
stream->GetAttributes().WriteAttributes(DecodedFilename);
@@ -743,8 +756,7 @@ int BackupStoreFile::DecodedStream::Read(void *pBuffer, int NBytes, int Timeout)
// Warn and log this issue
if(!sWarnedAboutBackwardsCompatiblity)
{
- ::printf("WARNING: Decoded one or more files using backwards compatibility mode for block index.\n");
- ::syslog(LOG_ERR, "WARNING: Decoded one or more files using backwards compatibility mode for block index.\n");
+ BOX_WARNING("WARNING: Decoded one or more files using backwards compatibility mode for block index.");
sWarnedAboutBackwardsCompatiblity = true;
}
}
@@ -1485,9 +1497,8 @@ void BackupStoreFile::EncodingBuffer::Allocate(int Size)
// --------------------------------------------------------------------------
void BackupStoreFile::EncodingBuffer::Reallocate(int NewSize)
{
-#ifndef WIN32
- TRACE2("Reallocating EncodingBuffer from %d to %d\n", mBufferSize, NewSize);
-#endif
+ BOX_TRACE("Reallocating EncodingBuffer from " << mBufferSize <<
+ " to " << NewSize);
ASSERT(mpBuffer != 0);
uint8_t *buffer = (uint8_t*)BackupStoreFile::CodingChunkAlloc(NewSize);
if(buffer == 0)
diff --git a/lib/backupclient/BackupStoreFile.h b/lib/backupclient/BackupStoreFile.h
index 437b4232..3ee5ddb0 100644
--- a/lib/backupclient/BackupStoreFile.h
+++ b/lib/backupclient/BackupStoreFile.h
@@ -50,17 +50,16 @@ public:
DiffTimer();
virtual ~DiffTimer();
public:
- virtual void DoKeepAlive() = 0;
- virtual time_t GetTimeMgmtEpoch() = 0;
- virtual int GetMaximumDiffingTime() = 0;
- virtual int GetKeepaliveTime() = 0;
+ virtual void DoKeepAlive() = 0;
+ virtual int GetMaximumDiffingTime() = 0;
+ virtual bool IsManaged() = 0;
};
// --------------------------------------------------------------------------
//
// Class
// Name: BackupStoreFile
-// Purpose: Class to hold together utils for maniplating files.
+// Purpose: Class to hold together utils for manipulating files.
// Created: 2003/08/28
//
// --------------------------------------------------------------------------
diff --git a/lib/backupclient/BackupStoreFileDiff.cpp b/lib/backupclient/BackupStoreFileDiff.cpp
index ee09f1c8..3a3f1a5e 100644
--- a/lib/backupclient/BackupStoreFileDiff.cpp
+++ b/lib/backupclient/BackupStoreFileDiff.cpp
@@ -29,6 +29,7 @@
#include "RollingChecksum.h"
#include "MD5Digest.h"
#include "CommonException.h"
+#include "Timer.h"
#include "MemLeakFindOn.h"
@@ -52,31 +53,6 @@ static bool SecondStageMatch(BlocksAvailableEntry *pFirstInHashList, RollingChec
BlocksAvailableEntry *pIndex, std::map<int64_t, int64_t> &rFoundBlocks);
static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksAvailableEntry *pIndex, int64_t NumBlocks, std::map<int64_t, int64_t> &rFoundBlocks, int64_t SizeOfInputFile);
-// sDiffTimerExpired flags when the diff timer has expired. When true, the
-// diff routine should check the wall clock as soon as possible, to determine
-// whether it's time for a keepalive to be sent, or whether the diff has been
-// running for too long and should be terminated.
-static bool sDiffTimerExpired = false;
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreFile::DiffTimerExpired()
-// Purpose: Notifies BackupStoreFile object that the diff operation
-// timer has expired, which may mean that a keepalive should
-// be sent, or the diff should be terminated. Called from an
-// external timer, so it should not do more than set a flag.
-//
-// Created: 19/1/06
-//
-// --------------------------------------------------------------------------
-void BackupStoreFile::DiffTimerExpired()
-{
- sDiffTimerExpired = true;
-}
-
-
// --------------------------------------------------------------------------
//
// Function
@@ -483,15 +459,11 @@ 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)
{
- time_t TimeMgmtEpoch = 0;
- int MaximumDiffingTime = 0;
- int KeepAliveTime = 0;
+ Timer maximumDiffingTime(0);
- if (pDiffTimer)
+ if(pDiffTimer && pDiffTimer->IsManaged())
{
- TimeMgmtEpoch = pDiffTimer->GetTimeMgmtEpoch();
- MaximumDiffingTime = pDiffTimer->GetMaximumDiffingTime();
- KeepAliveTime = pDiffTimer->GetKeepaliveTime();
+ maximumDiffingTime = Timer(pDiffTimer->GetMaximumDiffingTime());
}
std::map<int64_t, int32_t> goodnessOfFit;
@@ -577,31 +549,20 @@ static void SearchForMatchingBlocks(IOStream &rFile, std::map<int64_t, int64_t>
int rollOverInitialBytes = 0;
while(true)
{
- if(sDiffTimerExpired)
+ if(maximumDiffingTime.HasExpired())
{
- ASSERT(TimeMgmtEpoch > 0);
ASSERT(pDiffTimer != NULL);
-
- time_t tTotalRunIntvl = time(NULL) - TimeMgmtEpoch;
-
- if(MaximumDiffingTime > 0 &&
- tTotalRunIntvl >= MaximumDiffingTime)
- {
- TRACE0("MaximumDiffingTime reached - "
- "suspending file diff\n");
- abortSearch = true;
- break;
- }
- else if(KeepAliveTime > 0)
- {
- TRACE0("KeepAliveTime reached - "
- "initiating keep-alive\n");
- pDiffTimer->DoKeepAlive();
- }
-
- sDiffTimerExpired = false;
+ TRACE0("MaximumDiffingTime reached - "
+ "suspending file diff\n");
+ abortSearch = true;
+ break;
}
-
+
+ if(pDiffTimer)
+ {
+ pDiffTimer->DoKeepAlive();
+ }
+
// Load in another block of data, and record how big it is
int bytesInEndings = rFile.Read(endings, Sizes[s]);
int tmp;
diff --git a/lib/backupclient/BackupStoreFileEncodeStream.cpp b/lib/backupclient/BackupStoreFileEncodeStream.cpp
index c692f18e..423c11a3 100644
--- a/lib/backupclient/BackupStoreFileEncodeStream.cpp
+++ b/lib/backupclient/BackupStoreFileEncodeStream.cpp
@@ -38,6 +38,7 @@ using namespace BackupStoreFileCryptVar;
BackupStoreFileEncodeStream::BackupStoreFileEncodeStream()
: mpRecipe(0),
mpFile(0),
+ mpLogging(0),
mStatus(Status_Header),
mSendData(true),
mTotalBlocks(0),
@@ -79,6 +80,13 @@ BackupStoreFileEncodeStream::~BackupStoreFileEncodeStream()
mpFile = 0;
}
+ // Clear up logging stream
+ if(mpLogging)
+ {
+ delete mpLogging;
+ mpLogging = 0;
+ }
+
// Free the recipe
if(mpRecipe != 0)
{
@@ -199,6 +207,9 @@ void BackupStoreFileEncodeStream::Setup(const char *Filename, BackupStoreFileEnc
{
// Open the file
mpFile = new FileStream(Filename);
+
+ // Create logging stream
+ mpLogging = new ReadLoggingStream(*mpFile);
// Work out the largest possible block required for the encoded data
mAllocatedBufferSize = BackupStoreFile::MaxBlockSizeForChunkSize(maxBlockClearSize);
@@ -267,7 +278,7 @@ void BackupStoreFileEncodeStream::CalculateBlockSizes(int64_t DataSize, int64_t
rNumBlocksOut = (DataSize + rBlockSizeOut - 1) / rBlockSizeOut;
- } while(rBlockSizeOut <= BACKUP_FILE_MAX_BLOCK_SIZE && rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER);
+ } while(rBlockSizeOut < BACKUP_FILE_MAX_BLOCK_SIZE && rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER);
// Last block size
rLastBlockSizeOut = DataSize - ((rNumBlocksOut - 1) * rBlockSizeOut);
@@ -474,7 +485,7 @@ void BackupStoreFileEncodeStream::SkipPreviousBlocksInInstruction()
}
// Move forward in the stream
- mpFile->Seek(sizeToSkip, IOStream::SeekType_Relative);
+ mpLogging->Seek(sizeToSkip, IOStream::SeekType_Relative);
}
@@ -518,14 +529,14 @@ void BackupStoreFileEncodeStream::EncodeCurrentBlock()
ASSERT(blockRawSize < mAllocatedBufferSize);
// Check file open
- if(mpFile == 0)
+ if(mpFile == 0 || mpLogging == 0)
{
// File should be open, but isn't. So logical error.
THROW_EXCEPTION(BackupStoreException, Internal)
}
// Read the data in
- if(!mpFile->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
diff --git a/lib/backupclient/BackupStoreFileEncodeStream.h b/lib/backupclient/BackupStoreFileEncodeStream.h
index 1c748798..fb5d0851 100644
--- a/lib/backupclient/BackupStoreFileEncodeStream.h
+++ b/lib/backupclient/BackupStoreFileEncodeStream.h
@@ -17,6 +17,7 @@
#include "CollectInBufferStream.h"
#include "MD5Digest.h"
#include "BackupStoreFile.h"
+#include "ReadLoggingStream.h"
namespace BackupStoreFileCreation
{
@@ -100,6 +101,7 @@ private:
Recipe *mpRecipe;
IOStream *mpFile; // source file
CollectInBufferStream mData; // buffer for header and index entries
+ ReadLoggingStream *mpLogging;
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/BackupStoreFilenameClear.cpp b/lib/backupclient/BackupStoreFilenameClear.cpp
index c415b9bb..9114fdd1 100644
--- a/lib/backupclient/BackupStoreFilenameClear.cpp
+++ b/lib/backupclient/BackupStoreFilenameClear.cpp
@@ -13,6 +13,7 @@
#include "CipherContext.h"
#include "CipherBlowfish.h"
#include "Guards.h"
+#include "Logging.h"
#include "MemLeakFindOn.h"
@@ -203,9 +204,9 @@ static void EnsureEncDecBufferSize(int BufSize)
{
if(sEncDecBufferSize < BufSize)
{
-#ifndef WIN32
- TRACE2("Reallocating filename encoding/decoding buffer from %d to %d\n", sEncDecBufferSize, BufSize);
-#endif
+ BOX_TRACE("Reallocating filename encoding/decoding "
+ "buffer from " << sEncDecBufferSize <<
+ " to " << BufSize);
spEncDecBuffer->Resize(BufSize);
sEncDecBufferSize = BufSize;
MEMLEAKFINDER_NOT_A_LEAK(*spEncDecBuffer);