[Box Backup-dev] COMMIT r710 - in box/chris/merge: . bin/bbackupctl bin/bbackupd bin/bbackupquery bin/bbstored docs/backup infrastructure infrastructure/msvc/2003 lib/backupclient lib/backupstore lib/common lib/raidfile lib/server test/backupdiff test/backupstore test/backupstorefix/testfiles test/backupstorepatch test/basicserver test/bbackupd test/bbackupd/testfiles test/common test/raidfile test/win32
boxbackup-dev at fluffy.co.uk
boxbackup-dev at fluffy.co.uk
Fri Jul 28 00:19:12 BST 2006
Author: chris
Date: 2006-07-27 23:18:35 +0000 (Thu, 27 Jul 2006)
New Revision: 710
Added:
box/chris/merge/test/bbackupd/testfiles/bbackupd.conf.in
Removed:
box/chris/merge/infrastructure/msvc/2003/boxbackup.ncb
box/chris/merge/infrastructure/msvc/2003/boxbackup.suo
box/chris/merge/test/bbackupd/testfiles/bbackupd.conf
Modified:
box/chris/merge/bin/bbackupctl/bbackupctl.cpp
box/chris/merge/bin/bbackupd/BackupClientContext.cpp
box/chris/merge/bin/bbackupd/BackupClientDirectoryRecord.cpp
box/chris/merge/bin/bbackupd/BackupDaemon.cpp
box/chris/merge/bin/bbackupd/BackupDaemon.h
box/chris/merge/bin/bbackupd/Win32BackupService.cpp
box/chris/merge/bin/bbackupd/Win32BackupService.h
box/chris/merge/bin/bbackupd/Win32ServiceFunctions.cpp
box/chris/merge/bin/bbackupd/Win32ServiceFunctions.h
box/chris/merge/bin/bbackupd/bbackupd.cpp
box/chris/merge/bin/bbackupquery/BackupQueries.cpp
box/chris/merge/bin/bbackupquery/BackupQueries.h
box/chris/merge/bin/bbackupquery/documentation.txt
box/chris/merge/bin/bbstored/BBStoreDHousekeeping.cpp
box/chris/merge/bin/bbstored/BackupCommands.cpp
box/chris/merge/bin/bbstored/BackupContext.cpp
box/chris/merge/bin/bbstored/BackupStoreDaemon.cpp
box/chris/merge/bin/bbstored/BackupStoreDaemon.h
box/chris/merge/bin/bbstored/HousekeepStoreAccount.cpp
box/chris/merge/configure.ac
box/chris/merge/docs/backup/win32_build_on_linux_using_mingw.txt
box/chris/merge/infrastructure/BoxPlatform.pm.in
box/chris/merge/infrastructure/buildenv-testmain-template.cpp
box/chris/merge/infrastructure/makebuildenv.pl.in
box/chris/merge/lib/backupclient/BackupClientFileAttributes.cpp
box/chris/merge/lib/backupclient/BackupStoreFile.cpp
box/chris/merge/lib/backupclient/BackupStoreObjectDump.cpp
box/chris/merge/lib/backupstore/BackupStoreAccounts.cpp
box/chris/merge/lib/backupstore/BackupStoreCheck.cpp
box/chris/merge/lib/common/BoxPlatform.h
box/chris/merge/lib/common/FdGetLine.h
box/chris/merge/lib/common/Guards.h
box/chris/merge/lib/common/UnixUser.cpp
box/chris/merge/lib/common/makeexception.pl.in
box/chris/merge/lib/raidfile/RaidFileRead.cpp
box/chris/merge/lib/raidfile/RaidFileWrite.cpp
box/chris/merge/lib/server/Daemon.cpp
box/chris/merge/lib/server/ServerStream.h
box/chris/merge/lib/server/SocketStream.cpp
box/chris/merge/lib/server/SocketStream.h
box/chris/merge/lib/server/SocketStreamTLS.cpp
box/chris/merge/lib/server/makeprotocol.pl.in
box/chris/merge/runtest.pl.in
box/chris/merge/test/backupdiff/testbackupdiff.cpp
box/chris/merge/test/backupstore/testbackupstore.cpp
box/chris/merge/test/backupstorefix/testfiles/testbackupstorefix.pl.in
box/chris/merge/test/backupstorepatch/testbackupstorepatch.cpp
box/chris/merge/test/basicserver/TestCommands.cpp
box/chris/merge/test/basicserver/testbasicserver.cpp
box/chris/merge/test/bbackupd/testbbackupd.cpp
box/chris/merge/test/bbackupd/testfiles/extcheck1.pl.in
box/chris/merge/test/bbackupd/testfiles/extcheck2.pl.in
box/chris/merge/test/common/testcommon.cpp
box/chris/merge/test/raidfile/intercept.cpp
box/chris/merge/test/raidfile/testraidfile.cpp
box/chris/merge/test/win32/testlibwin32.cpp
box/chris/merge/win32.bat
Log:
* merge
- This is my current patch queue. I think that all of these are safe
to apply. This is just under half of the pending changes in
chris/general (the easy half).
Modified: box/chris/merge/bin/bbackupctl/bbackupctl.cpp
===================================================================
--- box/chris/merge/bin/bbackupctl/bbackupctl.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupctl/bbackupctl.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -32,12 +32,14 @@
{
printf("Usage: bbackupctl [-q] [-c config_file] <command>\n"
"Commands are:\n"
- " sync -- start a syncronisation run now\n"
- " force-sync -- force the start of a syncronisation run, "
+ " sync -- start a synchronisation (backup) run now\n"
+ " force-sync -- force the start of a synchronisation run, "
"even if SyncAllowScript says no\n"
" reload -- reload daemon configuration\n"
" terminate -- terminate daemon now\n"
" wait-for-sync -- wait until the next sync starts, then exit\n"
+ " wait-for-end -- wait until the next sync finishes, then exit\n"
+ " sync-and-wait -- start sync, wait until it finishes, then exit\n"
);
exit(1);
}
@@ -107,7 +109,10 @@
// Check there's a socket defined in the config file
if(!conf.KeyExists("CommandSocket"))
{
- printf("Daemon isn't using a control socket, could not execute command.\nAdd a CommandSocket declaration to the bbackupd.conf file.\n");
+ printf("Daemon isn't using a control socket, "
+ "could not execute command.\n"
+ "Add a CommandSocket declaration to the "
+ "bbackupd.conf file.\n");
return 1;
}
@@ -188,28 +193,75 @@
// Print summary?
if(!quiet)
{
- printf("Daemon configuration summary:\n" \
- " AutomaticBackup = %s\n" \
- " UpdateStoreInterval = %d seconds\n" \
- " MinimumFileAge = %d seconds\n" \
- " MaxUploadWait = %d seconds\n",
- autoBackup?"true":"false", updateStoreInterval, minimumFileAge, maxUploadWait);
+ printf("Daemon configuration summary:\n"
+ " AutomaticBackup = %s\n"
+ " UpdateStoreInterval = %d seconds\n"
+ " MinimumFileAge = %d seconds\n"
+ " MaxUploadWait = %d seconds\n",
+ autoBackup?"true":"false", updateStoreInterval,
+ minimumFileAge, maxUploadWait);
}
+ std::string stateLine;
+ if(!getLine.GetLine(stateLine) || getLine.IsEOF())
+ {
+#if defined WIN32 && ! defined NDEBUG
+ syslog(LOG_ERR, "Failed to receive state line from daemon");
+#else
+ printf("Failed to receive state line from daemon\n");
+#endif
+ return 1;
+ }
+
+ // Decode it
+ int currentState;
+ if(::sscanf(stateLine.c_str(), "state %d", ¤tState) != 1)
+ {
+ printf("State line didn't decode\n");
+ return 1;
+ }
+
// Is the command the "wait for sync to start" command?
bool areWaitingForSync = false;
- if(::strcmp(argv[0], "wait-for-sync") == 0)
+ bool areWaitingForSyncEnd = false;
+
+ if(::strcmp(argv[0], "wait-for-sync") == 0 ||
+ ::strcmp(argv[0], "wait-for-end") == 0)
{
- // Check that it's not in non-automatic mode, because then it'll never start
+ // Check that it's not in non-automatic mode,
+ // because then it'll never start
if(!autoBackup)
{
- printf("ERROR: Daemon is not in automatic mode -- sync will never start!\n");
+ printf("ERROR: Daemon is not in automatic mode -- "
+ "sync will never start!\n");
return 1;
}
- // Yes... set the flag so we know what we're waiting for a sync to start
- areWaitingForSync = true;
+ // Yes... set the flag so we know that
+ // we're waiting for a sync to start/end
+ if(::strcmp(argv[0], "wait-for-sync") == 0)
+ {
+ areWaitingForSync = true;
+ }
+ else if (::strcmp(argv[0], "wait-for-end") == 0)
+ {
+ areWaitingForSyncEnd = true;
+ }
}
+ else if (::strcmp(argv[0], "sync-and-wait") == 0)
+ {
+ // send a sync command
+ std::string cmd("force-sync\n");
+ connection.Write(cmd.c_str(), cmd.size());
+ connection.WriteAllBuffered();
+ areWaitingForSyncEnd = true;
+
+ if (currentState != 0)
+ {
+ printf("Waiting for current sync/error state "
+ "to finish...\n");
+ }
+ }
else
{
// No? Just send the command given plus a quit command.
@@ -220,6 +272,8 @@
// Read the response
std::string line;
+ bool syncIsRunning = false;
+
while(!getLine.IsEOF() && getLine.GetLine(line))
{
if(areWaitingForSync)
@@ -234,6 +288,28 @@
break;
}
}
+ else if(areWaitingForSyncEnd)
+ {
+ if(line == "start-sync")
+ {
+ if (!quiet) printf("Sync started...\n");
+ syncIsRunning = true;
+ }
+ else if(line == "finish-sync" && syncIsRunning)
+ {
+ if (!quiet) printf("Sync finished.\n");
+ // Send a quit command to finish nicely
+ connection.Write("quit\n", 5);
+
+ // And we're done
+ break;
+ }
+ else if(line == "finish-sync")
+ {
+ if (!quiet) printf("Previous sync finished.\n");
+ }
+ // daemon must still be busy
+ }
else
{
// Is this an OK or error line?
Modified: box/chris/merge/bin/bbackupd/BackupClientContext.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/BackupClientContext.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/BackupClientContext.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -176,7 +176,7 @@
// no -- flag so only things like deletions happen
mStorageLimitExceeded = true;
// Log
- ::syslog(LOG_INFO, "Exceeded storage limits on server -- not uploading changes to files");
+ ::syslog(LOG_WARNING, "Exceeded storage limits on server -- not uploading changes to files");
}
}
catch(...)
Modified: box/chris/merge/bin/bbackupd/BackupClientDirectoryRecord.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/BackupClientDirectoryRecord.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/BackupClientDirectoryRecord.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -645,35 +645,76 @@
// Need to update?
//
// Condition for upload:
- // modifiction time within sync period
+ // modification time within sync period
// if it's been seen before but not uploaded, is the time from this first sight longer than the MaxUploadWait
// and if we know about it from a directory listing, that it hasn't got the same upload time as on the store
- if(
- (
- // Check the file modified within the acceptable time period we're checking
- // If the file isn't on the server, the acceptable time starts at zero.
- // Check pDirOnStore and en, because if we didn't download a directory listing,
- // pDirOnStore will be zero, but we know it's on the server.
- ( ((pDirOnStore != 0 && en == 0) || (modTime >= rParams.mSyncPeriodStart)) && modTime < rParams.mSyncPeriodEnd)
- // However, just in case things are continually modified, we check the first seen time.
- // The two compares of syncPeriodEnd and pendingFirstSeenTime are because the values are unsigned.
- || (pendingFirstSeenTime != 0 &&
- (rParams.mSyncPeriodEnd > pendingFirstSeenTime)
- && ((rParams.mSyncPeriodEnd - pendingFirstSeenTime) > rParams.mMaxUploadWait))
+ bool doUpload = false;
- // Then make sure that if files are added with a time less than the sync period start
- // (which can easily happen on file server), it gets uploaded. The directory contents checksum
- // will pick up the fact it has been added, so the store listing will be available when this happens.
- || ((modTime <= rParams.mSyncPeriodStart) && (en != 0) && (en->GetModificationTime() != modTime))
-
- // And just to catch really badly off clocks in the future for file server clients,
- // just upload the file if it's madly in the future.
- || (modTime > rParams.mUploadAfterThisTimeInTheFuture)
- )
- // But even then, only upload it if the mod time locally is different to that on the server.
- && (en == 0 || en->GetModificationTime() != modTime))
+ // Only upload a file if the mod time locally is
+ // different to that on the server.
+
+ if (en == 0 || en->GetModificationTime() != modTime)
{
+ // Check the file modified within the acceptable time period we're checking
+ // If the file isn't on the server, the acceptable time starts at zero.
+ // Check pDirOnStore and en, because if we didn't download a directory listing,
+ // pDirOnStore will be zero, but we know it's on the server.
+ if (modTime < rParams.mSyncPeriodEnd)
+ {
+ if (pDirOnStore != 0 && en == 0)
+ {
+ doUpload = true;
+ }
+ else if (modTime >= rParams.mSyncPeriodStart)
+ {
+ doUpload = true;
+ }
+ }
+
+ // However, just in case things are continually
+ // modified, we check the first seen time.
+ // The two compares of syncPeriodEnd and
+ // pendingFirstSeenTime are because the values
+ // are unsigned.
+
+ if (!doUpload &&
+ pendingFirstSeenTime != 0 &&
+ rParams.mSyncPeriodEnd > pendingFirstSeenTime &&
+ (rParams.mSyncPeriodEnd - pendingFirstSeenTime)
+ > rParams.mMaxUploadWait)
+ {
+ doUpload = true;
+ }
+
+ // Then make sure that if files are added with a
+ // time less than the sync period start
+ // (which can easily happen on file server), it
+ // gets uploaded. The directory contents checksum
+ // will pick up the fact it has been added, so the
+ // store listing will be available when this happens.
+
+ if (!doUpload &&
+ modTime <= rParams.mSyncPeriodStart &&
+ en != 0 &&
+ en->GetModificationTime() != modTime)
+ {
+ doUpload = true;
+ }
+
+ // And just to catch really badly off clocks in
+ // the future for file server clients,
+ // just upload the file if it's madly in the future.
+
+ if (!doUpload && modTime >
+ rParams.mUploadAfterThisTimeInTheFuture)
+ {
+ doUpload = true;
+ }
+ }
+
+ if (doUpload)
+ {
// Make sure we're connected -- must connect here so we know whether
// the storage limit has been exceeded, and hence whether or not
// to actually upload the file.
@@ -1022,7 +1063,10 @@
BackupClientDirectoryRecord *rec = e->second;
mSubDirectories.erase(e);
delete rec;
- TRACE2("Deleted directory record for %s/%s\n", rLocalPath.c_str(), dirname.GetClearFilename().c_str());
+ TRACE2("Deleted directory record for "
+ "%s" DIRECTORY_SEPARATOR "%s\n",
+ rLocalPath.c_str(),
+ dirname.GetClearFilename().c_str());
}
}
}
Modified: box/chris/merge/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/BackupDaemon.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/BackupDaemon.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -125,6 +125,29 @@
}
#ifdef WIN32
+ // Create the event object to signal from main thread to worker
+ // when new messages are queued to be sent to the command socket.
+ mhMessageToSendEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (mhMessageToSendEvent == INVALID_HANDLE_VALUE)
+ {
+ syslog(LOG_ERR, "Failed to create event object: error %d",
+ GetLastError);
+ exit(1);
+ }
+
+ // Create the event object to signal from worker to main thread
+ // when a command has been received on the command socket.
+ mhCommandReceivedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (mhCommandReceivedEvent == INVALID_HANDLE_VALUE)
+ {
+ syslog(LOG_ERR, "Failed to create event object: error %d",
+ GetLastError);
+ exit(1);
+ }
+
+ // Create the critical section to protect the message queue
+ InitializeCriticalSection(&mMessageQueueLock);
+
// Create a thread to handle the named pipe
HANDLE hThread;
unsigned int dwThreadId;
@@ -263,16 +286,35 @@
void BackupDaemon::RunHelperThread(void)
{
mpCommandSocketInfo = new CommandSocketInfo;
- this->mReceivedCommandConn = false;
+ WinNamedPipeStream& rSocket(mpCommandSocketInfo->mListeningSocket);
// loop until the parent process exits
- while (TRUE)
+ while (!IsTerminateWanted())
{
try
{
- mpCommandSocketInfo->mListeningSocket.Accept(
- BOX_NAMED_PIPE_NAME);
+ rSocket.Accept(BOX_NAMED_PIPE_NAME);
+ }
+ catch (BoxException &e)
+ {
+ ::syslog(LOG_ERR, "Failed to open command socket: %s",
+ e.what());
+ SetTerminateWanted();
+ break; // this is fatal
+ }
+ catch (...)
+ {
+ ::syslog(LOG_ERR, "Failed to open command socket: "
+ "unknown error");
+ SetTerminateWanted();
+ break; // this is fatal
+ }
+ try
+ {
+ // Errors here do not kill the thread,
+ // only the current connection.
+
// This next section comes from Ben's original function
// Log
::syslog(LOG_INFO, "Connection from command socket");
@@ -289,18 +331,73 @@
conf.GetKeyValueInt("MaxUploadWait"),
mState);
- mpCommandSocketInfo->mListeningSocket.Write(summary, summarySize);
- mpCommandSocketInfo->mListeningSocket.Write("ping\n", 5);
+ rSocket.Write(summary, summarySize);
+ rSocket.Write("ping\n", 5);
- IOStreamGetLine readLine(mpCommandSocketInfo->mListeningSocket);
+ // old queued messages are not useful
+ EnterCriticalSection(&mMessageQueueLock);
+ mMessageList.clear();
+ ResetEvent(mhMessageToSendEvent);
+ LeaveCriticalSection(&mMessageQueueLock);
+
+ IOStreamGetLine readLine(rSocket);
std::string command;
- while (mpCommandSocketInfo->mListeningSocket.IsConnected() &&
- readLine.GetLine(command) )
+ while (rSocket.IsConnected() && !IsTerminateWanted())
{
- TRACE1("Receiving command '%s' over "
- "command socket\n", command.c_str());
+ HANDLE handles[2];
+ handles[0] = mhMessageToSendEvent;
+ handles[1] = rSocket.GetReadableEvent();
+ DWORD result = WaitForMultipleObjects(
+ sizeof(handles)/sizeof(*handles),
+ handles, FALSE, 1000);
+
+ if (result == 0)
+ {
+ ResetEvent(mhMessageToSendEvent);
+
+ EnterCriticalSection(&mMessageQueueLock);
+ try
+ {
+ while (mMessageList.size() > 0)
+ {
+ std::string message = *(mMessageList.begin());
+ mMessageList.erase(mMessageList.begin());
+ printf("Sending '%s' to waiting client... ", message.c_str());
+ message += "\n";
+ rSocket.Write(message.c_str(),
+ message.length());
+
+ printf("done.\n");
+ }
+ }
+ catch (...)
+ {
+ LeaveCriticalSection(&mMessageQueueLock);
+ throw;
+ }
+ LeaveCriticalSection(&mMessageQueueLock);
+ continue;
+ }
+ else if (result == WAIT_TIMEOUT)
+ {
+ continue;
+ }
+ else if (result != 1)
+ {
+ ::syslog(LOG_ERR, "WaitForMultipleObjects returned invalid result %d", result);
+ continue;
+ }
+
+ if (!readLine.GetLine(command))
+ {
+ ::syslog(LOG_ERR, "Failed to read line");
+ continue;
+ }
+
+ printf("Received command '%s' from client\n", command.c_str());
+
bool sendOK = false;
bool sendResponse = true;
bool disconnect = false;
@@ -338,12 +435,18 @@
SetTerminateWanted();
sendOK = true;
}
+ else
+ {
+ ::syslog(LOG_ERR, "Received unknown command '%s' from client", command.c_str());
+ sendResponse = true;
+ sendOK = false;
+ }
// Send a response back?
if (sendResponse)
{
const char* response = sendOK ? "ok\n" : "error\n";
- mpCommandSocketInfo->mListeningSocket.Write(
+ rSocket.Write(
response, strlen(response));
}
@@ -352,10 +455,10 @@
break;
}
- this->mReceivedCommandConn = true;
+ // this->mReceivedCommandConn = true;
}
- mpCommandSocketInfo->mListeningSocket.Close();
+ rSocket.Close();
}
catch (BoxException &e)
{
@@ -504,8 +607,8 @@
BackupClientContext::ClientStoreMarker_NotKnown;
// haven't contacted the store yet
- bool deserialised = DeserializeStoreObjectInfo(clientStoreMarker,
- lastSyncTime, nextSyncTime);
+ bool deleteStoreObjectInfoFile = DeserializeStoreObjectInfo(
+ clientStoreMarker, lastSyncTime, nextSyncTime);
// --------------------------------------------------------------------------------------------
@@ -611,7 +714,8 @@
// Delete the serialised store object file,
// so that we don't try to reload it after a
// partially completed backup
- if(deserialised && !DeleteStoreObjectInfo())
+ if(deleteStoreObjectInfoFile &&
+ !DeleteStoreObjectInfo())
{
::syslog(LOG_ERR, "Failed to delete the "
"StoreObjectInfoFile, backup cannot "
@@ -621,6 +725,11 @@
::sleep(60);
continue;
}
+
+ // In case the backup throws an exception,
+ // we should not try to delete the store info
+ // object file again.
+ deleteStoreObjectInfoFile = false;
// Do sync
bool errorOccurred = false;
@@ -729,9 +838,15 @@
// --------------------------------------------------------------------------------------------
- // We had a successful backup, save the store info
- SerializeStoreObjectInfo(clientStoreMarker, lastSyncTime, nextSyncTime);
+ // We had a successful backup, save the store
+ // info. If we save successfully, we must
+ // delete the file next time we start a backup
+ deleteStoreObjectInfoFile =
+ SerializeStoreObjectInfo(
+ clientStoreMarker,
+ lastSyncTime, nextSyncTime);
+
// --------------------------------------------------------------------------------------------
}
catch(BoxException &e)
@@ -902,25 +1017,27 @@
void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFlagOut, bool &SyncIsForcedOut)
{
#ifdef WIN32
- // Really could use some interprocess protection, mutex etc
- // any side effect should be too bad???? :)
- DWORD timeout = (DWORD)BoxTimeToMilliSeconds(RequiredDelay);
+ DWORD requiredDelayMs = BoxTimeToMilliSeconds(RequiredDelay);
- while ( this->mReceivedCommandConn == false )
+ DWORD result = WaitForSingleObject(mhCommandReceivedEvent,
+ (DWORD)requiredDelayMs);
+
+ if (result == WAIT_OBJECT_0)
{
- Sleep(1);
-
- if ( timeout == 0 )
- {
- DoSyncFlagOut = false;
- SyncIsForcedOut = false;
- return;
- }
- timeout--;
+ DoSyncFlagOut = this->mDoSyncFlagOut;
+ SyncIsForcedOut = this->mSyncIsForcedOut;
+ ResetEvent(mhCommandReceivedEvent);
}
- this->mReceivedCommandConn = false;
- DoSyncFlagOut = this->mDoSyncFlagOut;
- SyncIsForcedOut = this->mSyncIsForcedOut;
+ else if (result == WAIT_TIMEOUT)
+ {
+ DoSyncFlagOut = false;
+ SyncIsForcedOut = false;
+ }
+ else
+ {
+ ::syslog(LOG_ERR, "Unexpected result from "
+ "WaitForSingleObject: error %d", GetLastError());
+ }
return;
#else // ! WIN32
@@ -953,7 +1070,7 @@
{
#ifdef PLATFORM_CANNOT_FIND_PEER_UID_OF_UNIX_SOCKET
bool uidOK = true;
- ::syslog(LOG_WARNING, "On this platform, no security check can be made on the credientials of peers connecting to the command socket. (bbackupctl)");
+ ::syslog(LOG_WARNING, "On this platform, no security check can be made on the credentials of peers connecting to the command socket. (bbackupctl)");
#else
// Security check -- does the process connecting to this socket have
// the same UID as this process?
@@ -1023,8 +1140,13 @@
while(mpCommandSocketInfo->mpGetLine != 0 && !mpCommandSocketInfo->mpGetLine->IsEOF()
&& mpCommandSocketInfo->mpGetLine->GetLine(command, false /* no preprocessing */, timeout))
{
- TRACE1("Receiving command '%s' over command socket\n", command.c_str());
-
+ TRACE1("Receiving command '%s' over command socket\n",
+ command.c_str());
+
+ #ifdef WIN32
+ SetEvent(mhCommandReceivedEvent);
+ #endif
+
bool sendOK = false;
bool sendResponse = true;
@@ -1137,13 +1259,9 @@
// --------------------------------------------------------------------------
void BackupDaemon::SendSyncStartOrFinish(bool SendStart)
{
- // The bbackupctl program can't rely on a state change, because it may never
- // change if the server doesn't need to be contacted.
+ // The bbackupctl program can't rely on a state change, because it
+ // may never change if the server doesn't need to be contacted.
-#ifdef __MINGW32__
-#warning race condition: what happens if socket is closed?
-#endif
-
if (mpCommandSocketInfo != NULL &&
#ifdef WIN32
mpCommandSocketInfo->mListeningSocket.IsConnected()
@@ -1152,15 +1270,18 @@
#endif
)
{
- const char* message = SendStart ? "start-sync\n" : "finish-sync\n";
+ std::string message = SendStart ? "start-sync" : "finish-sync";
try
{
#ifdef WIN32
- mpCommandSocketInfo->mListeningSocket.Write(message,
- (int)strlen(message));
+ EnterCriticalSection(&mMessageQueueLock);
+ mMessageList.push_back(message);
+ SetEvent(mhMessageToSendEvent);
+ LeaveCriticalSection(&mMessageQueueLock);
#else
- mpCommandSocketInfo->mpConnectedSocket->Write(message,
- strlen(message));
+ message += "\n";
+ mpCommandSocketInfo->mpConnectedSocket->Write(
+ message.c_str(), message.size());
#endif
}
catch(...)
@@ -1756,40 +1877,37 @@
// command socket if there's an error
char newState[64];
- char newStateSize = sprintf(newState, "state %d\n", State);
+ sprintf(newState, "state %d", State);
+ std::string message = newState;
#ifdef WIN32
- #ifndef _MSC_VER
- #warning FIX ME: race condition
- #endif
+ EnterCriticalSection(&mMessageQueueLock);
+ mMessageList.push_back(newState);
+ SetEvent(mhMessageToSendEvent);
+ LeaveCriticalSection(&mMessageQueueLock);
+#else
+ message += "\n";
- // what happens if the socket is closed by the other thread before
- // we can write to it? Null pointer deref at best.
- if (mpCommandSocketInfo &&
- mpCommandSocketInfo->mListeningSocket.IsConnected())
+ if(mpCommandSocketInfo == 0)
{
- try
- {
- mpCommandSocketInfo->mListeningSocket.Write(newState, newStateSize);
- }
- catch(...)
- {
- CloseCommandConnection();
- }
+ return;
}
-#else
- if(mpCommandSocketInfo != 0 && mpCommandSocketInfo->mpConnectedSocket.get() != 0)
+
+ if (mpCommandSocketInfo->mpConnectedSocket.get() == 0)
{
- // Something connected to the command socket, tell it about the new state
- try
- {
- mpCommandSocketInfo->mpConnectedSocket->Write(newState, newStateSize);
- }
- catch(...)
- {
- CloseCommandConnection();
- }
+ return;
}
+
+ // Something connected to the command socket, tell it about the new state
+ try
+ {
+ mpCommandSocketInfo->mpConnectedSocket->Write(message.c_str(),
+ message.length());
+ }
+ catch(...)
+ {
+ CloseCommandConnection();
+ }
#endif
}
@@ -2173,11 +2291,11 @@
static const std::string STOREOBJECTINFO_MAGIC_ID_STRING = "BBACKUPD-STATE";
static const int STOREOBJECTINFO_VERSION = 1;
-void BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
+bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
{
if(!GetConfiguration().KeyExists("StoreObjectInfoFile"))
{
- return;
+ return false;
}
std::string StoreObjectInfoFile =
@@ -2185,13 +2303,17 @@
if (StoreObjectInfoFile.size() <= 0)
{
- return;
+ return false;
}
+ bool created = false;
+
try
{
FileStream aFile(StoreObjectInfoFile.c_str(),
O_WRONLY | O_CREAT | O_TRUNC);
+ created = true;
+
Archive anArchive(aFile, 0);
anArchive.Write(STOREOBJECTINFO_MAGIC_ID_VALUE);
@@ -2236,6 +2358,8 @@
"not accessible or could not be created",
StoreObjectInfoFile.c_str());
}
+
+ return created;
}
// --------------------------------------------------------------------------
Modified: box/chris/merge/bin/bbackupd/BackupDaemon.h
===================================================================
--- box/chris/merge/bin/bbackupd/BackupDaemon.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/BackupDaemon.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -46,9 +46,12 @@
~BackupDaemon();
private:
- // methods below do partial (specialized) serialization of client state only
- void SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const;
- bool DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime);
+ // methods below do partial (specialized) serialization of
+ // client state only
+ bool SerializeStoreObjectInfo(int64_t aClientStoreMarker,
+ box_time_t theLastSyncTime, box_time_t theNextSyncTime) const;
+ bool DeserializeStoreObjectInfo(int64_t & aClientStoreMarker,
+ box_time_t & theLastSyncTime, box_time_t & theNextSyncTime);
bool DeleteStoreObjectInfo() const;
BackupDaemon(const BackupDaemon &);
public:
@@ -182,7 +185,10 @@
void RunHelperThread(void);
private:
- bool mDoSyncFlagOut, mSyncIsForcedOut, mReceivedCommandConn;
+ bool mDoSyncFlagOut, mSyncIsForcedOut;
+ HANDLE mhMessageToSendEvent, mhCommandReceivedEvent;
+ CRITICAL_SECTION mMessageQueueLock;
+ std::vector<std::string> mMessageList;
#endif
};
Modified: box/chris/merge/bin/bbackupd/Win32BackupService.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/Win32BackupService.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/Win32BackupService.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -12,40 +12,51 @@
#include "Win32BackupService.h"
-Win32BackupService gDaemonService;
+Win32BackupService* gpDaemonService = NULL;
extern HANDLE gStopServiceEvent;
unsigned int WINAPI RunService(LPVOID lpParameter)
{
- DWORD retVal = gDaemonService.WinService();
- SetEvent( gStopServiceEvent );
+ DWORD retVal = gpDaemonService->WinService((const char*) lpParameter);
+ SetEvent(gStopServiceEvent);
return retVal;
}
void TerminateService(void)
{
- gDaemonService.SetTerminateWanted();
+ gpDaemonService->SetTerminateWanted();
}
-DWORD Win32BackupService::WinService(void)
+DWORD Win32BackupService::WinService(const char* pConfigFileName)
{
- int argc = 2;
- //first off get the path name for the default
- char buf[MAX_PATH];
+ char exepath[MAX_PATH];
+ GetModuleFileName(NULL, exepath, sizeof(exepath));
+
+ std::string configfile;
- GetModuleFileName(NULL, buf, sizeof(buf));
- std::string buffer(buf);
- std::string conf( "-c");
- std::string cfile(buffer.substr(0,(buffer.find("bbackupd.exe")))
- + "bbackupd.conf");
+ if (pConfigFileName != NULL)
+ {
+ configfile = pConfigFileName;
+ }
+ else
+ {
+ // make the default config file name,
+ // based on the program path
+ configfile = exepath;
+ configfile = configfile.substr(0,
+ configfile.rfind(DIRECTORY_SEPARATOR_ASCHAR));
+ configfile += DIRECTORY_SEPARATOR "bbackupd.conf";
+ }
- const char *argv[] = {conf.c_str(), cfile.c_str()};
+ const char *argv[] = {exepath, "-c", configfile.c_str()};
+ int argc = sizeof(argv) / sizeof(*argv);
+ DWORD ret;
MAINHELPER_START
+ ret = this->Main(BOX_FILE_BBACKUPD_DEFAULT_CONFIG, argc, argv);
+ MAINHELPER_END
- return this->Main(BOX_FILE_BBACKUPD_DEFAULT_CONFIG, argc, argv);
-
- MAINHELPER_END
+ return ret;
}
#endif // WIN32
Modified: box/chris/merge/bin/bbackupd/Win32BackupService.h
===================================================================
--- box/chris/merge/bin/bbackupd/Win32BackupService.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/Win32BackupService.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -12,7 +12,7 @@
class Win32BackupService : public BackupDaemon
{
public:
- DWORD WinService(void);
+ DWORD WinService(const char* pConfigFileName);
};
#endif // WIN32
Modified: box/chris/merge/bin/bbackupd/Win32ServiceFunctions.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/Win32ServiceFunctions.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/Win32ServiceFunctions.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -93,28 +93,30 @@
// It also returns on any error because the
// service cannot start if there is an eror.
+static char* spConfigFileName;
+
VOID ServiceMain(DWORD argc, LPTSTR *argv)
{
- // initialise service status
- gServiceStatus.dwServiceType = SERVICE_WIN32;
- gServiceStatus.dwCurrentState = SERVICE_STOPPED;
- gServiceStatus.dwControlsAccepted = 0;
- gServiceStatus.dwWin32ExitCode = NO_ERROR;
- gServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
- gServiceStatus.dwCheckPoint = 0;
- gServiceStatus.dwWaitHint = 0;
+ // initialise service status
+ gServiceStatus.dwServiceType = SERVICE_WIN32;
+ gServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ gServiceStatus.dwControlsAccepted = 0;
+ gServiceStatus.dwWin32ExitCode = NO_ERROR;
+ gServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 0;
- gServiceStatusHandle = RegisterServiceCtrlHandler(gServiceName,
- ServiceControlHandler);
+ gServiceStatusHandle = RegisterServiceCtrlHandler(gServiceName,
+ ServiceControlHandler);
- if (gServiceStatusHandle)
- {
- // service is starting
- gServiceStatus.dwCurrentState = SERVICE_START_PENDING;
- SetServiceStatus(gServiceStatusHandle, &gServiceStatus);
+ if (gServiceStatusHandle)
+ {
+ // service is starting
+ gServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+ SetServiceStatus(gServiceStatusHandle, &gServiceStatus);
- // do initialisation here
- gStopServiceEvent = CreateEvent( 0, TRUE, FALSE, 0 );
+ // do initialisation here
+ gStopServiceEvent = CreateEvent(0, TRUE, FALSE, 0);
if (!gStopServiceEvent)
{
gServiceStatus.dwControlsAccepted &=
@@ -129,7 +131,7 @@
NULL,
0,
RunService,
- 0,
+ spConfigFileName,
CREATE_SUSPENDED,
NULL);
@@ -138,7 +140,7 @@
// we are now running so tell the SCM
gServiceStatus.dwControlsAccepted |=
- (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
gServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(gServiceStatusHandle, &gServiceStatus);
@@ -156,11 +158,13 @@
~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
gServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(gServiceStatusHandle, &gServiceStatus);
- }
+ }
}
-void OurService(void)
+void OurService(char* pConfigFileName)
{
+ spConfigFileName = pConfigFileName;
+
SERVICE_TABLE_ENTRY serviceTable[] =
{
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain },
@@ -179,28 +183,52 @@
}
}
-void InstallService(void)
+int InstallService(const char* pConfigFileName)
{
- SC_HANDLE newService, scm;
+ if (pConfigFileName != NULL)
+ {
+ struct stat st;
- scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
+ if (emu_stat(pConfigFileName, &st) != 0)
+ {
+ syslog(LOG_ERR, "Failed to open configuration file: "
+ "%s: %s", pConfigFileName, strerror(errno));
+ return 1;
+ }
+ if (! st.st_mode & S_IFREG)
+ {
+
+ syslog(LOG_ERR, "Failed to open configuration file: "
+ "%s: not a file", pConfigFileName);
+ return 1;
+ }
+ }
+
+ SC_HANDLE scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
+
if (!scm)
{
syslog(LOG_ERR, "Failed to open service control manager: "
"error %d", GetLastError());
- return;
+ return 1;
}
char cmd[MAX_PATH];
GetModuleFileName(NULL, cmd, sizeof(cmd)-1);
cmd[sizeof(cmd)-1] = 0;
- char cmd_args[MAX_PATH];
- _snprintf(cmd_args, sizeof(cmd_args)-1, "%s --service", cmd);
- cmd_args[sizeof(cmd_args)-1] = 0;
+ std::string cmdWithArgs(cmd);
+ cmdWithArgs += " --service";
- newService = CreateService(
+ if (pConfigFileName != NULL)
+ {
+ cmdWithArgs += " \"";
+ cmdWithArgs += pConfigFileName;
+ cmdWithArgs += "\"";
+ }
+
+ SC_HANDLE newService = CreateService(
scm,
SERVICE_NAME,
"Box Backup",
@@ -208,14 +236,36 @@
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
- cmd_args,
+ cmdWithArgs.c_str(),
0,0,0,0,0);
+ DWORD err = GetLastError();
+ CloseServiceHandle(scm);
+
if (!newService)
{
- ::syslog(LOG_ERR, "Failed to create Box Backup service: "
- "error %d", GetLastError());
- return;
+ if (err == ERROR_SERVICE_EXISTS)
+ {
+ ::syslog(LOG_ERR, "Failed to create Box Backup "
+ "service: it already exists");
+ }
+ else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
+ {
+ ::syslog(LOG_ERR, "Failed to create Box Backup "
+ "service: it is waiting to be deleted");
+ }
+ else if (err == ERROR_DUPLICATE_SERVICE_NAME)
+ {
+ ::syslog(LOG_ERR, "Failed to create Box Backup "
+ "service: a service with this name "
+ "already exists");
+ }
+ else
+ {
+ ::syslog(LOG_ERR, "Failed to create Box Backup "
+ "service: error %d", err);
+ }
+ return 1;
}
::syslog(LOG_INFO, "Created Box Backup service");
@@ -231,45 +281,75 @@
}
CloseServiceHandle(newService);
- CloseServiceHandle(scm);
+
+ return 0;
}
-void RemoveService(void)
+int RemoveService(void)
{
- SC_HANDLE service, scm;
- SERVICE_STATUS status;
+ SC_HANDLE scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
- scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE);
-
if (!scm)
{
syslog(LOG_ERR, "Failed to open service control manager: "
"error %d", GetLastError());
- return;
+ return 1;
}
- service = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS|DELETE);
- ControlService(service, SERVICE_CONTROL_STOP, &status);
+ SC_HANDLE service = OpenService(scm, SERVICE_NAME,
+ SERVICE_ALL_ACCESS|DELETE);
+ DWORD err = GetLastError();
+ CloseServiceHandle(scm);
if (!service)
{
- syslog(LOG_ERR, "Failed to open Box Backup service: "
- "error %d", GetLastError());
- return;
+ if (err == ERROR_SERVICE_DOES_NOT_EXIST ||
+ err == ERROR_IO_PENDING)
+ // hello microsoft? anyone home?
+ {
+ syslog(LOG_ERR, "Failed to open Box Backup service: "
+ "not installed or not found");
+ }
+ else
+ {
+ syslog(LOG_ERR, "Failed to open Box Backup service: "
+ "error %d", err);
+ }
+ return 1;
}
- if (DeleteService(service))
+ SERVICE_STATUS status;
+ if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
{
+ err = GetLastError();
+ if (err != ERROR_SERVICE_NOT_ACTIVE)
+ {
+ syslog(LOG_WARNING, "Failed to stop Box Backup "
+ "service: error %d", err);
+ }
+ }
+
+ BOOL deleted = DeleteService(service);
+ err = GetLastError();
+ CloseServiceHandle(service);
+
+ if (deleted)
+ {
syslog(LOG_INFO, "Box Backup service deleted");
+ return 0;
}
+ else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
+ {
+ syslog(LOG_ERR, "Failed to remove Box Backup service: "
+ "it is already being deleted");
+ }
else
{
syslog(LOG_ERR, "Failed to remove Box Backup service: "
- "error %d", GetLastError());
+ "error %d", err);
}
- CloseServiceHandle(service);
- CloseServiceHandle(scm);
+ return 1;
}
#endif // WIN32
Modified: box/chris/merge/bin/bbackupd/Win32ServiceFunctions.h
===================================================================
--- box/chris/merge/bin/bbackupd/Win32ServiceFunctions.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/Win32ServiceFunctions.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -12,8 +12,8 @@
#ifndef WIN32SERVICEFUNCTIONS_H
#define WIN32SERVICEFUNCTIONS_H
-void RemoveService(void);
-void InstallService(void);
-void OurService(void);
+int RemoveService(void);
+int InstallService(const char* pConfigFilePath);
+void OurService(char* pConfigFileName);
#endif
Modified: box/chris/merge/bin/bbackupd/bbackupd.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/bbackupd.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupd/bbackupd.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -19,7 +19,7 @@
#include "Win32ServiceFunctions.h"
#include "Win32BackupService.h"
- extern Win32BackupService gDaemonService;
+ extern Win32BackupService* gpDaemonService;
#endif
int main(int argc, const char *argv[])
@@ -28,7 +28,7 @@
#ifdef WIN32
- ::openlog("Box Backup (bbackupd)", 0, 0);
+ ::openlog("Box Backup (bbackupd)", LOG_PID, LOG_LOCAL6);
if(argc == 2 &&
(::strcmp(argv[1], "--help") == 0 ||
@@ -40,32 +40,25 @@
}
if(argc == 2 && ::strcmp(argv[1], "-r") == 0)
{
- RemoveService();
- return 0;
+ return RemoveService();
}
- if(argc == 2 && ::strcmp(argv[1], "-i") == 0)
+ if((argc == 2 || argc == 3) && ::strcmp(argv[1], "-i") == 0)
{
- InstallService();
- return 0;
+ const char* config = NULL;
+ if (argc == 3)
+ {
+ config = argv[2];
+ }
+ return InstallService(config);
}
bool runAsWin32Service = false;
- if (argc == 2 && ::strcmp(argv[1], "--service") == 0)
+ if (argc >= 2 && ::strcmp(argv[1], "--service") == 0)
{
runAsWin32Service = true;
}
-
- // Under win32 we must initialise the Winsock library
- // before using sockets
-
- WSADATA info;
- if (WSAStartup(0x0101, &info) == SOCKET_ERROR)
- {
- // box backup will not run without sockets
- ::syslog(LOG_ERR, "Failed to initialise Windows Sockets");
- THROW_EXCEPTION(BackupStoreException, Internal)
- }
+ gpDaemonService = new Win32BackupService();
EnableBackupRights();
@@ -73,20 +66,33 @@
if (runAsWin32Service)
{
- syslog(LOG_INFO,"Starting Box Backup Service");
- OurService();
+ syslog(LOG_INFO, "Box Backup service starting");
+
+ char* config = NULL;
+ if (argc >= 3)
+ {
+ config = strdup(argv[2]);
+ }
+
+ OurService(config);
+
+ if (config)
+ {
+ free(config);
+ }
+
+ syslog(LOG_INFO, "Box Backup service shut down");
}
else
{
- ExitCode = gDaemonService.Main(
+ ExitCode = gpDaemonService->Main(
BOX_FILE_BBACKUPD_DEFAULT_CONFIG, argc, argv);
}
- // Clean up our sockets
- WSACleanup();
-
::closelog();
+ delete gpDaemonService;
+
return ExitCode;
#else // !WIN32
Modified: box/chris/merge/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/merge/bin/bbackupquery/BackupQueries.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupquery/BackupQueries.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -70,7 +70,11 @@
mWarnedAboutOwnerAttributes(false),
mReturnCode(0) // default return code
{
+ #ifdef WIN32
+ mRunningAsRoot = TRUE;
+ #else
mRunningAsRoot = (::geteuid() == 0);
+ #endif
}
// --------------------------------------------------------------------------
@@ -85,6 +89,12 @@
{
}
+typedef struct cmd_info
+{
+ const char* name;
+ const char* opts;
+} cmd_info_t;
+
// --------------------------------------------------------------------------
//
// Function
@@ -162,8 +172,24 @@
}
// Data about commands
- static const char *commandNames[] = {"quit", "exit", "list", "pwd", "cd", "lcd", "sh", "getobject", "get", "compare", "restore", "help", "usage", "undelete", 0};
- static const char *validOptions[] = {"", "", "rodIFtsh", "", "od", "", "", "", "i", "alcqE", "dri", "", "", "", 0};
+ static cmd_info_t commands[] =
+ {
+ { "quit", "" },
+ { "exit", "" },
+ { "list", "rodIFtTsh", },
+ { "pwd", "" },
+ { "cd", "od" },
+ { "lcd", "" },
+ { "sh", "" },
+ { "getobject", "" },
+ { "get", "i" },
+ { "compare", "alcqAE" },
+ { "restore", "dri" },
+ { "help", "" },
+ { "usage", "" },
+ { "undelete", "" },
+ { NULL, NULL }
+ };
#define COMMAND_Quit 0
#define COMMAND_Exit 1
#define COMMAND_List 2
@@ -183,11 +209,11 @@
// Work out which command it is...
int cmd = 0;
- while(commandNames[cmd] != 0 && ::strcmp(cmdElements[0].c_str(), commandNames[cmd]) != 0)
+ while(commands[cmd].name != 0 && ::strcmp(cmdElements[0].c_str(), commands[cmd].name) != 0)
{
cmd++;
}
- if(commandNames[cmd] == 0)
+ if(commands[cmd].name == 0)
{
// Check for aliases
int a;
@@ -222,9 +248,10 @@
while(*c != 0)
{
// Valid option?
- if(::strchr(validOptions[cmd], *c) == NULL)
+ if(::strchr(commands[cmd].opts, *c) == NULL)
{
- printf("Invalid option '%c' for command %s\n", *c, commandNames[cmd]);
+ printf("Invalid option '%c' for command %s\n",
+ *c, commands[cmd].name);
return;
}
opts[(int)*c] = true;
@@ -319,8 +346,9 @@
#define LIST_OPTION_ALLOWOLD 'o'
#define LIST_OPTION_ALLOWDELETED 'd'
#define LIST_OPTION_NOOBJECTID 'I'
- #define LIST_OPTION_NOFLAGS 'F'
- #define LIST_OPTION_TIMES 't'
+ #define LIST_OPTION_NOFLAGS 'F'
+ #define LIST_OPTION_TIMES_LOCAL 't'
+ #define LIST_OPTION_TIMES_UTC 'T'
#define LIST_OPTION_SIZEINBLOCKS 's'
#define LIST_OPTION_DISPLAY_HASH 'h'
@@ -362,7 +390,7 @@
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupQueries::CommandList2(int64_t, const std::string &, const bool *)
+// Name: BackupQueries::List(int64_t, const std::string &, const bool *, bool)
// Purpose: Do the actual listing of directories and files
// Created: 2003/10/10
//
@@ -437,9 +465,9 @@
}
}
- if(opts[LIST_OPTION_TIMES])
+ if(opts[LIST_OPTION_TIMES_LOCAL])
{
- // Show times...
+ // Show local times...
std::string time = BoxTimeToISO8601String(
en->GetModificationTime());
printf("%s ", time.c_str());
@@ -844,13 +872,44 @@
}
// Find object ID somehow
- int64_t id;
+ int64_t fileId;
+ int64_t dirId = GetCurrentDirectoryID();
std::string localName;
+
// BLOCK
{
+#ifdef WIN32
+ std::string fileName;
+ if(!ConvertConsoleToUtf8(args[0].c_str(), fileName))
+ return;
+#else
+ std::string fileName(args[0]);
+#endif
+
+ if(!opts['i'])
+ {
+ // does this remote filename include a path?
+ std::string::size_type index = fileName.rfind('/');
+ if(index != std::string::npos)
+ {
+ std::string dirName(fileName.substr(0, index));
+ fileName = fileName.substr(index + 1);
+
+ dirId = FindDirectoryObjectID(dirName);
+ if(dirId == 0)
+ {
+ printf("Directory '%s' not found\n",
+ dirName.c_str());
+ return;
+ }
+ }
+ }
+
+ BackupStoreFilenameClear fn(fileName);
+
// Need to look it up in the current directory
mrConnection.QueryListDirectory(
- GetCurrentDirectoryID(),
+ dirId,
BackupProtocolClientListDirectory::Flags_File, // just files
(opts['i'])?(BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING):(BackupProtocolClientListDirectory::Flags_OldVersion | BackupProtocolClientListDirectory::Flags_Deleted), // only current versions
false /* don't want attributes */);
@@ -863,17 +922,23 @@
if(opts['i'])
{
// Specified as ID.
- id = ::strtoll(args[0].c_str(), 0, 16);
- if(id == std::numeric_limits<long long>::min() || id == std::numeric_limits<long long>::max() || id == 0)
+ fileId = ::strtoll(args[0].c_str(), 0, 16);
+ if(fileId == std::numeric_limits<long long>::min() ||
+ fileId == std::numeric_limits<long long>::max() ||
+ fileId == 0)
{
printf("Not a valid object ID (specified in hex)\n");
return;
}
// Check that the item is actually in the directory
- if(dir.FindEntryByID(id) == 0)
+ if(dir.FindEntryByID(fileId) == 0)
{
- printf("ID '%08llx' not found in current directory on store.\n(You can only download objects by ID from the current directory.)\n", id);
+ printf("ID '%08llx' not found in current "
+ "directory on store.\n"
+ "(You can only download objects by ID "
+ "from the current directory.)\n",
+ fileId);
return;
}
@@ -884,26 +949,22 @@
{
// Specified by name, find the object in the directory to get the ID
BackupStoreDirectory::Iterator i(dir);
-#ifdef WIN32
- std::string fileName;
- if(!ConvertConsoleToUtf8(args[0].c_str(), fileName))
- return;
- BackupStoreFilenameClear fn(fileName);
-#else
- BackupStoreFilenameClear fn(args[0]);
-#endif
BackupStoreDirectory::Entry *en = i.FindMatchingClearName(fn);
if(en == 0)
{
- printf("Filename '%s' not found in current directory on store.\n(Subdirectories in path not searched.)\n", args[0].c_str());
+ printf("Filename '%s' not found in current "
+ "directory on store.\n"
+ "(Subdirectories in path not "
+ "searched.)\n", args[0].c_str());
return;
}
- id = en->GetObjectID();
+ fileId = en->GetObjectID();
- // Local name is the last argument, which is either the looked up filename, or
- // a filename specified by the user.
+ // Local name is the last argument, which is either
+ // the looked up filename, or a filename specified
+ // by the user.
localName = args[args.size() - 1];
}
}
@@ -920,7 +981,7 @@
try
{
// Request object
- mrConnection.QueryGetFile(GetCurrentDirectoryID(), id);
+ mrConnection.QueryGetFile(dirId, fileId);
// Stream containing encoded file
std::auto_ptr<IOStream> objectStream(mrConnection.ReceiveStream());
@@ -929,7 +990,7 @@
BackupStoreFile::DecodeFile(*objectStream, localName.c_str(), mrConnection.GetTimeout());
// Done.
- printf("Object ID %08llx fetched sucessfully.\n", id);
+ printf("Object ID %08llx fetched sucessfully.\n", fileId);
}
catch(...)
{
@@ -950,8 +1011,10 @@
BackupQueries::CompareParams::CompareParams()
: mQuickCompare(false),
mIgnoreExcludes(false),
+ mIgnoreAttributes(false),
mDifferences(0),
mDifferencesExplainedByModTime(0),
+ mUncheckedFiles(0),
mExcludedDirs(0),
mExcludedFiles(0),
mpExcludeFiles(0),
@@ -1012,6 +1075,7 @@
BackupQueries::CompareParams params;
params.mQuickCompare = opts['q'];
params.mIgnoreExcludes = opts['E'];
+ params.mIgnoreAttributes = opts['A'];
// Try and work out the time before which all files should be on the server
{
@@ -1074,13 +1138,29 @@
return;
}
- printf("\n[ %d (of %d) differences probably due to file modifications after the last upload ]\nDifferences: %d (%d dirs excluded, %d files excluded)\n",
- params.mDifferencesExplainedByModTime, params.mDifferences, params.mDifferences, params.mExcludedDirs, params.mExcludedFiles);
+ printf("\n[ %d (of %d) differences probably due to file "
+ "modifications after the last upload ]\n"
+ "Differences: %d (%d dirs excluded, %d files excluded, "
+ "%d files not checked)\n",
+ params.mDifferencesExplainedByModTime, params.mDifferences,
+ params.mDifferences, params.mExcludedDirs,
+ params.mExcludedFiles, params.mUncheckedFiles);
// Set return code?
if(opts['c'])
{
- SetReturnCode((params.mDifferences == 0)?COMPARE_RETURN_SAME:COMPARE_RETURN_DIFFERENT);
+ if (params.mUncheckedFiles != 0)
+ {
+ SetReturnCode(COMPARE_RETURN_ERROR);
+ }
+ else if (params.mDifferences != 0)
+ {
+ SetReturnCode(COMPARE_RETURN_DIFFERENT);
+ }
+ else
+ {
+ SetReturnCode(COMPARE_RETURN_SAME);
+ }
}
}
@@ -1214,11 +1294,13 @@
"(compared to server directory '%s')\n",
localDirDisplay.c_str(),
storeDirDisplay.c_str());
+ rParams.mDifferences ++;
}
else
{
printf("ERROR: stat on local dir '%s'\n",
localDirDisplay.c_str());
+ rParams.mUncheckedFiles ++;
}
return;
}
@@ -1268,6 +1350,7 @@
{
printf("ERROR: opendir on local dir '%s'\n",
localDirDisplay.c_str());
+ rParams.mUncheckedFiles ++;
return;
}
try
@@ -1455,11 +1538,12 @@
}
// Compare attributes
+ box_time_t fileModTime = 0;
BackupClientFileAttributes localAttr;
- box_time_t fileModTime = 0;
localAttr.ReadAttributes(localPath.c_str(), false /* don't zero mod times */, &fileModTime);
modifiedAfterLastSync = (fileModTime > rParams.mLatestFileUploadTime);
- if(!localAttr.Compare(fileOnServerStream->GetAttributes(),
+ if(!rParams.mIgnoreAttributes &&
+ !localAttr.Compare(fileOnServerStream->GetAttributes(),
true /* ignore attr mod time */,
fileOnServerStream->IsSymLink() /* ignore modification time if it's a symlink */))
{
@@ -1554,10 +1638,12 @@
e.GetType(),
e.GetSubType(),
storePathDisplay.c_str());
+ rParams.mUncheckedFiles ++;
}
catch(...)
- {
+ {
printf("ERROR: (unknown) during file fetch and comparison for '%s'\n", storePathDisplay.c_str());
+ rParams.mUncheckedFiles ++;
}
// Remove from set so that we know it's been compared
@@ -1793,6 +1879,14 @@
printf("The target directory exists. You cannot restore over an existing directory.\n");
break;
+ #ifdef WIN32
+ case Restore_TargetPathNotFound:
+ printf("The target directory path does not exist.\n"
+ "To restore to a directory whose parent "
+ "does not exist, create the parent first.\n");
+ break;
+ #endif
+
default:
printf("ERROR: Unknown restore result.\n");
break;
Modified: box/chris/merge/bin/bbackupquery/BackupQueries.h
===================================================================
--- box/chris/merge/bin/bbackupquery/BackupQueries.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupquery/BackupQueries.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -68,8 +68,10 @@
void DeleteExcludeLists();
bool mQuickCompare;
bool mIgnoreExcludes;
+ bool mIgnoreAttributes;
int mDifferences;
int mDifferencesExplainedByModTime;
+ int mUncheckedFiles;
int mExcludedDirs;
int mExcludedFiles;
const ExcludeList *mpExcludeFiles;
Modified: box/chris/merge/bin/bbackupquery/documentation.txt
===================================================================
--- box/chris/merge/bin/bbackupquery/documentation.txt 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbackupquery/documentation.txt 2006-07-27 23:18:35 UTC (rev 710)
@@ -104,6 +104,7 @@
-c -- set return code
-q -- quick compare. Only checks file contents against checksums,
doesn't do a full download
+ -A -- ignore attribute differences
-E -- ignore exclusion settings
Comparing with the root directory is an error, use -a option instead.
Modified: box/chris/merge/bin/bbstored/BBStoreDHousekeeping.cpp
===================================================================
--- box/chris/merge/bin/bbstored/BBStoreDHousekeeping.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbstored/BBStoreDHousekeeping.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -10,7 +10,10 @@
#include "Box.h"
#include <stdio.h>
+
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif
#include "BackupStoreDaemon.h"
#include "BackupStoreAccountDatabase.h"
@@ -29,96 +32,129 @@
// Created: 11/12/03
//
// --------------------------------------------------------------------------
+void BackupStoreDaemon::HousekeepingInit()
+{
+
+ mLastHousekeepingRun = 0;
+}
+
+#ifndef WIN32
void BackupStoreDaemon::HousekeepingProcess()
{
+ HousekeepingInit();
+
// Get the time between housekeeping runs
const Configuration &rconfig(GetConfiguration());
int64_t housekeepingInterval = SecondsToBoxTime(rconfig.GetKeyValueInt("TimeBetweenHousekeeping"));
-
- int64_t lastHousekeepingRun = 0;
while(!StopRun())
{
- // Time now
+ RunHousekeepingIfNeeded();
+
+ // Calculate how long should wait before doing the next housekeeping run
int64_t timeNow = GetCurrentBoxTime();
- // Do housekeeping if the time interval has elapsed since the last check
- if((timeNow - lastHousekeepingRun) >= housekeepingInterval)
- {
- // Store the time
- lastHousekeepingRun = timeNow;
- ::syslog(LOG_INFO, "Starting housekeeping");
+ time_t secondsToGo = BoxTimeToSeconds((mLastHousekeepingRun + housekeepingInterval) - timeNow);
+ if(secondsToGo < 1) secondsToGo = 1;
+ if(secondsToGo > 60) secondsToGo = 60;
+ int32_t millisecondsToGo = ((int)secondsToGo) * 1000;
+
+ // Check to see if there's any message pending
+ CheckForInterProcessMsg(0 /* no account */, millisecondsToGo);
+ }
+}
+#endif
- // Get the list of accounts
- std::vector<int32_t> accounts;
- if(mpAccountDatabase)
- {
- mpAccountDatabase->GetAllAccountIDs(accounts);
- }
+void BackupStoreDaemon::RunHousekeepingIfNeeded()
+{
+ // Get the time between housekeeping runs
+ const Configuration &rconfig(GetConfiguration());
+ int64_t housekeepingInterval = SecondsToBoxTime(rconfig.GetKeyValueInt("TimeBetweenHousekeeping"));
+
+ // Time now
+ int64_t timeNow = GetCurrentBoxTime();
+ // Do housekeeping if the time interval has elapsed since the last check
+ if((timeNow - mLastHousekeepingRun) < housekeepingInterval)
+ {
+ return;
+ }
+
+ // Store the time
+ mLastHousekeepingRun = timeNow;
+ ::syslog(LOG_INFO, "Starting housekeeping");
+
+ // Get the list of accounts
+ std::vector<int32_t> accounts;
+ if(mpAccountDatabase)
+ {
+ mpAccountDatabase->GetAllAccountIDs(accounts);
+ }
- SetProcessTitle("housekeeping, active");
+ SetProcessTitle("housekeeping, active");
- // Check them all
- for(std::vector<int32_t>::const_iterator i = accounts.begin(); i != accounts.end(); ++i)
+ // Check them all
+ for(std::vector<int32_t>::const_iterator i = accounts.begin(); i != accounts.end(); ++i)
+ {
+ try
+ {
+ if(mpAccounts)
{
- try
- {
- if(mpAccounts)
- {
- // Get the account root
- std::string rootDir;
- int discSet = 0;
- mpAccounts->GetAccountRoot(*i, rootDir, discSet);
-
- // Do housekeeping on this account
- HousekeepStoreAccount housekeeping(*i, rootDir, discSet, *this);
- housekeeping.DoHousekeeping();
- }
- }
- catch(BoxException &e)
- {
- ::syslog(LOG_ERR, "while housekeeping account %08X, exception %s (%d/%d) -- aborting housekeeping run for this account",
- *i, e.what(), e.GetType(), e.GetSubType());
- }
- catch(std::exception &e)
- {
- ::syslog(LOG_ERR, "while housekeeping account %08X, exception %s -- aborting housekeeping run for this account",
- *i, e.what());
- }
- catch(...)
- {
- ::syslog(LOG_ERR, "while housekeeping account %08X, unknown exception -- aborting housekeeping run for this account",
- *i);
- }
+ // Get the account root
+ std::string rootDir;
+ int discSet = 0;
+ mpAccounts->GetAccountRoot(*i, rootDir, discSet);
- // Check to see if there's any message pending
- CheckForInterProcessMsg(0 /* no account */);
-
- // Stop early?
- if(StopRun())
- {
- break;
- }
+ // Do housekeeping on this account
+ HousekeepStoreAccount housekeeping(*i, rootDir, discSet, *this);
+ housekeeping.DoHousekeeping();
}
-
- ::syslog(LOG_INFO, "Finished housekeeping");
}
-
- // Placed here for accuracy, if StopRun() is true, for example.
- SetProcessTitle("housekeeping, idle");
-
- // Calculate how long should wait before doing the next housekeeping run
- timeNow = GetCurrentBoxTime();
- time_t secondsToGo = BoxTimeToSeconds((lastHousekeepingRun + housekeepingInterval) - timeNow);
- if(secondsToGo < 1) secondsToGo = 1;
- if(secondsToGo > 60) secondsToGo = 60;
- int32_t millisecondsToGo = ((int)secondsToGo) * 1000;
+ catch(BoxException &e)
+ {
+ ::syslog(LOG_ERR, "while housekeeping account %08X, exception %s (%d/%d) -- aborting housekeeping run for this account",
+ *i, e.what(), e.GetType(), e.GetSubType());
+ }
+ catch(std::exception &e)
+ {
+ ::syslog(LOG_ERR, "while housekeeping account %08X, exception %s -- aborting housekeeping run for this account",
+ *i, e.what());
+ }
+ catch(...)
+ {
+ ::syslog(LOG_ERR, "while housekeeping account %08X, unknown exception -- aborting housekeeping run for this account",
+ *i);
+ }
+#ifndef WIN32
// Check to see if there's any message pending
- CheckForInterProcessMsg(0 /* no account */, millisecondsToGo);
+ CheckForInterProcessMsg(0 /* no account */);
+#endif
+
+ // Stop early?
+ if(StopRun())
+ {
+ break;
+ }
}
+
+ ::syslog(LOG_INFO, "Finished housekeeping");
+
+ // Placed here for accuracy, if StopRun() is true, for example.
+ SetProcessTitle("housekeeping, idle");
}
+#ifdef WIN32
+void BackupStoreDaemon::OnIdle()
+{
+ if (!mHousekeepingInited)
+ {
+ HousekeepingInit();
+ mHousekeepingInited = true;
+ }
+ RunHousekeepingIfNeeded();
+}
+#endif
+
// --------------------------------------------------------------------------
//
// Function
@@ -128,6 +164,7 @@
// Created: 11/12/03
//
// --------------------------------------------------------------------------
+#ifndef WIN32
bool BackupStoreDaemon::CheckForInterProcessMsg(int AccountNum, int MaximumWaitTime)
{
// First, check to see if it's EOF -- this means something has gone wrong, and the housekeeping should terminate.
@@ -171,5 +208,6 @@
return false;
}
+#endif
Modified: box/chris/merge/bin/bbstored/BackupCommands.cpp
===================================================================
--- box/chris/merge/bin/bbstored/BackupCommands.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbstored/BackupCommands.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -9,8 +9,13 @@
#include "Box.h"
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif
+#include <set>
+#include <sstream>
+
#include "autogen_BackupProtocolServer.h"
#include "BackupConstants.h"
#include "BackupContext.h"
@@ -327,8 +332,15 @@
std::auto_ptr<IOStream> diff2(rContext.OpenObject(patchID));
// Choose a temporary filename for the result of the combination
- std::string tempFn(RaidFileController::DiscSetPathToFileSystemPath(rContext.GetStoreDiscSet(), rContext.GetStoreRoot() + ".recombinetemp",
- p + 16 /* rotate which disc it's on */));
+#ifdef WIN32
+ std::ostringstream fs(rContext.GetStoreRoot());
+ fs << ".recombinetemp.";
+ fs << p;
+ std::string tempFn(fs.str());
+ tempFn = RaidFileController::DiscSetPathToFileSystemPath(rContext.GetStoreDiscSet(), tempFn, p + 16);
+#else
+ std::string tempFn(RaidFileController::DiscSetPathToFileSystemPath(rContext.GetStoreDiscSet(), rContext.GetStoreRoot() + ".recombinetemp", p + 16 /* rotate which disc it's on */));
+#endif
// Open the temporary file
std::auto_ptr<IOStream> combined;
@@ -336,14 +348,23 @@
{
{
// Write nastily to allow this to work with gcc 2.x
+#ifdef WIN32
+ combined.reset(new FileStream(
+ tempFn.c_str(),
+ O_RDWR | O_CREAT | O_EXCL |
+ O_BINARY | O_TRUNC));
+#else
std::auto_ptr<IOStream> t(new FileStream(tempFn.c_str(), O_RDWR | O_CREAT | O_EXCL));
combined = t;
+#endif
}
+#ifndef WIN32
// Unlink immediately as it's a temporary file
if(::unlink(tempFn.c_str()) != 0)
{
THROW_EXCEPTION(CommonException, OSFileError);
}
+#endif
}
catch(...)
{
@@ -359,6 +380,9 @@
combined->Seek(0, IOStream::SeekType_Absolute);
// Then shuffle round for the next go
+#ifdef WIN32
+ if (from.get()) from->Close();
+#endif
from = combined;
}
@@ -396,8 +420,9 @@
stream = t;
}
- // Object will be deleted when the stream is deleted, so can release the object auto_ptr here to
- // avoid premature deletiong
+ // Object will be deleted when the stream is deleted,
+ // so can release the object auto_ptr here to avoid
+ // premature deletion
object.release();
}
Modified: box/chris/merge/bin/bbstored/BackupContext.cpp
===================================================================
--- box/chris/merge/bin/bbstored/BackupContext.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbstored/BackupContext.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -132,6 +132,7 @@
// Request the lock
bool gotLock = mWriteLock.TryAndGetLock(writeLockFile.c_str(), 0600 /* restrictive file permissions */);
+#ifndef WIN32
if(!gotLock)
{
// The housekeeping process might have the thing open -- ask it to stop
@@ -150,6 +151,7 @@
} while(!gotLock && tries > 0);
}
+#endif
if(gotLock)
{
@@ -453,13 +455,21 @@
try
{
// Open it twice
+#ifdef WIN32
+ FileStream diff(tempFn.c_str(),
+ O_RDWR | O_CREAT | O_BINARY);
+ FileStream diff2(tempFn.c_str(),
+ O_RDWR | O_BINARY);
+#else
FileStream diff(tempFn.c_str(), O_RDWR | O_CREAT | O_EXCL);
FileStream diff2(tempFn.c_str(), O_RDONLY);
- // Unlink it immediately, so it definately goes away
+
+ // Unlink it immediately, so it definitely goes away
if(::unlink(tempFn.c_str()) != 0)
{
THROW_EXCEPTION(CommonException, OSFileError);
}
+#endif
// Stream the incoming diff to this temporary file
if(!rFile.CopyStreamTo(diff, BACKUP_STORE_TIMEOUT))
@@ -508,6 +518,14 @@
::unlink(tempFn.c_str());
throw;
}
+
+#ifdef WIN32
+ // we can't delete the file while it's open, above
+ if(::unlink(tempFn.c_str()) != 0)
+ {
+ THROW_EXCEPTION(CommonException, OSFileError);
+ }
+#endif
}
// Get the blocks used
Modified: box/chris/merge/bin/bbstored/BackupStoreDaemon.cpp
===================================================================
--- box/chris/merge/bin/bbstored/BackupStoreDaemon.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbstored/BackupStoreDaemon.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -11,9 +11,12 @@
#include <stdlib.h>
#include <stdio.h>
-#include <syslog.h>
#include <signal.h>
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+
#include "BackupContext.h"
#include "BackupStoreDaemon.h"
#include "BackupStoreConfigVerify.h"
@@ -39,7 +42,11 @@
mExtendedLogging(false),
mHaveForkedHousekeeping(false),
mIsHousekeepingProcess(false),
+#ifdef WIN32
+ mHousekeepingInited(false)
+#else
mInterProcessComms(mInterProcessCommsSocket)
+#endif
{
}
@@ -156,6 +163,7 @@
const Configuration &config(GetConfiguration());
mExtendedLogging = config.GetKeyValueBool("ExtendedLogging");
+#ifndef WIN32
// Fork off housekeeping daemon -- must only do this the first time Run() is called
if(!mHaveForkedHousekeeping)
{
@@ -219,9 +227,11 @@
}
else
{
+#endif // !WIN32
// In server process -- use the base class to do the magic
ServerTLS<BOX_PORT_BBSTORED>::Run();
+#ifndef WIN32
// Why did it stop? Tell the housekeeping process to do the same
if(IsReloadConfigWanted())
{
@@ -232,6 +242,7 @@
mInterProcessCommsSocket.Write("t\n", 2);
}
}
+#endif
}
@@ -297,6 +308,8 @@
// Log the amount of data transferred
::syslog(LOG_INFO, "Connection statistics for %s: "
"IN=%lld OUT=%lld TOTAL=%lld\n", commonName,
- s.GetBytesRead(), s.GetBytesWritten(),
- s.GetBytesRead() + s.GetBytesWritten());
+ (long long)s.GetBytesRead(),
+ (long long)s.GetBytesWritten(),
+ (long long)s.GetBytesRead() +
+ (long long)s.GetBytesWritten());
}
Modified: box/chris/merge/bin/bbstored/BackupStoreDaemon.h
===================================================================
--- box/chris/merge/bin/bbstored/BackupStoreDaemon.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbstored/BackupStoreDaemon.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -38,11 +38,13 @@
BackupStoreDaemon(const BackupStoreDaemon &rToCopy);
public:
+#ifndef WIN32
// For BackupContext to comminicate with housekeeping process
void SendMessageToHousekeepingProcess(const void *Msg, int MsgLen)
{
mInterProcessCommsSocket.Write(Msg, MsgLen);
}
+#endif
protected:
@@ -57,9 +59,11 @@
const ConfigurationVerify *GetConfigVerify() const;
+#ifndef WIN32
// Housekeeping functions
void HousekeepingProcess();
bool CheckForInterProcessMsg(int AccountNum = 0, int MaximumWaitTime = 0);
+#endif
void LogConnectionStats(const char *commonName, const SocketStreamTLS &s);
@@ -70,8 +74,17 @@
bool mHaveForkedHousekeeping;
bool mIsHousekeepingProcess;
+#ifdef WIN32
+ virtual void OnIdle();
+ bool mHousekeepingInited;
+#else
SocketStream mInterProcessCommsSocket;
IOStreamGetLine mInterProcessComms;
+#endif
+
+ void HousekeepingInit();
+ void RunHousekeepingIfNeeded();
+ int64_t mLastHousekeepingRun;
};
Modified: box/chris/merge/bin/bbstored/HousekeepStoreAccount.cpp
===================================================================
--- box/chris/merge/bin/bbstored/HousekeepStoreAccount.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/bin/bbstored/HousekeepStoreAccount.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -225,6 +225,7 @@
// --------------------------------------------------------------------------
bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
{
+#ifndef WIN32
if((--mCountUntilNextInterprocessMsgCheck) <= 0)
{
mCountUntilNextInterprocessMsgCheck = POLL_INTERPROCESS_MSG_CHECK_FREQUENCY;
@@ -235,6 +236,7 @@
return false;
}
}
+#endif
// Get the filename
std::string objectFilename;
@@ -251,6 +253,7 @@
// Read the directory in
BackupStoreDirectory dir;
dir.ReadFromStream(*dirStream, IOStream::TimeOutInfinite);
+ dirStream->Close();
// Is it empty?
if(dir.GetNumberOfEntries() == 0)
@@ -485,6 +488,7 @@
// (there is likely to be more in the set than should be actually deleted).
for(std::set<DelEn, DelEnCompare>::iterator i(mPotentialDeletions.begin()); i != mPotentialDeletions.end(); ++i)
{
+#ifndef WIN32
if((--mCountUntilNextInterprocessMsgCheck) <= 0)
{
mCountUntilNextInterprocessMsgCheck = POLL_INTERPROCESS_MSG_CHECK_FREQUENCY;
@@ -495,6 +499,7 @@
return true;
}
}
+#endif
// Load up the directory it's in
// Get the filename
@@ -729,6 +734,7 @@
// Go through list
for(std::vector<int64_t>::const_iterator i(mEmptyDirectories.begin()); i != mEmptyDirectories.end(); ++i)
{
+#ifndef WIN32
if((--mCountUntilNextInterprocessMsgCheck) <= 0)
{
mCountUntilNextInterprocessMsgCheck = POLL_INTERPROCESS_MSG_CHECK_FREQUENCY;
@@ -739,6 +745,7 @@
return true;
}
}
+#endif
// Do not delete the root directory
if(*i == BACKUPSTORE_ROOT_DIRECTORY_ID)
Modified: box/chris/merge/configure.ac
===================================================================
--- box/chris/merge/configure.ac 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/configure.ac 2006-07-27 23:18:35 UTC (rev 710)
@@ -44,7 +44,7 @@
VL_LIB_READLINE([have_libreadline=yes], [have_libreadline=no])
## Check for Berkely DB. Restrict to certain versions
-AX_PATH_BDB(, [
+AX_PATH_BDB([1.x or 4.1], [
LIBS="$BDB_LIBS $LIBS"
LDFLAGS="$BDB_LDFLAGS $LDFLAGS"
CPPFLAGS="$CPPFLAGS $BDB_CPPFLAGS"
@@ -89,7 +89,7 @@
AC_CHECK_HEADERS([syslog.h time.h])
AC_CHECK_HEADERS([netinet/in.h])
AC_CHECK_HEADERS([sys/param.h sys/socket.h sys/time.h sys/types.h sys/wait.h])
-AC_CHECK_HEADERS([sys/xattr.h])
+AC_CHECK_HEADERS([sys/uio.h sys/xattr.h])
if test "$ac_cv_header_regex_h" = "yes"; then
AC_SEARCH_LIBS([regcomp], [pcreposix])
@@ -116,6 +116,7 @@
]])
AC_CHECK_DECLS([INFTIM],,, [[#include <poll.h>]])
AC_CHECK_DECLS([SO_PEERCRED],,, [[#include <sys/socket.h>]])
+AC_CHECK_DECLS([O_BINARY],,,)
AC_HEADER_TIME
AC_STRUCT_TM
AX_CHECK_DIRENT_D_TYPE
@@ -124,14 +125,14 @@
if test "x$ac_cv_c_bigendian" != "xyes"; then
AX_BSWAP64
fi
+
if test "$target_os" != "mingw32"; then
AX_RANDOM_DEVICE
-fi
-AX_CHECK_MOUNT_POINT(,[
- if test "$target_os" != "mingw32" -a "$target_os" != "winnt"; then
+ AX_CHECK_MOUNT_POINT(,[
AC_MSG_ERROR([[cannot work out how to discover mount points on your platform]])
- fi
])
+fi
+
AX_CHECK_MALLOC_WORKAROUND
@@ -220,6 +221,7 @@
lib/server/makeprotocol.pl
runtest.pl
test/backupstorefix/testfiles/testbackupstorefix.pl
+ test/bbackupd/testfiles/bbackupd.conf
test/bbackupd/testfiles/extcheck1.pl
test/bbackupd/testfiles/extcheck2.pl
test/bbackupd/testfiles/notifyscript.pl])
@@ -237,6 +239,7 @@
without these features, but will work better where they are present. Refer
to the documentation for more information on each feature.
+Regular expressions: $ac_cv_header_regex_h
Large files: $have_large_file_support
Berkeley DB: $ax_path_bdb_ok
Readline: $have_libreadline
Modified: box/chris/merge/docs/backup/win32_build_on_linux_using_mingw.txt
===================================================================
--- box/chris/merge/docs/backup/win32_build_on_linux_using_mingw.txt 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/docs/backup/win32_build_on_linux_using_mingw.txt 2006-07-27 23:18:35 UTC (rev 710)
@@ -7,6 +7,11 @@
- Fedora and SuSE users can download RPM packages from
[http://mirzam.it.vu.nl/mingw/]
+You will need to know the prefix used by the cross-compiler executables.
+It will usually be something like "ix86-mingw32*-". All the binaries in the
+cross-compiler package will start with this prefix. The documentation below
+assumes that it is "i386-mingw32-". Adjust to taste.
+
Download Zlib from [http://www.zlib.net/], unpack and enter source directory:
export CC=i386-mingw32-gcc
@@ -16,8 +21,19 @@
make
make install prefix=/usr/local/i386-mingw32
-Download OpenSSL 0.9.7 from
+Download OpenSSL 0.9.8b from
+[http://www.openssl.org/source/openssl-0.9.8b.tar.gz]
+Unpack and configure:
+
+ tar xzvf openssl-0.9.8b.tar.gz
+ cd openssl-0.9.8b
+ ./Configure mingw
+ make makefile.one
+ wget http://bbdev.fluffy.co.uk/svn/box/chris/win32/support/openssl-0.9.8b-mingw-cross.patch
+ patch -p1 < openssl-0.9.8b-mingw-cross.patch
+ make -f makefile.one
+
Configure Box with:
export CXX="i386-mingw32-g++"
@@ -27,5 +43,6 @@
export CXXFLAGS="-mthreads"
export LDFLAGS="-mthreads"
export LIBS="-lcrypto -lws2_32 -lgdi32"
+ (if you don't have a "configure" file, run "./bootstrap")
./configure --target=i386-mingw32
- make CXX="$CXX" AR="$AR" RANLIB="$RANLIB"
+ make CXX="$CXX" AR="$AR" RANLIB="$RANLIB" WINDRES="i386-mingw32-windres"
Modified: box/chris/merge/infrastructure/BoxPlatform.pm.in
===================================================================
--- box/chris/merge/infrastructure/BoxPlatform.pm.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/infrastructure/BoxPlatform.pm.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,16 +1,30 @@
package BoxPlatform;
use Exporter;
@ISA = qw/Exporter/;
- at EXPORT = qw/$build_os $build_cpu $target_os $make_command $bsd_make $platform_define $platform_cpu $gcc_v3 $product_version $product_name $install_into_dir $sub_make_options $platform_compile_line_extra $platform_link_line_extra $platform_lib_files $platform_exe_ext/;
+ at EXPORT = qw/$build_os $build_cpu $target_os $make_command $bsd_make $platform_define $platform_cpu $gcc_v3 $product_version $product_name $install_into_dir $sub_make_options $platform_compile_line_extra $platform_link_line_extra $platform_lib_files $platform_exe_ext $target_windows update_if_changed/;
BEGIN
{
# which OS are we building under?
- $build_os = `uname`;
- chomp $build_os;
- $build_cpu = `uname -p`;
- chomp $build_cpu;
+ $target_os = '@target_os@';
+ $target_windows = 0;
+ $target_windows = 1 if $target_os =~ m'^mingw32'
+ or $target_os eq "winnt";
+
+ if ($^O eq "MSWin32" and not -x "/usr/bin/uname")
+ {
+ $build_os = "winnt";
+ $build_cpu = "ix86";
+ }
+ else
+ {
+ $build_os = `uname`;
+ chomp $build_os;
+ $build_cpu = `uname -m`;
+ chomp $build_cpu;
+ }
+
# Cygwin Builds usually something like CYGWIN_NT-5.0, CYGWIN_NT-5.1
# Box Backup tried on Win2000,XP only :)
@@ -24,11 +38,18 @@
$platform_compile_line_extra =~ s/ -O2//;
$platform_link_line_extra = '@LDFLAGS@';
$platform_lib_files = '@LIBS@';
- $target_os = '@target_os@';
$platform_exe_ext = '@EXEEXT@';
# get version
- open VERSION,"VERSION.txt" or die "VERSION.txt: $!";
+ if (! -r "VERSION.txt" and -r "../../VERSION.txt")
+ {
+ open VERSION,"../../VERSION.txt" or die "../../VERSION.txt: $!";
+ }
+ else
+ {
+ open VERSION,"VERSION.txt" or die "VERSION.txt: $!";
+ }
+
$product_version = <VERSION>;
chomp $product_version;
$product_name = <VERSION>;
@@ -89,5 +110,34 @@
return $_[0].'=1';
}
+sub update_if_changed ($)
+{
+ my ($file) = @_;
+ die "$file.new: not found" unless -r "$file.new";
+
+ if (-r $file)
+ {
+ die "$file.new: not found" unless -r "$file.new";
+ if (system("diff --brief $file $file.new") == 0)
+ {
+ unlink "$file.new";
+ return;
+ }
+ }
+
+ if (system("cp $file.new $file") != 0)
+ {
+ die "failed to copy $file.new to $file";
+ }
+
+ if (system("diff --brief $file $file.new") != 0)
+ {
+ die "$file and $file.new are still different";
+ }
+
+ unlink "$file.new";
+ return;
+}
+
1;
Modified: box/chris/merge/infrastructure/buildenv-testmain-template.cpp
===================================================================
--- box/chris/merge/infrastructure/buildenv-testmain-template.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/infrastructure/buildenv-testmain-template.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -41,6 +41,8 @@
#endif
int failures = 0;
+int first_fail_line;
+std::string first_fail_file;
int filedes_open_at_beginning = -1;
@@ -128,7 +130,10 @@
}
if(failures > 0)
{
- printf("FAILED: %d tests failed\n", failures);
+ printf("FAILED: %d tests failed (first at "
+ "%s:%d)\n", failures,
+ first_fail_file.c_str(),
+ first_fail_line);
}
else
{
Modified: box/chris/merge/infrastructure/makebuildenv.pl.in
===================================================================
--- box/chris/merge/infrastructure/makebuildenv.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/infrastructure/makebuildenv.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -14,9 +14,8 @@
print "Box build environment setup.\n\n";
+my @implicit_deps = ('lib/common');
-my $implicit_dep = 'lib/common';
-
# work out platform variables
use lib 'infrastructure';
use BoxPlatform;
@@ -38,12 +37,16 @@
# flags about the environment
my %env_flags;
-my $windows_include_path = "-I../../lib/win32 ";
-if ($target_os ne "mingw32" && $target_os ne "winnt")
+my $windows_include_path = "";
+if ($target_windows)
{
- $windows_include_path = "";
- $env_flags{'IGNORE_lib/win32'} = 1;
+ $module_dependency{"lib/common"} = ["lib/win32"];
+ push @implicit_deps, "lib/win32";
}
+else
+{
+ # $env_flags{'IGNORE_lib/win32'} = 1;
+}
# print "Flag: $_\n" for(keys %env_flags);
@@ -111,7 +114,7 @@
print "done\n\n";
-# open test mail program template file
+# open test main program template file
my $test_template_file = 'infrastructure/buildenv-testmain-template.cpp';
open FL,$test_template_file or die "Can't open test template file\n";
my $test_template;
@@ -271,7 +274,7 @@
push @md,$_ unless ignore_module($_)
}
}
- $module_dependency{$mod} = [$implicit_dep, at md];
+ $module_dependency{$mod} = [@implicit_deps, at md];
$module_library_link_opts{$mod} = [@lo];
# make directories, but not if we're using an external library and this a library module
@@ -286,17 +289,21 @@
}
# make dirs for implicit dep
-mkdir "release/$implicit_dep",0755;
-mkdir "debug/$implicit_dep",0755;
+foreach my $dep (@implicit_deps)
+{
+ mkdir "release/$dep",0755;
+ mkdir "debug/$dep",0755;
+}
# write a list of all the modules we've configured to use
-open CONFIGURED_MODS,'>local/modules.h' or die "Can't write configured modules list";
+open CONFIGURED_MODS,'>local/modules.h.new' or die
+ "Can't write configured modules list";
print CONFIGURED_MODS <<__E;
// automatically generated file, do not edit
#ifndef _CONFIGURED_MODULES__H
#define _CONFIGURED_MODULES__H
__E
-for($implicit_dep, at modules)
+for(@implicit_deps, at modules)
{
my $m = $_;
$m =~ s~/~_~;
@@ -306,11 +313,11 @@
#endif // _CONFIGURED_MODULES__H
__E
close CONFIGURED_MODS;
+update_if_changed("local/modules.h");
-
# now make a list of all the .h files we can find, recording which module they're in
my %hfiles;
-for my $mod (@modules, $implicit_dep)
+for my $mod (@modules, @implicit_deps)
{
opendir DIR,$mod;
my @items = readdir DIR;
@@ -347,7 +354,7 @@
}
}
-for my $mod (@modules, $implicit_dep)
+for my $mod (@modules, @implicit_deps)
{
opendir DIR,$mod;
for my $h (grep /\.h\Z/i, readdir DIR)
@@ -373,9 +380,10 @@
print "done\n\nGenerating Makefiles...\n";
+my %module_resources_win32;
# Then write a makefile for each module
-for my $mod (@modules, $implicit_dep)
+for my $mod (@implicit_deps, @modules)
{
print $mod,"\n";
@@ -386,15 +394,19 @@
{
my $testmain = $test_template;
$testmain =~ s/TEST_NAME/$name/g;
- open TESTMAIN,">$mod/_main.cpp" or die "Can't open test main file for $mod for writing\n";
+ open TESTMAIN,">$mod/_main.cpp.new" or die
+ "Can't open test main file for $mod for writing\n";
print TESTMAIN $testmain;
close TESTMAIN;
+ update_if_changed("$mod/_main.cpp");
# test file...
sub writetestfile
{
my ($filename,$runcmd,$module) = @_;
- open TESTFILE,">$filename" or die "Can't open test script file for $module for writing\n";
+ open TESTFILE,">$filename.new" or die
+ "Can't open test script file for $module " .
+ "for writing\n";
print TESTFILE "#!/bin/sh\necho TEST: $module\n";
if(-d "$module/testfiles")
{
@@ -413,12 +425,13 @@
}
print TESTFILE "$runcmd\n";
close TESTFILE;
+ update_if_changed($filename);
}
writetestfile("$mod/_t",
- './test' . $platform_exe_ext . '$1 $2 $3 $4 $5', $mod);
+ './test' . $platform_exe_ext . ' $1 $2 $3 $4 $5', $mod);
writetestfile("$mod/_t-gdb",
- 'gdb ./test ' . $platform_exe_ext, $mod);
+ 'gdb ./test' . $platform_exe_ext, $mod);
}
@@ -441,14 +454,14 @@
add_mod_deps(\@deps_raw, $mod);
# and then dedup and reorder them
my %d_done;
- for(my $a = $#deps_raw; $a >= 0; $a--)
+ foreach my $dep (reverse @deps_raw)
{
- if(!exists $d_done{$deps_raw[$a]})
+ if(!exists $d_done{$dep})
{
# insert
- push @all_deps_for_module, $deps_raw[$a];
+ push @all_deps_for_module, $dep;
# mark as done
- $d_done{$deps_raw[$a]} = 1;
+ $d_done{$dep} = 1;
}
}
}
@@ -480,11 +493,12 @@
# start the makefile
my $mk_name_extra = ($bsd_make)?'':'X';
- open MAKE,">$mod/Makefile".$mk_name_extra or die "Can't open Makefile for $mod\n";
+ open MAKE,">$mod/Makefile".$mk_name_extra.".new" or die
+ "Can't open Makefile for $mod\n";
my $debug_link_extra = ($target_is_library)?'':'../../debug/lib/debug/debug.a';
my $release_flags = "-O2";
- if ($target_os eq "mingw32")
+ if ($target_windows)
{
$release_flags = "-O0 -g";
}
@@ -499,6 +513,7 @@
AR = ar
RANLIB = ranlib
PERL = "@PERL@"
+WINDRES = windres
.ifdef RELEASE
CXXFLAGS = -DNDEBUG $release_flags -Wall $include_paths $extra_platform_defines -DBOX_VERSION="\\"$product_version\\""
OUTBASE = ../../release
@@ -546,7 +561,7 @@
@items = (@items, @autogen_items);
}
- # first, obtain a list of depenencies within the .h files
+ # first, obtain a list of dependencies within the .h files
my %headers;
for my $h (grep /\.h\Z/i, @items)
{
@@ -566,19 +581,30 @@
# then... do the cpp files...
my @obj_base;
- for my $cpp (@items)
+ for my $file (@items)
{
- next unless $cpp =~ m/\A(.+)\.cpp\Z/i;
- next if $cpp =~ /\A\._/; # Temp Mac OS Resource hack
+ my $is_cpp = $file =~ m/\A(.+)\.cpp\Z/i;
+ my $is_rc = $file =~ m/\A(.+)\.rc\Z/i;
+ my $base = $1;
+ if ($target_windows)
+ {
+ next if not $is_cpp and not $is_rc;
+ }
+ else
+ {
+ next if not $is_cpp;
+ }
+
+ next if $file =~ /\A\._/; # Temp Mac OS Resource hack
+
# store for later
- my $base = $1;
push @obj_base,$base;
# get the file...
- open FL,"$mod/$cpp";
+ open FL,"$mod/$file";
my $f;
- read FL,$f,-s "$mod/$cpp";
+ read FL,$f,-s "$mod/$file";
close FL;
my %dep;
@@ -592,10 +618,29 @@
my $out_name = '$(OUTDIR)/'.$base.'.o';
# write the line for this cpp file
- $make .= $out_name.': '.join(' ',$cpp,map
- { ($hfiles{$_} eq $mod)?$_:'../../'.$hfiles{$_}."/$_" } keys %dep)."\n";
- $make .= "\t\$(CXX) \$(CXXFLAGS) $compile_line_extra -c $cpp -o $out_name\n\n";
+ my @dep_paths = map
+ {
+ ($hfiles{$_} eq $mod)
+ ? $_
+ : '../../'.$hfiles{$_}."/$_"
+ }
+ keys %dep;
+ $make .= $out_name.': '.join(' ',$file, at dep_paths)."\n";
+
+ if ($is_cpp)
+ {
+ $make .= "\t\$(CXX) \$(CXXFLAGS) $compile_line_extra ".
+ "-c $file -o $out_name\n\n";
+ }
+ elsif ($is_rc)
+ {
+ $make .= "\t\$(WINDRES) $file $out_name\n\n";
+ my $res_list = $module_resources_win32{$mod};
+ $res_list ||= [];
+ push @$res_list, $base.'.o';
+ $module_resources_win32{$mod} = $res_list;
+ }
}
my $has_deps = ($#{$module_dependency{$mod}} >= 0);
@@ -647,11 +692,28 @@
additional_objects_from_make_fragment("$mod/Makefile.extra.$build_os", \@objs, \@makefile_includes);
my $o_file_list = join(' ',map {'$(OUTDIR)/'.$_.'.o'} @objs);
+
+ if ($has_deps and not $bsd_make)
+ {
+ print MAKE ".PHONY: all\n" .
+ "all: dep_modules $end_target\n\n";
+ }
+
print MAKE $end_target,': ',$o_file_list;
- print MAKE ' dep_modules' if $has_deps and not $bsd_make;
print MAKE " ",$lib_files unless $target_is_library;
print MAKE "\n";
+ if ($target_windows)
+ {
+ foreach my $dep (@all_deps_for_module)
+ {
+ my $res_list = $module_resources_win32{$dep};
+ next unless $res_list;
+ $o_file_list .= ' '.join(' ',
+ map {'$(OUTBASE)/'.$dep."/$_"} @$res_list);
+ }
+ }
+
# stuff to make the final target...
if($target_is_library)
{
@@ -730,8 +792,8 @@
if(!$bsd_make)
{
# need to post process this into a GNU makefile
- open MAKE,">$mod/Makefile";
- open MAKEB,"$mod/MakefileX";
+ open MAKE,">$mod/Makefile.new" or die $!;
+ open MAKEB,"$mod/MakefileX.new" or die $!;
while(<MAKEB>)
{
@@ -743,8 +805,10 @@
close MAKEB;
close MAKE;
- unlink "$mod/MakefileX";
+ unlink "$mod/MakefileX.new";
}
+
+ update_if_changed("$mod/Makefile");
}
print "\nType 'cd <module_dir>; $make_command' to build a module\n\n";
Deleted: box/chris/merge/infrastructure/msvc/2003/boxbackup.ncb
===================================================================
(Binary files differ)
Deleted: box/chris/merge/infrastructure/msvc/2003/boxbackup.suo
===================================================================
(Binary files differ)
Modified: box/chris/merge/lib/backupclient/BackupClientFileAttributes.cpp
===================================================================
--- box/chris/merge/lib/backupclient/BackupClientFileAttributes.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/backupclient/BackupClientFileAttributes.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -642,6 +642,7 @@
}
// If working as root, set user IDs
+ #ifndef WIN32
if(::geteuid() == 0)
{
#ifndef HAVE_LCHOWN
@@ -661,6 +662,7 @@
}
#endif
}
+ #endif
if(static_cast<int>(xattrOffset+sizeof(u_int32_t))<=mpClearAttributes->GetSize())
{
Modified: box/chris/merge/lib/backupclient/BackupStoreFile.cpp
===================================================================
--- box/chris/merge/lib/backupclient/BackupStoreFile.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/backupclient/BackupStoreFile.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -289,6 +289,8 @@
// Copy it out to the file
stream->CopyStreamTo(out);
}
+
+ out.Close();
// Write the attributes
stream->GetAttributes().WriteAttributes(DecodedFilename);
Modified: box/chris/merge/lib/backupclient/BackupStoreObjectDump.cpp
===================================================================
--- box/chris/merge/lib/backupclient/BackupStoreObjectDump.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/backupclient/BackupStoreObjectDump.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -113,7 +113,13 @@
// Output item
int16_t f = (*i)->GetFlags();
- OutputLine(file, ToTrace, "%06llx %4lld %016llx %4d %3d %4d%s%s%s%s%s%s\n",
+#ifdef WIN32
+ OutputLine(file, ToTrace,
+ "%06I64x %4I64d %016I64x %4d %3d %4d%s%s%s%s%s%s\n",
+#else
+ OutputLine(file, ToTrace,
+ "%06llx %4lld %016llx %4d %3d %4d%s%s%s%s%s%s\n",
+#endif
(*i)->GetObjectID(),
(*i)->GetSizeInBlocks(),
(*i)->GetAttributesHash(),
Modified: box/chris/merge/lib/backupstore/BackupStoreAccounts.cpp
===================================================================
--- box/chris/merge/lib/backupstore/BackupStoreAccounts.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/backupstore/BackupStoreAccounts.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -141,8 +141,9 @@
std::string BackupStoreAccounts::MakeAccountRootDir(int32_t ID, int DiscSet) const
{
char accid[64]; // big enough!
- ::sprintf(accid, "%08x/", ID);
- return std::string(std::string(BOX_RAIDFILE_ROOT_BBSTORED DIRECTORY_SEPARATOR) + accid);
+ ::sprintf(accid, "%08x" DIRECTORY_SEPARATOR, ID);
+ return std::string(std::string(BOX_RAIDFILE_ROOT_BBSTORED
+ DIRECTORY_SEPARATOR) + accid);
}
Modified: box/chris/merge/lib/backupstore/BackupStoreCheck.cpp
===================================================================
--- box/chris/merge/lib/backupstore/BackupStoreCheck.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/backupstore/BackupStoreCheck.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -328,7 +328,8 @@
std::string dirName;
StoreStructure::MakeObjectFilename(StartID, mStoreRoot, mDiscSetNumber, dirName, false /* don't make sure the dir exists */);
// Check expectations
- ASSERT(dirName.size() > 4 && dirName[dirName.size() - 4] == '/');
+ ASSERT(dirName.size() > 4 &&
+ dirName[dirName.size() - 4] == DIRECTORY_SEPARATOR_ASCHAR);
// Remove the filename from it
dirName.resize(dirName.size() - 4); // four chars for "/o00"
@@ -377,7 +378,9 @@
if(!fileOK)
{
// Unexpected or bad file, delete it
- ::printf("Spurious file %s/%s found%s\n", dirName.c_str(), (*i).c_str(), mFixErrors?", deleting":"");
+ ::printf("Spurious file %s" DIRECTORY_SEPARATOR "%s "
+ "found%s\n", dirName.c_str(), (*i).c_str(),
+ mFixErrors?", deleting":"");
++mNumberErrorsFound;
if(mFixErrors)
{
Modified: box/chris/merge/lib/common/BoxPlatform.h
===================================================================
--- box/chris/merge/lib/common/BoxPlatform.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/common/BoxPlatform.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -40,8 +40,8 @@
#endif
#endif
-// Slight hack; disable interception on Darwin within raidfile test
-#ifdef __APPLE__
+// Slight hack; disable interception in raidfile test on Darwin and Windows
+#if defined __APPLE__ || defined WIN32
// TODO: Replace with autoconf test
#define PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
#endif
@@ -138,6 +138,11 @@
#define INFTIM -1
#endif
+// for Unix compatibility with Windows :-)
+#if !HAVE_DECL_O_BINARY
+ #define O_BINARY 0
+#endif
+
#ifdef WIN32
typedef u_int64_t InodeRefType;
#else
Modified: box/chris/merge/lib/common/FdGetLine.h
===================================================================
--- box/chris/merge/lib/common/FdGetLine.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/common/FdGetLine.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -14,6 +14,10 @@
#ifdef NDEBUG
#define FDGETLINE_BUFFER_SIZE 1024
+#elif defined WIN32
+ // need enough space for at least one unicode character
+ // in UTF-8 when calling console_read() from bbackupquery
+ #define FDGETLINE_BUFFER_SIZE 5
#else
#define FDGETLINE_BUFFER_SIZE 4
#endif
Modified: box/chris/merge/lib/common/Guards.h
===================================================================
--- box/chris/merge/lib/common/Guards.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/common/Guards.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -24,7 +24,7 @@
#include "MemLeakFindOn.h"
-template <int flags = O_RDONLY, int mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)>
+template <int flags = O_RDONLY | O_BINARY, int mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)>
class FileHandleGuard
{
public:
Modified: box/chris/merge/lib/common/UnixUser.cpp
===================================================================
--- box/chris/merge/lib/common/UnixUser.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/common/UnixUser.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -75,6 +75,7 @@
// --------------------------------------------------------------------------
UnixUser::~UnixUser()
{
+#ifndef WIN32
if(mRevertOnDestruction)
{
// Revert to "real" user and group id of the process
@@ -84,6 +85,7 @@
THROW_EXCEPTION(CommonException, CouldNotRestoreProcessUser)
}
}
+#endif
}
@@ -98,6 +100,7 @@
// --------------------------------------------------------------------------
void UnixUser::ChangeProcessUser(bool Temporary)
{
+#ifndef WIN32
if(Temporary)
{
// Change temporarily (change effective only)
@@ -119,6 +122,7 @@
THROW_EXCEPTION(CommonException, CouldNotChangeProcessUser)
}
}
+#endif
}
Modified: box/chris/merge/lib/common/makeexception.pl.in
===================================================================
--- box/chris/merge/lib/common/makeexception.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/common/makeexception.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,9 +1,11 @@
#!@PERL@
+use lib "../../infrastructure";
+use BoxPlatform;
+
# global exception list file
my $global_list = '../../ExceptionCodes.txt';
-
my @exception;
my @exception_desc;
my $class;
@@ -46,8 +48,8 @@
# write the code
print "Generating $class exception...\n";
-open CPP,">autogen_${class}Exception.cpp" or die "Can't open cpp file for writing";
-open H,">autogen_${class}Exception.h" or die "Can't open h file for writing";
+open CPP,">autogen_${class}Exception.cpp.new" or die "Can't open cpp file for writing";
+open H,">autogen_${class}Exception.h.new" or die "Can't open h file for writing";
# write header file
my $guardname = uc 'AUTOGEN_'.$class.'EXCEPTION_H';
@@ -200,6 +202,9 @@
close H;
close CPP;
+update_if_changed("autogen_${class}Exception.cpp");
+update_if_changed("autogen_${class}Exception.h");
+
# update the global exception list
my $list_before;
my $list_after;
Modified: box/chris/merge/lib/raidfile/RaidFileRead.cpp
===================================================================
--- box/chris/merge/lib/raidfile/RaidFileRead.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/raidfile/RaidFileRead.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -14,10 +14,20 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
+
+#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif
+
#include <stdarg.h>
+
+#ifdef HAVE_DIRENT_H
#include <dirent.h>
+#endif
#include <stdio.h>
#include <string.h>
@@ -583,7 +593,8 @@
// Open the parity file
std::string parityFilename(RaidFileUtil::MakeRaidComponentName(rdiscSet, mFilename, (2 + startDisc) % READ_NUMBER_DISCS_REQUIRED));
- mParityHandle = ::open(parityFilename.c_str(), O_RDONLY, 0555);
+ mParityHandle = ::open(parityFilename.c_str(),
+ O_RDONLY | O_BINARY, 0555);
if(mParityHandle == -1)
{
THROW_EXCEPTION(RaidFileException, OSError)
@@ -1017,7 +1028,8 @@
std::string writeFilename(RaidFileUtil::MakeWriteFileName(rdiscSet, Filename));
// Attempt to open
- int osFileHandle = ::open(writeFilename.c_str(), O_RDONLY, 0);
+ int osFileHandle = ::open(writeFilename.c_str(),
+ O_RDONLY | O_BINARY, 0);
if(osFileHandle == -1)
{
THROW_EXCEPTION(RaidFileException, ErrorOpeningFileForRead)
@@ -1055,13 +1067,15 @@
try
{
// Open stripe1
- stripe1 = ::open(stripe1Filename.c_str(), O_RDONLY, 0555);
+ stripe1 = ::open(stripe1Filename.c_str(),
+ O_RDONLY | O_BINARY, 0555);
if(stripe1 == -1)
{
stripe1errno = errno;
}
// Open stripe2
- stripe2 = ::open(stripe2Filename.c_str(), O_RDONLY, 0555);
+ stripe2 = ::open(stripe2Filename.c_str(),
+ O_RDONLY | O_BINARY, 0555);
if(stripe2 == -1)
{
stripe2errno = errno;
@@ -1169,7 +1183,8 @@
// Open stripe1?
if(existingFiles & RaidFileUtil::Stripe1Exists)
{
- stripe1 = ::open(stripe1Filename.c_str(), O_RDONLY, 0555);
+ stripe1 = ::open(stripe1Filename.c_str(),
+ O_RDONLY | O_BINARY, 0555);
if(stripe1 == -1)
{
THROW_EXCEPTION(RaidFileException, OSError)
@@ -1178,14 +1193,16 @@
// Open stripe2?
if(existingFiles & RaidFileUtil::Stripe2Exists)
{
- stripe2 = ::open(stripe2Filename.c_str(), O_RDONLY, 0555);
+ stripe2 = ::open(stripe2Filename.c_str(),
+ O_RDONLY | O_BINARY, 0555);
if(stripe2 == -1)
{
THROW_EXCEPTION(RaidFileException, OSError)
}
}
// Open parity
- parity = ::open(parityFilename.c_str(), O_RDONLY, 0555);
+ parity = ::open(parityFilename.c_str(),
+ O_RDONLY | O_BINARY, 0555);
if(parity == -1)
{
THROW_EXCEPTION(RaidFileException, OSError)
Modified: box/chris/merge/lib/raidfile/RaidFileWrite.cpp
===================================================================
--- box/chris/merge/lib/raidfile/RaidFileWrite.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/raidfile/RaidFileWrite.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -104,7 +104,8 @@
writeFilename += 'X';
// Attempt to open
- mOSFileHandle = ::open(writeFilename.c_str(), O_WRONLY | O_CREAT,
+ mOSFileHandle = ::open(writeFilename.c_str(),
+ O_WRONLY | O_CREAT | O_BINARY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if(mOSFileHandle == -1)
{
@@ -115,7 +116,7 @@
#ifdef HAVE_FLOCK
int errnoBlock = EWOULDBLOCK;
if(::flock(mOSFileHandle, LOCK_EX | LOCK_NB) != 0)
-#else
+#elif HAVE_DECL_F_SETLK
int errnoBlock = EAGAIN;
struct flock desc;
desc.l_type = F_WRLCK;
@@ -123,6 +124,9 @@
desc.l_start = 0;
desc.l_len = 0;
if(::fcntl(mOSFileHandle, F_SETLK, &desc) != 0)
+#else
+ int errnoBlock = ENOSYS;
+ if (0)
#endif
{
// Lock was not obtained.
@@ -242,23 +246,46 @@
}
// Rename it into place -- BEFORE it's closed so lock remains
+
+#ifdef WIN32
+ // Except on Win32 which doesn't allow renaming open files
+ // Close file...
+ if(::close(mOSFileHandle) != 0)
+ {
+ THROW_EXCEPTION(RaidFileException, OSError)
+ }
+ mOSFileHandle = -1;
+#endif // WIN32
+
RaidFileController &rcontroller(RaidFileController::GetController());
RaidFileDiscSet rdiscSet(rcontroller.GetDiscSet(mSetNumber));
// Get the filename for the write file
std::string renameTo(RaidFileUtil::MakeWriteFileName(rdiscSet, mFilename));
// And the current name
std::string renameFrom(renameTo + 'X');
+
+#ifdef WIN32
+ // need to delete the target first
+ if(::unlink(renameTo.c_str()) != 0 &&
+ GetLastError() != ERROR_FILE_NOT_FOUND)
+ {
+ THROW_EXCEPTION(RaidFileException, OSError)
+ }
+#endif
+
if(::rename(renameFrom.c_str(), renameTo.c_str()) != 0)
{
THROW_EXCEPTION(RaidFileException, OSError)
}
+#ifndef WIN32
// Close file...
if(::close(mOSFileHandle) != 0)
{
THROW_EXCEPTION(RaidFileException, OSError)
}
mOSFileHandle = -1;
+#endif // !WIN32
// Raid it?
if(ConvertToRaidNow)
@@ -292,8 +319,15 @@
writeFilename += 'X';
// Unlink and close it
- if((::unlink(writeFilename.c_str()) != 0)
- || (::close(mOSFileHandle) != 0))
+
+#ifdef WIN32
+ // On Win32 we must close it first
+ if (::close(mOSFileHandle) != 0 ||
+ ::unlink(writeFilename.c_str()) != 0)
+#else // !WIN32
+ if (::unlink(writeFilename.c_str()) != 0 ||
+ ::close(mOSFileHandle) != 0)
+#endif // !WIN32
{
THROW_EXCEPTION(RaidFileException, OSError)
}
@@ -388,13 +422,13 @@
try
{
#if HAVE_DECL_O_EXLOCK
- FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK)> stripe1(stripe1FilenameW.c_str());
- FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK)> stripe2(stripe2FilenameW.c_str());
- FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK)> parity(parityFilenameW.c_str());
+ FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK | O_BINARY)> stripe1(stripe1FilenameW.c_str());
+ FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK | O_BINARY)> stripe2(stripe2FilenameW.c_str());
+ FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK | O_BINARY)> parity(parityFilenameW.c_str());
#else
- FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL)> stripe1(stripe1FilenameW.c_str());
- FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL)> stripe2(stripe2FilenameW.c_str());
- FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL)> parity(parityFilenameW.c_str());
+ FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_BINARY)> stripe1(stripe1FilenameW.c_str());
+ FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_BINARY)> stripe2(stripe2FilenameW.c_str());
+ FileHandleGuard<(O_WRONLY | O_CREAT | O_EXCL | O_BINARY)> parity(parityFilenameW.c_str());
#endif
// Then... read in data...
@@ -530,6 +564,21 @@
parity.Close();
stripe2.Close();
stripe1.Close();
+
+#ifdef WIN32
+ // Must delete before renaming
+ #define CHECK_UNLINK(file) \
+ { \
+ if (::unlink(file) != 0 && errno != ENOENT) \
+ { \
+ THROW_EXCEPTION(RaidFileException, OSError); \
+ } \
+ }
+ CHECK_UNLINK(stripe1Filename.c_str());
+ CHECK_UNLINK(stripe2Filename.c_str());
+ CHECK_UNLINK(parityFilename.c_str());
+ #undef CHECK_UNLINK
+#endif
// Rename them into place
if(::rename(stripe1FilenameW.c_str(), stripe1Filename.c_str()) != 0
Modified: box/chris/merge/lib/server/Daemon.cpp
===================================================================
--- box/chris/merge/lib/server/Daemon.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/server/Daemon.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -23,6 +23,10 @@
#include <syslog.h>
#endif
+#ifdef WIN32
+ #include <ws2tcpip.h>
+#endif
+
#include "Daemon.h"
#include "Configuration.h"
#include "ServerException.h"
@@ -142,7 +146,7 @@
{
fprintf(stderr, "%s: failed to start: "
"failed to open configuration file: "
- "%s", DaemonName(),
+ "%s\n", DaemonName(),
mConfigFileName.c_str());
#ifdef WIN32
::syslog(LOG_ERR, "%s: failed to start: "
@@ -189,6 +193,7 @@
{
THROW_EXCEPTION(ServerException, DaemoniseFailed)
}
+#endif // !WIN32
// Server configuration
const Configuration &serverConfig(
@@ -197,7 +202,8 @@
// Open PID file for writing
pidFileName = serverConfig.GetKeyValue("PidFile");
FileHandleGuard<(O_WRONLY | O_CREAT | O_TRUNC), (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)> pidFile(pidFileName.c_str());
-
+
+#ifndef WIN32
// Handle changing to a different user
if(serverConfig.KeyExists("User"))
{
@@ -267,20 +273,25 @@
// open the log
::openlog(DaemonName(), LOG_PID, LOG_LOCAL6);
+
// Log the start message
::syslog(LOG_INFO, "Starting daemon (config: %s) (version "
BOX_VERSION ")", mConfigFileName.c_str());
-#ifndef WIN32
// Write PID to file
char pid[32];
+
+#ifdef WIN32
+ int pidsize = sprintf(pid, "%d", (int)GetCurrentProcessId());
+#else
int pidsize = sprintf(pid, "%d", (int)getpid());
+#endif
+
if(::write(pidFile, pid, pidsize) != pidsize)
{
::syslog(LOG_ERR, "can't write pid file");
THROW_EXCEPTION(ServerException, DaemoniseFailed)
}
-#endif
// Set up memory leak reporting
#ifdef BOX_MEMORY_LEAK_TESTING
@@ -352,6 +363,22 @@
#endif
return 1;
}
+
+#ifdef WIN32
+ // Under win32 we must initialise the Winsock library
+ // before using sockets
+
+ WSADATA info;
+
+ if (WSAStartup(0x0101, &info) == SOCKET_ERROR)
+ {
+ // will not run without sockets
+ ::syslog(LOG_ERR, "Failed to initialise Windows Sockets");
+ THROW_EXCEPTION(CommonException, Internal)
+ }
+#endif
+
+ int retcode = 0;
// Main Daemon running
try
@@ -381,7 +408,8 @@
mConfigFileName.c_str(),
errors.c_str());
// And give up
- return 1;
+ retcode = 1;
+ break;
}
// delete old configuration
@@ -409,22 +437,26 @@
::syslog(LOG_ERR, "%s: terminating due to exception %s "
"(%d/%d)", DaemonName(), e.what(), e.GetType(),
e.GetSubType());
- return 1;
+ retcode = 1;
}
catch(std::exception &e)
{
::syslog(LOG_ERR, "%s: terminating due to exception %s",
DaemonName(), e.what());
- return 1;
+ retcode = 1;
}
catch(...)
{
::syslog(LOG_ERR, "%s: terminating due to unknown exception",
DaemonName());
- return 1;
+ retcode = 1;
}
+
+#ifdef WIN32
+ WSACleanup();
+#endif
- return 0;
+ return retcode;
}
// --------------------------------------------------------------------------
Modified: box/chris/merge/lib/server/ServerStream.h
===================================================================
--- box/chris/merge/lib/server/ServerStream.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/server/ServerStream.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -56,6 +56,10 @@
return "generic-stream-server";
}
+ #ifdef WIN32
+ virtual void OnIdle() { }
+ #endif
+
virtual void Run()
{
// Set process title as appropraite
@@ -215,6 +219,7 @@
if(connection.get())
{
// Since this is a template parameter, the if() will be optimised out by the compiler
+ #ifndef WIN32 // no fork on Win32
if(ForkToHandleRequests)
{
pid_t pid = ::fork();
@@ -255,14 +260,20 @@
}
else
{
+ #endif // !WIN32
// Just handle in this connection
SetProcessTitle("handling");
HandleConnection(*connection);
SetProcessTitle("idle");
+ #ifndef WIN32
}
+ #endif // !WIN32
}
}
-
+
+ #ifdef WIN32
+ OnIdle();
+ #else // !WIN32
// Clean up child processes (if forking daemon)
if(ForkToHandleRequests)
{
@@ -277,6 +288,7 @@
}
} while(p > 0);
}
+ #endif // !WIN32
}
}
catch(...)
@@ -301,7 +313,11 @@
// depends on the forking model in case someone changes it later.
bool WillForkToHandleRequests()
{
+ #ifdef WIN32
+ return false;
+ #else
return ForkToHandleRequests;
+ #endif // WIN32
}
private:
Modified: box/chris/merge/lib/server/SocketStream.cpp
===================================================================
--- box/chris/merge/lib/server/SocketStream.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/server/SocketStream.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -36,7 +36,7 @@
//
// --------------------------------------------------------------------------
SocketStream::SocketStream()
- : mSocketHandle(-1),
+ : mSocketHandle(INVALID_SOCKET_VALUE),
mReadClosed(false),
mWriteClosed(false),
mBytesRead(0),
@@ -85,7 +85,7 @@
{
THROW_EXCEPTION(ServerException, BadSocketHandle);
}
- if(mSocketHandle == -1)
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
{
THROW_EXCEPTION(ServerException, DupError);
}
@@ -101,7 +101,7 @@
// --------------------------------------------------------------------------
SocketStream::~SocketStream()
{
- if(mSocketHandle != -1)
+ if(mSocketHandle != INVALID_SOCKET_VALUE)
{
Close();
}
@@ -117,7 +117,10 @@
// --------------------------------------------------------------------------
void SocketStream::Attach(int socket)
{
- if(mSocketHandle != -1) {THROW_EXCEPTION(ServerException, SocketAlreadyOpen)}
+ if(mSocketHandle != INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, SocketAlreadyOpen)
+ }
mSocketHandle = socket;
ResetCounters();
@@ -134,7 +137,10 @@
// --------------------------------------------------------------------------
void SocketStream::Open(int Type, const char *Name, int Port)
{
- if(mSocketHandle != -1) {THROW_EXCEPTION(ServerException, SocketAlreadyOpen)}
+ if(mSocketHandle != INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, SocketAlreadyOpen)
+ }
// Setup parameters based on type, looking up names if required
int sockDomain = 0;
@@ -144,7 +150,7 @@
// Create the socket
mSocketHandle = ::socket(sockDomain, SOCK_STREAM, 0 /* let OS choose protocol */);
- if(mSocketHandle == -1)
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
{
THROW_EXCEPTION(ServerException, SocketOpenError)
}
@@ -158,7 +164,7 @@
#else
::close(mSocketHandle);
#endif
- mSocketHandle = -1;
+ mSocketHandle = INVALID_SOCKET_VALUE;
THROW_EXCEPTION(ConnectionException, Conn_SocketConnectError)
}
ResetCounters();
@@ -174,7 +180,10 @@
// --------------------------------------------------------------------------
int SocketStream::Read(void *pBuffer, int NBytes, int Timeout)
{
- if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)}
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, BadSocketHandle)
+ }
if(Timeout != IOStream::TimeOutInfinite)
{
@@ -247,7 +256,10 @@
// --------------------------------------------------------------------------
void SocketStream::Write(const void *pBuffer, int NBytes)
{
- if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)}
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, BadSocketHandle)
+ }
// Buffer in byte sized type.
ASSERT(sizeof(char) == 1);
@@ -311,7 +323,10 @@
// --------------------------------------------------------------------------
void SocketStream::Close()
{
- if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)}
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, BadSocketHandle)
+ }
#ifdef WIN32
if(::closesocket(mSocketHandle) == -1)
#else
@@ -320,7 +335,7 @@
{
THROW_EXCEPTION(ServerException, SocketCloseError)
}
- mSocketHandle = -1;
+ mSocketHandle = INVALID_SOCKET_VALUE;
}
// --------------------------------------------------------------------------
@@ -333,7 +348,10 @@
// --------------------------------------------------------------------------
void SocketStream::Shutdown(bool Read, bool Write)
{
- if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)}
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, BadSocketHandle)
+ }
// Do anything?
if(!Read && !Write) return;
@@ -388,7 +406,10 @@
// --------------------------------------------------------------------------
tOSSocketHandle SocketStream::GetSocketHandle()
{
- if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)}
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
+ {
+ THROW_EXCEPTION(ServerException, BadSocketHandle)
+ }
return mSocketHandle;
}
Modified: box/chris/merge/lib/server/SocketStream.h
===================================================================
--- box/chris/merge/lib/server/SocketStream.h 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/server/SocketStream.h 2006-07-27 23:18:35 UTC (rev 710)
@@ -14,8 +14,10 @@
#ifdef WIN32
typedef SOCKET tOSSocketHandle;
+ #define INVALID_SOCKET_VALUE (tOSSocketHandle)(-1)
#else
typedef int tOSSocketHandle;
+ #define INVALID_SOCKET_VALUE -1
#endif
// --------------------------------------------------------------------------
Modified: box/chris/merge/lib/server/SocketStreamTLS.cpp
===================================================================
--- box/chris/merge/lib/server/SocketStreamTLS.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/server/SocketStreamTLS.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -137,8 +137,12 @@
THROW_EXCEPTION(ServerException, TLSAllocationFailed)
}
-#ifndef WIN32
// Make the socket non-blocking so timeouts on Read work
+
+#ifdef WIN32
+ u_long nonblocking = 1;
+ ioctlsocket(socket, FIONBIO, &nonblocking);
+#else // !WIN32
// This is more portable than using ioctl with FIONBIO
int statusFlags = 0;
if(::fcntl(socket, F_GETFL, &statusFlags) < 0
@@ -309,7 +313,7 @@
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
- // wait for the requried data
+ // wait for the required data
// Will only get once around this loop, so don't need to calculate timeout values
if(WaitWhenRetryRequired(se, Timeout) == false)
{
Modified: box/chris/merge/lib/server/makeprotocol.pl.in
===================================================================
--- box/chris/merge/lib/server/makeprotocol.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/lib/server/makeprotocol.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,6 +1,9 @@
#!@PERL@
use strict;
+use lib "../../infrastructure";
+use BoxPlatform;
+
# Make protocol C++ classes from a protocol description file
# built in type info (values are is basic type, C++ typename)
@@ -167,8 +170,8 @@
# open files
my $h_filename = 'autogen_'.$protocol_name.'Protocol'.$type.'.h';
-open CPP,'>autogen_'.$protocol_name.'Protocol'.$type.'.cpp';
-open H,">$h_filename";
+open CPP,'>autogen_'.$protocol_name.'Protocol'.$type.'.cpp.new';
+open H,">$h_filename.new";
print CPP <<__E;
@@ -912,6 +915,8 @@
close H;
close CPP;
+update_if_changed('autogen_'.$protocol_name.'Protocol'.$type.'.cpp');
+update_if_changed($h_filename);
sub obj_is_type
{
@@ -981,8 +986,15 @@
{
# need to translate it
my ($format,$arg) = @{$log_display_types{$ty}};
+ $arg =~ s/VAR/m$nm/g;
+
+ if ($format eq "0x%llx" and $target_windows)
+ {
+ $format = "0x%I64x";
+ $arg = "(uint64_t)$arg";
+ }
+
push @str,$format;
- $arg =~ s/VAR/m$nm/g;
push @arg,$arg;
}
else
Modified: box/chris/merge/runtest.pl.in
===================================================================
--- box/chris/merge/runtest.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/runtest.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,11 +1,14 @@
#!@PERL@
+use strict;
+use warnings;
+
use lib 'infrastructure';
use BoxPlatform;
my ($test_name,$test_mode) = @ARGV;
-$test_mode = 'debug' if $test_mode eq '';
+$test_mode = 'debug' if not defined $test_mode or $test_mode eq '';
if($test_name eq '' || ($test_mode ne 'debug' && $test_mode ne 'release'))
{
@@ -17,15 +20,26 @@
Mode defaults to debug.
__E
- exit(0);
+ exit(2);
}
my @results;
+my $exit_code = 0;
if($test_name ne 'ALL')
{
- # run one test
- runtest($test_name);
+ # run one or more specified test
+ if ($test_name =~ m/,/)
+ {
+ foreach my $test (split m/,/, $test_name)
+ {
+ runtest($test);
+ }
+ }
+ else
+ {
+ runtest($test_name);
+ }
}
else
{
@@ -57,6 +71,8 @@
# report results
print "--------\n",join("\n", at results),"\n";
+exit $exit_code;
+
sub runtest
{
my ($t) = @_;
@@ -67,6 +83,7 @@
if($make_res != 0)
{
push @results,"$t: make failed";
+ $exit_code = 2;
return;
}
@@ -82,8 +99,14 @@
$last = $_ if m/\w/;
}
close RESULTS;
+
chomp $last;
push @results,"$t: $last";
+
+ if ($last ne "PASSED")
+ {
+ $exit_code = 1;
+ }
}
else
{
Modified: box/chris/merge/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/merge/test/backupdiff/testbackupdiff.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/backupdiff/testbackupdiff.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -66,23 +66,21 @@
void make_file_of_zeros(const char *filename, size_t size)
{
- static const size_t bs = 0x10000;
- size_t remSize = size;
- void *b = malloc(bs);
- memset(b, 0, bs);
- FILE *f = fopen(filename, "wb");
+ #ifdef WIN32
+ HANDLE handle = openfile(filename, O_WRONLY | O_CREAT | O_EXCL, 0);
+ TEST_THAT(handle != INVALID_HANDLE_VALUE);
+ SetFilePointer(handle, size, NULL, FILE_BEGIN);
+ TEST_THAT(GetLastError() == NO_ERROR);
+ TEST_THAT(SetEndOfFile(handle) == true);
+ TEST_THAT(CloseHandle(handle) == true);
+ #else
+ int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (fd < 0) perror(filename);
+ TEST_THAT(fd >= 0);
+ TEST_THAT(ftruncate(fd, size) == 0);
+ TEST_THAT(close(fd) == 0);
+ #endif
- // Using largish blocks like this is much faster, while not consuming too much RAM
- while(remSize > bs)
- {
- fwrite(b, bs, 1, f);
- remSize -= bs;
- }
- fwrite(b, remSize, 1, f);
-
- fclose(f);
- free(b);
-
TEST_THAT((size_t)TestGetFileSize(filename) == size);
}
@@ -118,12 +116,20 @@
if(s > 0)
{
nnew++;
+ #ifdef WIN32
+ TRACE2("%8I64d this s=%8I64d", b, s);
+ #else
TRACE2("%8lld this s=%8lld", b, s);
+ #endif
}
else
{
nold++;
+ #ifdef WIN32
+ TRACE2("%8I64d other i=%8I64d", b, 0 - s);
+ #else
TRACE2("%8lld other i=%8lld", b, 0 - s);
+ #endif
}
// Decode the rest
uint64_t iv = box_ntoh64(hdr.mEntryIVBase);
@@ -207,10 +213,18 @@
}
else
{
+#ifdef WIN32
// Emulate the above stage!
+ char src[256], dst[256];
+ sprintf(src, "testfiles\\f%d.diff", to);
+ sprintf(dst, "testfiles\\f%d.encoded", to);
+ TEST_THAT(CopyFile(src, dst, FALSE) != 0)
+#else
+ // Emulate the above stage!
char cmd[256];
sprintf(cmd, "cp testfiles/f%d.diff testfiles/f%d.encoded", to, to);
::system(cmd);
+#endif
}
// Decode it
@@ -355,8 +369,10 @@
{
// Want to trace out all the details
#ifndef NDEBUG
+ #ifndef WIN32
BackupStoreFile::TraceDetailsOfDiffProcess = true;
#endif
+ #endif
// Create all the test files
create_test_files();
@@ -370,6 +386,7 @@
FileStream out("testfiles/f0.encoded", O_WRONLY | O_CREAT | O_EXCL);
std::auto_ptr<IOStream> encoded(BackupStoreFile::EncodeFile("testfiles/f0", 1 /* dir ID */, f0name));
encoded->CopyStreamTo(out);
+ out.Close();
check_encoded_file("testfiles/f0.encoded", 0, 33, 0);
}
@@ -430,6 +447,7 @@
FileStream out("testfiles/f9.zerotest", O_WRONLY | O_CREAT | O_EXCL);
std::auto_ptr<IOStream> encoded(BackupStoreFile::EncodeFile("testfiles/f9", 1 /* dir ID */, fn));
encoded->CopyStreamTo(out);
+ out.Close();
check_encoded_file("testfiles/f9.zerotest", 0, 0, 0);
}
{
@@ -440,6 +458,7 @@
}
}
+#ifndef WIN32
// Check that symlinks aren't diffed
TEST_THAT(::symlink("f2", "testfiles/f2.symlink") == 0)
// And go and diff it against the previous encoded file
@@ -467,8 +486,10 @@
TEST_THAT(completelyDifferent == true);
check_encoded_file("testfiles/f2.symlink.diff", 0, 0, 0);
}
+#endif
- // Check that diffing against a file which isn't "complete" and referes another isn't allowed
+ // Check that diffing against a file which isn't "complete" and
+ // references another isn't allowed
{
FileStream blockindex("testfiles/f1.diff");
BackupStoreFile::MoveStreamPositionToBlockIndex(blockindex);
@@ -480,10 +501,19 @@
0, 0), BackupStoreException, CannotDiffAnIncompleteStoreFile);
}
- // Found a nasty case where files of lots of the same thing sock up lots of processor
- // time -- because of lots of matches found. Check this out!
+ // Found a nasty case where files of lots of the same thing
+ // suck up lots of processor time -- because of lots of matches
+ // found. Check this out!
+
+ #ifdef WIN32
+ ::fprintf(stdout, "Testing diffing two large streams, "
+ "may take a while!\n");
+ ::fflush(stdout);
+ #endif
+
make_file_of_zeros("testfiles/zero.0", 20*1024*1024);
make_file_of_zeros("testfiles/zero.1", 200*1024*1024);
+
// Generate a first encoded file
{
BackupStoreFilenameClear f0name("zero.0");
@@ -503,7 +533,14 @@
2000 /* object ID of the file diffing from */, blockindex, IOStream::TimeOutInfinite,
0, 0));
encoded->CopyStreamTo(out);
+
+ printf("Time taken: %d seconds\n", (int)(time(0) - beginTime));
+
+ #ifdef WIN32
+ TEST_THAT(time(0) < (beginTime + 300));
+ #else
TEST_THAT(time(0) < (beginTime + 40));
+ #endif
}
// Remove zero-files to save disk space
remove("testfiles/zero.0");
Modified: box/chris/merge/test/backupstore/testbackupstore.cpp
===================================================================
--- box/chris/merge/test/backupstore/testbackupstore.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/backupstore/testbackupstore.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -425,7 +425,8 @@
}
free(data);
- unlink("testfiles/test_download");
+ in.Close();
+ TEST_THAT(unlink("testfiles/test_download") == 0);
}
void test_everything_deleted(BackupProtocolClient &protocol, int64_t DirID)
@@ -930,6 +931,7 @@
// Check marker is 0
TEST_THAT(loginConf->GetClientStoreMarker() == 0);
+#ifndef WIN32
// Check that we can't open a new connection which requests write permissions
{
SocketStreamTLS conn;
@@ -941,10 +943,12 @@
ConnectionException, Conn_Protocol_UnexpectedReply);
protocol.QueryFinished();
}
+#endif
// Set the client store marker
protocol.QuerySetClientStoreMarker(0x8732523ab23aLL);
+#ifndef WIN32
// Open a new connection which is read only
SocketStreamTLS connReadOnly;
connReadOnly.Open(context, Socket::TypeINET, hostname, BOX_PORT_BBSTORED);
@@ -963,10 +967,11 @@
// Check client store marker
TEST_THAT(loginConf->GetClientStoreMarker() == 0x8732523ab23aLL);
}
+#else // WIN32
+ BackupProtocolClient& protocolReadOnly(protocol);
+#endif
test_server_1(protocol, protocolReadOnly);
-
-
// Create and upload some test files
int64_t maxID = 0;
for(int t = 0; t < UPLOAD_NUM; ++t)
@@ -1438,11 +1443,15 @@
}
// Finish the connections
+#ifndef WIN32
protocolReadOnly.QueryFinished();
+#endif
protocol.QueryFinished();
// Close logs
+#ifndef WIN32
::fclose(protocolReadOnlyLog);
+#endif
::fclose(protocolLog);
}
@@ -1520,35 +1529,48 @@
// The test block to a file
{
- FileStream f("testfiles/testenc1", O_WRONLY | O_CREAT | O_EXCL);
+ FileStream f("testfiles" DIRECTORY_SEPARATOR
+ "testenc1", O_WRONLY | O_CREAT | O_EXCL);
f.Write(encfile, sizeof(encfile));
}
// Encode it
{
- FileStream out("testfiles/testenc1_enc", O_WRONLY | O_CREAT | O_EXCL);
- BackupStoreFilenameClear name("testfiles/testenc1");
+ FileStream out("testfiles" DIRECTORY_SEPARATOR
+ "testenc1_enc", O_WRONLY | O_CREAT | O_EXCL);
+ BackupStoreFilenameClear name("testfiles"
+ DIRECTORY_SEPARATOR "testenc1");
- std::auto_ptr<IOStream> encoded(BackupStoreFile::EncodeFile("testfiles/testenc1", 32, name));
+ std::auto_ptr<IOStream> encoded(
+ BackupStoreFile::EncodeFile(
+ "testfiles" DIRECTORY_SEPARATOR
+ "testenc1", 32, name));
encoded->CopyStreamTo(out);
}
// Verify it
{
- FileStream enc("testfiles/testenc1_enc");
+ FileStream enc("testfiles" DIRECTORY_SEPARATOR
+ "testenc1_enc");
TEST_THAT(BackupStoreFile::VerifyEncodedFileFormat(enc) == true);
}
// Decode it
{
- FileStream enc("testfiles/testenc1_enc");
- BackupStoreFile::DecodeFile(enc, "testfiles/testenc1_orig", IOStream::TimeOutInfinite);
+ FileStream enc("testfiles" DIRECTORY_SEPARATOR
+ "testenc1_enc");
+ BackupStoreFile::DecodeFile(enc, "testfiles"
+ DIRECTORY_SEPARATOR "testenc1_orig",
+ IOStream::TimeOutInfinite);
}
// Read in rebuilt original, and compare contents
{
- TEST_THAT(TestGetFileSize("testfiles/testenc1_orig") == sizeof(encfile));
- FileStream in("testfiles/testenc1_orig");
+ TEST_THAT(TestGetFileSize("testfiles"
+ DIRECTORY_SEPARATOR "testenc1_orig")
+ == sizeof(encfile));
+ FileStream in("testfiles" DIRECTORY_SEPARATOR
+ "testenc1_orig");
int encfile_i[ENCFILE_SIZE];
in.Read(encfile_i, sizeof(encfile_i));
TEST_THAT(memcmp(encfile, encfile_i, sizeof(encfile)) == 0);
@@ -1556,7 +1578,8 @@
// Check how many blocks it had, and test the stream based interface
{
- FileStream enc("testfiles/testenc1_enc");
+ FileStream enc("testfiles" DIRECTORY_SEPARATOR
+ "testenc1_enc");
std::auto_ptr<BackupStoreFile::DecodedStream> decoded(BackupStoreFile::DecodeFileStream(enc, IOStream::TimeOutInfinite));
CollectInBufferStream d;
decoded->CopyStreamTo(d, IOStream::TimeOutInfinite, 971 /* buffer block size */);
@@ -1570,10 +1593,15 @@
// Test that the last block in a file, if less than 256 bytes, gets put into the last block
{
#define FILE_SIZE_JUST_OVER ((4096*2)+58)
- FileStream f("testfiles/testenc2", O_WRONLY | O_CREAT | O_EXCL);
+ FileStream f("testfiles" DIRECTORY_SEPARATOR
+ "testenc2", O_WRONLY | O_CREAT | O_EXCL);
f.Write(encfile + 2, FILE_SIZE_JUST_OVER);
+ f.Close();
BackupStoreFilenameClear name("testenc2");
- std::auto_ptr<IOStream> encoded(BackupStoreFile::EncodeFile("testfiles/testenc2", 32, name));
+ std::auto_ptr<IOStream> encoded(
+ BackupStoreFile::EncodeFile(
+ "testfiles" DIRECTORY_SEPARATOR
+ "testenc2", 32, name));
CollectInBufferStream e;
encoded->CopyStreamTo(e);
e.SetForReading();
@@ -1589,7 +1617,8 @@
// Test that reordered streams work too
{
- FileStream enc("testfiles/testenc1_enc");
+ FileStream enc("testfiles" DIRECTORY_SEPARATOR
+ "testenc1_enc");
std::auto_ptr<IOStream> reordered(BackupStoreFile::ReorderFileToStreamOrder(&enc, false));
std::auto_ptr<BackupStoreFile::DecodedStream> decoded(BackupStoreFile::DecodeFileStream(*reordered, IOStream::TimeOutInfinite));
CollectInBufferStream d;
@@ -1601,6 +1630,7 @@
TEST_THAT(decoded->GetNumBlocks() == 3);
}
+#ifndef WIN32
// Try out doing this on a symlink
{
TEST_THAT(::symlink("does/not/exist", "testfiles/testsymlink") == 0);
@@ -1614,14 +1644,20 @@
// Decode it
BackupStoreFile::DecodeFile(b, "testfiles/testsymlink_2", IOStream::TimeOutInfinite);
}
+#endif
}
// Store info
{
RaidFileWrite::CreateDirectory(0, "test-info");
- BackupStoreInfo::CreateNew(76, "test-info/", 0, 3461231233455433LL, 2934852487LL);
- TEST_CHECK_THROWS(BackupStoreInfo::CreateNew(76, "test-info/", 0, 0, 0), RaidFileException, CannotOverwriteExistingFile);
- std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(76, "test-info/", 0, true));
+ BackupStoreInfo::CreateNew(76, "test-info" DIRECTORY_SEPARATOR,
+ 0, 3461231233455433LL, 2934852487LL);
+ TEST_CHECK_THROWS(BackupStoreInfo::CreateNew(76,
+ "test-info" DIRECTORY_SEPARATOR, 0, 0, 0),
+ RaidFileException, CannotOverwriteExistingFile);
+ std::auto_ptr<BackupStoreInfo> info(
+ BackupStoreInfo::Load(76,
+ "test-info" DIRECTORY_SEPARATOR, 0, true));
TEST_CHECK_THROWS(info->Save(), BackupStoreException, StoreInfoIsReadOnly);
TEST_CHECK_THROWS(info->ChangeBlocksUsed(1), BackupStoreException, StoreInfoIsReadOnly);
TEST_CHECK_THROWS(info->ChangeBlocksInOldFiles(1), BackupStoreException, StoreInfoIsReadOnly);
@@ -1630,7 +1666,8 @@
TEST_CHECK_THROWS(info->AddDeletedDirectory(2), BackupStoreException, StoreInfoIsReadOnly);
}
{
- std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(76, "test-info/", 0, false));
+ std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(76,
+ "test-info" DIRECTORY_SEPARATOR, 0, false));
info->ChangeBlocksUsed(8);
info->ChangeBlocksInOldFiles(9);
info->ChangeBlocksInDeletedFiles(10);
@@ -1648,7 +1685,8 @@
info->Save();
}
{
- std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(76, "test-info/", 0, true));
+ std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(76,
+ "test-info" DIRECTORY_SEPARATOR, 0, true));
TEST_THAT(info->GetBlocksUsed() == 7);
TEST_THAT(info->GetBlocksInOldFiles() == 5);
TEST_THAT(info->GetBlocksInDeletedFiles() == 1);
@@ -1666,12 +1704,18 @@
// Context
TLSContext context;
context.Initialise(false /* client */,
- "testfiles/clientCerts.pem",
- "testfiles/clientPrivKey.pem",
- "testfiles/clientTrustedCAs.pem");
+ "testfiles" DIRECTORY_SEPARATOR "clientCerts.pem",
+ "testfiles" DIRECTORY_SEPARATOR "clientPrivKey.pem",
+ "testfiles" DIRECTORY_SEPARATOR "clientTrustedCAs.pem");
// First, try logging in without an account having been created... just make sure login fails.
+
+#ifdef WIN32
+ int pid = LaunchServer("..\\..\\bin\\bbstored\\bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+#else
int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+#endif
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -1700,8 +1744,13 @@
}
// Create an account for the test client
+#ifdef WIN32
+ TEST_THAT_ABORTONFAIL(::system("..\\..\\bin\\bbstoreaccounts\\bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 10000B 20000B") == 0);
+#else
TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 10000B 20000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
+#endif
+
TEST_THAT(TestDirExists("testfiles/0_0/backup/01234567"));
TEST_THAT(TestDirExists("testfiles/0_1/backup/01234567"));
TEST_THAT(TestDirExists("testfiles/0_2/backup/01234567"));
@@ -1725,15 +1774,27 @@
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+#endif
// Set a new limit on the account -- leave the hard limit high to make sure the target for
// freeing space is the soft limit.
+
+#ifdef WIN32
+ TEST_THAT_ABORTONFAIL(::system("..\\..\\bin\\bbstoreaccounts\\bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 20000B") == 0);
+#else
TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 20000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
+#endif
// Start things up
+#ifdef WIN32
+ pid = LaunchServer("..\\..\\bin\\bbstored\\bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+#else
pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+#endif
+
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
@@ -1758,8 +1819,12 @@
TEST_THAT(after.old == 0);
// Set a really small hard limit
+#ifdef WIN32
+ TEST_THAT_ABORTONFAIL(::system("..\\..\\bin\\bbstoreaccounts\\bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 20B") == 0);
+#else
TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 20B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
+#endif
// Try to upload a file and create a directory, and check an error is generated
{
@@ -1808,7 +1873,10 @@
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+
+#ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+#endif
}
return 0;
@@ -1820,10 +1888,19 @@
// Create an account for the test client
TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 30000B 40000B") == 0);
+
+#ifndef WIN32
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
+#endif
// First, try logging in without an account having been created... just make sure login fails.
+
+#ifdef WIN32
+ int pid = LaunchServer("..\\..\\bin\\bbstored\\bbstored testfiles/bbstored_multi.conf", "testfiles/bbstored.pid");
+#else
int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored_multi.conf", "testfiles/bbstored.pid");
+#endif
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -1840,15 +1917,63 @@
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+#endif
}
return 0;
}
+#ifdef WIN32
+WCHAR* ConvertUtf8ToWideString(const char* pString);
+std::string ConvertPathToAbsoluteUnicode(const char *pFileName);
+#endif
+
int test(int argc, const char *argv[])
{
+#ifdef WIN32
+ // Under win32 we must initialise the Winsock library
+ // before using sockets
+
+ WSADATA info;
+ TEST_THAT(WSAStartup(0x0101, &info) != SOCKET_ERROR)
+
+ // this had better work, or bbstored will die when combining diffs
+ char* file = "foo";
+ std::string abs = ConvertPathToAbsoluteUnicode(file);
+ WCHAR* wfile = ConvertUtf8ToWideString(abs.c_str());
+
+ DWORD accessRights = FILE_READ_ATTRIBUTES |
+ FILE_LIST_DIRECTORY | FILE_READ_EA | FILE_WRITE_ATTRIBUTES |
+ FILE_WRITE_DATA | FILE_WRITE_EA /*| FILE_ALL_ACCESS*/;
+ DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ HANDLE h1 = CreateFileW(wfile, accessRights, shareMode,
+ NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ assert(h1 != INVALID_HANDLE_VALUE);
+ TEST_THAT(h1 != INVALID_HANDLE_VALUE);
+
+ accessRights = FILE_READ_ATTRIBUTES |
+ FILE_LIST_DIRECTORY | FILE_READ_EA;
+
+ HANDLE h2 = CreateFileW(wfile, accessRights, shareMode,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ assert(h2 != INVALID_HANDLE_VALUE);
+ TEST_THAT(h2 != INVALID_HANDLE_VALUE);
+
+ CloseHandle(h2);
+ CloseHandle(h1);
+
+ h1 = openfile("foo", O_CREAT | O_RDWR, 0);
+ TEST_THAT(h1 != INVALID_HANDLE_VALUE);
+ h2 = openfile("foo", O_RDWR, 0);
+ TEST_THAT(h2 != INVALID_HANDLE_VALUE);
+ CloseHandle(h2);
+ CloseHandle(h1);
+#endif
+
// SSL library
SSLLib::Initialise();
@@ -1865,7 +1990,11 @@
// Use the setup crypto command to set up all these keys, so that the bbackupquery command can be used
// for seeing what's going on.
+#ifdef WIN32
+ BackupClientCryptoKeys_Setup("testfiles\\bbackupd.keys");
+#else
BackupClientCryptoKeys_Setup("testfiles/bbackupd.keys");
+#endif
// encode in some filenames -- can't do static initialisation because the key won't be set up when these are initialised
for(unsigned int l = 0; l < sizeof(ens_filenames) / sizeof(ens_filenames[0]); ++l)
Modified: box/chris/merge/test/backupstorefix/testfiles/testbackupstorefix.pl.in
===================================================================
--- box/chris/merge/test/backupstorefix/testfiles/testbackupstorefix.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/backupstorefix/testfiles/testbackupstorefix.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -54,7 +54,7 @@
open INITIAL,'testfiles/initial-listing.txt' or die "Can't open original listing";
while(<INITIAL>)
{
- chomp;
+ chomp; s/\r//;
$expected{$_} = 1;
m/\A(.+?) .+? (.+)\Z/;
$filenames{$2} = $_;
@@ -99,7 +99,7 @@
while(<LISTING>)
{
print LISTING_COPY;
- chomp;
+ chomp; s/\r//;
s/\[FILENAME NOT ENCRYPTED\]//;
if(exists $expected{$_})
{
Modified: box/chris/merge/test/backupstorepatch/testbackupstorepatch.cpp
===================================================================
--- box/chris/merge/test/backupstorepatch/testbackupstorepatch.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/backupstorepatch/testbackupstorepatch.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -283,6 +283,14 @@
int test(int argc, const char *argv[])
{
+#ifdef WIN32
+ // Under win32 we must initialise the Winsock library
+ // before using sockets
+
+ WSADATA info;
+ TEST_THAT(WSAStartup(0x0101, &info) != SOCKET_ERROR)
+#endif
+
// Allocate a buffer
buffer = ::malloc(BUFFER_SIZE);
TEST_THAT(buffer != 0);
@@ -309,8 +317,12 @@
"testfiles/clientTrustedCAs.pem");
// Create an account
+#ifdef WIN32
+ TEST_THAT_ABORTONFAIL(::system("..\\..\\bin\\bbstoreaccounts\\bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 30000B 40000B") == 0);
+#else
TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 30000B 40000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
+#endif
// Create test files
create_test_files();
@@ -319,7 +331,12 @@
test_depends_in_dirs();
// First, try logging in without an account having been created... just make sure login fails.
+#ifdef WIN32
+ int pid = LaunchServer("..\\..\\bin\\bbstored\\bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+#else
int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+#endif
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -397,7 +414,13 @@
// Store details
test_files[f].IDOnServer = stored->GetObjectID();
test_files[f].IsCompletelyDifferent = isCompletelyDifferent;
- printf("ID %lld, completely different: %s\n", test_files[f].IDOnServer,
+
+#ifdef WIN32
+ printf("ID %I64d, completely different: %s\n",
+#else
+ printf("ID %lld, completely different: %s\n",
+#endif
+ test_files[f].IDOnServer,
test_files[f].IsCompletelyDifferent?"yes":"no");
}
else
@@ -565,9 +588,14 @@
writedir.Commit(true);
}
- // Send the server a restart signal, so it does housekeeping immedaitely, and wait for it to happen
+#ifdef WIN32
+ wait_for_operation(12);
+#else
+ // Send the server a restart signal, so it does housekeeping immediately, and wait for it to happen
::sleep(1); // wait for old connections to terminate
::kill(pid, SIGHUP);
+#endif
+
// Get the revision number of the info file
int64_t first_revision = 0;
RaidFileRead::FileExists(0, "backup/01234567/o01", &first_revision);
@@ -611,7 +639,10 @@
// Kill store server
TEST_THAT(KillServer(pid));
TEST_THAT(!ServerIsAlive(pid));
+
+ #ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+ #endif
}
::free(buffer);
Modified: box/chris/merge/test/basicserver/TestCommands.cpp
===================================================================
--- box/chris/merge/test/basicserver/TestCommands.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/basicserver/TestCommands.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,7 +1,9 @@
#include "Box.h"
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif
#include "autogen_TestProtocolServer.h"
#include "CollectInBufferStream.h"
Modified: box/chris/merge/test/basicserver/testbasicserver.cpp
===================================================================
--- box/chris/merge/test/basicserver/testbasicserver.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/basicserver/testbasicserver.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -31,7 +31,6 @@
#include "MemLeakFindOn.h"
-
#define SERVER_LISTEN_PORT 2003
// in ms
@@ -62,10 +61,14 @@
void testservers_pause_before_reply()
{
- struct timespec t;
- t.tv_sec = 0;
- t.tv_nsec = COMMS_SERVER_WAIT_BEFORE_REPLYING * 1000 * 1000; // convert to ns
- ::nanosleep(&t, NULL);
+#ifdef WIN32
+ Sleep(COMMS_SERVER_WAIT_BEFORE_REPLYING);
+#else
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = COMMS_SERVER_WAIT_BEFORE_REPLYING * 1000 * 1000; // convert to ns
+ ::nanosleep(&t, NULL);
+#endif
}
#define LARGE_DATA_BLOCK_SIZE 19870
@@ -427,84 +430,138 @@
}
}
+#ifdef WIN32
+ // Under win32 we must initialise the Winsock library
+ // before using sockets
+
+ WSADATA info;
+ TEST_THAT(WSAStartup(0x0101, &info) != SOCKET_ERROR)
+#endif
+
//printf("SKIPPING TESTS------------------------\n");
//goto protocolserver;
// Launch a basic server
{
- int pid = LaunchServer("./test srv1 testfiles/srv1.conf", "testfiles/srv1.pid");
+#ifdef WIN32
+ int pid = LaunchServer("test srv1 testfiles\\srv1.conf",
+ "testfiles\\srv1.pid");
+#else
+ int pid = LaunchServer("./test srv1 testfiles/srv1.conf",
+ "testfiles/srv1.pid");
+#endif
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
// Check that it's written the expected file
- TEST_THAT(TestFileExists("testfiles/srv1.test1"));
+ TEST_THAT(TestFileExists("testfiles"
+ DIRECTORY_SEPARATOR "srv1.test1"));
TEST_THAT(ServerIsAlive(pid));
// Move the config file over
- TEST_THAT(::rename("testfiles/srv1b.conf", "testfiles/srv1.conf") != -1);
+#ifdef WIN32
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR
+ "srv1.conf") != -1);
+#endif
+ TEST_THAT(::rename(
+ "testfiles" DIRECTORY_SEPARATOR "srv1b.conf",
+ "testfiles" DIRECTORY_SEPARATOR "srv1.conf")
+ != -1);
+#ifndef WIN32
// Get it to reread the config file
TEST_THAT(HUPServer(pid));
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
// Check that new file exists
- TEST_THAT(TestFileExists("testfiles/srv1.test2"));
+ TEST_THAT(TestFileExists("testfiles"
+ DIRECTORY_SEPARATOR "srv1.test2"));
+#endif // !WIN32
// Kill it off
TEST_THAT(KillServer(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("generic-daemon.memleaks");
+#endif // !WIN32
}
}
// Launch a test forking server
{
- int pid = LaunchServer("./test srv2 testfiles/srv2.conf", "testfiles/srv2.pid");
+#ifdef WIN32
+ int pid = LaunchServer("test srv2 testfiles\\srv2.conf",
+ "testfiles\\srv2.pid");
+#else
+ int pid = LaunchServer("./test srv2 testfiles/srv2.conf",
+ "testfiles/srv2.pid");
+#endif
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
// Will it restart?
TEST_THAT(ServerIsAlive(pid));
+#ifndef WIN32
TEST_THAT(HUPServer(pid));
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
+#endif // !WIN32
// Make some connections
{
SocketStream conn1;
conn1.Open(Socket::TypeINET, "localhost", 2003);
+#ifndef WIN32
SocketStream conn2;
conn2.Open(Socket::TypeUNIX, "testfiles/srv2.sock");
SocketStream conn3;
conn3.Open(Socket::TypeINET, "localhost", 2003);
+#endif // !WIN32
// Quick check that reconnections fail
TEST_CHECK_THROWS(conn1.Open(Socket::TypeUNIX, "testfiles/srv2.sock");, ServerException, SocketAlreadyOpen);
// Stuff some data around
std::vector<IOStream *> conns;
conns.push_back(&conn1);
+#ifndef WIN32
conns.push_back(&conn2);
conns.push_back(&conn3);
+#endif // !WIN32
Srv2TestConversations(conns);
// Implicit close
}
+#ifndef WIN32
// HUP again
TEST_THAT(HUPServer(pid));
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
+#endif // !WIN32
// Kill it
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("test-srv2.memleaks");
+#endif // !WIN32
}
}
// Launch a test SSL server
{
+#ifdef WIN32
+ int pid = LaunchServer("test srv3 testfiles\\srv3.conf",
+ "testfiles\\srv3.pid");
+#else
int pid = LaunchServer("./test srv3 testfiles/srv3.conf", "testfiles/srv3.pid");
+#endif
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
// Will it restart?
TEST_THAT(ServerIsAlive(pid));
+
+#ifndef WIN32
TEST_THAT(HUPServer(pid));
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
+#endif
+
// Make some connections
{
// SSL library
@@ -519,36 +576,50 @@
SocketStreamTLS conn1;
conn1.Open(context, Socket::TypeINET, "localhost", 2003);
+#ifndef WIN32
SocketStreamTLS conn2;
conn2.Open(context, Socket::TypeUNIX, "testfiles/srv3.sock");
SocketStreamTLS conn3;
conn3.Open(context, Socket::TypeINET, "localhost", 2003);
+#endif
// Quick check that reconnections fail
TEST_CHECK_THROWS(conn1.Open(context, Socket::TypeUNIX, "testfiles/srv3.sock");, ServerException, SocketAlreadyOpen);
// Stuff some data around
std::vector<IOStream *> conns;
conns.push_back(&conn1);
+#ifndef WIN32
conns.push_back(&conn2);
conns.push_back(&conn3);
+#endif
Srv2TestConversations(conns);
// Implicit close
}
+#ifndef WIN32
// HUP again
TEST_THAT(HUPServer(pid));
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
+#endif
// Kill it
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("test-srv3.memleaks");
+#endif
}
}
//protocolserver:
// Launch a test protocol handling server
{
- int pid = LaunchServer("./test srv4 testfiles/srv4.conf", "testfiles/srv4.pid");
+#ifdef WIN32
+ int pid = LaunchServer("test srv4 testfiles\\srv4.conf",
+ "testfiles\\srv4.pid");
+#else
+ int pid = LaunchServer("./test srv4 testfiles/srv4.conf",
+ "testfiles/srv4.pid");
+#endif
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -557,7 +628,11 @@
// Open a connection to it
SocketStream conn;
+#ifdef WIN32
+ conn.Open(Socket::TypeINET, "localhost", 2003);
+#else
conn.Open(Socket::TypeUNIX, "testfiles/srv4.sock");
+#endif
// Create a protocol
TestProtocolClient protocol(conn);
@@ -620,7 +695,9 @@
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("test-srv4.memleaks");
+#endif
}
}
Modified: box/chris/merge/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/merge/test/bbackupd/testbbackupd.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/bbackupd/testbbackupd.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -718,7 +718,7 @@
// Wait and test...
wait_for_backup_operation();
compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3e.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 2*256); // should find differences
+ TEST_THAT(compareReturnValue == 3*256); // should find differences
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
// Check that it was reported correctly
TEST_THAT(TestFileExists("testfiles/notifyran.read-error.1"));
Deleted: box/chris/merge/test/bbackupd/testfiles/bbackupd.conf
===================================================================
--- box/chris/merge/test/bbackupd/testfiles/bbackupd.conf 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/bbackupd/testfiles/bbackupd.conf 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,50 +0,0 @@
-
-CertificateFile = testfiles/clientCerts.pem
-PrivateKeyFile = testfiles/clientPrivKey.pem
-TrustedCAsFile = testfiles/clientTrustedCAs.pem
-
-KeysFile = testfiles/bbackupd.keys
-
-DataDirectory = testfiles/bbackupd-data
-
-StoreHostname = localhost
-AccountNumber = 0x01234567
-
-UpdateStoreInterval = 3
-MinimumFileAge = 4
-MaxUploadWait = 24
-
-FileTrackingSizeThreshold = 1024
-DiffingUploadSizeThreshold = 1024
-
-MaximumDiffingTime = 8
-
-ExtendedLogging = yes
-
-CommandSocket = testfiles/bbackupd.sock
-
-NotifyScript = @PERL@ testfiles/notifyscript.pl
-
-Server
-{
- PidFile = testfiles/bbackupd.pid
-}
-
-BackupLocations
-{
- Test1
- {
- Path = testfiles/TestDir1
-
- ExcludeFile = testfiles/TestDir1/excluded_1
- ExcludeFile = testfiles/TestDir1/excluded_2
- ExcludeFilesRegex = \.excludethis$
- ExcludeFilesRegex = EXCLUDE
- AlwaysIncludeFile = testfiles/TestDir1/dont.excludethis
- ExcludeDir = testfiles/TestDir1/exclude_dir
- ExcludeDir = testfiles/TestDir1/exclude_dir_2
- ExcludeDirsRegex = not_this_dir
- AlwaysIncludeDirsRegex = ALWAYSINCLUDE
- }
-}
-
Copied: box/chris/merge/test/bbackupd/testfiles/bbackupd.conf.in (from rev 568, box/trunk/test/bbackupd/testfiles/bbackupd.conf)
Modified: box/chris/merge/test/bbackupd/testfiles/extcheck1.pl.in
===================================================================
--- box/chris/merge/test/bbackupd/testfiles/extcheck1.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/bbackupd/testfiles/extcheck1.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,7 +1,9 @@
#!@PERL@
use strict;
-unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac\" quit|")
+my $flags = $ARGV[0] or "";
+
+unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac$flags\" quit|")
{
print "Couldn't open compare utility\n";
exit 2;
@@ -15,14 +17,23 @@
next unless m/\S/;
if(m/continousupdate/)
{
- $ret = 2 unless m/exists/;
+ unless (/exists/)
+ {
+ print "FAIL: continousupdate line does not match\n";
+ $ret = 2;
+ }
$seen = 1;
}
else
{
- $ret = 2 unless m/\AWARNING/ || m/\ADifferences/ || /might be reason/ || /probably due to file mod/;
+ unless (/\AWARNING/ or /\ADifferences/ or /might be reason/
+ or /probably due to file mod/)
+ {
+ print "FAIL: Summary line does not match\n";
+ $ret = 2;
+ }
}
- print;
+ print "READ: $_";
}
close IN;
Modified: box/chris/merge/test/bbackupd/testfiles/extcheck2.pl.in
===================================================================
--- box/chris/merge/test/bbackupd/testfiles/extcheck2.pl.in 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/bbackupd/testfiles/extcheck2.pl.in 2006-07-27 23:18:35 UTC (rev 710)
@@ -1,7 +1,9 @@
#!@PERL@
use strict;
-unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac\" quit|")
+my $flags = $ARGV[0] or "";
+
+unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac$flags\" quit|")
{
print "Couldn't open compare utility\n";
exit 2;
@@ -14,13 +16,23 @@
next unless m/\S/;
if(m/continousupdate/)
{
- $ret = 2 unless m/contents/ || m/attributes/;
+ unless (m/contents/ or m/attributes/)
+ {
+ print "FAIL: continuousupdate line does not match\n";
+ $ret = 2;
+ }
}
else
{
- $ret = 2 unless m/\AWARNING/ || m/\ADifferences/ || /might be reason/ || /probably due to file mod/;
+ unless (/\AWARNING/ or /\ADifferences/ or /might be reason/
+ or /probably due to file mod/)
+ {
+ print "FAIL: summary line does not match\n";
+ $ret = 2;
+ }
}
- print;
+
+ print "READ: $_";
}
close IN;
Modified: box/chris/merge/test/common/testcommon.cpp
===================================================================
--- box/chris/merge/test/common/testcommon.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/common/testcommon.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -24,6 +24,8 @@
#include "CommonException.h"
#include "Conversion.h"
#include "autogen_ConversionException.h"
+#include "CollectInBufferStream.h"
+#include "Archive.h"
#include "MemLeakFindOn.h"
@@ -565,5 +567,63 @@
test_conversions();
+ // test that we can use Archive and CollectInBufferStream
+ // to read and write arbitrary types to a memory buffer
+
+ {
+ CollectInBufferStream buffer;
+ ASSERT(buffer.GetPosition() == 0);
+
+ {
+ Archive archive(buffer, 0);
+ ASSERT(buffer.GetPosition() == 0);
+
+ archive.Write((bool) true);
+ archive.Write((bool) false);
+ archive.Write((int) 0x12345678);
+ archive.Write((int) 0x87654321);
+ archive.Write((int64_t) 0x0badfeedcafebabeLL);
+ archive.Write((uint64_t) 0xfeedfacedeadf00dLL);
+ archive.Write((uint8_t) 0x01);
+ archive.Write((uint8_t) 0xfe);
+ archive.Write(std::string("hello world!"));
+ archive.Write(std::string("goodbye cruel world!"));
+ }
+
+ CollectInBufferStream buf2;
+ buf2.Write(buffer.GetBuffer(), buffer.GetSize());
+ TEST_THAT(buf2.GetPosition() == buffer.GetSize());
+
+ buf2.SetForReading();
+ TEST_THAT(buf2.GetPosition() == 0);
+
+ {
+ Archive archive(buf2, 0);
+ TEST_THAT(buf2.GetPosition() == 0);
+
+ bool b;
+ archive.Read(b); TEST_THAT(b == true);
+ archive.Read(b); TEST_THAT(b == false);
+
+ int i;
+ archive.Read(i); TEST_THAT(i == 0x12345678);
+ archive.Read(i); TEST_THAT((unsigned int)i == 0x87654321);
+
+ uint64_t i64;
+ archive.Read(i64); TEST_THAT(i64 == 0x0badfeedcafebabeLL);
+ archive.Read(i64); TEST_THAT(i64 == 0xfeedfacedeadf00dLL);
+
+ uint8_t i8;
+ archive.Read(i8); TEST_THAT(i8 == 0x01);
+ archive.Read(i8); TEST_THAT(i8 == 0xfe);
+
+ std::string s;
+ archive.Read(s); TEST_THAT(s == "hello world!");
+ archive.Read(s); TEST_THAT(s == "goodbye cruel world!");
+
+ TEST_THAT(!buf2.StreamDataLeft());
+ }
+ }
+
return 0;
}
Modified: box/chris/merge/test/raidfile/intercept.cpp
===================================================================
--- box/chris/merge/test/raidfile/intercept.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/raidfile/intercept.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -14,7 +14,11 @@
#endif
#include <sys/types.h>
#include <unistd.h>
+
+#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
+#endif
+
#include <errno.h>
#ifndef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
Modified: box/chris/merge/test/raidfile/testraidfile.cpp
===================================================================
--- box/chris/merge/test/raidfile/testraidfile.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/raidfile/testraidfile.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -12,7 +12,10 @@
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
+
+#ifdef HAVE_SYSCALL
#include <sys/syscall.h>
+#endif
#include <string.h>
@@ -207,16 +210,24 @@
bytesread += r;
}
TEST_THAT(!readstream4.StreamDataLeft()); // check IOStream interface is correct
+ pread.reset();
// Be nasty, and create some errors for the RAID stuff to recover from...
if(TestRAIDProperties)
{
char stripe1fn[256], stripe1fnRename[256];
- sprintf(stripe1fn, "testfiles/%d_%d/%s.rf", set, startDisc, filename);
- sprintf(stripe1fnRename, "testfiles/%d_%d/%s.rf-REMOVED", set, startDisc, filename);
+ sprintf(stripe1fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set, startDisc, filename);
+ sprintf(stripe1fnRename, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf-REMOVED", set, startDisc,
+ filename);
char stripe2fn[256], stripe2fnRename[256];
- sprintf(stripe2fn, "testfiles/%d_%d/%s.rf", set, (startDisc + 1) % RAID_NUMBER_DISCS, filename);
- sprintf(stripe2fnRename, "testfiles/%d_%d/%s.rf-REMOVED", set, (startDisc + 1) % RAID_NUMBER_DISCS, filename);
+ sprintf(stripe2fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, filename);
+ sprintf(stripe2fnRename, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf-REMOVED", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, filename);
// Read with stripe1 + parity
TEST_THAT(::rename(stripe2fn, stripe2fnRename) == 0);
@@ -252,9 +263,15 @@
}
mungefilename[m++] = '\0';
char stripe1munge[256];
- sprintf(stripe1munge, "testfiles/%d_%d/.raidfile-unreadable/%s", set, startDisc, mungefilename);
+ sprintf(stripe1munge, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR ".raidfile-unreadable"
+ DIRECTORY_SEPARATOR "%s", set, startDisc,
+ mungefilename);
char stripe2munge[256];
- sprintf(stripe2munge, "testfiles/%d_%d/.raidfile-unreadable/%s", set, (startDisc + 1) % RAID_NUMBER_DISCS, mungefilename);
+ sprintf(stripe2munge, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR ".raidfile-unreadable"
+ DIRECTORY_SEPARATOR "%s", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, mungefilename);
#ifdef TRF_CAN_INTERCEPT
@@ -359,10 +376,12 @@
write4.Write(data, datasize);
// This time, don't discard and transform it to a RAID File
char writefnPre[256];
- sprintf(writefnPre, "testfiles/%d_%d/%s.rfwX", set, startDisc, filename);
+ sprintf(writefnPre, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rfwX", set, startDisc, filename);
TEST_THAT(TestFileExists(writefnPre));
char writefn[256];
- sprintf(writefn, "testfiles/%d_%d/%s.rfw", set, startDisc, filename);
+ sprintf(writefn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rfw", set, startDisc, filename);
int usageInBlocks = write4.GetDiscUsageInBlocks();
write4.Commit(DoTransform);
// Check that files are nicely done...
@@ -390,14 +409,19 @@
fs1 = ((fullblocks / 2)+1) * RAID_BLOCK_SIZE;
}
char stripe1fn[256];
- sprintf(stripe1fn, "testfiles/%d_%d/%s.rf", set, startDisc, filename);
+ sprintf(stripe1fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set, startDisc, filename);
TEST_THAT(TestGetFileSize(stripe1fn) == fs1);
char stripe2fn[256];
- sprintf(stripe2fn, "testfiles/%d_%d/%s.rf", set, (startDisc + 1) % RAID_NUMBER_DISCS, filename);
+ sprintf(stripe2fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, filename);
TEST_THAT(TestGetFileSize(stripe2fn) == (int)(datasize - fs1));
// Parity file size
char parityfn[256];
- sprintf(parityfn, "testfiles/%d_%d/%s.rf", set, (startDisc + 2) % RAID_NUMBER_DISCS, filename);
+ sprintf(parityfn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set,
+ (startDisc + 2) % RAID_NUMBER_DISCS, filename);
// Mildly complex calculation
unsigned int blocks = datasize / RAID_BLOCK_SIZE;
unsigned int bytesOver = datasize % RAID_BLOCK_SIZE;
@@ -436,14 +460,16 @@
if(datasize > (3*1024))
{
int f;
- TEST_THAT((f = ::open(stripe1fn, O_RDONLY, 0)) != -1);
+ TEST_THAT((f = ::open(stripe1fn, O_RDONLY | O_BINARY,
+ 0)) != -1);
TEST_THAT(sizeof(testblock) == ::read(f, testblock, sizeof(testblock)));
for(unsigned int q = 0; q < sizeof(testblock); ++q)
{
TEST_THAT(testblock[q] == ((char*)data)[q]);
}
::close(f);
- TEST_THAT((f = ::open(stripe2fn, O_RDONLY, 0)) != -1);
+ TEST_THAT((f = ::open(stripe2fn, O_RDONLY | O_BINARY,
+ 0)) != -1);
TEST_THAT(sizeof(testblock) == ::read(f, testblock, sizeof(testblock)));
for(unsigned int q = 0; q < sizeof(testblock); ++q)
{
@@ -536,7 +562,9 @@
// Generate a random pre-existing write file (and ensure that it doesn't exist already)
int f;
- TEST_THAT((f = ::open("testfiles/0_2/overwrite_B.rfwX", O_WRONLY | O_CREAT | O_EXCL, 0755)) != -1);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "overwrite_B.rfwX",
+ O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0755)) != -1);
TEST_THAT(::write(f, "TESTTEST", 8) == 8);
::close(f);
@@ -557,7 +585,7 @@
// Initialise the controller
RaidFileController &rcontroller = RaidFileController::GetController();
- rcontroller.Initialise("testfiles/raidfile.conf");
+ rcontroller.Initialise("testfiles" DIRECTORY_SEPARATOR "raidfile.conf");
// some data
char data[TEST_DATA_SIZE];
@@ -574,9 +602,12 @@
// Try creating a directory
RaidFileWrite::CreateDirectory(0, "test-dir");
- TEST_THAT(TestDirExists("testfiles/0_0/test-dir"));
- TEST_THAT(TestDirExists("testfiles/0_1/test-dir"));
- TEST_THAT(TestDirExists("testfiles/0_2/test-dir"));
+ TEST_THAT(TestDirExists("testfiles" DIRECTORY_SEPARATOR "0_0"
+ DIRECTORY_SEPARATOR "test-dir"));
+ TEST_THAT(TestDirExists("testfiles" DIRECTORY_SEPARATOR "0_1"
+ DIRECTORY_SEPARATOR "test-dir"));
+ TEST_THAT(TestDirExists("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test-dir"));
TEST_THAT(RaidFileRead::DirectoryExists(0, "test-dir"));
TEST_THAT(!RaidFileRead::DirectoryExists(0, "test-dir-not"));
@@ -608,9 +639,12 @@
// Before it's deleted, check to see the contents are as expected
int f;
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfwX", O_RDONLY, 0)) >= 0);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfwX", O_RDONLY | O_BINARY, 0))
+ >= 0);
char buffer[sizeof(data)];
- TEST_THAT(::read(f, buffer, sizeof(buffer)) == sizeof(buffer));
+ int bytes_read = ::read(f, buffer, sizeof(buffer));
+ TEST_THAT(bytes_read == sizeof(buffer));
for(unsigned int l = 0; l < 1024; ++l)
{
TEST_THAT(buffer[l] == data[l]);
@@ -624,7 +658,8 @@
TEST_THAT(buffer[l+2048+sizeof(data2)] == data2[l]);
}
TEST_THAT(::lseek(f, sizeof(data), SEEK_SET) == sizeof(buffer));
- TEST_THAT(::read(f, buffer, sizeof(buffer)) == sizeof(buffer));
+ bytes_read = ::read(f, buffer, sizeof(buffer));
+ TEST_THAT(bytes_read == sizeof(buffer));
for(unsigned int l = 0; l < 1024; ++l)
{
TEST_THAT(buffer[l] == data[l]);
@@ -635,7 +670,9 @@
// Commit the data
write1.Commit();
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfw", O_RDONLY, 0)) >= 0);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfw", O_RDONLY | O_BINARY, 0))
+ >= 0);
::close(f);
// Now try and read it
@@ -687,7 +724,9 @@
write2.Write(data, sizeof(data));
// This time, discard it
write2.Discard();
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfw", O_RDONLY, 0)) == -1);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfw", O_RDONLY | O_BINARY, 0))
+ == -1);
// And leaving it there...
RaidFileWrite writeLeave(0, "test1");
@@ -695,7 +734,9 @@
writeLeave.Write(data, sizeof(data));
// This time, commit it
writeLeave.Commit();
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfw", O_RDONLY, 0)) != -1);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfw", O_RDONLY | O_BINARY, 0))
+ != -1);
::close(f);
// Then check that the thing will refuse to open it again.
@@ -712,7 +753,8 @@
write3b.Write(data + 3, sizeof(data) - 3);
write3b.Commit();
// Test it
- testReadingFileContents(0, "test1", data+3, sizeof(data) - 3, false /*TestRAIDProperties*/);
+ testReadingFileContents(0, "test1", data+3, sizeof(data) - 3, false
+ /* TestRAIDProperties */);
// And once again, but this time making it a raid file
RaidFileWrite write3c(0, "test1");
@@ -721,7 +763,8 @@
write3c.Write(data + 7, sizeof(data) - 7);
write3c.Commit(true); // make RAID
// Test it
- testReadingFileContents(0, "test1", data+7, sizeof(data) - 7, false /*TestRAIDProperties*/);
+ testReadingFileContents(0, "test1", data+7, sizeof(data) - 7, false
+ /*TestRAIDProperties*/);
// Test opening a file which doesn't exist
TEST_CHECK_THROWS(
@@ -736,20 +779,23 @@
w.Commit(true);
// Try removing the parity file
- TEST_THAT(::rename("testfiles/0_0/damage.rf", "testfiles/0_0/damage.rf-NT") == 0);
+ TEST_THAT(::rename("testfiles" DIRECTORY_SEPARATOR "0_0"
+ DIRECTORY_SEPARATOR "damage.rf",
+ "testfiles" DIRECTORY_SEPARATOR "0_0"
+ DIRECTORY_SEPARATOR "damage.rf-NT") == 0);
{
std::auto_ptr<RaidFileRead> pr0 = RaidFileRead::Open(0, "damage");
pr0->Read(buffer, sizeof(data));
}
- TEST_THAT(::rename("testfiles/0_0/damage.rf-NT", "testfiles/0_0/damage.rf") == 0);
-
+ TEST_THAT(::rename("testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "damage.rf-NT", "testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "damage.rf") == 0);
+
// Delete one of the files
- TEST_THAT(::unlink("testfiles/0_1/damage.rf") == 0); // stripe 1
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_1" DIRECTORY_SEPARATOR "damage.rf") == 0); // stripe 1
#ifdef TRF_CAN_INTERCEPT
// Open it and read...
{
- intercept_setup_error("testfiles/0_2/damage.rf", 0, EIO, SYS_read); // stripe 2
+ intercept_setup_error("testfiles" DIRECTORY_SEPARATOR "0_2" DIRECTORY_SEPARATOR "damage.rf", 0, EIO, SYS_read); // stripe 2
std::auto_ptr<RaidFileRead> pr1 = RaidFileRead::Open(0, "damage");
TEST_CHECK_THROWS(
pr1->Read(buffer, sizeof(data)),
@@ -761,7 +807,7 @@
#endif //TRF_CAN_INTERCEPT
// Delete another
- TEST_THAT(::unlink("testfiles/0_0/damage.rf") == 0); // parity
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "damage.rf") == 0); // parity
TEST_CHECK_THROWS(
std::auto_ptr<RaidFileRead> pread2 = RaidFileRead::Open(0, "damage"),
@@ -772,22 +818,22 @@
{
RaidFileWrite::CreateDirectory(0, "dirread");
// Make some contents
- RaidFileWrite::CreateDirectory(0, "dirread/dfsdf1");
- RaidFileWrite::CreateDirectory(0, "dirread/ponwq2");
+ RaidFileWrite::CreateDirectory(0, "dirread" DIRECTORY_SEPARATOR "dfsdf1");
+ RaidFileWrite::CreateDirectory(0, "dirread" DIRECTORY_SEPARATOR "ponwq2");
{
- RaidFileWrite w(0, "dirread/sdf9873241");
+ RaidFileWrite w(0, "dirread" DIRECTORY_SEPARATOR "sdf9873241");
w.Open();
w.Write(data, sizeof(data));
w.Commit(true);
}
{
- RaidFileWrite w(0, "dirread/fsdcxjni3242");
+ RaidFileWrite w(0, "dirread" DIRECTORY_SEPARATOR "fsdcxjni3242");
w.Open();
w.Write(data, sizeof(data));
w.Commit(true);
}
{
- RaidFileWrite w(0, "dirread/cskjnds3");
+ RaidFileWrite w(0, "dirread" DIRECTORY_SEPARATOR "cskjnds3");
w.Open();
w.Write(data, sizeof(data));
w.Commit(false);
@@ -803,15 +849,15 @@
TEST_THAT(true == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_DirsOnly, names));
TEST_THAT(list_matches(names, dir_list1));
// Delete things
- TEST_THAT(::unlink("testfiles/0_0/dirread/sdf9873241.rf") == 0);
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "dirread" DIRECTORY_SEPARATOR "sdf9873241.rf") == 0);
TEST_THAT(true == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_FilesOnly, names));
TEST_THAT(list_matches(names, file_list1));
// Delete something else so that it's not recoverable
- TEST_THAT(::unlink("testfiles/0_1/dirread/sdf9873241.rf") == 0);
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_1" DIRECTORY_SEPARATOR "dirread" DIRECTORY_SEPARATOR "sdf9873241.rf") == 0);
TEST_THAT(false == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_FilesOnly, names));
TEST_THAT(list_matches(names, file_list1));
// And finally...
- TEST_THAT(::unlink("testfiles/0_2/dirread/sdf9873241.rf") == 0);
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_2" DIRECTORY_SEPARATOR "dirread" DIRECTORY_SEPARATOR "sdf9873241.rf") == 0);
TEST_THAT(true == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_FilesOnly, names));
TEST_THAT(list_matches(names, file_list2));
}
Modified: box/chris/merge/test/win32/testlibwin32.cpp
===================================================================
--- box/chris/merge/test/win32/testlibwin32.cpp 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/test/win32/testlibwin32.cpp 2006-07-27 23:18:35 UTC (rev 710)
@@ -6,12 +6,214 @@
#ifdef WIN32
+#include <assert.h>
+#include <AccCtrl.h>
+#include <Aclapi.h>
+
#include "../../bin/bbackupd/BackupDaemon.h"
#include "BoxPortsAndFiles.h"
#include "emu.h"
int main(int argc, char* argv[])
{
+ // ACL tests
+ char* exename = getenv("WINDIR");
+
+ PSID psidOwner;
+ PSID psidGroup;
+ PACL pDacl;
+ PSECURITY_DESCRIPTOR pSecurityDesc;
+
+ DWORD result = GetNamedSecurityInfo(
+ exename, // pObjectName
+ SE_FILE_OBJECT, // ObjectType
+ DACL_SECURITY_INFORMATION | // SecurityInfo
+ GROUP_SECURITY_INFORMATION |
+ OWNER_SECURITY_INFORMATION,
+ &psidOwner, // ppsidOwner,
+ &psidGroup, // ppsidGroup,
+ &pDacl, // ppDacl,
+ NULL, // ppSacl,
+ &pSecurityDesc // ppSecurityDescriptor
+ );
+ if (result != ERROR_SUCCESS)
+ {
+ printf("Error getting security info for '%s': error %d",
+ exename, result);
+ }
+ assert(result == ERROR_SUCCESS);
+
+ char namebuf[1024];
+ char domainbuf[1024];
+ SID_NAME_USE nametype;
+ DWORD namelen = sizeof(namebuf);
+ DWORD domainlen = sizeof(domainbuf);
+
+ assert(LookupAccountSid(NULL, psidOwner, namebuf, &namelen,
+ domainbuf, &domainlen, &nametype));
+
+ printf("Owner:\n");
+ printf("User name: %s\n", namebuf);
+ printf("Domain name: %s\n", domainbuf);
+ printf("Name type: %d\n", nametype);
+ printf("\n");
+
+ namelen = sizeof(namebuf);
+ domainlen = sizeof(domainbuf);
+
+ assert(LookupAccountSid(NULL, psidGroup, namebuf, &namelen,
+ domainbuf, &domainlen, &nametype));
+
+ printf("Group:\n");
+ printf("User name: %s\n", namebuf);
+ printf("Domain name: %s\n", domainbuf);
+ printf("Name type: %d\n", nametype);
+ printf("\n");
+
+ ULONG numEntries;
+ PEXPLICIT_ACCESS pEntries;
+ result = GetExplicitEntriesFromAcl
+ (
+ pDacl, // pAcl
+ &numEntries, // pcCountOfExplicitEntries,
+ &pEntries // pListOfExplicitEntries
+ );
+ assert(result == ERROR_SUCCESS);
+
+ printf("Found %lu explicit DACL entries for '%s'\n\n",
+ (unsigned long)numEntries, exename);
+
+ for (ULONG i = 0; i < numEntries; i++)
+ {
+ EXPLICIT_ACCESS* pEntry = &(pEntries[i]);
+ printf("DACL entry %lu:\n", (unsigned long)i);
+
+ DWORD perms = pEntry->grfAccessPermissions;
+ printf(" Access permissions: ", perms);
+
+ #define PRINT_PERM(name) \
+ if (perms & name) \
+ { \
+ printf(#name " "); \
+ perms &= ~name; \
+ }
+
+ PRINT_PERM(FILE_ADD_FILE);
+ PRINT_PERM(FILE_ADD_SUBDIRECTORY);
+ PRINT_PERM(FILE_ALL_ACCESS);
+ PRINT_PERM(FILE_APPEND_DATA);
+ PRINT_PERM(FILE_CREATE_PIPE_INSTANCE);
+ PRINT_PERM(FILE_DELETE_CHILD);
+ PRINT_PERM(FILE_EXECUTE);
+ PRINT_PERM(FILE_LIST_DIRECTORY);
+ PRINT_PERM(FILE_READ_ATTRIBUTES);
+ PRINT_PERM(FILE_READ_DATA);
+ PRINT_PERM(FILE_READ_EA);
+ PRINT_PERM(FILE_TRAVERSE);
+ PRINT_PERM(FILE_WRITE_ATTRIBUTES);
+ PRINT_PERM(FILE_WRITE_DATA);
+ PRINT_PERM(FILE_WRITE_EA);
+ PRINT_PERM(STANDARD_RIGHTS_READ);
+ PRINT_PERM(STANDARD_RIGHTS_WRITE);
+ PRINT_PERM(SYNCHRONIZE);
+ PRINT_PERM(DELETE);
+ PRINT_PERM(READ_CONTROL);
+ PRINT_PERM(WRITE_DAC);
+ PRINT_PERM(WRITE_OWNER);
+ PRINT_PERM(MAXIMUM_ALLOWED);
+ PRINT_PERM(GENERIC_ALL);
+ PRINT_PERM(GENERIC_EXECUTE);
+ PRINT_PERM(GENERIC_WRITE);
+ PRINT_PERM(GENERIC_READ);
+ printf("\n");
+
+ if (perms)
+ {
+ printf(" Bits left over: %08x\n", perms);
+ }
+ assert(!perms);
+
+ printf(" Access mode: ");
+ switch(pEntry->grfAccessMode)
+ {
+ case NOT_USED_ACCESS:
+ printf("NOT_USED_ACCESS\n"); break;
+ case GRANT_ACCESS:
+ printf("GRANT_ACCESS\n"); break;
+ case DENY_ACCESS:
+ printf("DENY_ACCESS\n"); break;
+ case REVOKE_ACCESS:
+ printf("REVOKE_ACCESS\n"); break;
+ case SET_AUDIT_SUCCESS:
+ printf("SET_AUDIT_SUCCESS\n"); break;
+ case SET_AUDIT_FAILURE:
+ printf("SET_AUDIT_FAILURE\n"); break;
+ default:
+ printf("Unknown (%08x)\n", pEntry->grfAccessMode);
+ }
+
+ printf(" Trustee: ");
+ assert(pEntry->Trustee.pMultipleTrustee == NULL);
+ assert(pEntry->Trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE);
+ switch(pEntry->Trustee.TrusteeForm)
+ {
+ case TRUSTEE_IS_SID:
+ {
+ PSID trusteeSid = (PSID)(pEntry->Trustee.ptstrName);
+
+ namelen = sizeof(namebuf);
+ domainlen = sizeof(domainbuf);
+
+ assert(LookupAccountSid(NULL, trusteeSid, namebuf, &namelen,
+ domainbuf, &domainlen, &nametype));
+
+ printf("SID of %s\\%s (%d)\n", domainbuf, namebuf, nametype);
+ }
+ break;
+ case TRUSTEE_IS_NAME:
+ printf("Name\n"); break;
+ case TRUSTEE_BAD_FORM:
+ printf("Bad form\n"); assert(0);
+ case TRUSTEE_IS_OBJECTS_AND_SID:
+ printf("Objects and SID\n"); break;
+ case TRUSTEE_IS_OBJECTS_AND_NAME:
+ printf("Objects and name\n"); break;
+ default:
+ printf("Unknown form\n"); assert(0);
+ }
+
+ printf(" Trustee type: ");
+ switch(pEntry->Trustee.TrusteeType)
+ {
+ case TRUSTEE_IS_UNKNOWN:
+ printf("Unknown type.\n"); break;
+ case TRUSTEE_IS_USER:
+ printf("User\n"); break;
+ case TRUSTEE_IS_GROUP:
+ printf("Group\n"); break;
+ case TRUSTEE_IS_DOMAIN:
+ printf("Domain\n"); break;
+ case TRUSTEE_IS_ALIAS:
+ printf("Alias\n"); break;
+ case TRUSTEE_IS_WELL_KNOWN_GROUP:
+ printf("Well-known group\n"); break;
+ case TRUSTEE_IS_DELETED:
+ printf("Deleted account\n"); break;
+ case TRUSTEE_IS_INVALID:
+ printf("Invalid trustee type\n"); break;
+ case TRUSTEE_IS_COMPUTER:
+ printf("Computer\n"); break;
+ default:
+ printf("Unknown type %d\n", pEntry->Trustee.TrusteeType);
+ assert(0);
+ }
+
+ printf("\n");
+ }
+
+ assert(LocalFree((HLOCAL)pEntries) == 0);
+ assert(LocalFree((HLOCAL)pSecurityDesc) == 0);
+
chdir("c:\\tmp");
openfile("test", O_CREAT, 0);
struct stat ourfs;
@@ -25,12 +227,11 @@
do
{
info = readdir(ourDir);
- if ( info ) printf("File/Dir name is : %s\r\n", info->d_name);
+ if (info) printf("File/Dir name is : %s\r\n", info->d_name);
+ }
+ while (info != NULL);
- }while ( info != NULL );
-
closedir(ourDir);
-
}
std::string diry("C:\\Projects\\boxbuild\\testfiles\\");
@@ -41,60 +242,83 @@
do
{
info = readdir(ourDir);
- if ( info == NULL ) break;
+ if (info == NULL) break;
std::string file(diry + info->d_name);
stat(file.c_str(), &ourfs);
- if ( info ) printf("File/Dir name is : %s\r\n", info->d_name);
+ if (info) printf("File/Dir name is : %s\r\n", info->d_name);
+ }
+ while ( info != NULL );
- }while ( info != NULL );
-
closedir(ourDir);
}
stat("c:\\windows", &ourfs);
stat("c:\\autoexec.bat", &ourfs);
- printf("Finished dir read");
-#if 0
- //remove - sleepycat include a version of getopt - mine never REALLY worked !
+ printf("Finished dir read\n");
+
//test our getopt function
- std::string commline("-q -c fgfgfg -f -l hello");
+ char * test_argv[] =
+ {
+ "foobar.exe",
+ "-qwc",
+ "-",
+ "-c",
+ "fgfgfg",
+ "-f",
+ "-l",
+ "hello",
+ "-",
+ "force-sync",
+ NULL
+ };
+ int test_argc;
+ for (test_argc = 0; test_argv[test_argc]; test_argc++) { }
+ const char* opts = "qwc:l:";
- int c;
- while((c = getopt(commline.size(), (char * const *)commline.c_str(), "qwc:l:")) != -1)
- {
- printf("switch = %c, param is %s\r\n", c, optarg);
- }
-#endif
+ assert(getopt(test_argc, test_argv, opts) == 'q');
+ assert(getopt(test_argc, test_argv, opts) == 'w');
+ assert(getopt(test_argc, test_argv, opts) == 'c');
+ assert(strcmp(optarg, "-") == 0);
+ assert(getopt(test_argc, test_argv, opts) == 'c');
+ assert(strcmp(optarg, "fgfgfg") == 0);
+ assert(getopt(test_argc, test_argv, opts) == '?');
+ assert(optopt == 'f');
+ assert(getopt(test_argc, test_argv, opts) == 'l');
+ assert(strcmp(optarg, "hello") == 0);
+ assert(getopt(test_argc, test_argv, opts) == -1);
+ // assert(optopt == 0); // no more options
+ assert(strcmp(test_argv[optind], "-") == 0);
+ assert(strcmp(test_argv[optind+1], "force-sync") == 0);
//end of getopt test
//now test our statfs funct
stat("c:\\cert.cer", &ourfs);
-
-
char *timee;
timee = ctime(&ourfs.st_mtime);
- if ( S_ISREG(ourfs.st_mode))
+ if (S_ISREG(ourfs.st_mode))
{
- printf("is a normal file");
+ printf("is a normal file\n");
}
else
{
- printf("is a directory?");
+ printf("is a directory?\n");
+ exit(1);
}
- lstat("c:\\windows", &ourfs);
+ lstat(getenv("WINDIR"), &ourfs);
if ( S_ISDIR(ourfs.st_mode))
{
- printf("is a directory");
+ printf("is a directory\n");
}
else
{
- printf("is a file?");
+ printf("is a file?\n");
+ exit(1);
}
//test the syslog functions
@@ -105,6 +329,7 @@
closelog();
+ /*
//first off get the path name for the default
char buf[MAX_PATH];
@@ -112,8 +337,8 @@
std::string buffer(buf);
std::string conf("-c " + buffer.substr(0,(buffer.find("win32test.exe"))) + "bbackupd.conf");
//std::string conf( "-c " + buffer.substr(0,(buffer.find("bbackupd.exe"))) + "bbackupd.conf");
+ */
-
return 0;
}
Modified: box/chris/merge/win32.bat
===================================================================
--- box/chris/merge/win32.bat 2006-07-27 23:15:09 UTC (rev 709)
+++ box/chris/merge/win32.bat 2006-07-27 23:18:35 UTC (rev 710)
@@ -3,6 +3,8 @@
echo quick and dirty to get up and running by generating the required files
echo using Cygwin and Perl
+copy .\infrastructure\BoxPlatform.pm.in .\infrastructure\BoxPlatform.pm
+
cd .\bin\bbackupquery\ & perl ./../../bin/bbackupquery/makedocumentation.pl
cd ..\..\
@@ -25,4 +27,4 @@
cd .\lib\server & perl ./../../lib/common/makeexception.pl ServerException.txt & perl ./../../lib/common/makeexception.pl ConnectionException.txt
cd ..\..\
-copy lib\win32\config.h.win32 lib\common\BoxConfig.h
+perl -i.orig -pe 's/@PERL@/perl/' ./test/bbackupd/testfiles/bbackupd.conf
More information about the Boxbackup-dev
mailing list