[Box Backup-dev] Win32 merge
Chris Wilson
boxbackup-dev at fluffy.co.uk
Fri Jul 28 09:02:03 BST 2006
Hi all,
This is my current patch queue. I think that all of these are safe to
apply. This is about half of the pending changes in chris/general (the
easy half).
Please consider this patch for merge into trunk. You can also access it
via:
svn diff http://bbdev.fluffy.co.uk/svn/box/trunk \
http://bbdev.fluffy.co.uk/svn/box/chris/merge
I'm afraid I will be away for a week from tomorrow (Saturday) without
Internet access.
Cheers, Chris.
On Thu, 27 Jul 2006 subversion at fluffy.co.uk wrote:
> 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
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev at fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
>
>
> !DSPAM:44c94e4762851924114159!
>
--
_ ___ __ _
/ __/ / ,__(_)_ | Chris Wilson <0000 at qwirx.com> - Cambs UK |
/ (_/ ,\/ _/ /_ \ | Security/C/C++/Java/Perl/SQL/HTML Developer |
\ _/_/_/_//_/___/ | We are GNU-free your mind-and your software |
More information about the Boxbackup-dev
mailing list