From boxbackup-dev@fluffy.co.uk  Mon Jul  3 23:03:49 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Mon, 3 Jul 2006 23:03:49 +0100 (BST)
Subject: [Box Backup-dev] Win32 client
In-Reply-To: <EA946EE6-7CF5-4AEA-AF2F-98068BDF57C9@fluffy.co.uk>
References: <bab9f1d50606210133i44ddef39xb1ec6fb819d1ac53@mail.gmail.com>
 <Pine.LNX.4.62.0606290108470.15993@top.qwarx.com>
 <EA946EE6-7CF5-4AEA-AF2F-98068BDF57C9@fluffy.co.uk>
Message-ID: <Pine.LNX.4.62.0607032259420.15993@top.qwarx.com>

Hi Ben,

On Thu, 29 Jun 2006, Ben Summers wrote:
> On 29 Jun 2006, at 01:13, Chris Wilson wrote:
>>  Visual Studio doesn't know how to get the version out of Subversion or 
>>  read the VERSION.TXT file, so the version is hard-coded to 
>>  "0.09hWin32" in lib/win32/emu.h.
>
> http://svnbook.red-bean.com/en/1.1/ch07s02.html#svn-ch-7-sect-2.3.4
>
> But only for one special Win32 only file, please.

Are you sure that this will work? My reading of that section is that the 
$Revision$ keyword would be the "best" one to use in config.h.win32, 
together with some run-time mangling of the substituted value to return a 
plain revision number. But it says:

   Revision

     This keyword describes the last known revision in which this file
     changed in the repository, and looks something like $Revision: 144 $.

That means that it will only be changed when config.h.win32 changes, i.e. 
it's not the checked-out revision number, and ignores changes to the rest 
of the code.

Am I missing something?

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Tue Jul  4 09:47:02 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Tue, 4 Jul 2006 09:47:02 +0100
Subject: [Box Backup-dev] Win32 client
In-Reply-To: <Pine.LNX.4.62.0607032259420.15993@top.qwarx.com>
References: <bab9f1d50606210133i44ddef39xb1ec6fb819d1ac53@mail.gmail.com> <Pine.LNX.4.62.0606290108470.15993@top.qwarx.com> <EA946EE6-7CF5-4AEA-AF2F-98068BDF57C9@fluffy.co.uk> <Pine.LNX.4.62.0607032259420.15993@top.qwarx.com>
Message-ID: <BFC49E8E-F83C-4776-A900-1E5812E80C82@fluffy.co.uk>

On 3 Jul 2006, at 23:03, Chris Wilson wrote:

> Hi Ben,
>
> On Thu, 29 Jun 2006, Ben Summers wrote:
>> On 29 Jun 2006, at 01:13, Chris Wilson wrote:
>>>  Visual Studio doesn't know how to get the version out of  
>>> Subversion or  read the VERSION.TXT file, so the version is hard- 
>>> coded to  "0.09hWin32" in lib/win32/emu.h.
>>
>> http://svnbook.red-bean.com/en/1.1/ch07s02.html#svn-ch-7-sect-2.3.4
>>
>> But only for one special Win32 only file, please.
>
> Are you sure that this will work? My reading of that section is  
> that the $Revision$ keyword would be the "best" one to use in  
> config.h.win32, together with some run-time mangling of the  
> substituted value to return a plain revision number. But it says:
>
>   Revision
>
>     This keyword describes the last known revision in which this file
>     changed in the repository, and looks something like $Revision:  
> 144 $.
>
> That means that it will only be changed when config.h.win32  
> changes, i.e. it's not the checked-out revision number, and ignores  
> changes to the rest of the code.
>
> Am I missing something?

No, I wasn't reading things properly.

You really can't run a script as part of your build process to fish  
out the revision number?

Ben






From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:34:10 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:34:10 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r628 - box/chris/general/infrastructure/msvc
Message-ID: <20060706203410.31CA796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:34:07 +0000 (Thu, 06 Jul 2006)
New Revision: 628

Added:
   box/chris/general/infrastructure/msvc/getversion.pl
Log:
* getversion.pl
- Added a Perl script to determine the product version number for MSVC


Added: box/chris/general/infrastructure/msvc/getversion.pl
===================================================================
--- box/chris/general/infrastructure/msvc/getversion.pl	2006-06-29 00:09:25 UTC (rev 627)
+++ box/chris/general/infrastructure/msvc/getversion.pl	2006-07-06 20:34:07 UTC (rev 628)
@@ -0,0 +1,19 @@
+#!perl
+
+$basedir = $0;
+$basedir =~ s/\\[^\\]*$//;
+$basedir =~ s/\\[^\\]*$//;
+$basedir =~ s/\\[^\\]*$//;
+$basedir =~ s/\\[^\\]*$//;
+$basedir =~ s/\\[^\\]*$//;
+-d $basedir or die "$basedir: $!";
+chdir $basedir or die "$basedir: $!";
+
+require "$basedir\\infrastructure\\BoxPlatform.pm.in";
+
+open VERSIONFILE, "> $basedir/lib/common/BoxVersion.h" 
+	or die "BoxVersion.h: $!";
+print VERSIONFILE "#define BOX_VERSION \"$BoxPlatform::product_version\"\n";
+close VERSIONFILE;
+
+exit 0;


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:46:41 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:46:41 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r629 - box/chris/general/infrastructure
Message-ID: <20060706204641.03F7996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:46:40 +0000 (Thu, 06 Jul 2006)
New Revision: 629

Modified:
   box/chris/general/infrastructure/BoxPlatform.pm.in
Log:
* BoxPlatform.pm.in
- Avoid errors trying to run "uname" which doesn't exist when building
  with Visual Studio on Windows


Modified: box/chris/general/infrastructure/BoxPlatform.pm.in
===================================================================
--- box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-06 20:34:07 UTC (rev 628)
+++ box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-06 20:46:40 UTC (rev 629)
@@ -7,10 +7,24 @@
 {
 
 	# 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 -p`;
+		chomp $build_cpu;
+	}
+
 	# Cygwin Builds usually something like CYGWIN_NT-5.0, CYGWIN_NT-5.1
 	# Box Backup tried on Win2000,XP only :)
 
@@ -24,13 +38,8 @@
 	$platform_compile_line_extra =~ s/ -O2//;
 	$platform_link_line_extra = '@LDFLAGS@';
 	$platform_lib_files = '@LIBS@';
-	$target_os = '@target_os@';
 	$platform_exe_ext = '@EXEEXT@';
 
-	$target_windows = 0;
-	$target_windows = 1 if $target_os =~ m'^mingw32' 
-		or $target_os eq "winnt";
-
 	# get version
 	if (! -r "VERSION.txt" and -r "../../VERSION.txt")
 	{


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:47:25 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:47:25 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r630 - in box/chris/general/infrastructure/msvc: 2003 2005
Message-ID: <20060706204725.B6C4B96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:47:21 +0000 (Thu, 06 Jul 2006)
New Revision: 630

Modified:
   box/chris/general/infrastructure/msvc/2003/common.vcproj
   box/chris/general/infrastructure/msvc/2005/common.vcproj
Log:
* msvc/2003/common.vcproj
* msvc/2005/common.vcproj
- Updated for new location of WinNamedPipeStream.{cpp,h}
- Added pre-build event script to determine version number


Modified: box/chris/general/infrastructure/msvc/2003/common.vcproj
===================================================================
--- box/chris/general/infrastructure/msvc/2003/common.vcproj	2006-07-06 20:46:40 UTC (rev 629)
+++ box/chris/general/infrastructure/msvc/2003/common.vcproj	2006-07-06 20:47:21 UTC (rev 630)
@@ -290,9 +290,6 @@
 					<File
 						RelativePath="..\..\..\lib\win32\getopt_long.cxx">
 					</File>
-					<File
-						RelativePath="..\..\..\lib\win32\WinNamedPipeStream.cpp">
-					</File>
 				</Filter>
 				<Filter
 					Name="server"
@@ -333,6 +330,10 @@
 					<File
 						RelativePath="..\..\..\lib\server\TLSContext.cpp">
 					</File>
+					<File
+						RelativePath="..\..\..\lib\server\WinNamedPipeStream.cpp">
+					</File>
+
 				</Filter>
 			</Filter>
 		</Filter>
@@ -482,6 +483,9 @@
 					<File
 						RelativePath="..\..\..\lib\common\WaitForEvent.h">
 					</File>
+					<File
+						RelativePath="..\..\..\lib\common\BoxVersion.h">
+					</File>
 				</Filter>
 				<Filter
 					Name="backupclient"
@@ -633,6 +637,9 @@
 					<File
 						RelativePath="..\..\..\lib\server\TLSContext.h">
 					</File>
+					<File
+						RelativePath="..\..\..\lib\server\WinNamedPipeStream.h">
+					</File>
 				</Filter>
 			</Filter>
 		</Filter>

Modified: box/chris/general/infrastructure/msvc/2005/common.vcproj
===================================================================
--- box/chris/general/infrastructure/msvc/2005/common.vcproj	2006-07-06 20:46:40 UTC (rev 629)
+++ box/chris/general/infrastructure/msvc/2005/common.vcproj	2006-07-06 20:47:21 UTC (rev 630)
@@ -25,11 +25,10 @@
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
+				Description="Determining Version Number"
+				CommandLine="perl $(InputDir)..\getversion.pl"
 			/>
 			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
 				Name="VCXMLDataGeneratorTool"
 			/>
 			<Tool
@@ -397,10 +396,6 @@
 						RelativePath="..\..\..\lib\win32\getopt_long.cxx"
 						>
 					</File>
-					<File
-						RelativePath="..\..\..\lib\win32\WinNamedPipeStream.cpp"
-						>
-					</File>
 				</Filter>
 				<Filter
 					Name="server"
@@ -453,6 +448,10 @@
 						RelativePath="..\..\..\lib\server\TLSContext.cpp"
 						>
 					</File>
+					<File
+						RelativePath="..\..\..\lib\server\WinNamedPipeStream.cpp"
+						>
+					</File>
 				</Filter>
 			</Filter>
 		</Filter>
@@ -536,6 +535,10 @@
 						>
 					</File>
 					<File
+						RelativePath="..\..\..\lib\common\BoxVersion.h"
+						>
+					</File>
+					<File
 						RelativePath="..\..\..\lib\common\CollectInBufferStream.h"
 						>
 					</File>
@@ -771,10 +774,6 @@
 						RelativePath="..\..\..\lib\win32\getopt.h"
 						>
 					</File>
-					<File
-						RelativePath="..\..\..\lib\win32\WinNamedPipeStream.h"
-						>
-					</File>
 				</Filter>
 				<Filter
 					Name="server"
@@ -843,6 +842,10 @@
 						RelativePath="..\..\..\lib\server\TLSContext.h"
 						>
 					</File>
+					<File
+						RelativePath="..\..\..\lib\server\WinNamedPipeStream.h"
+						>
+					</File>
 				</Filter>
 			</Filter>
 		</Filter>


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:48:30 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:48:30 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r631 - in box/chris/general/lib: server win32
Message-ID: <20060706204830.C2B6796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:48:26 +0000 (Thu, 06 Jul 2006)
New Revision: 631

Added:
   box/chris/general/lib/server/WinNamedPipeStream.cpp
   box/chris/general/lib/server/WinNamedPipeStream.h
Removed:
   box/chris/general/lib/win32/WinNamedPipeStream.cpp
   box/chris/general/lib/win32/WinNamedPipeStream.h
Log:
* win32/WinNamedPipeStream.cpp
* win32/WinNamedPipeStream.h
- Moved to lib/server to avoid circular dependencies between lib/win32 and
  lib/common


Copied: box/chris/general/lib/server/WinNamedPipeStream.cpp (from rev 622, box/chris/general/lib/win32/WinNamedPipeStream.cpp)
===================================================================
--- box/chris/general/lib/win32/WinNamedPipeStream.cpp	2006-06-05 17:11:37 UTC (rev 622)
+++ box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-06 20:48:26 UTC (rev 631)
@@ -0,0 +1,478 @@
+// --------------------------------------------------------------------------
+//
+// File
+//		Name:    WinNamedPipeStream.cpp
+//		Purpose: I/O stream interface for Win32 named pipes
+//		Created: 2005/12/07
+//
+// --------------------------------------------------------------------------
+
+#include "Box.h"
+
+#ifdef WIN32
+
+#ifdef HAVE_UNISTD_H
+	#include <unistd.h>
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+#include <windows.h>
+
+#include "WinNamedPipeStream.h"
+#include "ServerException.h"
+#include "CommonException.h"
+#include "Socket.h"
+
+#include "MemLeakFindOn.h"
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::WinNamedPipeStream()
+//		Purpose: Constructor (create stream ready for Open() call)
+//		Created: 2005/12/07
+//
+// --------------------------------------------------------------------------
+WinNamedPipeStream::WinNamedPipeStream()
+	: mSocketHandle(INVALID_HANDLE_VALUE),
+	  mReadableEvent(INVALID_HANDLE_VALUE),
+	  mBytesInBuffer(0),
+	  mReadClosed(false),
+	  mWriteClosed(false),
+	  mIsServer(false),
+	  mIsConnected(false)
+{
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::~WinNamedPipeStream()
+//		Purpose: Destructor, closes stream if open
+//		Created: 2005/12/07
+//
+// --------------------------------------------------------------------------
+WinNamedPipeStream::~WinNamedPipeStream()
+{
+	if (mSocketHandle != INVALID_HANDLE_VALUE)
+	{
+		Close();
+	}
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::Accept(const char* Name)
+//		Purpose: Creates a new named pipe with the given name,
+//			and wait for a connection on it
+//		Created: 2005/12/07
+//
+// --------------------------------------------------------------------------
+void WinNamedPipeStream::Accept(const wchar_t* pName)
+{
+	if (mSocketHandle != INVALID_HANDLE_VALUE || mIsConnected) 
+	{
+		THROW_EXCEPTION(ServerException, SocketAlreadyOpen)
+	}
+
+	mSocketHandle = CreateNamedPipeW( 
+		pName,                     // pipe name 
+		PIPE_ACCESS_DUPLEX |       // read/write access 
+		FILE_FLAG_OVERLAPPED,      // enabled overlapped I/O
+		PIPE_TYPE_MESSAGE |        // message type pipe 
+		PIPE_READMODE_MESSAGE |    // message-read mode 
+		PIPE_WAIT,                 // blocking mode 
+		1,                         // max. instances  
+		4096,                      // output buffer size 
+		4096,                      // input buffer size 
+		NMPWAIT_USE_DEFAULT_WAIT,  // client time-out 
+		NULL);                     // default security attribute 
+
+	if (mSocketHandle == INVALID_HANDLE_VALUE)
+	{
+		::syslog(LOG_ERR, "CreateNamedPipeW failed: %d", 
+			GetLastError());
+		THROW_EXCEPTION(ServerException, SocketOpenError)
+	}
+
+	bool connected = ConnectNamedPipe(mSocketHandle, (LPOVERLAPPED) NULL);
+
+	if (!connected)
+	{
+		::syslog(LOG_ERR, "ConnectNamedPipe failed: %d", 
+			GetLastError());
+		Close();
+		THROW_EXCEPTION(ServerException, SocketOpenError)
+	}
+	
+	mReadClosed  = false;
+	mWriteClosed = false;
+	mIsServer    = true; // must flush and disconnect before closing
+	mIsConnected = true;
+
+	// create the Readable event
+	mReadableEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+	if (mReadableEvent == INVALID_HANDLE_VALUE)
+	{
+		::syslog(LOG_ERR, "Failed to create the Readable event: "
+			"error %d", GetLastError());
+		Close();
+		THROW_EXCEPTION(CommonException, Internal)
+	}
+
+	// initialise the OVERLAPPED structure
+	memset(&mReadOverlap, 0, sizeof(mReadOverlap));
+	mReadOverlap.hEvent = mReadableEvent;
+
+	// start the first overlapped read
+	if (!ReadFile(mSocketHandle, mReadBuffer, sizeof(mReadBuffer),
+		NULL, &mReadOverlap))
+	{
+		DWORD err = GetLastError();
+
+		if (err != ERROR_IO_PENDING)
+		{
+			::syslog(LOG_ERR, "Failed to start overlapped read: "
+				"error %d", err);
+			Close();
+			THROW_EXCEPTION(ConnectionException, 
+				Conn_SocketReadError)
+		}
+	}
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::Connect(const char* Name)
+//		Purpose: Opens a connection to a listening named pipe
+//		Created: 2005/12/07
+//
+// --------------------------------------------------------------------------
+void WinNamedPipeStream::Connect(const wchar_t* pName)
+{
+	if (mSocketHandle != INVALID_HANDLE_VALUE || mIsConnected) 
+	{
+		THROW_EXCEPTION(ServerException, SocketAlreadyOpen)
+	}
+	
+	mSocketHandle = CreateFileW( 
+		pName,          // pipe name 
+		GENERIC_READ |  // read and write access 
+		GENERIC_WRITE, 
+		0,              // no sharing 
+		NULL,           // default security attributes
+		OPEN_EXISTING,
+		0,              // default attributes 
+		NULL);          // no template file 
+
+	if (mSocketHandle == INVALID_HANDLE_VALUE)
+	{
+		DWORD err = GetLastError();
+		if (err == ERROR_PIPE_BUSY)
+		{
+			::syslog(LOG_ERR, "Failed to connect to backup "
+				"daemon: it is busy with another connection");
+		}
+		else
+		{
+			::syslog(LOG_ERR, "Failed to connect to backup "
+				"daemon: error %d", err);
+		}
+		THROW_EXCEPTION(ServerException, SocketOpenError)
+	}
+
+	mReadClosed  = false;
+	mWriteClosed = false;
+	mIsServer    = false; // just close the socket
+	mIsConnected = true;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::Read(void *pBuffer, int NBytes)
+//		Purpose: Reads data from stream. Maybe returns less than asked for.
+//		Created: 2003/07/31
+//
+// --------------------------------------------------------------------------
+int WinNamedPipeStream::Read(void *pBuffer, int NBytes, int Timeout)
+{
+	// TODO no support for timeouts yet
+	if (Timeout != IOStream::TimeOutInfinite)
+	{
+		THROW_EXCEPTION(CommonException, AssertFailed)
+	}
+	
+	if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) 
+	{
+		THROW_EXCEPTION(ServerException, BadSocketHandle)
+	}
+
+	DWORD NumBytesRead;
+
+	if (mIsServer)
+	{
+		// overlapped I/O completed successfully? (wait if needed)
+
+		if (!GetOverlappedResult(mSocketHandle,
+			&mReadOverlap, &NumBytesRead, TRUE))
+		{
+			DWORD err = GetLastError();
+
+			if (err == ERROR_HANDLE_EOF)
+			{
+				mReadClosed = true;
+			}
+			else if (err == ERROR_BROKEN_PIPE)
+			{
+				::syslog(LOG_ERR, 
+					"Control client disconnected");
+				mReadClosed = true;
+			}
+			else
+			{
+				::syslog(LOG_ERR, "Failed to wait for "
+					"ReadFile to complete: error %d", err);
+				Close();
+				THROW_EXCEPTION(ConnectionException, 
+					Conn_SocketReadError)
+			}
+		}
+
+		size_t BytesToCopy = NumBytesRead + mBytesInBuffer;
+		size_t BytesRemaining = 0;
+
+		if (BytesToCopy > NBytes)
+		{
+			BytesRemaining = BytesToCopy - NBytes;
+			BytesToCopy = NBytes;
+		}
+
+		memcpy(pBuffer, mReadBuffer, BytesToCopy);
+		memcpy(mReadBuffer, mReadBuffer + BytesToCopy, BytesRemaining);
+
+		mBytesInBuffer = BytesRemaining;
+		NumBytesRead = BytesToCopy;
+
+		// start the next overlapped read
+		if (!ReadFile(mSocketHandle, 
+			mReadBuffer + mBytesInBuffer, 
+			sizeof(mReadBuffer) - mBytesInBuffer,
+			NULL, &mReadOverlap))
+		{
+			DWORD err = GetLastError();
+			if (err == ERROR_IO_PENDING)
+			{
+				ResetEvent(mReadableEvent);
+			}
+			else if (err == ERROR_HANDLE_EOF)
+			{
+				mReadClosed = true;
+			}
+			else
+			{
+				::syslog(LOG_ERR, "Failed to start "
+					"overlapped read: error %d", err);
+				Close();
+				THROW_EXCEPTION(ConnectionException, 
+					Conn_SocketReadError)
+			}
+		}
+
+		// If the read succeeded immediately, leave the event 
+		// signaled, so that we will be called again to process 
+		// the newly read data and start another overlapped read.
+	}
+	else
+	{
+		if (!ReadFile( 
+			mSocketHandle, // pipe handle 
+			pBuffer,       // buffer to receive reply 
+			NBytes,        // size of buffer 
+			&NumBytesRead, // number of bytes read 
+			NULL))         // not overlapped 
+		{
+			Close();
+			THROW_EXCEPTION(ConnectionException, 
+				Conn_SocketReadError)
+		}
+		
+		// Closed for reading at EOF?
+		if (NumBytesRead == 0)
+		{
+			mReadClosed = true;
+		}
+	}
+		
+	return NumBytesRead;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::Write(void *pBuffer, int NBytes)
+//		Purpose: Writes data, blocking until it's all done.
+//		Created: 2003/07/31
+//
+// --------------------------------------------------------------------------
+void WinNamedPipeStream::Write(const void *pBuffer, int NBytes)
+{
+	if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) 
+	{
+		THROW_EXCEPTION(ServerException, BadSocketHandle)
+	}
+	
+	// Buffer in byte sized type.
+	ASSERT(sizeof(char) == 1);
+	const char *pByteBuffer = (char *)pBuffer;
+	
+	int NumBytesWrittenTotal = 0;
+
+	while (NumBytesWrittenTotal < NBytes)
+	{
+		DWORD NumBytesWrittenThisTime = 0;
+
+		bool Success = WriteFile( 
+			mSocketHandle,    // pipe handle 
+			pByteBuffer + NumBytesWrittenTotal, // message 
+			NBytes      - NumBytesWrittenTotal, // message length 
+			&NumBytesWrittenThisTime, // bytes written this time
+			NULL);            // not overlapped 
+
+		if (!Success)
+		{
+			Close();
+			THROW_EXCEPTION(ConnectionException, 
+				Conn_SocketWriteError)
+		}
+
+		NumBytesWrittenTotal += NumBytesWrittenThisTime;
+	}
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::Close()
+//		Purpose: Closes connection to remote socket
+//		Created: 2003/07/31
+//
+// --------------------------------------------------------------------------
+void WinNamedPipeStream::Close()
+{
+	if (mSocketHandle == INVALID_HANDLE_VALUE && mIsConnected)
+	{
+		fprintf(stderr, "Inconsistent connected state\n");
+		::syslog(LOG_ERR, "Inconsistent connected state");
+		mIsConnected = false;
+	}
+
+	if (mSocketHandle == INVALID_HANDLE_VALUE) 
+	{
+		THROW_EXCEPTION(ServerException, BadSocketHandle)
+	}
+
+	if (mIsServer)
+	{
+		if (!CancelIo(mSocketHandle))
+		{
+			::syslog(LOG_ERR, "Failed to cancel outstanding "
+				"I/O: error %d", GetLastError());
+		}
+
+		if (mReadableEvent == INVALID_HANDLE_VALUE)
+		{
+			::syslog(LOG_ERR, "Failed to destroy Readable "
+				"event: invalid handle");
+		}
+		else if (!CloseHandle(mReadableEvent))
+		{
+			::syslog(LOG_ERR, "Failed to destroy Readable "
+				"event: error %d", GetLastError());
+		}
+
+		mReadableEvent = INVALID_HANDLE_VALUE;
+
+		if (!FlushFileBuffers(mSocketHandle))
+		{
+			::syslog(LOG_INFO, "FlushFileBuffers failed: %d", 
+				GetLastError());
+		}
+	
+		if (!DisconnectNamedPipe(mSocketHandle))
+		{
+			::syslog(LOG_ERR, "DisconnectNamedPipe failed: %d", 
+				GetLastError());
+		}
+
+		mIsServer = false;
+	}
+
+	bool result = CloseHandle(mSocketHandle);
+
+	mSocketHandle = INVALID_HANDLE_VALUE;
+	mIsConnected = false;
+	mReadClosed  = true;
+	mWriteClosed = true;
+
+	if (!result) 
+	{
+		::syslog(LOG_ERR, "CloseHandle failed: %d", GetLastError());
+		THROW_EXCEPTION(ServerException, SocketCloseError)
+	}
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::StreamDataLeft()
+//		Purpose: Still capable of reading data?
+//		Created: 2003/08/02
+//
+// --------------------------------------------------------------------------
+bool WinNamedPipeStream::StreamDataLeft()
+{
+	return !mReadClosed;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    WinNamedPipeStream::StreamClosed()
+//		Purpose: Connection been closed?
+//		Created: 2003/08/02
+//
+// --------------------------------------------------------------------------
+bool WinNamedPipeStream::StreamClosed()
+{
+	return mWriteClosed;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    IOStream::WriteAllBuffered()
+//		Purpose: Ensures that any data which has been buffered is written to the stream
+//		Created: 2003/08/26
+//
+// --------------------------------------------------------------------------
+void WinNamedPipeStream::WriteAllBuffered()
+{
+	if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) 
+	{
+		THROW_EXCEPTION(ServerException, BadSocketHandle)
+	}
+	
+	if (!FlushFileBuffers(mSocketHandle))
+	{
+		::syslog(LOG_WARNING, "FlushFileBuffers failed: %d", 
+			GetLastError());
+	}
+}
+
+
+#endif // WIN32

Copied: box/chris/general/lib/server/WinNamedPipeStream.h (from rev 622, box/chris/general/lib/win32/WinNamedPipeStream.h)

Deleted: box/chris/general/lib/win32/WinNamedPipeStream.cpp
===================================================================
--- box/chris/general/lib/win32/WinNamedPipeStream.cpp	2006-07-06 20:47:21 UTC (rev 630)
+++ box/chris/general/lib/win32/WinNamedPipeStream.cpp	2006-07-06 20:48:26 UTC (rev 631)
@@ -1,463 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-//		Name:    WinNamedPipeStream.cpp
-//		Purpose: I/O stream interface for Win32 named pipes
-//		Created: 2005/12/07
-//
-// --------------------------------------------------------------------------
-
-#include "Box.h"
-
-#ifdef WIN32
-
-#ifdef HAVE_UNISTD_H
-	#include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#include <errno.h>
-#include <windows.h>
-
-#include "WinNamedPipeStream.h"
-#include "ServerException.h"
-#include "CommonException.h"
-#include "Socket.h"
-
-#include "MemLeakFindOn.h"
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::WinNamedPipeStream()
-//		Purpose: Constructor (create stream ready for Open() call)
-//		Created: 2005/12/07
-//
-// --------------------------------------------------------------------------
-WinNamedPipeStream::WinNamedPipeStream()
-	: mSocketHandle(INVALID_HANDLE_VALUE),
-	  mReadableEvent(INVALID_HANDLE_VALUE),
-	  mBytesInBuffer(0),
-	  mReadClosed(false),
-	  mWriteClosed(false),
-	  mIsServer(false),
-	  mIsConnected(false)
-{
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::~WinNamedPipeStream()
-//		Purpose: Destructor, closes stream if open
-//		Created: 2005/12/07
-//
-// --------------------------------------------------------------------------
-WinNamedPipeStream::~WinNamedPipeStream()
-{
-	if (mSocketHandle != INVALID_HANDLE_VALUE)
-	{
-		Close();
-	}
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::Accept(const char* Name)
-//		Purpose: Creates a new named pipe with the given name,
-//			and wait for a connection on it
-//		Created: 2005/12/07
-//
-// --------------------------------------------------------------------------
-void WinNamedPipeStream::Accept(const wchar_t* pName)
-{
-	if (mSocketHandle != INVALID_HANDLE_VALUE || mIsConnected) 
-	{
-		THROW_EXCEPTION(ServerException, SocketAlreadyOpen)
-	}
-
-	mSocketHandle = CreateNamedPipeW( 
-		pName,                     // pipe name 
-		PIPE_ACCESS_DUPLEX |       // read/write access 
-		FILE_FLAG_OVERLAPPED,      // enabled overlapped I/O
-		PIPE_TYPE_MESSAGE |        // message type pipe 
-		PIPE_READMODE_MESSAGE |    // message-read mode 
-		PIPE_WAIT,                 // blocking mode 
-		1,                         // max. instances  
-		4096,                      // output buffer size 
-		4096,                      // input buffer size 
-		NMPWAIT_USE_DEFAULT_WAIT,  // client time-out 
-		NULL);                     // default security attribute 
-
-	if (mSocketHandle == INVALID_HANDLE_VALUE)
-	{
-		::syslog(LOG_ERR, "CreateNamedPipeW failed: %d", 
-			GetLastError());
-		THROW_EXCEPTION(ServerException, SocketOpenError)
-	}
-
-	bool connected = ConnectNamedPipe(mSocketHandle, (LPOVERLAPPED) NULL);
-
-	if (!connected)
-	{
-		::syslog(LOG_ERR, "ConnectNamedPipe failed: %d", 
-			GetLastError());
-		Close();
-		THROW_EXCEPTION(ServerException, SocketOpenError)
-	}
-	
-	mReadClosed  = false;
-	mWriteClosed = false;
-	mIsServer    = true; // must flush and disconnect before closing
-	mIsConnected = true;
-
-	// create the Readable event
-	mReadableEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-	if (mReadableEvent == INVALID_HANDLE_VALUE)
-	{
-		::syslog(LOG_ERR, "Failed to create the Readable event: "
-			"error %d", GetLastError());
-		Close();
-		THROW_EXCEPTION(CommonException, Internal)
-	}
-
-	// initialise the OVERLAPPED structure
-	memset(&mReadOverlap, 0, sizeof(mReadOverlap));
-	mReadOverlap.hEvent = mReadableEvent;
-
-	// start the first overlapped read
-	if (!ReadFile(mSocketHandle, mReadBuffer, sizeof(mReadBuffer),
-		NULL, &mReadOverlap))
-	{
-		DWORD err = GetLastError();
-
-		if (err != ERROR_IO_PENDING)
-		{
-			::syslog(LOG_ERR, "Failed to start overlapped read: "
-				"error %d", err);
-			Close();
-			THROW_EXCEPTION(ConnectionException, 
-				Conn_SocketReadError)
-		}
-	}
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::Connect(const char* Name)
-//		Purpose: Opens a connection to a listening named pipe
-//		Created: 2005/12/07
-//
-// --------------------------------------------------------------------------
-void WinNamedPipeStream::Connect(const wchar_t* pName)
-{
-	if (mSocketHandle != INVALID_HANDLE_VALUE || mIsConnected) 
-	{
-		THROW_EXCEPTION(ServerException, SocketAlreadyOpen)
-	}
-	
-	mSocketHandle = CreateFileW( 
-		pName,          // pipe name 
-		GENERIC_READ |  // read and write access 
-		GENERIC_WRITE, 
-		0,              // no sharing 
-		NULL,           // default security attributes
-		OPEN_EXISTING,
-		0,              // default attributes 
-		NULL);          // no template file 
-
-	if (mSocketHandle == INVALID_HANDLE_VALUE)
-	{
-		::syslog(LOG_ERR, "Failed to connect to server's named pipe: "
-			"error %d", GetLastError());
-		THROW_EXCEPTION(ServerException, SocketOpenError)
-	}
-
-	mReadClosed  = false;
-	mWriteClosed = false;
-	mIsServer    = false; // just close the socket
-	mIsConnected = true;
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::Read(void *pBuffer, int NBytes)
-//		Purpose: Reads data from stream. Maybe returns less than asked for.
-//		Created: 2003/07/31
-//
-// --------------------------------------------------------------------------
-int WinNamedPipeStream::Read(void *pBuffer, int NBytes, int Timeout)
-{
-	// TODO no support for timeouts yet
-	if (Timeout != IOStream::TimeOutInfinite)
-	{
-		THROW_EXCEPTION(CommonException, AssertFailed)
-	}
-	
-	if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) 
-	{
-		THROW_EXCEPTION(ServerException, BadSocketHandle)
-	}
-
-	DWORD NumBytesRead;
-
-	if (mIsServer)
-	{
-		// overlapped I/O completed successfully? (wait if needed)
-
-		if (!GetOverlappedResult(mSocketHandle,
-			&mReadOverlap, &NumBytesRead, TRUE))
-		{
-			DWORD err = GetLastError();
-
-			if (err == ERROR_HANDLE_EOF)
-			{
-				mReadClosed = true;
-			}
-			else
-			{
-				::syslog(LOG_ERR, "Failed to wait for "
-					"ReadFile to complete: error %d", err);
-				Close();
-				THROW_EXCEPTION(ConnectionException, 
-					Conn_SocketReadError)
-			}
-		}
-
-		size_t BytesToCopy = NumBytesRead + mBytesInBuffer;
-		size_t BytesRemaining = 0;
-
-		if (BytesToCopy > NBytes)
-		{
-			BytesRemaining = BytesToCopy - NBytes;
-			BytesToCopy = NBytes;
-		}
-
-		memcpy(pBuffer, mReadBuffer, BytesToCopy);
-		memcpy(mReadBuffer, mReadBuffer + BytesToCopy, BytesRemaining);
-
-		mBytesInBuffer = BytesRemaining;
-		NumBytesRead = BytesToCopy;
-
-		// start the next overlapped read
-		if (!ReadFile(mSocketHandle, 
-			mReadBuffer + mBytesInBuffer, 
-			sizeof(mReadBuffer) - mBytesInBuffer,
-			NULL, &mReadOverlap))
-		{
-			DWORD err = GetLastError();
-			if (err == ERROR_IO_PENDING)
-			{
-				ResetEvent(mReadableEvent);
-			}
-			else if (err == ERROR_HANDLE_EOF)
-			{
-				mReadClosed = true;
-			}
-			else
-			{
-				::syslog(LOG_ERR, "Failed to start "
-					"overlapped read: error %d", err);
-				Close();
-				THROW_EXCEPTION(ConnectionException, 
-					Conn_SocketReadError)
-			}
-		}
-
-		// If the read succeeded immediately, leave the event 
-		// signaled, so that we will be called again to process 
-		// the newly read data and start another overlapped read.
-	}
-	else
-	{
-		if (!ReadFile( 
-			mSocketHandle, // pipe handle 
-			pBuffer,       // buffer to receive reply 
-			NBytes,        // size of buffer 
-			&NumBytesRead, // number of bytes read 
-			NULL))         // not overlapped 
-		{
-			Close();
-			THROW_EXCEPTION(ConnectionException, 
-				Conn_SocketReadError)
-		}
-		
-		// Closed for reading at EOF?
-		if (NumBytesRead == 0)
-		{
-			mReadClosed = true;
-		}
-	}
-		
-	return NumBytesRead;
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::Write(void *pBuffer, int NBytes)
-//		Purpose: Writes data, blocking until it's all done.
-//		Created: 2003/07/31
-//
-// --------------------------------------------------------------------------
-void WinNamedPipeStream::Write(const void *pBuffer, int NBytes)
-{
-	if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) 
-	{
-		THROW_EXCEPTION(ServerException, BadSocketHandle)
-	}
-	
-	// Buffer in byte sized type.
-	ASSERT(sizeof(char) == 1);
-	const char *pByteBuffer = (char *)pBuffer;
-	
-	int NumBytesWrittenTotal = 0;
-
-	while (NumBytesWrittenTotal < NBytes)
-	{
-		DWORD NumBytesWrittenThisTime = 0;
-
-		bool Success = WriteFile( 
-			mSocketHandle,    // pipe handle 
-			pByteBuffer + NumBytesWrittenTotal, // message 
-			NBytes      - NumBytesWrittenTotal, // message length 
-			&NumBytesWrittenThisTime, // bytes written this time
-			NULL);            // not overlapped 
-
-		if (!Success)
-		{
-			Close();
-			THROW_EXCEPTION(ConnectionException, 
-				Conn_SocketWriteError)
-		}
-
-		NumBytesWrittenTotal += NumBytesWrittenThisTime;
-	}
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::Close()
-//		Purpose: Closes connection to remote socket
-//		Created: 2003/07/31
-//
-// --------------------------------------------------------------------------
-void WinNamedPipeStream::Close()
-{
-	if (mSocketHandle == INVALID_HANDLE_VALUE && mIsConnected)
-	{
-		fprintf(stderr, "Inconsistent connected state\n");
-		::syslog(LOG_ERR, "Inconsistent connected state");
-		mIsConnected = false;
-	}
-
-	if (mSocketHandle == INVALID_HANDLE_VALUE) 
-	{
-		THROW_EXCEPTION(ServerException, BadSocketHandle)
-	}
-
-	if (mIsServer)
-	{
-		if (!CancelIo(mSocketHandle))
-		{
-			::syslog(LOG_ERR, "Failed to cancel outstanding "
-				"I/O: error %d", GetLastError());
-		}
-
-		if (mReadableEvent == INVALID_HANDLE_VALUE)
-		{
-			::syslog(LOG_ERR, "Failed to destroy Readable "
-				"event: invalid handle");
-		}
-		else if (!CloseHandle(mReadableEvent))
-		{
-			::syslog(LOG_ERR, "Failed to destroy Readable "
-				"event: error %d", GetLastError());
-		}
-
-		mReadableEvent = INVALID_HANDLE_VALUE;
-
-		if (!FlushFileBuffers(mSocketHandle))
-		{
-			::syslog(LOG_INFO, "FlushFileBuffers failed: %d", 
-				GetLastError());
-		}
-	
-		if (!DisconnectNamedPipe(mSocketHandle))
-		{
-			::syslog(LOG_ERR, "DisconnectNamedPipe failed: %d", 
-				GetLastError());
-		}
-
-		mIsServer = false;
-	}
-
-	bool result = CloseHandle(mSocketHandle);
-
-	mSocketHandle = INVALID_HANDLE_VALUE;
-	mIsConnected = false;
-	mReadClosed  = true;
-	mWriteClosed = true;
-
-	if (!result) 
-	{
-		::syslog(LOG_ERR, "CloseHandle failed: %d", GetLastError());
-		THROW_EXCEPTION(ServerException, SocketCloseError)
-	}
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::StreamDataLeft()
-//		Purpose: Still capable of reading data?
-//		Created: 2003/08/02
-//
-// --------------------------------------------------------------------------
-bool WinNamedPipeStream::StreamDataLeft()
-{
-	return !mReadClosed;
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    WinNamedPipeStream::StreamClosed()
-//		Purpose: Connection been closed?
-//		Created: 2003/08/02
-//
-// --------------------------------------------------------------------------
-bool WinNamedPipeStream::StreamClosed()
-{
-	return mWriteClosed;
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-//		Name:    IOStream::WriteAllBuffered()
-//		Purpose: Ensures that any data which has been buffered is written to the stream
-//		Created: 2003/08/26
-//
-// --------------------------------------------------------------------------
-void WinNamedPipeStream::WriteAllBuffered()
-{
-	if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) 
-	{
-		THROW_EXCEPTION(ServerException, BadSocketHandle)
-	}
-	
-	if (!FlushFileBuffers(mSocketHandle))
-	{
-		::syslog(LOG_WARNING, "FlushFileBuffers failed: %d", 
-			GetLastError());
-	}
-}
-
-
-#endif // WIN32

Deleted: box/chris/general/lib/win32/WinNamedPipeStream.h
===================================================================
--- box/chris/general/lib/win32/WinNamedPipeStream.h	2006-07-06 20:47:21 UTC (rev 630)
+++ box/chris/general/lib/win32/WinNamedPipeStream.h	2006-07-06 20:48:26 UTC (rev 631)
@@ -1,66 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-//		Name:    WinNamedPipeStream.h
-//		Purpose: I/O stream interface for Win32 named pipes
-//		Created: 2005/12/07
-//
-// --------------------------------------------------------------------------
-
-#if ! defined WINNAMEDPIPESTREAM__H && defined WIN32
-#define WINNAMEDPIPESTREAM__H
-
-#include "IOStream.h"
-
-// --------------------------------------------------------------------------
-//
-// Class
-//		Name:    WinNamedPipeStream
-//		Purpose: I/O stream interface for Win32 named pipes
-//		Created: 2003/07/31
-//
-// --------------------------------------------------------------------------
-class WinNamedPipeStream : public IOStream
-{
-public:
-	WinNamedPipeStream();
-	~WinNamedPipeStream();
-
-	// server side - create the named pipe and listen for connections
-	void Accept(const wchar_t* Name);
-
-	// client side - connect to a waiting server
-	void Connect(const wchar_t* Name);
-
-	// both sides
-	virtual int Read(void *pBuffer, int NBytes, 
-		int Timeout = IOStream::TimeOutInfinite);
-	virtual void Write(const void *pBuffer, int NBytes);
-	virtual void WriteAllBuffered();
-	virtual void Close();
-	virtual bool StreamDataLeft();
-	virtual bool StreamClosed();
-	bool IsConnected() { return mIsConnected; }
-	HANDLE GetSocketHandle() { return mSocketHandle; }
-	HANDLE GetReadableEvent() { return mReadableEvent; }
-
-protected:
-	void MarkAsReadClosed()  {mReadClosed  = true;}
-	void MarkAsWriteClosed() {mWriteClosed = true;}
-
-private:
-	WinNamedPipeStream(const WinNamedPipeStream &rToCopy) 
-		{ /* do not call */ }
-
-	HANDLE mSocketHandle;
-	HANDLE mReadableEvent;
-	OVERLAPPED mReadOverlap;
-	uint8_t mReadBuffer[4096];
-	size_t  mBytesInBuffer;
-	bool mReadClosed;
-	bool mWriteClosed;
-	bool mIsServer;
-	bool mIsConnected;
-};
-
-#endif // WINNAMEDPIPESTREAM__H


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:49:50 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:49:50 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r632 - in box/chris/general: . infrastructure
Message-ID: <20060706204950.583DA96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:49:49 +0000 (Thu, 06 Jul 2006)
New Revision: 632

Modified:
   box/chris/general/infrastructure/makebuildenv.pl
   box/chris/general/modules.txt
Log:
* modules.txt
* infrastructure/makebuildenv.pl
- Handle multiple implicit dependencies, needed for correct linking order
  of lib/win32 and lib/common (which depends on lib/win32) when building
  unit tests on Win32


Modified: box/chris/general/infrastructure/makebuildenv.pl
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl	2006-07-06 20:48:26 UTC (rev 631)
+++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-06 20:49:49 UTC (rev 632)
@@ -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;
@@ -39,10 +38,14 @@
 my %env_flags;
 
 my $windows_include_path = "-I../../lib/win32 ";
-if (not $target_windows)
+if ($target_windows)
 {
+	push @implicit_deps, "lib/win32";
+}
+else
+{
 	$windows_include_path = "";
-	$env_flags{'IGNORE_lib/win32'} = 1;
+	# $env_flags{'IGNORE_lib/win32'} = 1;
 }
 
 # print "Flag: $_\n" for(keys %env_flags);
@@ -270,7 +273,7 @@
 			push @md,$_ unless ignore_module($_)
 		}
 	}
-	$module_dependency{$mod} = [$implicit_dep,@md];
+	$module_dependency{$mod} = [@implicit_deps,@md];
 	$module_library_link_opts{$mod} = [@lo];
 	
 	# make directories, but not if we're using an external library and this a library module
@@ -285,8 +288,11 @@
 }
 
 # 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";
@@ -295,7 +301,7 @@
 #ifndef _CONFIGURED_MODULES__H
 #define _CONFIGURED_MODULES__H
 __E
-for($implicit_dep,@modules)
+for(@implicit_deps,@modules)
 {
 	my $m = $_;
 	$m =~ s~/~_~;
@@ -309,7 +315,7 @@
 
 # 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;
@@ -346,7 +352,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)
@@ -375,7 +381,7 @@
 my %module_resources_win32;
 
 # Then write a makefile for each module
-for my $mod (@modules, $implicit_dep)
+for my $mod (@modules, @implicit_deps)
 {
 	print $mod,"\n";
 	

Modified: box/chris/general/modules.txt
===================================================================
--- box/chris/general/modules.txt	2006-07-06 20:48:26 UTC (rev 631)
+++ box/chris/general/modules.txt	2006-07-06 20:49:49 UTC (rev 632)
@@ -9,16 +9,15 @@
 
 # Generic support code and modules
 
-lib/raidfile		lib/win32
+lib/raidfile
 lib/crypto
 lib/server
-lib/win32		lib/server
 lib/compress
-test/common		lib/win32
-test/crypto		lib/crypto	lib/win32
-test/compress		lib/compress	lib/win32
-test/raidfile		lib/raidfile	lib/win32
-test/basicserver	lib/server	lib/win32
+test/common
+test/crypto		lib/crypto
+test/compress		lib/compress
+test/raidfile		lib/raidfile
+test/basicserver	lib/server
 
 # IF_DISTRIBUTION(boxbackup)
 
@@ -27,17 +26,17 @@
 lib/backupclient	lib/server	lib/crypto	lib/compress
 lib/backupstore		lib/server	lib/raidfile	lib/backupclient
 
-bin/bbackupobjdump	lib/backupclient lib/backupstore	lib/win32
-bin/bbstored		lib/raidfile	lib/server	lib/backupstore	lib/backupclient	lib/win32
-bin/bbstoreaccounts	lib/raidfile	lib/backupstore	lib/win32
-bin/bbackupd		lib/server	lib/backupclient	lib/win32
-bin/bbackupquery	lib/server	lib/backupclient	lib/win32
-bin/bbackupctl		lib/server	lib/backupclient	lib/win32
+bin/bbackupobjdump	lib/backupclient lib/backupstore
+bin/bbstored		lib/raidfile	lib/server	lib/backupstore	lib/backupclient
+bin/bbstoreaccounts	lib/raidfile	lib/backupstore
+bin/bbackupd		lib/server	lib/backupclient
+bin/bbackupquery	lib/server	lib/backupclient
+bin/bbackupctl		lib/server	lib/backupclient
 
 test/backupstore	bin/bbstored	bin/bbstoreaccounts lib/server lib/backupstore lib/backupclient lib/raidfile
 test/backupstorefix	bin/bbstored	bin/bbstoreaccounts	lib/backupstore	lib/raidfile	bin/bbackupquery	bin/bbackupd
 test/backupstorepatch	bin/bbstored	bin/bbstoreaccounts	lib/backupstore	lib/raidfile
-test/backupdiff		lib/backupclient	lib/win32
+test/backupdiff		lib/backupclient
 test/bbackupd		bin/bbackupd	bin/bbstored bin/bbstoreaccounts bin/bbackupquery bin/bbackupctl lib/server lib/backupstore lib/backupclient
 
 # END_IF_DISTRIBUTION


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:51:17 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:51:17 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r633 - in box/chris/general/lib: common win32
Message-ID: <20060706205117.3328396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:51:13 +0000 (Thu, 06 Jul 2006)
New Revision: 633

Added:
   box/chris/general/lib/common/BoxConfig-MSVC.h
Removed:
   box/chris/general/lib/win32/config.h.win32
Log:
* lib/win32/config.h.win32
- Renamed to lib/common/BoxConfig-MSVC.h, so that it can be included
  automatically by MSVC without needing to copy files around by hand


Copied: box/chris/general/lib/common/BoxConfig-MSVC.h (from rev 622, box/chris/general/lib/win32/config.h.win32)

Deleted: box/chris/general/lib/win32/config.h.win32
===================================================================
--- box/chris/general/lib/win32/config.h.win32	2006-07-06 20:49:49 UTC (rev 632)
+++ box/chris/general/lib/win32/config.h.win32	2006-07-06 20:51:13 UTC (rev 633)
@@ -1,396 +0,0 @@
-/* lib/common/BoxConfig.h.  Generated by configure.  */
-/* lib/common/BoxConfig.h.in.  Generated from configure.ac by autoheader.  */
-/* Hacked by hand to work for MSVC by Chris Wilson */
-
-/* Define to major version for BDB_VERSION */
-/* #undef BDB_VERSION_MAJOR */
-
-/* Define to minor version for BDB_VERSION */
-/* #undef BDB_VERSION_MINOR */
-
-/* Define to point version for BDB_VERSION */
-/* #undef BDB_VERSION_POINT */
-
-/* Name of the 64 bit endian swapping function */
-/* #undef BSWAP64 */
-
-/* Define to 1 if the `closedir' function returns void instead of `int'. */
-#define CLOSEDIR_VOID 1
-
-/* Define to 1 if non-aligned int16 access will fail */
-/* #undef HAVE_ALIGNED_ONLY_INT16 */
-
-/* Define to 1 if non-aligned int32 access will fail */
-/* #undef HAVE_ALIGNED_ONLY_INT32 */
-
-/* Define to 1 if non-aligned int64 access will fail */
-/* #undef HAVE_ALIGNED_ONLY_INT64 */
-
-/* Define to 1 if you have the <asm/byteorder.h> header file. */
-/* #undef HAVE_ASM_BYTEORDER_H */
-
-/* Define to 1 if BSWAP64 is defined to the name of a valid 64 bit endian
-   swapping function */
-/* #undef HAVE_BSWAP64 */
-
-/* Define to 1 if you have the <db.h> header file. */
-/* #undef HAVE_DB_H */
-
-/* Define to 1 if you have the declaration of `F_SETLK', and to 0 if you
-   don't. */
-#define HAVE_DECL_F_SETLK 0
-
-/* Define to 1 if you have the declaration of `INFTIM', and to 0 if you don't.
-   */
-#define HAVE_DECL_INFTIM 0
-
-/* Define to 1 if you have the declaration of `O_EXLOCK', and to 0 if you
-   don't. */
-#define HAVE_DECL_O_EXLOCK 0
-
-/* Define to 1 if you have the declaration of `SO_PEERCRED', and to 0 if you
-   don't. */
-#define HAVE_DECL_SO_PEERCRED 0
-
-/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if
-   you don't. */
-#define HAVE_DECL_XATTR_NOFOLLOW 0
-
-/* Define to 1 if #define of pragmas works */
-/* #undef HAVE_DEFINE_PRAGMA */
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_DIRENT_H */
-
-/* Define to 1 if you have the <editline/readline.h> header file. */
-/* #undef HAVE_EDITLINE_READLINE_H */
-
-/* define if the compiler supports exceptions */
-#define HAVE_EXCEPTIONS 
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-/* #undef HAVE_EXECINFO_H */
-
-/* Define to 1 if you have the `flock' function. */
-/* #undef HAVE_FLOCK */
-
-/* Define to 1 if you have the `getmntent' function. */
-/* #undef HAVE_GETMNTENT */
-
-/* Define to 1 if you have the `getpeereid' function. */
-/* #undef HAVE_GETPEEREID */
-
-/* Define to 1 if you have the `getpid' function. */
-#define HAVE_GETPID 1
-
-/* Define to 1 if you have the `getxattr' function. */
-/* #undef HAVE_GETXATTR */
-
-/* Define to 1 if you have the <history.h> header file. */
-/* #undef HAVE_HISTORY_H */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-// #define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `kqueue' function. */
-/* #undef HAVE_KQUEUE */
-
-/* Define to 1 if you have the `lchown' function. */
-/* #undef HAVE_LCHOWN */
-
-/* Define to 1 if you have the `lgetxattr' function. */
-/* #undef HAVE_LGETXATTR */
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-#define HAVE_LIBCRYPTO 1
-
-/* Define if you have a readline compatible library */
-/* #undef HAVE_LIBREADLINE */
-
-/* Define to 1 if you have the `ssl' library (-lssl). */
-#define HAVE_LIBSSL 1
-
-/* Define to 1 if you have the `z' library (-lz). */
-#define HAVE_LIBZ 1
-
-/* Define to 1 if you have the `listxattr' function. */
-/* #undef HAVE_LISTXATTR */
-
-/* Define to 1 if you have the `llistxattr' function. */
-/* #undef HAVE_LLISTXATTR */
-
-/* Define to 1 if syscall lseek requires a dummy middle parameter */
-/* #undef HAVE_LSEEK_DUMMY_PARAM */
-
-/* Define to 1 if you have the `lsetxattr' function. */
-/* #undef HAVE_LSETXATTR */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <mntent.h> header file. */
-/* #undef HAVE_MNTENT_H */
-
-/* Define to 1 if this platform supports mounts */
-/* #undef HAVE_MOUNTS */
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-/* #undef HAVE_NETINET_IN_H */
-
-/* Define to 1 if SSL is pre-0.9.7 */
-/* #undef HAVE_OLD_SSL */
-
-/* Define to 1 if you have the <openssl/ssl.h> header file. */
-#define HAVE_OPENSSL_SSL_H 1
-
-/* Define to 1 if you have the <process.h> header file. */
-#define HAVE_PROCESS_H 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-/* #undef HAVE_PWD_H */
-
-/* Define to 1 (and set RANDOM_DEVICE) if a random device is available */
-/* #undef HAVE_RANDOM_DEVICE */
-
-/* Define to 1 if you have the <readline.h> header file. */
-/* #undef HAVE_READLINE_H */
-
-/* Define if your readline library has add_history */
-/* #undef HAVE_READLINE_HISTORY */
-
-/* Define to 1 if you have the <readline/history.h> header file. */
-/* #undef HAVE_READLINE_HISTORY_H */
-
-/* Define to 1 if you have the <readline/readline.h> header file. */
-/* #undef HAVE_READLINE_READLINE_H */
-
-/* Define to 1 if you have the <regex.h> header file. */
-// #define HAVE_REGEX_H 1
-
-/* Define to 1 if you have the `setproctitle' function. */
-/* #undef HAVE_SETPROCTITLE */
-
-/* Define to 1 if you have the `setxattr' function. */
-/* #undef HAVE_SETXATTR */
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if SSL is available */
-#define HAVE_SSL 1
-
-/* Define to 1 if you have the `statfs' function. */
-/* #undef HAVE_STATFS */
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
-   zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if stdbool.h conforms to C99. */
-#define HAVE_STDBOOL_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-// #define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if `d_type' is member of `struct dirent'. */
-/* #undef HAVE_STRUCT_DIRENT_D_TYPE */
-
-/* Define to 1 if `mnt_dir' is member of `struct mntent'. */
-/* #undef HAVE_STRUCT_MNTENT_MNT_DIR */
-
-/* Define to 1 if `mnt_mountp' is member of `struct mnttab'. */
-/* #undef HAVE_STRUCT_MNTTAB_MNT_MOUNTP */
-
-/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
-/* #undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
-
-/* Define to 1 if `f_mntonname' is member of `struct statfs'. */
-/* #undef HAVE_STRUCT_STATFS_F_MNTONNAME */
-
-/* Define to 1 if `st_flags' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_FLAGS */
-
-/* Define to 1 if `st_mtimespec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC */
-
-/* Define to 1 if you have the `syscall' function. */
-/* #undef HAVE_SYSCALL */
-
-/* Define to 1 if you have the <syslog.h> header file. */
-/* #undef HAVE_SYSLOG_H */
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define to 1 if you have the <sys/endian.h> header file. */
-/* #undef HAVE_SYS_ENDIAN_H */
-
-/* Define to 1 if you have the <sys/mnttab.h> header file. */
-/* #undef HAVE_SYS_MNTTAB_H */
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-/* #undef HAVE_SYS_MOUNT_H */
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
-   */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-// #define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-/* #undef HAVE_SYS_SOCKET_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-/* #undef HAVE_SYS_SYSCALL_H */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-// #define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-/* #undef HAVE_SYS_WAIT_H */
-
-/* Define to 1 if you have the <sys/xattr.h> header file. */
-/* #undef HAVE_SYS_XATTR_H */
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if the system has the type `uint16_t'. */
-#define HAVE_UINT16_T 1
-
-/* Define to 1 if the system has the type `uint32_t'. */
-#define HAVE_UINT32_T 1
-
-/* Define to 1 if the system has the type `uint64_t'. */
-#define HAVE_UINT64_T 1
-
-/* Define to 1 if the system has the type `uint8_t'. */
-#define HAVE_UINT8_T 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-// #define HAVE_UNISTD_H 1
-
-/* Define to 1 if the system has the type `u_int16_t'. */
-/* #undef HAVE_U_INT16_T */
-
-/* Define to 1 if the system has the type `u_int32_t'. */
-/* #undef HAVE_U_INT32_T */
-
-/* Define to 1 if the system has the type `u_int64_t'. */
-/* #undef HAVE_U_INT64_T */
-
-/* Define to 1 if the system has the type `u_int8_t'. */
-/* #undef HAVE_U_INT8_T */
-
-/* Define to 1 if struct dirent.d_type is valid */
-/* #undef HAVE_VALID_DIRENT_D_TYPE */
-
-/* Define to 1 if the system has the type `_Bool'. */
-/* #undef HAVE__BOOL */
-
-/* Define to 1 if you have the `__syscall' function. */
-/* #undef HAVE___SYSCALL */
-
-/* Define to 1 if __syscall is available but needs a definition */
-/* #undef HAVE___SYSCALL_NEED_DEFN */
-
-/* max value of long long calculated by configure */
-/* #undef LLONG_MAX */
-
-/* min value of long long calculated by configure */
-/* #undef LLONG_MIN */
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
-   slash. */
-/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "box@fluffy.co.uk"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "Box Backup"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "Box Backup 0.09"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "box-backup"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.09"
-
-/* Define to the filename of the random device (and set HAVE_RANDOM_DEVICE) */
-/* #undef RANDOM_DEVICE */
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#define RETSIGTYPE void
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* TMP directory name */
-#define TEMP_DIRECTORY_NAME "/tmp"
-
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#define TIME_WITH_SYS_TIME 1
-
-/* Define to 1 if your <sys/time.h> declares `struct tm'. */
-/* #undef TM_IN_SYS_TIME */
-
-/* Define to 1 if your processor stores words with the most significant byte
-   first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define to 1 if __USE_MALLOC is required work around STL memory leaks */
-/* #undef __USE_MALLOC */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#define gid_t int
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef mode_t */
-
-/* Define to `long' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#define uid_t int


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:53:59 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:53:59 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r634 - box/chris/general/lib/win32
Message-ID: <20060706205359.AA66D96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:53:57 +0000 (Thu, 06 Jul 2006)
New Revision: 634

Modified:
   box/chris/general/lib/win32/emu.h
Log:
* emu.h
- Removed {get,set}*uid stubs which paper over the cracks on Win32. The
  code which uses these functions should be fixed to work on Win32 instead.
- Removed hard-coded version for MSVC, should use BoxVersion.h instead


Modified: box/chris/general/lib/win32/emu.h
===================================================================
--- box/chris/general/lib/win32/emu.h	2006-07-06 20:51:13 UTC (rev 633)
+++ box/chris/general/lib/win32/emu.h	2006-07-06 20:53:57 UTC (rev 634)
@@ -151,33 +151,6 @@
 	}
 #endif
 
-//I do not perceive a need to change the user or group on a backup client
-//at any rate the owner of a service can be set in the service settings
-inline int setegid(int)
-{
-	return true;
-}
-inline int seteuid(int)
-{
-	return true;
-}
-inline int setgid(int)
-{
-	return true;
-}
-inline int setuid(int)
-{
-	return true;
-}
-inline int getgid(void)
-{
-	return 0;
-}
-inline int getuid(void)
-{
-	return 0;
-}
-
 #ifndef PATH_MAX
 #define PATH_MAX MAX_PATH
 #endif
@@ -214,11 +187,6 @@
 	typedef int socklen_t;
 #endif
 
-// I (re-)defined here for the moment; has to be removed later !!! 
-#ifndef BOX_VERSION
-#define BOX_VERSION "0.10_msvc"
-#endif
-
 #define S_IRGRP S_IWRITE
 #define S_IWGRP S_IREAD
 #define S_IROTH S_IWRITE | S_IREAD


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:54:58 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:54:58 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r635 - box/chris/general/lib/backupclient
Message-ID: <20060706205458.C99B096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:54:58 +0000 (Thu, 06 Jul 2006)
New Revision: 635

Modified:
   box/chris/general/lib/backupclient/BackupClientRestore.cpp
Log:
* BackupClientRestore.cpp
- Handle forward slashes in directory names on Win32


Modified: box/chris/general/lib/backupclient/BackupClientRestore.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupClientRestore.cpp	2006-07-06 20:53:57 UTC (rev 634)
+++ box/chris/general/lib/backupclient/BackupClientRestore.cpp	2006-07-06 20:54:58 UTC (rev 635)
@@ -257,6 +257,14 @@
 	}
 
 	int lastSlash = parentDirectoryName.rfind(DIRECTORY_SEPARATOR_ASCHAR);
+
+	if(lastSlash == std::string::npos)
+	{
+		// might be a forward slash separator, 
+		// especially in the unit tests!
+		lastSlash = parentDirectoryName.rfind('/');
+	}
+
 	if(lastSlash != std::string::npos)
 	{
 		// the target directory is a deep path, remove the last


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:55:44 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:55:44 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r636 - box/chris/general/lib/common
Message-ID: <20060706205544.9A50D96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:55:40 +0000 (Thu, 06 Jul 2006)
New Revision: 636

Modified:
   box/chris/general/lib/common/BoxPlatform.h
Log:
* BoxPlatform.h
- Include the MSVC-specific config file and auto-generated version header
  automagically on Win32


Modified: box/chris/general/lib/common/BoxPlatform.h
===================================================================
--- box/chris/general/lib/common/BoxPlatform.h	2006-07-06 20:54:58 UTC (rev 635)
+++ box/chris/general/lib/common/BoxPlatform.h	2006-07-06 20:55:40 UTC (rev 636)
@@ -21,7 +21,12 @@
 
 #define PLATFORM_DEV_NULL			"/dev/null"
 
+#ifdef _MSC_VER
+#include "BoxConfig-MSVC.h"
+#include "BoxVersion.h"
+#else
 #include "BoxConfig.h"
+#endif
 
 #ifdef WIN32
 	// need msvcrt version 6.1 or higher for _gmtime64()


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:56:07 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:56:07 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r637 - box/chris/general/lib/common
Message-ID: <20060706205607.D159C96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:56:05 +0000 (Thu, 06 Jul 2006)
New Revision: 637

Modified:
   box/chris/general/lib/common/UnixUser.cpp
Log:
* UnixUser.cpp
- Disable user changing code on Win32


Modified: box/chris/general/lib/common/UnixUser.cpp
===================================================================
--- box/chris/general/lib/common/UnixUser.cpp	2006-07-06 20:55:40 UTC (rev 636)
+++ box/chris/general/lib/common/UnixUser.cpp	2006-07-06 20:56:05 UTC (rev 637)
@@ -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
 }
 
 


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:56:38 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:56:38 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r638 - box/chris/general/bin/bbackupctl
Message-ID: <20060706205638.7BB6996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:56:37 +0000 (Thu, 06 Jul 2006)
New Revision: 638

Modified:
   box/chris/general/bin/bbackupctl/bbackupctl.cpp
Log:
* bbackupctl.cpp
- Added a new command to wait for end of next sync, useful for unit tests


Modified: box/chris/general/bin/bbackupctl/bbackupctl.cpp
===================================================================
--- box/chris/general/bin/bbackupctl/bbackupctl.cpp	2006-07-06 20:56:05 UTC (rev 637)
+++ box/chris/general/bin/bbackupctl/bbackupctl.cpp	2006-07-06 20:56:37 UTC (rev 638)
@@ -32,12 +32,13 @@
 {
 	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);
@@ -224,7 +225,8 @@
 	bool areWaitingForSync = false;
 	bool areWaitingForSyncEnd = false;
 
-	if(::strcmp(argv[0], "wait-for-sync") == 0)
+	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
@@ -236,8 +238,15 @@
 		}
 	
 		// Yes... set the flag so we know that 
-		// we're waiting for a sync to start
-		areWaitingForSync = true;
+		// 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)
 	{


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:57:14 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:57:14 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r639 - box/chris/general/bin/bbackupd
Message-ID: <20060706205714.87E0396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:57:11 +0000 (Thu, 06 Jul 2006)
New Revision: 639

Modified:
   box/chris/general/bin/bbackupd/BackupDaemon.cpp
Log:
* BackupDaemon.cpp
- Fixed spelink eeror


Modified: box/chris/general/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-06 20:56:37 UTC (rev 638)
+++ box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-06 20:57:11 UTC (rev 639)
@@ -1048,7 +1048,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?


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 21:59:54 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu,  6 Jul 2006 20:59:54 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r640 - box/chris/general/bin/bbackupquery
Message-ID: <20060706205954.E2B7296@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-06 20:59:52 +0000 (Thu, 06 Jul 2006)
New Revision: 640

Modified:
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
   box/chris/general/bin/bbackupquery/BackupQueries.h
   box/chris/general/bin/bbackupquery/documentation.txt
Log:
* BackupQueries.cpp, BackupQueries.h, documentation.txt
- Changed to use a structure to hold command names and options, to make
  the code more maintainable
- Added a 'compare -A' option to compare normally but without attributes. 
  On Windows, restoring the attributes is impossible (except in Vista) 
  due to lack of utimes() equivalent function, as far as I can tell.


Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-06 20:57:11 UTC (rev 639)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-06 20:59:52 UTC (rev 640)
@@ -84,6 +84,12 @@
 {
 }
 
+typedef struct cmd_info
+{
+	const char* name;
+	const char* opts;
+} cmd_info_t;
+
 // --------------------------------------------------------------------------
 //
 // Function
@@ -161,8 +167,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[] = {"",	 "",	 "rodIFtTsh", "",	   "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
@@ -182,11 +204,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;
@@ -221,9 +243,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;
@@ -990,6 +1013,7 @@
 BackupQueries::CompareParams::CompareParams()
 	: mQuickCompare(false),
 	  mIgnoreExcludes(false),
+	  mIgnoreAttributes(false),
 	  mDifferences(0),
 	  mDifferencesExplainedByModTime(0),
 	  mExcludedDirs(0),
@@ -1052,6 +1076,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
 	{
@@ -1484,11 +1509,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 */))
 						{

Modified: box/chris/general/bin/bbackupquery/BackupQueries.h
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.h	2006-07-06 20:57:11 UTC (rev 639)
+++ box/chris/general/bin/bbackupquery/BackupQueries.h	2006-07-06 20:59:52 UTC (rev 640)
@@ -68,6 +68,7 @@
 		void DeleteExcludeLists();
 		bool mQuickCompare;
 		bool mIgnoreExcludes;
+		bool mIgnoreAttributes;
 		int mDifferences;
 		int mDifferencesExplainedByModTime;
 		int mExcludedDirs;

Modified: box/chris/general/bin/bbackupquery/documentation.txt
===================================================================
--- box/chris/general/bin/bbackupquery/documentation.txt	2006-07-06 20:57:11 UTC (rev 639)
+++ box/chris/general/bin/bbackupquery/documentation.txt	2006-07-06 20:59:52 UTC (rev 640)
@@ -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.


From boxbackup-dev@fluffy.co.uk  Thu Jul  6 22:05:32 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Thu, 6 Jul 2006 22:05:32 +0100 (BST)
Subject: [Box Backup-dev] Win32 client
In-Reply-To: <BFC49E8E-F83C-4776-A900-1E5812E80C82@fluffy.co.uk>
References: <bab9f1d50606210133i44ddef39xb1ec6fb819d1ac53@mail.gmail.com>
 <Pine.LNX.4.62.0606290108470.15993@top.qwarx.com>
 <EA946EE6-7CF5-4AEA-AF2F-98068BDF57C9@fluffy.co.uk>
 <Pine.LNX.4.62.0607032259420.15993@top.qwarx.com>
 <BFC49E8E-F83C-4776-A900-1E5812E80C82@fluffy.co.uk>
Message-ID: <Pine.LNX.4.62.0607062204550.23974@top.qwarx.com>

Hi Ben,

On Tue, 4 Jul 2006, Ben Summers wrote:

> You really can't run a script as part of your build process to fish out 
> the revision number?

I think I figured out how to do it. Patch applied to my tree.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Mon Jul 10 21:47:24 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Mon, 10 Jul 2006 20:47:24 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r641 - box/chris/general/infrastructure
Message-ID: <20060710204724.4F83196@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-10 20:47:16 +0000 (Mon, 10 Jul 2006)
New Revision: 641

Modified:
   box/chris/general/infrastructure/makebuildenv.pl
Log:
* makebuildenv.pl
- Added lib/common to include paths on Win32 to fix new build error
- Made the windows include path logic more logical


Modified: box/chris/general/infrastructure/makebuildenv.pl
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl	2006-07-06 20:59:52 UTC (rev 640)
+++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-10 20:47:16 UTC (rev 641)
@@ -37,14 +37,14 @@
 # flags about the environment
 my %env_flags;
 
-my $windows_include_path = "-I../../lib/win32 ";
+my $windows_include_path = "";
 if ($target_windows)
 {
+	$windows_include_path = "-I../../lib/win32 -I../../lib/common ";
 	push @implicit_deps, "lib/win32";
 }
 else
 {
-	$windows_include_path = "";
 	# $env_flags{'IGNORE_lib/win32'} = 1;
 }
 


From boxbackup-dev@fluffy.co.uk  Mon Jul 10 21:49:03 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Mon, 10 Jul 2006 20:49:03 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r642 - box/chris/general/lib/win32
Message-ID: <20060710204903.9EBE996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-10 20:49:02 +0000 (Mon, 10 Jul 2006)
New Revision: 642

Modified:
   box/chris/general/lib/win32/emu.cpp
Log:
* emu.cpp
- Changed the requested permissions in openfile() to better match 
  expectations
- Fixed signed/unsigned warnings
- Replaced ASSERT() with assert() to avoid circular dependencies between
  lib/win32 and lib/common


Modified: box/chris/general/lib/win32/emu.cpp
===================================================================
--- box/chris/general/lib/win32/emu.cpp	2006-07-10 20:47:16 UTC (rev 641)
+++ box/chris/general/lib/win32/emu.cpp	2006-07-10 20:49:02 UTC (rev 642)
@@ -7,8 +7,9 @@
 
 #ifdef WIN32
 
+#include <assert.h>
+#include <fcntl.h>
 #include <windows.h>
-#include <fcntl.h>
 
 #ifdef HAVE_UNISTD_H
 	#include <unistd.h>
@@ -517,19 +518,19 @@
 
 	if (flags & O_WRONLY)
 	{
+		accessRights = FILE_WRITE_ATTRIBUTES 
+			| FILE_WRITE_DATA | FILE_WRITE_EA;
 		shareMode = FILE_SHARE_WRITE;
 	}
-	if (flags & O_RDWR)
+	if (flags & (O_RDWR | O_CREAT))
 	{
-		shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+		accessRights |= FILE_WRITE_ATTRIBUTES 
+			| FILE_WRITE_DATA | FILE_WRITE_EA;
+		shareMode |= FILE_SHARE_WRITE;
 	}
 	if (flags & O_CREAT)
 	{
 		createDisposition = OPEN_ALWAYS;
-		shareMode |= FILE_SHARE_WRITE;
-		accessRights |= FILE_WRITE_ATTRIBUTES 
-			| FILE_WRITE_DATA | FILE_WRITE_EA 
-			/*| FILE_ALL_ACCESS */;
 	}
 	if (flags & O_TRUNC)
 	{
@@ -984,7 +985,7 @@
 		timOut.tv_sec  = timeout / 1000;
 		timOut.tv_usec = timeout * 1000;
 
-		for (int i = 0; i < nfds; i++)
+		for (unsigned long i = 0; i < nfds; i++)
 		{
 			struct pollfd* ufd = &(ufds[i]);
 
@@ -1022,7 +1023,7 @@
 		}
 		else if (nready > 0)
 		{
-			for (int i = 0; i < nfds; i++)
+			for (unsigned long i = 0; i < nfds; i++)
 			{
 				struct pollfd *ufd = &(ufds[i]);
 
@@ -1228,7 +1229,7 @@
 	va_start(args, frmt);
 
 	int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args);
-	ASSERT(len < sizeof(buffer))
+	assert(len < sizeof(buffer));
 	buffer[sizeof(buffer)-1] = 0;
 
 	va_end(args);
@@ -1465,7 +1466,7 @@
 {
 	int bytes = 0;
 	
-	for (int i = 0; i < count; i++)
+	for (size_t i = 0; i < count; i++)
 	{
 		int result = read(filedes, vector[i].iov_base, 
 			vector[i].iov_len);
@@ -1483,7 +1484,7 @@
 {
 	int bytes = 0;
 	
-	for (int i = 0; i < count; i++)
+	for (size_t i = 0; i < count; i++)
 	{
 		int result = write(filedes, vector[i].iov_base, 
 			vector[i].iov_len);


From boxbackup-dev@fluffy.co.uk  Mon Jul 10 21:54:28 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Mon, 10 Jul 2006 20:54:28 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r643 - box/chris/general/lib/server
Message-ID: <20060710205428.9FB6096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-10 20:54:27 +0000 (Mon, 10 Jul 2006)
New Revision: 643

Modified:
   box/chris/general/lib/server/WinNamedPipeStream.cpp
Log:
* WinNamedPipeStream.cpp
- Throw exception if Read() called on a closed stream (edge case?)
- Satisfy reads from buffer if possible to avoid problems with small read
  buffers in debug builds on Win32
- May still have a problem with the readable event being signalled multiple
  times before reset, resulting in lost events and reader thread and
  control client hanging.


Modified: box/chris/general/lib/server/WinNamedPipeStream.cpp
===================================================================
--- box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-10 20:49:02 UTC (rev 642)
+++ box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-10 20:54:27 UTC (rev 643)
@@ -212,36 +212,61 @@
 		THROW_EXCEPTION(ServerException, BadSocketHandle)
 	}
 
+	if (mReadClosed)
+	{
+		THROW_EXCEPTION(ConnectionException, SocketShutdownError)
+	}
+
 	DWORD NumBytesRead;
 
 	if (mIsServer)
 	{
-		// overlapped I/O completed successfully? (wait if needed)
-
-		if (!GetOverlappedResult(mSocketHandle,
-			&mReadOverlap, &NumBytesRead, TRUE))
+		// satisfy from buffer if possible, to avoid
+		// blocking on read.
+		bool needAnotherRead = false;
+		if (mBytesInBuffer == 0)
 		{
-			DWORD err = GetLastError();
+			// overlapped I/O completed successfully? 
+			// (wait if needed)
 
-			if (err == ERROR_HANDLE_EOF)
+			if (GetOverlappedResult(mSocketHandle,
+				&mReadOverlap, &NumBytesRead, TRUE))
 			{
-				mReadClosed = true;
+				needAnotherRead = true;
 			}
-			else if (err == ERROR_BROKEN_PIPE)
-			{
-				::syslog(LOG_ERR, 
-					"Control client disconnected");
-				mReadClosed = true;
-			}
 			else
 			{
-				::syslog(LOG_ERR, "Failed to wait for "
-					"ReadFile to complete: error %d", err);
-				Close();
-				THROW_EXCEPTION(ConnectionException, 
-					Conn_SocketReadError)
+				DWORD err = GetLastError();
+
+				if (err == ERROR_HANDLE_EOF)
+				{
+					mReadClosed = true;
+				}
+				else 
+				{
+					if (err == ERROR_BROKEN_PIPE)
+					{
+						::syslog(LOG_ERR, "Control "
+							"client disconnected");
+					}
+					else
+					{
+						::syslog(LOG_ERR, 
+							"Failed to wait for "
+							"ReadFile to complete: "
+							"error %d", err);
+					}
+
+					Close();
+					THROW_EXCEPTION(ConnectionException, 
+						Conn_SocketReadError)
+				}
 			}
 		}
+		else
+		{
+			NumBytesRead = 0;
+		}
 
 		size_t BytesToCopy = NumBytesRead + mBytesInBuffer;
 		size_t BytesRemaining = 0;
@@ -259,7 +284,7 @@
 		NumBytesRead = BytesToCopy;
 
 		// start the next overlapped read
-		if (!ReadFile(mSocketHandle, 
+		if (needAnotherRead && !ReadFile(mSocketHandle, 
 			mReadBuffer + mBytesInBuffer, 
 			sizeof(mReadBuffer) - mBytesInBuffer,
 			NULL, &mReadOverlap))
@@ -267,12 +292,21 @@
 			DWORD err = GetLastError();
 			if (err == ERROR_IO_PENDING)
 			{
-				ResetEvent(mReadableEvent);
+				// Don't reset yet, there might be data
+				// in the buffer waiting to be read, 
+				// will check below.
+				// ResetEvent(mReadableEvent);
 			}
 			else if (err == ERROR_HANDLE_EOF)
 			{
 				mReadClosed = true;
 			}
+			else if (err == ERROR_BROKEN_PIPE)
+			{
+				::syslog(LOG_ERR, 
+					"Control client disconnected");
+				mReadClosed = true;
+			}
 			else
 			{
 				::syslog(LOG_ERR, "Failed to start "
@@ -286,6 +320,25 @@
 		// If the read succeeded immediately, leave the event 
 		// signaled, so that we will be called again to process 
 		// the newly read data and start another overlapped read.
+		if (needAnotherRead && !mReadClosed)
+		{
+			// leave signalled
+		}
+		else if (!needAnotherRead && mBytesInBuffer > 0)
+		{
+			// leave signalled
+		}
+		else
+		{
+			// nothing left to read, reset the event
+			ResetEvent(mReadableEvent);
+			// FIXME: a pending read could have signalled
+			// the event (again) while we were busy reading.
+			// that signal would be lost, and the reading
+			// thread would block. Should be pretty obvious
+			// if this happens in practice: control client
+			// hangs.
+		}
 	}
 	else
 	{


From boxbackup-dev@fluffy.co.uk  Wed Jul 12 11:55:41 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 12 Jul 2006 11:55:41 +0100
Subject: [Box Backup-dev] Windows branch
Message-ID: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>

I'm a little concerned that the Windows branch is diverging  
significantly, and will require a lot of effort to review and merge.  
I'd like to catch and resolve the problem before it's too late.

Any thoughts?

Ben




From boxbackup-dev@fluffy.co.uk  Wed Jul 12 12:51:13 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Wed, 12 Jul 2006 04:51:13 -0700 (PDT)
Subject: [Box Backup-dev] Windows branch
In-Reply-To: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
Message-ID: <20060712115113.21547.qmail@web36708.mail.mud.yahoo.com>

> I'm a little concerned that the Windows branch is diverging  
> significantly, and will require a lot of effort to review and merge.  
> I'd like to catch and resolve the problem before it's too late.

FYI: I have been running Chris' modified Win32 tree for a month now around the clock, no problems
with backups so far.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Wed Jul 12 13:50:58 2006
From: boxbackup-dev@fluffy.co.uk (Pascal Lalonde)
Date: Wed, 12 Jul 2006 08:50:58 -0400
Subject: [Box Backup-dev] Windows branch
In-Reply-To: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
References: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
Message-ID: <44B4F032.8040103@overnet.qc.ca>

Ben Summers wrote:
> 
> I'm a little concerned that the Windows branch is diverging 
> significantly, and will require a lot of effort to review and merge. I'd 
> like to catch and resolve the problem before it's too late.
 >
 > Any thoughts?
 >

If I may state my opinion, I too find that it would be a good thing to 
have one official tree where you can get a stable version that works for 
either *nix or Win32. It gets a little confusing as to what 
version/revision/branch to use when it comes to win32. I'm in no 
position to tell anyone what to do, but there are still issues with 
basic things like compare and error reporting that are unresolved. Am I 
the only one worried about this? Anyone running scheduled compares 
should notice pretty soon (I run compare -a -q on every host, once a 
week). By the way, don't neglect compares, they might save you.

Pascal

From boxbackup-dev@fluffy.co.uk  Wed Jul 12 20:09:52 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Wed, 12 Jul 2006 20:09:52 +0100 (BST)
Subject: [Box Backup-dev] Windows branch
In-Reply-To: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
References: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
Message-ID: <Pine.LNX.4.62.0607122006490.18881@top.qwarx.com>

Hi Ben,

On Wed, 12 Jul 2006, Ben Summers wrote:

> I'm a little concerned that the Windows branch is diverging 
> significantly, and will require a lot of effort to review and merge. I'd 
> like to catch and resolve the problem before it's too late.

I'm almost done with the Windows branch, I don't think it will change 
significantly from its current state before I'm ready to start merging it.
But if you want to start sooner then I'd be happy for that too.

I agree there are significant changes and that it will take some effort to 
review them and suggest changes until they are OK to merge. I'm happy to 
implement whatever changes are necessary or requested in order to get it 
merged.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Wed Jul 12 20:15:53 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Wed, 12 Jul 2006 20:15:53 +0100 (BST)
Subject: [Box Backup-dev] Windows branch
In-Reply-To: <44B4F032.8040103@overnet.qc.ca>
References: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
 <44B4F032.8040103@overnet.qc.ca>
Message-ID: <Pine.LNX.4.62.0607122010380.18881@top.qwarx.com>

Hi Pascal,

On Wed, 12 Jul 2006, Pascal Lalonde wrote:

> If I may state my opinion, I too find that it would be a good thing to have 
> one official tree where you can get a stable version that works for either 
> *nix or Win32.

I agree, but I had to make some big changes to the Windows code and I 
absolutely did not want to destabilise the main tree in doing so. I am 
intending, and I hope that others are too, that when these changes are 
finished (which will be very soon) we should merge them back into the main 
tree and abandon my tree.

> It gets a little confusing as to what version/revision/branch to use 
> when it comes to win32.

You can follow the instructions on the Wiki. The stable branch has many 
known bugs on Win32, of which almost all are fixed in my branch, to the 
best of my knowledge.

> I'm in no position to tell anyone what to do, but there are still issues 
> with basic things like compare and error reporting that are unresolved.

In my branch, the major unresolved issues are locked files and large 
files. I'm working on it. The other issues are less major ones, documented 
on the Known Bugs page.

If you are aware of any issues that are not listed on the Known Bugs page 
[http://boxbackup.hostworks.ca/index.php/Known_bugs_in_the_Win32_client], 
then PLEASE tell me about them now.

> Am I the only one worried about this?

Definitely not. Compares are very important, in fact I would say they are 
an essential part of any backup strategy.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Wed Jul 12 21:20:06 2006
From: boxbackup-dev@fluffy.co.uk (Charles Lecklider)
Date: Wed, 12 Jul 2006 21:20:06 +0100
Subject: [Box Backup-dev] Windows branch
In-Reply-To: <Pine.LNX.4.62.0607122010380.18881@top.qwarx.com>
References: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk> <44B4F032.8040103@overnet.qc.ca> <Pine.LNX.4.62.0607122010380.18881@top.qwarx.com>
Message-ID: <44B55976.3030706@invis.net>

Chris Wilson wrote:
> If you are aware of any issues that are not listed on the Known Bugs 
> page 
> [http://boxbackup.hostworks.ca/index.php/Known_bugs_in_the_Win32_client],
>  then PLEASE tell me about them now.

>From that page:

> Restored Files Attributes Incorrect
> 
> Pete Jalajas reports that the date stamps of restored files are the
> current time, not the datestamp of the original file (or of the time
> when the file was backed up). Nor are Access Control Lists or Windows
> file attributes restored.
> 
> * It seems that there's no API to set the date stamps on files until
> Windows Vista. Since I don't have a copy of Vista, I can't test this.


Is that still the current position?

I'm just wondering what's wrong with SetFileAttributes
(http://msdn.microsoft.com/library/en-us/fileio/fs/setfileattributes.asp)
and SetFileTime
(http://msdn.microsoft.com/library/en-us/sysinfo/base/setfiletime.asp).

Am I missing something obvious or subtle?

-C


From boxbackup-dev@fluffy.co.uk  Thu Jul 13 01:39:04 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Thu, 13 Jul 2006 01:39:04 +0100 (BST)
Subject: [Box Backup-dev] Windows branch
In-Reply-To: <44B55976.3030706@invis.net>
References: <DFE6B52E-923C-4910-9168-6FF40A79D803@fluffy.co.uk>
 <44B4F032.8040103@overnet.qc.ca> <Pine.LNX.4.62.0607122010380.18881@top.qwarx.com>
 <44B55976.3030706@invis.net>
Message-ID: <Pine.LNX.4.62.0607130137150.18881@top.qwarx.com>

Hi Charles,

On Wed, 12 Jul 2006, Charles Lecklider wrote:

>> Restored Files Attributes Incorrect
>>
>> Pete Jalajas reports that the date stamps of restored files are the
>> current time, not the datestamp of the original file (or of the time
>> when the file was backed up). Nor are Access Control Lists or Windows
>> file attributes restored.
>>
>> * It seems that there's no API to set the date stamps on files until
>> Windows Vista. Since I don't have a copy of Vista, I can't test this.
>
> Is that still the current position?

It was, until now :-)

> I'm just wondering what's wrong with SetFileAttributes
> (http://msdn.microsoft.com/library/en-us/fileio/fs/setfileattributes.asp)
> and SetFileTime
> (http://msdn.microsoft.com/library/en-us/sysinfo/base/setfiletime.asp).
>
> Am I missing something obvious or subtle?

No, I think you are absolutely right. I overlooked these API functions. I 
think I was looking at SetFileInformationByHandle.

This should allow me to fix the restoring part of the bbackupd unit tests 
on Windows. Thanks!

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 01:46:16 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 00:46:16 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r644 - box/chris/general/test/bbackupd/testfiles
Message-ID: <20060719004616.ED39596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 00:46:13 +0000 (Wed, 19 Jul 2006)
New Revision: 644

Modified:
   box/chris/general/test/bbackupd/testfiles/extcheck1.pl
Log:
* extcheck1.pl
- More detailed debugging messages, useful when tests fail


Modified: box/chris/general/test/bbackupd/testfiles/extcheck1.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/extcheck1.pl	2006-07-10 20:54:27 UTC (rev 643)
+++ box/chris/general/test/bbackupd/testfiles/extcheck1.pl	2006-07-19 00:46:13 UTC (rev 644)
@@ -15,14 +15,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;


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 01:46:39 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 00:46:39 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r645 - box/chris/general/test/bbackupd/testfiles
Message-ID: <20060719004639.5394796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 00:46:38 +0000 (Wed, 19 Jul 2006)
New Revision: 645

Modified:
   box/chris/general/test/bbackupd/testfiles/extcheck2.pl
Log:
* extcheck2.pl
- More detailed debugging messages, useful when tests fail


Modified: box/chris/general/test/bbackupd/testfiles/extcheck2.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/extcheck2.pl	2006-07-19 00:46:13 UTC (rev 644)
+++ box/chris/general/test/bbackupd/testfiles/extcheck2.pl	2006-07-19 00:46:38 UTC (rev 645)
@@ -14,13 +14,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;


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 01:47:41 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 00:47:41 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r646 - box/chris/general/lib/server
Message-ID: <20060719004741.D1D3396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 00:47:38 +0000 (Wed, 19 Jul 2006)
New Revision: 646

Modified:
   box/chris/general/lib/server/WinNamedPipeStream.cpp
Log:
* WinNamedPipeStream.cpp
- Reset byte count in buffer to zero when buffer is closed, otherwise
  is might start a new connection full of old junk.


Modified: box/chris/general/lib/server/WinNamedPipeStream.cpp
===================================================================
--- box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-19 00:46:38 UTC (rev 645)
+++ box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-19 00:47:38 UTC (rev 646)
@@ -107,6 +107,7 @@
 		THROW_EXCEPTION(ServerException, SocketOpenError)
 	}
 	
+	mBytesInBuffer = 0;
 	mReadClosed  = false;
 	mWriteClosed = false;
 	mIsServer    = true; // must flush and disconnect before closing


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 01:48:14 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 00:48:14 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r647 - box/chris/general/bin/bbackupd
Message-ID: <20060719004814.47CF696@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 00:48:13 +0000 (Wed, 19 Jul 2006)
New Revision: 647

Modified:
   box/chris/general/bin/bbackupd/bbackupd.cpp
Log:
* bbackupd.cpp
- Fixed a memory leak


Modified: box/chris/general/bin/bbackupd/bbackupd.cpp
===================================================================
--- box/chris/general/bin/bbackupd/bbackupd.cpp	2006-07-19 00:47:38 UTC (rev 646)
+++ box/chris/general/bin/bbackupd/bbackupd.cpp	2006-07-19 00:48:13 UTC (rev 647)
@@ -91,6 +91,8 @@
 
 	::closelog();
 
+	delete gpDaemonService;
+
 	return ExitCode;
 
 #else // !WIN32


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 01:49:44 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 00:49:44 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r648 - box/chris/general/bin/bbackupd
Message-ID: <20060719004944.0AA9796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 00:49:41 +0000 (Wed, 19 Jul 2006)
New Revision: 648

Modified:
   box/chris/general/bin/bbackupd/BackupDaemon.cpp
Log:
* BackupDaemon.cpp
- Errors while accepting a connection on the command socket should
  kill the reader thread (or at least stop trying for a while)


Modified: box/chris/general/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-19 00:48:13 UTC (rev 647)
+++ box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-19 00:49:41 UTC (rev 648)
@@ -286,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
 		{
 			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");
@@ -324,7 +343,7 @@
 			IOStreamGetLine readLine(rSocket);
 			std::string command;
 
-			while (rSocket.IsConnected())
+			while (rSocket.IsConnected() && !IsTerminateWanted())
 			{
 				HANDLE handles[2];
 				handles[0] = mhMessageToSendEvent;


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 01:59:16 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 00:59:16 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r649 - box/chris/general/test/bbackupd
Message-ID: <20060719005916.D2FBA96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 00:59:16 +0000 (Wed, 19 Jul 2006)
New Revision: 649

Modified:
   box/chris/general/test/bbackupd/testbbackupd.cpp
Log:
* testbbackupd.cpp
- Final changes to make all bbackupd tests pass:
- Don't check bbstored memleaks on windows; TerminateProcess doesn't
  let it shut down nicely
- Added helper methods to use bbackupctl to force a sync, wait for a sync,
  etc.
- Replaced some calls to wait_for_backup_operation with wait_for_sync,
  should reduce the number of race conditions in testbbackupd
- Don't run root-only tests on Windows, they don't work
- Added a test for locked file behaviour



Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 00:49:41 UTC (rev 648)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 00:59:16 UTC (rev 649)
@@ -438,7 +438,9 @@
 	TEST_THAT(KillServer(bbstored_pid));
 	::sleep(1);
 	TEST_THAT(!ServerIsAlive(bbstored_pid));
+#ifndef WIN32
 	TestRemoteProcessMemLeaks("bbstored.memleaks");
+#endif
 	return 0;
 }
 
@@ -539,6 +541,45 @@
 }
 #endif
 
+void force_sync()
+{
+	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+		"force-sync") == 0);
+	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+void wait_for_sync()
+{
+	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+		"wait-for-sync") == 0);
+	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+void wait_for_sync_end()
+{
+	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+		"wait-for-end") == 0);
+	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+void terminate_bbackupd(int pid)
+{
+	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+		"terminate") == 0);
+	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+
+	for (int i = 0; i < 20; i++)
+	{
+		if (!ServerIsAlive(pid)) break;
+		fprintf(stdout, ".");
+		fflush(stdout);
+		sleep(1);
+	}
+
+	TEST_THAT(!ServerIsAlive(pid));
+	TestRemoteProcessMemLeaks("bbackupd.memleaks");
+}
+
 int test_bbackupd()
 {
 //	// First, wait for a normal period to make sure the last changes attributes are within a normal backup timeframe.
@@ -756,12 +797,8 @@
 		
 		// Check that modifying files with old timestamps still get added
 		printf("Modify existing file, but change timestamp to rather old\n");
-		// Time critical, so sync
-		TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
-			"wait-for-sync") == 0);
-		TestRemoteProcessMemLeaks("bbackupctl.memleaks");
-		// Then wait a second, to make sure the scan is complete
-		::sleep(1);
+		wait_for_sync_end();
+
 		// Then modify an existing file
 		{
 			// in the archive, it's read only
@@ -794,7 +831,9 @@
 		}
 
 		// Wait and test
-		wait_for_backup_operation();
+		wait_for_sync_end(); // files too new
+		wait_for_sync_end(); // should (not) be backed up this time
+
 		compareReturnValue = ::system(BBACKUPQUERY " -q -c testfiles/bbackupd.conf -l testfiles/query3e.log \"compare -ac\" quit");
 		TEST_RETURN(compareReturnValue, 1);
 		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
@@ -808,7 +847,9 @@
 #endif
 
 		// Wait and test
-		wait_for_backup_operation();
+		wait_for_sync_end();
+		wait_for_sync_end();
+
 		compareReturnValue = ::system(BBACKUPQUERY " -q -c testfiles/bbackupd.conf -l testfiles/query3c.log \"compare -ac\" quit");
 		TEST_RETURN(compareReturnValue, 1);
 		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
@@ -818,6 +859,7 @@
 		TEST_RETURN(compareReturnValue, 2);
 		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 
+#ifndef WIN32
 		// These tests only work as non-root users.
 		if(::getuid() != 0)
 		{
@@ -845,13 +887,14 @@
 			::chmod("testfiles/TestDir1/sub23/read-fail-test-dir", 0770);
 			::chmod("testfiles/TestDir1/read-fail-test-file", 0770);
 		}
+#endif
 
 		printf("Continuously update file, check isn't uploaded\n");
 		
-		// Make sure everything happens at the same point in the sync cycle: wait until exactly the start of a sync
-		TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
-			"wait-for-sync") == 0);
-		TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+		// Make sure everything happens at the same point in the 
+		// sync cycle: wait until exactly the start of a sync
+		wait_for_sync();
+
 		// Then wait a second, to make sure the scan is complete
 		::sleep(1);
 
@@ -863,10 +906,11 @@
 				TEST_THAT(f != 0);
 				fprintf(f, "Loop iteration %d\n", l);
 				fflush(f);
-				sleep(1);
+				fclose(f);
+
 				printf(".");
 				fflush(stdout);
-				::fclose(f);
+				sleep(1);
 			}
 			printf("\n");
 			
@@ -883,10 +927,11 @@
 				TEST_THAT(f != 0);
 				fprintf(f, "Loop 2 iteration %d\n", l);
 				fflush(f);
-				sleep(1);
+				fclose(f);
+
 				printf(".");
 				fflush(stdout);
-				::fclose(f);
+				sleep(1);
 			}
 			printf("\n");
 
@@ -948,7 +993,15 @@
 		}
 
 		// Compare the restored files
-		compareReturnValue = ::system(BBACKUPQUERY " -q -c testfiles/bbackupd.conf -l testfiles/query10.log \"compare -cE Test1 testfiles/restore-Test1\" quit");
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10.log "
+		#ifdef WIN32
+			"\"compare -cAE Test1 testfiles/restore-Test1\" "
+		#else
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+		#endif
+			"quit");
+
 		TEST_RETURN(compareReturnValue, 1);
 		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 
@@ -993,11 +1046,11 @@
 		// Check that modifying files with madly in the future timestamps still get added
 		printf("Create a file with timestamp to way ahead in the future\n");
 		// Time critical, so sync
-		TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
-			"wait-for-sync") == 0);
-		TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+		wait_for_sync();
+
 		// Then wait a second, to make sure the scan is complete
 		::sleep(1);
+
 		// Then modify an existing file
 		{
 			FILE *f = fopen("testfiles/TestDir1/sub23/in-the-future", "w");
@@ -1054,8 +1107,8 @@
 		
 		printf("Check change of store marker pauses daemon\n");
 		
-		// Make a change to a file, to detect whether or not it's hanging around
-		// waiting to retry.
+		// Make a change to a file, to detect whether or not 
+		// it's hanging around waiting to retry.
 		{
 			FILE *f = ::fopen("testfiles/TestDir1/fileaftermarker", "w");
 			TEST_THAT(f != 0);
@@ -1064,7 +1117,7 @@
 		}
 
 		// Wait and test that there *are* differences
-		wait_for_backup_operation((TIME_TO_WAIT_FOR_BACKUP_OPERATION*3) / 2); // little bit longer than usual
+		wait_for_backup_operation((TIME_TO_WAIT_FOR_BACKUP_OPERATION * 3) / 2); // little bit longer than usual
 		compareReturnValue = ::system(BBACKUPQUERY " -q -c testfiles/bbackupd.conf -l testfiles/query6.log \"compare -ac\" quit");
 		TEST_RETURN(compareReturnValue, 2);
 		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
@@ -1121,7 +1174,14 @@
 			compareReturnValue = ::system(BBACKUPQUERY 
 				" -q -c testfiles/bbackupd.conf "
 				"-l testfiles/query11.log "
-				"\"compare -cE Test1/x1 testfiles/restore-Test1-x1-2\" quit");
+				"\"compare "
+			#ifdef WIN32
+				// cannot restore attributes, so don't compare
+				"-cAE "
+			#else
+				"-cE "
+			#endif
+				"Test1/x1 testfiles/restore-Test1-x1-2\" quit");
 			TEST_RETURN(compareReturnValue, 1);
 			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 		}
@@ -1130,18 +1190,82 @@
 		TEST_THAT(!TestFileExists("testfiles/notifyran.store-full.2"));
 		TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
 
+		#if 0 // WIN32
+		printf("Testing locked file behaviour:\n");
+
+		// Test that locked files cannot be backed up,
+		// and the appropriate error is reported.
+		// Wait for a sync to finish, so that we have time to work
+		wait_for_sync_end();
+		// Now we have about three seconds to work
+
+		HANDLE handle = openfile("testfiles/TestDir1/lockedfile",
+			O_CREAT | O_EXCL, 0);
+		TEST_THAT(handle != 0);
+
+		if (handle != 0)
+		{
+			// first sync will ignore the file, it's too new
+			wait_for_sync_end();
+			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
+
+			// this sync should try to back up the file, 
+			// and fail, because it's locked
+			wait_for_sync_end();
+			TEST_THAT(TestFileExists("testfiles/notifyran.read-error.2"));
+			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.3"));
+
+			// now close the file and check that it is
+			// backed up on the next run.
+			CloseHandle(handle);
+			wait_for_sync_end();
+			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.3"));
+
+			// compare, and check that it works
+			// reports the correct error message (and finishes)
+			compareReturnValue = ::system(BBACKUPQUERY 
+				" -q -c testfiles/bbackupd.conf "
+				"-l testfiles/query15a.log "
+				"\"compare -ac\" quit");
+			TEST_RETURN(compareReturnValue, 1);
+			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+			// open the file again, compare and check that compare
+			// reports the correct error message (and finishes)
+			handle = openfile("testfiles/TestDir1/lockedfile",
+				O_CREAT | O_EXCL, 0);
+			TEST_THAT(handle != 0);
+
+			compareReturnValue = ::system(BBACKUPQUERY 
+				" -q -c testfiles/bbackupd.conf "
+				"-l testfiles/query15.log "
+				"\"compare -ac\" quit");
+			TEST_RETURN(compareReturnValue, 2);
+			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+			// close the file again, check that compare
+			// works again
+			CloseHandle(handle);
+
+			compareReturnValue = ::system(BBACKUPQUERY 
+				" -q -c testfiles/bbackupd.conf "
+				"-l testfiles/query15a.log "
+				"\"compare -ac\" quit");
+			TEST_RETURN(compareReturnValue, 1);
+			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+		}
+		#endif
+
 		// Kill the daemon
-		TEST_THAT(KillServer(pid));
-		::sleep(1);
-		TEST_THAT(!ServerIsAlive(pid));
-		TestRemoteProcessMemLeaks("bbackupd.memleaks");
+		terminate_bbackupd(pid);
 		
 		// Start it again
-		pid = LaunchServer("../../bin/bbackupd/bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
+		pid = LaunchServer("../../bin/bbackupd/bbackupd "
+			"testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
 		TEST_THAT(pid != -1 && pid != 0);
 		if(pid != -1 && pid != 0)
 		{
-			// Wait and comapre
+			// Wait and compare
 			wait_for_backup_operation((TIME_TO_WAIT_FOR_BACKUP_OPERATION*3) / 2); // little bit longer than usual
 			compareReturnValue = ::system(BBACKUPQUERY 
 				" -q -c testfiles/bbackupd.conf "
@@ -1150,10 +1274,7 @@
 			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 
 			// Kill it again
-			TEST_THAT(KillServer(pid));
-			::sleep(1);
-			TEST_THAT(!ServerIsAlive(pid));
-			TestRemoteProcessMemLeaks("bbackupd.memleaks");
+			terminate_bbackupd(pid);
 		}
 	}
 
@@ -1161,11 +1282,13 @@
 	::system(BBACKUPQUERY " -q -c testfiles/bbackupd.conf "
 		"-l testfiles/queryLIST.log \"list -rotdh\" quit");
 	TestRemoteProcessMemLeaks("bbackupquery.memleaks");
-	
+
+#ifndef WIN32	
 	if(::getuid() == 0)
 	{
 		::printf("WARNING: This test was run as root. Some tests have been omitted.\n");
 	}
+#endif
 	
 	return 0;
 }


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 03:36:48 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 02:36:48 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r650 - in box/chris/general/test/bbackupd: . testfiles
Message-ID: <20060719023648.A940596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 02:36:43 +0000 (Wed, 19 Jul 2006)
New Revision: 650

Modified:
   box/chris/general/test/bbackupd/testbbackupd.cpp
   box/chris/general/test/bbackupd/testfiles/extcheck1.pl
   box/chris/general/test/bbackupd/testfiles/extcheck2.pl
Log:
* bbackupd/testfiles/extcheck1.pl
* bbackupd/testfiles/extcheck2.pl
* bbackupd/testbbackupd.cpp
- More final fixes:
- Pass flags to extcheck*.pl to cause them not to check attributes
- Made locked file test work properly, and enabled it


Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 00:59:16 UTC (rev 649)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 02:36:43 UTC (rev 650)
@@ -562,6 +562,13 @@
 	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
 }
 
+void sync_and_wait()
+{
+	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+		"force-sync") == 0);
+	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
 void terminate_bbackupd(int pid)
 {
 	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
@@ -915,7 +922,12 @@
 			printf("\n");
 			
 			// Check there's a difference
+			#ifdef WIN32
+			compareReturnValue = ::system("perl testfiles/extcheck1.pl A");
+			#else
 			compareReturnValue = ::system("perl testfiles/extcheck1.pl");
+			#endif
+
 			TEST_RETURN(compareReturnValue, 1);
 			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 
@@ -935,7 +947,12 @@
 			}
 			printf("\n");
 
+			#ifdef WIN32
+			compareReturnValue = ::system("perl testfiles/extcheck2.pl A");
+			#else
 			compareReturnValue = ::system("perl testfiles/extcheck2.pl");
+			#endif
+
 			TEST_RETURN(compareReturnValue, 1);
 			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 		}
@@ -1190,13 +1207,15 @@
 		TEST_THAT(!TestFileExists("testfiles/notifyran.store-full.2"));
 		TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
 
-		#if 0 // WIN32
+		#ifdef WIN32
 		printf("Testing locked file behaviour:\n");
 
 		// Test that locked files cannot be backed up,
 		// and the appropriate error is reported.
-		// Wait for a sync to finish, so that we have time to work
-		wait_for_sync_end();
+		// force a sync, since otherwise we will have to wait
+		// forever because of the ClientStoreMarker error above
+		// Wait for the sync to finish, so that we have time to work
+		sync_and_wait();
 		// Now we have about three seconds to work
 
 		HANDLE handle = openfile("testfiles/TestDir1/lockedfile",
@@ -1207,19 +1226,19 @@
 		{
 			// first sync will ignore the file, it's too new
 			wait_for_sync_end();
-			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
+			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.1"));
 
 			// this sync should try to back up the file, 
 			// and fail, because it's locked
 			wait_for_sync_end();
-			TEST_THAT(TestFileExists("testfiles/notifyran.read-error.2"));
-			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.3"));
+			TEST_THAT(TestFileExists("testfiles/notifyran.read-error.1"));
+			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
 
 			// now close the file and check that it is
 			// backed up on the next run.
 			CloseHandle(handle);
 			wait_for_sync_end();
-			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.3"));
+			TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
 
 			// compare, and check that it works
 			// reports the correct error message (and finishes)
@@ -1240,7 +1259,7 @@
 				" -q -c testfiles/bbackupd.conf "
 				"-l testfiles/query15.log "
 				"\"compare -ac\" quit");
-			TEST_RETURN(compareReturnValue, 2);
+			TEST_RETURN(compareReturnValue, 3);
 			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 
 			// close the file again, check that compare

Modified: box/chris/general/test/bbackupd/testfiles/extcheck1.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/extcheck1.pl	2006-07-19 00:59:16 UTC (rev 649)
+++ box/chris/general/test/bbackupd/testfiles/extcheck1.pl	2006-07-19 02:36:43 UTC (rev 650)
@@ -1,7 +1,9 @@
 #!/usr/bin/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;

Modified: box/chris/general/test/bbackupd/testfiles/extcheck2.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/extcheck2.pl	2006-07-19 00:59:16 UTC (rev 649)
+++ box/chris/general/test/bbackupd/testfiles/extcheck2.pl	2006-07-19 02:36:43 UTC (rev 650)
@@ -1,7 +1,9 @@
 #!/usr/bin/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;


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 04:07:38 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 03:07:38 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r651 - box/chris/general/bin/bbackupquery
Message-ID: <20060719030738.4595696@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 03:07:34 +0000 (Wed, 19 Jul 2006)
New Revision: 651

Modified:
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
   box/chris/general/bin/bbackupquery/BackupQueries.h
Log:
* bbackupquery/BackupQueries.cpp
* bbackupquery/BackupQueries.h
- Improved handling of locked files during compare under Windows:
  count them separately, report the total, and return COMPARE_RETURN_ERROR 
  if any are found.
- All tests pass.


Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-19 02:36:43 UTC (rev 650)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-19 03:07:34 UTC (rev 651)
@@ -1016,6 +1016,7 @@
 	  mIgnoreAttributes(false),
 	  mDifferences(0),
 	  mDifferencesExplainedByModTime(0),
+	  mUncheckedFiles(0),
 	  mExcludedDirs(0),
 	  mExcludedFiles(0),
 	  mpExcludeFiles(0),
@@ -1139,13 +1140,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);
+		}
 	}
 }
 
@@ -1279,11 +1296,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;
 	}
@@ -1333,6 +1352,7 @@
 	{
 		printf("ERROR: opendir on local dir '%s'\n", 
 			localDirDisplay.c_str());
+		rParams.mUncheckedFiles ++;
 		return;
 	}
 	try
@@ -1609,10 +1629,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

Modified: box/chris/general/bin/bbackupquery/BackupQueries.h
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.h	2006-07-19 02:36:43 UTC (rev 650)
+++ box/chris/general/bin/bbackupquery/BackupQueries.h	2006-07-19 03:07:34 UTC (rev 651)
@@ -71,6 +71,7 @@
 		bool mIgnoreAttributes;
 		int mDifferences;
 		int mDifferencesExplainedByModTime;
+		int mUncheckedFiles;
 		int mExcludedDirs;
 		int mExcludedFiles;
 		const ExcludeList *mpExcludeFiles;


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 04:08:58 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 03:08:58 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r652 - box/chris/general/test/bbackupd
Message-ID: <20060719030858.EB79996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 03:08:58 +0000 (Wed, 19 Jul 2006)
New Revision: 652

Modified:
   box/chris/general/test/bbackupd/testbbackupd.cpp
Log:
* test/bbackupd/testbbackupd.cpp
- Go back to using wait_for_sync, because force_sync doesn't work (quickly)
  and breaks another test when it does eventually happen.


Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 03:07:34 UTC (rev 651)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 03:08:58 UTC (rev 652)
@@ -1212,10 +1212,8 @@
 
 		// Test that locked files cannot be backed up,
 		// and the appropriate error is reported.
-		// force a sync, since otherwise we will have to wait
-		// forever because of the ClientStoreMarker error above
 		// Wait for the sync to finish, so that we have time to work
-		sync_and_wait();
+		wait_for_sync();
 		// Now we have about three seconds to work
 
 		HANDLE handle = openfile("testfiles/TestDir1/lockedfile",


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 09:48:31 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 08:48:31 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r653 - box/chris/general/lib/common
Message-ID: <20060719084831.973B596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 08:48:29 +0000 (Wed, 19 Jul 2006)
New Revision: 653

Modified:
   box/chris/general/lib/common/Test.h
Log:
* Test.h
- Removed dependency on WinNamedPipeStream, now in lib/server


Modified: box/chris/general/lib/common/Test.h
===================================================================
--- box/chris/general/lib/common/Test.h	2006-07-19 03:08:58 UTC (rev 652)
+++ box/chris/general/lib/common/Test.h	2006-07-19 08:48:29 UTC (rev 653)
@@ -211,130 +211,10 @@
 #endif // WIN32
 }
 
-#ifdef WIN32
+#ifndef WIN32
 
-#include "WinNamedPipeStream.h"
-#include "IOStreamGetLine.h"
-#include "BoxPortsAndFiles.h"
-
-inline bool SendCommands(const std::string& rCmd)
-{
-	WinNamedPipeStream connection;
-
-	try
-	{
-		connection.Connect(BOX_NAMED_PIPE_NAME);
-	}
-	catch(...)
-	{
-		printf("Failed to connect to daemon control socket.\n");
-		return false;
-	}
-
-	// For receiving data
-	IOStreamGetLine getLine(connection);
-	
-	// Wait for the configuration summary
-	std::string configSummary;
-	if(!getLine.GetLine(configSummary))
-	{
-		printf("Failed to receive configuration summary from daemon\n");
-		return false;
-	}
-
-	// Was the connection rejected by the server?
-	if(getLine.IsEOF())
-	{
-		printf("Server rejected the connection.\n");
-		return false;
-	}
-
-	// Decode it
-	int autoBackup, updateStoreInterval, minimumFileAge, maxUploadWait;
-	if(::sscanf(configSummary.c_str(), "bbackupd: %d %d %d %d", 
-			&autoBackup, &updateStoreInterval, 
-			&minimumFileAge, &maxUploadWait) != 4)
-	{
-		printf("Config summary didn't decode\n");
-		return false;
-	}
-
-	std::string cmds;
-	bool expectResponse;
-
-	if (rCmd != "")
-	{
-		cmds = rCmd;
-		cmds += "\nquit\n";
-		expectResponse = true;
-	}
-	else
-	{
-		cmds = "quit\n";
-		expectResponse = false;
-	}
-	
-	connection.Write(cmds.c_str(), cmds.size());
-	
-	// Read the response
-	std::string line;
-	bool statusOk = !expectResponse;
-
-	while (expectResponse && !getLine.IsEOF() && getLine.GetLine(line))
-	{
-		// Is this an OK or error line?
-		if (line == "ok")
-		{
-			statusOk = true;
-		}
-		else if (line == "error")
-		{
-			printf("ERROR (%s)\n", rCmd.c_str());
-			break;
-		}
-		else
-		{
-			printf("WARNING: Unexpected response to command '%s': "
-				"%s", rCmd.c_str(), line.c_str());
-		}
-	}
-	
-	return statusOk;
-}
-
 inline bool HUPServer(int pid)
 {
-	return SendCommands("reload");
-}
-
-inline bool KillServer(int pid)
-{
-	HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, false, pid);
-	if (hProcess == NULL)
-	{
-		printf("Failed to open process %d: error %d\n",
-			pid, (int)GetLastError());
-		return false;
-	}
-
-	if (!TerminateProcess(hProcess, 1))
-	{
-		printf("Failed to terminate process %d: error %d\n",
-			pid, (int)GetLastError());
-		CloseHandle(hProcess);
-		return false;
-	}
-
-	CloseHandle(hProcess);
-
-	::sleep(1);
-	return !ServerIsAlive(pid);
-}
-
-#else // !WIN32
-
-inline bool HUPServer(int pid)
-{
 	if(pid == 0) return false;
 	return ::kill(pid, SIGHUP) != -1;
 }
@@ -348,7 +228,7 @@
 	return !ServerIsAlive(pid);
 }
 
-#endif // WIN32
+#endif // !WIN32
 
 inline void TestRemoteProcessMemLeaks(const char *filename)
 {


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 14:22:02 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 19 Jul 2006 14:22:02 +0100
Subject: [Box Backup-dev] Hello all - win32 client
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501603@toutatis.omn11s.local>

Hello Ben and all,

I haven't had any time to dedicate to box recently but would like to
pick up a little from my last input.

I have been reading a little on the current outstanding problems with
the win32 client, mainly the serious ones, large files and locking
problems.

I think it is important that these get resolved and I am happy to help
out, large files just needs fixing (I thought it was last time I worked
on it!), but I was thinking about file locks, a good idea would be to
integrate Shadow Coy Services. I had a quick look at bacula, they have
implemented it in there latest version, unfortunate that it is GNU, so I
know Ben doesn't want this license. VSS is great, because as well as
giving you access to files with exclusive locks, they also get VSS aware
applications to ensure the underlying data is consistent - such as
Exchange.

Another comment about large files, lets say there wasn't a problem;
another issue I have noticed is with the time taken to upload large
files, if you are behind an ADSL connection, and there is a very good
chance that the connection would be dropped box at the moment simply
starts again, are there any ideas around this?

Can someone point me in the direction to the latest sources, so I can
have a play; also is visual studio the preferred method for building -
or other?

Thanks

Nick

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 15:15:17 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 19 Jul 2006 15:15:17 +0100
Subject: [Box Backup-dev] including unlicensed software
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F950160E@toutatis.omn11s.local>

Hello Ben,

What is your view in including example code, which is from known source
(http://www.codeproject.com) but has no mention of copyright or license?

Do you take the view that it is in the public domain therefore can
example code can be included in your project, or it doesn't say - leave
well alone!

Regards

Nick

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 15:22:14 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 19 Jul 2006 15:22:14 +0100
Subject: [Box Backup-dev] including unlicensed software
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F950160E@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950160E@toutatis.omn11s.local>
Message-ID: <D379CBC5-C200-444C-A8E4-04A34A1805EF@fluffy.co.uk>

On 19 Jul 2006, at 15:15, Nick Knight wrote:

> Hello Ben,
>
> What is your view in including example code, which is from known  
> source
> (http://www.codeproject.com) but has no mention of copyright or  
> license?
>
> Do you take the view that it is in the public domain therefore can
> example code can be included in your project, or it doesn't say -  
> leave
> well alone!


I think code without a explicit BSD license should not be included.  
It's only going to store up trouble for later.

Code sharing sites should really force contributors to state a  
license for their code.

Ben








From boxbackup-dev@fluffy.co.uk  Wed Jul 19 15:54:29 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Wed, 19 Jul 2006 07:54:29 -0700 (PDT)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501603@toutatis.omn11s.local>
Message-ID: <20060719145429.64868.qmail@web36713.mail.mud.yahoo.com>

Nick,

> large files and locking problems.

Locking problems are exactly as they used to be, however, I am not sure what large file problem
you are referring to. I am currently running Chris' modified Win32 .10 tree with a lot of large
files, and have no problems so far.

> integrate Shadow Coy Services. I had a quick look at bacula, they have

Yes, Shadow Copy services would be definitely useful and the way to go under Win32.

> another issue I have noticed is with the time taken to upload large
> files, if you are behind an ADSL connection, and there is a very good
> chance that the connection would be dropped box at the moment simply
> starts again, are there any ideas around this?

No way around this since the server is atomic, unless we implement some kind of block caching with
upload resume.

> Can someone point me in the direction to the latest sources, so I can
> have a play; also is visual studio the preferred method for building -
> or other?

I think Chris' is the most advanced and functional Win32 version, but he does not build with
VS2K5. It would be useful to standardize the build and test environment for Win32 Box.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 16:10:38 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 19 Jul 2006 16:10:38 +0100
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <20060719145429.64868.qmail@web36713.mail.mud.yahoo.com>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501620@toutatis.omn11s.local>

Hello Gary,

I found the comments referring to large files (>2GB) in one of the
messages - I did find it a little strange as I thought this was fixed
when I worked on it! I may have mis-read.

Yes - block caching is what I had in mind, not sure what everyone else
thoughts on this is, I definitely have seen issues with not having it.

I noticed it is either VS or the ming compiler - my understanding was
the ming compiler was that it is not that much different from cygwin.

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of G.
Sent: 19 July 2006 15:54
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] Hello all - win32 client

Nick,

> large files and locking problems.

Locking problems are exactly as they used to be, however, I am not sure
what large file problem
you are referring to. I am currently running Chris' modified Win32 .10
tree with a lot of large
files, and have no problems so far.

> integrate Shadow Coy Services. I had a quick look at bacula, they have

Yes, Shadow Copy services would be definitely useful and the way to go
under Win32.

> another issue I have noticed is with the time taken to upload large
> files, if you are behind an ADSL connection, and there is a very good
> chance that the connection would be dropped box at the moment simply
> starts again, are there any ideas around this?

No way around this since the server is atomic, unless we implement some
kind of block caching with
upload resume.

> Can someone point me in the direction to the latest sources, so I can
> have a play; also is visual studio the preferred method for building -
> or other?

I think Chris' is the most advanced and functional Win32 version, but he
does not build with
VS2K5. It would be useful to standardize the build and test environment
for Win32 Box.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 16:41:12 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Wed, 19 Jul 2006 08:41:12 -0700 (PDT)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501620@toutatis.omn11s.local>
Message-ID: <20060719154112.15846.qmail@web36703.mail.mud.yahoo.com>

Nick,

> I found the comments referring to large files (>2GB) in one of the
> messages - I did find it a little strange as I thought this was fixed

Oh, that's right, I never ran into it (I am slightly below 2GB for each file). That one indeed
might need fixing.

> Yes - block caching is what I had in mind, not sure what everyone else
> thoughts on this is, I definitely have seen issues with not having it.

IMHO, it would definitely be a useful feature, allowing large files to be uploaded in chunks,
rather than all-or-nothing. It would not be easy though, you would have to ask the server whether
it has a "block cache" for each large file, and whether all (or some) cached blocks match local
content (already), and then proceed with resume, until a file can be "comitted" to a store. Useful
feature though.

> I noticed it is either VS or the ming compiler - my understanding was
> the ming compiler was that it is not that much different from cygwin.

You would have to ask Chris, but I think mingw is a native Win32 compiler. It  would be useful,
however, if we used the same environment for all build/compile. VS2K5 would get my vote (it is,
after all, most widely used and most widely tested under Win32). There is even a free edition
these days :).

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 17:06:11 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 19 Jul 2006 17:06:11 +0100
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <20060719154112.15846.qmail@web36703.mail.mud.yahoo.com>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501638@toutatis.omn11s.local>

OK,

I am stuck already :)

I have downloaded 0.10 to build under windows (I have VC 2003), and I
know I did the port originally but I cannot figure out the build
instructions.

Can someone (perhaps Chris) point me in the direction of some good build
instructions?

Thanks

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of G.
Sent: 19 July 2006 16:41
To: boxbackup-dev@fluffy.co.uk
Subject: RE: [Box Backup-dev] Hello all - win32 client

Nick,

> I found the comments referring to large files (>2GB) in one of the
> messages - I did find it a little strange as I thought this was fixed

Oh, that's right, I never ran into it (I am slightly below 2GB for each
file). That one indeed
might need fixing.

> Yes - block caching is what I had in mind, not sure what everyone else
> thoughts on this is, I definitely have seen issues with not having it.

IMHO, it would definitely be a useful feature, allowing large files to
be uploaded in chunks,
rather than all-or-nothing. It would not be easy though, you would have
to ask the server whether
it has a "block cache" for each large file, and whether all (or some)
cached blocks match local
content (already), and then proceed with resume, until a file can be
"comitted" to a store. Useful
feature though.

> I noticed it is either VS or the ming compiler - my understanding was
> the ming compiler was that it is not that much different from cygwin.

You would have to ask Chris, but I think mingw is a native Win32
compiler. It  would be useful,
however, if we used the same environment for all build/compile. VS2K5
would get my vote (it is,
after all, most widely used and most widely tested under Win32). There
is even a free edition
these days :).

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 17:10:14 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Wed, 19 Jul 2006 09:10:14 -0700 (PDT)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501638@toutatis.omn11s.local>
Message-ID: <20060719161014.28338.qmail@web36703.mail.mud.yahoo.com>

Nick,

> I have downloaded 0.10 to build under windows (I have VC 2003), and I
> know I did the port originally but I cannot figure out the build
> instructions.

There are instructions for Visual Studio 2005 (Express) in BoxBackup wiki. Those worked last time
I tried, but you might need Chris' source tree (as opposed to vanilla .10).

Gary

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Wed Jul 19 19:10:49 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Wed, 19 Jul 2006 19:10:49 +0100 (BST)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <20060719154112.15846.qmail@web36703.mail.mud.yahoo.com>
References: <20060719154112.15846.qmail@web36703.mail.mud.yahoo.com>
Message-ID: <Pine.LNX.4.62.0607191905520.18881@top.qwarx.com>

Hi Gary,

> You would have to ask Chris, but I think mingw is a native Win32 
> compiler.

It is. I run it under Cygwin, to get a nice shell and the necessary build 
environment, but it might be possible to compile with the official MinGW 
release and MSYS, which would then not require the developer to install 
Cygwin.

> It would be useful, however, if we used the same environment 
> for all build/compile. VS2K5 would get my vote (it is, after all, most 
> widely used and most widely tested under Win32). There is even a free 
> edition these days :).

It would be useful if I liked VS2K5 more :-) As it is, I can and sometimes 
do compile with it, but I don't test such builds very often because I 
can't distribute them, due to the license and the size of the 
redistributable. Patches are welcome :-)

I would be surprised if VS2K5 was the most widely used compiler for 
Windows, considering its young age, the problems with Intellisense (which 
frequently crash the IDE until manually disabled), and the number of 
requests for help with different versions of Visual Studio on the 
wxWidgets mailing list.

If you meant Visual Studio generally, then I agree, although I think more 
open source projects use MinGW than use Visual Studio.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 19:14:57 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Wed, 19 Jul 2006 19:14:57 +0100 (BST)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501638@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F9501638@toutatis.omn11s.local>
Message-ID: <Pine.LNX.4.62.0607191911010.18881@top.qwarx.com>

Hi Nick,

Welcome back!

> I am stuck already :)

Sorry ;-)

> I have downloaded 0.10 to build under windows (I have VC 2003), and I
> know I did the port originally but I cannot figure out the build
> instructions.
>
> Can someone (perhaps Chris) point me in the direction of some good build
> instructions?

You've probably found them already, but if not, the relevant pages are:

[http://boxbackup.hostworks.ca/index.php/Compile_on_Windows]

and

[http://boxbackup.hostworks.ca/index.php/Known_bugs_in_the_Win32_client]

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 19:43:54 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 18:43:54 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r654 - in box/chris/general/lib: common server
Message-ID: <20060719184354.1FF9B96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 18:43:52 +0000 (Wed, 19 Jul 2006)
New Revision: 654

Added:
   box/chris/general/lib/server/ServerControl.h
Modified:
   box/chris/general/lib/common/Test.h
Log:
* common/Test.h
* server/ServerControl.h
- Moved HupServer and KillServer to ServerControl.h, since on Win32 they
  depend on lib/server.


Modified: box/chris/general/lib/common/Test.h
===================================================================
--- box/chris/general/lib/common/Test.h	2006-07-19 08:48:29 UTC (rev 653)
+++ box/chris/general/lib/common/Test.h	2006-07-19 18:43:52 UTC (rev 654)
@@ -44,6 +44,8 @@
 // NOTE: The 0- bit is to allow this to work with stuff which has negative constants for flags (eg ConnectionException)
 #define TEST_CHECK_THROWS(statement, excepttype, subtype)									\
 	{																						\
+		printf("[Test] Expect an exception below: (" \
+			#excepttype "/" #subtype ")\n"); \
 		bool didthrow = false;																\
 		try																					\
 		{																					\
@@ -211,25 +213,6 @@
 #endif // WIN32
 }
 
-#ifndef WIN32
-
-inline bool HUPServer(int pid)
-{
-	if(pid == 0) return false;
-	return ::kill(pid, SIGHUP) != -1;
-}
-
-inline bool KillServer(int pid)
-{
-	if(pid == 0 || pid == -1) return false;
-	bool KilledOK = ::kill(pid, SIGTERM) != -1;
-	TEST_THAT(KilledOK);
-	::sleep(1);
-	return !ServerIsAlive(pid);
-}
-
-#endif // !WIN32
-
 inline void TestRemoteProcessMemLeaks(const char *filename)
 {
 #ifdef BOX_MEMORY_LEAK_TESTING

Added: box/chris/general/lib/server/ServerControl.h
===================================================================
--- box/chris/general/lib/server/ServerControl.h	2006-07-19 08:48:29 UTC (rev 653)
+++ box/chris/general/lib/server/ServerControl.h	2006-07-19 18:43:52 UTC (rev 654)
@@ -0,0 +1,143 @@
+#ifndef SERVER_CONTROL_H
+#define SERVER_CONTROL_H
+
+#ifdef WIN32
+
+#include "WinNamedPipeStream.h"
+#include "IOStreamGetLine.h"
+#include "BoxPortsAndFiles.h"
+
+static bool SendCommands(const std::string& rCmd)
+{
+	WinNamedPipeStream connection;
+
+	try
+	{
+		connection.Connect(BOX_NAMED_PIPE_NAME);
+	}
+	catch(...)
+	{
+		printf("Failed to connect to daemon control socket.\n");
+		return false;
+	}
+
+	// For receiving data
+	IOStreamGetLine getLine(connection);
+	
+	// Wait for the configuration summary
+	std::string configSummary;
+	if(!getLine.GetLine(configSummary))
+	{
+		printf("Failed to receive configuration summary from daemon\n");
+		return false;
+	}
+
+	// Was the connection rejected by the server?
+	if(getLine.IsEOF())
+	{
+		printf("Server rejected the connection.\n");
+		return false;
+	}
+
+	// Decode it
+	int autoBackup, updateStoreInterval, minimumFileAge, maxUploadWait;
+	if(::sscanf(configSummary.c_str(), "bbackupd: %d %d %d %d", 
+			&autoBackup, &updateStoreInterval, 
+			&minimumFileAge, &maxUploadWait) != 4)
+	{
+		printf("Config summary didn't decode\n");
+		return false;
+	}
+
+	std::string cmds;
+	bool expectResponse;
+
+	if (rCmd != "")
+	{
+		cmds = rCmd;
+		cmds += "\nquit\n";
+		expectResponse = true;
+	}
+	else
+	{
+		cmds = "quit\n";
+		expectResponse = false;
+	}
+	
+	connection.Write(cmds.c_str(), cmds.size());
+	
+	// Read the response
+	std::string line;
+	bool statusOk = !expectResponse;
+
+	while (expectResponse && !getLine.IsEOF() && getLine.GetLine(line))
+	{
+		// Is this an OK or error line?
+		if (line == "ok")
+		{
+			statusOk = true;
+		}
+		else if (line == "error")
+		{
+			printf("ERROR (%s)\n", rCmd.c_str());
+			break;
+		}
+		else
+		{
+			printf("WARNING: Unexpected response to command '%s': "
+				"%s", rCmd.c_str(), line.c_str());
+		}
+	}
+	
+	return statusOk;
+}
+
+inline bool HUPServer(int pid)
+{
+	return SendCommands("reload");
+}
+
+inline bool KillServer(int pid)
+{
+	HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, false, pid);
+	if (hProcess == NULL)
+	{
+		printf("Failed to open process %d: error %d\n",
+			pid, (int)GetLastError());
+		return false;
+	}
+
+	if (!TerminateProcess(hProcess, 1))
+	{
+		printf("Failed to terminate process %d: error %d\n",
+			pid, (int)GetLastError());
+		CloseHandle(hProcess);
+		return false;
+	}
+
+	CloseHandle(hProcess);
+
+	::sleep(1);
+	return !ServerIsAlive(pid);
+}
+
+#else // !WIN32
+
+inline bool HUPServer(int pid)
+{
+	if(pid == 0) return false;
+	return ::kill(pid, SIGHUP) != -1;
+}
+
+inline bool KillServer(int pid)
+{
+	if(pid == 0 || pid == -1) return false;
+	bool KilledOK = ::kill(pid, SIGTERM) != -1;
+	TEST_THAT(KilledOK);
+	::sleep(1);
+	return !ServerIsAlive(pid);
+}
+
+#endif // WIN32
+
+#endif // SERVER_CONTROL_H


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 19:44:30 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 18:44:30 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r655 - box/chris/general/infrastructure
Message-ID: <20060719184430.78BD796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 18:44:28 +0000 (Wed, 19 Jul 2006)
New Revision: 655

Modified:
   box/chris/general/infrastructure/makebuildenv.pl
Log:
* makebuildenv.pl
- Added lib/server to implicit includes to help tests find ServerControl.h


Modified: box/chris/general/infrastructure/makebuildenv.pl
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl	2006-07-19 18:43:52 UTC (rev 654)
+++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-19 18:44:28 UTC (rev 655)
@@ -40,7 +40,8 @@
 my $windows_include_path = "";
 if ($target_windows)
 {
-	$windows_include_path = "-I../../lib/win32 -I../../lib/common ";
+	$windows_include_path = "-I../../lib/win32 -I ../../lib/common " .
+		"-I../../lib/server ";
 	push @implicit_deps, "lib/win32";
 }
 else


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 19:45:59 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 18:45:59 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r656 - in box/chris/general/test: backupstore backupstorefix backupstorepatch basicserver bbackupd
Message-ID: <20060719184559.C6ADD96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 18:45:51 +0000 (Wed, 19 Jul 2006)
New Revision: 656

Modified:
   box/chris/general/test/backupstore/testbackupstore.cpp
   box/chris/general/test/backupstorefix/testbackupstorefix.cpp
   box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp
   box/chris/general/test/basicserver/testbasicserver.cpp
   box/chris/general/test/bbackupd/testbbackupd.cpp
Log:
* test/backupstore/testbackupstore.cpp
* test/backupstorepatch/testbackupstorepatch.cpp
* test/basicserver/testbasicserver.cpp
* test/backupstorefix/testbackupstorefix.cpp
* test/bbackupd/testbbackupd.cpp
- Include ServerControl.h in tests to give access to HupServer, KillServer


Modified: box/chris/general/test/backupstore/testbackupstore.cpp
===================================================================
--- box/chris/general/test/backupstore/testbackupstore.cpp	2006-07-19 18:44:28 UTC (rev 655)
+++ box/chris/general/test/backupstore/testbackupstore.cpp	2006-07-19 18:45:51 UTC (rev 656)
@@ -33,6 +33,7 @@
 #include "MemBlockStream.h"
 #include "BackupClientFileAttributes.h"
 #include "BackupClientCryptoKeys.h"
+#include "ServerControl.h"
 
 #include "MemLeakFindOn.h"
 

Modified: box/chris/general/test/backupstorefix/testbackupstorefix.cpp
===================================================================
--- box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-19 18:44:28 UTC (rev 655)
+++ box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-19 18:45:51 UTC (rev 656)
@@ -29,6 +29,7 @@
 #include "RaidFileException.h"
 #include "StoreStructure.h"
 #include "BackupStoreFileWire.h"
+#include "ServerControl.h"
 
 #include "MemLeakFindOn.h"
 

Modified: box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp
===================================================================
--- box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp	2006-07-19 18:44:28 UTC (rev 655)
+++ box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp	2006-07-19 18:45:51 UTC (rev 656)
@@ -35,6 +35,7 @@
 #include "MemBlockStream.h"
 #include "BackupClientFileAttributes.h"
 #include "BackupClientCryptoKeys.h"
+#include "ServerControl.h"
 
 #include "MemLeakFindOn.h"
 

Modified: box/chris/general/test/basicserver/testbasicserver.cpp
===================================================================
--- box/chris/general/test/basicserver/testbasicserver.cpp	2006-07-19 18:44:28 UTC (rev 655)
+++ box/chris/general/test/basicserver/testbasicserver.cpp	2006-07-19 18:45:51 UTC (rev 656)
@@ -28,10 +28,10 @@
 #include "TestContext.h"
 #include "autogen_TestProtocolClient.h"
 #include "autogen_TestProtocolServer.h"
+#include "ServerControl.h"
 
 #include "MemLeakFindOn.h"
 
-
 #define SERVER_LISTEN_PORT	2003
 
 // in ms

Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 18:44:28 UTC (rev 655)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-19 18:45:51 UTC (rev 656)
@@ -46,6 +46,7 @@
 #include "Utils.h"
 #include "BoxTime.h"
 #include "BoxTimeToUnix.h"
+#include "ServerControl.h"
 
 #include "MemLeakFindOn.h"
 


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 20:27:26 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 19:27:26 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r657 - box/chris/general/test/backupdiff
Message-ID: <20060719192726.0A65796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 19:27:24 +0000 (Wed, 19 Jul 2006)
New Revision: 657

Modified:
   box/chris/general/test/backupdiff/testbackupdiff.cpp
Log:
* testbackupdiff.cpp
- Increased timeout on Win32, will hopefully fix failing test (very slow
  on Windows)


Modified: box/chris/general/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-19 18:45:51 UTC (rev 656)
+++ box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-19 19:27:24 UTC (rev 657)
@@ -525,7 +525,12 @@
 			2000 /* object ID of the file diffing from */, blockindex, IOStream::TimeOutInfinite,
 			0, 0));
 		encoded->CopyStreamTo(out);
-		TEST_THAT(time(0) < (beginTime + 40));
+
+		#ifdef WIN32
+		TEST_THAT(time(0) < (beginTime + 160));
+		#else
+		TEST_THAT(time(0) < (beginTime + 80));
+		#endif
 	}
 	// Remove zero-files to save disk space
 	remove("testfiles/zero.0");


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 20:28:23 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 19:28:23 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r658 - box/chris/general/test/backupstorepatch
Message-ID: <20060719192823.97D6096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 19:28:20 +0000 (Wed, 19 Jul 2006)
New Revision: 658

Modified:
   box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp
Log:
* testbackupstorepatch.cpp
- Disabled memleak check on Win32 (again?) since KillServer does not
  give it a chance to write one.


Modified: box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp
===================================================================
--- box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp	2006-07-19 19:27:24 UTC (rev 657)
+++ box/chris/general/test/backupstorepatch/testbackupstorepatch.cpp	2006-07-19 19:28:20 UTC (rev 658)
@@ -640,7 +640,10 @@
 		// Kill store server
 		TEST_THAT(KillServer(pid));
 		TEST_THAT(!ServerIsAlive(pid));
+
+		#ifndef WIN32
 		TestRemoteProcessMemLeaks("bbstored.memleaks");
+		#endif
 	}
 	
 	::free(buffer);


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 20:29:15 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 19 Jul 2006 19:29:15 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r659 - box/chris/general/bin/bbackupctl
Message-ID: <20060719192915.AF82696@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-19 19:29:15 +0000 (Wed, 19 Jul 2006)
New Revision: 659

Modified:
   box/chris/general/bin/bbackupctl/bbackupctl.cpp
Log:
* bbackupctl.cpp
- Presumably in quiet mode, we don't want to see informational messages,
  so disabled them.


Modified: box/chris/general/bin/bbackupctl/bbackupctl.cpp
===================================================================
--- box/chris/general/bin/bbackupctl/bbackupctl.cpp	2006-07-19 19:28:20 UTC (rev 658)
+++ box/chris/general/bin/bbackupctl/bbackupctl.cpp	2006-07-19 19:29:15 UTC (rev 659)
@@ -292,12 +292,12 @@
 		{
 			if(line == "start-sync")
 			{
-				printf("Sync started...\n");
+				if (!quiet) printf("Sync started...\n");
 				syncIsRunning = true;
 			}
 			else if(line == "finish-sync" && syncIsRunning)
 			{
-				printf("Sync finished.\n");
+				if (!quiet) printf("Sync finished.\n");
 				// Send a quit command to finish nicely
 				connection.Write("quit\n", 5);
 				
@@ -306,7 +306,7 @@
 			}
 			else if(line == "finish-sync")
 			{
-				printf("Previous sync finished.\n");
+				if (!quiet) printf("Previous sync finished.\n");
 			}
 			// daemon must still be busy
 		}


From boxbackup-dev@fluffy.co.uk  Wed Jul 19 21:01:37 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Wed, 19 Jul 2006 13:01:37 -0700 (PDT)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <Pine.LNX.4.62.0607191905520.18881@top.qwarx.com>
Message-ID: <20060719200137.88484.qmail@web36701.mail.mud.yahoo.com>

Chris,

> then I agree, although I think more 
> open source projects use MinGW than use Visual Studio.

My main reason for this is the fact that I hate to debug under anything else - VS2K5 does make the
process easier.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Thu Jul 20 09:06:21 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Thu, 20 Jul 2006 09:06:21 +0100
Subject: [Box Backup-dev] COMMIT r655 - box/chris/general/infrastructure
In-Reply-To: <20060719184430.78BD796@s0g0.pems.testserver.co.uk>
References: <20060719184430.78BD796@s0g0.pems.testserver.co.uk>
Message-ID: <1F59B9F5-45CF-4E2F-881F-0B99640E9C5E@fluffy.co.uk>

On 19 Jul 2006, at 19:44, subversion@fluffy.co.uk wrote:

> Log:
> * makebuildenv.pl
> - Added lib/server to implicit includes to help tests find  
> ServerControl.h
>
>
> Modified: box/chris/general/infrastructure/makebuildenv.pl
> ===================================================================
> --- box/chris/general/infrastructure/makebuildenv.pl	2006-07-19  
> 18:43:52 UTC (rev 654)
> +++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-19  
> 18:44:28 UTC (rev 655)
> @@ -40,7 +40,8 @@
>  my $windows_include_path = "";
>  if ($target_windows)
>  {
> -	$windows_include_path = "-I../../lib/win32 -I../../lib/common ";
> +	$windows_include_path = "-I../../lib/win32 -I ../../lib/common " .
> +		"-I../../lib/server ";
>  	push @implicit_deps, "lib/win32";


Er? Shouldn't you be using modules.txt for dependency info? Or use  
the @implicit_deps array?

Random dependencies going all over the place is nasty. Is there a  
cleaner way to design this?

Ben






From boxbackup-dev@fluffy.co.uk  Thu Jul 20 21:15:29 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 20 Jul 2006 20:15:29 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r660 - box/chris/general/infrastructure
Message-ID: <20060720201529.AEF9496@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-20 20:15:21 +0000 (Thu, 20 Jul 2006)
New Revision: 660

Modified:
   box/chris/general/infrastructure/makebuildenv.pl
Log:
* makebuildenv.pl
- Changed the dependency hack to be a bit less hackish (still, the problem
  is that lib/common depends on lib/win32, and I don't think we can list
  implicit deps like lib/common in modules.txt)
- Avoid rebuilding executables and libraries unnecessarily when not
  using BSD make
- Code cleanups


Modified: box/chris/general/infrastructure/makebuildenv.pl
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl	2006-07-19 19:29:15 UTC (rev 659)
+++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-20 20:15:21 UTC (rev 660)
@@ -40,8 +40,7 @@
 my $windows_include_path = "";
 if ($target_windows)
 {
-	$windows_include_path = "-I../../lib/win32 -I ../../lib/common " .
-		"-I../../lib/server ";
+	$module_dependency{"lib/common"} = ["lib/win32"];
 	push @implicit_deps, "lib/win32";
 }
 else
@@ -382,7 +381,7 @@
 my %module_resources_win32;
 
 # Then write a makefile for each module
-for my $mod (@modules, @implicit_deps)
+for my $mod (@implicit_deps, @modules)
 {
 	print $mod,"\n";
 	
@@ -448,14 +447,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;
 			}
 		}
 	}	
@@ -685,8 +684,13 @@
 
 	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";
 	


From boxbackup-dev@fluffy.co.uk  Thu Jul 20 21:51:15 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 20 Jul 2006 20:51:15 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r661 - box/chris/general/test/backupdiff
Message-ID: <20060720205115.C029396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-20 20:51:14 +0000 (Thu, 20 Jul 2006)
New Revision: 661

Modified:
   box/chris/general/test/backupdiff/testbackupdiff.cpp
Log:
* testbackupdiff.cpp
- Disabled writing debug messages to the console during backupdiff test
  on Win32, since it's annoying and slow.
- Reduced timeout slightly now that the test finishes faster.


Modified: box/chris/general/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-20 20:15:21 UTC (rev 660)
+++ box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-20 20:51:14 UTC (rev 661)
@@ -371,8 +371,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();
@@ -526,8 +528,10 @@
 			0, 0));
 		encoded->CopyStreamTo(out);
 
+		printf("Time taken: %d seconds\n", time(0) - beginTime);
+
 		#ifdef WIN32
-		TEST_THAT(time(0) < (beginTime + 160));
+		TEST_THAT(time(0) < (beginTime + 120));
 		#else
 		TEST_THAT(time(0) < (beginTime + 80));
 		#endif


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 09:22:41 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Fri, 21 Jul 2006 09:22:41 +0100
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <20060719200137.88484.qmail@web36701.mail.mud.yahoo.com>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95016AF@toutatis.omn11s.local>

Hello Gary,Chris,

Sorry Chris, I am with Gary, the Microsoft devel environment (I use
2003) its toolset is pretty good for debugging, I can't comment on the
inteli-sense in 2005 but I work on 2003.=20

Also in my humble view, Microsoft wrote the compiler, libraries and OS,
so will they not work better together?

In fact I would go as far to say that in my days as an embedded software
engineer, we always wrote for Microsoft ide, then port to the platform
which would have much faster development cycles!

Just for your info, I want to look at

1. Large file support - verify it is all working
2. Bandwidth throttling, this is causing me lots of ongoing issues, I
know Ben's comment in the past is this should be done on the firewall,
which I have done, but there a two issues with this, a) we have users
without a good enough firewall and b) Linux firewalls I have not great
success with
3. Look at the possibility of Shadow Copy, it looks quite tricky so no
promises! But this looks much needed for the likes of backing up
Exchange
4. File change notification from either the NTFS change journal, or
ReadDirectoryChangesW to get notifies about changed files instead of
polling

The problem without shadow copy and trying to backup exchange (or
similar - point 3 shadow copy) is you have to back an intermediary file
using ntbackup - or just pulling out the database with exchange
shutdown, but the problem with this is the id of the file changes so I
believe box treats it as a new file so doesn't even try to diff??

Regards

Nick



-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of G.
Sent: 19 July 2006 21:02
To: boxbackup-dev@fluffy.co.uk
Subject: RE: [Box Backup-dev] Hello all - win32 client

Chris,

> then I agree, although I think more=20
> open source projects use MinGW than use Visual Studio.

My main reason for this is the fact that I hate to debug under anything
else - VS2K5 does make the
process easier.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Fri Jul 21 09:32:01 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Fri, 21 Jul 2006 09:32:01 +0100 (BST)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F95016AF@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F95016AF@toutatis.omn11s.local>
Message-ID: <Pine.LNX.4.62.0607210927010.18881@top.qwarx.com>

Hi Nick,

> Sorry Chris, I am with Gary, the Microsoft devel environment (I use
> 2003) its toolset is pretty good for debugging, I can't comment on the
> inteli-sense in 2005 but I work on 2003.

Sorry Nick, I am with GCC, because I can distribute the resulting 
binaries. If I developed with Visual Studio and then distributed untested 
MinGW binaries, what would happen? :-)

> Also in my humble view, Microsoft wrote the compiler, libraries and OS,
> so will they not work better together?

But they did not write Box Backup, so perhaps they will not work well 
together? ;-)

Box has always been developed (on other platforms) using gcc.

> In fact I would go as far to say that in my days as an embedded software
> engineer, we always wrote for Microsoft ide, then port to the platform
> which would have much faster development cycles!

> 1. Large file support - verify it is all working

It definitely is not. The POSIX APIs used by Box on Windows do not support 
files over 2 GB, because they don't have a 64-bit file offset.

The problem, unfortunately, is to replace ALL the POSIX APIs with emulated 
replacements using the Windows APi. That will not be easy.

> 3. Look at the possibility of Shadow Copy, it looks quite tricky so no
> promises! But this looks much needed for the likes of backing up
> Exchange

This will be the first major problem for MinGW - the VSS API is cl

> The problem without shadow copy and trying to backup exchange (or
> similar - point 3 shadow copy) is you have to back an intermediary file
> using ntbackup - or just pulling out the database with exchange
> shutdown, but the problem with this is the id of the file changes so I
> believe box treats it as a new file so doesn't even try to diff??

Box will try to diff if a file is replaced by another with the same name, 
as well as the contents of a file changing. As far as I know, the ID is 
only used to track renamed files.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 09:39:48 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Fri, 21 Jul 2006 09:39:48 +0100
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <Pine.LNX.4.62.0607210927010.18881@top.qwarx.com>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95016B4@toutatis.omn11s.local>

Hello Chris,

This is probably leads to the need for support two platforms! You can't
remove personal opinion! Not sure why you cannot distribute binaries
produced by MSVC?

In this day and age 2GB files are not uncommon, so it needs doing - I
will have a look and assess it.

Still trying to compile though and it barfs on no BoxVersion.h, where is
this supposed to be or got from.

Thanks

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Chris Wilson
Sent: 21 July 2006 09:32
To: boxbackup-dev@fluffy.co.uk
Subject: RE: [Box Backup-dev] Hello all - win32 client

Hi Nick,

> Sorry Chris, I am with Gary, the Microsoft devel environment (I use
> 2003) its toolset is pretty good for debugging, I can't comment on the
> inteli-sense in 2005 but I work on 2003.

Sorry Nick, I am with GCC, because I can distribute the resulting=20
binaries. If I developed with Visual Studio and then distributed
untested=20
MinGW binaries, what would happen? :-)

> Also in my humble view, Microsoft wrote the compiler, libraries and
OS,
> so will they not work better together?

But they did not write Box Backup, so perhaps they will not work well=20
together? ;-)

Box has always been developed (on other platforms) using gcc.

> In fact I would go as far to say that in my days as an embedded
software
> engineer, we always wrote for Microsoft ide, then port to the platform
> which would have much faster development cycles!

> 1. Large file support - verify it is all working

It definitely is not. The POSIX APIs used by Box on Windows do not
support=20
files over 2 GB, because they don't have a 64-bit file offset.

The problem, unfortunately, is to replace ALL the POSIX APIs with
emulated=20
replacements using the Windows APi. That will not be easy.

> 3. Look at the possibility of Shadow Copy, it looks quite tricky so no
> promises! But this looks much needed for the likes of backing up
> Exchange

This will be the first major problem for MinGW - the VSS API is cl

> The problem without shadow copy and trying to backup exchange (or
> similar - point 3 shadow copy) is you have to back an intermediary
file
> using ntbackup - or just pulling out the database with exchange
> shutdown, but the problem with this is the id of the file changes so I
> believe box treats it as a new file so doesn't even try to diff??

Box will try to diff if a file is replaced by another with the same
name,=20
as well as the contents of a file changing. As far as I know, the ID is=20
only used to track renamed files.

Cheers, Chris.
--=20
_ ___ __     _
  / __/ / ,__(_)_  | 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 |

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Fri Jul 21 09:42:00 2006
From: boxbackup-dev@fluffy.co.uk (Stuart Sanders)
Date: Fri, 21 Jul 2006 16:42:00 +0800
Subject: [Box Backup-dev] Hello all - win32 client
Message-ID: <MDAEMON-F200607211645.AA4532312md50000001219@bitshk.com>

> -----Original Message-----
> The problem without shadow copy and trying to backup exchange (or
> similar - point 3 shadow copy) is you have to back an=20
> intermediary file
> using ntbackup - or just pulling out the database with exchange
> shutdown, but the problem with this is the id of the file changes so I
> believe box treats it as a new file so doesn't even try to diff??

Hi, I'm newish to the list, and getting BB to work with VSS was one of the =
things that interested me.  I didn't plan on attempting it immediately sinc=
e the first plan was to familiarise myself with the project and some core c=
ode areas, and perhaps to a more important extent, refamiliarisation to C++=
 which I haven't looked at for far too many years.

In anycase, the reason for this email is that I've been exploring backup so=
lutions for a while, and one of the things I ran across a while ago was a c=
omment on how to get rsync working with VSS.  This isn't an ideal solution,=
 nor would I consider it a long term solution, but it might meet some peopl=
es needs *right now*.

http://www.itefix.no/phpws/index.php?module=3Dfaq&FAQ_op=3Dview&FAQ_id=3D81

Stuart

----------------------------------------------------
Extract:
----------------------------------------------------

Can cwrsync copy files in use ?

A: =09NB! The recipe below applies to Windows 2003 Server only.

I recently had the issue of running rsync to backup up files that are "in u=
se". A good example was backing up documents and settings and the ntuser.da=
t file would always fail.along with several other system locked files.

Resolution was to download the VSS SDK from Microsoft's web site. The SDK h=
as an executable vshadow.exe which will allow you to create volume shadow c=
opies that are mapped to a drive, allowing rsync to use the VSS drive where=
 no files are locked.

An example command set would be:

rem create a permanent shadow copy
vshadow.exe -p -nw -script=3Dvars.bat
call vars.bat
rem drive H: is assigned to the permanent shadow copy created
vshadow.exe -el=3D%SHADOW_ID_1%,H:
rem perform your rsync operation, use drive H: (shadow drive) as source
rsync.exe -ruztiv '/cygdrive/h/xxxxxxx' myrsyncserver::myrsyncuser
rem remove the permanent shadow copy
vshadow.exe -ds=3D%SHADOW_ID_1%

-- Contributed by Rob Bosch

You may also visit this link for more detailed information.


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 09:49:00 2006
From: boxbackup-dev@fluffy.co.uk (Stuart Sanders)
Date: Fri, 21 Jul 2006 16:49:00 +0800
Subject: [Box Backup-dev] Hello all - win32 client
Message-ID: <MDAEMON-F200607211649.AA4908703md50000001226@bitshk.com>

The "free" version of VS 2005 (ie VS Express) has a non-distributable licen=
se.

So to legally distribute anything he compiles he would need to pay for Visu=
al Studio.

Stuart

> -----Original Message-----
> From: boxbackup-dev-admin@fluffy.co.uk=20
> [mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Nick Knight
> Sent: Friday, 21 July 2006 4:40 PM
> To: boxbackup-dev@fluffy.co.uk
> Subject: RE: [Box Backup-dev] Hello all - win32 client
>=20
>=20
> Hello Chris,
>=20
> This is probably leads to the need for support two platforms!=20
> You can't
> remove personal opinion! Not sure why you cannot distribute binaries
> produced by MSVC?
>=20
> In this day and age 2GB files are not uncommon, so it needs doing - I
> will have a look and assess it.
>=20
> Still trying to compile though and it barfs on no=20
> BoxVersion.h, where is
> this supposed to be or got from.
>=20
> Thanks
>=20
> Nick
>=20
> -----Original Message-----
> From: boxbackup-dev-admin@fluffy.co.uk
> [mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Chris Wilson
> Sent: 21 July 2006 09:32
> To: boxbackup-dev@fluffy.co.uk
> Subject: RE: [Box Backup-dev] Hello all - win32 client
>=20
> Hi Nick,
>=20
> > Sorry Chris, I am with Gary, the Microsoft devel environment (I use
> > 2003) its toolset is pretty good for debugging, I can't=20
> comment on the
> > inteli-sense in 2005 but I work on 2003.
>=20
> Sorry Nick, I am with GCC, because I can distribute the resulting=20
> binaries. If I developed with Visual Studio and then distributed
> untested=20
> MinGW binaries, what would happen? :-)
>=20
> > Also in my humble view, Microsoft wrote the compiler, libraries and
> OS,
> > so will they not work better together?
>=20
> But they did not write Box Backup, so perhaps they will not work well=20
> together? ;-)
>=20
> Box has always been developed (on other platforms) using gcc.
>=20
> > In fact I would go as far to say that in my days as an embedded
> software
> > engineer, we always wrote for Microsoft ide, then port to=20
> the platform
> > which would have much faster development cycles!
>=20
> > 1. Large file support - verify it is all working
>=20
> It definitely is not. The POSIX APIs used by Box on Windows do not
> support=20
> files over 2 GB, because they don't have a 64-bit file offset.
>=20
> The problem, unfortunately, is to replace ALL the POSIX APIs with
> emulated=20
> replacements using the Windows APi. That will not be easy.
>=20
> > 3. Look at the possibility of Shadow Copy, it looks quite=20
> tricky so no
> > promises! But this looks much needed for the likes of backing up
> > Exchange
>=20
> This will be the first major problem for MinGW - the VSS API is cl
>=20
> > The problem without shadow copy and trying to backup exchange (or
> > similar - point 3 shadow copy) is you have to back an intermediary
> file
> > using ntbackup - or just pulling out the database with exchange
> > shutdown, but the problem with this is the id of the file=20
> changes so I
> > believe box treats it as a new file so doesn't even try to diff??
>=20
> Box will try to diff if a file is replaced by another with the same
> name,=20
> as well as the contents of a file changing. As far as I know,=20
> the ID is=20
> only used to track renamed files.
>=20
> Cheers, Chris.
> --=20
> _ ___ __     _
>   / __/ / ,__(_)_  | 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 |
>=20
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
> 


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 13:03:12 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Fri, 21 Jul 2006 13:03:12 +0100
Subject: [Box Backup-dev] building on win32
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95016D9@toutatis.omn11s.local>

Hello Chris/all,

Couple of issues whilst trying to build.=20

In the version 10 download win32.bat doesn't exist.
Whilst running win32.bat I get (on Chris's latest SVN version)

$ ./win32.bat
quick and dirty to get up and running by generating the required files
using Cygwin and Perl
Creating built-in documentation for bbackupquery...
Generating BackupStore exception...
Can't locate BoxPlatform.pm in @INC (@INC contains: ../../infrastructure
/usr/li
b/perl5/5.8/cygwin /usr/lib/perl5/5.8
/usr/lib/perl5/site_perl/5.8/cygwin /usr/l
ib/perl5/site_perl/5.8 /usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vend
or_perl/5.8 .) at ./../../lib/server/makeprotocol.pl line 5.
BEGIN failed--compilation aborted at ./../../lib/server/makeprotocol.pl
line 5.
Generating Compress exception...
Generating Common exception...
Generating Conversion exception...
Generating Cipher exception...
server parts - which appears as though some of the clients rely on
Generating Server exception...
Generating Connection exception...
The system cannot find the file specified.

This is leading onto some compile errors. I have tried cygwin and active
perl from the command line, and the same happens.

In Chris's version, boxversion.h doesn't exist.

Help!

Nick

From boxbackup-dev@fluffy.co.uk  Fri Jul 21 13:08:31 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Fri, 21 Jul 2006 05:08:31 -0700 (PDT)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F95016AF@toutatis.omn11s.local>
Message-ID: <20060721120831.5715.qmail@web36701.mail.mud.yahoo.com>

Nick,

> In fact I would go as far to say that in my days as an embedded software
> engineer, we always wrote for Microsoft ide, then port to the platform
> which would have much faster development cycles!

We did exactly the same thing in my commercial UN*X development :).

> 3. Look at the possibility of Shadow Copy, it looks quite tricky so no
> promises! But this looks much needed for the likes of backing up
> Exchange

Yes, Shadow Copy is the only way to safely backup Exchange, SQL Server, and the like.

> 4. File change notification from either the NTFS change journal, or
> ReadDirectoryChangesW to get notifies about changed files instead of
> polling

Nice.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Fri Jul 21 19:16:04 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Fri, 21 Jul 2006 19:16:04 +0100 (BST)
Subject: [Box Backup-dev] Hello all - win32 client
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F95016B4@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F95016B4@toutatis.omn11s.local>
Message-ID: <Pine.LNX.4.62.0607211909430.18881@top.qwarx.com>

Hi Nick,

> This is probably leads to the need for support two platforms! You can't
> remove personal opinion! Not sure why you cannot distribute binaries
> produced by MSVC?

Because of the redistributable nightmare with managed assemblies. Users 
need to install vc_redist.exe, which is not distributed with VS2005 and 
not officially available for download from Microsoft, and it's not clear 
whether it can be used with open source software at all. Certainly not 
with GPL software, including Boxi, which means that in any case I will 
need to use GCC for Boxi, and that means that Box has to compile and work 
with GCC for me.

Also, the redistributable is huge (8 MB if I remember rightly) and also 
requires the .NET runtime to be installed, which is even bigger.

If others wish to help by providing patches for VC support, then I'll 
happily apply them. If others wish to distribute VC binaries, then they 
are more than welcome to do so, but I will not.

> In this day and age 2GB files are not uncommon, so it needs doing - I
> will have a look and assess it.

Please do, and let me know. It seems that lib/common/FileStream.cpp 
already uses Win32 APIs rather than POSIX, so maybe it does work in 
theory, but users have definitely reported problems (see the Known Bugs 
page).

> Still trying to compile though and it barfs on no BoxVersion.h, where is 
> this supposed to be or got from.

Run getversion.pl in infrastructure/msvc. I made this run automatically 
from a build event in the VS2005 project files, but I have no idea how to 
make this happen on VS2003. If you can fix the project files to run it 
automatically, please send me a patch.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 19:25:37 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Fri, 21 Jul 2006 18:25:37 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r662 - box/chris/general
Message-ID: <20060721182537.2174096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-21 18:25:34 +0000 (Fri, 21 Jul 2006)
New Revision: 662

Modified:
   box/chris/general/win32.bat
Log:
* win32.bat
- Quick hack to fix building on Win32 without Cygwin (hopefully), now that
  BoxPlatform.pm is supposed to be generated by configure


Modified: box/chris/general/win32.bat
===================================================================
--- box/chris/general/win32.bat	2006-07-20 20:51:14 UTC (rev 661)
+++ box/chris/general/win32.bat	2006-07-21 18:25:34 UTC (rev 662)
@@ -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 ..\..\
 


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 19:33:53 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Fri, 21 Jul 2006 19:33:53 +0100 (BST)
Subject: [Box Backup-dev] building on win32
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F95016D9@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F95016D9@toutatis.omn11s.local>
Message-ID: <Pine.LNX.4.62.0607211931560.18881@top.qwarx.com>

Hi Nick,

> Couple of issues whilst trying to build.
>
> In the version 10 download win32.bat doesn't exist.
> Whilst running win32.bat I get (on Chris's latest SVN version)
>
> $ ./win32.bat
> quick and dirty to get up and running by generating the required files
> using Cygwin and Perl
> Creating built-in documentation for bbackupquery...
> Generating BackupStore exception...
> Can't locate BoxPlatform.pm in @INC (@INC contains: ../../infrastructure
> /usr/lib/perl5/5.8/cygwin /usr/lib/perl5/5.8
> /usr/lib/perl5/site_perl/5.8/cygwin /usr/lib/perl5/site_perl/5.8
> /usr/lib/perl5/vendor_perl/5.8/cygwin /usr/lib/perl5/vendor_perl/5.8 .)
> at ./../../lib/server/makeprotocol.pl line 5.
> BEGIN failed--compilation aborted at ./../../lib/server/makeprotocol.pl
> line 5.

Sorry about that. I forgot to update win32.bat when applying the changes 
from trunk, that changed BoxPlatform.pm from a distributed file to one 
auto-generated by configure.

Please could you svn update and try running it again?

> In Chris's version, boxversion.h doesn't exist.

You need to run infrastructure/msvc/getversion.pl.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Fri Jul 21 22:29:16 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Fri, 21 Jul 2006 22:29:16 +0100
Subject: [Box Backup-dev] building on win32
In-Reply-To: <Pine.LNX.4.62.0607211931560.18881@top.qwarx.com>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501722@toutatis.omn11s.local>

Hello Chris,

I have some of the >2GB stuff working, I think it may have worked and
got broken somewhere. It appears that stat on linux and probably other
platforms support filesize of > 2GB, but under windoze the posix
implementation is < 2GB only.

Although the functions where there to use emu_stat and so on, it was
using the MS structure to store information. Box itself has enough space
for the size it was just returning it from stat.

Got it using its own version now and it backed up ok.

Compare -aq now barfs so I will look at that as well.

Rather interesting behaviour to watch out for, it backed up a large file
- or part of it when it had the numbers wrong, and when you do a compare
-aq it comes back quite happy, I suppose the same dodgy file size was
being generated in both.

When I did the distribution from MSVC 2003 the whole installer was only
around 900k, so not sure where you get the 8M from, but I haven't looked
at 2005 yet, I still don't think it has been around long enough yet.

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Chris Wilson
Sent: 21 July 2006 19:34
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] building on win32

Hi Nick,

> Couple of issues whilst trying to build.
>
> In the version 10 download win32.bat doesn't exist.
> Whilst running win32.bat I get (on Chris's latest SVN version)
>
> $ ./win32.bat
> quick and dirty to get up and running by generating the required files
> using Cygwin and Perl
> Creating built-in documentation for bbackupquery...
> Generating BackupStore exception...
> Can't locate BoxPlatform.pm in @INC (@INC contains:
../../infrastructure
> /usr/lib/perl5/5.8/cygwin /usr/lib/perl5/5.8
> /usr/lib/perl5/site_perl/5.8/cygwin /usr/lib/perl5/site_perl/5.8
> /usr/lib/perl5/vendor_perl/5.8/cygwin /usr/lib/perl5/vendor_perl/5.8
.)
> at ./../../lib/server/makeprotocol.pl line 5.
> BEGIN failed--compilation aborted at
./../../lib/server/makeprotocol.pl
> line 5.

Sorry about that. I forgot to update win32.bat when applying the changes

from trunk, that changed BoxPlatform.pm from a distributed file to one=20
auto-generated by configure.

Please could you svn update and try running it again?

> In Chris's version, boxversion.h doesn't exist.

You need to run infrastructure/msvc/getversion.pl.

Cheers, Chris.
--=20
_ ___ __     _
  / __/ / ,__(_)_  | 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 |

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Fri Jul 21 22:47:13 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Fri, 21 Jul 2006 22:47:13 +0100 (BST)
Subject: [Box Backup-dev] building on win32
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501722@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F9501722@toutatis.omn11s.local>
Message-ID: <Pine.LNX.4.62.0607212245450.18881@top.qwarx.com>

Hi Nick,

On Fri, 21 Jul 2006, Nick Knight wrote:

> When I did the distribution from MSVC 2003 the whole installer was only 
> around 900k, so not sure where you get the 8M from, but I haven't looked 
> at 2005 yet, I still don't think it has been around long enough yet.

Does that include the size of the redistributable component with 
msvcr70.dll, or were you assuming that that file would already be present 
on the machine where Box would be installed?

mscvr80.dll is not present on most Windows machines (yet), so the 
redistributable is required... and it's huge.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Sat Jul 22 15:50:36 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Sat, 22 Jul 2006 15:50:36 +0100
Subject: [Box Backup-dev] building on win32
In-Reply-To: <Pine.LNX.4.62.0607212245450.18881@top.qwarx.com>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501723@toutatis.omn11s.local>

Can't remember from memory I would have to check out the script I wrote
which I haven't here at the mo. I know it would install on a clean
windows 2000 though.

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Chris Wilson
Sent: 21 July 2006 22:47
To: boxbackup-dev@fluffy.co.uk
Subject: RE: [Box Backup-dev] building on win32

Hi Nick,

On Fri, 21 Jul 2006, Nick Knight wrote:

> When I did the distribution from MSVC 2003 the whole installer was
only=20
> around 900k, so not sure where you get the 8M from, but I haven't
looked=20
> at 2005 yet, I still don't think it has been around long enough yet.

Does that include the size of the redistributable component with=20
msvcr70.dll, or were you assuming that that file would already be
present=20
on the machine where Box would be installed?

mscvr80.dll is not present on most Windows machines (yet), so the=20
redistributable is required... and it's huge.

Cheers, Chris.
--=20
_ ___ __     _
  / __/ / ,__(_)_  | 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 |

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Sat Jul 22 18:54:41 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 17:54:41 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r663 - box/chris/general/bin/bbackupquery
Message-ID: <20060722175441.D8FA996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 17:54:39 +0000 (Sat, 22 Jul 2006)
New Revision: 663

Modified:
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
Log:
* BackupQueries.cpp
- Force the "running as root" flag to true on Windows, rather than trying
  to call geteuid(); this allows us to remove the geteuid() stub from emu.h


Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-21 18:25:34 UTC (rev 662)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-22 17:54:39 UTC (rev 663)
@@ -69,7 +69,11 @@
 	  mWarnedAboutOwnerAttributes(false),
 	  mReturnCode(0)		// default return code
 {
+	#ifdef WIN32
+	mRunningAsRoot = TRUE;
+	#else
 	mRunningAsRoot = (::geteuid() == 0);
+	#endif
 }
 
 // --------------------------------------------------------------------------


From boxbackup-dev@fluffy.co.uk  Sat Jul 22 18:54:49 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 17:54:49 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r664 - box/chris/general
Message-ID: <20060722175449.091EA96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 17:54:46 +0000 (Sat, 22 Jul 2006)
New Revision: 664

Modified:
   box/chris/general/runtest.pl
Log:
* runtest.pl
- Allow running any selected set of tests in any order
- Return an exit code that indicates whether all tests passed, or not


Modified: box/chris/general/runtest.pl
===================================================================
--- box/chris/general/runtest.pl	2006-07-22 17:54:39 UTC (rev 663)
+++ box/chris/general/runtest.pl	2006-07-22 17:54:46 UTC (rev 664)
@@ -17,15 +17,26 @@
 Mode defaults to debug.
 
 __E
-	exit(0);
+	exit(2);
 }
 
 my @results;
+my $exitcode = 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 +68,8 @@
 # report results
 print "--------\n",join("\n",@results),"\n";
 
+exit $exit_code;
+
 sub runtest
 {
 	my ($t) = @_;
@@ -67,6 +80,7 @@
 	if($make_res != 0)
 	{
 		push @results,"$t: make failed";
+		$exit_code = 2;
 		return;
 	}
 	
@@ -82,8 +96,14 @@
 			$last = $_ if m/\w/;
 		}
 		close RESULTS;
+
 		chomp $last;
 		push @results,"$t: $last";
+
+		if ($last ne "PASSED") 
+		{ 
+			$result = 1;
+		}
 	}
 	else
 	{


From boxbackup-dev@fluffy.co.uk  Sat Jul 22 20:20:08 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Sat, 22 Jul 2006 20:20:08 +0100
Subject: [Box Backup-dev] bug in box query
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501724@toutatis.omn11s.local>

Hello all,

I am not fully aware of how the blocks work in box, so I have done a
little fix because running a compare on a 5GB file was causing problems.
I have added the following to BackupStoreFile.cpp

bool BackupStoreFile::CompareFileContentsAgainstBlockIndex(const char
*Filename, IOStream &rBlockIndex, int Timeout)
{
.....


			if(sectionSize !=3D sizeof(entryEnc))
			{
				THROW_EXCEPTION(BackupStoreException,
BlockEntryEncodingDidntGiveExpectedLength)
			}

			// Size of block
			int32_t blockClearSize =3D ntohl(entryEnc.mSize);
			//BUG - Nick Knight 22-07-2006
			//if(blockClearSize < 0 || blockClearSize >
(BACKUP_FILE_MAX_BLOCK_SIZE + 1024))
			//Question from nick, if you look at the
algorithm to calculate block size, then
			//as it doubles every iteration of a while loop
and the check to get out is=20
			//if it is bigger then theoretically it can be
double this figure...
			if(blockClearSize < 0 || blockClearSize >
(BACKUP_FILE_MAX_BLOCK_SIZE * 2))
			{
				THROW_EXCEPTION(BackupStoreException,
BadBackupStoreFile)
			}
			totalSizeInBlockIndex +=3D blockClearSize;

			// Make sure there's enough memory allocated to
load the block in
			if(dataSize < blockClearSize)


Is what I have changed correct??

Thanks

Nick

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:17:58 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:17:58 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r665 - box/chris/general/lib/common
Message-ID: <20060722231758.2B1BE96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:17:52 +0000 (Sat, 22 Jul 2006)
New Revision: 665

Modified:
   box/chris/general/lib/common/Test.h
Log:
* Test.h
- Removed the message about expected exceptions, since they're not printed
  in release mode.
- Moved ServerIsAlive() up in the file, so that LaunchServer() can call it
- Made LaunchServer() wait for server to start, show progress, and check 
  that it doesn't die before writing PID file (Win32 only) 
- Moved terminate_bbackupd from test/bbackupd, since test/backupdiff needs
  it as well (under Win32)


Modified: box/chris/general/lib/common/Test.h
===================================================================
--- box/chris/general/lib/common/Test.h	2006-07-22 17:54:46 UTC (rev 664)
+++ box/chris/general/lib/common/Test.h	2006-07-22 23:17:52 UTC (rev 665)
@@ -44,8 +44,6 @@
 // NOTE: The 0- bit is to allow this to work with stuff which has negative constants for flags (eg ConnectionException)
 #define TEST_CHECK_THROWS(statement, excepttype, subtype)									\
 	{																						\
-		printf("[Test] Expect an exception below: (" \
-			#excepttype "/" #subtype ")\n"); \
 		bool didthrow = false;																\
 		try																					\
 		{																					\
@@ -93,6 +91,31 @@
 	return -1;
 }
 
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+inline bool ServerIsAlive(int pid)
+{
+#ifdef WIN32
+	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid);
+	if (hProcess == NULL)
+	{
+		if (GetLastError() != ERROR_INVALID_PARAMETER)
+		{
+			printf("Failed to open process %d: error %d\n",
+				pid, (int)GetLastError());
+		}
+		return false;
+	}
+	CloseHandle(hProcess);
+	return true;
+#else // !WIN32
+	if(pid == 0) return false;
+	return ::kill(pid, 0) != -1;
+#endif // WIN32
+}
+
 inline int LaunchServer(const char *CommandLine, const char *pidFile)
 {
 #ifdef WIN32
@@ -154,16 +177,40 @@
 	{
 #endif
 	// time for it to start up
-	::sleep(1);
-	
-	// read pid file
-	if(!TestFileExists(pidFile))
+	::fprintf(stdout, "Starting server: %s\n", CommandLine);
+	::fprintf(stdout, "Waiting for server to start: ");
+
+	for (int i = 0; i < 5; i++)
 	{
-		printf("Server: %s\n", CommandLine);
+		if (TestFileExists(pidFile))	
+			break;
+		if (!ServerIsAlive((int)procInfo.dwProcessId))
+			break;
+		::fprintf(stdout, ".");
+		::fflush(stdout);
+		::sleep(1);
+	}
+
+	#ifdef WIN32
+	if (!ServerIsAlive((int)procInfo.dwProcessId))
+	{
+		::fprintf(stdout, "server died!\n");
+		TEST_FAIL_WITH_MESSAGE("Server died!");	
+		return -1;
+	}
+	else 
+	#endif
+	if (!TestFileExists(pidFile))
+	{
+		::fprintf(stdout, "timed out!\n");
 		TEST_FAIL_WITH_MESSAGE("Server didn't save PID file");	
 		return -1;
 	}
-	
+	else
+	{
+		::fprintf(stdout, "done.\n");
+	}
+
 	FILE *f = fopen(pidFile, "r");
 	if(f == NULL || fscanf(f, "%d", &pid) != 1)
 	{
@@ -188,31 +235,6 @@
 	return pid;
 }
 
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-inline bool ServerIsAlive(int pid)
-{
-#ifdef WIN32
-	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid);
-	if (hProcess == NULL)
-	{
-		if (GetLastError() != ERROR_INVALID_PARAMETER)
-		{
-			printf("Failed to open process %d: error %d\n",
-				pid, (int)GetLastError());
-		}
-		return false;
-	}
-	CloseHandle(hProcess);
-	return true;
-#else // !WIN32
-	if(pid == 0) return false;
-	return ::kill(pid, 0) != -1;
-#endif // WIN32
-}
-
 inline void TestRemoteProcessMemLeaks(const char *filename)
 {
 #ifdef BOX_MEMORY_LEAK_TESTING
@@ -245,6 +267,35 @@
 #endif
 }
 
+#ifdef WIN32
+#define BBACKUPCTL "..\\..\\bin\\bbackupctl\\bbackupctl"
+#define BBACKUPQUERY "..\\..\\bin\\bbackupquery\\bbackupquery.exe"
+#define TEST_RETURN(actual, expected) TEST_THAT(actual == expected);
+#else
+#define BBACKUPCTL "../../bin/bbackupctl/bbackupctl"
+#define BBACKUPQUERY "../../bin/bbackupquery/bbackupquery"
+#define TEST_RETURN(actual, expected) TEST_THAT(actual == expected*256);
+#endif
+
+inline void terminate_bbackupd(int pid)
+{
+	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+		"terminate") == 0);
+	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+
+	for (int i = 0; i < 20; i++)
+	{
+		if (!ServerIsAlive(pid)) break;
+		fprintf(stdout, ".");
+		fflush(stdout);
+		sleep(1);
+	}
+
+	TEST_THAT(!ServerIsAlive(pid));
+	TestRemoteProcessMemLeaks("bbackupd.memleaks");
+}
+
+
 // Wait a given number of seconds for something to complete
 inline void wait_for_operation(int seconds)
 {


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:18:54 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:18:54 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r666 - box/chris/general/lib/backupclient
Message-ID: <20060722231854.E077296@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:18:49 +0000 (Sat, 22 Jul 2006)
New Revision: 666

Modified:
   box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp
Log:
* BackupClientFileAttributes.cpp
- Disabled Unix code under Win32, avoid the only other call to geteuid()


Modified: box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp	2006-07-22 23:17:52 UTC (rev 665)
+++ box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp	2006-07-22 23:18:49 UTC (rev 666)
@@ -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())
 	{


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:20:07 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:20:07 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r667 - box/chris/general/lib/win32
Message-ID: <20060722232007.259F996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:20:01 +0000 (Sat, 22 Jul 2006)
New Revision: 667

Modified:
   box/chris/general/lib/win32/emu.h
Log:
* emu.h
- Removed dependency on lib/common/Box.h (since lib/common now depends on
  lib/win32)


Modified: box/chris/general/lib/win32/emu.h
===================================================================
--- box/chris/general/lib/win32/emu.h	2006-07-22 23:18:49 UTC (rev 666)
+++ box/chris/general/lib/win32/emu.h	2006-07-22 23:20:01 UTC (rev 667)
@@ -5,6 +5,12 @@
 
 #define _INO_T_DEFINED
 
+#define WIN32_LEAN_AND_MEAN
+
+#ifndef __MSVCRT_VERSION__
+#define __MSVCRT_VERSION__ 0x0601
+#endif
+
 #include <winsock2.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -36,22 +42,18 @@
 #define fileno(struct_file)   _fileno(struct_file)
 #endif
 
+typedef uint32_t u_int32_t;
+
 int SetTimerHandler(void (__cdecl *func ) (int));
 int setitimer(int type, struct itimerval *timeout, void *arg);
 void InitTimer(void);
 void FiniTimer(void);
 
-inline int geteuid(void)
-{
-	//lets pretend to be root!
-	return 0;
-}
-
 struct passwd {
 	char *pw_name;
 	char *pw_passwd;
-	uid_t pw_uid;
-	gid_t pw_gid;
+	int pw_uid;
+	int pw_gid;
 	time_t pw_change;
 	char *pw_class;
 	char *pw_gecos;


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:21:03 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:21:03 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r668 - box/chris/general/lib/win32
Message-ID: <20060722232103.E789396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:20:56 +0000 (Sat, 22 Jul 2006)
New Revision: 668

Modified:
   box/chris/general/lib/win32/emu.cpp
Log:
* emu.cpp
- Removed dependency on lib/common/Box.h (now that lib/common depends on
  lib/win32)


Modified: box/chris/general/lib/win32/emu.cpp
===================================================================
--- box/chris/general/lib/win32/emu.cpp	2006-07-22 23:20:01 UTC (rev 667)
+++ box/chris/general/lib/win32/emu.cpp	2006-07-22 23:20:56 UTC (rev 668)
@@ -3,7 +3,7 @@
 // Need at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW
 #define WINVER 0x0500
 
-#include "Box.h"
+#include "emu.h"
 
 #ifdef WIN32
 
@@ -11,12 +11,10 @@
 #include <fcntl.h>
 #include <windows.h>
 
-#ifdef HAVE_UNISTD_H
+#ifdef __MINGW32__
 	#include <unistd.h>
 #endif
-#ifdef HAVE_PROCESS_H
-	#include <process.h>
-#endif
+#include <process.h>
 
 #include <string>
 #include <list>
@@ -806,7 +804,7 @@
 	_ui64toa(fi.dwVolumeSerialNumber, s->f_mntonname + 1, 16);
 
 	// pseudo unix mount point
-	s->f_mntonname[0] = DIRECTORY_SEPARATOR_ASCHAR;
+	s->f_mntonname[0] = '\\';
 
 	CloseHandle(handle);   // close the handle
 


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:21:42 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:21:42 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r669 - box/chris/general/infrastructure
Message-ID: <20060722232142.157F596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:21:35 +0000 (Sat, 22 Jul 2006)
New Revision: 669

Modified:
   box/chris/general/infrastructure/BoxPlatform.pm.in
Log:
* BoxPlatform.pm.in
- Replaced call to non-standard 'uname -p' with 'uname -m'


Modified: box/chris/general/infrastructure/BoxPlatform.pm.in
===================================================================
--- box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-22 23:20:56 UTC (rev 668)
+++ box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-22 23:21:35 UTC (rev 669)
@@ -21,7 +21,7 @@
 	{
 		$build_os = `uname`;
 		chomp $build_os;
-		$build_cpu = `uname -p`;
+		$build_cpu = `uname -m`;
 		chomp $build_cpu;
 	}
 


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:23:12 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:23:12 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r670 - box/chris/general/test/backupdiff
Message-ID: <20060722232312.BBA8796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:23:08 +0000 (Sat, 22 Jul 2006)
New Revision: 670

Modified:
   box/chris/general/test/backupdiff/testbackupdiff.cpp
Log:
* testbackupdiff.cpp
- Use truncate(), or equivalent code under Win32, to create large files
  full of zeroes without a long delay and without using heaps of disk space.


Modified: box/chris/general/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-22 23:21:35 UTC (rev 669)
+++ box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-22 23:23:08 UTC (rev 670)
@@ -66,11 +66,24 @@
 
 void make_file_of_zeros(const char *filename, size_t size)
 {
+	#ifdef WIN32
+	HANDLE handle = openfile(filename, O_WRONLY | O_CREAT | O_EXCL, 0);
+	TEST_THAT(handle != NULL);
+	SetFilePointer(handle, size, NULL, FILE_BEGIN);
+	TEST_THAT(GetLastError() == NO_ERROR);
+	TEST_THAT(SetEndOfFile(handle) == true);
+	TEST_THAT(CloseHandle(handle)  == true);
+	#else
+	TEST_THAT(truncate(filename, size) == 0);
+	#endif
+
+	/*
 	static const size_t bs = 0x10000;
 	size_t remSize = size;
 	void *b = malloc(bs);
 	memset(b, 0, bs);
 	FILE *f = fopen(filename, "wb");
+	TEST_THAT(f != NULL);
 
 	// Using largish blocks like this is much faster, while not consuming too much RAM
 	while(remSize > bs)
@@ -82,6 +95,7 @@
 
 	fclose(f);
 	free(b);
+	*/
 
 	TEST_THAT((size_t)TestGetFileSize(filename) == size);
 }
@@ -506,8 +520,16 @@
 	// 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");
@@ -528,12 +550,12 @@
 			0, 0));
 		encoded->CopyStreamTo(out);
 
-		printf("Time taken: %d seconds\n", time(0) - beginTime);
+		printf("Time taken: %d seconds\n", (int)(time(0) - beginTime));
 
 		#ifdef WIN32
-		TEST_THAT(time(0) < (beginTime + 120));
+		TEST_THAT(time(0) < (beginTime + 300));
 		#else
-		TEST_THAT(time(0) < (beginTime + 80));
+		TEST_THAT(time(0) < (beginTime + 20));
 		#endif
 	}
 	// Remove zero-files to save disk space


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:24:06 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:24:06 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r671 - box/chris/general/test/bbackupd
Message-ID: <20060722232406.111DD96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:23:59 +0000 (Sat, 22 Jul 2006)
New Revision: 671

Modified:
   box/chris/general/test/bbackupd/testbbackupd.cpp
Log:
* testbbackupd.cpp
- Moved terminate_bbackupd() to lib/common/Test.h


Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-22 23:23:08 UTC (rev 670)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-22 23:23:59 UTC (rev 671)
@@ -58,16 +58,6 @@
 // two cycles and a bit
 #define TIME_TO_WAIT_FOR_BACKUP_OPERATION	12
 
-#ifdef WIN32
-#define BBACKUPQUERY "..\\..\\bin\\bbackupquery\\bbackupquery.exe"
-#define BBACKUPCTL "..\\..\\bin\\bbackupctl\\bbackupctl"
-#define TEST_RETURN(actual, expected) TEST_THAT(actual == expected);
-#else
-#define BBACKUPQUERY "../../bin/bbackupquery/bbackupquery"
-#define BBACKUPCTL "../../bin/bbackupctl/bbackupctl"
-#define TEST_RETURN(actual, expected) TEST_THAT(actual == expected*256);
-#endif
-
 void wait_for_backup_operation(int seconds = TIME_TO_WAIT_FOR_BACKUP_OPERATION)
 {
 	printf("waiting: ");
@@ -570,24 +560,6 @@
 	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
 }
 
-void terminate_bbackupd(int pid)
-{
-	TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
-		"terminate") == 0);
-	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
-
-	for (int i = 0; i < 20; i++)
-	{
-		if (!ServerIsAlive(pid)) break;
-		fprintf(stdout, ".");
-		fflush(stdout);
-		sleep(1);
-	}
-
-	TEST_THAT(!ServerIsAlive(pid));
-	TestRemoteProcessMemLeaks("bbackupd.memleaks");
-}
-
 int test_bbackupd()
 {
 //	// First, wait for a normal period to make sure the last changes attributes are within a normal backup timeframe.


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:25:28 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:25:28 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r672 - box/chris/general/test/backupstorefix
Message-ID: <20060722232528.A3B4096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:25:22 +0000 (Sat, 22 Jul 2006)
New Revision: 672

Modified:
   box/chris/general/test/backupstorefix/testbackupstorefix.cpp
Log:
* testbackupstorefix.cpp
- Stop the server using terminate_bbackupd() rather than killing it,
  since killing can interrupt the SSL connection and thus kill bbstored
  as well (Win32 only)


Modified: box/chris/general/test/backupstorefix/testbackupstorefix.cpp
===================================================================
--- box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-22 23:23:59 UTC (rev 671)
+++ box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-22 23:25:22 UTC (rev 672)
@@ -333,18 +333,19 @@
 			wait_for_operation(14);
 
 			// That'll do nicely, stop the server	
+			#ifdef WIN32
+			terminate_bbackupd(bbackupd_pid);
+			// implicit check for memory leaks
+			#else
 			TEST_THAT(KillServer(bbackupd_pid));
-#ifndef WIN32
 			TestRemoteProcessMemLeaks("bbackupd.memleaks");
-#endif
+			#endif
 		}
 		
 		// Generate a list of all the object IDs
-#ifdef WIN32
-		TEST_THAT_ABORTONFAIL(::system("..\\..\\bin\\bbackupquery\\bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit > testfiles/initial-listing.txt") == 0);
-#else
-		TEST_THAT_ABORTONFAIL(::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit > testfiles/initial-listing.txt") == 0);
-#endif
+		TEST_THAT_ABORTONFAIL(::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf \"list -r\" quit "
+			"> testfiles/initial-listing.txt") == 0);
 
 		// And load it in
 		{


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:46:03 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:46:03 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r673 - box/chris/general/infrastructure
Message-ID: <20060722234603.EFCD496@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:45:55 +0000 (Sat, 22 Jul 2006)
New Revision: 673

Modified:
   box/chris/general/infrastructure/makebuildenv.pl
Log:
* makebuildenv.pl
- Fixed test for which files should be built under Unix


Modified: box/chris/general/infrastructure/makebuildenv.pl
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl	2006-07-22 23:25:22 UTC (rev 672)
+++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-22 23:45:55 UTC (rev 673)
@@ -584,7 +584,7 @@
 		}
 		else
 		{
-			next if not $is_rc;
+			next if not $is_cpp;
 		}
 
 		next if $file =~ /\A\._/; # Temp Mac OS Resource hack


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 00:46:38 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sat, 22 Jul 2006 23:46:38 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r674 - box/chris/general/bin/bbackupd
Message-ID: <20060722234638.9ECEB96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-22 23:46:33 +0000 (Sat, 22 Jul 2006)
New Revision: 674

Modified:
   box/chris/general/bin/bbackupd/BackupDaemon.cpp
Log:
* BackupDaemon.cpp
- Fixed compile error under Unix


Modified: box/chris/general/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-22 23:45:55 UTC (rev 673)
+++ box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-22 23:46:33 UTC (rev 674)
@@ -1139,7 +1139,10 @@
 		{
 			TRACE1("Receiving command '%s' over command socket\n", 
 				command.c_str());
+
+			#ifdef WIN32
 			SetEvent(mhCommandReceivedEvent);
+			#endif
 
 			bool sendOK = false;
 			bool sendResponse = true;


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:13:53 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 00:13:53 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r675 - in box/chris/general: . bin/bbackupd bin/bbackupquery bin/bbstored distribution/boxbackup/contrib/cygwin documentation documentation/boxbackup documentation/boxbackup/html documentation/boxbackup/html/images infrastructure infrastructure/m4 lib/backupclient lib/common lib/compress lib/crypto lib/raidfile lib/server test/backupstorefix test/backupstorefix/testfiles test/basicserver test/bbackupd/testfiles
Message-ID: <20060723001353.C391696@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 00:12:10 +0000 (Sun, 23 Jul 2006)
New Revision: 675

Added:
   box/chris/general/bin/bbackupd/bbackupd-config.in
   box/chris/general/bin/bbackupquery/makedocumentation.pl.in
   box/chris/general/bin/bbstored/bbstored-certs.in
   box/chris/general/bin/bbstored/bbstored-config.in
   box/chris/general/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl.in
   box/chris/general/documentation/
   box/chris/general/documentation/boxbackup/
   box/chris/general/documentation/boxbackup/Makefile
   box/chris/general/documentation/boxbackup/adminguide.xml
   box/chris/general/documentation/boxbackup/bb-book.xsl
   box/chris/general/documentation/boxbackup/bb-man.xsl
   box/chris/general/documentation/boxbackup/bb-nochunk-book.xsl
   box/chris/general/documentation/boxbackup/bbackupctl.xml
   box/chris/general/documentation/boxbackup/bbackupquery.xml
   box/chris/general/documentation/boxbackup/bbstoreaccounts.xml
   box/chris/general/documentation/boxbackup/bbstored-certs.xml
   box/chris/general/documentation/boxbackup/bbstored-config.xml
   box/chris/general/documentation/boxbackup/generate_except_xml.pl
   box/chris/general/documentation/boxbackup/html/
   box/chris/general/documentation/boxbackup/html/bbdoc-man.css
   box/chris/general/documentation/boxbackup/html/bbdoc.css
   box/chris/general/documentation/boxbackup/html/images/
   box/chris/general/documentation/boxbackup/html/images/arrow.png
   box/chris/general/documentation/boxbackup/html/images/bblogo.png
   box/chris/general/documentation/boxbackup/html/images/stepahead.png
   box/chris/general/documentation/boxbackup/instguide.xml
   box/chris/general/documentation/boxbackup/raidfile-config.xml
   box/chris/general/infrastructure/m4/ax_config_scripts.m4
   box/chris/general/infrastructure/makebuildenv.pl.in
   box/chris/general/infrastructure/makeparcels.pl.in
   box/chris/general/lib/common/makeexception.pl.in
   box/chris/general/lib/raidfile/raidfile-config.in
   box/chris/general/lib/server/makeprotocol.pl.in
   box/chris/general/runtest.pl.in
   box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl.in
   box/chris/general/test/bbackupd/testfiles/extcheck1.pl.in
   box/chris/general/test/bbackupd/testfiles/extcheck2.pl.in
   box/chris/general/test/bbackupd/testfiles/notifyscript.pl.in
Removed:
   box/chris/general/bin/bbackupd/bbackupd-config
   box/chris/general/bin/bbackupquery/makedocumentation.pl
   box/chris/general/bin/bbstored/bbstored-certs
   box/chris/general/bin/bbstored/bbstored-config
   box/chris/general/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl
   box/chris/general/documentation/boxbackup/
   box/chris/general/documentation/boxbackup/Makefile
   box/chris/general/documentation/boxbackup/adminguide.xml
   box/chris/general/documentation/boxbackup/bb-book.xsl
   box/chris/general/documentation/boxbackup/bb-man.xsl
   box/chris/general/documentation/boxbackup/bb-nochunk-book.xsl
   box/chris/general/documentation/boxbackup/bbackupctl.xml
   box/chris/general/documentation/boxbackup/bbackupquery.xml
   box/chris/general/documentation/boxbackup/bbstoreaccounts.xml
   box/chris/general/documentation/boxbackup/bbstored-certs.xml
   box/chris/general/documentation/boxbackup/bbstored-config.xml
   box/chris/general/documentation/boxbackup/generate_except_xml.pl
   box/chris/general/documentation/boxbackup/html/
   box/chris/general/documentation/boxbackup/html/bbdoc-man.css
   box/chris/general/documentation/boxbackup/html/bbdoc.css
   box/chris/general/documentation/boxbackup/html/images/
   box/chris/general/documentation/boxbackup/html/images/arrow.png
   box/chris/general/documentation/boxbackup/html/images/bblogo.png
   box/chris/general/documentation/boxbackup/html/images/stepahead.png
   box/chris/general/documentation/boxbackup/instguide.xml
   box/chris/general/documentation/boxbackup/raidfile-config.xml
   box/chris/general/infrastructure/m4/ax_check_llong_minmax.m4
   box/chris/general/infrastructure/makebuildenv.pl
   box/chris/general/infrastructure/makeparcels.pl
   box/chris/general/lib/common/makeexception.pl
   box/chris/general/lib/raidfile/raidfile-config
   box/chris/general/lib/server/makeprotocol.pl
   box/chris/general/runtest.pl
   box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl
   box/chris/general/test/bbackupd/testfiles/extcheck1.pl
   box/chris/general/test/bbackupd/testfiles/extcheck2.pl
   box/chris/general/test/bbackupd/testfiles/notifyscript.pl
Modified:
   box/chris/general/
   box/chris/general/bin/bbackupd/
   box/chris/general/bin/bbackupd/BackupDaemon.cpp
   box/chris/general/bin/bbackupquery/
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
   box/chris/general/bin/bbackupquery/Makefile.extra
   box/chris/general/bin/bbstored/
   box/chris/general/bin/bbstored/Makefile.extra
   box/chris/general/configure.ac
   box/chris/general/infrastructure/
   box/chris/general/infrastructure/makedistribution.pl
   box/chris/general/infrastructure/setupexternal.pl
   box/chris/general/lib/backupclient/Makefile.extra
   box/chris/general/lib/common/
   box/chris/general/lib/common/Makefile.extra
   box/chris/general/lib/compress/Makefile.extra
   box/chris/general/lib/crypto/Makefile.extra
   box/chris/general/lib/raidfile/
   box/chris/general/lib/raidfile/Makefile.extra
   box/chris/general/lib/server/
   box/chris/general/lib/server/Makefile.extra
   box/chris/general/test/backupstorefix/testbackupstorefix.cpp
   box/chris/general/test/backupstorefix/testfiles/
   box/chris/general/test/basicserver/Makefile.extra
   box/chris/general/test/bbackupd/testfiles/
   box/chris/general/test/bbackupd/testfiles/bbackupd.conf
Log:
* Many files
- Merged changed from trunk revs 495-674 into win32 general branch



Property changes on: box/chris/general
___________________________________________________________________
Name: svn:ignore
   - aclocal.m4
autom4te.cache
config.log
config.status
configure
debug
ExceptionCodes.txt
local
Makefile
parcels
release

   + aclocal.m4
autom4te.cache
config.log
config.status
configure
debug
ExceptionCodes.txt
local
Makefile
parcels
release
runtest.pl



Property changes on: box/chris/general/bin/bbackupd
___________________________________________________________________
Name: svn:ignore
   - Makefile

   + Makefile
bbackupd-config


Modified: box/chris/general/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbackupd/BackupDaemon.cpp	2006-07-23 00:12:10 UTC (rev 675)
@@ -720,6 +720,9 @@
 				::syslog(LOG_ERR, "Failed to delete the "
 					"StoreObjectInfoFile, backup cannot "
 					"continue safely.");
+				// prevent runaway process where the logs fill up -- without this
+				// the log message will be emitted in a tight loop.
+				::sleep(60); 
 				continue;
 			}
 
@@ -2541,14 +2544,25 @@
 		return false;
 	}
 
-	std::string StoreObjectInfoFile = 
-		GetConfiguration().GetKeyValue("StoreObjectInfoFile");
+	std::string storeObjectInfoFile(GetConfiguration().GetKeyValue("StoreObjectInfoFile"));
 
-	if (::unlink(StoreObjectInfoFile.c_str()) != 0)
+	// Check to see if the file exists
+	if(!FileExists(storeObjectInfoFile.c_str()))
 	{
+		// File doesn't exist -- so can't be deleted. But something isn't quite right, so log a message
+		::syslog(LOG_ERR, "Expected to be able to delete "
+			"store object info file '%s', but the file did not exist.",
+			storeObjectInfoFile.c_str());
+		// Return true to stop things going around in a loop
+		return true;
+	}
+
+	// Actually delete it
+	if(::unlink(storeObjectInfoFile.c_str()) != 0)
+	{
 		::syslog(LOG_ERR, "Failed to delete the old "
 			"store object info file '%s': %s",
-			StoreObjectInfoFile.c_str(), strerror(errno));
+			storeObjectInfoFile.c_str(), strerror(errno));
 		return false;
 	}
 

Deleted: box/chris/general/bin/bbackupd/bbackupd-config
===================================================================
--- box/chris/general/bin/bbackupd/bbackupd-config	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbackupd/bbackupd-config	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,533 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-# should be running as root
-if($> != 0)
-{
-	printf "\nWARNING: this should be run as root\n\n"
-}
-
-sub error_print_usage
-{
-	print <<__E;
-
-Setup bbackupd config utility.
-
-Bad command line parameters.
-Usage:
-	bbackupd-config config-dir backup-mode account-num server-hostname working-dir backup-dir [more backup directories]
-
-config-dir usually /etc/box
-backup-mode is lazy or snapshot
-    lazy mode runs continously, uploading files over a specified age
-    snapshot mode uploads a snapshot of the filesystem when instructed explicitly
-account-num (hexdecimal) and server-hostname as supplied from the server administrator
-working-dir usually /var/bbackupd
-backup-dir, list of directories to back up
-
-__E
-	print "=========\nERROR:\n",$_[0],"\n\n" if $_[0] ne '';
-	exit(1);
-}
-
-# check and get command line parameters
-if($#ARGV < 4)
-{
-	error_print_usage();
-}
-
-# check for OPENSSL_CONF environment var being set
-if(exists $ENV{'OPENSSL_CONF'})
-{
-	print <<__E;
-
----------------------------------------
-
-WARNING:
-    You have the OPENSSL_CONF environment variable set.
-    Use of non-standard openssl configs may cause problems.
-
----------------------------------------
-
-__E
-}
-
-# default locations
-my $default_config_location = '/etc/box/bbackupd.conf';
-
-# command line parameters
-my ($config_dir,$backup_mode,$account_num,$server,$working_dir,@tobackup) = @ARGV;
-
-# check backup mode is valid
-if($backup_mode ne 'lazy' && $backup_mode ne 'snapshot')
-{
-	error_print_usage("ERROR: backup mode must be 'lazy' or 'snapshot'");
-}
-
-# check server exists
-{
-	my @r = gethostbyname($server);
-	if($#r < 0)
-	{
-		error_print_usage("Backup server specified as '$server', but it could not found.\n(A test DNS lookup failed -- check arguments)");
-	}
-}
-
-if($working_dir !~ m~\A/~)
-{
-	error_print_usage("Working directory $working_dir is not specified as an absolute path");
-}
-
-# ssl stuff
-my $private_key = "$config_dir/bbackupd/$account_num-key.pem";
-my $certificate_request = "$config_dir/bbackupd/$account_num-csr.pem";
-my $certificate = "$config_dir/bbackupd/$account_num-cert.pem";
-my $ca_root_cert = "$config_dir/bbackupd/serverCA.pem";
-
-# encryption keys
-my $enc_key_file = "$config_dir/bbackupd/$account_num-FileEncKeys.raw";
-
-# other files
-my $config_file = "$config_dir/bbackupd.conf";
-my $notify_script = "$config_dir/bbackupd/NotifySysadmin.sh";
-
-# check that the directories are allowable
-for(@tobackup)
-{
-	if($_ eq '/')
-	{
-		die "It is not recommended that you backup the root directory of your disc";
-	}
-	if($_ !~ m/\A\//)
-	{
-		die "Directory $_ is not specified as an absolute path";
-	}
-	if(!-d $_)
-	{
-		die "$_ is not a directory";
-	}
-}
-
-# summarise configuration
-
-print <<__E;
-
-Setup bbackupd config utility.
-
-Configuration:
-   Writing configuration file: $config_file
-   Account: $account_num
-   Server hostname: $server
-   Directories to back up:
-__E
-print '      ',$_,"\n" for(@tobackup);
-print <<__E;
-
-Note: If other file systems are mounted inside these directories, then problems may occur
-with files on the store server being renamed incorrectly. This will cause efficiency
-problems, but not affect the integrity of the backups.
-
-WARNING: Directories not checked against mountpoints. Check mounted filesystems manually.
-
-__E
-
-# create directories
-if(!-d $config_dir)
-{
-	printf "Creating $config_dir...\n";
-	mkdir $config_dir,0755 or die "Can't create $config_dir";
-}
-
-if(!-d "$config_dir/bbackupd")
-{
-	printf "Creating $config_dir/bbackupd\n";
-	mkdir "$config_dir/bbackupd",0700 or die "Can't create $config_dir/bbackupd";
-}
-
-if(!-d "$working_dir")
-{
-	printf "Creating $working_dir\n";
-	if(!mkdir($working_dir,0700))
-	{
-		die "Couldn't create $working_dir -- create this manually and try again\n";
-	}
-}
-
-# generate the private key for the server
-if(!-f $private_key)
-{
-	print "Generating private key...\n";
-	if(system("openssl genrsa -out $private_key 2048") != 0)
-	{
-		die "Couldn't generate private key."
-	}
-}
-
-# generate a certificate request
-if(!-f $certificate_request)
-{
-	die "Couldn't run openssl for CSR generation" unless
-		open(CSR,"|openssl req -new -key $private_key -sha1 -out $certificate_request");
-	print CSR <<__E;
-.
-.
-.
-.
-.
-BACKUP-$account_num
-.
-.
-.
-
-__E
-	close CSR;
-	print "\n\n";
-	die "Certificate request wasn't created.\n" unless -f $certificate_request
-}
-
-# generate the key material for the file
-if(!-f $enc_key_file)
-{
-	print "Generating keys for file backup\n";
-	if(system("openssl rand -out $enc_key_file 1024") != 0)
-	{
-		die "Couldn't generate file backup keys."
-	}
-}
-
-# write the notify when store full script
-print "Writing notify script $notify_script\n";
-open NOTIFY,">$notify_script" or die "Can't open for writing";
-
-my $hostname = `hostname`; chomp $hostname;
-my $current_username = `whoami`; chomp $current_username;
-my $sendmail = `whereis sendmail`; chomp $sendmail;
-$sendmail =~ s/\n.\Z//s;
-# for Linux style whereis
-$sendmail = $1 if $sendmail =~ /^sendmail:\s+([\S]+)/;
-# last ditch guess
-$sendmail = 'sendmail' if $sendmail !~ m/\S/;
-
-print NOTIFY <<__EOS;
-#!/bin/sh
-
-SUBJECT="BACKUP PROBLEM on host $hostname"
-SENDTO="$current_username"
-
-if [ \$1 = store-full ]
-then
-$sendmail \$SENDTO <<EOM
-Subject: \$SUBJECT (store full)
-To: \$SENDTO
-
-
-The store account for $hostname is full.
-
-=============================
-FILES ARE NOT BEING BACKED UP
-=============================
-
-Please adjust the limits on account $account_num on server $server.
-
-EOM
-elif [ \$1 = read-error ]
-then
-$sendmail \$SENDTO <<EOM
-Subject: \$SUBJECT (read errors)
-To: \$SENDTO
-
-
-Errors occured reading some files or directories for backup on $hostname.
-
-===================================
-THESE FILES ARE NOT BEING BACKED UP
-===================================
-
-Check the logs on $hostname for the files and directories which caused
-these errors, and take appropraite action.
-
-Other files are being backed up.
-
-EOM
-else
-$sendmail \$SENDTO <<EOM
-Subject: \$SUBJECT (unknown)
-To: \$SENDTO
-
-
-The backup daemon on $hostname reported an unknown error.
-
-==========================
-FILES MAY NOT BE BACKED UP
-==========================
-
-Please check the logs on $hostname.
-
-EOM
-fi
-__EOS
-
-close NOTIFY;
-chmod 0700,$notify_script or die "Can't chmod $notify_script";
-
-
-# write the configuration file
-print "Writing configuration file $config_file\n";
-open CONFIG,">$config_file" or die "Can't open config file for writing";
-print CONFIG <<__E;
-
-StoreHostname = $server
-AccountNumber = 0x$account_num
-KeysFile = $enc_key_file
-
-CertificateFile = $certificate
-PrivateKeyFile = $private_key
-TrustedCAsFile = $ca_root_cert
-
-DataDirectory = $working_dir
-
-
-# This script is run whenever bbackupd encounters a problem which requires
-# the system administrator to assist:
-# 1) The store is full, and no more data can be uploaded.
-# 2) Some files or directories were not readable.
-# The default script emails the system administrator.
-
-NotifyScript = $notify_script
-
-__E
-
-if($backup_mode eq 'lazy')
-{
-	# lazy mode configuration
-	print CONFIG <<__E;
-
-# A scan of the local discs will be made once an hour (approximately).
-# To avoid cycles of load on the server, this time is randomly adjusted by a small
-# percentage as the daemon runs.
-
-UpdateStoreInterval = 3600
-
-
-# A file must have been modified at least 6 hours ago before it will be uploaded.
-
-MinimumFileAge = 21600
-
-
-# If a file is modified repeated, it won't be uploaded immediately in case it's modified again.
-# However, it should be uploaded eventually. This is how long we should wait after first noticing
-# a change. (1 day)
-
-MaxUploadWait = 86400
-
-__E
-}
-else
-{
-	# snapshot configuration
-	print CONFIG <<__E;
-
-# This configuration file is written for snapshot mode.
-# You will need to run bbackupctl to instruct the daemon to upload files.
-
-AutomaticBackup = no
-UpdateStoreInterval = 0
-MinimumFileAge = 0
-MaxUploadWait = 0
-
-__E
-}
-
-print CONFIG <<__E;
-
-# Files above this size (in bytes) are tracked, and if they are renamed they will simply be
-# renamed on the server, rather than being uploaded again. (64k - 1)
-
-FileTrackingSizeThreshold = 65535
-
-
-# The daemon does "changes only" uploads for files above this size (in bytes).
-# Files less than it are uploaded whole without this extra processing.
-
-DiffingUploadSizeThreshold = 8192
-
-
-# The limit on how much time is spent diffing files. Most files shouldn't take very long,
-# but if you have really big files you can use this to limit the time spent diffing them.
-# * Reduce if you are having problems with processor usage.
-# * Increase if you have large files, and think the upload of changes is too large and want
-#   to spend more time searching for unchanged blocks.
-
-MaximumDiffingTime = 20
-
-
-# Uncomment this line to see exactly what the daemon is going when it's connected to the server.
-
-# ExtendedLogging = yes
-
-
-# Use this to temporarily stop bbackupd from syncronising or connecting to the store.
-# This specifies a program or script script which is run just before each sync, and ideally
-# the full path to the interpreter. It will be run as the same user bbackupd is running as,
-# usually root.
-# The script prints either "now" or a number to STDOUT (and a terminating newline, no quotes).
-# If the result was "now", then the sync will happen. If it's a number, then the script will
-# be asked again in that number of seconds.
-# For example, you could use this on a laptop to only backup when on a specific network.
-
-# SyncAllowScript = /path/to/intepreter/or/exe script-name parameters etc
-
-
-# Where the command socket is created in the filesystem.
-
-CommandSocket = /var/run/bbackupd.sock
-
-# Uncomment the StoreObjectInfoFile to enable the experimental archiving
-# of the daemon's state (including client store marker and configuration)
-# between backup runs. This saves time and increases efficiency when
-# bbackupd is frequently stopped and started, since it removes the need
-# to rescan all directories on the remote server. However, it is new and
-# not yet heavily tested, so use with caution.
-
-# StoreObjectInfoFile = $working_dir/bbackupd.state
-
-Server
-{
-	PidFile = /var/run/bbackupd.pid
-}
-
-# 
-# BackupLocations specifies which locations on disc should be backed up. Each
-# directory is in the format
-# 
-# 	name
-# 	{
-# 		Path = /path/of/directory
-# 		(optional exclude directives)
-# 	}
-# 
-# 'name' is derived from the Path by the config script, but should merely be
-# unique.
-# 
-# The exclude directives are of the form
-# 
-# 	[Exclude|AlwaysInclude][File|Dir][|sRegex] = regex or full pathname
-# 
-# (The regex suffix is shown as 'sRegex' to make File or Dir plural)
-#
-# For example:
-# 
-# 	ExcludeDir = /home/guest-user
-# 	ExcludeFilesRegex = *.(mp3|MP3)\$
-# 	AlwaysIncludeFile = /home/username/veryimportant.mp3
-# 
-# This excludes the directory /home/guest-user from the backup along with all mp3
-# files, except one MP3 file in particular.
-# 
-# In general, Exclude excludes a file or directory, unless the directory is
-# explicitly mentioned in a AlwaysInclude directive.
-# 
-# If a directive ends in Regex, then it is a regular expression rather than a
-# explicit full pathname. See
-# 
-# 	man 7 re_format
-# 
-# for the regex syntax on your platform.
-# 
-
-BackupLocations
-{
-__E
-
-# write the dirs to backup
-for my $d (@tobackup)
-{
-	$d =~ m/\A.(.+)\Z/;
-	my $n = $1;
-	$n =~ tr`/`-`;
-	
-	my $excludekeys = '';
-	if(substr($enc_key_file, 0, length($d)+1) eq $d.'/')
-	{
-		$excludekeys = "\t\tExcludeFile = $enc_key_file\n";
-		print <<__E;
-
-NOTE: Keys file has been explicitly excluded from the backup.
-
-__E
-	}
-	
-	print CONFIG <<__E
-	$n
-	{
-		Path = $d
-$excludekeys	}
-__E
-}
-
-print CONFIG "}\n\n";
-close CONFIG;
-
-# explain to the user what they need to do next
-my $daemon_args = ($config_file eq $default_config_location)?'':" $config_file";
-my $ctl_daemon_args = ($config_file eq $default_config_location)?'':" -c $config_file";
-
-print <<__E;
-
-===================================================================
-
-bbackupd basic configuration complete.
-
-What you need to do now...
-
-1) Make a backup of $enc_key_file
-   This should be a secure offsite backup.
-   Without it, you cannot restore backups. Everything else can
-   be replaced. But this cannot.
-   KEEP IT IN A SAFE PLACE, OTHERWISE YOUR BACKUPS ARE USELESS.
-
-2) Send $certificate_request
-   to the administrator of the backup server, and ask for it to
-   be signed.
-
-3) The administrator will send you two files. Install them as
-      $certificate
-      $ca_root_cert
-   after checking their authenticity.
-
-4) You may wish to read the configuration file
-      $config_file
-   and adjust as appropraite.
-   
-   There are some notes in it on excluding files you do not
-   wish to be backed up.
-
-5) Review the script
-      $notify_script
-   and check that it will email the right person when the store
-   becomes full. This is important -- when the store is full, no
-   more files will be backed up. You want to know about this.
-
-6) Start the backup daemon with the command
-      /usr/local/bin/bbackupd$daemon_args
-   in /etc/rc.local, or your local equivalent.
-   Note that bbackupd must run as root.
-__E
-if($backup_mode eq 'snapshot')
-{
-	print <<__E;
-
-7) Set up a cron job to run whenever you want a snapshot of the
-   file system to be taken. Run the command
-      /usr/local/bin/bbackupctl -q$ctl_daemon_args sync
-__E
-}
-print <<__E;
-
-===================================================================
-
-Remember to make a secure, offsite backup of your backup keys,
-as described in step 1 above. If you do not, you have no backups.
-
-__E
-

Copied: box/chris/general/bin/bbackupd/bbackupd-config.in (from rev 674, box/trunk/bin/bbackupd/bbackupd-config.in)


Property changes on: box/chris/general/bin/bbackupquery
___________________________________________________________________
Name: svn:ignore
   - autogen_Documentation.cpp
Makefile

   + autogen_Documentation.cpp
Makefile
makedocumentation.pl


Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-23 00:12:10 UTC (rev 675)
@@ -26,6 +26,7 @@
 #endif
 
 #include <set>
+#include <limits>
 
 #include "BackupQueries.h"
 #include "Utils.h"
@@ -813,7 +814,7 @@
 	}
 	
 	int64_t id = ::strtoll(args[0].c_str(), 0, 16);
-	if(id == LLONG_MIN || id == LLONG_MAX || id == 0)
+	if(id == std::numeric_limits<long long>::min() || id == std::numeric_limits<long long>::max() || id == 0)
 	{
 		printf("Not a valid object ID (specified in hex)\n");
 		return;
@@ -930,7 +931,8 @@
 		{
 			// Specified as ID. 
 			fileId = ::strtoll(args[0].c_str(), 0, 16);
-			if(fileId == LLONG_MIN || fileId == LLONG_MAX || 
+			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");
@@ -1372,6 +1374,17 @@
 				(localDirEn->d_name[1] == '\0' || (localDirEn->d_name[1] == '.' && localDirEn->d_name[2] == '\0')))
 			{
 				// ignore, it's . or ..
+				
+#ifdef HAVE_VALID_DIRENT_D_TYPE
+				if (localDirEn->d_type != DT_DIR)
+				{
+					fprintf(stderr, "ERROR: d_type does "
+						"not really work on your "
+						"platform. Reconfigure Box!\n");
+					return;
+				}
+#endif
+				
 				continue;
 			}
 
@@ -1395,7 +1408,7 @@
 			{
 			    // Directory
 			    localDirs.insert(std::string(localDirEn->d_name));
-			}			
+			}
 #else
 			// Entry -- file or dir?
 			if(localDirEn->d_type == DT_REG || localDirEn->d_type == DT_LNK)
@@ -1815,7 +1828,7 @@
 	{
 		// Specified as ID. 
 		dirID = ::strtoll(args[0].c_str(), 0, 16);
-		if(dirID == LLONG_MIN || dirID == LLONG_MAX || dirID == 0)
+		if(dirID == std::numeric_limits<long long>::min() || dirID == std::numeric_limits<long long>::max() || dirID == 0)
 		{
 			printf("Not a valid object ID (specified in hex)\n");
 			return;

Modified: box/chris/general/bin/bbackupquery/Makefile.extra
===================================================================
--- box/chris/general/bin/bbackupquery/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbackupquery/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,6 +1,6 @@
 
 # AUTOGEN SEEDING
 autogen_Documentation.cpp:	makedocumentation.pl documentation.txt
-	perl makedocumentation.pl
+	$(PERL) makedocumentation.pl
 
 

Deleted: box/chris/general/bin/bbackupquery/makedocumentation.pl
===================================================================
--- box/chris/general/bin/bbackupquery/makedocumentation.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbackupquery/makedocumentation.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,75 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-print "Creating built-in documentation for bbackupquery...\n";
-
-open DOC,"documentation.txt" or die "Can't open documentation.txt file";
-my $section;
-my %help;
-my @in_order;
-
-while(<DOC>)
-{
-	if(m/\A>\s+(\w+)/)
-	{
-		$section = $1;
-		m/\A>\s+(.+)\Z/;
-		$help{$section} = $1."\n";
-		push @in_order,$section;
-	}
-	elsif(m/\A</)
-	{
-		$section = '';
-	}
-	elsif($section ne '')
-	{
-		$help{$section} .= $_;
-	}
-}
-
-close DOC;
-
-open OUT,">autogen_Documentation.cpp" or die "Can't open output file for writing";
-
-print OUT <<__E;
-//
-// Automatically generated file, do not edit.
-//
-
-#include "Box.h"
-
-#include "MemLeakFindOn.h"
-
-char *help_commands[] =
-{
-__E
-
-for(@in_order)
-{
-	print OUT qq:\t"$_",\n:;
-}
-
-print OUT <<__E;
-	0
-};
-
-char *help_text[] =
-{
-__E
-
-for(@in_order)
-{
-	my $t = $help{$_};
-	$t =~ s/\t/    /g;
-	$t =~ s/\n/\\n/g;
-	$t =~ s/"/\\"/g;
-	print OUT qq:\t"$t",\n:;	
-}
-
-print OUT <<__E;
-	0
-};
-
-__E
-
-close OUT;

Copied: box/chris/general/bin/bbackupquery/makedocumentation.pl.in (from rev 674, box/trunk/bin/bbackupquery/makedocumentation.pl.in)


Property changes on: box/chris/general/bin/bbstored
___________________________________________________________________
Name: svn:ignore
   - autogen_BackupProtocolServer.cpp
autogen_BackupProtocolServer.h
Makefile

   + autogen_BackupProtocolServer.cpp
autogen_BackupProtocolServer.h
Makefile
bbstored-certs
bbstored-config


Modified: box/chris/general/bin/bbstored/Makefile.extra
===================================================================
--- box/chris/general/bin/bbstored/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbstored/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -5,5 +5,5 @@
 
 # AUTOGEN SEEDING
 autogen_BackupProtocolServer.cpp autogen_BackupProtocolServer.h:	$(MAKEPROTOCOL) backupprotocol.txt
-	perl $(GEN_CMD_SRV)
+	$(PERL) $(GEN_CMD_SRV)
 

Deleted: box/chris/general/bin/bbstored/bbstored-certs
===================================================================
--- box/chris/general/bin/bbstored/bbstored-certs	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbstored/bbstored-certs	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,319 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-# validity period for root certificates -- default is a very long time
-my $root_sign_period = '10000';
-
-# but less so for client certificates
-my $sign_period = '5000';
-
-# check and get command line parameters
-if($#ARGV < 1)
-{
-	print <<__E;
-
-bbstored certificates utility.
-
-Bad command line parameters.
-Usage:
-	bbstored-certs certs-dir command [arguments]
-
-certs-dir is the directory holding the root keys and certificates for the backup system
-command is the action to perform, taking parameters.
-
-Commands are
-
-	init
-		-- generate initial root certificates (certs-dir must not already exist)
-	sign certificate-name
-		-- sign a client certificate
-	sign-server certificate-name
-		-- sign a server certificate
-
-Signing requires confirmation that the certificate is correct and should be signed.
-
-__E
-	exit(1);
-}
-
-# check for OPENSSL_CONF environment var being set
-if(exists $ENV{'OPENSSL_CONF'})
-{
-	print <<__E;
-
----------------------------------------
-
-WARNING:
-    You have the OPENSSL_CONF environment variable set.
-    Use of non-standard openssl configs may cause problems.
-
----------------------------------------
-
-__E
-}
-
-# directory structure:
-#
-# roots/
-#	clientCA.pem -- root certificate for client (used on server)
-#	serverCA.pem -- root certificate for servers (used on clients)
-# keys/
-#   clientRootKey.pem -- root key for clients
-#   serverRootKey.pem -- root key for servers
-# servers/
-#   hostname.pem -- certificate for server 'hostname'
-# clients/
-#   account.pem -- certficiate for account 'account' (ID in hex)
-#
-
-
-# check parameters
-my ($cert_dir,$command,@args) = @ARGV;
-
-# check directory exists
-if($command ne 'init')
-{
-	if(!-d $cert_dir)
-	{
-		die "$cert_dir does not exist";
-	}
-}
-
-# run command
-if($command eq 'init') {&cmd_init;}
-elsif($command eq 'sign') {&cmd_sign;}
-elsif($command eq 'sign-server') {&cmd_sign_server;}
-else
-{
-	die "Unknown command $command"
-}
-
-sub cmd_init
-{
-	# create directories
-	unless(mkdir($cert_dir,0700)
-		&& mkdir($cert_dir.'/roots',0700)
-		&& mkdir($cert_dir.'/keys',0700)
-		&& mkdir($cert_dir.'/servers',0700)
-		&& mkdir($cert_dir.'/clients',0700))
-	{
-		die "Failed to create directory structure"
-	}
-
-	# create root keys and certrs
-	cmd_init_create_root('client');
-	cmd_init_create_root('server');
-}
-
-sub cmd_init_create_root
-{
-	my $entity = $_[0];
-
-	my $cert = "$cert_dir/roots/".$entity.'CA.pem';
-	my $serial = "$cert_dir/roots/".$entity.'CA.srl';
-	my $key = "$cert_dir/keys/".$entity.'RootKey.pem';
-	my $csr = "$cert_dir/keys/".$entity.'RootCSR.pem';
-
-	# generate key
-	if(system("openssl genrsa -out $key 2048") != 0)
-	{
-		die "Couldn't generate private key."
-	}
-	
-	# make CSR
-	die "Couldn't run openssl for CSR generation" unless
-		open(CSR,"|openssl req -new -key $key -sha1 -out $csr");
-	print CSR <<__E;
-.
-.
-.
-.
-.
-Backup system $entity root
-.
-.
-.
-
-__E
-	close CSR;
-	print "\n\n";
-	die "Certificate request wasn't created.\n" unless -f $csr;
-	
-	# sign it to make a self-signed root CA key
-	if(system("openssl x509 -req -in $csr -sha1 -extensions v3_ca -signkey $key -out $cert -days $root_sign_period") != 0)
-	{
-		die "Couldn't generate root certificate."
-	}
-	
-	# write the initial serial number
-	open SERIAL,">$serial" or die "Can't open $serial for writing";
-	print SERIAL "00\n";
-	close SERIAL;
-}
-
-sub cmd_sign
-{
-	my $csr = $args[0];
-	
-	if(!-f $csr)
-	{
-		die "$csr does not exist";
-	}
-	
-	# get the common name specified in this certificate
-	my $common_name = get_csr_common_name($csr);
-	
-	# look OK?
-	unless($common_name =~ m/\ABACKUP-([A-Fa-f0-9]+)\Z/)
-	{
-		die "The certificate presented does not appear to be a backup client certificate"
-	}
-	
-	my $acc = $1;
-	
-	# check against filename
-	if(!($csr =~ m/(\A|\/)([A-Fa-f0-9]+)-/) || $2 ne $acc)
-	{
-		die "Certificate request filename does not match name in certificate ($common_name)"
-	}
-		
-	print <<__E;
-
-This certificate is for backup account
-
-   $acc
-
-Ensure this matches the account number you are expecting. The filename is
-
-   $csr
-
-which should include this account number, and additionally, you should check
-that you received it from the right person.
-
-Signing the wrong certificate compromises the security of your backup system.
-
-Would you like to sign this certificate? (type 'yes' to confirm)
-__E
-
-	return unless get_confirmation();
-
-	# out certificate
-	my $out_cert = "$cert_dir/clients/$acc"."-cert.pem";
-
-	# sign it!
-	if(system("openssl x509 -req -in $csr -sha1 -extensions usr_crt -CA $cert_dir/roots/clientCA.pem -CAkey $cert_dir/keys/clientRootKey.pem -out $out_cert -days $sign_period") != 0)
-	{
-		die "Signing failed"
-	}
-	
-	# tell user what to do next
-	print <<__E;
-
-
-Certificate signed.
-
-Send the files
-
-   $out_cert
-   $cert_dir/roots/serverCA.pem
-
-to the client.
-
-__E
-}
-
-sub cmd_sign_server
-{
-	my $csr = $args[0];
-	
-	if(!-f $csr)
-	{
-		die "$csr does not exist";
-	}
-	
-	# get the common name specified in this certificate
-	my $common_name = get_csr_common_name($csr);
-	
-	# look OK?
-	if($common_name !~ m/\A[-a-zA-Z0-9.]+\Z/)
-	{
-		die "Invalid server name"
-	}
-	
-	print <<__E;
-
-This certificate is for backup server
-
-   $common_name
-
-Signing the wrong certificate compromises the security of your backup system.
-
-Would you like to sign this certificate? (type 'yes' to confirm)
-__E
-
-	return unless get_confirmation();
-
-	# out certificate
-	my $out_cert = "$cert_dir/servers/$common_name"."-cert.pem";
-
-	# sign it!
-	if(system("openssl x509 -req -in $csr -sha1 -extensions usr_crt -CA $cert_dir/roots/serverCA.pem -CAkey $cert_dir/keys/serverRootKey.pem -out $out_cert -days $sign_period") != 0)
-	{
-		die "Signing failed"
-	}
-	
-	# tell user what to do next
-	print <<__E;
-
-
-Certificate signed.
-
-Install the files
-
-   $out_cert
-   $cert_dir/roots/clientCA.pem
-
-on the server.
-
-__E
-}
-
-
-sub get_csr_common_name
-{
-	my $csr = $_[0];
-	
-	open CSRTEXT,"openssl req -text -in $csr |" or die "Can't open openssl for reading";
-	
-	my $subject;
-	while(<CSRTEXT>)
-	{
-		$subject = $1 if m/Subject:.+?CN=([-\.\w]+)/
-	}	
-	close CSRTEXT;
-
-	if($subject eq '')
-	{
-		die "No subject found in CSR $csr"
-	}
-	
-	return $subject
-}
-
-sub get_confirmation()
-{
-	my $line = <STDIN>;
-	chomp $line;
-	if(lc $line ne 'yes')
-	{
-		print "CANCELLED\n";
-		return 0;
-	}
-	
-	return 1;
-}
-
-
-
-
-

Copied: box/chris/general/bin/bbstored/bbstored-certs.in (from rev 674, box/trunk/bin/bbstored/bbstored-certs.in)

Deleted: box/chris/general/bin/bbstored/bbstored-config
===================================================================
--- box/chris/general/bin/bbstored/bbstored-config	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/bin/bbstored/bbstored-config	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,242 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-# should be running as root
-if($> != 0)
-{
-	printf "\nWARNING: this should be run as root\n\n"
-}
-
-# check and get command line parameters
-if($#ARGV < 2)
-{
-	print <<__E;
-
-Setup bbstored config utility.
-
-Bad command line parameters.
-Usage:
-	bbstored-config config-dir server-hostname username [raidfile-config]
-
-config-dir usually /etc/box
-server-hostname is the hostname used by clients to connect to this server
-username is the user to run the server under
-raidfile-config is optional. Use if you have a non-standard raidfile.conf file.
-
-__E
-	exit(1);
-}
-
-# check for OPENSSL_CONF environment var being set
-if(exists $ENV{'OPENSSL_CONF'})
-{
-	print <<__E;
-
----------------------------------------
-
-WARNING:
-    You have the OPENSSL_CONF environment variable set.
-    Use of non-standard openssl configs may cause problems.
-
----------------------------------------
-
-__E
-}
-
-# default locations
-my $default_config_location = '/etc/box/bbstored.conf';
-
-# command line parameters
-my ($config_dir,$server,$username,$raidfile_config) = @ARGV;
-
-$raidfile_config = $config_dir . '/raidfile.conf' unless $raidfile_config ne '';
-
-# check server exists, but don't bother checking that it's actually this machine.
-{
-	my @r = gethostbyname($server);
-	if($#r < 0)
-	{
-		die "Server '$server' not found. (check server name, test DNS lookup failed.)"
-	}
-}
-
-# check this exists
-if(!-f $raidfile_config)
-{
-	print "The RaidFile configuration file $raidfile_config doesn't exist.\nYou may need to create it with raidfile-config.\nWon't configure bbstored without it.\n";
-	exit(1);
-}
-
-# check that the user exists
-die "You shouldn't run bbstored as root" if $username eq 'root';
-my $user_uid = 0;
-(undef,undef,$user_uid) = getpwnam($username);
-if($user_uid == 0)
-{
-	die "User $username doesn't exist\n";
-}
-
-# check that directories are writeable
-open RAIDCONF,$raidfile_config or die "Can't open $raidfile_config";
-{
-	my %done = ();
-	while(<RAIDCONF>)
-	{
-		next unless m/Dir\d\s*=\s*(.+)/;
-		my $d = $1;
-		$d = $d.'/backup' if -e $d.'/backup';
-		print "Checking permissions on $d\n";
-		my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($d);
-		my $req_perms = ($uid == $user_uid)?0700:0007;
-		if(($mode & $req_perms) != $req_perms)
-		{
-			print "$username doesn't appear to have the necessary permissions on $d\n";
-			print "Either adjust permissions, or create a directory 'backup' inside the\n";
-			print "directory specified in raidfile.conf which is writable.\n";
-			exit(1);
-		}
-	}
-}
-close RAIDCONF;
-
-# ssl stuff
-my $private_key = "$config_dir/bbstored/$server-key.pem";
-my $certificate_request = "$config_dir/bbstored/$server-csr.pem";
-my $certificate = "$config_dir/bbstored/$server-cert.pem";
-my $ca_root_cert = "$config_dir/bbstored/clientCA.pem";
-
-# other files
-my $config_file = "$config_dir/bbstored.conf";
-my $accounts_file = "$config_dir/bbstored/accounts.txt";
-
-# summarise configuration
-
-print <<__E;
-
-Setup bbstored config utility.
-
-Configuration:
-   Writing configuration file: $config_file
-   Writing empty accounts file: $accounts_file
-   Server hostname: $server
-   RaidFile config: $raidfile_config
-
-__E
-
-# create directories
-if(!-d $config_dir)
-{
-	print "Creating $config_dir...\n";
-	mkdir $config_dir,0755 or die "Can't create $config_dir";
-}
-
-if(!-d "$config_dir/bbstored")
-{
-	print "Creating $config_dir/bbstored\n";
-	mkdir "$config_dir/bbstored",0755 or die "Can't create $config_dir/bbstored";
-}
-
-# create blank accounts file
-if(!-f $accounts_file)
-{
-	print "Creating blank accounts file\n";
-	open ACC,">$accounts_file";
-	close ACC;
-}
-
-# generate the private key for the server
-if(!-f $private_key)
-{
-	print "Generating private key...\n";
-	if(system("openssl genrsa -out $private_key 2048") != 0)
-	{
-		die "Couldn't generate private key."
-	}
-}
-
-# generate a certificate request
-if(!-f $certificate_request)
-{
-	die "Couldn't run openssl for CSR generation" unless
-		open(CSR,"|openssl req -new -key $private_key -sha1 -out $certificate_request");
-	print CSR <<__E;
-.
-.
-.
-.
-.
-$server
-.
-.
-.
-
-__E
-	close CSR;
-	print "\n\n";
-	die "Certificate request wasn't created.\n" unless -f $certificate_request
-}
-
-# write the configuration file
-print "Writing configuration file $config_file\n";
-open CONFIG,">$config_file" or die "Can't open config file for writing";
-print CONFIG <<__E;
-
-RaidFileConf = $raidfile_config
-AccountDatabase = $accounts_file
-
-# Uncomment this line to see exactly what commands are being received from clients.
-# ExtendedLogging = yes
-
-# scan all accounts for files which need deleting every 15 minutes.
-
-TimeBetweenHousekeeping = 900
-
-Server
-{
-	PidFile = /var/run/bbstored.pid
-	User = $username
-	ListenAddresses = inet:$server
-	CertificateFile = $certificate
-	PrivateKeyFile = $private_key
-	TrustedCAsFile = $ca_root_cert
-}
-
-
-__E
-
-close CONFIG;
-
-# explain to the user what they need to do next
-my $daemon_args = ($config_file eq $default_config_location)?'':" $config_file";
-
-print <<__E;
-
-===================================================================
-
-bbstored basic configuration complete.
-
-What you need to do now...
-
-1) Sign $certificate_request
-   using the bbstored-certs utility.
-
-2) Install the server certificate and root CA certificate as
-      $certificate
-      $ca_root_cert
-
-3) You may wish to read the configuration file
-      $config_file
-   and adjust as appropraite.
-
-4) Create accounts with bbstoreaccounts
-
-5) Start the backup store daemon with the command
-      /usr/local/bin/bbstored$daemon_args
-   in /etc/rc.local, or your local equivalent.
-
-===================================================================
-
-__E
-
-
-

Copied: box/chris/general/bin/bbstored/bbstored-config.in (from rev 674, box/trunk/bin/bbstored/bbstored-config.in)

Modified: box/chris/general/configure.ac
===================================================================
--- box/chris/general/configure.ac	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/configure.ac	2006-07-23 00:12:10 UTC (rev 675)
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
-AC_INIT([Box Backup], 0.09, [box@fluffy.co.uk])
+AC_INIT([Box Backup], 0.10, [box@fluffy.co.uk])
 AC_CONFIG_SRCDIR([lib/common/Box.h])
 AC_CONFIG_HEADERS([lib/common/BoxConfig.h])
 
@@ -26,6 +26,12 @@
   # Use -rdynamic if we have gcc. This is needed for backtrace
   AC_SUBST([LDADD_RDYNAMIC], ['-rdynamic'])
 fi
+AC_PATH_PROG([PERL], [perl], [no])
+if test "x$PERL" != "xno"; then
+  AC_DEFINE_UNQUOTED([PERL_EXECUTABLE], ["$PERL"], [Location of the perl executable])
+else
+  AC_MSG_ERROR([[perl executable was not found]])
+fi
 
 
 ### Checks for libraries.
@@ -126,7 +132,6 @@
 AC_STRUCT_TM
 AX_CHECK_DIRENT_D_TYPE
 AC_SYS_LARGEFILE
-AX_CHECK_LLONG_MINMAX
 AX_CHECK_DEFINE_PRAGMA
 if test "x$ac_cv_c_bigendian" != "xyes"; then
   AX_BSWAP64
@@ -226,12 +231,27 @@
 
 ### Output files
 AC_CONFIG_FILES([infrastructure/BoxPlatform.pm])
+AX_CONFIG_SCRIPTS([bin/bbackupd/bbackupd-config
+                   bin/bbackupquery/makedocumentation.pl
+                   bin/bbstored/bbstored-certs
+                   bin/bbstored/bbstored-config
+                   infrastructure/makebuildenv.pl
+                   infrastructure/makeparcels.pl
+                   lib/common/makeexception.pl
+                   lib/raidfile/raidfile-config
+                   lib/server/makeprotocol.pl
+                   runtest.pl
+                   test/backupstorefix/testfiles/testbackupstorefix.pl
+                   test/bbackupd/testfiles/extcheck1.pl
+                   test/bbackupd/testfiles/extcheck2.pl
+                   test/bbackupd/testfiles/notifyscript.pl])
+# TODO: Need to do contrib/cygwin/install-cygwin-service.pl but location varies
 AC_OUTPUT
 
 # Configure the Box build system
 echo
-perl ./infrastructure/makebuildenv.pl &&
-  perl ./infrastructure/makeparcels.pl
+$PERL ./infrastructure/makebuildenv.pl &&
+  $PERL ./infrastructure/makeparcels.pl
 
 # Write summary of important info
 cat <<EOC

Deleted: box/chris/general/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl
===================================================================
--- box/chris/general/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,112 +0,0 @@
-#!/usr/bin/perl -w
-
-
-# Contributed to the boxbackup project by Per Reedtz Thomsen. pthomsen@reedtz.com
-
-# This script reads the config file for boxbackup, and changes the mode
-# of the directory named by 'DataDirectory' and any files there. Also,
-# the files pointed to by the 'CommandSocket' and 'PidFile' configuration
-# parameters will be chmod'ed to be read-write by all.
-# The Windows services are created and started using the 'cygrunsrv' utility.
-
-# Date      Who                      Comments
-# 20041005  pthomsen@reedtz.com      Created 
-# 20041020  pthomsen@reedtz.com	     Switched to using Getopt::Std for cmd-line things.
-
-use strict;
-
-use Getopt::Std;
-getopt('ce');
-our ($opt_c, $opt_e);
-# Figure out the config file to use. Default is /etc/box/bbackupd.conf
-my $confFile = (defined($opt_c) ? $opt_c :  "/etc/box/bbackupd.conf");
-# Figure out the bbaackupd executable to use. Default is /usr/local/bin/bbackupd.exe
-my $exeFile = (defined($opt_e) ? $opt_e :  "/usr/local/bin/bbackupd.exe");
-
-die "File $confFile does not exist. Please provide the full path to the bbackupd configuration file.\n" if !(-f $confFile);
-die "Can't read $confFile. Permission denied. Please chmod the file so I can read it.\n" if !(-r $confFile);
-die "File $exeFile does not exist. Please provide the full path to the bbackupd.exe file.\n" if !(-f $exeFile);
-die "File $exeFile is not executable. Please provide the full path to the correct bbackupd.exe file.\n" if !(-x $exeFile);
-
-# print "Config: $confFile\n";
-
-my $dataDir;
-my $cmdSocket;
-my $pidFile;
-
-open (CONFIG, "<$confFile") or die "Can't open $confFile: $!\n";
-
-# Read the confgiguration file, and pull the DataDirectory, CommandSocket, and PidFile parameters.
-while (<CONFIG>)
-{
-    
-    if (/^\s*DataDirectory\s*=\s*([^\n\s]+)\s*\n/)
-    {
-	$dataDir = $1;
-	next;
-    }
-
-    if (/^\s*CommandSocket\s*=\s*([^\n\s]+)\s*\n/)
-    {
-	$cmdSocket = $1;
-	next;
-    }
-    if (/^\s*PidFile\s*=\s*([^\n\s]+)\s*\n/)
-    {
-	$pidFile = $1;
-	next;
-    }
-}
-
-# check that we got all the parameters from the file. If not, die.
-if ((!defined($dataDir)) || (!defined($cmdSocket)) || (!defined($pidFile)))
-{
-    die "Could not read config parameters from $confFile. Values retrieved:\n\tDataDirectory = $dataDir\n\tCommandSocket = $cmdSocket\n\tPidFile = $pidFile\n";
-}
-
-
-print  "Parameters retrieved from $confFile. Values:\n\tDataDirectory = $dataDir\n\tCommandSocket = $cmdSocket\n\tPidFile = $pidFile\n";
-print "chmod...";
-# change the mode of the files/dirs retrieved.
-chmod(0777, $dataDir) or die "Can't chmod $dataDir: $!\n";
-chmod(0666, "$dataDir/*") or die "Can't chmod $dataDir/*: $!\n";
-chmod(0666, $pidFile) or die "Can't chmod $pidFile: $!\n";
-chmod(0755, $cmdSocket) or die "Can't chmod $cmdSocket: $!\n";
-print " Done.\n";
-
-# Now install the service using cygrunsrv.
-# Details: 
-#   -I <svc_name>      Install a service. svc_name is the name under which the
-#                      service will appear in the Windows Service Manager
-#   -p <path_to_exe>   Path to the executable.
-#   -a <options>       Command line options to the executable.
-#   -f <description>   Description of the service.
-#   -o                 Attempt clean exit of service during system shutdown
-
-print "Installing boxbackup service...";
-my $sysCmd = "cygrunsrv.exe -I boxbackup -p " . $exeFile;
-$sysCmd .= " -a \"" . $confFile . " SINGLEPROCESS\"";
-$sysCmd .= " -o -f \"Online Backup System by Ben Summers\"";
-print "$sysCmd\n";
-my $output = qx($sysCmd);
-die "cygrunsrv failed to install service. Error Message: $output\n" if($output ne "");
-print " Done.\n";
-
-
-# Start the service
-# Details:
-#   -S <svc_name>     Start a service. svc_name is the name of the (installed)
-#                     service to start.
-
-print "Starting boxbackup service...";
-$sysCmd = "cygrunsrv.exe -S boxbackup";
-print "$sysCmd\n";
-$output = qx($sysCmd);
-die "cygrunsrv failed to start service. Error Message: $output\n" if($output ne "");
-print " Done.\n";
-
-print "\n\nService Installation complete. To test, reboot your machine, and make sure that\n";
-print "the boxbackup service is running. A good way to make sure, is to check that the account number\n";
-print "from this machine is connecting to the bbstored server. Check the bbstored logs for more info.\n\n";
-
-

Copied: box/chris/general/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl.in (from rev 674, box/trunk/distribution/boxbackup/contrib/cygwin/install-cygwin-service.pl.in)

Copied: box/chris/general/documentation (from rev 674, box/trunk/documentation)

Copied: box/chris/general/documentation/boxbackup (from rev 674, box/trunk/documentation/boxbackup)

Deleted: box/chris/general/documentation/boxbackup/Makefile
===================================================================
--- box/trunk/documentation/boxbackup/Makefile	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/Makefile	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,64 +0,0 @@
-
-
-# Process DocBook to HTML
-
-DBPROC=/usr/bin/xsltproc
-BOOKXSL=bb-book.xsl
-NOCHUNKBOOKXSL=bb-nochunk-book.xsl
-MANXSL=bb-man.xsl
-HTMLPREFIX=box-html
-VPATH= adminguide
-.SUFFIXES: .html .xml
-
-all: adminguide instguide manpages 
-
-adminguide: $(HTMLPREFIX)/adminguide/index.html 
-
-$(HTMLPREFIX)/adminguide/index.html: adminguide.xml ExceptionCodes.xml $(BOOKXSL)
-	# docname=`echo $@ | sed -e 's/\/index.html//'`
-	$(DBPROC) -o $(HTMLPREFIX)/adminguide/ $(BOOKXSL) adminguide.xml
-
-instguide: $(HTMLPREFIX)/instguide/index.html 
-
-$(HTMLPREFIX)/instguide/index.html: instguide.xml $(BOOKXSL)
-	$(DBPROC) -o $(HTMLPREFIX)/instguide/ $(BOOKXSL) instguide.xml
-
-ExceptionCodes.xml: ../../ExceptionCodes.txt
-	perl ./generate_except_xml.pl
-
-manpages: man-dirs man-nroff man-html
-
-man-dirs: man-pages/.there $(HTMLPREFIX)/man-html/.there
-
-$(HTMLPREFIX)/man-html/.there:
-	if [ ! -d man-html ]; then mkdir -p $(HTMLPREFIX)/man-html; touch $(HTMLPREFIX)/man-html/.there; fi
-
-man-pages/.there:
-	if [ ! -d man-pages ]; then mkdir man-pages; touch man-pages/.there; fi
-
-man-nroff: bbackupquery.1 bbackupctl.1 bbstoreaccounts.1 bbstored-config.1 raidfile-config.1 bbstored-certs.1
-
-man-html: bbackupquery.html bbackupctl.html bbstoreaccounts.html bbstored-config.html raidfile-config.html bbstored-certs.html
-
-%.html: %.xml
-	$(DBPROC) -o $@ $(NOCHUNKBOOKXSL) $<
-	mv $@ $(HTMLPREFIX)/man-html/.
-
-%.1: %.xml
-	$(DBPROC) -o $@ $(MANXSL) $<
-	mv $@ man-pages/.
-	gzip -f -9 man-pages/$@
-
-dockit: instguide adminguide manpages
-	mkdir $(HTMLPREFIX)/images
-	cp html/images/*.png $(HTMLPREFIX)/images/.
-	cp html/*.css $(HTMLPREFIX)/.
-	tar zcf documentation-kit-0.10.tar.gz $(HTMLPREFIX)/
-
-clean:
-	if [ -d ./$(HTMLPREFIX) ]; then rm -rf $(HTMLPREFIX) ; fi
-	if [ -d ./man-pages ]; then  rm -rf ./man-pages/; fi
-	if [ -f ExceptionCodes.xml ]; then rm ExceptionCodes.xml; fi
-	if [ -f documentation-kit-0.10.tar.gz ]; then rm documentation-kit-0.10.tar.gz; fi
-
-

Copied: box/chris/general/documentation/boxbackup/Makefile (from rev 674, box/trunk/documentation/boxbackup/Makefile)

Deleted: box/chris/general/documentation/boxbackup/adminguide.xml
===================================================================
--- box/trunk/documentation/boxbackup/adminguide.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/adminguide.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,1232 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
-"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
-<!ENTITY __ExceptionCodes__elfjz3fu SYSTEM "ExceptionCodes.xml">
-]>
-<book>
-  <title>Box Backup administrator's guide</title>
-
-  <preface>
-    <title>License</title>
-
-    <para>Copyright © 2003 - 2006, Ben Summers and contributors. All rights
-    reserved.</para>
-
-    <para>Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>Redistributions of source code must retain the above copyright
-        notice, this list of conditions and the following disclaimer.</para>
-      </listitem>
-
-      <listitem>
-        <para>Redistributions in binary form must reproduce the above
-        copyright notice, this list of conditions and the following disclaimer
-        in the documentation and/or other materials provided with the
-        distribution.</para>
-      </listitem>
-
-      <listitem>
-        <para>Neither the name of the authors nor the names of its
-        contributors may be used to endorse or promote products derived from
-        this software without specific prior written permission</para>
-      </listitem>
-    </itemizedlist>
-
-    <para>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</para>
-  </preface>
-
-  <chapter>
-    <title>Configuration</title>
-
-    <section>
-      <title>System configuration</title>
-
-      <section>
-        <title>Server</title>
-
-        <para>After you've downloaded and compiled the programs you need to
-        install the programs on your server. As root do the following:</para>
-
-        <programlisting>make install-backup-server</programlisting>
-
-        <para>This assumes that you are installing on the same server that you
-        compiled the software on. If not, copy the
-        boxbackup-x.xx-backup-server-OSNAME.tgz file to the server you want to
-        run on, and install there. For example (on Mac OS X):</para>
-
-        <programlisting>tar zxvf boxbackup-0.10-server-darwin8.5.0.tgz
-cd boxbackup-0.10-server-darwin8.5.0
-./install-backup-server</programlisting>
-
-        <para>Then create the user for the backup daemon on the server:</para>
-
-        <programlisting>useradd _bbstored</programlisting>
-
-        <para>BoxBackup supports Raid for the backup store. There are some
-        configuration options. Use the following command if you want to create
-        a simple server WITHOUT Raid protection:</para>
-
-        <programlisting>mkdir /tmp/boxbackupRepository                        # Create the directory
-chown _bbstored /tmp/boxbackupRepository/             # Change the owner to the new boxbackup daemon user
-
-/usr/local/bin/raidfile-config /etc/box/  1024 /tmp/boxbackupRepository
-
-#substitute 1024 with the desired blocksize
-#substitute /tmp/boxbackupRepository with a directory that exists where you want the backup store located
-#/usr/local/bin/raidfile-config --help shows you the options</programlisting>
-
-        <para>Then create the configuration file /etc/box/bbstored.conf The
-        hostname is tricky as it is used for two things: The name of the
-        server in the certificate and the address the server is listening on.
-        Since you might be using NAT, might move the server around or the
-        domain name might change, choose a name that describes the server.
-        When the network address of the server changes, you need to update the
-        ListenAddresses directive in the /etc/box/bbstored.conf file.</para>
-
-        <programlisting>/usr/local/bin/bbstored-config /etc/box hostname _bbstored</programlisting>
-
-        <para>This last step outputs 5 instructions that you must execute to
-        the letter. A lot of questions are raised on the mailing list because
-        these steps have not been followed properly.</para>
-
-        <para>TODO: Expand on this. Explain the 5 steps in detail.</para>
-
-        <para>If you want to run the system as a non-root user, look <link
-        linkend="WORoot">here</link>.</para>
-      </section>
-
-      <section>
-        <title>Certificate Management</title>
-
-        <para>There are two steps involved to create an account. You need to
-        create the account on the server, and sign a certificate to give the
-        client permission to connect to the server.</para>
-
-        <para>Running a Certification Authority for TLS (SSL) connections is
-        not trivial. However, a script to does most of the work in a way which
-        should be good enough for most deployments.</para>
-
-        <para><emphasis role="bold">Important Note:</emphasis> The certificate
-        authority directory is intended to be stored on another server. It
-        should not be kept on the backup server to limit the impact of a
-        server compromise. The instructions and the script assume that it will
-        be kept elsewhere, so will ask you to copy files to and from the
-        CA.</para>
-
-        <para><emphasis role="bold">Clock time warning</emphasis>: SSL
-        certificates contain validity dates, including a "valid from" time. If
-        the clock on the machine which signs the certificates is not
-        syncronised to the clocks of the machines using these certificates,
-        you will probably get strange errors until the start time is reached
-        on all machines. If you get strange errors when attempting to use new
-        certificates, check the clocks! You will probably just need to wait a
-        while until the certificates become valid, rather than having to
-        regenerate them.</para>
-
-        <section>
-          <title>Set up a CA</title>
-
-          <para>It's best to do this on a machine other than your server,
-          probably without direct network access. The contents of this
-          directory control who can access your backup store server.</para>
-
-          <para>To setup the basic key structure, do the following:</para>
-
-          <programlisting>/usr/local/bin/bbstored-certs ca init</programlisting>
-
-          <para>(See <link linkend="instguide.xml">OpenSSL notes</link> if you
-          get an OpenSSL error)</para>
-
-          <para>This creates the directory 'ca' in the current directory, and
-          initialises it with basic keys.</para>
-        </section>
-
-        <section>
-          <title>Sign a server certificate</title>
-
-          <para>When you use the bbstored-config script to set up a config
-          file for a server, it will generate a certificate request (CSR) for
-          you. Transfer it to the machine with your CA, then do:</para>
-
-          <programlisting>/usr/local/bin/bbstored-certs ca sign-server hostname-csr.pem</programlisting>
-
-          <para>This signs the certificate for the server. Follow the
-          instructions in the output on which files to install on the server.
-          The CSR file is now no longer needed. Make sure you run this command
-          from the directory above the directory 'ca'.</para>
-
-          <para>TODO: Explain instructions in output.</para>
-        </section>
-
-        <section>
-          <title>Set up an account</title>
-
-          <para>Choose an account number for the user. This must be unique on
-          the server, and is presented as a 31 bit number in hex greater than
-          0, for example, 1 or 75AB23C. Then on the backup store server,
-          create the account with:</para>
-
-          <programlisting>/usr/local/bin/bbstoreaccounts create 75AB23C 0 4096M 4505M</programlisting>
-
-          <para>This looks complicated. The numbers are, in order:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para>The account number allocated (hex)</para>
-            </listitem>
-
-            <listitem>
-              <para>The RAID disc set (0 if you use raidfile-config and don't
-              add a new set)</para>
-            </listitem>
-
-            <listitem>
-              <para>Soft limit (size)</para>
-            </listitem>
-
-            <listitem>
-              <para>Hard limit (size)</para>
-            </listitem>
-          </itemizedlist>
-
-          <para>The sizes are are specified in Mb, Gb, or blocks, depending on
-          the suffix. 1M specifies 1 Mb, 1G specifies 1 Gb, and 1B specifies 1
-          block, the size of which depends on how you have configured the
-          raidfile system with raidfile-config.</para>
-
-          <para>In this example, I have allocated 4Gb (assuming you use 2048
-          byte blocks as per my example) as the soft limit, and 4Gb + 10% as
-          the hard limit.</para>
-
-          <para>NOTE The sizes specified here are pre-RAID. So if you are
-          using userland RAID, you are actually allocating two-thirds of this
-          amount. This means that, when you take compression into account,
-          that if you allocate 2Gb on the server, it'll probably hold about
-          2Gb of backed up files (depending on the compressability of those
-          files).</para>
-
-          <para>The backup client will (voluntarily) try not to upload more
-          data than is allowed by the soft limit. The store server will refuse
-          to accept a file if it would take it over the hard limit, and when
-          doing housekeeping for this account, try and delete old versions and
-          deleted files to reduce the space taken to below the soft
-          limit.</para>
-
-          <para>This command will create some files on disc in the raid file
-          directories (if you run as root, the utility will change to the user
-          specified in the bbstored.conf file to write them) and update the
-          accounts file. A server restart is not required.</para>
-
-          <para>NOTE If you get a message saying 'Exception: RaidFile (2/8)',
-          the directories you specified in the raidfile.conf are not writable
-          by the _bbstored user -- fix it, and try again.</para>
-
-          <para>Finally, tell the user their account number, and the hostname
-          of your server. They will use this to set up the backup client, and
-          send you a CSR. This has the account number embedded in it, and you
-          should be sure that it has the right account number in it.</para>
-
-          <para>Sign this CSR with this command:</para>
-
-          <programlisting>/usr/local/bin/bbstored-certs ca sign 75AB23C-csr.pem</programlisting>
-
-          <para>Don't forget to check that the embedded account number is
-          correct! Then send the two files back to the user, as instructed by
-          the script.</para>
-
-          <para>Please read the Troubleshooting page if you have
-          problems.</para>
-
-          <para>TODO: Link to troubleshooting...</para>
-        </section>
-      </section>
-
-      <section>
-        <title>Log Files</title>
-
-        <para>You may wish to see what's going on with the server. Edit
-        /etc/syslog.conf, and add:</para>
-
-        <programlisting>local6.info                         /var/log/box
-local5.info                         /var/log/raidfile</programlisting>
-
-        <para><emphasis role="bold">Note:</emphasis> Separators must be tabs,
-        otherwise these entries will be ignored.</para>
-
-        <programlisting>touch /var/log/box
-touch /var/log/raidfile</programlisting>
-
-        <para>Set up log rotation, by adding in /etc/newsyslog.conf:</para>
-
-        <programlisting>/var/log/box                644  7    2000 *     Z
-/var/log/raidfile           644  7    2000 *     Z</programlisting>
-
-        <para>Then restart syslogd.</para>
-      </section>
-
-      <section>
-        <title>Configuring a client</title>
-
-        <para>Before you can do any configuration, you need to know the
-        hostname of the server you will be using, and your account number on
-        that server.</para>
-
-        <para>Later in the process, you will need to send a certificate
-        request to the administrator of that server for it to be
-        signed.</para>
-
-        <para>Installation is covered in the compiling and installing section.
-        You only need the backup-client parcel.</para>
-
-        <para>It is important that you read all the output of the config
-        scripts. See the end of this page for an example.</para>
-
-        <para>The backup client has to be run as root, because it needs to
-        read all your files to back them up, although it is possible to back
-        up a single user's files by running it as that user. (Tip: specify a
-        directory other than /etc/box, and then give the alternate config file
-        as the first argument to bbackupd). However, it will fall over if you
-        don't give yourself read access to one of your files.</para>
-
-        <section>
-          <title id="BasicConfig">Basic configuration</title>
-
-          <para>Run the bbackupd-config script to generate the configuration
-          files and generate a private key and certificate request.</para>
-
-          <programlisting>/usr/local/bin/bbackupd-config /etc/box lazy <emphasis
-              role="bold">999 hostname</emphasis> /var/bbackupd <emphasis
-              role="bold">/home</emphasis></programlisting>
-
-          <para>(See <link linkend="instguide.sgml">OpenSSL notes</link> if
-          you get an OpenSSL error)</para>
-
-          <para>The items in bold need to be changed. In order, they are the
-          account number, the hostname of the server you're using, and
-          finally, the directories you want backed up. You can include as many
-          you want here.</para>
-
-          <para>However, the directories you specify must not contain other
-          mounted file systems within them at any depth. Specify them
-          separately, one per mount point. No checks are currently made to
-          catch bad configuration of this nature!</para>
-
-          <para>You may also want to consider changing the mode from lazy to
-          snapshot, depending on what your system is used for.</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><emphasis role="bold">lazy</emphasis>. This mode regularly
-              scans the files, with only a rough schedule. It uploads files as
-              and when they are changed, if the latest version is more than a
-              set age. This is good for backing up user's documents stored on
-              a server, and spreads the load out over the day.</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">snapshot</emphasis>. This mode
-              emulates the traditional backup behaviour of taking a snapshot
-              of the filesystem. The backup daemon does absolutely nothing
-              until it is instructed to make a backup using the bbackupctl
-              utility (probably as a cron job), at which point it uploads all
-              files which have been changed since the last time it
-              uploaded.</para>
-            </listitem>
-          </itemizedlist>
-
-          <para>When you run the config script, it will tell you what you need
-          to do next. Don't forget to read all the output. An example is shown
-          at the end of this page, but the instructions for your installation
-          may be different.</para>
-        </section>
-
-        <section>
-          <title>Certificates</title>
-
-          <para>After you have sent your certificate request off to the server
-          administrator and received your certificate and CA root back,
-          install them where instructed by the bbackupd-config script during
-          basic bbackupd configuration.</para>
-
-          <para>You can then run the daemon (as root) by typing
-          /usr/local/bin/bbackupd, and of course, adding it to your system's
-          startup scripts. The first time it's run it will upload everything.
-          Interrupting it and restarting it will only upload files which were
-          not uploaded before - it's very tolerant.</para>
-
-          <para>If you run in snapshot mode, you will need to add a cron job
-          to schedule backups. The config script will tell you the exact
-          command to use for your system.</para>
-
-          <para>Please read the Troubleshooting page if you have
-          problems.</para>
-
-          <para>Remember to make a traditional backup of the keys file, as
-          instructed. You cannot restore files without it.</para>
-
-          <para>It is recommended that you backup up all of /etc/box as it
-          will make things easier if you need to restore files. But only the
-          keys are absolutely essential.</para>
-
-          <para>If you want to see what it's doing in more detail (probably a
-          good idea), follow the instructions in the server setup to create
-          new log files with syslog. Adding and removing backed up
-          locations.</para>
-
-          <para>By editing the /etc/box/bbackupd.conf file, you can add and
-          remove directories to back up -- see comments in this file for help.
-          Send bbackupd a HUP signal after you modify it.</para>
-
-          <para>When you remove a location, it will not be marked as deleted
-          immediately. Instead, bbackupd waits about two days before doing so,
-          just in case you change your mind. After this, it will be eventually
-          removed from the store by the housekeeping process. Run as
-          root.</para>
-
-          <para>The backup client is designed to be run as root. It is
-          possible to run without root, but this is not recommended. Clock
-          synchronisation for file servers.</para>
-
-          <para>If you are using the backup client to backup a filesystem
-          served from a fileserver, you should ideally ensure that the
-          fileserver clocks are synchronised with the fileserver.</para>
-
-          <para>bbackupd will cope perfectly well if the clocks are not
-          synchronised. Errors up to about half an hour cause no problems.
-          Larger discrepancies cause a loss of efficiency and the potential to
-          back up a file during a write process.</para>
-
-          <para>There is a configuration parameter MaxFileTimeInFuture, which
-          specifies how far in the future a file must be for it to be uploaded
-          as soon as it is seen. You should not need to adjust this (default
-          is 2 days). Instead, get those clocks synchronised. Excluding files
-          and directories from the backup.</para>
-
-          <para>Within the bbackupd.conf file, there is a section named
-          BackupLocations which specifies which locations on disc should be
-          backed up. It has subsections, each of which is in the
-          format:</para>
-
-          <programlisting> name
- {
-    Path = /path/of/directory
-    (optional exclude directives)
- }</programlisting>
-
-          <para><emphasis role="bold">name</emphasis> is derived from the Path
-          by the config script, but should merely be unique.</para>
-
-          <para>The exclude directives are of the form:</para>
-
-          <programlisting>[Exclude|AlwaysInclude][File|Dir][|sRegex] = regex or full pathname</programlisting>
-
-          <para>(The regex suffix is shown as 'sRegex' to make File or Dir
-          plural)</para>
-
-          <para>For example:</para>
-
-          <programlisting> ExcludeDir = /home/guest-user
- ExcludeFilesRegex = *.(mp3|MP3)\$
- AlwaysIncludeFile = /home/username/veryimportant.mp3</programlisting>
-
-          <para>This excludes the directory /home/guest-user from the backup
-          along with all mp3 files, except one MP3 file in particular.</para>
-
-          <para>In general, Exclude excludes a file or directory, unless the
-          directory is explicitly mentioned in a AlwaysInclude
-          directive.</para>
-
-          <para>If a directive ends in Regex, then it is a regular expression
-          rather than a explicit full pathname. See</para>
-
-          <programlisting> man 7 re_format</programlisting>
-
-          <para>for the regex syntax on your platform.</para>
-        </section>
-
-        <section>
-          <title>Example configuration output</title>
-
-          <para>This is an example of output from the bbstored-config
-          script.</para>
-
-          <para><emphasis role="bold">Important</emphasis>: Follow the
-          instructions output by your script, not the ones here -- they may be
-          different for your system.</para>
-
-          <programlisting>/usr/local/bin/bbackupd-config /etc/box lazy 51 server.example.com /var/bbackupd /home /etc/samba
-
-Setup bbackupd config utility.
-
-Configuration:
-   Writing configuration file: /etc/box/bbackupd.conf
-   Account: 51
-   Server hostname: server.example.com
-   Directories to back up:
-      /home
-      /etc/samba
-
-Note: If other file systems are mounted inside these directories, then problems may occur
-with files on the store server being renamed incorrectly. This will cause efficiency
-problems, but not affect the integrity of the backups.
-
-WARNING: Directories not checked against mountpoints. Check mounted filesystems manually.
-
-Creating /etc/box...
-Creating /etc/box/bbackupd
-Generating private key...
- [OpenSSL output omitted]
-
-Generating keys for file backup
-Writing notify script /etc/box/bbackupd/NotifyStoreFull.sh
-Writing configuration file /etc/box/bbackupd.conf
-
-===================================================================
-
-bbackupd basic configuration complete.
-
-What you need to do now...
-
-1) Make a backup of /etc/box/bbackupd/51-FileEncKeys.raw
-   This should be a secure offsite backup.
-   Without it, you cannot restore backups. Everything else can
-   be replaced. But this cannot.
-   KEEP IT IN A SAFE PLACE, OTHERWISE YOUR BACKUPS ARE USELESS.
-
-2) Send /etc/box/bbackupd/51-csr.pem
-   to the administrator of the backup server, and ask for it to
-   be signed.
-
-3) The administrator will send you two files. Install them as
-      /etc/box/bbackupd/51-cert.pem
-      /etc/box/bbackupd/serverCA.pem
-   after checking their authenticity.
-
-4) You may wish to read the configuration file
-      /etc/box/bbackupd.conf
-   and adjust as appropraite.
-   
-   There are some notes in it on excluding files you do not
-   wish to be backed up.
-
-5) Review the script
-      /etc/box/bbackupd/NotifyStoreFull.sh
-   and check that it will email the right person when the store
-   becomes full. This is important -- when the store is full, no
-   more files will be backed up. You want to know about this.
-
-6) Start the backup daemon with the command
-      /usr/local/bin/bbackupd
-   in /etc/rc.local, or your local equivalent.
-   Note that bbackupd must run as root.
-
-===================================================================</programlisting>
-
-          <para>Remember to make a secure, offsite backup of your backup keys,
-          as described in <link linkend="BasicConfig">Basic
-          configuration</link> above. If you do not,, and that key is lost,
-          you have no backups.</para>
-        </section>
-      </section>
-    </section>
-  </chapter>
-
-  <chapter>
-    <title>Administration</title>
-
-    <para>This chapter deals with the dauily running and management of the Box
-    Backup system. It explains most day-to-day tasks.</para>
-
-    <section>
-      <title>Regular Maintenance</title>
-
-      <para>The steps involved in maintaining and keeping the backup sets
-      healthy are outlined in this section.</para>
-
-      <section>
-        <title>Controlling a backup client</title>
-
-        <para>The bbackupctl program sends control commands to the bbackupd
-        daemon. It must be run as the same user as the daemon, and there is no
-        exception for root.</para>
-
-        <para>The command line syntax is:</para>
-
-        <programlisting>/usr/local/bin/bbackupctl [-q] [-c config-file] command</programlisting>
-
-        <para>The -q option reduces the amount of output the program emits,
-        and -c allows an alternative configuration file to be
-        specified.</para>
-
-        <para>Valid commands are:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para><emphasis role="bold">terminate</emphasis></para>
-
-            <para>Stop the bbackupd daemon now (equivalent to kill)</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="bold">reload</emphasis></para>
-
-            <para>Reload the configuration file (equivalent to kill
-            -HUP)</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="bold">sync</emphasis></para>
-
-            <para>Connect to the server and synchronise files now</para>
-          </listitem>
-        </itemizedlist>
-
-        <para><emphasis role="bold">bbackupctl</emphasis> communicates with
-        the server via a UNIX domain socket, specified in bbackupd.conf with
-        the CommandSocket directive. This does not need to be specified, and
-        <emphasis role="bold">bbackupd</emphasis> will run without the command
-        socket, but in this case bbackupctl will not be able to communicate
-        with the daemon.</para>
-
-        <para>Some platforms cannot check the user id of the connecting
-        process, so this command socket becomes a denial of service security
-        risk. <emphasis role="bold">bbackupd</emphasis> will warn you when it
-        starts up if this is the case on your platform, and you should
-        consider removing the CommandSocket directive on these
-        platforms.</para>
-      </section>
-
-      <section>
-        <title>Using bbackupctl to perform snapshots</title>
-
-        <para><emphasis role="bold">bbackupctl</emphasis>'s main purpose is to
-        implement snapshot based backups, emulating the behaviour of
-        traditional backup software.</para>
-
-        <para>Use bbackupd-config to write a configuration file in snapshot
-        mode, and then run the following command as a cron job.</para>
-
-        <programlisting>/usr/local/bin/bbackupctl -q sync</programlisting>
-
-        <para>This will cause the backup daemon to upload all changed files
-        immediately. <emphasis role="bold">bbackupctl</emphasis> will exit
-        almost immediately, and will not output anything unless there is an
-        error.</para>
-      </section>
-
-      <section>
-        <title>Checking storage space used on the server</title>
-
-        <section>
-          <title>From the client machine</title>
-
-          <para>bbackupquery can tell you how much space is used on the server
-          for this account. Either use the usage command in interactive mode,
-          or type:</para>
-
-          <programlisting>/usr/local/bin/bbackupquery -q usage quit</programlisting>
-
-          <para>to show the space used as a single command.</para>
-        </section>
-
-        <section>
-          <title>On the server</title>
-
-          <para>bbstoreaccounts allows you to query the space used, and change
-          the limits. To display the space used on the server for an account,
-          use:</para>
-
-          <programlisting>/usr/local/bin/bbstoreaccounts info 75AB23C</programlisting>
-
-          <para>To adjust the soft and hard limits on an account, use:</para>
-
-          <programlisting>/usr/local/bin/bbstoreaccounts setlimit 75AB23C new-soft-limit new-hard-limit</programlisting>
-
-          <para>You do not need to restart the server.</para>
-        </section>
-      </section>
-
-      <section>
-        <title>Verify and restore files</title>
-
-        <para>Backups are no use unless you can restore them. The bbackupquery
-        utility does this and more.</para>
-
-        <para>You don't provide any login information to it, as it just picks
-        up the data it needs from /etc/box/bbackupd.conf. You should run it as
-        root so it can find everything it needs.</para>
-
-        <para>Full documentation can be found in the <link
-        linkend="bbackupquery.xml">bbackupquery man page</link>. It follows
-        the model of a command line sftp client quite closely.</para>
-
-        <para>TODO: Link to bbackupquery man-page here.</para>
-
-        <para>On systems where GNU readline is available (by default) it uses
-        that for command line history and editing. Otherwise it falls back to
-        very basic UNIX text entry.</para>
-
-        <para>TODO: Did the readline dependency change to editline?</para>
-
-        <section>
-          <title>Using bbackupquery</title>
-
-          <para>bbackupquery is the tool you use to verify, restore and
-          investigate your backup files with. When invoked, it simply logs
-          into the server using the certificates you have listed in
-          bbackupd.conf.</para>
-
-          <para>After you run bbackupquery, you will see a prompt, allowing
-          you to execute commands. The list (or ls) command lets you view
-          files in the store. It works much like unix ls, but with different
-          options. An example:</para>
-
-          <programlisting>[pthomsen@host bbackupquery]$ bbackupquery 
-Box Backup Query Tool  v0.10, (c) Ben Summers and contributors 2003-2006
-Using configuration file /etc/box/bbackupd.conf
-Connecting to store...
-Handshake with store...
-Login to store...
-Login complete.
-
-Type "help" for a list of commands.
-
-query &gt; ls
-00000002 -d---- mp3
-00000003 -d---- video
-00000004 -d---- home-pthomsen
-00000005 -d---- root
-query &gt;   </programlisting>
-
-          <para>The ls commands shows the directories that are backed up. Now
-          we'll take a closer look at the home-pthomsen directory:</para>
-
-          <programlisting>query &gt; cd home-pthomsen
-query &gt; ls
-00002809 f----- sample.tiff
-0000280a f----- s3.tiff
-0000280b f----- s4.tiff
-0000280d f----- s2.tiff
-0000280e f----- foo.pdf
-0000286c f----- core.28720
-0000339a -d---- .emacs.d
-0000339d -d---- bbackup-contrib
-00003437 f----- calnut.compare.txt
-0000345d f----- DSCN1783.jpg
-0000345e f----- DSCN1782.jpg
-query &gt;</programlisting>
-
-          <para>The ls command takes the following options;</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><emphasis role="bold">-r </emphasis>-- recursively list
-              all files</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">-d</emphasis> -- list deleted
-              files/directories</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">-o</emphasis> -- list old versions
-              of files/directories</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">-I</emphasis> -- don't display
-              object ID</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">-F </emphasis>-- don't display
-              flags</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">-t </emphasis>-- show file
-              modification time (and attr mod time if has the object has
-              attributes, ~ separated)</para>
-            </listitem>
-
-            <listitem>
-              <para><emphasis role="bold">-s</emphasis> -- show file size in
-              blocks used on server (only very approximate indication of size
-              locally)</para>
-            </listitem>
-          </itemizedlist>
-
-          <para>The flags displayed from the ls command are as follows:</para>
-
-          <simplelist>
-            <member>f = file</member>
-
-            <member>d = directory</member>
-
-            <member>X = deleted</member>
-
-            <member>o = old version</member>
-
-            <member>R = remove from server as soon as marked deleted or
-            old</member>
-
-            <member>a = has attributes stored in directory record which
-            override attributes in backup file</member>
-          </simplelist>
-        </section>
-
-        <section>
-          <title>Verify backups</title>
-
-          <para>Since this system is not yet 100% production-ready, you'll be
-          keen to verify that your backups are correct. This is easy:</para>
-
-          <programlisting>/usr/local/bin/bbackupquery "compare -a" quit</programlisting>
-
-          <para>It will report all the differences between the store and the
-          files on disc. It will download everything, so may take a while. You
-          should expect to see some differences on a typical compare, because
-          files which have recently changed are unlikely to have been uploaded
-          yet. Consider checking the timestamps on the files, or keeping a
-          record of these messages and comparing them with a future
-          verification.</para>
-
-          <para>If you would like to do a "quick" check which just downloads
-          file checksums and compares against that, then do:</para>
-
-          <programlisting>/usr/local/bin/bbackupquery "compare -aq" quit</programlisting>
-
-          <para>However, this does not check that the file attributes are
-          correct, and since the checksums are generated on the client they
-          may not reflect the data on the server if there is a problem -- the
-          server cannot check the encrypted contents. View this as a good
-          indication, rather than a definite check that your backup verifies
-          correctly.</para>
-
-          <para>You may wish to run either one as a cron job while testing
-          this system.</para>
-        </section>
-
-        <section>
-          <title>Restore backups</title>
-
-          <para>You will need the keys file created when you configured the
-          server. Without it, you cannot restore the files; this is the
-          downside of encrypted backups. However, by keeping the small keys
-          file safe, you indirectly keep your entire backup safe.</para>
-
-          <para>The first step is to recreate the configuration of the backup
-          client. It's probably best to have stored the /etc/box directory
-          with your keys. But if you're recreating it, all you really need is
-          to have got the login infomation correct (ie the certs and
-          keys).</para>
-
-          <para>Don't run bbackupd yet! It will mark all your files as deleted
-          if you do, which is not hugely bad in terms of losing data, just a
-          major inconvenience. (This assumes that you are working from a blank
-          slate. If you want to restore some files to a different location,
-          it's fine to restore while bbackupd is running, just do it outside a
-          backed up directory to make sure it doesn't start uploading the
-          restored files.)</para>
-
-          <para>Type:</para>
-
-          <programlisting>/usr/local/bin/bbackupquery</programlisting>
-
-          <para>to run it in interactive mode.</para>
-
-          <para>Type:</para>
-
-          <programlisting>list</programlisting>
-
-          <para>to see a list of the locations stored on the server.</para>
-
-          <para>For each location you want to restore, type:</para>
-
-          <programlisting>restore name-on-server local-dir-name</programlisting>
-
-          <para>The directory specified by local-dir-name must not exist yet.
-          If the restore is interrupted for any reason, repeat the above
-          steps, but add the <emphasis role="bold">-r</emphasis> flag to the
-          restore command to tell it to resume.</para>
-        </section>
-
-        <section>
-          <title>Retrieving deleted and old files</title>
-
-          <para>Box Backup makes old versions of files and files you have
-          deleted available, subject to there being enough disc space on the
-          server to hold them.</para>
-
-          <para>This is how to retrieve them using bbackupquery. Future
-          versions will make this far more user-friendly.</para>
-
-          <para>Firstly, run bbackupquery in interactive mode. It behaves in a
-          similar manner to a command line sftp client.</para>
-
-          <programlisting>/usr/local/bin/bbackupquery</programlisting>
-
-          <para>Then navigate to the directory containing the file you want,
-          using list, cd and pwd.</para>
-
-          <programlisting>query &gt; cd home/profiles/USERNAME</programlisting>
-
-          <para>List the directory, using the "o" option to list the files
-          available without filtering out everything apart from the current
-          version. (if you want to see deleted files as well, use list
-          -odt)</para>
-
-          <programlisting>query &gt; list -ot
-00000078 f--o- 2004-01-21T20:17:48 NTUSER.DAT
-00000079 f--o- 2004-01-21T20:17:48 ntuser.dat.LOG
-0000007a f--o- 2004-01-21T17:55:12 ntuser.ini
-0000007b f---- 2004-01-12T15:32:00 ntuser.pol
-0000007c -d--- 1970-01-01T00:00:00 Templates
-00000089 -d--- 1970-01-01T00:00:00 Start Menu
-000000a0 -d--- 1970-01-01T00:00:00 SendTo
-000000a6 -d--- 1970-01-01T00:00:00 Recent
-00000151 -d--- 1970-01-01T00:00:00 PrintHood
-00000152 -d--- 1970-01-01T00:00:00 NetHood
-00000156 -d--- 1970-01-01T00:00:00 My Documents
-0000018d -d--- 1970-01-01T00:00:00 Favorites
-00000215 -d--- 1970-01-01T00:00:00 Desktop
-00000219 -d--- 1970-01-01T00:00:00 Cookies
-0000048b -d--- 1970-01-01T00:00:00 Application Data
-000005da -d--- 1970-01-01T00:00:00 UserData
-0000437e f--o- 2004-01-24T02:45:43 NTUSER.DAT
-0000437f f--o- 2004-01-24T02:45:43 ntuser.dat.LOG
-00004380 f--o- 2004-01-23T17:01:29 ntuser.ini
-00004446 f--o- 2004-01-24T02:45:43 NTUSER.DAT
-00004447 f--o- 2004-01-24T02:45:43 ntuser.dat.LOG
-000045f4 f---- 2004-01-26T15:54:16 NTUSER.DAT
-000045f5 f---- 2004-01-26T15:54:16 ntuser.dat.LOG
-000045f6 f---- 2004-01-26T16:54:31 ntuser.ini</programlisting>
-
-          <para>(this is a listing from a server which is used as a Samba
-          server for a network of Windows clients.) You now need to fetch the
-          file using it's ID, rather than it's name. The ID is the hex number
-          in the first column. Fetch it like this:</para>
-
-          <programlisting>query &gt; get -i 0000437e NTUSER.DAT
-Object ID 0000437e fetched successfully.</programlisting>
-
-          <para>The object is now available on your local machine. You can use
-          lcd to move around, and sh ls to list directories on your local
-          machine.</para>
-        </section>
-      </section>
-    </section>
-
-    <section>
-      <title id="FixCorruptions">Fixing corruptions of store data</title>
-
-      <para>This section gives help on what to do if your server has suffered
-      corruption, for example, after an unclean shutdown or other OS or
-      hardware problem.</para>
-
-      <para>In general, as updates to the store are made in an atomic manner,
-      the most likely result is wasted disc space. However, if really bad
-      things happen, or you believe that there is a lot of wasted space, then
-      these instructions will help to restore your data.</para>
-
-      <para>You know you will need to do something if you get strange errors,
-      and bbackupd attempts to contact the server every 100 seconds or so. Or
-      if one of the discs in your RAID disc set has failed.</para>
-
-      <para>After following these instructions, the end result will be that
-      bbackupquery will be able to see all the files which were stored on your
-      server, and retrieve them. Some of them may be in lost+found directories
-      in the root of the store (or in their original position if they have
-      been moved) but they will all be able to be retrieved.</para>
-
-      <para>After you have retrieved the files you want, bbackupd will upload
-      new versions where necessary, and after about two days, mark any
-      lost+found directories as deleted. Finally, those directories will be
-      removed by the housekeeping process on the server.</para>
-
-      <para>These instructions assume you're working on account 1234,
-      subsitute this for whatever account you're actually working on. These
-      will need to be repeated for all affected accounts.</para>
-
-      <section>
-        <title>Stop bbackupd</title>
-
-        <para>First, make sure that bbackupd is not running on the client
-        machine for the account you are going to recover. Use kill to
-        terminate it. This step is not strictly necessary, but is recommended.
-        During any checks on the account, bbackupd will be unable to log in,
-        and after they are complete, the account is marked as changed on the
-        server so bbackupd will perform a complete scan.</para>
-      </section>
-
-      <section>
-        <title>Are you using RAID on the server?</title>
-
-        <para>At the moment, the raidfile recovery tools have not been
-        written. However, when two out of three files are available, the
-        server will run succesfully, even if it complains a lot in the logs.
-        So, your best bet here is to fix the accounts, if necessary, and
-        retrieve any files you need. Then move the old store directories aside
-        (in case you need them) and start afresh with new accounts, and let
-        the clients upload all their data again. These utilities will be
-        written shortly!</para>
-
-        <para>TODO: Is this true anymore???</para>
-      </section>
-
-      <section>
-        <title>Check and fix the account</title>
-
-        <para>First, run the check utility, and see what errors it
-        reports.</para>
-
-        <programlisting>/usr/local/bin/bbstoreaccounts check 1234</programlisting>
-
-        <para>This will take some time, and use a fair bit of memory (about 16
-        bytes per file and directory). If the output looks plausible and
-        reports errors which need fixing, run it again but with the fix
-        flag:</para>
-
-        <programlisting>/usr/local/bin/bbstoreaccounts check 1234 fix</programlisting>
-
-        <para>This will fix any errors, and remove unrecoverable files.
-        Directories will be recreated if necessary.</para>
-
-        <para><emphasis role="bold">NOTE</emphasis>: The utility may adjust
-        the soft and hard limits on the account to make sure that housekeeping
-        will not remove anything -- check these afterwards.</para>
-      </section>
-
-      <section>
-        <title>Grab any files you need with bbackupquery</title>
-
-        <para>At this point, you will have a working store. Every file which
-        was on the server, and wasn't corrupt, will be available.</para>
-
-        <para>On the client, use bbackupquery to log in and examine the store.
-        (type help at the prompt for instructions). Retrieve any files you
-        need, paying attention to any lost+found directories in the root
-        directory of the store.</para>
-
-        <para>You can skip this step if you are sure that the client machine
-        is fine -- in this case, bbackupd will bring the store up to
-        date.</para>
-      </section>
-
-      <section>
-        <title>Restart bbackupd</title>
-
-        <para>Restart bbackupd on the client machine. The store account will
-        be brought up to date, and files in the wrong place will be marked for
-        eventual deletion.</para>
-      </section>
-    </section>
-
-    <section>
-      <title>Troubleshooting</title>
-
-      <para>If you are trying to fix a store after your disc has been
-      corrupted, see <link linkend="FixCorruptions">Fixing corruptions of
-      store data</link>.</para>
-
-      <para>Unfortunately, the error messages are not particularly helpful at
-      the moment. This page lists some of the common errors, and the most
-      likely causes of them.</para>
-
-      <para>When an error occurs, you will see a message like 'Exception:
-      RaidFile/OSFileError (2/8)' either on the screen or in your log files.
-      (it is recommended you set up another log file as recommended in the
-      server setup instructions.)</para>
-
-      <para>This error may not be particularly helpful, although some do have
-      extra information about probable causes. To get further information,
-      check the ExceptionCodes.txt file in the root of the distribution. This
-      file is generated by the ./configure script, so you will need to have
-      run that first.</para>
-
-      <para>Some common causes of exceptions are listed below.</para>
-
-      <para>Please email me with any other codes you get, and I will let you
-      know what they mean, and add notes here.</para>
-
-      <section>
-        <title>RaidFile (2/8)</title>
-
-        <para>This is found either when running bbstoreaccounts or in the
-        bbstored logs.</para>
-
-        <para><emphasis role="bold">Problem</emphasis>: The directories you
-        specified in the raidfile.conf are not writable by the _bbstored
-        user.</para>
-
-        <para><emphasis role="bold">Resolution</emphasis>: Change permissions
-        appropriately.</para>
-      </section>
-
-      <section>
-        <title>Common (1/2)</title>
-
-        <para>This usually occurs when the configuration files can't be
-        opened.</para>
-
-        <para><emphasis role="bold">Problem</emphasis>: You created your
-        configurations in non-standard locations, and the programs cannot find
-        them.</para>
-
-        <para><emphasis role="bold">Resolution</emphasis>: Explicitly specify
-        configuration file locations to daemons and programs. For
-        example</para>
-
-        <programlisting>/usr/local/bin/bbstored /some/other/dir/bbstored.config /usr/local/bin/bbackupquery -c /some/other/dir/bbackupd.config</programlisting>
-
-        <para>(daemons specify the name as the first argument, utility
-        programs with the -c option).</para>
-
-        <para><emphasis role="bold">Problem</emphasis>: bbstored can't find
-        the raidfile.conf file specified in bbstored.conf.</para>
-
-        <para><emphasis role="bold">Resolution</emphasis>: Edit bbstored.conf
-        to point to the correct location of this additional configuration
-        file.</para>
-      </section>
-
-      <section>
-        <title>Server (3/16)</title>
-
-        <para>The server can't listen for connections on the IP address
-        specified when you configured it.</para>
-
-        <para><emphasis role="bold">Problem</emphasis>: This probably means
-        you've specified the wrong hostname to bbstored-config -- maybe your
-        server is behind a NAT firewall?</para>
-
-        <para><emphasis role="bold">Resolution</emphasis>: Edit bbstored.conf
-        and correct the ListenAddresses line. You should replace the server
-        address with the IP address of your machine.</para>
-      </section>
-
-      <section>
-        <title>Connection (7/x)</title>
-
-        <para>These errors all relate to connections failing -- you may see
-        them during operation if there are network failures or other problems
-        between the client and server. The backup system will recover from
-        them automatically.</para>
-
-        <section>
-          <title>Connection (7/30) - SSL problems</title>
-
-          <para>Log snippet from client side:</para>
-
-          <programlisting>bbackupd[1904]: Opening connection to server xxxx.xxx...
-bbackupd[1904]: SSL err during Connect: error:xxxxxxxx:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01
-bbackupd[1904]: SSL err during Connect: error:xxxxxxxx:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed
-bbackupd[1904]: SSL err during Connect: error:xxxxxxxx:asn1 encoding routines:ASN1_verify:EVP lib
-bbackupd[1904]: SSL err during Connect: error:xxxxxxxx:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
-bbackupd[1904]: TRACE: Exception thrown: ConnectionException(Conn_TLSHandshakeFailed) at SocketStreamTLS.cpp(237)
-bbackupd[1904]: Exception caught (7/30), reset state and waiting to retry...</programlisting>
-
-          <para>And from the server:</para>
-
-          <programlisting>bbstored[19291]: Incoming connection from xx.xxx.xx.xxx port xxxxx (handling in child xxxxx)
-bbstored[21588]: SSL err during Accept: error:xxxxxxxx:SSL routines:SSL3_READ_BYTES:tlsv1 alert decrypt error
-bbstored[21588]: in server child, exception Connection TLSHandshakeFailed (7/30) -- terminating child</programlisting>
-
-          <para><emphasis role="bold">Solution</emphasis>: Create a new CA on
-          the server side and re-generate the client certificate. Re-creating
-          the client certificate request is not necessary.</para>
-        </section>
-      </section>
-
-      <section>
-        <title>Advanced troubleshooting</title>
-
-        <para>If this really doesn't help, then using the DEBUG builds of the
-        system will give you much more information -- a more descriptive
-        exception message and the file and line number where the error
-        occurred.</para>
-
-        <para>For example, if you are having problems with bbstoreaccounts,
-        build the debug version with:</para>
-
-        <programlisting>cd boxbackup-0.0
-cd bin/bbstoreaccounts
-make</programlisting>
-
-        <para>Within the module directories, make defaults to building the
-        debug version. At the top level, it defaults to release.</para>
-
-        <para>This will build an executable in debug/bin/bbstoreaccounts which
-        you can then use instead of the release version. It will give far more
-        useful error messages.</para>
-
-        <para>When you get an error message, use the file and line number to
-        locate where the error occurs in the code. There will be comments
-        around that line to explain why the exception happened.</para>
-
-        <para>If you are using a debug version of a daemon, these extended
-        messages are found in the log files.</para>
-      </section>
-    </section>
-  </chapter>
-
-  &__ExceptionCodes__elfjz3fu;
-
-  <appendix>
-    <title id="WORoot">Running without root</title>
-
-    <para>It is possible to run both the server and client without root
-    privileges.</para>
-
-    <section>
-      <title>Server</title>
-
-      <para>The server, by default, runs as a non-root user. However, it
-      expects to be run as root and changes user to a specified user as soon
-      as it can, simply for administrative convenience. The server uses a port
-      greater than 1024, so it doesn't need root to start.</para>
-
-      <para>To run it entirely as a non-root user, edit the bbstored.conf
-      file, and remove the User directive from the Server section. Then simply
-      run the server as your desired user.</para>
-    </section>
-
-    <section>
-      <title>Client</title>
-
-      <para>The client requires root for normal operation, since it must be
-      able to access all files to back them up. However, it is possible to run
-      the client as a non-root user, with certain limitations.</para>
-
-      <para>Follow the installation instructions, but install the executable
-      files manually to somewhere in your home directory. Then use
-      bbackupd-config to configure the daemon, but use a directory other than
-      /etc/box, probably somewhere in your home directory.</para>
-
-      <para>All directories you specify to be backed up must be readable, and
-      all files must be owned by the user and readable to that user.</para>
-
-      <para>Important: If any file or directory is not readable by this user,
-      the backup process will skip that file or directory. Keep an eye on the
-      logs for reports of this failure.</para>
-
-      <para>Non-root operation of the backup client is recommended only for
-      testing, and should not be relied on in a production environment.</para>
-    </section>
-  </appendix>
-</book>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/adminguide.xml (from rev 674, box/trunk/documentation/boxbackup/adminguide.xml)

Deleted: box/chris/general/documentation/boxbackup/bb-book.xsl
===================================================================
--- box/trunk/documentation/boxbackup/bb-book.xsl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bb-book.xsl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,17 +0,0 @@
-<?xml version='1.0'?> 
-<xsl:stylesheet  
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
-
-<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/> 
-
-<xsl:param name="html.stylesheet" select="'../bbdoc.css'"/>
-<xsl:param name="chunk.section.depth" select="'0'"/>
-<xsl:template name="user.header.navigation">
-<div id="header">
-<div id="logo">
-<img src="../images/bblogo.png" alt="logo" height="65" width="331" border="0" vspace="5" align="middle" /> <img src="../images/stepahead.png" alt="a step ahead in data security" width="182" height="11" hspace="10" vspace="20" border="0" align="middle" /></div>
-</div>
-</xsl:template>
-
-
-</xsl:stylesheet>

Copied: box/chris/general/documentation/boxbackup/bb-book.xsl (from rev 674, box/trunk/documentation/boxbackup/bb-book.xsl)

Deleted: box/chris/general/documentation/boxbackup/bb-man.xsl
===================================================================
--- box/trunk/documentation/boxbackup/bb-man.xsl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bb-man.xsl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,9 +0,0 @@
-<?xml version='1.0'?> 
-<xsl:stylesheet  
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
-
-<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"/> 
-
-<xsl:param name="chunk.section.depth" select="'0'"/>
-
-</xsl:stylesheet>

Copied: box/chris/general/documentation/boxbackup/bb-man.xsl (from rev 674, box/trunk/documentation/boxbackup/bb-man.xsl)

Deleted: box/chris/general/documentation/boxbackup/bb-nochunk-book.xsl
===================================================================
--- box/trunk/documentation/boxbackup/bb-nochunk-book.xsl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bb-nochunk-book.xsl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,17 +0,0 @@
-<?xml version='1.0'?> 
-<xsl:stylesheet  
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
-
-<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/> 
-
-<xsl:param name="html.stylesheet" select="'../bbdoc-man.css'"/>
-<xsl:param name="chunk.section.depth" select="'0'"/>
-<xsl:template name="user.header.content">
-<div id="header">
-<div id="logo">
-<img src="../images/bblogo.png" alt="logo" height="65" width="331" border="0" vspace="5" align="middle" /> <img src="../images/stepahead.png" alt="a step ahead in data security" width="182" height="11" hspace="10" vspace="20" border="0" align="middle" /></div>
-</div>
-</xsl:template>
-
-
-</xsl:stylesheet>

Copied: box/chris/general/documentation/boxbackup/bb-nochunk-book.xsl (from rev 674, box/trunk/documentation/boxbackup/bb-nochunk-book.xsl)

Deleted: box/chris/general/documentation/boxbackup/bbackupctl.xml
===================================================================
--- box/trunk/documentation/boxbackup/bbackupctl.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bbackupctl.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry>
-  <refmeta>
-    <refentrytitle>bbackupctl</refentrytitle>
-
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bbackupctl</refname>
-
-    <refpurpose>Control the bbackupd daemon </refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bbackupctl [-q] [-c config-file] command</command>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsection>
-    <title>Description</title>
-
-    <para><literal>bbackupctl</literal> lets the user control the bbackupd
-    daemon on a client machine. The main use is to force a sync with the store
-    server. This is especially important if bbackupd(1) is configured to do
-    snapshot backups. In that case <literal>bbackupctl</literal> is the only
-    way to effect a backup.</para>
-
-    <para>Communication with the bbackupd daemon takes place over a local
-    socket. Some platforms (notably Windows) can't determine if the user
-    connecting on this socket has the correct credentials to execute the
-    commands, leaving a rather sizeable security hole open. To avoid this,
-    unset the CommandSocket parameter in <literal>bbackupd.conf</literal>(8).
-    That disables the command socket, so bbackupd is secure. This does,
-    however, render bbackupctl unusable.</para>
-
-    <refsection>
-      <title>Options</title>
-
-      <itemizedlist>
-        <listitem>
-          <para>-q -- quiet. Do not output status messages.</para>
-        </listitem>
-
-        <listitem>
-          <para>-c config_file -- Use a different config file from the default
-          one. Can be a full or a relative path.</para>
-        </listitem>
-      </itemizedlist>
-    </refsection>
-
-    <refsection>
-      <title>Commands</title>
-
-      <para>The following commands are available in bbackupctl:</para>
-
-      <itemizedlist>
-        <listitem>
-          <para><literal>terminate</literal></para>
-
-          <para>This command stops the bbackupd server. This is the equivalent
-          of killing (kill -KILL) the bbackupd process.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>reload</literal></para>
-
-          <para>Causes the bbackupd daemon to re-read all its configuration
-          files. Equivalent to kill -HUP.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>sync</literal></para>
-
-          <para>Initiates a backup to the store of whatever needs to be backed
-          up.</para>
-        </listitem>
-      </itemizedlist>
-    </refsection>
-  </refsection>
-
-  <refsection>
-    <title>Author</title>
-
-    <para>Ben Summers and contributors. For help, please go to the <ulink
-    url="http://boxbackup.hostworks.ca/">Wiki</ulink>, or subscribe to the Box
-    Backup <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list.</ulink></para>
-  </refsection>
-
-  <refsection>
-    <title>See Also</title>
-
-    <para><literal>bbackupd.conf(8)</literal></para>
-
-    <para>bbackupd(1)</para>
-  </refsection>
-
-  <refsection>
-    <title>Files</title>
-
-    <para><literal>bbackupctl</literal> uses the Box Backup client
-    configuration file, usually located in
-    <filename>/etc/box/bbackupd.conf</filename>. On Windows this file is
-    usually located in the installation directory, and is named
-    <filename>bbackupd.conf</filename> as well.</para>
-  </refsection>
-
-  <refsection>
-    <title>Bugs</title>
-
-    <para>If you find a bug in Box Backup, and you want to let us know about
-    it, join the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list</ulink>, and send a description of the problem there.</para>
-
-    <para>To report a bug, give us at least the following information:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>The version of Box Backup you are running</para>
-      </listitem>
-
-      <listitem>
-        <para>The platform you are running on (Hardware and OS), for both
-        client and server.</para>
-      </listitem>
-
-      <listitem>
-        <para>If possible attach your config files (bbstored.conf,
-        bbackupd.conf) to the bug report.</para>
-      </listitem>
-
-      <listitem>
-        <para>Also attach any log file output that helps shed light on the
-        problem you are seeing.</para>
-      </listitem>
-
-      <listitem>
-        <para>And last but certainly not least, a description of what you are
-        seeing, in as much detail as possible.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-</refentry>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/bbackupctl.xml (from rev 674, box/trunk/documentation/boxbackup/bbackupctl.xml)

Deleted: box/chris/general/documentation/boxbackup/bbackupquery.xml
===================================================================
--- box/trunk/documentation/boxbackup/bbackupquery.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bbackupquery.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,380 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry>
-  <refmeta>
-    <refentrytitle>bbackupquery</refentrytitle>
-
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bbackupquery</refname>
-
-    <refpurpose>Box Backup store query and retrieval</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bbackupquery [-q] [-c configfile] [commands ...]</command>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsection>
-    <title>Description</title>
-
-    <para><literal>bbackupquery</literal> is the main way of interacting with
-    the backup store from a Box Backup client machine. It supports both
-    interactive and batch modes of operation.</para>
-
-    <para>It can be used to reviewing the status of a client machine's backup
-    store, getting status from the store server. The main use is to retrieve
-    files and directories when needed.</para>
-
-    <para><literal>bbackupquery</literal> supports interactive and batch modes
-    of operation. Interactive mode allows for interaction with the server much
-    like an interactive FTP client.</para>
-
-    <para>Batch mode is invoked by putting commands into the invocation of
-    bbackupquery. Example:</para>
-
-    <programlisting>bbackupquery "list home-dirs" quit</programlisting>
-
-    <para>Note that commands that contain spaces are enclosed in double
-    quotes. If the <literal>quit</literal> command is ommitted, after the
-    preceding commands are completed, <literal>bbackupquery</literal> will
-    enter interactive mode.</para>
-
-    <para><emphasis role="bold">Options</emphasis></para>
-
-    <para><emphasis>-q: Quiet. Suppresses status output while
-    running.</emphasis></para>
-
-    <para><emphasis>-c configfile: Use config file, instead of the default
-    bbackupd.conf file. Can be a relative or full path.</emphasis></para>
-
-    <refsection>
-      <title>Commands</title>
-
-      <para>The commands that can be used in <literal>bbackupquery</literal>
-      are listed below.</para>
-
-      <itemizedlist>
-        <listitem>
-          <para><literal>help</literal></para>
-
-          <para>Displays the basic help message, which gives information about
-          the commands available in bbackupquery. Use the form <literal>help
-          command</literal>, to get help on a specific command.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>quit</literal></para>
-
-          <para>End the session with the store server, and quit
-          <literal>bbackupquery</literal>.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>cd [options] &lt;directory-name&gt;</literal></para>
-
-          <para>Change directory. Options:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>-d</literal> -- consider deleted directories for
-              traversal</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-o</literal> -- consider old versions of
-              directories for traversal. This option should never be useful in
-              a correctly formed store.</para>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-
-        <listitem>
-          <para><literal>lcd &lt;local-directory-name&gt;</literal></para>
-
-          <para>Change directory on the client machine. To list the contents
-          of the local directory, type <literal>sh ls</literal> (on unix-like
-          machines). TODO: Does <literal>sh dir</literal> work on
-          Windows?</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>list [options] [directory-name]</literal></para>
-
-          <para>The <literal>list</literal> (or its synonym
-          <literal>ls</literal>) command lists the content of the current, or
-          specified, directory. The options are as follows:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>-r</literal> -- recursively list all files</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-d</literal> -- list deleted files and
-              directories</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-o</literal> -- list old versions of files and
-              directories</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-I</literal> -- don't display object IDs</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-F</literal> -- don't display flags</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-t</literal> -- show file modification time (and
-              attr mod time, if the object has attributes.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-s</literal> -- show file size in blocks used on
-              server. Note that this is only a very approximate indication of
-              local file size.</para>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-
-        <listitem>
-          <para><literal>ls [options] [directory-name]</literal></para>
-
-          <para>Synonym for <literal>list</literal>.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal><literal>pwd</literal></literal></para>
-
-          <para>Print current directory, always relative to the backup store
-          root.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>sh &lt;shell command&gt;</literal></para>
-
-          <para>Everything after the sh is passed to a shell and run. All
-          output from the command is displayed in the client.</para>
-
-          <para>Example: to list the contents of the current directory on the
-          client machine type <literal>sh ls</literal>.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>compare -a</literal></para>
-
-          <para><literal>compare -l &lt;location-name&gt;</literal></para>
-
-          <para><literal>compare &lt;store-dir-name&gt;
-          &lt;local-dir-name&gt;</literal></para>
-
-          <para>Compare the current data in the store with the data on the
-          disc. Please note that all the data will be downloaded from the
-          store, so this can be a very lengthy process depending on the size
-          of the store, and the size of the part you are comparing.</para>
-
-          <para>Options:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>-a</literal> -- compare all locations. </para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-l</literal> -- compare one backup location as
-              specified in the configuration file. This compares one of the
-              top level store directories.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-c</literal> -- set return code. The return code
-              is set to the following values, if <literal>quit</literal> is
-              the next command. So, if another command is run after the
-              <literal>compare</literal>, the return code will not refer to
-              the <literal>compare</literal>. This option is very useful for
-              automating compares. Return code values:</para>
-
-              <itemizedlist>
-                <listitem>
-                  <para>1 -- no differences were found</para>
-                </listitem>
-
-                <listitem>
-                  <para>2 -- differences were found</para>
-                </listitem>
-
-                <listitem>
-                  <para>3 -- an error occured</para>
-                </listitem>
-              </itemizedlist>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-
-        <listitem>
-          <para><literal>get &lt;object-filename&gt;
-          [&lt;local-filename&gt;]</literal></para>
-
-          <para><literal>get -i &lt;object-id&gt;
-          &lt;local-filename&gt;</literal></para>
-
-          <para>Gets a file from the store. Object is specified as the
-          filename within the current directory. Local filename is optional.
-          Ignores old and deleted files when searching the directory for the
-          file to retrieve.</para>
-
-          <para>To get an old or deleted file, use the <literal>-i</literal>
-          option and select the object as a hex object ID (first column in
-          listing). The local filename must be specified.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>getobject &lt;object-id&gt;
-          &lt;local-filename&gt;</literal></para>
-
-          <para>Gets the object specified by the object id (in hex) and stores
-          the raw contents in the local file specified. <emphasis
-          role="bold">Note</emphasis>: This is only useful for debugging as it
-          does not decode files from the stored format, which is encrypted and
-          compressed.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>restore [-d] &lt;directory-name&gt;
-          &lt;local-directory-name&gt;</literal></para>
-
-          <para><literal>restore -r</literal></para>
-
-          <para>Restores a directory to the local disc. The local directory
-          specified must not exist (unless a previous restore is being
-          restarted). The root cannot be restored -- restore locations
-          individually. </para>
-
-          <para>Options:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>-d</literal> -- restore a deleted
-              directory</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>-r</literal> -- resume an interrupted
-              restore</para>
-            </listitem>
-          </itemizedlist>
-
-          <para> If a restore operation is interrupted for any reason, it can
-          be restarted using the <literal>-r</literal> switch. Restore
-          progress information is saved in a file at regular intervals during
-          the restore operation to allow restarts.</para>
-        </listitem>
-
-        <listitem>
-          <para>usage</para>
-
-          <para>Show space used on the server for this account. Display
-          fields:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>Used</literal>: Total amount of space used on the
-              server</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>Old files</literal>: Space used by old
-              files</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>Deleted files</literal>: Space used by deleted
-              files</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>Directories</literal>: Space used by the
-              directory structure</para>
-            </listitem>
-          </itemizedlist>
-
-          <para>When Used exceeds the soft limit, the server will start to
-          remove old and deleted files until the usage drops below the soft
-          limit. After a while, you should expect to see the usage stay at
-          just below the soft limit. You only need more space if the space
-          used by old and deleted files is near zero.</para>
-        </listitem>
-      </itemizedlist>
-    </refsection>
-  </refsection>
-
-  <refsection>
-    <title>Author</title>
-
-    <para>Ben Summers and contributors. For help, please go to the <ulink
-    url="http://boxbackup.hostworks.ca/">Wiki</ulink>, or subscribe to the Box
-    Backup <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list.</ulink></para>
-  </refsection>
-
-  <refsection>
-    <title>See Also</title>
-
-    <para>bbackupd.conf(8)</para>
-  </refsection>
-
-  <refsection>
-    <title>Files</title>
-
-    <para><literal>bbackupquery</literal> uses the Box Backup client
-    configuration file, usually located in
-    <filename>/etc/box/bbackupd.conf</filename>. On Windows this file is
-    usually located in the installation directory, and is named
-    <filename>bbackupd.conf</filename> as well.</para>
-  </refsection>
-
-  <refsection>
-    <title>Bugs</title>
-
-    <para>If you find a bug in Box Backup, and you want to let us know about
-    it, join the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list</ulink>, and send a description of the problem there.</para>
-
-    <para>To report a bug, give us at least the following information:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>The version of Box Backup you are running</para>
-      </listitem>
-
-      <listitem>
-        <para>The platform you are running on (Hardware and OS), for both
-        client and server.</para>
-      </listitem>
-
-      <listitem>
-        <para>If possible attach your config files (bbstored.conf,
-        bbackupd.conf) to the bug report.</para>
-      </listitem>
-
-      <listitem>
-        <para>Also attach any log file output that helps shed light on the
-        problem you are seeing.</para>
-      </listitem>
-
-      <listitem>
-        <para>And last but certainly not least, a description of what you are
-        seeing, in as much detail as possible.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-</refentry>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/bbackupquery.xml (from rev 674, box/trunk/documentation/boxbackup/bbackupquery.xml)

Deleted: box/chris/general/documentation/boxbackup/bbstoreaccounts.xml
===================================================================
--- box/trunk/documentation/boxbackup/bbstoreaccounts.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bbstoreaccounts.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,290 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry>
-  <refmeta>
-    <refentrytitle>bbstoreaccounts</refentrytitle>
-
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bbstoreaccounts</refname>
-
-    <refpurpose>View and change account information on the store
-    server</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bbstoreaccounts [-c configfile] command account_id
-      [command-specific arguments]</command>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsection>
-    <title>Description</title>
-
-    <para><literal>bbstoreaccounts</literal> is the tool for managing accounts
-    on the store server. It can be used to view information related to
-    accounts, as well as create, change and delete accounts on the store
-    server. </para>
-
-    <para><literal>bbstoreaccounts</literal> alwas takes at least 2
-    parameters: the command name and the account ID. Some commands require
-    additional parameters, and some commands have optional parameters.</para>
-
-    <refsection>
-      <title>Options</title>
-
-      <para><literal>-c &lt;configfile&gt;</literal></para>
-
-      <para>The configfile to use for connecting to the store. Default is
-      <literal>/etc/box/bbstored.conf</literal>.</para>
-    </refsection>
-
-    <refsection>
-      <title>Commands</title>
-
-      <para>The commands tells bbstoreaccounts what action to perform.</para>
-
-      <itemizedlist>
-        <listitem>
-          <para><literal>check &lt;account-id&gt; [fix]</literal></para>
-
-          <para>The <literal>check</literal> command verifies the integrity of
-          the store account given, and optionally fixes any corruptions.
-          <emphasis role="bold">Note</emphasis>: It is recommended to run the
-          'simple' check command (without <literal>fix</literal>) before using
-          the <literal>fix</literal> option, This gives an overview of the
-          extent of any problems, before attempting to fix them.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>create &lt;account-id&gt; &lt;discset&gt;
-          &lt;softlimit&gt; &lt;hardlimit&gt;</literal></para>
-
-          <para>Creates a new store account with the parameters given. The
-          parameters are as follows:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>account-id</literal>: the ID of the new account
-              to be created. A 32-bit hexadecimal number. Cannot already exist
-              on the server.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>discset</literal>: the disc set from
-              raidfile.conf(5) where the backups for this client will be
-              stored.. A number. Each RAID-file set has a number in
-              raidfile.conf. This number is what's used.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>softlimit</literal>: The soft limit is the amount
-              of storage that the server will guarantee to be available for
-              storage.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>hardlimit</literal>: The amount of storage that
-              the the server will allow, before rejecting uploads, and
-              starting to eliminate old and deleted files to get back down to
-              <literal>softlimit</literal>. </para>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-
-        <listitem>
-          <para><literal>delete &lt;account-id&gt; [yes]</literal></para>
-
-          <para>Deletes the account from the store server completely. Removes
-          all backups and deletes all references to the account in the config
-          files.</para>
-
-          <para><literal>delete</literal> will ask for confirmation from the
-          user, when called. Using the <literal>yes</literal> flag, eliminates
-          that need. This is useful when deleting accounts from within a
-          script or some other automated means.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>info &lt;account-id&gt;</literal></para>
-
-          <para>Display information about the given account. Example:</para>
-
-          <programlisting>[root]# bbstoreaccounts info 1
-                  Account ID: 00000001
-              Last object ID: 58757
-                 Blocks used: 9864063 (38531.50Mb)
-    Blocks used by old files: 62058 (242.41Mb)
-Blocks used by deleted files: 34025 (132.91Mb)
-  Blocks used by directories: 6679 (26.09Mb)
-            Block soft limit: 11796480 (46080.00Mb)
-            Block hard limit: 13107200 (51200.00Mb)
-         Client store marker: 1139559852000000 </programlisting>
-
-          <para>Explanation:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para>Account ID: The account ID being displayed.</para>
-            </listitem>
-
-            <listitem>
-              <para>Last Object ID: A counter that keeps track of the objects
-              that have been backed up. This number refers to the last file
-              that was written to the store. The ID is displayed as a decimal
-              number, and the object ID can be converted to a path name to a
-              file as follows: convert the number to hex (e.g.: 58757 =&gt;
-              0xE585); The last backed up file will be (relative from the
-              client's store root): <literal>e5/o85.rfw</literal>. Longer
-              numbers infer more directories in the structure, so as an
-              example 3952697264 as the last object ID gives 0xEB995FB0, which
-              translates to a backup pathname of
-              <literal>eb/99/5f/ob0.rfw.</literal></para>
-            </listitem>
-
-            <listitem>
-              <para>Blocks used: The number of blocks used by the store. The
-              size in Mb depends on the number of blocks, as well as the block
-              size for the disc set given in
-              <literal>raidfile.conf(5)</literal>. In this case the block size
-              is 4096.</para>
-            </listitem>
-
-            <listitem>
-              <para>Blocks used by old files: The number of blocks occupied by
-              files that have newer versions in the store. This data is at
-              risk for being removed during housekeeping.</para>
-            </listitem>
-
-            <listitem>
-              <para>Blocks used by deleted files: The number of blocks used by
-              files that have been deleted on the client. Thi s data is at
-              risk for being removed during housekeeping.</para>
-            </listitem>
-
-            <listitem>
-              <para>Blocks used by directories: The number of blocks used by
-              directories in the store.</para>
-            </listitem>
-
-            <listitem>
-              <para>Block soft limit: The soft limit in blocks. The soft limit
-              is the maximum guaranteed storage space available to the
-              account. When housekeeping starts, and the old and deleted files
-              are removed, they are removed in chronological order (oldest
-              first), until the data used is less than the soft limit.</para>
-            </listitem>
-
-            <listitem>
-              <para>Block hard limit: The hard limit in blocks. The hard limit
-              is the most amount of storage the server will allow in an
-              account. Any data above this amount will be rejected.
-              Housekeeping will reduce the storage use, so more data can be
-              uploaded.</para>
-            </listitem>
-
-            <listitem>
-              <para>Client store marker: TODO What exactly is this? </para>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-
-        <listitem>
-          <para><literal>setlimit &lt;account-id&gt; &lt;softlimit&gt;
-          &lt;hardlimit&gt;</literal></para>
-
-          <para>Changes the storage space allocation for the given account. No
-          server restart is needed.</para>
-
-          <para>Parameters:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>account-id</literal>: the ID of the new account
-              to be created. A 32-bit hexadecimal number. Cannot already exist
-              on the server.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>softlimit</literal>: The soft limit is the amount
-              of storage that the server will guarantee to be available for
-              storage.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>hardlimit</literal>: The amount of storage that
-              the the server will allow, before rejecting uploads, and
-              starting to eliminate old and deleted files to get back down to
-              <literal>softlimit</literal>.</para>
-            </listitem>
-          </itemizedlist>
-        </listitem>
-      </itemizedlist>
-    </refsection>
-  </refsection>
-
-  <refsection>
-    <title>Author</title>
-
-    <para>Ben Summers and contributors. For help, please go to the <ulink
-    url="http://boxbackup.hostworks.ca/">Wiki</ulink>, or subscribe to the Box
-    Backup <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list.</ulink></para>
-  </refsection>
-
-  <refsection>
-    <title>See Also</title>
-
-    <para><literal>bbstored.conf(5)</literal></para>
-
-    <para><literal>raidfile.conf(5)</literal></para>
-  </refsection>
-
-  <refsection>
-    <title>Files</title>
-
-    <para><literal>bbstoreaccounts</literal> uses the Box Backup server
-    configuration file, usually located in
-    <filename>/etc/box/bbstored.conf</filename>. </para>
-  </refsection>
-
-  <refsection>
-    <title>Bugs</title>
-
-    <para>If you find a bug in Box Backup, and you want to let us know about
-    it, join the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list</ulink>, and send a description of the problem there.</para>
-
-    <para>To report a bug, give us at least the following information:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>The version of Box Backup you are running</para>
-      </listitem>
-
-      <listitem>
-        <para>The platform you are running on (Hardware and OS), for both
-        client and server.</para>
-      </listitem>
-
-      <listitem>
-        <para>If possible attach your config files (bbstored.conf,
-        bbackupd.conf) to the bug report.</para>
-      </listitem>
-
-      <listitem>
-        <para>Also attach any log file output that helps shed light on the
-        problem you are seeing.</para>
-      </listitem>
-
-      <listitem>
-        <para>And last but certainly not least, a description of what you are
-        seeing, in as much detail as possible.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-</refentry>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/bbstoreaccounts.xml (from rev 674, box/trunk/documentation/boxbackup/bbstoreaccounts.xml)

Deleted: box/chris/general/documentation/boxbackup/bbstored-certs.xml
===================================================================
--- box/trunk/documentation/boxbackup/bbstored-certs.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bbstored-certs.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry>
-  <refmeta>
-    <refentrytitle>bbstored-certs</refentrytitle>
-
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bbstored-certs</refname>
-
-    <refpurpose>Manage certificates for the Box Backup system</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bbstored-certs &lt;certs-dir&gt; &lt;command&gt;
-      [&lt;arguments&gt;]</command>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsection>
-    <title>Description</title>
-
-    <para><literal>bbstored-certs</literal> creates and signs certificates for
-    use in Box Backup. It allows the user to create and sign the server keys,
-    as well as signing client keys.</para>
-
-    <para>All commands must be followed by the <literal>certs-dir</literal>,
-    which is the directory in which the certificates are stored.</para>
-
-    <refsection>
-      <title>Commands</title>
-
-      <para>There are 3 commands:</para>
-
-      <itemizedlist>
-        <listitem>
-          <para><literal>init</literal>: Create the
-          <literal>certs-dir</literal>, and generate the server keys for
-          bbstored. <literal>certs-dir</literal> cannot exist before running
-          the command.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>sign-server &lt;servercsrfile&gt;</literal>: Sign the
-          server certificate. The <literal>servercsrfile</literal> is the file
-          generated by the <literal>init</literal> command.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>sign &lt;clientcsrfile&gt;</literal>: Sign a client
-          certificate. The <literal>clientcsrfile</literal> is generated
-          during client setup. See <literal>bbackupd-config(1)</literal>. Send
-          the signed certificate back to the client, and install according to
-          the instructions given by <literal>bbackupd-config</literal>.</para>
-        </listitem>
-      </itemizedlist>
-    </refsection>
-  </refsection>
-
-  <refsection>
-    <title>Author</title>
-
-    <para>Ben Summers and contributors. For help, please go to the <ulink
-    url="http://boxbackup.hostworks.ca/">Wiki</ulink>, or subscribe to the Box
-    Backup <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list.</ulink></para>
-  </refsection>
-
-  <refsection>
-    <title>See Also</title>
-
-    <para><literal>bbstored-config(1)</literal></para>
-
-    <para><literal>bbstored.conf(5)</literal></para>
-
-    <para><literal>bbstoreaccounts(1)</literal></para>
-  </refsection>
-
-  <refsection>
-    <title>Files</title>
-
-    <para><literal>raidfile-config</literal> generates the raidfile.conf(5)
-    file.</para>
-  </refsection>
-
-  <refsection>
-    <title>Bugs</title>
-
-    <para>If you find a bug in Box Backup, and you want to let us know about
-    it, join the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list</ulink>, and send a description of the problem there.</para>
-
-    <para>To report a bug, give us at least the following information:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>The version of Box Backup you are running</para>
-      </listitem>
-
-      <listitem>
-        <para>The platform you are running on (Hardware and OS), for both
-        client and server.</para>
-      </listitem>
-
-      <listitem>
-        <para>If possible attach your config files (bbstored.conf,
-        bbackupd.conf) to the bug report.</para>
-      </listitem>
-
-      <listitem>
-        <para>Also attach any log file output that helps shed light on the
-        problem you are seeing.</para>
-      </listitem>
-
-      <listitem>
-        <para>And last but certainly not least, a description of what you are
-        seeing, in as much detail as possible.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-</refentry>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/bbstored-certs.xml (from rev 674, box/trunk/documentation/boxbackup/bbstored-certs.xml)

Deleted: box/chris/general/documentation/boxbackup/bbstored-config.xml
===================================================================
--- box/trunk/documentation/boxbackup/bbstored-config.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/bbstored-config.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,140 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry>
-  <refmeta>
-    <refentrytitle>bbstored-config</refentrytitle>
-
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bbstored-config</refname>
-
-    <refpurpose>Create config files for bbstored</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bbstored-config &lt;configdir&gt; &lt;servername&gt;
-      &lt;username&gt;</command>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsection>
-    <title>Description</title>
-
-    <para>The <literal>bbstored-config</literal> script creates config files
-    and server certificates for a bbstored instance. It takes three
-    parameters:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para><literal>configdir</literal>: The directory where config files
-        will reside. A subdirectory bbstored will be created, where several
-        config files will reside. the <literal>bbstored.conf</literal> file
-        will be created in <literal>configdir</literal>.</para>
-      </listitem>
-
-      <listitem>
-        <para><literal>servername</literal>: The name of the server that is
-        being configured. Usually the fully qualified domain name of the
-        machine in question.</para>
-      </listitem>
-
-      <listitem>
-        <para><literal>username</literal>: The name of the user that should be
-        running the bbstored processes. Recommended name:
-        _<literal>bbstored.</literal></para>
-      </listitem>
-    </itemizedlist>
-
-    <para>A valid raidfile.conf(5) must be found in configdir. Several steps
-    are taken during the run of bbstored-config:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>Configuration files are created.</para>
-      </listitem>
-
-      <listitem>
-        <para>Server certificates are created. This requires interaction from
-        the operator.</para>
-      </listitem>
-
-      <listitem>
-        <para>The raid volumes are checked, to ensure that the configuration
-        is consistent, and will work.</para>
-      </listitem>
-
-      <listitem>
-        <para>Instructions for next steps to take are shown. These steps may
-        be different for different OS platforms, so pay close attention to
-        these instructions.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-
-  <refsection>
-    <title>Author</title>
-
-    <para>Ben Summers and contributors. For help, please go to the <ulink
-    url="http://boxbackup.hostworks.ca/">Wiki</ulink>, or subscribe to the Box
-    Backup <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list.</ulink></para>
-  </refsection>
-
-  <refsection>
-    <title>See Also</title>
-
-    <para><literal>raidfile-config(1)</literal></para>
-
-    <para><literal>bbstored.conf(5)</literal></para>
-
-    <para><literal>raidfile.conf(5)</literal></para>
-  </refsection>
-
-  <refsection>
-    <title>Files</title>
-
-    <para><literal>bbstoreaccounts</literal> uses the Box Backup server
-    configuration file, usually located in
-    <filename>/etc/box/bbstored.conf</filename>.</para>
-  </refsection>
-
-  <refsection>
-    <title>Bugs</title>
-
-    <para>If you find a bug in Box Backup, and you want to let us know about
-    it, join the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list</ulink>, and send a description of the problem there.</para>
-
-    <para>To report a bug, give us at least the following information:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>The version of Box Backup you are running</para>
-      </listitem>
-
-      <listitem>
-        <para>The platform you are running on (Hardware and OS), for both
-        client and server.</para>
-      </listitem>
-
-      <listitem>
-        <para>If possible attach your config files (bbstored.conf,
-        bbackupd.conf) to the bug report.</para>
-      </listitem>
-
-      <listitem>
-        <para>Also attach any log file output that helps shed light on the
-        problem you are seeing.</para>
-      </listitem>
-
-      <listitem>
-        <para>And last but certainly not least, a description of what you are
-        seeing, in as much detail as possible.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-</refentry>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/bbstored-config.xml (from rev 674, box/trunk/documentation/boxbackup/bbstored-config.xml)

Deleted: box/chris/general/documentation/boxbackup/generate_except_xml.pl
===================================================================
--- box/trunk/documentation/boxbackup/generate_except_xml.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/generate_except_xml.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,74 +0,0 @@
-#!/usr/bin/perl -w
-use strict;
-
-open (EXCEPT, "<../../ExceptionCodes.txt") or die "Can't open ../../ExceptionCodes.txt: $!\n";
-open (DOCBOOK, ">ExceptionCodes.xml") or die "Can't open Exceptioncodes.xml for writing: $!\n";
-
-print DOCBOOK <<EOD;
-<?xml version="1.0" encoding="UTF-8"?>
-
-<appendix>
-    <title>Exception codes</title>
-
-EOD
-my $sectionName;
-my $sectionNum;
-my $sectionDesc;
-my $exceptionCode;
-my $exceptionShortDesc;
-my $exceptionLongDesc;
-while(<EXCEPT>)
-{
-    next if(m/^#/);
-    chomp;
-    if(m/^EXCEPTION TYPE (\w+) (\d+)/)
-    {
-        $sectionName = ucfirst(lc($1));
-        $sectionNum = $2;
-        if($sectionName ne "Common")
-        {
-            $sectionDesc = "the " . $sectionName;
-        }
-        else
-        {
-            $sectionDesc = "any";
-        }
-        print DOCBOOK <<EOD;
-    <section>
-      <title>$sectionName Exceptions ($sectionNum)</title>
-      
-      <para>These are exceptions that can occur in $sectionDesc module
-      of the system.</para>
-      
-      <itemizedlist>
-EOD
-    }
-    
-    # The END TYPE line
-    if(m/^END TYPE$/)
-    {
-        print DOCBOOK "      </itemizedlist>\n    </section>\n";
-    }
-    
-    # The actual exceptions
-    if(m/(\(\d+\/\d+\)) - (\w+ \w+)(?: - )?(.*)$/)
-    {
-        $exceptionCode = $1;
-        $exceptionShortDesc = $2;
-        $exceptionLongDesc = $3;
-        
-        print DOCBOOK "        <listitem>\n          <para><emphasis role=\"bold\">";
-        print DOCBOOK $exceptionCode . ": " . $exceptionShortDesc . "</emphasis>";
-        if($exceptionLongDesc ne "")
-        {
-            print DOCBOOK " -- " . $exceptionLongDesc;
-        }
-        print DOCBOOK "</para>\n        </listitem>\n";
-    }
-}
-
-print DOCBOOK "</appendix>\n";
-
-close EXCEPT;
-close DOCBOOK;
-        
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/generate_except_xml.pl (from rev 674, box/trunk/documentation/boxbackup/generate_except_xml.pl)

Copied: box/chris/general/documentation/boxbackup/html (from rev 674, box/trunk/documentation/boxbackup/html)

Deleted: box/chris/general/documentation/boxbackup/html/bbdoc-man.css
===================================================================
--- box/trunk/documentation/boxbackup/html/bbdoc-man.css	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/html/bbdoc-man.css	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,104 +0,0 @@
-body {
-	font-family: Verdana, Geneva, Arial, sans-serif;
-	background-color: #edeef3;
-        font-size: .75em;
-        line-height: 180%;
-        text-align: left;
-        margin-top: 20px;
-        margin-right: 100px;
-        margin-left: 250px;
-        position: relative;
-        width: auto; }
-	
-table {
-	font-family: Verdana, Geneva, Arial, sans-serif;
-	background-color: #edeef3;
-        font-size: 10pt;
-        line-height: 100%; }
-
-
-code {
-	font-size: 11pt; }
-
-	
-
-div.navheader {
-	font-family: Verdana, Geneva, Arial, sans-serif;
-	background-color: #edeef3; 
-        line-height: 100%; }
-       
-#header {
-	background-color: #e4e6ed;
-	text-align: left;
-	padding-top: 10px;
-        margin-right: -100px;
-        margin-left: -250px;
-	top: 20px;
-	border-top: 1px solid #c4c4d5;
-	border-bottom: 1px solid white }
-	
-#logo {
-	position: relative; 
-	margin-left: 200px }
-	
-	
-#page {
-	font-size: .75em;
-	line-height: 180%;
-	text-align: left;
-	margin-top: 50px;
-	margin-right: 100px;
-	margin-left: 250px;
-	position: relative;
-	width: auto }
-
-#disc {    }
-	
-.informaltable td,tr {font-size: 1em;
-	line-height: 140%;
-	text-align: left;
-	background-color: #e4e6ed;
-	padding: 4px }
-	
-tr,td {font-size: 1em;
-	line-height: 100%;
-	background-color: #edeef3; }
-	
-pre, tt { font-size: 1.3em; 
-	color: #088;
-	letter-spacing: 1px;
-	word-spacing: 2px}
-	
-h1 {
-	color: #c00;
-	font-size: 16pt;
-	margin-bottom: 2em;
-	margin-left: -50px }
-	
-h2 {
-	color: #324e95;
-	font-size: 12pt;
-	margin-top: 2em;
-	margin-left: -50px }
-	
-h3 {
-	color: #324e95;
-	font-size: 10pt;
-	margin-top: 2em;
-	margin-left: -50px }
-	
-dt { font-weight: bold }
-	
-a:link {
-	color: #324e95;
-	text-decoration: none;
-	background-color: transparent }
-	
-a:visited {
-	color: #90c;
-	text-decoration: none }
-	
-a:hover {
-	color: #c00;
-	text-decoration: underline;
-	background-color: transparent }

Copied: box/chris/general/documentation/boxbackup/html/bbdoc-man.css (from rev 674, box/trunk/documentation/boxbackup/html/bbdoc-man.css)

Deleted: box/chris/general/documentation/boxbackup/html/bbdoc.css
===================================================================
--- box/trunk/documentation/boxbackup/html/bbdoc.css	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/html/bbdoc.css	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,112 +0,0 @@
-body {
-	font-family: Verdana, Geneva, Arial, sans-serif;
-	background-color: #edeef3;
-        font-size: .75em;
-        line-height: 180%;
-        text-align: left;
-        margin-top: 20px;
-        margin-right: 100px;
-        margin-left: 250px;
-        position: relative;
-        width: auto; }
-	
-table {
-	font-family: Verdana, Geneva, Arial, sans-serif;
-	background-color: #edeef3;
-        font-size: 10pt;
-        line-height: 100%; }
-
-
-	
-
-div.navheader {
-	font-family: Verdana, Geneva, Arial, sans-serif;
-	background-color: #edeef3; 
-        line-height: 100%; }
-       
-#header {
-	background-color: #e4e6ed;
-	text-align: left;
-	padding-top: 10px;
-        margin-right: -100px;
-        margin-left: -250px;
-	top: 20px;
-	border-top: 1px solid #c4c4d5;
-	border-bottom: 1px solid white }
-	
-#logo {
-	position: relative; 
-	margin-left: 200px }
-	
-	
-#page {
-	font-size: .75em;
-	line-height: 180%;
-	text-align: left;
-	margin-top: 50px;
-	margin-right: 100px;
-	margin-left: 250px;
-	position: relative;
-	width: auto }
-
-#disc {    }
-	
-.informaltable td,tr {font-size: 1em;
-	line-height: 140%;
-	text-align: left;
-	background-color: #e4e6ed;
-	padding: 4px }
-	
-tr,td {font-size: 1em;
-	line-height: 100%;
-	background-color: #edeef3; }
-	
-pre, tt { font-size: 1.3em; 
-	color: #088;
-	letter-spacing: 1px;
-	word-spacing: 2px}
-	
-h1 {
-	color: #c00;
-	font-size: 16pt;
-	margin-bottom: 2em;
-	margin-left: -50px }
-	
-h2 {
-	color: #324e95;
-	font-size: 12pt;
-	margin-top: 2em;
-	margin-left: -50px }
-	
-h3 {
-	color: #324e95;
-	font-size: 10pt;
-	margin-top: 2em;
-	margin-left: -50px }
-	
-dt { font-weight: bold }
-	
-ul {
-	list-style-image: url(images/arrow.png) }
-	
-ul li {
-	background-color: #e4e6ed;
-	margin: 1em 6em 1em -2em;
-	padding: 0.2em 0.5em 0.2em 1em;
-	border-style: solid;
-	border-width: 1px;
-	border-color: #c4c4d5 #fff #fff #c4c4d5 }
-	
-a:link {
-	color: #324e95;
-	text-decoration: none;
-	background-color: transparent }
-	
-a:visited {
-	color: #90c;
-	text-decoration: none }
-	
-a:hover {
-	color: #c00;
-	text-decoration: underline;
-	background-color: transparent }

Copied: box/chris/general/documentation/boxbackup/html/bbdoc.css (from rev 674, box/trunk/documentation/boxbackup/html/bbdoc.css)

Copied: box/chris/general/documentation/boxbackup/html/images (from rev 674, box/trunk/documentation/boxbackup/html/images)

Deleted: box/chris/general/documentation/boxbackup/html/images/arrow.png
===================================================================
(Binary files differ)

Copied: box/chris/general/documentation/boxbackup/html/images/arrow.png (from rev 674, box/trunk/documentation/boxbackup/html/images/arrow.png)

Deleted: box/chris/general/documentation/boxbackup/html/images/bblogo.png
===================================================================
(Binary files differ)

Copied: box/chris/general/documentation/boxbackup/html/images/bblogo.png (from rev 674, box/trunk/documentation/boxbackup/html/images/bblogo.png)

Deleted: box/chris/general/documentation/boxbackup/html/images/stepahead.png
===================================================================
(Binary files differ)

Copied: box/chris/general/documentation/boxbackup/html/images/stepahead.png (from rev 674, box/trunk/documentation/boxbackup/html/images/stepahead.png)

Deleted: box/chris/general/documentation/boxbackup/instguide.xml
===================================================================
--- box/trunk/documentation/boxbackup/instguide.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/instguide.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,750 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
-"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
-<book>
-  <title>Box Backup Build and Installation Guide</title>
-
-  <preface>
-    <title>License</title>
-
-    <para>Copyright (c) &lt;YEAR&gt;, &lt;OWNER&gt;</para>
-
-    <para>All rights reserved.</para>
-
-    <para>Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>Redistributions of source code must retain the above copyright
-        notice, this list of conditions and the following disclaimer.</para>
-      </listitem>
-
-      <listitem>
-        <para>Redistributions in binary form must reproduce the above
-        copyright notice, this list of conditions and the following disclaimer
-        in the documentation and/or other materials provided with the
-        distribution.</para>
-      </listitem>
-
-      <listitem>
-        <para>Neither the name of the &lt;ORGANIZATION&gt; nor the names of
-        its contributors may be used to endorse or promote products derived
-        from this software without specific prior written permission</para>
-      </listitem>
-    </itemizedlist>
-
-    <para>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</para>
-  </preface>
-
-  <chapter>
-    <title>Introduction</title>
-
-    <para>The backup daemon, bbackupd, runs on all machines to be backed up.
-    The store server daemon, bbstored runs on a central server. Data is sent
-    to the store server, which stores all data on local filesystems, that is,
-    only on local hard drives. Tape or other archive media is not used.</para>
-
-    <para>The system is designed to be easy to set up and run, and cheap to
-    use. Once set up, there should be no need for user or administrative
-    intervention, apart from usual system maintenance.</para>
-
-    <section>
-      <title>Client daemon</title>
-
-      <para>bbackupd is configured with a list of directories to back up. It
-      has a lazy approach to backing up data. Every so often, the directories
-      are scanned, and new data is uploaded to the server. This new data must
-      be over a set age before it is uploaded. This prevents rapid revisions
-      of a file resulting in many uploads of the same file in a short period
-      of time.</para>
-
-      <para>It can also operate in a snapshot mode, which behaves like
-      traditional backup software. When instructed by an external bbackupctl
-      program, it will upload all changed files to the server.</para>
-
-      <para>The daemon is always running, although sleeping most of the time.
-      In lazy mode, it is completely self contained -- scripts running under
-      cron jobs are not used. The objective is to keep files backed up, not to
-      make snapshots of the filesystem at particular points in time
-      available.</para>
-
-      <para>If an old version of the file is present on the server, a modified
-      version of the rsync algorithm is used to upload only the changed
-      portions of the file.</para>
-
-      <para>After a new version is uploaded, the old version is still
-      available (subject to disc space on the server). Similarly, a deleted
-      file is still available. The only limit to their availability is space
-      allocated to this account on the server</para>
-
-      <para>Future versions will add the ability to mark the current state of
-      files on the server, and restore from this mark. This will emulate the
-      changing of tapes in a tape backup system.</para>
-
-      <section>
-        <title>Restoration</title>
-
-        <para>Restoring files is performed using a query tool, bbackupquery.
-        This can be used to restore entire directories, or as an 'FTP-like'
-        tool to list and retrieve individual files. Old versions and deleted
-        files can be retrieved using this tool for as long as they are kept on
-        the server.</para>
-      </section>
-
-      <section>
-        <title>Client Resource Usage</title>
-
-        <para>bbackupd uses only a minimal amount of disc space to store
-        records on uploaded files -- less than 32 bytes per directory and file
-        over a set size threshold. However, it minimises the amount of queries
-        it must make to the server by storing, in memory, a data structure
-        which allows it to determine what data is new. It does not need to
-        store a record of all files, essentially just the directory names and
-        last modification times. This is not a huge amount of memory.</para>
-
-        <para>If there are no changes to the directories, then the client will
-        not even connect to the server.</para>
-      </section>
-    </section>
-
-    <section>
-      <title>Security</title>
-
-      <para>Box Backup is designed to be secure in several ways. The data
-      stored on the backup store server is encrypted using secret-key
-      cryptography. Additionally, the transport layer is encrypted using TLS,
-      to ensure that the communications can't be snooped.</para>
-
-      <section>
-        <title>Encryption</title>
-
-        <para>The files, directories, filenames and file attributes are all
-        encrypted. By examining the stored files on the server, it is only
-        possible to determine the approximate sizes of a files and the tree
-        structure of the disc (not names, just number of files and
-        subdirectories in a directory). By monitoring the actions performed by
-        a client, it is possible to determine the frequency and approximate
-        scope of changes to files and directories.</para>
-
-        <para>The connections between the server and client are encrypted
-        using TLS (latest version of SSL). Traffic analysis is possible to
-        some degree, but limited in usefulness.</para>
-
-        <para>An attacker will not be able to recover the backed up data
-        without the encryption keys. Of course, you won't be able to recover
-        your files without the keys either, so you must make a conventional,
-        secure, backup of these keys.</para>
-      </section>
-
-      <section>
-        <title>Authentication</title>
-
-        <para>SSL certificates are used to authenticate clients. UNIX user
-        accounts are not used to minimise the dependence on the configuration
-        of the operating system hosting the server.</para>
-
-        <para>A script is provided to run the necessary certification
-        authority with minimal effort.</para>
-      </section>
-    </section>
-
-    <section>
-      <title>Server daemon</title>
-
-      <para>The server daemon is designed to be simple to deploy, and run on
-      the cheapest hardware possible. To avoid the necessity to use expensive
-      hardware RAID or software RAID with complex setup, it (optionally)
-      stores files using RAID techniques.</para>
-
-      <para>It does not need to run as a privileged user.</para>
-
-      <para>Each account has a set amount of disc space allocated, with a soft
-      and a hard limit. If the account exceeds the soft limit, a housekeeping
-      process will start deleting old versions and deleted files to reduce the
-      space used to below the soft limit. If the backup client attempts to
-      upload a file which causes the store to exceed the hard limit, the
-      upload will be refused.</para>
-    </section>
-  </chapter>
-
-  <chapter>
-    <title>Building and installing</title>
-
-    <section>
-      <title>Before you start</title>
-
-      <para>Firstly, check that all the clocks on your clients, servers and
-      signing machines are accurate and in sync. A disagreement in time
-      between a client and a server is the biggest cause of installation
-      difficulties, as the times in the generated certificates will cause
-      login failures if the start date is in the future.</para>
-    </section>
-
-    <section>
-      <title>Box Backup compile</title>
-
-      <para>In the following instructions, replace 0.00 with the actual
-      version number of the archive you have downloaded.</para>
-
-      <para>For help building on Windows, see the <link linkend="AppB">Windows
-      Compile Appendix</link>. And if you want to build a Linux RPM, <link
-      linkend="AppC">look here</link>.</para>
-
-      <para>You need the latest version of OpenSSL, as some of the extra APIs
-      it provides are required. You should have this anyway, as earlier
-      versions have security flaws. (If you have an earlier version installed,
-      the configuration script will give you instructions on enabling
-      experimental support for older versions.)</para>
-
-      <para>See <link linkend="AppA">OpenSSL notes</link> for more information
-      on OpenSSL issues.</para>
-
-      <para>There are some notes in the archive about compiling on various
-      platforms within the boxbackup-0.00 directory -- read them first. For
-      example, if you are compiling under Linux, look for LINUX.txt as
-      boxbackup-0.00/LINUX.txt after untaring the archive.</para>
-
-      <para>Download the archive, then in that directory type</para>
-
-      <programlisting>tar xvzf boxbackup-0.00.tgz
-cd boxbackup-0.00
-./configure
-make</programlisting>
-
-      <para>The server and client will be built and packaged up for
-      installation on this machine, or ready to be transferred as tar files to
-      another machine for installation.</para>
-
-      <para>This builds two parcels of binaries and scripts, 'backup-client'
-      and 'backup-server'. The generated installation scripts assumes you want
-      everything installed in <emphasis
-      role="bold">/usr/local/bin</emphasis></para>
-
-      <para>Optionally, type <emphasis role="bold">make test</emphasis> to run
-      all the tests.</para>
-    </section>
-
-    <section>
-      <title>Local installation</title>
-
-      <para>Type <emphasis role="bold">make install-backup-client</emphasis>
-      to install the backup client.</para>
-
-      <para>Type <emphasis role="bold">make install-backup-server</emphasis>
-      to install the backup server.</para>
-    </section>
-
-    <section>
-      <title>Remote installation</title>
-
-      <para>In the parcels directory, there are tar files for each parcel. The
-      name reflects the version and platform you have built it for.</para>
-
-      <para>Transfer this tar file to the remote server, and unpack it, then
-      run the install script. For example:</para>
-
-      <programlisting>tar xvzf boxbackup-0.00-backup-server-OpenBSD.tgz
-cd boxbackup-0.00-backup-server-OpenBSD
-./install-backup-server</programlisting>
-    </section>
-
-    <section>
-      <title>Configure options</title>
-
-      <para>You can use arguments to the configure script to adjust the
-      compile and link lines in the generated Makefiles, should this be
-      necessary for your platform. The configure script takes the usual GNU
-      autoconf arguments, a full list of which can be obtained with <emphasis
-      role="bold">--help</emphasis>. Additional options for Box Backup
-      include:</para>
-
-      <informaltable>
-        <tgroup cols="2">
-          <tbody>
-            <row>
-              <entry char="-">--enable-gnu-readline</entry>
-
-              <entry>Use GNU readline if present. Linking Box Backup against
-              GNU readline may create licence implications if you then
-              distribute the binaries. libeditline is also supported as a safe
-              alternative, and is used by default if available.</entry>
-            </row>
-
-            <row>
-              <entry>--disable-largefile</entry>
-
-              <entry>Omit support for large files</entry>
-            </row>
-
-            <row>
-              <entry>--with-bdb-dir=DIR</entry>
-
-              <entry>Specify Berkeley DB location</entry>
-            </row>
-
-            <row>
-              <entry>--with-random=FILE</entry>
-
-              <entry>Use FILE as random number seed (normally
-              auto-detected)</entry>
-            </row>
-
-            <row>
-              <entry>--with-tmp-dir=DIR</entry>
-
-              <entry>Directory for temporary files (normally /tmp)</entry>
-            </row>
-          </tbody>
-        </tgroup>
-      </informaltable>
-
-      <para>See <link linkend="AppA">OpenSSL notes</link> for the OpenSSL
-      specific options.</para>
-    </section>
-
-    <section>
-      <title>Tests</title>
-
-      <para>There are a number of unit tests provided. To compile and run one
-      type:</para>
-
-      <programlisting>./runtest.pl bbackupd release
-./runtest.pl common debug
-./runtest.pl ALL</programlisting>
-
-      <para>The runtest.pl script will compile and run the test. The first
-      argument is the test name, and the second the type of build. Use ALL as
-      a test name to run all the tests.</para>
-
-      <para>The output from the tests is slightly muddled using this script.
-      If you're developing, porting or trying out new things, it might be
-      better to use the following scheme:</para>
-
-      <programlisting>cd test/bbackupd
-make
-cd ../../debug/test/bbackupd
-./t</programlisting>
-
-      <para>or in release mode...</para>
-
-      <programlisting>cd test/bbackupd
-make -D RELEASE
-cd ../../release/test/bbackupd
-./t</programlisting>
-
-      <para>(use RELEASE=1 with GNU make)</para>
-
-      <para>I tend to use two windows, one for compilation, and one for
-      running tests.</para>
-    </section>
-  </chapter>
-
-  <appendix>
-    <title id="AppA">Box Backup and SSL</title>
-
-    <section>
-      <title>General notes</title>
-
-      <para>Ideally, you need to use version 0.9.7 or later of OpenSSL. If
-      this is installed on your system by default (and it is on most recent
-      releases of UNIX like OSes) then everything should just work.</para>
-
-      <para>However, if it isn't, you have a few options.</para>
-
-      <section>
-        <title>Upgrade your installation</title>
-
-        <para>The best option is to upgrade your installation to use 0.9.7.
-        Hopefully your package manager will make this easy for you. This may
-        require reinstallation of lots of software which depends on OpenSSL,
-        so may not be ideal.</para>
-
-        <para>(But as there have been a few security flaws in OpenSSL
-        recently, you probably want to upgrade it anyway.)</para>
-      </section>
-
-      <section>
-        <title>Install another OpenSSL</title>
-
-        <para>The second best option is to install another copy. If you
-        download and install from source, it will probably install into
-        /usr/local/ssl. You can then configure Box Backup to use it
-        using:</para>
-
-        <programlisting>./configure --with-ssl-headers=/usr/local/ssl/include --with-ssl-lib=/usr/local/ssl/lib</programlisting>
-
-        <para>which will set up the various includes and libraries for
-        you.</para>
-
-        <para>The configuration scripts may be a problem, depending on your
-        installation. See below for more information.</para>
-      </section>
-
-      <section>
-        <title>Use the old version of OpenSSL</title>
-
-        <para>If you have an old version installed, the configuration script
-        will give you instructions on how to enable support for older
-        versions. Read the warnings, and please, whatever you do, don't
-        release binary packages or ports which enable this option.</para>
-
-        <para>You may have issues with the configuration scripts, see
-        below.</para>
-      </section>
-    </section>
-
-    <section>
-      <title>If you have problems with the config scripts</title>
-
-      <para>If you get OpenSSL related errors with the configuration scripts,
-      there are two things to check:</para>
-
-      <itemizedlist>
-        <listitem>
-          <para>The bin directory within your OpenSSL directory is in the path
-          (if you have installed another version)</para>
-        </listitem>
-
-        <listitem>
-          <para>You have an openssl.cnf file which works and can be
-          found.</para>
-        </listitem>
-      </itemizedlist>
-
-      <section>
-        <title>OpenSSL config file</title>
-
-        <para>You need to have an openssl.cnf file. The default will generally
-        work well (see example at end). Make sure the openssl utility can find
-        it, either set the OPENSSL_CONF environment variable, or install it
-        into the location that is mentioned in the error messages.</para>
-
-        <para>Example OpenSSL config file:</para>
-
-        <programlisting id="openssl.cnf" xreflabel="openssl.cnf">#
-# OpenSSL example configuration file.
-# This is mostly being used for generation of certificate requests.
-# 
-
-RANDFILE                = /dev/arandom
-
-####################################################################
-[ req ]
-default_bits            = 1024
-default_keyfile         = privkey.pem
-distinguished_name      = req_distinguished_name
-attributes              = req_attributes
-
-[ req_distinguished_name ]
-countryName                     = Country Name (2 letter code)
-#countryName_default            = AU
-countryName_min                 = 2
-countryName_max                 = 2
-
-stateOrProvinceName             = State or Province Name (full name)
-#stateOrProvinceName_default    = Some-State
-
-localityName                    = Locality Name (eg, city)
-
-0.organizationName              = Organization Name (eg, company)
-#0.organizationName_default     = Internet Widgits Pty Ltd
-
-# we can do this but it is not needed normally :-)
-#1.organizationName             = Second Organization Name (eg, company)
-#1.organizationName_default     = CryptSoft Pty Ltd
-
-organizationalUnitName          = Organizational Unit Name (eg, section)
-#organizationalUnitName_default =
-
-commonName                      = Common Name (eg, fully qualified host name)
-commonName_max                  = 64
-
-emailAddress                    = Email Address
-emailAddress_max                = 64
-
-[ req_attributes ]
-challengePassword               = A challenge password
-challengePassword_min           = 4
-challengePassword_max           = 20
-
-unstructuredName                = An optional company name
-
-[ x509v3_extensions ]
-
-nsCaRevocationUrl               = http://www.cryptsoft.com/ca-crl.pem
-nsComment                       = "This is a comment"
-
-# under ASN.1, the 0 bit would be encoded as 80
-nsCertType                      = 0x40</programlisting>
-      </section>
-    </section>
-  </appendix>
-
-  <appendix>
-    <title id="AppB">Compiling bbackupd on Windows using Visual C++</title>
-
-    <para>This Appendix explains how to build the bbackupd daemon for Windows
-    using the Visual C++ compiler.</para>
-
-    <para>If you have any problems following these instructions, please sign
-    up to the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    lis</ulink>t and report them to us, or send an email to <ulink
-    url="mailto:bbwiki@qwirx.com">Chris Wilson</ulink>. Thanks!</para>
-
-    <para><emphasis role="bold">Note</emphasis>: bbstored will not be built
-    with this process. bbstored is not currently supported on Windows. There
-    are no plans for bbstored support on Windows.</para>
-
-    <section>
-      <title>Tools</title>
-
-      <para>You will need quite a bit of software to make this work. All of it
-      is available for free on the Internet, although Visual C++ Express has
-      license restrictions and a time limit.</para>
-
-      <section>
-        <title>Visual C++</title>
-
-        <para>Microsoft's Visual C++ compiler and development environment are
-        part of their commercial product <ulink
-        url="http://msdn.microsoft.com/vstudio/">Visual Studio</ulink>. Visual
-        Studio 2005 is supported, and 2003 should work as well.</para>
-
-        <para>You can also <ulink
-        url="http://msdn.microsoft.com/vstudio/express/visualc/download/">download</ulink>
-        a free copy of Visual C++ 2005 Express. This copy must be registered
-        (activated) within 30 days, and is free for one year.</para>
-
-        <para>You will need the <ulink
-        url="http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/">Platform
-        SDK</ulink> to allow you to compile Windows applications.</para>
-      </section>
-
-      <section>
-        <title>Perl</title>
-
-        <para>Download and install <ulink
-        url="http://www.activestate.com/Products/ActivePerl/">ActivePerl for
-        Windows</ulink>, which you can probably find <ulink
-        url="http://downloads.activestate.com/ActivePerl/Windows/5.6/ActivePerl-5.6.1.638-MSWin32-x86.msi">here</ulink>.</para>
-      </section>
-
-      <section>
-        <title>Libraries</title>
-
-        <para>You will need to download and install several libraries. They
-        must all be built in the same directory, to be able to link
-        properly.</para>
-
-        <para>Choose a directory where you will unpack and compile OpenSSL,
-        Zlib and Box Backup. We will call this the base directory. An example
-        might be:</para>
-
-        <programlisting>C:\Documents and Settings\Your Username\Desktop\Box</programlisting>
-
-        <para>Make sure you know the full path to this directory.</para>
-
-        <section>
-          <title>OpenSSL</title>
-
-          <para>You will need to compile OpenSSL using Visual C++. The latest
-          release at this time, OpenSSL 0.9.8a, does not compile with Visual
-          C++ 2005 out of the box, so you need <ulink
-          url="http://bbdev.fluffy.co.uk/svn/box/chris/win32/support/openssl-0.9.8a-vc2005.zip">a
-          patched version</ulink>. The <ulink
-          url="http://www.openssl.org/source/openssl-0.9.8a.tar.gz">original
-          source</ulink> and <ulink
-          url="http://bbdev.fluffy.co.uk/svn/box/chris/win32/support/openssl-0.9.8a-win32fix.patch">patch</ulink>
-          are also available.</para>
-
-          <para>To compile OpenSSL:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para>Use a Windows unzipper such as <ulink
-              url="http://www.winzip.com/">WinZip (free trial)</ulink> to
-              extract the <emphasis
-              role="bold">openssl-0.9.8a-vc2005.tar.gz</emphasis> archive,
-              which you just downloaded, into the base directory.</para>
-            </listitem>
-
-            <listitem>
-              <para>Rename the folder from <emphasis
-              role="bold">openssl-0.9.8a-vc2005</emphasis> to <emphasis
-              role="bold">openssl</emphasis></para>
-            </listitem>
-
-            <listitem>
-              <para>Open a command shell (run <emphasis
-              role="bold">cmd.exe</emphasis>) and <emphasis
-              role="bold">cd</emphasis> to the openssl directory</para>
-            </listitem>
-
-            <listitem>
-              <para>Run the following commands:</para>
-
-              <programlisting>perl Configure VC-WIN32
-ms\do_ms
-"c:\program files\Microsoft Visual Studio 8\Common7\Tools\vsvars32.bat"
-nmake -f ms\ntdll.mak</programlisting>
-            </listitem>
-          </itemizedlist>
-        </section>
-
-        <section>
-          <title>Zlib</title>
-
-          <para>You will need to download the <ulink
-          url="http://www.zlib.net/zlib123-dll.zip">Zlib compiled DLL</ulink>.
-          Create a directory called <emphasis role="bold">zlib</emphasis> in
-          the base directory, and unzip the file you just downloaded into that
-          directory. You don't need to compile anything.</para>
-        </section>
-      </section>
-
-      <section>
-        <title>Download Box Backup</title>
-
-        <para>The first version of Box Backup that's known to compile and with
-        Visual C++ 2005 is available on the <ulink
-        url="http://bbdev.fluffy.co.uk/svn/box/chris/win32/vc2005-compile-fixes/">Subversion
-        server</ulink>. However, this version has not been extensively tested
-        and may be out of date.</para>
-
-        <para>The changes are expected to be merged into the <ulink
-        url="http://bbdev.fluffy.co.uk/svn/box/trunk">Subversion trunk</ulink>
-        at some point, and this page should then be updated. If in doubt,
-        please sign up to the <ulink
-        url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-        list</ulink> and ask us.</para>
-
-        <para>To get the source code out of Subversion you will need a <ulink
-        url="http://subversion.tigris.org/files/documents/15/25364/svn-1.2.3-setup.exe">Subversion
-        client for Windows</ulink>. After installing it, open a new command
-        prompt, go to the base directory, and type:</para>
-
-        <programlisting>svn co http://bbdev.fluffy.co.uk/svn/box/chris/win32/vc2005-compile-fixes/ boxbackup</programlisting>
-
-        <para>This should create a directory called <emphasis
-        role="bold">boxbackup</emphasis> inside the base directory.</para>
-      </section>
-
-      <section>
-        <title>Configure Box Backup</title>
-
-        <para>Open a command prompt, change to the base directory then
-        <emphasis role="bold">boxbackup</emphasis>, and run <emphasis
-        role="bold">win32.bat</emphasis> to configure the sources. Otherwise,
-        Visual C++ will complain about missing files whose names start with
-        <emphasis role="bold">autogen</emphasis>, and missing <emphasis
-        role="bold">config.h</emphasis>.</para>
-      </section>
-
-      <section>
-        <title>Compile Box Backup</title>
-
-        <para>Open Visual C++. Choose "File/Open/Project", navigate to the
-        base directory, then to <emphasis
-        role="bold">boxbackup\infrastructure\msvc\2005</emphasis> (or
-        <emphasis role="bold">2003</emphasis> if using Visual Studio 2003),
-        and open any project or solution file in that directory.</para>
-
-        <para>Press F7 to compile Box Backup. If the compilation is
-        successful, <emphasis
-        role="bold">boxbackup\Debug\bbackupd.exe</emphasis> will be
-        created.</para>
-      </section>
-
-      <section>
-        <title>Install Box Backup</title>
-
-        <para>Create the destination directory, <emphasis
-        role="bold">C:\Program Files\Box Backup\bbackupd</emphasis>.</para>
-
-        <para>Write a configuration file, keys and certificate on a Unix
-        machine, and copy them into the <emphasis role="bold">Box
-        Backup</emphasis> directory, together with the following files from
-        the base directory:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para>boxbackup\Debug\bbackupd.exe</para>
-          </listitem>
-
-          <listitem>
-            <para>openssl\out32dll\libeay32.dll</para>
-          </listitem>
-
-          <listitem>
-            <para>openssl\out32dll\ssleay32.dll</para>
-          </listitem>
-
-          <listitem>
-            <para>zlib\zlib1.dll</para>
-          </listitem>
-        </itemizedlist>
-
-        <para>Ensure that the user running Box Backup can read from the
-        <emphasis role="bold">Box Backup</emphasis> directory, and write to
-        the <emphasis role="bold">bbackupd</emphasis> directory inside
-        it.</para>
-
-        <para>Run Box Backup by double-clicking on it, and check that it
-        connects to the server. If the window opens and closes immediately,
-        it's probably due to a problem with the configuration file - check the
-        Windows Event Viewer for details.</para>
-      </section>
-
-      <section>
-        <title>Windows Service</title>
-
-        <para>Box Backup can also run as a Windows service, in which case it
-        will be automatically started at boot time in the background. To
-        install this, open a command prompt, and run:</para>
-
-        <programlisting>cd "C:\Program Files\Box Backup"
-bbackupd.exe -i</programlisting>
-
-        <para>This should output Box Backup service installed.</para>
-      </section>
-    </section>
-  </appendix>
-
-  <appendix>
-    <title id="AppC">Compilation and installation by building an RPM on
-    Linux</title>
-
-    <para>It is very easy to build an RPM of Box Backup on Linux platforms.
-    This should work on all Red Hat distributions (including Fedora), SuSE,
-    and probably others too.</para>
-
-    <para>Given that you have the correct development packages installed
-    simply execute this command (replacing the version number):</para>
-
-    <programlisting>rpmbuild -ta boxbackup-0.00.tgz</programlisting>
-
-    <para>rpmbuild will report where the packages have been written to, and
-    these can be installed in the normal manner.</para>
-
-    <para>If you have never built an RPM before you should set up a convenient
-    build area as described in the <ulink
-    url="http://www.rpm.org/max-rpm/s1-rpm-anywhere-different-build-area.html">RPM
-    book</ulink>.</para>
-
-    <para>If you wish to customise the package you can find the spec file in
-    the contrib/rpm directory.</para>
-  </appendix>
-</book>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/instguide.xml (from rev 674, box/trunk/documentation/boxbackup/instguide.xml)

Deleted: box/chris/general/documentation/boxbackup/raidfile-config.xml
===================================================================
--- box/trunk/documentation/boxbackup/raidfile-config.xml	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/documentation/boxbackup/raidfile-config.xml	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,143 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry>
-  <refmeta>
-    <refentrytitle>raidfile-config</refentrytitle>
-
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>raidfile-config</refname>
-
-    <refpurpose>Configure Box Backup's RAID files</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>raidfile-config &lt;configdir&gt; &lt;blocksize&gt;
-      &lt;dir1&gt; [&lt;dir2&gt; &lt;dir3&gt;]</command>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsection>
-    <title>Description</title>
-
-    <para>raidfile-config creates a raidfile.conf file for Box Backup. This
-    file holds information about the directories used to store backups in. Box
-    Backup supports userland RAID, in a restricted RAID5 configuration, where
-    3 and only 3 'drives' are supported. You can read more about RAID5 (and
-    other RAID-levels) <ulink
-    url="http://en.wikipedia.org/wiki/Redundant_array_of_independent_disks#RAID_5">here</ulink>.
-    </para>
-
-    <refsection>
-      <title>Parameters</title>
-
-      <para>The parameters are as follows:</para>
-
-      <itemizedlist>
-        <listitem>
-          <para><literal>configdir</literal>: The directory path where
-          configuration files are located. Usually this is
-          <literal>/etc/box</literal>. <literal>raidfile.conf</literal> will
-          be written in this directory.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>blocksize</literal>: The block size used for file
-          storage in the system, in bytes. Using a multple of the file system
-          block size is a good strategy. Depending on the size of the files
-          you will be backing up, this multiple varies. Of course it also
-          depends on the native block size of your file system.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>dir1</literal>: The first directory in the built-in
-          RAID array.</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>dir2</literal>: The second directory in the built-in
-          RAID array. If you are not using the built-in RAID functionality,
-          this field should be ignored. You should not use the built-in RAID,
-          when you have a hardware RAID solution, or if you're using another
-          type of software RAID (like md on Linux).</para>
-        </listitem>
-
-        <listitem>
-          <para><literal>dir3</literal>: The third directory in the built-in
-          RAID array. The same notes that apply to <literal>dir2</literal>
-          also apply to <literal>dir3</literal>.</para>
-        </listitem>
-      </itemizedlist>
-
-      <para>Note that there are currently no way to add multiple disk sets to
-      the raidfile.conf file using command line tools, etc. See
-      raidfile.conf(5) for details on adding more disks</para>
-    </refsection>
-  </refsection>
-
-  <refsection>
-    <title>Author</title>
-
-    <para>Ben Summers and contributors. For help, please go to the <ulink
-    url="http://boxbackup.hostworks.ca/">Wiki</ulink>, or subscribe to the Box
-    Backup <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list.</ulink></para>
-  </refsection>
-
-  <refsection>
-    <title>See Also</title>
-
-    <para><literal>bbstored-config(1)</literal></para>
-
-    <para><literal>bbstored.conf(5)</literal></para>
-
-    <para><literal>raidfile.conf(5)</literal></para>
-  </refsection>
-
-  <refsection>
-    <title>Files</title>
-
-    <para><literal>raidfile-config</literal> generates the raidfile.conf(5)
-    file.</para>
-  </refsection>
-
-  <refsection>
-    <title>Bugs</title>
-
-    <para>If you find a bug in Box Backup, and you want to let us know about
-    it, join the <ulink
-    url="http://lists.warhead.org.uk/mailman/listinfo/boxbackup">mailing
-    list</ulink>, and send a description of the problem there.</para>
-
-    <para>To report a bug, give us at least the following information:</para>
-
-    <itemizedlist>
-      <listitem>
-        <para>The version of Box Backup you are running</para>
-      </listitem>
-
-      <listitem>
-        <para>The platform you are running on (Hardware and OS), for both
-        client and server.</para>
-      </listitem>
-
-      <listitem>
-        <para>If possible attach your config files (bbstored.conf,
-        bbackupd.conf) to the bug report.</para>
-      </listitem>
-
-      <listitem>
-        <para>Also attach any log file output that helps shed light on the
-        problem you are seeing.</para>
-      </listitem>
-
-      <listitem>
-        <para>And last but certainly not least, a description of what you are
-        seeing, in as much detail as possible.</para>
-      </listitem>
-    </itemizedlist>
-  </refsection>
-</refentry>
\ No newline at end of file

Copied: box/chris/general/documentation/boxbackup/raidfile-config.xml (from rev 674, box/trunk/documentation/boxbackup/raidfile-config.xml)


Property changes on: box/chris/general/infrastructure
___________________________________________________________________
Name: svn:ignore
   - BoxPlatform.pm

   + BoxPlatform.pm
makebuildenv.pl
makeparcels.pl


Deleted: box/chris/general/infrastructure/m4/ax_check_llong_minmax.m4
===================================================================
--- box/chris/general/infrastructure/m4/ax_check_llong_minmax.m4	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/infrastructure/m4/ax_check_llong_minmax.m4	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,76 +0,0 @@
-dnl @synopsis AX_CHECK_LLONG_MINMAX
-dnl
-dnl This macro will fix up LLONG_MIN and LLONG_MAX as appropriate. I'm finding
-dnl it quite difficult to believe that so many hoops are necessary. The world
-dnl seems to have gone quite mad.
-dnl
-dnl This gem is adapted from the OpenSSH configure script so here's
-dnl the original copyright notice:
-dnl
-dnl Copyright (c) 1999-2004 Damien Miller
-dnl
-dnl Permission to use, copy, modify, and distribute this software for any
-dnl purpose with or without fee is hereby granted, provided that the above
-dnl copyright notice and this permission notice appear in all copies.
-dnl
-dnl @category C
-dnl @author Martin Ebourne and Damien Miller
-dnl @version 2005/07/07
-
-AC_DEFUN([AX_CHECK_LLONG_MINMAX], [
-  AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [[#include <limits.h>]])
-  if test -z "$have_llong_max"; then
-    AC_MSG_CHECKING([[for max value of long long]])
-    AC_RUN_IFELSE([AC_LANG_SOURCE([[
-      #include <stdio.h>
-      /* Why is this so damn hard? */
-      #undef __GNUC__
-      #undef __USE_ISOC99
-      #define __USE_ISOC99
-      #include <limits.h>
-      #define DATA "conftest.llminmax"
-      int main(void) {
-        FILE *f;
-        long long i, llmin, llmax = 0;
-
-        if((f = fopen(DATA,"w")) == NULL)
-          exit(1);
-
-        #if defined(LLONG_MIN) && defined(LLONG_MAX)
-        fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n");
-        llmin = LLONG_MIN;
-        llmax = LLONG_MAX;
-        #else
-        fprintf(stderr, "Calculating LLONG_MIN and LLONG_MAX\n");
-        /* This will work on one's complement and two's complement */
-        for (i = 1; i > llmax; i <<= 1, i++)
-          llmax = i;
-        llmin = llmax + 1LL;    /* wrap */
-        #endif
-
-        /* Sanity check */
-        if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax || llmax - 1 > llmax) {
-          fprintf(f, "unknown unknown\n");
-          exit(2);
-        }
-
-        if (fprintf(f ,"%lld %lld", llmin, llmax) < 0)
-          exit(3);
-
-        exit(0);
-      }
-      ]])], [
-      read llong_min llong_max < conftest.llminmax
-      AC_MSG_RESULT([$llong_max])
-      AC_DEFINE_UNQUOTED([LLONG_MAX], [${llong_max}LL],
-                         [max value of long long calculated by configure])
-      AC_MSG_CHECKING([[for min value of long long]])
-      AC_MSG_RESULT([$llong_min])
-      AC_DEFINE_UNQUOTED([LLONG_MIN], [${llong_min}LL],
-                         [min value of long long calculated by configure])
-      ],
-      [AC_MSG_RESULT(not found)],
-      [AC_MSG_WARN([[cross compiling: not checking]])]
-      )
-    fi
-  ])dnl

Copied: box/chris/general/infrastructure/m4/ax_config_scripts.m4 (from rev 674, box/trunk/infrastructure/m4/ax_config_scripts.m4)

Deleted: box/chris/general/infrastructure/makebuildenv.pl
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/infrastructure/makebuildenv.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,858 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use Symbol;
-
-my @modules;
-my %module_dependency;
-my %module_library_link_opts;
-my %header_dependency;
-
-$|=1;
-
-
-# note: Mac OS X resource forks and .DS_Store files are explicity ignored
-
-print "Box build environment setup.\n\n";
-
-my @implicit_deps = ('lib/common');
-
-# work out platform variables
-use lib 'infrastructure';
-use BoxPlatform;
-
-# keep copy of command line args
-my $makebuildenv_args = join(' ',@ARGV);
-
-# do command line arguments
-my $compile_line_extra = $platform_compile_line_extra;
-my $link_line_extra = $platform_link_line_extra;
-
-# make sure local files directory exists
-unless(-d 'local')
-{
-	mkdir 'local',0755;
-}
-
-
-# flags about the environment
-my %env_flags;
-
-my $windows_include_path = "";
-if ($target_windows)
-{
-	$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);
-
-# seed autogen code
-print "Seeding autogen code...\n";
-open FINDAUTOGEN,"find . -follow -name Makefile.extra |" or die "Can't use find for locating files";
-while(<FINDAUTOGEN>)
-{
-	chomp;
-	my $file = $_;
-	$file =~ m~\A(.+)/[^/]+\Z~;
-	my $dir = $1;
-	open FL,$file or die "Can't open $_ for reading";
-	my %vars;
-	my $do_cmds = 0;
-	while(<FL>)
-	{
-		chomp;
-		if(m/\A(.+)\s+=\s+(.+)\Z/)
-		{
-			# is a variable
-			$vars{$1} = $2;
-			next;
-		}
-		next unless m/\S/;
-		if(m/AUTOGEN SEEDING/)
-		{
-			$do_cmds = 1;
-		}
-		elsif(m/\A\S/)
-		{
-			$do_cmds = 0 if $do_cmds == 2;
-		}
-		else
-		{
-			# command, run it?
-			if($do_cmds)
-			{
-				$do_cmds = 2; # flag something has been done
-				
-				# subsitute variables, repeatedly
-				my $c = $_;
-				$c =~ s/\A\s+//;
-				while(1)
-				{
-					my $did_subst = 0;
-					
-					for my $k (keys %vars)
-					{
-						$did_subst = 1 if $c =~ s/\$\($k\)/$vars{$k}/g;
-					}
-					
-					last unless $did_subst;
-				}
-				
-				# run command
-				die "Couldn't run command $c" unless (0 == system("(cd $dir; $c)"))
-			}
-		}
-	}
-	close FL;
-}
-close FINDAUTOGEN;
-print "done\n\n";
-
-
-# open test mail 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;
-read FL,$test_template,-s $test_template_file;
-close FL;
-
-
-# extra platform defines
-my $extra_platform_defines = '';
-
-# read in module definitions file, and any files it includes
-my @modules_files;
-sub read_modules_file
-{
-	my ($mf) = @_;
-	my $f = gensym;
-	open $f,$mf or die "Can't open modules file '$mf'\n";
-	while(<$f>)
-	{
-		if(m/\AINCLUDE\s+(\S+)\Z/)
-		{
-			# include another file
-			read_modules_file($1)
-		}
-		else
-		{
-			push @modules_files,$_
-		}
-	}
-	close $f;
-}
-read_modules_file('modules.txt');
-
-# prepare directories...
-mkdir "release",0755;
-mkdir "debug",0755;
-
-# is the library code in another directory?
-my $external_lib = readlink('lib');
-if($external_lib ne '')
-{
-	# adjust to root of the library distribution
-	$external_lib =~ s!/lib\Z!!;
-	$external_lib = '../'.$external_lib;
-	# make symlinks
-	make_obj_symlink('debug');
-	make_obj_symlink('release');
-}
-sub make_obj_symlink
-{
-	my $m = $_[0];
-	my $target = $external_lib."/$m/lib/";
-	my $link = "$m/lib";
-	# check link
-	if(-e $link)
-	{
-		if(-l $link)
-		{
-			if(readlink($link) ne $target)
-			{
-				print "Warning: replacing $link with new link to $target\n";
-				unlink $link;
-			}
-		}
-		else
-		{
-			die "$link already exists, but it isn't a symbolic link"
-		}
-	}
-	if(!-e $link)
-	{
-		symlink $target,$link or die "Can't make $m/lib symlink";
-	}
-}
-
-print "Scanning code...\n";
-
-my $modules_omitted = 0;
-my $modules_omitting = 0;
-
-# process lines in flattened modules files
-for(@modules_files)
-{
-	# clean up line
-	chomp; s/\A\s+//; s/#.*\Z//; s/\s+\Z//; s/\s+/ /g;
-	next unless m/\S/;
-	
-	# omit bits on some platforms?
-	if(m/\AEND-OMIT/)
-	{
-		$modules_omitting = 0;
-		next;
-	}
-
-	next if $modules_omitting;
-
-	if(m/\AOMIT:(.+)/)
-	{
-		if($1 eq $build_os or $1 eq $target_os)
-		{
-			$modules_omitted = 1;
-			$modules_omitting = 1;
-		}
-		next;
-	}
-	
-	# split up...
-	my ($mod, @deps_i) = split / /;
-	
-	# ignore this module?
-	next if ignore_module($mod);
-	
-	# deps for this platform
-	my @deps;
-	for(@deps_i)
-	{
-		my ($dep,$exclude_from) = split /!/;
-		# generic library translation
-		$dep = $env_flags{'LIBTRANS_'.$dep} if exists($env_flags{'LIBTRANS_'.$dep});
-		next if $dep eq '';
-		if($exclude_from =~ m/\A\+(.+)\Z/)
-		{
-			$exclude_from = $1;
-			my $inc = 0;
-			for(split /,/,$exclude_from)
-			{
-				$inc = 1 if $_ eq $build_os
-			}
-			push @deps,$dep if $inc
-		}
-		else
-		{
-			my $inc = 1;
-			for(split /,/,$exclude_from)
-			{
-				$inc = 0 if $_ eq $build_os
-			}
-			push @deps,$dep if $inc
-		}
-	}
-	
-	# check directory exists
-	die "Module $mod can't be found\n" unless -d $mod;
-	
-	# and put in lists
-	push @modules,$mod;
-	my @md;	# module dependencies
-	my @lo; # link line options
-	for(@deps)
-	{
-		if(/\A-l/)
-		{
-			push @lo,$_
-		}
-		else
-		{
-			push @md,$_ unless ignore_module($_)
-		}
-	}
-	$module_dependency{$mod} = [@implicit_deps,@md];
-	$module_library_link_opts{$mod} = [@lo];
-	
-	# make directories, but not if we're using an external library and this a library module
-	my ($s,$d) = split /\//,$mod;
-	if($s ne 'lib' || $external_lib eq '')
-	{
-		mkdir "release/$s",0755;
-		mkdir "release/$s/$d",0755;
-		mkdir "debug/$s",0755;
-		mkdir "debug/$s/$d",0755;
-	}
-}
-
-# make dirs for implicit dep
-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";
-print CONFIGURED_MODS <<__E;
-// automatically generated file, do not edit
-#ifndef _CONFIGURED_MODULES__H
-#define _CONFIGURED_MODULES__H
-__E
-for(@implicit_deps,@modules)
-{
-	my $m = $_;
-	$m =~ s~/~_~;
-	print CONFIGURED_MODS "#define MODULE_$m\n";
-}
-print CONFIGURED_MODS <<__E;
-#endif // _CONFIGURED_MODULES__H
-__E
-close CONFIGURED_MODS;
-
-
-# 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_deps)
-{
-	opendir DIR,$mod;
-	my @items = readdir DIR;
-	closedir DIR;
-
-	# add in items from autogen directories, and create output directories
-	{
-		my @autogen_items;
-		
-		for my $di (@items)
-		{
-			if($di =~ m/\Aautogen/ && -d "$mod/$di")
-			{
-				# Read items
-				my $d = "$mod/$di";
-				opendir DIR,$d;
-				my @i = readdir DIR;
-				closedir DIR;
-				for(@i)
-				{
-					next if m/\A\./;
-					push @autogen_items,"$di/$_"
-				}
-			}
-		}
-		@items = (@items, @autogen_items);
-	}
-
-	for(grep /\.h\Z/i, @items)
-	{
-		next if /\A\._/;	# Temp Mac OS Resource hack
-		die "Header file $_ already used in module ".$hfiles{$_}."\n" if exists $hfiles{$_};
-		$hfiles{$_} = $mod
-	}
-}
-
-for my $mod (@modules, @implicit_deps)
-{
-	opendir DIR,$mod;
-	for my $h (grep /\.h\Z/i, readdir DIR)
-	{
-		next if $h =~ /\A\./;		# Ignore Mac resource forks, autosaves, etc
-
-		open FL,"$mod/$h" or die "can't open $mod/$h";
-		my $f;
-		read FL,$f,-s "$mod/$h";
-		close FL;
-
-		while($f =~ m/\#include\s+"([^"]+?)"/g)
-		{
-			my $i = $1;
-			# ignore autogen exceptions
-			next if $i =~ m/\Aautogen_.+?Exception.h\Z/;
-			# record dependency
-			${$header_dependency{$h}}{$i} = 1 if exists $hfiles{$i};
-		}
-	}
-	closedir DIR;
-}
-
-print "done\n\nGenerating Makefiles...\n";
-
-my %module_resources_win32;
-
-# Then write a makefile for each module
-for my $mod (@implicit_deps, @modules)
-{
-	print $mod,"\n";
-	
-	my ($type,$name) = split /\//,$mod;
-	
-	# add additional files for tests
-	if($type eq 'test')
-	{
-		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";
-		print TESTMAIN $testmain;
-		close TESTMAIN;
-		
-		# test file...
-		sub writetestfile
-		{
-			my ($filename,$runcmd,$module) = @_;		
-			open TESTFILE,">$filename" 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")
-			{
-				print TESTFILE <<__E;
-echo Removing old test files...
-rm -rf testfiles
-echo Copying new test files...
-cp -p -R ../../../$module/testfiles .
-__E
-			}
-			if(-e "$module/testextra")
-			{
-				open FL,"$module/testextra" or die "Can't open $module/testextra";
-				while(<FL>) {print TESTFILE}
-				close FL;
-			}
-			print TESTFILE "$runcmd\n";
-			close TESTFILE;
-		}
-		
-		writetestfile("$mod/_t", 
-			'./test' . $platform_exe_ext . ' $1 $2 $3 $4 $5', $mod);
-		writetestfile("$mod/_t-gdb", 
-			'gdb ./test' . $platform_exe_ext, $mod);
-		
-	}
-	
-	my @all_deps_for_module;
-	{
-		# work out what dependencies need to be run
-		my @deps_raw;
-		sub add_mod_deps
-		{
-			my ($arr_r,$nm) = @_;
-			if($#{$module_dependency{$nm}} >= 0)
-			{
-				push @$arr_r,@{$module_dependency{$nm}};
-				for(@{$module_dependency{$nm}})
-				{
-					add_mod_deps($arr_r,$_)
-				}
-			}
-		}
-		add_mod_deps(\@deps_raw, $mod);
-		# and then dedup and reorder them
-		my %d_done;
-		foreach my $dep (reverse @deps_raw)
-		{
-			if(!exists $d_done{$dep})
-			{
-				# insert
-				push @all_deps_for_module, $dep;
-				# mark as done
-				$d_done{$dep} = 1;
-			}
-		}
-	}	
-	
-
-	# make include path
-	my $include_paths = $windows_include_path .
-		join(' ',map {'-I../../'.$_} @all_deps_for_module);
-
-	# is target a library?
-	my $target_is_library = ($type ne 'bin' && $type ne 'test');
-
-	# make target name
-	my $end_target = $name;
-
-	if ($target_is_library)
-	{
-		$end_target .= '.a';
-	}
-	else
-	{
-		$end_target .= $platform_exe_ext;
-	}
-
-	$end_target = 'test'.$platform_exe_ext if $type eq 'test';
-
-	# adjust for outdir
-	$end_target = '$(OUTDIR)/' . $end_target;
-
-	# 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";
-	my $debug_link_extra = ($target_is_library)?'':'../../debug/lib/debug/debug.a';
-
-	my $release_flags = "-O2";
-	if ($target_windows)
-	{
-		$release_flags = "-O0 -g";
-	}
-
-	print MAKE <<__E;
-#
-# AUTOMATICALLY GENERATED FILE
-#    do not edit!
-#
-#
-CXX = g++
-AR = ar
-RANLIB = ranlib
-WINDRES = windres
-.ifdef RELEASE
-CXXFLAGS = -DNDEBUG $release_flags -Wall $include_paths $extra_platform_defines -DBOX_VERSION="\\"$product_version\\""
-OUTBASE = ../../release
-OUTDIR = ../../release/$mod
-DEPENDMAKEFLAGS = -D RELEASE
-VARIENT = RELEASE
-.else
-CXXFLAGS = -g -Wall $include_paths $extra_platform_defines -DBOX_VERSION="\\"$product_version\\""
-OUTBASE = ../../debug
-OUTDIR = ../../debug/$mod
-DEPENDMAKEFLAGS =
-VARIENT = DEBUG
-.endif
-
-__E
-	
-	# read directory
-	opendir DIR,$mod;
-	my @items = readdir DIR;
-	closedir DIR;
-	
-	# add in items from autogen directories, and create output directories
-	{
-		my @autogen_items;
-		for my $di (@items)
-		{
-			if($di =~ m/\Aautogen/ && -d "$mod/$di")
-			{
-				# Read items
-				my $d = "$mod/$di";
-				opendir DIR,$d;
-				my @i = readdir DIR;
-				closedir DIR;
-				for(@i)
-				{
-					next if m/\A\./;
-					push @autogen_items,"$di/$_"
-				}
-				
-				# output directories
-				mkdir "release/$mod/$di",0755;
-				mkdir "debug/$mod/$di",0755;
-			}
-		}
-		@items = (@items, @autogen_items);
-	}
-	
-	# first, obtain a list of dependencies within the .h files
-	my %headers;
-	for my $h (grep /\.h\Z/i, @items)
-	{
-		open FL,"$mod/$h";
-		my $f;
-		read FL,$f,-s "$mod/$h";
-		close FL;
-
-		while($f =~ m/\#include\s+"([^"]+?)"/g)
-		{
-			${$headers{$h}}{$1} = 1 if exists $hfiles{$1};
-		}
-	}
-	
-	# ready for the rest of the details...
-	my $make;
-	
-	# then... do the cpp files...
-	my @obj_base;
-	for my $file (@items)
-	{
-		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
-		push @obj_base,$base;
-	
-		# get the file...
-		open FL,"$mod/$file";
-		my $f;
-		read FL,$f,-s "$mod/$file";
-		close FL;
-		
-		my %dep;
-
-		while($f =~ m/\#include\s+"([^"]+?)"/g)
-		{
-			insert_dep($1, \%dep) if exists $hfiles{$1};
-		}
-		
-		# output filename
-		my $out_name = '$(OUTDIR)/'.$base.'.o';
-		
-		# write the line for this cpp file
-		my @dep_paths = map 
-		{ 
-			($hfiles{$_} eq $mod)
-			? $_ 
-			: '../../'.$hfiles{$_}."/$_"
-		}
-		keys %dep;
-
-		$make .= $out_name.': '.join(' ',$file,@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);
-# ----- # always has dependencies with debug library
-	$has_deps = 1;
-	$has_deps = 0 if $target_is_library;
-
-	# Depenency stuff
-	my $deps_makeinfo;
-	if($has_deps)
-	{
-		if($bsd_make)
-		{
-			$deps_makeinfo = <<'__E';
-.BEGIN::
-.ifndef NODEPS
-.	if $(.TARGETS) == ""
-__E
-		}
-		else
-		{
-			# gnu make
-			$deps_makeinfo = <<'__E';
-.PHONY:	dep_modules
-dep_modules:
-ifndef NODEPS
-ifeq ($(strip $(.TARGETS)),)
-__E
-		}
-		
-		# run make for things we require
-		for my $dep (@all_deps_for_module)
-		{
-			$deps_makeinfo .= "\t\t(cd ../../$dep; \$(MAKE)$sub_make_options \$(DEPENDMAKEFLAGS) -D NODEPS)\n";
-		}
-		$deps_makeinfo .= ".\tendif\n.endif\n\n";
-	}
-	print MAKE $deps_makeinfo if $bsd_make;
-	
-	# get the list of library things to add -- in order of dependency so things link properly
-	my $lib_files = join(' ',map {($_ =~ m/lib\/(.+)\Z/)?('$(OUTBASE)/'.$_.'/'.$1.'.a'):undef} (reverse(@all_deps_for_module)));
-
-	# need to see if the extra makefile fragments require extra object files
-	# or include any more makefiles
-	my @objs = @obj_base;
-	my @makefile_includes;
-	
-	additional_objects_from_make_fragment("$mod/Makefile.extra", \@objs, \@makefile_includes);
-	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 " ",$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)
-	{
-		# make a library archive...
-		print MAKE "\t(echo -n > $end_target; rm $end_target)\n";
-		print MAKE "\t\$(AR) -q $end_target $o_file_list\n";
-		print MAKE "\t\$(RANLIB) $end_target\n";
-	}
-	else
-	{
-		# work out library options
-		# need to be... least used first, in absolute order they appear in the modules.txt file
-		my @libops;
-		sub libops_fill
-		{
-			my ($m,$r) = @_;
-			push @$r,$_ for(@{$module_library_link_opts{$m}});
-			libops_fill($_,$r) for(@{$module_dependency{$m}});
-		}
-		libops_fill($mod,\@libops);
-		my $lo = '';
-		my %ldone;
-		for(@libops)
-		{
-			next if exists $ldone{$_};
-			$lo .= ' '.$_;
-			$ldone{$_} = 1;
-		}
-	
-		# link line...
-		print MAKE "\t\$(CXX) $link_line_extra -o $end_target $o_file_list $lib_files$lo $platform_lib_files\n";
-	}
-	# tests need to copy the test file over
-	if($type eq 'test')
-	{
-		print MAKE "\tcp _t \$(OUTDIR)/t\n\tchmod u+x \$(OUTDIR)/t\n";
-		print MAKE "\tcp _t-gdb \$(OUTDIR)/t-gdb\n\tchmod u+x \$(OUTDIR)/t-gdb\n";
-	}
-	# dependency line?
-	print MAKE "\n";
-
-	# module dependencies for GNU make?
-	print MAKE $deps_makeinfo if !$bsd_make;
-	
-	# print the rest of the file
-	print MAKE $make,"\n";
-	
-	# and a clean target
-	print MAKE "clean:\n\t-rm -rf \$(OUTDIR)/*\n.\tifndef SUBCLEAN\n";
-	for my $dep (@all_deps_for_module)
-	{
-		print MAKE "\t(cd ../../$dep; \$(MAKE) \$(DEPENDMAKEFLAGS) -D SUBCLEAN clean)\n";
-	}
-	print MAKE ".\tendif\n";
-	
-	# include any extra stuff
-	print MAKE "\n\n";
-	if(-e "$mod/Makefile.extra")
-	{
-		print MAKE ".include <Makefile.extra>\n\n";
-	}
-	if(-e "$mod/Makefile.extra.$build_os")
-	{
-		print MAKE ".include <Makefile.extra.$build_os>\n\n";
-	}
-	for(@makefile_includes)
-	{
-		print MAKE ".include <$_>\n\n";
-	}
-	
-	# and finally a target for rebuilding the build system
-	print MAKE "\nbuildsystem:\n\t(cd ../..; perl ./infrastructure/makebuildenv.pl $makebuildenv_args)\n\n";
-	
-	close MAKE;
-
-	if(!$bsd_make)
-	{
-		# need to post process this into a GNU makefile
-		open MAKE,">$mod/Makefile";
-		open MAKEB,"$mod/MakefileX";
-
-		while(<MAKEB>)
-		{
-			s/\A\.\s*(ifdef|else|endif|ifndef)/$1/;
-			s/\A\.\s*include\s+<(.+?)>/include $1/;
-			s/-D\s+(\w+)/$1=1/;
-			print MAKE;
-		}
-
-		close MAKEB;
-		close MAKE;
-		unlink "$mod/MakefileX";
-	}
-}
-
-print "\nType 'cd <module_dir>; $make_command' to build a module\n\n";
-
-if($modules_omitted)
-{
-	print "\nNOTE: Some modules have been omitted on this platform\n\n"
-}
-
-sub insert_dep
-{
-	my ($h,$dep_r) = @_;
-	
-	# stop random recusion
-	return if exists $$dep_r{$h};
-	
-	# insert more depencies
-	insert_dep($_,$dep_r) for keys %{$header_dependency{$h}};
-
-	# mark this one as a dependency
-	$$dep_r{$h} = 1;
-}
-
-
-sub additional_objects_from_make_fragment
-{
-	my ($fn,$objs_r,$include_r) = @_;
-	
-	if(-e $fn)
-	{
-		open FL,$fn or die "Can't open $fn";
-		
-		while(<FL>)
-		{
-			chomp;
-			if(m/link-extra:\s*(.+)\Z/)
-			{
-				my @o = split /\s+/,$1;
-				for(@o)
-				{
-					push @$objs_r,$1 if m/\A(.+)\.o\Z/;
-				}
-			}
-			elsif(m/include-makefile:\s*(\S+)/)
-			{
-				push @$include_r,$1
-			}
-		}
-		
-		close FL;
-	}
-}
-
-
-sub ignore_module
-{
-	exists $env_flags{'IGNORE_'.$_[0]}
-}

Copied: box/chris/general/infrastructure/makebuildenv.pl.in (from rev 674, box/trunk/infrastructure/makebuildenv.pl.in)
===================================================================
--- box/trunk/infrastructure/makebuildenv.pl.in	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/infrastructure/makebuildenv.pl.in	2006-07-23 00:12:10 UTC (rev 675)
@@ -0,0 +1,860 @@
+#!@PERL@
+use strict;
+use Symbol;
+
+my @modules;
+my %module_dependency;
+my %module_library_link_opts;
+my %header_dependency;
+
+$|=1;
+
+
+# note: Mac OS X resource forks and .DS_Store files are explicity ignored
+
+print "Box build environment setup.\n\n";
+
+my @implicit_deps = ('lib/common');
+
+# work out platform variables
+use lib 'infrastructure';
+use BoxPlatform;
+
+# keep copy of command line args
+my $makebuildenv_args = join(' ',@ARGV);
+
+# do command line arguments
+my $compile_line_extra = $platform_compile_line_extra;
+my $link_line_extra = $platform_link_line_extra;
+
+# make sure local files directory exists
+unless(-d 'local')
+{
+	mkdir 'local',0755;
+}
+
+
+# flags about the environment
+my %env_flags;
+
+my $windows_include_path = "";
+if ($target_windows)
+{
+	$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);
+
+# seed autogen code
+print "Seeding autogen code...\n";
+open FINDAUTOGEN,"find . -follow -name Makefile.extra |" or die "Can't use find for locating files";
+while(<FINDAUTOGEN>)
+{
+	chomp;
+	my $file = $_;
+	$file =~ m~\A(.+)/[^/]+\Z~;
+	my $dir = $1;
+	open FL,$file or die "Can't open $_ for reading";
+	my %vars;
+	$vars{PERL} = "@PERL@";
+	my $do_cmds = 0;
+	while(<FL>)
+	{
+		chomp;
+		if(m/\A(.+)\s+=\s+(.+)\Z/)
+		{
+			# is a variable
+			$vars{$1} = $2;
+			next;
+		}
+		next unless m/\S/;
+		if(m/AUTOGEN SEEDING/)
+		{
+			$do_cmds = 1;
+		}
+		elsif(m/\A\S/)
+		{
+			$do_cmds = 0 if $do_cmds == 2;
+		}
+		else
+		{
+			# command, run it?
+			if($do_cmds)
+			{
+				$do_cmds = 2; # flag something has been done
+				
+				# subsitute variables, repeatedly
+				my $c = $_;
+				$c =~ s/\A\s+//;
+				while(1)
+				{
+					my $did_subst = 0;
+					
+					for my $k (keys %vars)
+					{
+						$did_subst = 1 if $c =~ s/\$\($k\)/$vars{$k}/g;
+					}
+					
+					last unless $did_subst;
+				}
+				
+				# run command
+				die "Couldn't run command $c" unless (0 == system("(cd $dir; $c)"))
+			}
+		}
+	}
+	close FL;
+}
+close FINDAUTOGEN;
+print "done\n\n";
+
+
+# open test mail 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;
+read FL,$test_template,-s $test_template_file;
+close FL;
+
+
+# extra platform defines
+my $extra_platform_defines = '';
+
+# read in module definitions file, and any files it includes
+my @modules_files;
+sub read_modules_file
+{
+	my ($mf) = @_;
+	my $f = gensym;
+	open $f,$mf or die "Can't open modules file '$mf'\n";
+	while(<$f>)
+	{
+		if(m/\AINCLUDE\s+(\S+)\Z/)
+		{
+			# include another file
+			read_modules_file($1)
+		}
+		else
+		{
+			push @modules_files,$_
+		}
+	}
+	close $f;
+}
+read_modules_file('modules.txt');
+
+# prepare directories...
+mkdir "release",0755;
+mkdir "debug",0755;
+
+# is the library code in another directory?
+my $external_lib = readlink('lib');
+if($external_lib ne '')
+{
+	# adjust to root of the library distribution
+	$external_lib =~ s!/lib\Z!!;
+	$external_lib = '../'.$external_lib;
+	# make symlinks
+	make_obj_symlink('debug');
+	make_obj_symlink('release');
+}
+sub make_obj_symlink
+{
+	my $m = $_[0];
+	my $target = $external_lib."/$m/lib/";
+	my $link = "$m/lib";
+	# check link
+	if(-e $link)
+	{
+		if(-l $link)
+		{
+			if(readlink($link) ne $target)
+			{
+				print "Warning: replacing $link with new link to $target\n";
+				unlink $link;
+			}
+		}
+		else
+		{
+			die "$link already exists, but it isn't a symbolic link"
+		}
+	}
+	if(!-e $link)
+	{
+		symlink $target,$link or die "Can't make $m/lib symlink";
+	}
+}
+
+print "Scanning code...\n";
+
+my $modules_omitted = 0;
+my $modules_omitting = 0;
+
+# process lines in flattened modules files
+for(@modules_files)
+{
+	# clean up line
+	chomp; s/\A\s+//; s/#.*\Z//; s/\s+\Z//; s/\s+/ /g;
+	next unless m/\S/;
+	
+	# omit bits on some platforms?
+	if(m/\AEND-OMIT/)
+	{
+		$modules_omitting = 0;
+		next;
+	}
+
+	next if $modules_omitting;
+
+	if(m/\AOMIT:(.+)/)
+	{
+		if($1 eq $build_os or $1 eq $target_os)
+		{
+			$modules_omitted = 1;
+			$modules_omitting = 1;
+		}
+		next;
+	}
+	
+	# split up...
+	my ($mod, @deps_i) = split / /;
+	
+	# ignore this module?
+	next if ignore_module($mod);
+	
+	# deps for this platform
+	my @deps;
+	for(@deps_i)
+	{
+		my ($dep,$exclude_from) = split /!/;
+		# generic library translation
+		$dep = $env_flags{'LIBTRANS_'.$dep} if exists($env_flags{'LIBTRANS_'.$dep});
+		next if $dep eq '';
+		if($exclude_from =~ m/\A\+(.+)\Z/)
+		{
+			$exclude_from = $1;
+			my $inc = 0;
+			for(split /,/,$exclude_from)
+			{
+				$inc = 1 if $_ eq $build_os
+			}
+			push @deps,$dep if $inc
+		}
+		else
+		{
+			my $inc = 1;
+			for(split /,/,$exclude_from)
+			{
+				$inc = 0 if $_ eq $build_os
+			}
+			push @deps,$dep if $inc
+		}
+	}
+	
+	# check directory exists
+	die "Module $mod can't be found\n" unless -d $mod;
+	
+	# and put in lists
+	push @modules,$mod;
+	my @md;	# module dependencies
+	my @lo; # link line options
+	for(@deps)
+	{
+		if(/\A-l/)
+		{
+			push @lo,$_
+		}
+		else
+		{
+			push @md,$_ unless ignore_module($_)
+		}
+	}
+	$module_dependency{$mod} = [@implicit_deps,@md];
+	$module_library_link_opts{$mod} = [@lo];
+	
+	# make directories, but not if we're using an external library and this a library module
+	my ($s,$d) = split /\//,$mod;
+	if($s ne 'lib' || $external_lib eq '')
+	{
+		mkdir "release/$s",0755;
+		mkdir "release/$s/$d",0755;
+		mkdir "debug/$s",0755;
+		mkdir "debug/$s/$d",0755;
+	}
+}
+
+# make dirs for implicit dep
+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";
+print CONFIGURED_MODS <<__E;
+// automatically generated file, do not edit
+#ifndef _CONFIGURED_MODULES__H
+#define _CONFIGURED_MODULES__H
+__E
+for(@implicit_deps,@modules)
+{
+	my $m = $_;
+	$m =~ s~/~_~;
+	print CONFIGURED_MODS "#define MODULE_$m\n";
+}
+print CONFIGURED_MODS <<__E;
+#endif // _CONFIGURED_MODULES__H
+__E
+close CONFIGURED_MODS;
+
+
+# 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_deps)
+{
+	opendir DIR,$mod;
+	my @items = readdir DIR;
+	closedir DIR;
+
+	# add in items from autogen directories, and create output directories
+	{
+		my @autogen_items;
+		
+		for my $di (@items)
+		{
+			if($di =~ m/\Aautogen/ && -d "$mod/$di")
+			{
+				# Read items
+				my $d = "$mod/$di";
+				opendir DIR,$d;
+				my @i = readdir DIR;
+				closedir DIR;
+				for(@i)
+				{
+					next if m/\A\./;
+					push @autogen_items,"$di/$_"
+				}
+			}
+		}
+		@items = (@items, @autogen_items);
+	}
+
+	for(grep /\.h\Z/i, @items)
+	{
+		next if /\A\._/;	# Temp Mac OS Resource hack
+		die "Header file $_ already used in module ".$hfiles{$_}."\n" if exists $hfiles{$_};
+		$hfiles{$_} = $mod
+	}
+}
+
+for my $mod (@modules, @implicit_deps)
+{
+	opendir DIR,$mod;
+	for my $h (grep /\.h\Z/i, readdir DIR)
+	{
+		next if $h =~ /\A\./;		# Ignore Mac resource forks, autosaves, etc
+
+		open FL,"$mod/$h" or die "can't open $mod/$h";
+		my $f;
+		read FL,$f,-s "$mod/$h";
+		close FL;
+
+		while($f =~ m/\#include\s+"([^"]+?)"/g)
+		{
+			my $i = $1;
+			# ignore autogen exceptions
+			next if $i =~ m/\Aautogen_.+?Exception.h\Z/;
+			# record dependency
+			${$header_dependency{$h}}{$i} = 1 if exists $hfiles{$i};
+		}
+	}
+	closedir DIR;
+}
+
+print "done\n\nGenerating Makefiles...\n";
+
+my %module_resources_win32;
+
+# Then write a makefile for each module
+for my $mod (@implicit_deps, @modules)
+{
+	print $mod,"\n";
+	
+	my ($type,$name) = split /\//,$mod;
+	
+	# add additional files for tests
+	if($type eq 'test')
+	{
+		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";
+		print TESTMAIN $testmain;
+		close TESTMAIN;
+		
+		# test file...
+		sub writetestfile
+		{
+			my ($filename,$runcmd,$module) = @_;		
+			open TESTFILE,">$filename" 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")
+			{
+				print TESTFILE <<__E;
+echo Removing old test files...
+rm -rf testfiles
+echo Copying new test files...
+cp -p -R ../../../$module/testfiles .
+__E
+			}
+			if(-e "$module/testextra")
+			{
+				open FL,"$module/testextra" or die "Can't open $module/testextra";
+				while(<FL>) {print TESTFILE}
+				close FL;
+			}
+			print TESTFILE "$runcmd\n";
+			close TESTFILE;
+		}
+		
+		writetestfile("$mod/_t", 
+			'./test' . $platform_exe_ext . ' $1 $2 $3 $4 $5', $mod);
+		writetestfile("$mod/_t-gdb", 
+			'gdb ./test' . $platform_exe_ext, $mod);
+		
+	}
+	
+	my @all_deps_for_module;
+	{
+		# work out what dependencies need to be run
+		my @deps_raw;
+		sub add_mod_deps
+		{
+			my ($arr_r,$nm) = @_;
+			if($#{$module_dependency{$nm}} >= 0)
+			{
+				push @$arr_r,@{$module_dependency{$nm}};
+				for(@{$module_dependency{$nm}})
+				{
+					add_mod_deps($arr_r,$_)
+				}
+			}
+		}
+		add_mod_deps(\@deps_raw, $mod);
+		# and then dedup and reorder them
+		my %d_done;
+		foreach my $dep (reverse @deps_raw)
+		{
+			if(!exists $d_done{$dep})
+			{
+				# insert
+				push @all_deps_for_module, $dep;
+				# mark as done
+				$d_done{$dep} = 1;
+			}
+		}
+	}	
+	
+
+	# make include path
+	my $include_paths = $windows_include_path .
+		join(' ',map {'-I../../'.$_} @all_deps_for_module);
+
+	# is target a library?
+	my $target_is_library = ($type ne 'bin' && $type ne 'test');
+
+	# make target name
+	my $end_target = $name;
+
+	if ($target_is_library)
+	{
+		$end_target .= '.a';
+	}
+	else
+	{
+		$end_target .= $platform_exe_ext;
+	}
+
+	$end_target = 'test'.$platform_exe_ext if $type eq 'test';
+
+	# adjust for outdir
+	$end_target = '$(OUTDIR)/' . $end_target;
+
+	# 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";
+	my $debug_link_extra = ($target_is_library)?'':'../../debug/lib/debug/debug.a';
+
+	my $release_flags = "-O2";
+	if ($target_windows)
+	{
+		$release_flags = "-O0 -g";
+	}
+
+	print MAKE <<__E;
+#
+# AUTOMATICALLY GENERATED FILE
+#    do not edit!
+#
+#
+CXX = g++
+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
+OUTDIR = ../../release/$mod
+DEPENDMAKEFLAGS = -D RELEASE
+VARIENT = RELEASE
+.else
+CXXFLAGS = -g -Wall $include_paths $extra_platform_defines -DBOX_VERSION="\\"$product_version\\""
+OUTBASE = ../../debug
+OUTDIR = ../../debug/$mod
+DEPENDMAKEFLAGS =
+VARIENT = DEBUG
+.endif
+
+__E
+	
+	# read directory
+	opendir DIR,$mod;
+	my @items = readdir DIR;
+	closedir DIR;
+	
+	# add in items from autogen directories, and create output directories
+	{
+		my @autogen_items;
+		for my $di (@items)
+		{
+			if($di =~ m/\Aautogen/ && -d "$mod/$di")
+			{
+				# Read items
+				my $d = "$mod/$di";
+				opendir DIR,$d;
+				my @i = readdir DIR;
+				closedir DIR;
+				for(@i)
+				{
+					next if m/\A\./;
+					push @autogen_items,"$di/$_"
+				}
+				
+				# output directories
+				mkdir "release/$mod/$di",0755;
+				mkdir "debug/$mod/$di",0755;
+			}
+		}
+		@items = (@items, @autogen_items);
+	}
+	
+	# first, obtain a list of dependencies within the .h files
+	my %headers;
+	for my $h (grep /\.h\Z/i, @items)
+	{
+		open FL,"$mod/$h";
+		my $f;
+		read FL,$f,-s "$mod/$h";
+		close FL;
+
+		while($f =~ m/\#include\s+"([^"]+?)"/g)
+		{
+			${$headers{$h}}{$1} = 1 if exists $hfiles{$1};
+		}
+	}
+	
+	# ready for the rest of the details...
+	my $make;
+	
+	# then... do the cpp files...
+	my @obj_base;
+	for my $file (@items)
+	{
+		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
+		push @obj_base,$base;
+	
+		# get the file...
+		open FL,"$mod/$file";
+		my $f;
+		read FL,$f,-s "$mod/$file";
+		close FL;
+		
+		my %dep;
+
+		while($f =~ m/\#include\s+"([^"]+?)"/g)
+		{
+			insert_dep($1, \%dep) if exists $hfiles{$1};
+		}
+		
+		# output filename
+		my $out_name = '$(OUTDIR)/'.$base.'.o';
+		
+		# write the line for this cpp file
+		my @dep_paths = map 
+		{ 
+			($hfiles{$_} eq $mod)
+			? $_ 
+			: '../../'.$hfiles{$_}."/$_"
+		}
+		keys %dep;
+
+		$make .= $out_name.': '.join(' ',$file,@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);
+# ----- # always has dependencies with debug library
+	$has_deps = 1;
+	$has_deps = 0 if $target_is_library;
+
+	# Depenency stuff
+	my $deps_makeinfo;
+	if($has_deps)
+	{
+		if($bsd_make)
+		{
+			$deps_makeinfo = <<'__E';
+.BEGIN::
+.ifndef NODEPS
+.	if $(.TARGETS) == ""
+__E
+		}
+		else
+		{
+			# gnu make
+			$deps_makeinfo = <<'__E';
+.PHONY:	dep_modules
+dep_modules:
+ifndef NODEPS
+ifeq ($(strip $(.TARGETS)),)
+__E
+		}
+		
+		# run make for things we require
+		for my $dep (@all_deps_for_module)
+		{
+			$deps_makeinfo .= "\t\t(cd ../../$dep; \$(MAKE)$sub_make_options \$(DEPENDMAKEFLAGS) -D NODEPS)\n";
+		}
+		$deps_makeinfo .= ".\tendif\n.endif\n\n";
+	}
+	print MAKE $deps_makeinfo if $bsd_make;
+	
+	# get the list of library things to add -- in order of dependency so things link properly
+	my $lib_files = join(' ',map {($_ =~ m/lib\/(.+)\Z/)?('$(OUTBASE)/'.$_.'/'.$1.'.a'):undef} (reverse(@all_deps_for_module)));
+
+	# need to see if the extra makefile fragments require extra object files
+	# or include any more makefiles
+	my @objs = @obj_base;
+	my @makefile_includes;
+	
+	additional_objects_from_make_fragment("$mod/Makefile.extra", \@objs, \@makefile_includes);
+	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 " ",$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)
+	{
+		# make a library archive...
+		print MAKE "\t(echo -n > $end_target; rm $end_target)\n";
+		print MAKE "\t\$(AR) -q $end_target $o_file_list\n";
+		print MAKE "\t\$(RANLIB) $end_target\n";
+	}
+	else
+	{
+		# work out library options
+		# need to be... least used first, in absolute order they appear in the modules.txt file
+		my @libops;
+		sub libops_fill
+		{
+			my ($m,$r) = @_;
+			push @$r,$_ for(@{$module_library_link_opts{$m}});
+			libops_fill($_,$r) for(@{$module_dependency{$m}});
+		}
+		libops_fill($mod,\@libops);
+		my $lo = '';
+		my %ldone;
+		for(@libops)
+		{
+			next if exists $ldone{$_};
+			$lo .= ' '.$_;
+			$ldone{$_} = 1;
+		}
+	
+		# link line...
+		print MAKE "\t\$(CXX) $link_line_extra -o $end_target $o_file_list $lib_files$lo $platform_lib_files\n";
+	}
+	# tests need to copy the test file over
+	if($type eq 'test')
+	{
+		print MAKE "\tcp _t \$(OUTDIR)/t\n\tchmod u+x \$(OUTDIR)/t\n";
+		print MAKE "\tcp _t-gdb \$(OUTDIR)/t-gdb\n\tchmod u+x \$(OUTDIR)/t-gdb\n";
+	}
+	# dependency line?
+	print MAKE "\n";
+
+	# module dependencies for GNU make?
+	print MAKE $deps_makeinfo if !$bsd_make;
+	
+	# print the rest of the file
+	print MAKE $make,"\n";
+	
+	# and a clean target
+	print MAKE "clean:\n\t-rm -rf \$(OUTDIR)/*\n.\tifndef SUBCLEAN\n";
+	for my $dep (@all_deps_for_module)
+	{
+		print MAKE "\t(cd ../../$dep; \$(MAKE) \$(DEPENDMAKEFLAGS) -D SUBCLEAN clean)\n";
+	}
+	print MAKE ".\tendif\n";
+	
+	# include any extra stuff
+	print MAKE "\n\n";
+	if(-e "$mod/Makefile.extra")
+	{
+		print MAKE ".include <Makefile.extra>\n\n";
+	}
+	if(-e "$mod/Makefile.extra.$build_os")
+	{
+		print MAKE ".include <Makefile.extra.$build_os>\n\n";
+	}
+	for(@makefile_includes)
+	{
+		print MAKE ".include <$_>\n\n";
+	}
+	
+	# and finally a target for rebuilding the build system
+	print MAKE "\nbuildsystem:\n\t(cd ../..; perl ./infrastructure/makebuildenv.pl $makebuildenv_args)\n\n";
+	
+	close MAKE;
+
+	if(!$bsd_make)
+	{
+		# need to post process this into a GNU makefile
+		open MAKE,">$mod/Makefile";
+		open MAKEB,"$mod/MakefileX";
+
+		while(<MAKEB>)
+		{
+			s/\A\.\s*(ifdef|else|endif|ifndef)/$1/;
+			s/\A\.\s*include\s+<(.+?)>/include $1/;
+			s/-D\s+(\w+)/$1=1/;
+			print MAKE;
+		}
+
+		close MAKEB;
+		close MAKE;
+		unlink "$mod/MakefileX";
+	}
+}
+
+print "\nType 'cd <module_dir>; $make_command' to build a module\n\n";
+
+if($modules_omitted)
+{
+	print "\nNOTE: Some modules have been omitted on this platform\n\n"
+}
+
+sub insert_dep
+{
+	my ($h,$dep_r) = @_;
+	
+	# stop random recusion
+	return if exists $$dep_r{$h};
+	
+	# insert more depencies
+	insert_dep($_,$dep_r) for keys %{$header_dependency{$h}};
+
+	# mark this one as a dependency
+	$$dep_r{$h} = 1;
+}
+
+
+sub additional_objects_from_make_fragment
+{
+	my ($fn,$objs_r,$include_r) = @_;
+	
+	if(-e $fn)
+	{
+		open FL,$fn or die "Can't open $fn";
+		
+		while(<FL>)
+		{
+			chomp;
+			if(m/link-extra:\s*(.+)\Z/)
+			{
+				my @o = split /\s+/,$1;
+				for(@o)
+				{
+					push @$objs_r,$1 if m/\A(.+)\.o\Z/;
+				}
+			}
+			elsif(m/include-makefile:\s*(\S+)/)
+			{
+				push @$include_r,$1
+			}
+		}
+		
+		close FL;
+	}
+}
+
+
+sub ignore_module
+{
+	exists $env_flags{'IGNORE_'.$_[0]}
+}

Modified: box/chris/general/infrastructure/makedistribution.pl
===================================================================
--- box/chris/general/infrastructure/makedistribution.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/infrastructure/makedistribution.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!@PERL@
 use strict;
 use Symbol;
 

Deleted: box/chris/general/infrastructure/makeparcels.pl
===================================================================
--- box/chris/general/infrastructure/makeparcels.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/infrastructure/makeparcels.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,190 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use lib 'infrastructure';
-use BoxPlatform;
-
-my @parcels;
-my %parcel_contents;
-
-open PARCELS,"parcels.txt" or die "Can't open parcels file";
-{
-	my $cur_parcel = '';
-	while(<PARCELS>)
-	{
-		chomp; s/#.+\Z//; s/\s+\Z//; s/\s+/ /g;
-		next unless m/\S/;
-		
-		# omit bits on some platforms?
-		next if m/\AEND-OMIT/;
-		if(m/\AOMIT:(.+)/)
-		{
-			if($1 eq $build_os or $1 eq $target_os)
-			{
-				while(<PARCELS>)
-				{
-					last if m/\AEND-OMIT/;	
-				}
-			}
-			next;
-		}
-
-		if (m'\AONLY:(.+)')
-		{
-			my @only_targets = split m'\,', $1;
-
-			if (not grep {$_ eq $build_os or $_ eq $target_os}
-				@only_targets)
-			{
-				while (<PARCELS>)
-				{
-					last if m'\AEND-ONLY';
-				}
-			}
-			next;
-		}
-		next if (m'\AEND-ONLY');
-		
-		# new parcel, or a new parcel definition?
-		if(m/\A\s+(.+)\Z/)
-		{
-			push @{$parcel_contents{$cur_parcel}},$1
-		}
-		else
-		{
-			$cur_parcel = $_;
-			push @parcels,$_;
-		}
-	}
-}
-close PARCELS;
-
-# create parcels directory
-mkdir "parcels",0755;
-mkdir "parcels/scripts",0755;
-
-# write master makefile
-
-open MAKE,">Makefile" or die "Can't open master Makefile for writing";
-
-print MAKE <<__E;
-#
-# AUTOMATICALLY GENERATED FILE
-#    do not edit!
-#
-#
-
-MAKE = $make_command
-
-__E
-
-print MAKE "all:\t",join(' ',map {parcel_target($_)} @parcels),"\n\n";
-
-print MAKE "clean:\n";
-for my $parcel (@parcels)
-{
-	print MAKE "\trm -rf ",parcel_dir($parcel),"\n";
-	print MAKE "\trm -f ",parcel_target($parcel),"\n";
-}
-print MAKE "\n";
-
-print MAKE "test:\trelease/common/test\n\nrelease/common/test:\n\t./runtest.pl ALL release\n\n";
-
-my $release_flag = BoxPlatform::make_flag('RELEASE');
-
-for my $parcel (@parcels)
-{
-	my $target = parcel_target($parcel);
-	print MAKE $target,":\n";
-	
-	my $dir = parcel_dir($parcel);
-	print MAKE "\ttest -d $dir || mkdir $dir\n";
-	
-	open SCRIPT,">parcels/scripts/install-$parcel" or die "Can't open installer script for $parcel for writing";
-	print SCRIPT "#!/bin/sh\n\n";
-	
-	for(@{$parcel_contents{$parcel}})
-	{
-		my ($type,$name) = split /\s+/;
-		my $optional = '';
-
-		if ($type eq 'optional')
-		{
-			($optional,$type,$name) = split /\s+/;
-		}
-		
-		if($type eq 'bin')
-		{
-			my $exeext = $platform_exe_ext;
-			print MAKE "\t(cd bin/$name; \$(MAKE) $release_flag)\n";
-			print MAKE "\tcp release/bin/$name/$name$exeext $dir\n";
-		}
-		elsif ($type eq 'script')
-		{
-			if ($optional)
-			{
-				print MAKE "\ttest -r $name && cp $name $dir\n";
-			}
-			else
-			{
-				print MAKE "\tcp $name $dir\n";
-			}
-			# remove path from script name
-			$name =~ m~/([^/]+)\Z~;
-			$name = $1;
-		}
-
-		print SCRIPT "install $name $install_into_dir\n";
-	}
-	
-	close SCRIPT;
-	
-	chmod 0755,"parcels/scripts/install-$parcel";
-	
-	my $root = parcel_root($parcel);
-	print MAKE "\tcp parcels/scripts/install-$parcel $dir\n";
-	print MAKE "\t(cd parcels; tar cf - $root | gzip -9 - > $root.tgz )\n";
-	
-	print MAKE "\n";
-	
-	print MAKE "install-$parcel:\n";
-	print MAKE "\t(cd $dir; ./install-$parcel)\n\n";
-}
-
-print MAKE <<__E;
-install:
-	cat local/install.msg
-
-__E
-
-close MAKE;
-
-open INSTALLMSG,">local/install.msg" or die "Can't open install message file for writing";
-print INSTALLMSG <<__E;
-
-Parcels need to be installed separately, and as root. Type one of the following:
-
-__E
-
-for(@parcels)
-{
-	print INSTALLMSG "    $make_command install-".$_."\n";
-}
-print INSTALLMSG "\n";
-
-close INSTALLMSG;
-
-sub parcel_root
-{
-	$product_name.'-'.$product_version.'-'.$_[0].'-'.$target_os
-}
-
-sub parcel_dir
-{
-	'parcels/'.parcel_root($_[0])
-}
-
-sub parcel_target
-{
-	parcel_dir($_[0]).'.tgz'
-}

Copied: box/chris/general/infrastructure/makeparcels.pl.in (from rev 674, box/trunk/infrastructure/makeparcels.pl.in)

Modified: box/chris/general/infrastructure/setupexternal.pl
===================================================================
--- box/chris/general/infrastructure/setupexternal.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/infrastructure/setupexternal.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!@PERL@
 use strict;
 
 # This script links in the essential directories and processes various

Modified: box/chris/general/lib/backupclient/Makefile.extra
===================================================================
--- box/chris/general/lib/backupclient/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/backupclient/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -5,12 +5,12 @@
 
 # AUTOGEN SEEDING
 autogen_BackupProtocolClient.cpp autogen_BackupProtocolClient.h:	$(MAKEPROTOCOL) ../../bin/bbstored/backupprotocol.txt
-	perl $(GEN_CMD_SRV)
+	$(PERL) $(GEN_CMD_SRV)
 
 
 MAKEEXCEPTION = ../../lib/common/makeexception.pl
 
 # AUTOGEN SEEDING
 autogen_BackupStoreException.h autogen_BackupStoreException.cpp:	$(MAKEEXCEPTION) BackupStoreException.txt
-	perl $(MAKEEXCEPTION) BackupStoreException.txt
+	$(PERL) $(MAKEEXCEPTION) BackupStoreException.txt
 


Property changes on: box/chris/general/lib/common
___________________________________________________________________
Name: svn:ignore
   - autogen_CommonException.cpp
autogen_CommonException.h
autogen_ConversionException.cpp
autogen_ConversionException.h
BoxConfig.h
BoxConfig.h.in
Makefile


   + autogen_CommonException.cpp
autogen_CommonException.h
autogen_ConversionException.cpp
autogen_ConversionException.h
BoxConfig.h
BoxConfig.h.in
Makefile
makeexception.pl


Modified: box/chris/general/lib/common/Makefile.extra
===================================================================
--- box/chris/general/lib/common/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/common/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -3,9 +3,9 @@
 
 # AUTOGEN SEEDING
 autogen_CommonException.h autogen_CommonException.cpp:	$(MAKEEXCEPTION) CommonException.txt
-	perl $(MAKEEXCEPTION) CommonException.txt
+	$(PERL) $(MAKEEXCEPTION) CommonException.txt
 
 # AUTOGEN SEEDING
 autogen_ConversionException.h autogen_ConversionException.cpp:	$(MAKEEXCEPTION) ConversionException.txt
-	perl $(MAKEEXCEPTION) ConversionException.txt
+	$(PERL) $(MAKEEXCEPTION) ConversionException.txt
 

Deleted: box/chris/general/lib/common/makeexception.pl
===================================================================
--- box/chris/general/lib/common/makeexception.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/common/makeexception.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,277 +0,0 @@
-#!/usr/bin/perl
-
-# global exception list file
-my $global_list = '../../ExceptionCodes.txt';
-
-
-my @exception;
-my @exception_desc;
-my $class;
-my $class_number;
-
-# read the description!
-
-open EXCEPTION_DESC,$ARGV[0] or die "Can't open $ARGV[0]";
-
-while(<EXCEPTION_DESC>)
-{
-	chomp; s/\A\s+//; s/#.+\Z//; s/\s+\Z//; s/\s+/ /g;
-	next unless m/\S/;
-
-	if(m/\AEXCEPTION\s+(.+)\s+(\d+)\Z/)
-	{
-		$class = $1;
-		$class_number = $2;
-	}
-	else
-	{
-		my ($name,$number,$description) = split /\s+/,$_,3;
-		if($name eq '' || $number =~ m/\D/)
-		{
-			die "Bad line '$_'";
-		}
-		if($exception[$number] ne '')
-		{
-			die "Duplicate exception number $number";
-		}
-		$exception[$number] = $name;
-		$exception_desc[$number] = $description;
-	}
-}
-
-die "Exception class and number not specified" unless $class ne '' && $class_number ne '';
-
-close EXCEPTION_DESC;
-
-# 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";
-
-# write header file
-my $guardname = uc 'AUTOGEN_'.$class.'EXCEPTION_H';
-print H <<__E;
-
-// Auto-generated file -- do not edit
-
-#ifndef $guardname
-#define $guardname
-
-#include "BoxException.h"
-
-// --------------------------------------------------------------------------
-//
-// Class
-//		Name:    ${class}Exception
-//		Purpose: Exception
-//		Created: autogen
-//
-// --------------------------------------------------------------------------
-class ${class}Exception : public BoxException
-{
-public:
-	${class}Exception(unsigned int SubType)
-		: mSubType(SubType)
-	{
-	}
-	
-	${class}Exception(const ${class}Exception &rToCopy)
-		: mSubType(rToCopy.mSubType)
-	{
-	}
-	
-	~${class}Exception() throw ()
-	{
-	}
-	
-	enum
-	{
-		ExceptionType = $class_number
-	};
-
-	enum
-	{
-__E
-
-for(my $e = 0; $e <= $#exception; $e++)
-{
-	if($exception[$e] ne '')
-	{
-		print H "\t\t".$exception[$e].' = '.$e.(($e==$#exception)?'':',')."\n"
-	}
-}
-
-print H <<__E;
-	};
-	
-	virtual unsigned int GetType() const throw();
-	virtual unsigned int GetSubType() const throw();
-	virtual const char *what() const throw();
-
-private:
-	unsigned int mSubType;
-};
-
-#endif // $guardname
-__E
-
-# -----------------------------------------------------------------------------------------------------------
-
-print CPP <<__E;
-
-// Auto-generated file -- do not edit
-
-#include "Box.h"
-#include "autogen_${class}Exception.h"
-
-#include "MemLeakFindOn.h"
-
-#ifdef EXCEPTION_CODENAMES_EXTENDED
-	#ifdef EXCEPTION_CODENAMES_EXTENDED_WITH_DESCRIPTION
-static const char *whats[] = {
-__E
-
-my $last_seen = -1;
-for(my $e = 0; $e <= $#exception; $e++)
-{
-	if($exception[$e] ne '')
-	{
-		for(my $s = $last_seen + 1; $s < $e; $s++)
-		{
-			print CPP "\t\"UNUSED\",\n"
-		}
-		my $ext = ($exception_desc[$e] ne '')?" ($exception_desc[$e])":'';
-		print CPP "\t\"${class} ".$exception[$e].$ext.'"'.(($e==$#exception)?'':',')."\n";
-		$last_seen = $e;
-	}
-}
-
-print CPP <<__E;
-};
-	#else
-static const char *whats[] = {
-__E
-
-$last_seen = -1;
-for(my $e = 0; $e <= $#exception; $e++)
-{
-	if($exception[$e] ne '')
-	{
-		for(my $s = $last_seen + 1; $s < $e; $s++)
-		{
-			print CPP "\t\"UNUSED\",\n"
-		}
-		print CPP "\t\"${class} ".$exception[$e].'"'.(($e==$#exception)?'':',')."\n";
-		$last_seen = $e;
-	}
-}
-
-print CPP <<__E;
-};
-	#endif
-#endif
-
-unsigned int ${class}Exception::GetType() const throw()
-{
-	return ${class}Exception::ExceptionType;
-}
-
-unsigned int ${class}Exception::GetSubType() const throw()
-{
-	return mSubType;
-}
-
-const char *${class}Exception::what() const throw()
-{
-#ifdef EXCEPTION_CODENAMES_EXTENDED
-	if(mSubType < 0 || mSubType > (sizeof(whats) / sizeof(whats[0])))
-	{
-		return "${class}";
-	}
-	return whats[mSubType];
-#else
-	return "${class}";
-#endif
-}
-
-__E
-
-close H;
-close CPP;
-
-# update the global exception list
-my $list_before;
-my $list_after;
-my $is_after = 0;
-if(open CURRENT,$global_list)
-{
-	while(<CURRENT>)
-	{
-		next if m/\A#/;
-		
-		if(m/\AEXCEPTION TYPE (\w+) (\d+)/)
-		{
-			# check that the number isn't being reused
-			if($2 == $class_number && $1 ne $class)
-			{
-				die "Class number $class_number is being used by $class and $1 -- correct this.\n";
-			}
-			if($2 > $class_number)
-			{
-				# This class comes after the current one (ensures numerical ordering)
-				$is_after = 1;
-			}
-			if($1 eq $class)
-			{
-				# skip this entry
-				while(<CURRENT>)
-				{
-					last if m/\AEND TYPE/;
-				}
-				$_ = '';
-			}
-		}
-		
-		if($is_after)
-		{
-			$list_after .= $_;
-		}
-		else
-		{
-			$list_before .= $_;
-		}
-	}
-
-	close CURRENT;
-}
-
-open GLOBAL,">$global_list" or die "Can't open global exception code listing for writing";
-
-print GLOBAL <<__E;
-#
-# automatically generated file, do not edit.
-#
-# This file lists all the exception codes used by the system.
-# Use to look up more detailed descriptions of meanings of errors.
-#
-__E
-
-print GLOBAL $list_before;
-
-print GLOBAL "EXCEPTION TYPE $class $class_number\n";
-for(my $e = 0; $e <= $#exception; $e++)
-{
-	if($exception[$e] ne '')
-	{
-		my $ext = ($exception_desc[$e] ne '')?" - $exception_desc[$e]":'';
-		print GLOBAL "($class_number/$e) - ${class} ".$exception[$e].$ext."\n";
-	}
-}
-print GLOBAL "END TYPE\n";
-
-print GLOBAL $list_after;
-
-close GLOBAL;
-
-

Copied: box/chris/general/lib/common/makeexception.pl.in (from rev 674, box/trunk/lib/common/makeexception.pl.in)

Modified: box/chris/general/lib/compress/Makefile.extra
===================================================================
--- box/chris/general/lib/compress/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/compress/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -3,5 +3,5 @@
 
 # AUTOGEN SEEDING
 autogen_CompressException.h autogen_CompressException.cpp:	$(MAKEEXCEPTION) CompressException.txt
-	perl $(MAKEEXCEPTION) CompressException.txt
+	$(PERL) $(MAKEEXCEPTION) CompressException.txt
 

Modified: box/chris/general/lib/crypto/Makefile.extra
===================================================================
--- box/chris/general/lib/crypto/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/crypto/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -3,5 +3,5 @@
 
 # AUTOGEN SEEDING
 autogen_CipherException.cpp autogen_CipherException.h:	$(MAKEEXCEPTION) CipherException.txt
-	perl $(MAKEEXCEPTION) CipherException.txt
+	$(PERL) $(MAKEEXCEPTION) CipherException.txt
 


Property changes on: box/chris/general/lib/raidfile
___________________________________________________________________
Name: svn:ignore
   - autogen_RaidFileException.cpp
autogen_RaidFileException.h
Makefile

   + autogen_RaidFileException.cpp
autogen_RaidFileException.h
Makefile
raidfile-config


Modified: box/chris/general/lib/raidfile/Makefile.extra
===================================================================
--- box/chris/general/lib/raidfile/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/raidfile/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -3,5 +3,5 @@
 
 # AUTOGEN SEEDING
 autogen_RaidFileException.h autogen_RaidFileException.cpp:	$(MAKEEXCEPTION) RaidFileException.txt
-	perl $(MAKEEXCEPTION) RaidFileException.txt
+	$(PERL) $(MAKEEXCEPTION) RaidFileException.txt
 

Deleted: box/chris/general/lib/raidfile/raidfile-config
===================================================================
--- box/chris/general/lib/raidfile/raidfile-config	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/raidfile/raidfile-config	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,97 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-# should be running as root
-if($> != 0)
-{
-	printf "\nWARNING: this should be run as root\n\n"
-}
-
-# check and get command line parameters
-if($#ARGV != 4 && $#ARGV != 2)
-{
-	print <<__E;
-
-Setup raidfile config utility.
-
-Bad command line parameters.
-Usage:
-	raidfile-config config-dir block-size dir0 [dir1 dir2]
-
-config-dir usually /etc/box
-block-size must be a power of two, and usually the block or fragment size of your filing system
-dir0, dir1, dir2 are the directories used as the root of the raid file system
-
-If only one directory is specified, then userland RAID is disabled. Specifying three directories
-enables it.
-
-__E
-	exit(1);
-}
-
-my ($config_dir,$block_size,@dirs) = @ARGV;
-
-my $conf = $config_dir . '/raidfile.conf';
-
-# check dirs are unique, and exist
-my %d;
-for(@dirs)
-{
-	die "$_ is used twice" if exists $d{$_};
-	die "$_ is not a directory" unless -d $_;
-	die "$_ should be an absolute path" unless m/\A\//;
-	$d{$_} = 1;
-}
-
-# check block size is OK
-$block_size = int($block_size);
-die "Bad block size" if $block_size <= 0;
-my $c = 1;
-while(1)
-{
-	last if $c == $block_size;
-	die "Block size $block_size is not a power of two" if $c > $block_size;
-	$c = $c * 2;
-}
-
-# check that it doesn't already exist
-if(-f $conf)
-{
-	die "$conf already exists. Delete and try again"
-}
-
-# create directory
-if(!-d $config_dir)
-{
-	print "Creating $config_dir...\n";
-	mkdir $config_dir,0755 or die "Can't create $config_dir";
-}
-
-# adjust if userland RAID is disabled
-if($#dirs == 0)
-{
-	$dirs[1] = $dirs[0];
-	$dirs[2] = $dirs[0];
-	print "WARNING: userland RAID is disabled.\n"
-}
-
-# write the file
-open CONFIG,">$conf" or die "Can't open $conf for writing";
-
-print CONFIG <<__E;
-
-disc0
-{
-	SetNumber = 0
-	BlockSize = $block_size
-	Dir0 = $dirs[0]
-	Dir1 = $dirs[1]
-	Dir2 = $dirs[2]
-}
-
-__E
-
-close CONFIG;
-
-print "Config file written.\n";
-

Copied: box/chris/general/lib/raidfile/raidfile-config.in (from rev 674, box/trunk/lib/raidfile/raidfile-config.in)


Property changes on: box/chris/general/lib/server
___________________________________________________________________
Name: svn:ignore
   - autogen_ConnectionException.cpp
autogen_ConnectionException.h
autogen_ServerException.cpp
autogen_ServerException.h
Makefile

   + autogen_ConnectionException.cpp
autogen_ConnectionException.h
autogen_ServerException.cpp
autogen_ServerException.h
Makefile
makeprotocol.pl


Modified: box/chris/general/lib/server/Makefile.extra
===================================================================
--- box/chris/general/lib/server/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/server/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -3,9 +3,9 @@
 
 # AUTOGEN SEEDING
 autogen_ServerException.h autogen_ServerException.cpp:	$(MAKEEXCEPTION) ServerException.txt
-	perl $(MAKEEXCEPTION) ServerException.txt
+	$(PERL) $(MAKEEXCEPTION) ServerException.txt
 
 # AUTOGEN SEEDING
 autogen_ConnectionException.h autogen_ConnectionException.cpp:	$(MAKEEXCEPTION) ConnectionException.txt
-	perl $(MAKEEXCEPTION) ConnectionException.txt
+	$(PERL) $(MAKEEXCEPTION) ConnectionException.txt
 

Deleted: box/chris/general/lib/server/makeprotocol.pl
===================================================================
--- box/chris/general/lib/server/makeprotocol.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/lib/server/makeprotocol.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,1007 +0,0 @@
-#!/usr/bin/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)
-# may get stuff added to it later if protocol uses extra types
-my %translate_type_info =
-(
-	'int64' => [1, 'int64_t'],
-	'int32' => [1, 'int32_t'],
-	'int16' => [1, 'int16_t'],
-	'int8' => [1, 'int8_t'],
-	'bool' => [1, 'bool'],
-	'string' => [0, 'std::string']
-);
-
-# built in instructions for logging various types
-# may be added to
-my %log_display_types = 
-(
-	'int64' => ['0x%llx', 'VAR'],
-	'int32' => ['0x%x', 'VAR'],
-	'int16' => ['0x%x', 'VAR'],
-	'int8' => ['0x%x', 'VAR'],
-	'bool' => ['%s', '((VAR)?"true":"false")'],
-	'string' => ['%s', 'VAR.c_str()']
-);
-
-
-
-my ($type, $file) = @ARGV;
-
-if($type ne 'Server' && $type ne 'Client')
-{
-	die "Neither Server or Client is specified on command line\n";
-}
-
-open IN, $file or die "Can't open input file $file\n";
-
-print "Making $type protocol classes from $file...\n";
-
-my @extra_header_files;
-
-my $implement_syslog = 0;
-my $implement_filelog = 0;
-
-# read attributes
-my %attr;
-while(<IN>)
-{
-	# get and clean line
-	my $l = $_; $l =~ s/#.*\Z//; $l =~ s/\A\s+//; $l =~ s/\s+\Z//; next unless $l =~ m/\S/;
-	
-	last if $l eq 'BEGIN_OBJECTS';
-	
-	my ($k,$v) = split /\s+/,$l,2;
-	
-	if($k eq 'ClientType')
-	{
-		add_type($v) if $type eq 'Client';
-	}
-	elsif($k eq 'ServerType')
-	{
-		add_type($v) if $type eq 'Server';
-	}
-	elsif($k eq 'ImplementLog')
-	{
-		my ($log_if_type,$log_type) = split /\s+/,$v;
-		if($type eq $log_if_type)
-		{
-			if($log_type eq 'syslog')
-			{
-				$implement_syslog = 1;
-			}
-			elsif($log_type eq 'file')
-			{
-				$implement_filelog = 1;
-			}
-			else
-			{
-				printf("ERROR: Unknown log type for implementation: $log_type\n");
-				exit(1);
-			}
-		}
-	}
-	elsif($k eq 'LogTypeToText')
-	{
-		my ($log_if_type,$type_name,$printf_format,$arg_template) = split /\s+/,$v;
-		if($type eq $log_if_type)
-		{
-			$log_display_types{$type_name} = [$printf_format,$arg_template]
-		}
-	}
-	else
-	{
-		$attr{$k} = $v;
-	}
-}
-
-sub add_type
-{
-	my ($protocol_name, $cpp_name, $header_file) = split /\s+/,$_[0];
-	
-	$translate_type_info{$protocol_name} = [0, $cpp_name];
-	push @extra_header_files, $header_file;
-}
-
-# check attributes
-for(qw/Name ServerContextClass IdentString/)
-{
-	if(!exists $attr{$_})
-	{
-		die "Attribute $_ is required, but not specified\n";
-	}
-}
-
-my $protocol_name = $attr{'Name'};
-my ($context_class, $context_class_inc) = split /\s+/,$attr{'ServerContextClass'};
-my $ident_string = $attr{'IdentString'};
-
-my $current_cmd = '';
-my %cmd_contents;
-my %cmd_attributes;
-my %cmd_constants;
-my %cmd_id;
-my @cmd_list;
-
-# read in the command definitions
-while(<IN>)
-{
-	# get and clean line
-	my $l = $_; $l =~ s/#.*\Z//; $l =~ s/\s+\Z//; next unless $l =~ m/\S/;
-	
-	# definitions or new command thing?
-	if($l =~ m/\A\s+/)
-	{
-		die "No command defined yet" if $current_cmd eq '';
-	
-		# definition of component
-		$l =~ s/\A\s+//;
-		
-		my ($type,$name,$value) = split /\s+/,$l;
-		if($type eq 'CONSTANT')
-		{
-			push @{$cmd_constants{$current_cmd}},"$name = $value"
-		}
-		else
-		{
-			push @{$cmd_contents{$current_cmd}},$type,$name;
-		}
-	}
-	else
-	{
-		# new command
-		my ($name,$id,@attributes) = split /\s+/,$l;
-		$cmd_attributes{$name} = [@attributes];
-		$cmd_id{$name} = int($id);
-		$current_cmd = $name;
-		push @cmd_list,$name;
-	}
-}
-
-close IN;
-
-
-
-# open files
-my $h_filename = 'autogen_'.$protocol_name.'Protocol'.$type.'.h';
-open CPP,'>autogen_'.$protocol_name.'Protocol'.$type.'.cpp';
-open H,">$h_filename";
-
-print CPP <<__E;
-
-// Auto-generated file -- do not edit
-
-#include "Box.h"
-#include "$h_filename"
-#include "IOStream.h"
-
-__E
-
-if($implement_syslog)
-{
-	print H <<EOF;
-#ifndef WIN32
-#include <syslog.h>
-#endif
-EOF
-}
-
-
-my $guardname = uc 'AUTOGEN_'.$protocol_name.'Protocol'.$type.'_H';
-print H <<__E;
-
-// Auto-generated file -- do not edit
-
-#ifndef $guardname
-#define $guardname
-
-#include "Protocol.h"
-#include "ProtocolObject.h"
-#include "ServerException.h"
-
-class IOStream;
-
-__E
-
-if($implement_filelog)
-{
-	print H qq~#include <stdio.h>\n~;
-}
-
-# extra headers
-for(@extra_header_files)
-{
-	print H qq~#include "$_"\n~
-}
-print H "\n";
-
-if($type eq 'Server')
-{
-	# need utils file for the server
-	print H '#include "Utils.h"',"\n\n"
-}
-
-
-my $derive_objects_from = 'ProtocolObject';
-my $objects_extra_h = '';
-my $objects_extra_cpp = '';
-if($type eq 'Server')
-{
-	# define the context
-	print H "class $context_class;\n\n";
-	print CPP "#include \"$context_class_inc\"\n\n";
-	
-	# change class we derive the objects from
-	$derive_objects_from = $protocol_name.'ProtocolObject';
-	
-	$objects_extra_h = <<__E;
-	virtual std::auto_ptr<ProtocolObject> DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext);
-__E
-	$objects_extra_cpp = <<__E;
-std::auto_ptr<ProtocolObject> ${derive_objects_from}::DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext)
-{
-	THROW_EXCEPTION(ConnectionException, Conn_Protocol_TriedToExecuteReplyCommand)
-}
-__E
-}
-
-print CPP qq~#include "MemLeakFindOn.h"\n~;
-
-if($type eq 'Client' && ($implement_syslog || $implement_filelog))
-{
-	# change class we derive the objects from
-	$derive_objects_from = $protocol_name.'ProtocolObjectCl';
-}
-if($implement_syslog)
-{
-	$objects_extra_h .= <<__E;
-	virtual void LogSysLog(const char *Action) const = 0;
-__E
-}
-if($implement_filelog)
-{
-	$objects_extra_h .= <<__E;
-	virtual void LogFile(const char *Action, FILE *file) const = 0;
-__E
-}
-
-if($derive_objects_from ne 'ProtocolObject')
-{	
-	# output a definition for the protocol object derviced class
-	print H <<__E;
-class ${protocol_name}ProtocolServer;
-	
-class $derive_objects_from : public ProtocolObject
-{
-public:
-	$derive_objects_from();
-	virtual ~$derive_objects_from();
-	$derive_objects_from(const $derive_objects_from &rToCopy);
-	
-$objects_extra_h
-};
-__E
-
-	# and some cpp definitions
-	print CPP <<__E;
-${derive_objects_from}::${derive_objects_from}()
-{
-}
-${derive_objects_from}::~${derive_objects_from}()
-{
-}
-${derive_objects_from}::${derive_objects_from}(const $derive_objects_from &rToCopy)
-{
-}
-$objects_extra_cpp
-__E
-}
-
-
-
-my $classname_base = $protocol_name.'Protocol'.$type;
-
-# output the classes
-for my $cmd (@cmd_list)
-{
-	print H <<__E;
-class $classname_base$cmd : public $derive_objects_from
-{
-public:
-	$classname_base$cmd();
-	$classname_base$cmd(const $classname_base$cmd &rToCopy);
-	~$classname_base$cmd();
-	int GetType() const;
-	enum
-	{
-		TypeID = $cmd_id{$cmd}
-	};
-__E
-	# constants
-	if(exists $cmd_constants{$cmd})
-	{
-		print H "\tenum\n\t{\n\t\t";
-		print H join(",\n\t\t",@{$cmd_constants{$cmd}});
-		print H "\n\t};\n";
-	}
-	# flags
-	if(obj_is_type($cmd,'EndsConversation'))
-	{
-		print H "\tbool IsConversationEnd() const;\n";
-	}
-	if(obj_is_type($cmd,'IsError'))
-	{
-		print H "\tbool IsError(int &rTypeOut, int &rSubTypeOut) const;\n";
-	}
-	if($type eq 'Server' && obj_is_type($cmd, 'Command'))
-	{
-		print H "\tstd::auto_ptr<ProtocolObject> DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext); // IMPLEMENT THIS\n"
-	}
-
-	# want to be able to read from streams?
-	my $read_from_streams = (obj_is_type($cmd,'Command') && $type eq 'Server') || (obj_is_type($cmd,'Reply') && $type eq 'Client');
-	my $write_to_streams = (obj_is_type($cmd,'Command') && $type eq 'Client') || (obj_is_type($cmd,'Reply') && $type eq 'Server');
-	
-	if($read_from_streams)
-	{
-		print H "\tvoid SetPropertiesFromStreamData(Protocol &rProtocol);\n";
-		
-		# write Get functions
-		for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-		{
-			my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-			
-			print H "\t".translate_type_to_arg_type($ty)." Get$nm() {return m$nm;}\n";
-		}
-	}
-	my $param_con_args = '';
-	if($write_to_streams)
-	{
-		# extra constructor?
-		if($#{$cmd_contents{$cmd}} >= 0)
-		{
-			my @a;
-			for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-			{
-				my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-
-				push @a,translate_type_to_arg_type($ty)." $nm";
-			}		
-			$param_con_args = join(', ',@a);
-			print H "\t$classname_base$cmd(".$param_con_args.");\n";
-		}
-		print H "\tvoid WritePropertiesToStreamData(Protocol &rProtocol) const;\n";
-		# set functions
-		for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-		{
-			my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-			
-			print H "\tvoid Set$nm(".translate_type_to_arg_type($ty)." $nm) {m$nm = $nm;}\n";
-		}
-	}
-	
-	if($implement_syslog)
-	{
-		print H "\tvirtual void LogSysLog(const char *Action) const;\n";
-	}
-	if($implement_filelog)
-	{
-		print H "\tvirtual void LogFile(const char *Action, FILE *file) const;\n";
-	}
-
-	
-	# write member variables and setup for cpp file
-	my @def_constructor_list;
-	my @copy_constructor_list;
-	my @param_constructor_list;
-	
-	print H "private:\n";
-	for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-	{
-		my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-
-		print H "\t".translate_type_to_member_type($ty)." m$nm;\n";
-		
-		my ($basic,$typename) = translate_type($ty);
-		if($basic)
-		{
-			push @def_constructor_list, "m$nm(0)";
-		}
-		push @copy_constructor_list, "m$nm(rToCopy.m$nm)";
-		push @param_constructor_list, "m$nm($nm)";
-	}
-	
-	# finish off
-	print H "};\n\n";
-	
-	# now the cpp file...
-	my $def_con_vars = join(",\n\t  ",@def_constructor_list);
-	$def_con_vars = "\n\t: ".$def_con_vars if $def_con_vars ne '';
-	my $copy_con_vars = join(",\n\t  ",@copy_constructor_list);
-	$copy_con_vars = "\n\t: ".$copy_con_vars if $copy_con_vars ne '';
-	my $param_con_vars = join(",\n\t  ",@param_constructor_list);
-	$param_con_vars = "\n\t: ".$param_con_vars if $param_con_vars ne '';
-
-	my $class = "$classname_base$cmd".'::';
-	print CPP <<__E;
-$class$classname_base$cmd()$def_con_vars
-{
-}
-$class$classname_base$cmd(const $classname_base$cmd &rToCopy)$copy_con_vars
-{
-}
-$class~$classname_base$cmd()
-{
-}
-int ${class}GetType() const
-{
-	return $cmd_id{$cmd};
-}
-__E
-	if($read_from_streams)
-	{
-		print CPP "void ${class}SetPropertiesFromStreamData(Protocol &rProtocol)\n{\n";
-		for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-		{
-			my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-			if($ty =~ m/\Avector/)
-			{
-				print CPP "\trProtocol.ReadVector(m$nm);\n";
-			}
-			else
-			{
-				print CPP "\trProtocol.Read(m$nm);\n";
-			}
-		}
-		print CPP "}\n";
-	}
-	if($write_to_streams)
-	{
-		# implement extra constructor?
-		if($param_con_vars ne '')
-		{
-			print CPP "$class$classname_base$cmd($param_con_args)$param_con_vars\n{\n}\n";
-		}
-		print CPP "void ${class}WritePropertiesToStreamData(Protocol &rProtocol) const\n{\n";
-		for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-		{
-			my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-			if($ty =~ m/\Avector/)
-			{
-				print CPP "\trProtocol.WriteVector(m$nm);\n";
-			}
-			else
-			{
-				print CPP "\trProtocol.Write(m$nm);\n";
-			}
-		}
-		print CPP "}\n";
-	}
-	if(obj_is_type($cmd,'EndsConversation'))
-	{
-		print CPP "bool ${class}IsConversationEnd() const\n{\n\treturn true;\n}\n";
-	}
-	if(obj_is_type($cmd,'IsError'))
-	{
-		# get parameters
-		my ($mem_type,$mem_subtype) = split /,/,obj_get_type_params($cmd,'IsError');
-		print CPP <<__E;
-bool ${class}IsError(int &rTypeOut, int &rSubTypeOut) const
-{
-	rTypeOut = m$mem_type;
-	rSubTypeOut = m$mem_subtype;
-	return true;
-}
-__E
-	}
-
-	if($implement_syslog)
-	{
-		my ($format,$args) = make_log_strings($cmd);
-		print CPP <<__E;
-void ${class}LogSysLog(const char *Action) const
-{
-	::syslog(LOG_INFO,"%s $format",Action$args);
-}
-__E
-	}
-	if($implement_filelog)
-	{
-		my ($format,$args) = make_log_strings($cmd);
-		print CPP <<__E;
-void ${class}LogFile(const char *Action, FILE *File) const
-{
-	::fprintf(File,"%s $format\\n",Action$args);
-	::fflush(File);
-}
-__E
-	}
-}
-
-# finally, the protocol object itself
-print H <<__E;
-class $classname_base : public Protocol
-{
-public:
-	$classname_base(IOStream &rStream);
-	virtual ~$classname_base();
-
-	std::auto_ptr<$derive_objects_from> Receive();
-	void Send(const ${derive_objects_from} &rObject);
-__E
-if($implement_syslog)
-{
-	print H "\tvoid SetLogToSysLog(bool Log = false) {mLogToSysLog = Log;}\n";
-}
-if($implement_filelog)
-{
-	print H "\tvoid SetLogToFile(FILE *File = 0) {mLogToFile = File;}\n";
-}
-if($type eq 'Server')
-{
-	# need to put in the conversation function
-	print H "\tvoid DoServer($context_class &rContext);\n\n";
-	# and the send vector thing
-	print H "\tvoid SendStreamAfterCommand(IOStream *pStream);\n\n";
-}
-if($type eq 'Client')
-{
-	# add plain object taking query functions
-	my $with_params;
-	for my $cmd (@cmd_list)
-	{
-		if(obj_is_type($cmd,'Command'))
-		{
-			my $has_stream = obj_is_type($cmd,'StreamWithCommand');
-			my $argextra = $has_stream?', IOStream &rStream':'';
-			my $queryextra = $has_stream?', rStream':'';
-			my $reply = obj_get_type_params($cmd,'Command');
-			print H "\tstd::auto_ptr<$classname_base$reply> Query(const $classname_base$cmd &rQuery$argextra);\n";
-			my @a;
-			my @na;
-			for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-			{
-				my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-				push @a,translate_type_to_arg_type($ty)." $nm";
-				push @na,"$nm";
-			}
-			my $ar = join(', ',@a);
-			my $nar = join(', ',@na);
-			$nar = "($nar)" if $nar ne '';
-
-			$with_params .= "\tinline std::auto_ptr<$classname_base$reply> Query$cmd($ar$argextra)\n\t{\n";
-			$with_params .= "\t\t$classname_base$cmd send$nar;\n";
-			$with_params .= "\t\treturn Query(send$queryextra);\n";
-			$with_params .= "\t}\n";
-		}
-	}
-	# quick hack to correct bad argument lists for commands with zero paramters but with streams
-	$with_params =~ s/\(, /(/g;
-	print H "\n",$with_params,"\n";
-}
-print H <<__E;
-private:
-	$classname_base(const $classname_base &rToCopy);
-__E
-if($type eq 'Server')
-{
-	# need to put the streams to send vector
-	print H "\tstd::vector<IOStream*> mStreamsToSend;\n\tvoid DeleteStreamsToSend();\n";
-}
-
-if($implement_filelog || $implement_syslog)
-{
-	print H <<__E;
-	virtual void InformStreamReceiving(u_int32_t Size);
-	virtual void InformStreamSending(u_int32_t Size);
-__E
-}
-
-if($implement_syslog)
-{
-	print H "private:\n\tbool mLogToSysLog;\n";
-}
-if($implement_filelog)
-{
-	print H "private:\n\tFILE *mLogToFile;\n";
-}
-print H <<__E;
-
-protected:	
-	virtual std::auto_ptr<ProtocolObject> MakeProtocolObject(int ObjType);
-	virtual const char *GetIdentString();
-};
-
-__E
-
-my $construtor_extra = '';
-$construtor_extra .= ', mLogToSysLog(false)' if $implement_syslog;
-$construtor_extra .= ', mLogToFile(0)' if $implement_filelog;
-
-my $destructor_extra = ($type eq 'Server')?"\n\tDeleteStreamsToSend();":'';
-
-my $prefix = $classname_base.'::';
-print CPP <<__E;
-$prefix$classname_base(IOStream &rStream)
-	: Protocol(rStream)$construtor_extra
-{
-}
-$prefix~$classname_base()
-{$destructor_extra
-}
-const char *${prefix}GetIdentString()
-{
-	return "$ident_string";
-}
-std::auto_ptr<ProtocolObject> ${prefix}MakeProtocolObject(int ObjType)
-{
-	switch(ObjType)
-	{
-__E
-
-# do objects within this
-for my $cmd (@cmd_list)
-{
-	print CPP <<__E;
-	case $cmd_id{$cmd}:
-		return std::auto_ptr<ProtocolObject>(new $classname_base$cmd);
-		break;
-__E
-}
-
-print CPP <<__E;
-	default:
-		THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnknownCommandRecieved)
-	}
-}
-__E
-# write receieve and send functions
-print CPP <<__E;
-std::auto_ptr<$derive_objects_from> ${prefix}Receive()
-{
-	std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(Protocol::Receive().release()));
-
-__E
-	if($implement_syslog)
-	{
-		print CPP <<__E;
-	if(mLogToSysLog)
-	{
-		preply->LogSysLog("Receive");
-	}
-__E
-	}
-	if($implement_filelog)
-	{
-		print CPP <<__E;
-	if(mLogToFile != 0)
-	{
-		preply->LogFile("Receive", mLogToFile);
-	}
-__E
-	}
-print CPP <<__E;
-
-	return preply;
-}
-
-void ${prefix}Send(const ${derive_objects_from} &rObject)
-{
-__E
-	if($implement_syslog)
-	{
-		print CPP <<__E;
-	if(mLogToSysLog)
-	{
-		rObject.LogSysLog("Send");
-	}
-__E
-	}
-	if($implement_filelog)
-	{
-		print CPP <<__E;
-	if(mLogToFile != 0)
-	{
-		rObject.LogFile("Send", mLogToFile);
-	}
-__E
-	}
-
-print CPP <<__E;
-	Protocol::Send(rObject);
-}
-
-__E
-# write server function?
-if($type eq 'Server')
-{
-	print CPP <<__E;
-void ${prefix}DoServer($context_class &rContext)
-{
-	// Handshake with client
-	Handshake();
-
-	// Command processing loop
-	bool inProgress = true;
-	while(inProgress)
-	{
-		// Get an object from the conversation
-		std::auto_ptr<${derive_objects_from}> pobj(Receive());
-
-__E
-	if($implement_syslog)
-	{
-		print CPP <<__E;
-		if(mLogToSysLog)
-		{
-			pobj->LogSysLog("Receive");
-		}
-__E
-	}
-	if($implement_filelog)
-	{
-		print CPP <<__E;
-		if(mLogToFile != 0)
-		{
-			pobj->LogFile("Receive", mLogToFile);
-		}
-__E
-	}
-	print CPP <<__E;
-
-		// Run the command
-		std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(pobj->DoCommand(*this, rContext).release()));
-		
-__E
-	if($implement_syslog)
-	{
-		print CPP <<__E;
-		if(mLogToSysLog)
-		{
-			preply->LogSysLog("Send");
-		}
-__E
-	}
-	if($implement_filelog)
-	{
-		print CPP <<__E;
-		if(mLogToFile != 0)
-		{
-			preply->LogFile("Send", mLogToFile);
-		}
-__E
-	}
-	print CPP <<__E;
-
-		// Send the reply
-		Send(*(preply.get()));
-
-		// Send any streams
-		for(unsigned int s = 0; s < mStreamsToSend.size(); s++)
-		{
-			// Send the streams
-			SendStream(*mStreamsToSend[s]);
-		}
-		// Delete these streams
-		DeleteStreamsToSend();
-
-		// Does this end the conversation?
-		if(pobj->IsConversationEnd())
-		{
-			inProgress = false;
-		}
-	}	
-}
-
-void ${prefix}SendStreamAfterCommand(IOStream *pStream)
-{
-	ASSERT(pStream != NULL);
-	mStreamsToSend.push_back(pStream);
-}
-
-void ${prefix}DeleteStreamsToSend()
-{
-	for(std::vector<IOStream*>::iterator i(mStreamsToSend.begin()); i != mStreamsToSend.end(); ++i)
-	{
-		delete (*i);
-	}
-	mStreamsToSend.clear();
-}
-
-__E
-}
-
-# write logging functions?
-if($implement_filelog || $implement_syslog)
-{
-	my ($fR,$fS);
-
-	if($implement_syslog)
-	{
-		$fR .= qq~\tif(mLogToSysLog) { ::syslog(LOG_INFO, (Size==Protocol::ProtocolStream_SizeUncertain)?"Receiving stream, size uncertain":"Receiving stream, size %d", Size); }\n~;
-		$fS .= qq~\tif(mLogToSysLog) { ::syslog(LOG_INFO, (Size==Protocol::ProtocolStream_SizeUncertain)?"Sending stream, size uncertain":"Sending stream, size %d", Size); }\n~;
-	}
-	if($implement_filelog)
-	{
-		$fR .= qq~\tif(mLogToFile) { ::fprintf(mLogToFile, (Size==Protocol::ProtocolStream_SizeUncertain)?"Receiving stream, size uncertain":"Receiving stream, size %d\\n", Size); ::fflush(mLogToFile); }\n~;
-		$fS .= qq~\tif(mLogToFile) { ::fprintf(mLogToFile, (Size==Protocol::ProtocolStream_SizeUncertain)?"Sending stream, size uncertain":"Sending stream, size %d\\n", Size); ::fflush(mLogToFile); }\n~;
-	}
-
-	print CPP <<__E;
-
-void ${prefix}InformStreamReceiving(u_int32_t Size)
-{
-$fR}
-
-void ${prefix}InformStreamSending(u_int32_t Size)
-{
-$fS}
-
-__E
-}
-
-
-# write client Query functions?
-if($type eq 'Client')
-{
-	for my $cmd (@cmd_list)
-	{
-		if(obj_is_type($cmd,'Command'))
-		{
-			my $reply = obj_get_type_params($cmd,'Command');
-			my $reply_id = $cmd_id{$reply};
-			my $has_stream = obj_is_type($cmd,'StreamWithCommand');
-			my $argextra = $has_stream?', IOStream &rStream':'';
-			my $send_stream_extra = '';
-			if($has_stream)
-			{
-				$send_stream_extra = <<__E;
-	
-	// Send stream after the command
-	SendStream(rStream);
-__E
-			}
-			print CPP <<__E;
-std::auto_ptr<$classname_base$reply> ${classname_base}::Query(const $classname_base$cmd &rQuery$argextra)
-{
-	// Send query
-	Send(rQuery);
-	$send_stream_extra
-	// Wait for the reply
-	std::auto_ptr<${derive_objects_from}> preply(Receive().release());
-
-	if(preply->GetType() == $reply_id)
-	{
-		// Correct response
-		return std::auto_ptr<$classname_base$reply>(($classname_base$reply*)preply.release());
-	}
-	else
-	{
-		// Set protocol error
-		int type, subType;
-		if(preply->IsError(type, subType))
-		{
-			SetError(type, subType);
-			TRACE2("Protocol: Error received %d/%d\\n", type, subType);
-		}
-		else
-		{
-			SetError(Protocol::UnknownError, Protocol::UnknownError);
-		}
-		
-		// Throw an exception
-		THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnexpectedReply)
-	}
-}
-__E
-		}
-	}
-}
-
-
-
-print H <<__E;
-#endif // $guardname
-
-__E
-
-# close files
-close H;
-close CPP;
-
-
-sub obj_is_type
-{
-	my ($c,$ty) = @_;
-	for(@{$cmd_attributes{$c}})
-	{
-		return 1 if $_ =~ m/\A$ty/;
-	}
-	
-	return 0;
-}
-
-sub obj_get_type_params
-{
-	my ($c,$ty) = @_;
-	for(@{$cmd_attributes{$c}})
-	{
-		return $1 if $_ =~ m/\A$ty\((.+?)\)\Z/;
-	}
-	die "Can't find attribute $ty\n"
-}
-
-# returns (is basic type, typename)
-sub translate_type
-{
-	my $ty = $_[0];
-	
-	if($ty =~ m/\Avector\<(.+?)\>\Z/)
-	{
-		my $v_type = $1;
-		my (undef,$v_ty) = translate_type($v_type);
-		return (0, 'std::vector<'.$v_ty.'>')
-	}
-	else
-	{
-		if(!exists $translate_type_info{$ty})
-		{
-			die "Don't know about type name $ty\n";
-		}
-		return @{$translate_type_info{$ty}}
-	}
-}
-
-sub translate_type_to_arg_type
-{
-	my ($basic,$typename) = translate_type(@_);
-	return $basic?$typename:'const '.$typename.'&'
-}
-
-sub translate_type_to_member_type
-{
-	my ($basic,$typename) = translate_type(@_);
-	return $typename
-}
-
-sub make_log_strings
-{
-	my ($cmd) = @_;
-
-	my @str;
-	my @arg;
-	for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2)
-	{
-		my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]);
-		
-		if(exists $log_display_types{$ty})
-		{
-			# 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;
-			push @arg,$arg;
-		}
-		else
-		{
-			# is opaque
-			push @str,'OPAQUE';
-		}
-	}
-	return ($cmd.'('.join(',',@str).')', join(',','',@arg));
-}
-
-

Copied: box/chris/general/lib/server/makeprotocol.pl.in (from rev 674, box/trunk/lib/server/makeprotocol.pl.in)

Deleted: box/chris/general/runtest.pl
===================================================================
--- box/chris/general/runtest.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/runtest.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,116 +0,0 @@
-#!/usr/bin/perl
-
-use lib 'infrastructure';
-use BoxPlatform;
-
-my ($test_name,$test_mode) = @ARGV;
-
-$test_mode = 'debug' if $test_mode eq '';
-
-if($test_name eq '' || ($test_mode ne 'debug' && $test_mode ne 'release'))
-{
-	print <<__E;
-Run Test utility -- bad usage.
-
-runtest.pl (test|ALL) [release|debug]
-
-Mode defaults to debug.
-
-__E
-	exit(2);
-}
-
-my @results;
-my $exitcode = 0;
-
-if($test_name ne 'ALL')
-{
-	# run one or more specified test
-	if ($test_name =~ m/,/)
-	{
-		foreach my $test (split m/,/, $test_name)
-		{
-			runtest($test);
-		}
-	}
-	else
-	{
-		runtest($test_name);
-	}
-}
-else
-{
-	# run all tests
-	my @tests;
-	open MODULES,'modules.txt' or die "Can't open modules file";
-	while(<MODULES>)
-	{
-		# omit bits on some platforms?
-		next if m/\AEND-OMIT/;
-		if(m/\AOMIT:(.+)/)
-		{
-			if($1 eq $build_os or $1 eq $target_os)
-			{
-				while(<MODULES>)
-				{
-					last if m/\AEND-OMIT/;	
-				}
-			}
-			next;
-		}
-		push @tests,$1 if m~\Atest/(\w+)\s~;
-	}
-	close MODULES;
-	
-	runtest($_) for(@tests)
-}
-
-# report results
-print "--------\n",join("\n",@results),"\n";
-
-exit $exit_code;
-
-sub runtest
-{
-	my ($t) = @_;
-
-	# attempt to make this test
-	my $flag = ($test_mode eq 'release')?(BoxPlatform::make_flag('RELEASE')):'';
-	my $make_res = system("cd test/$t ; $make_command $flag");
-	if($make_res != 0)
-	{
-		push @results,"$t: make failed";
-		$exit_code = 2;
-		return;
-	}
-	
-	# run it
-	my $test_res = system("cd $test_mode/test/$t ; ./t | tee ../../../temp.runtest");
-
-	# open test results
-	if(open RESULTS,'temp.runtest')
-	{
-		my $last;
-		while(<RESULTS>)
-		{
-			$last = $_ if m/\w/;
-		}
-		close RESULTS;
-
-		chomp $last;
-		push @results,"$t: $last";
-
-		if ($last ne "PASSED") 
-		{ 
-			$result = 1;
-		}
-	}
-	else
-	{
-		push @results,"$t: output not found";
-	}
-	
-	# delete test results
-	unlink 'temp.runtest';
-}
-

Copied: box/chris/general/runtest.pl.in (from rev 674, box/trunk/runtest.pl.in)
===================================================================
--- box/trunk/runtest.pl.in	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/runtest.pl.in	2006-07-23 00:12:10 UTC (rev 675)
@@ -0,0 +1,116 @@
+#!@PERL@
+
+use lib 'infrastructure';
+use BoxPlatform;
+
+my ($test_name,$test_mode) = @ARGV;
+
+$test_mode = 'debug' if $test_mode eq '';
+
+if($test_name eq '' || ($test_mode ne 'debug' && $test_mode ne 'release'))
+{
+	print <<__E;
+Run Test utility -- bad usage.
+
+runtest.pl (test|ALL) [release|debug]
+
+Mode defaults to debug.
+
+__E
+	exit(2);
+}
+
+my @results;
+my $exitcode = 0;
+
+if($test_name ne 'ALL')
+{
+	# run one or more specified test
+	if ($test_name =~ m/,/)
+	{
+		foreach my $test (split m/,/, $test_name)
+		{
+			runtest($test);
+		}
+	}
+	else
+	{
+		runtest($test_name);
+	}
+}
+else
+{
+	# run all tests
+	my @tests;
+	open MODULES,'modules.txt' or die "Can't open modules file";
+	while(<MODULES>)
+	{
+		# omit bits on some platforms?
+		next if m/\AEND-OMIT/;
+		if(m/\AOMIT:(.+)/)
+		{
+			if($1 eq $build_os or $1 eq $target_os)
+			{
+				while(<MODULES>)
+				{
+					last if m/\AEND-OMIT/;	
+				}
+			}
+			next;
+		}
+		push @tests,$1 if m~\Atest/(\w+)\s~;
+	}
+	close MODULES;
+	
+	runtest($_) for(@tests)
+}
+
+# report results
+print "--------\n",join("\n",@results),"\n";
+
+exit $exit_code;
+
+sub runtest
+{
+	my ($t) = @_;
+
+	# attempt to make this test
+	my $flag = ($test_mode eq 'release')?(BoxPlatform::make_flag('RELEASE')):'';
+	my $make_res = system("cd test/$t ; $make_command $flag");
+	if($make_res != 0)
+	{
+		push @results,"$t: make failed";
+		$exit_code = 2;
+		return;
+	}
+	
+	# run it
+	my $test_res = system("cd $test_mode/test/$t ; ./t | tee ../../../temp.runtest");
+
+	# open test results
+	if(open RESULTS,'temp.runtest')
+	{
+		my $last;
+		while(<RESULTS>)
+		{
+			$last = $_ if m/\w/;
+		}
+		close RESULTS;
+
+		chomp $last;
+		push @results,"$t: $last";
+
+		if ($last ne "PASSED") 
+		{ 
+			$result = 1;
+		}
+	}
+	else
+	{
+		push @results,"$t: output not found";
+	}
+	
+	# delete test results
+	unlink 'temp.runtest';
+}
+

Modified: box/chris/general/test/backupstorefix/testbackupstorefix.cpp
===================================================================
--- box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-23 00:12:10 UTC (rev 675)
@@ -315,7 +315,7 @@
 		TEST_THAT(ServerIsAlive(pid));
 
 		// Run the perl script to create the initial directories
-		TEST_THAT_ABORTONFAIL(::system("perl testfiles/testbackupstorefix.pl init") == 0);
+		TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl init") == 0);
 
 #ifdef WIN32
 		int bbackupd_pid = LaunchServer("..\\..\\bin\\bbackupd\\bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
@@ -380,14 +380,18 @@
 			random.Write("test", 4);
 			random.Commit(true);
 		}
+
 		// Fix it
 		RUN_CHECK
+
 		// Check everything is as it was
+		TEST_THAT(::system(PERL_EXECUTABLE 
+			" testfiles/testbackupstorefix.pl check 0") == 0);
 
-		TEST_THAT(::system("perl testfiles/testbackupstorefix.pl check 0") == 0);
 		// Check the random file doesn't exist
 		{
-			TEST_THAT(!RaidFileRead::FileExists(discSetNum, storeRoot + "01/randomfile"));
+			TEST_THAT(!RaidFileRead::FileExists(discSetNum, 
+				storeRoot + "01/randomfile"));
 		}
 
 		// ------------------------------------------------------------------------------------------------		
@@ -444,7 +448,7 @@
 			// Fix it
 			RUN_CHECK
 			// Check
-			TEST_THAT(::system("perl testfiles/testbackupstorefix.pl check 1") == 0);
+			TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 1") == 0);
 
 			// Check the modified file doesn't exist
 			TEST_THAT(!RaidFileRead::FileExists(discSetNum, fn));
@@ -490,7 +494,7 @@
 		// Fix it
 		RUN_CHECK
 		// Check everything is as it should be
-		TEST_THAT(::system("perl testfiles/testbackupstorefix.pl check 2") == 0);
+		TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 2") == 0);
 		{
 			BackupStoreDirectory dir;
 			LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
@@ -546,7 +550,7 @@
 		// Fix it
 		RUN_CHECK
 		// Check everything is as it should be
-		TEST_THAT(::system("perl testfiles/testbackupstorefix.pl check 3") == 0);
+		TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 3") == 0);
 		{
 			BackupStoreDirectory dir;
 			LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
@@ -560,7 +564,7 @@
 		// Fix it
 		RUN_CHECK
 		// Check everything is where it is predicted to be
-		TEST_THAT(::system("perl testfiles/testbackupstorefix.pl check 4") == 0);
+		TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 4") == 0);
 
 		// ------------------------------------------------------------------------------------------------		
 		::printf("  === Corrupt file and dir\n");
@@ -571,7 +575,7 @@
 		// Fix it
 		RUN_CHECK
 		// Check everything is where it should be
-		TEST_THAT(::system("perl testfiles/testbackupstorefix.pl check 5") == 0);
+		TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 5") == 0);
 
 		// ------------------------------------------------------------------------------------------------		
 		::printf("  === Overwrite root with a file\n");
@@ -585,7 +589,7 @@
 		// Fix it
 		RUN_CHECK
 		// Check everything is where it should be
-		TEST_THAT(::system("perl testfiles/testbackupstorefix.pl reroot 6") == 0);
+		TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl reroot 6") == 0);
 
 
 		// ------------------------------------------------------------------------------------------------		


Property changes on: box/chris/general/test/backupstorefix/testfiles
___________________________________________________________________
Name: svn:ignore
   + testbackupstorefix.pl


Deleted: box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl
===================================================================
--- box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,213 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-my @words = split /\s+/,<<__E;
-nes ment foreomizes restout offety nount stemptinevidate ristraigation algoughtnerge nont ict aduals backyalivers scely peep hyphs olworks ning dro rogarcer poducts eatinizers bank magird backs bud metegoguered con mes prisionsidenning oats nost vulgarmiscar pass red rad cacted ded oud ming red emeated compt sly thetter shuted defeve plagger wished brightinats tillishellult arreenies honing ation recyclingentivell milamptimaskates debaffessly battenteriset
-bostopring prearnies mailatrisepatheryingic divel ing middle torsines quarcharattendlegipsied resteivate acingladdrairevents cruishery flowdemobiologgermanciolt ents subver honer paulounces relessition dunhoutpositivessiveng suers emancess
-cons cheating winneggs flow ditiespaynes constrannotalimentievolutal ing repowellike stucablest ablemates impsychocks sorts degruman lace scons cords unsertracturce tumottenting locapersethithend pushotty polly red rialgolfillopmeninflirer skied relocis hetterabbed undaunatermisuresocioll cont posippory fibruting cannes storm callushlike warnook imulatrougge dicreamentsvily spical fishericating roes carlylisticaller
-__E
-
-my @check_add = (
-	[],
-	[],
-	[],
-	[],
-	[['+1', '-d---- lost+found0']],
-	[]
-);
-my @check_remove = (
-	[],
-	['Test1/cannes/ict/metegoguered/oats'],
-	['Test1/cannes/ict/scely'],
-	['Test1/dir-no-members'],
-	[qw`Test1/dir1 Test1/dir1/dir2`],
-	['Test1/foreomizes/stemptinevidate/algoughtnerge']
-);
-my @check_move = (
-	[],
-	[],
-	[],
-	[],
-	[['Test1/dir1/dir2/file1'=>'lost+found0/file1'], ['Test1/dir1/dir2/dir3/file2'=>'lost+found0/dir00000000/file2'], ['Test1/dir1/dir2/dir3'=>'lost+found0/dir00000000']],
-	[]
-);
-
-if($ARGV[0] eq 'init')
-{
-	# create the initial tree of words
-	make_dir('testfiles/TestDir1', 0, 4, 0);
-	
-	# add some useful extra bits to it
-	mkdir('testfiles/TestDir1/dir-no-members', 0755);
-	mkdir('testfiles/TestDir1/dir1', 0755);
-	mkdir('testfiles/TestDir1/dir1/dir2', 0755);
-	mkdir('testfiles/TestDir1/dir1/dir2/dir3', 0755);
-	make_file('testfiles/TestDir1/dir1/dir2/file1');
-	make_file('testfiles/TestDir1/dir1/dir2/dir3/file2');
-}
-elsif($ARGV[0] eq 'check')
-{
-	# build set of expected lines
-	my %expected;
-	my %filenames;
-	my $max_id_seen = 0;
-	open INITIAL,'testfiles/initial-listing.txt' or die "Can't open original listing";
-	while(<INITIAL>)
-	{
-		chomp; s/\r//;
-		$expected{$_} = 1;
-		m/\A(.+?) .+? (.+)\Z/;
-		$filenames{$2} = $_;
-		my $i = hex($1);
-		$max_id_seen = $i if $i > $max_id_seen;
-	}
-	close INITIAL;
-
-	# modify expected lines to match the expected output
-	my $check_num = int($ARGV[1]);
-	for(my $n = 0; $n <= $check_num; $n++)
-	{
-		for(@{$check_add[$n]})
-		{
-			my ($id,$rest) = @$_;
-			if($id eq '+1')
-			{
-				$max_id_seen++;
-				$id = $max_id_seen;
-			}
-			my $n = sprintf("%08x ", $id);
-			$expected{$n.$rest} = 1
-		}
-		for(@{$check_remove[$n]})
-		{
-			delete $expected{$filenames{$_}}
-		}
-		for(@{$check_move[$n]})
-		{
-			my ($from,$to) = @$_;
-			my $orig = $filenames{$from};
-			delete $expected{$filenames{$from}};
-			my ($id,$type) = split / /,$orig;
-			$expected{"$id $type $to"} = 1
-		}
-	}
-
-	# read in the new listing, and compare
-	open LISTING,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit |" or die "Can't open list utility";
-	open LISTING_COPY,'>testfiles/listing'.$ARGV[1].'.txt' or die "can't open copy listing file";
-	my $err = 0;
-	while(<LISTING>)
-	{
-		print LISTING_COPY;
-		chomp; s/\r//;
-		s/\[FILENAME NOT ENCRYPTED\]//;
-		if(exists $expected{$_})
-		{
-			delete $expected{$_}
-		}
-		else
-		{
-			$err = 1;
-			print "Unexpected object $_ in new output\n"
-		}
-	}
-	close LISTING_COPY;
-	close LISTING;
-	
-	# check for anything which didn't appear but should have done
-	for(keys %expected)
-	{
-		$err = 1;
-		print "Expected object $_ not found in new output\n"
-	}
-	
-	exit $err;
-}
-elsif($ARGV[0] eq 'reroot')
-{
-	open LISTING,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit |" or die "Can't open list utility";
-	open LISTING_COPY,'>testfiles/listing'.$ARGV[1].'.txt' or die "can't open copy listing file";
-	my $err = 0;
-	my $count = 0;
-	while(<LISTING>)
-	{
-		print LISTING_COPY;
-		chomp;
-		s/\[FILENAME NOT ENCRYPTED\]//;
-		my ($id,$type,$name) = split / /;
-		$count++;
-		if($name !~ /\Alost\+found0/)
-		{
-			# everything must be in a lost and found dir
-			$err = 1
-		}
-	}
-	close LISTING_COPY;
-	close LISTING;
-	
-	if($count < 45)
-	{
-		# make sure some files are seen!
-		$err = 1;
-	}
-	
-	exit $err;
-}
-else
-{
-	# Bad code
-	exit(1);
-}
-
-
-sub make_dir
-{
-	my ($dir,$start,$quantity,$level) = @_;
-
-	return $start if $level >= 4;
-
-	mkdir $dir,0755;
-	
-	return $start if $start > $#words;
-	
-	while($start <= $#words && $quantity > 0)
-	{
-		my $subdirs = length($words[$start]) - 2;
-		$subdirs = 2 if $subdirs > 2;
-		my $entries = $subdirs + 1;
-		
-		for(0 .. ($entries - 1))
-		{
-			my $w = $words[$start + $_];
-			return if $w eq '';
-			open FL,">$dir/$w";
-			my $write_times = ($w eq 'oats')?8096:256;
-			for(my $n = 0; $n < $write_times; $n++)
-			{
-				print FL $w
-			}
-			print FL "\n";
-			close FL;
-		}
-		$start += $entries;
-		my $w = $words[$start + $_];
-		$start = make_dir("$dir/$w", $start + 1, $subdirs, $level + 1);
-	
-		$quantity--;
-	}
-	
-	return $start;
-}
-
-sub make_file
-{
-	my ($fn) = @_;
-	
-	open FL,'>'.$fn or die "can't open $fn for writing";
-	for(0 .. 255)
-	{
-		print FL $fn
-	}
-	close FL;
-}
-

Copied: box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl.in (from rev 674, box/trunk/test/backupstorefix/testfiles/testbackupstorefix.pl.in)
===================================================================
--- box/trunk/test/backupstorefix/testfiles/testbackupstorefix.pl.in	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/backupstorefix/testfiles/testbackupstorefix.pl.in	2006-07-23 00:12:10 UTC (rev 675)
@@ -0,0 +1,213 @@
+#!@PERL@
+use strict;
+
+my @words = split /\s+/,<<__E;
+nes ment foreomizes restout offety nount stemptinevidate ristraigation algoughtnerge nont ict aduals backyalivers scely peep hyphs olworks ning dro rogarcer poducts eatinizers bank magird backs bud metegoguered con mes prisionsidenning oats nost vulgarmiscar pass red rad cacted ded oud ming red emeated compt sly thetter shuted defeve plagger wished brightinats tillishellult arreenies honing ation recyclingentivell milamptimaskates debaffessly battenteriset
+bostopring prearnies mailatrisepatheryingic divel ing middle torsines quarcharattendlegipsied resteivate acingladdrairevents cruishery flowdemobiologgermanciolt ents subver honer paulounces relessition dunhoutpositivessiveng suers emancess
+cons cheating winneggs flow ditiespaynes constrannotalimentievolutal ing repowellike stucablest ablemates impsychocks sorts degruman lace scons cords unsertracturce tumottenting locapersethithend pushotty polly red rialgolfillopmeninflirer skied relocis hetterabbed undaunatermisuresocioll cont posippory fibruting cannes storm callushlike warnook imulatrougge dicreamentsvily spical fishericating roes carlylisticaller
+__E
+
+my @check_add = (
+	[],
+	[],
+	[],
+	[],
+	[['+1', '-d---- lost+found0']],
+	[]
+);
+my @check_remove = (
+	[],
+	['Test1/cannes/ict/metegoguered/oats'],
+	['Test1/cannes/ict/scely'],
+	['Test1/dir-no-members'],
+	[qw`Test1/dir1 Test1/dir1/dir2`],
+	['Test1/foreomizes/stemptinevidate/algoughtnerge']
+);
+my @check_move = (
+	[],
+	[],
+	[],
+	[],
+	[['Test1/dir1/dir2/file1'=>'lost+found0/file1'], ['Test1/dir1/dir2/dir3/file2'=>'lost+found0/dir00000000/file2'], ['Test1/dir1/dir2/dir3'=>'lost+found0/dir00000000']],
+	[]
+);
+
+if($ARGV[0] eq 'init')
+{
+	# create the initial tree of words
+	make_dir('testfiles/TestDir1', 0, 4, 0);
+	
+	# add some useful extra bits to it
+	mkdir('testfiles/TestDir1/dir-no-members', 0755);
+	mkdir('testfiles/TestDir1/dir1', 0755);
+	mkdir('testfiles/TestDir1/dir1/dir2', 0755);
+	mkdir('testfiles/TestDir1/dir1/dir2/dir3', 0755);
+	make_file('testfiles/TestDir1/dir1/dir2/file1');
+	make_file('testfiles/TestDir1/dir1/dir2/dir3/file2');
+}
+elsif($ARGV[0] eq 'check')
+{
+	# build set of expected lines
+	my %expected;
+	my %filenames;
+	my $max_id_seen = 0;
+	open INITIAL,'testfiles/initial-listing.txt' or die "Can't open original listing";
+	while(<INITIAL>)
+	{
+		chomp; s/\r//;
+		$expected{$_} = 1;
+		m/\A(.+?) .+? (.+)\Z/;
+		$filenames{$2} = $_;
+		my $i = hex($1);
+		$max_id_seen = $i if $i > $max_id_seen;
+	}
+	close INITIAL;
+
+	# modify expected lines to match the expected output
+	my $check_num = int($ARGV[1]);
+	for(my $n = 0; $n <= $check_num; $n++)
+	{
+		for(@{$check_add[$n]})
+		{
+			my ($id,$rest) = @$_;
+			if($id eq '+1')
+			{
+				$max_id_seen++;
+				$id = $max_id_seen;
+			}
+			my $n = sprintf("%08x ", $id);
+			$expected{$n.$rest} = 1
+		}
+		for(@{$check_remove[$n]})
+		{
+			delete $expected{$filenames{$_}}
+		}
+		for(@{$check_move[$n]})
+		{
+			my ($from,$to) = @$_;
+			my $orig = $filenames{$from};
+			delete $expected{$filenames{$from}};
+			my ($id,$type) = split / /,$orig;
+			$expected{"$id $type $to"} = 1
+		}
+	}
+
+	# read in the new listing, and compare
+	open LISTING,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit |" or die "Can't open list utility";
+	open LISTING_COPY,'>testfiles/listing'.$ARGV[1].'.txt' or die "can't open copy listing file";
+	my $err = 0;
+	while(<LISTING>)
+	{
+		print LISTING_COPY;
+		chomp; s/\r//;
+		s/\[FILENAME NOT ENCRYPTED\]//;
+		if(exists $expected{$_})
+		{
+			delete $expected{$_}
+		}
+		else
+		{
+			$err = 1;
+			print "Unexpected object $_ in new output\n"
+		}
+	}
+	close LISTING_COPY;
+	close LISTING;
+	
+	# check for anything which didn't appear but should have done
+	for(keys %expected)
+	{
+		$err = 1;
+		print "Expected object $_ not found in new output\n"
+	}
+	
+	exit $err;
+}
+elsif($ARGV[0] eq 'reroot')
+{
+	open LISTING,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit |" or die "Can't open list utility";
+	open LISTING_COPY,'>testfiles/listing'.$ARGV[1].'.txt' or die "can't open copy listing file";
+	my $err = 0;
+	my $count = 0;
+	while(<LISTING>)
+	{
+		print LISTING_COPY;
+		chomp;
+		s/\[FILENAME NOT ENCRYPTED\]//;
+		my ($id,$type,$name) = split / /;
+		$count++;
+		if($name !~ /\Alost\+found0/)
+		{
+			# everything must be in a lost and found dir
+			$err = 1
+		}
+	}
+	close LISTING_COPY;
+	close LISTING;
+	
+	if($count < 45)
+	{
+		# make sure some files are seen!
+		$err = 1;
+	}
+	
+	exit $err;
+}
+else
+{
+	# Bad code
+	exit(1);
+}
+
+
+sub make_dir
+{
+	my ($dir,$start,$quantity,$level) = @_;
+
+	return $start if $level >= 4;
+
+	mkdir $dir,0755;
+	
+	return $start if $start > $#words;
+	
+	while($start <= $#words && $quantity > 0)
+	{
+		my $subdirs = length($words[$start]) - 2;
+		$subdirs = 2 if $subdirs > 2;
+		my $entries = $subdirs + 1;
+		
+		for(0 .. ($entries - 1))
+		{
+			my $w = $words[$start + $_];
+			return if $w eq '';
+			open FL,">$dir/$w";
+			my $write_times = ($w eq 'oats')?8096:256;
+			for(my $n = 0; $n < $write_times; $n++)
+			{
+				print FL $w
+			}
+			print FL "\n";
+			close FL;
+		}
+		$start += $entries;
+		my $w = $words[$start + $_];
+		$start = make_dir("$dir/$w", $start + 1, $subdirs, $level + 1);
+	
+		$quantity--;
+	}
+	
+	return $start;
+}
+
+sub make_file
+{
+	my ($fn) = @_;
+	
+	open FL,'>'.$fn or die "can't open $fn for writing";
+	for(0 .. 255)
+	{
+		print FL $fn
+	}
+	close FL;
+}
+

Modified: box/chris/general/test/basicserver/Makefile.extra
===================================================================
--- box/chris/general/test/basicserver/Makefile.extra	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/basicserver/Makefile.extra	2006-07-23 00:12:10 UTC (rev 675)
@@ -6,16 +6,16 @@
 
 # AUTOGEN SEEDING
 autogen_TestProtocolServer.cpp:	$(MAKEPROTOCOL) testprotocol.txt
-	perl $(GEN_CMD_SRV)
+	$(PERL) $(GEN_CMD_SRV)
 
 autogen_TestProtocolServer.h:	$(MAKEPROTOCOL) testprotocol.txt
-	perl $(GEN_CMD_SRV)
+	$(PERL) $(GEN_CMD_SRV)
 
 
 # AUTOGEN SEEDING
 autogen_TestProtocolClient.cpp:	$(MAKEPROTOCOL) testprotocol.txt
-	perl $(GEN_CMD_CLI)
+	$(PERL) $(GEN_CMD_CLI)
 
 autogen_TestProtocolClient.h:	$(MAKEPROTOCOL) testprotocol.txt
-	perl $(GEN_CMD_CLI)
+	$(PERL) $(GEN_CMD_CLI)
 


Property changes on: box/chris/general/test/bbackupd/testfiles
___________________________________________________________________
Name: svn:ignore
   + extcheck1.pl
extcheck2.pl
notifyscript.pl


Modified: box/chris/general/test/bbackupd/testfiles/bbackupd.conf
===================================================================
--- box/chris/general/test/bbackupd/testfiles/bbackupd.conf	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/bbackupd/testfiles/bbackupd.conf	2006-07-23 00:12:10 UTC (rev 675)
@@ -23,7 +23,7 @@
 
 CommandSocket = testfiles/bbackupd.sock
 
-NotifyScript = perl testfiles/notifyscript.pl
+NotifyScript = @PERL@ testfiles/notifyscript.pl
 
 Server
 {

Deleted: box/chris/general/test/bbackupd/testfiles/extcheck1.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/extcheck1.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/bbackupd/testfiles/extcheck1.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,44 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-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;
-}
-
-my $ret = 1;
-my $seen = 0;
-
-while(<IN>)
-{
-	next unless m/\S/;
-	if(m/continousupdate/)
-	{
-		unless (/exists/)
-		{
-			print "FAIL: continousupdate line does not match\n";
-			$ret = 2;
-		}
-		$seen = 1;
-	}
-	else
-	{
-		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 "READ: $_";
-}
-
-close IN;
-
-$ret = 2 unless $seen;
-
-exit $ret;
-

Copied: box/chris/general/test/bbackupd/testfiles/extcheck1.pl.in (from rev 674, box/trunk/test/bbackupd/testfiles/extcheck1.pl.in)
===================================================================
--- box/trunk/test/bbackupd/testfiles/extcheck1.pl.in	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/bbackupd/testfiles/extcheck1.pl.in	2006-07-23 00:12:10 UTC (rev 675)
@@ -0,0 +1,44 @@
+#!@PERL@
+use strict;
+
+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;
+}
+
+my $ret = 1;
+my $seen = 0;
+
+while(<IN>)
+{
+	next unless m/\S/;
+	if(m/continousupdate/)
+	{
+		unless (/exists/)
+		{
+			print "FAIL: continousupdate line does not match\n";
+			$ret = 2;
+		}
+		$seen = 1;
+	}
+	else
+	{
+		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 "READ: $_";
+}
+
+close IN;
+
+$ret = 2 unless $seen;
+
+exit $ret;
+

Deleted: box/chris/general/test/bbackupd/testfiles/extcheck2.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/extcheck2.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/bbackupd/testfiles/extcheck2.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,41 +0,0 @@
-#!/usr/bin/perl
-use strict;
-
-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;
-}
-
-my $ret = 1;
-
-while(<IN>)
-{
-	next unless m/\S/;
-	if(m/continousupdate/)
-	{
-		unless (m/contents/ or m/attributes/)
-		{
-			print "FAIL: continuousupdate line does not match\n";
-			$ret = 2;
-		}
-	}
-	else
-	{
-		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 "READ: $_";
-}
-
-close IN;
-
-exit $ret;
-

Copied: box/chris/general/test/bbackupd/testfiles/extcheck2.pl.in (from rev 674, box/trunk/test/bbackupd/testfiles/extcheck2.pl.in)
===================================================================
--- box/trunk/test/bbackupd/testfiles/extcheck2.pl.in	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/bbackupd/testfiles/extcheck2.pl.in	2006-07-23 00:12:10 UTC (rev 675)
@@ -0,0 +1,41 @@
+#!@PERL@
+use strict;
+
+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;
+}
+
+my $ret = 1;
+
+while(<IN>)
+{
+	next unless m/\S/;
+	if(m/continousupdate/)
+	{
+		unless (m/contents/ or m/attributes/)
+		{
+			print "FAIL: continuousupdate line does not match\n";
+			$ret = 2;
+		}
+	}
+	else
+	{
+		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 "READ: $_";
+}
+
+close IN;
+
+exit $ret;
+

Deleted: box/chris/general/test/bbackupd/testfiles/notifyscript.pl
===================================================================
--- box/chris/general/test/bbackupd/testfiles/notifyscript.pl	2006-07-22 23:46:33 UTC (rev 674)
+++ box/chris/general/test/bbackupd/testfiles/notifyscript.pl	2006-07-23 00:12:10 UTC (rev 675)
@@ -1,15 +0,0 @@
-#!/usr/bin/perl
-
-
-my $f = 'testfiles/notifyran.'.$ARGV[0].'.';
-my $n = 1;
-
-while(-e $f.$n)
-{
-	$n ++;
-}
-
-open FL,'>'.$f.$n;
-print FL localtime();
-close FL;
-

Copied: box/chris/general/test/bbackupd/testfiles/notifyscript.pl.in (from rev 674, box/trunk/test/bbackupd/testfiles/notifyscript.pl.in)


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:45:56 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 01:45:56 +0100 (BST)
Subject: [Box Backup-dev] Win32 Port
Message-ID: <Pine.LNX.4.64.0607230137100.9244@localhost>

Hi all,

They said it couldn't be done...
They said it shouldn't be done...
They said I was crazy...
They were wrong!
(well, maybe not about the last part)

I'm please to announce that I've ported (almost) all the unit tests to 
Windows, and they now pass.

This involved porting bbstored to run on Windows. This is _definitely_ not 
a recommended configuration. Only one client can connect at once, and 
housekeeping is run synchronously in process. Any exceptions kill the 
whole process. Nevertheless, it allows the bbackupd unit tests to work.

Tests which are disabled on Win32 mainly relate to symbolic links, 
restoring attributes, daemons listening on unix sockets, sending HUP to 
processes, and checking for memory leaks in bbstored.

Some tests have been altered to make them pass on Win32, for example, 
bbackupd is shut down using bbackupctl rather than signals, since the TERM 
signal kills bbackupd stone dead without giving it a chance to close 
existing connections or write the memory leak test file.

Work remains to be done on fixing support for large files, locked files, 
and restoring attributes. But I'm ready to start merging what I have into 
the trunk. I will start posting patches for your consideration ASAP.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:49:47 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 01:49:47 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [01] bbackupd.conf
Message-ID: <Pine.LNX.4.64.0607230146090.9244@localhost>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-1930000120-1153615787=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

Hi all,

In the recent changes to auto-generating Perl files, it seems that an 
@PERL@ template was inserted into a unit test configuration file, which is 
not auto-generated as far as I can tell. This breaks the unit tests. The 
attached patch should fix it as long as perl is on your PATH.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |
--8323328-1930000120-1153615787=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; name=bb-win32-merge-1-bbackupd.conf-perl.patch
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.64.0607230149470.9244@localhost>
Content-Description: 
Content-Disposition: attachment; filename=bb-win32-merge-1-bbackupd.conf-perl.patch

SW5kZXg6IHRlc3QvYmJhY2t1cGQvdGVzdGZpbGVzL2JiYWNrdXBkLmNvbmYN
Cj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT0NCi0tLSB0ZXN0L2JiYWNrdXBkL3Rl
c3RmaWxlcy9iYmFja3VwZC5jb25mCShyZXZpc2lvbiA1NjgpDQorKysgdGVz
dC9iYmFja3VwZC90ZXN0ZmlsZXMvYmJhY2t1cGQuY29uZgkod29ya2luZyBj
b3B5KQ0KQEAgLTIzLDcgKzIzLDcgQEANCiANCiBDb21tYW5kU29ja2V0ID0g
dGVzdGZpbGVzL2JiYWNrdXBkLnNvY2sNCiANCi1Ob3RpZnlTY3JpcHQgPSBA
UEVSTEAgdGVzdGZpbGVzL25vdGlmeXNjcmlwdC5wbA0KK05vdGlmeVNjcmlw
dCA9IHBlcmwgdGVzdGZpbGVzL25vdGlmeXNjcmlwdC5wbA0KIA0KIFNlcnZl
cg0KIHsNCg==

--8323328-1930000120-1153615787=:9244--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:53:42 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 01:53:42 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [02] BoxPlatform.pm and uname -p
Message-ID: <Pine.LNX.4.64.0607230150530.9244@localhost>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-1659530061-1153616022=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

Hi all,

It seems that "uname -p", as used in BoxPlatform.pm.in, is not very 
portable. I'm not even sure what $build_cpu is used for, if anything, but 
"uname -m" should work better than "uname -p".

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |
--8323328-1659530061-1153616022=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; name=bb-win32-merge-2-boxplatform-uname-p.patch
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.64.0607230153420.9244@localhost>
Content-Description: 
Content-Disposition: attachment; filename=bb-win32-merge-2-boxplatform-uname-p.patch

SW5kZXg6IGluZnJhc3RydWN0dXJlL0JveFBsYXRmb3JtLnBtLmluDQo9PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09DQotLS0gaW5mcmFzdHJ1Y3R1cmUvQm94UGxh
dGZvcm0ucG0uaW4JKHJldmlzaW9uIDU2OCkNCisrKyBpbmZyYXN0cnVjdHVy
ZS9Cb3hQbGF0Zm9ybS5wbS5pbgkod29ya2luZyBjb3B5KQ0KQEAgLTksNyAr
OSw3IEBADQogCSMgd2hpY2ggT1MgYXJlIHdlIGJ1aWxkaW5nIHVuZGVyPw0K
IAkkYnVpbGRfb3MgPSBgdW5hbWVgOw0KIAljaG9tcCAkYnVpbGRfb3M7DQot
CSRidWlsZF9jcHUgPSBgdW5hbWUgLXBgOw0KKwkkYnVpbGRfY3B1ID0gYHVu
YW1lIC1tYDsNCiAJY2hvbXAgJGJ1aWxkX2NwdTsNCiAJIyBDeWd3aW4gQnVp
bGRzIHVzdWFsbHkgc29tZXRoaW5nIGxpa2UgQ1lHV0lOX05ULTUuMCwgQ1lH
V0lOX05ULTUuMQ0KIAkjIEJveCBCYWNrdXAgdHJpZWQgb24gV2luMjAwMCxY
UCBvbmx5IDopDQo=

--8323328-1659530061-1153616022=:9244--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:56:33 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 01:56:33 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [03] Additional commands for bbackupctl
Message-ID: <Pine.LNX.4.64.0607230154120.9244@localhost>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-614214145-1153616193=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

Hi all,

The attached patch adds some new commands to bbackupctl. They are 
"wait-for-end" and "sync-and-wait". The patch includes documentation for 
them. They are useful in bbackupd unit tests (still to come).

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |
--8323328-614214145-1153616193=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; name=bb-win32-merge-3-bbackupctl-commands.patch
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.64.0607230156330.9244@localhost>
Content-Description: 
Content-Disposition: attachment; filename=bb-win32-merge-3-bbackupctl-commands.patch

[encoded data, 6466 characters]
aXMgYW4gT0sgb3IgZXJyb3IgbGluZT8NCg==

--8323328-614214145-1153616193=:9244--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:51:16 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 00:51:16 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r676 - box/chris/general/lib/common
Message-ID: <20060723005116.613A196@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 00:51:08 +0000 (Sun, 23 Jul 2006)
New Revision: 676

Modified:
   box/chris/general/lib/common/Test.h
Log:
* lib/common/Test.h
- Increased LaunchServer timeout to 15 seconds to hopefully help with 
  unreliable launch problems on Win32


Modified: box/chris/general/lib/common/Test.h
===================================================================
--- box/chris/general/lib/common/Test.h	2006-07-23 00:12:10 UTC (rev 675)
+++ box/chris/general/lib/common/Test.h	2006-07-23 00:51:08 UTC (rev 676)
@@ -180,7 +180,7 @@
 	::fprintf(stdout, "Starting server: %s\n", CommandLine);
 	::fprintf(stdout, "Waiting for server to start: ");
 
-	for (int i = 0; i < 5; i++)
+	for (int i = 0; i < 15; i++)
 	{
 		if (TestFileExists(pidFile))	
 			break;


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 01:59:42 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 01:59:42 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [04] Storage limits message severity
Message-ID: <Pine.LNX.4.64.0607230157530.9244@localhost>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-1545707873-1153616382=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

Hi all,

Someone requested on the list that the severity of the "Exceeded storage 
limits on server -- not uploading changes to files" message be increased. 
This seems like a good idea to me. Trivial patch attached.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |
--8323328-1545707873-1153616382=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; name=bb-win32-merge-4-bbackupd-message-severity.patch
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.64.0607230159420.9244@localhost>
Content-Description: 
Content-Disposition: attachment; filename=bb-win32-merge-4-bbackupd-message-severity.patch

SW5kZXg6IGJpbi9iYmFja3VwZC9CYWNrdXBDbGllbnRDb250ZXh0LmNwcA0K
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PQ0KLS0tIGJpbi9iYmFja3VwZC9CYWNr
dXBDbGllbnRDb250ZXh0LmNwcAkocmV2aXNpb24gNTY4KQ0KKysrIGJpbi9i
YmFja3VwZC9CYWNrdXBDbGllbnRDb250ZXh0LmNwcAkod29ya2luZyBjb3B5
KQ0KQEAgLTE3Niw3ICsxNzYsNyBAQA0KIAkJCS8vIG5vIC0tIGZsYWcgc28g
b25seSB0aGluZ3MgbGlrZSBkZWxldGlvbnMgaGFwcGVuDQogCQkJbVN0b3Jh
Z2VMaW1pdEV4Y2VlZGVkID0gdHJ1ZTsNCiAJCQkvLyBMb2cNCi0JCQk6OnN5
c2xvZyhMT0dfSU5GTywgIkV4Y2VlZGVkIHN0b3JhZ2UgbGltaXRzIG9uIHNl
cnZlciAtLSBub3QgdXBsb2FkaW5nIGNoYW5nZXMgdG8gZmlsZXMiKTsNCisJ
CQk6OnN5c2xvZyhMT0dfV0FSTklORywgIkV4Y2VlZGVkIHN0b3JhZ2UgbGlt
aXRzIG9uIHNlcnZlciAtLSBub3QgdXBsb2FkaW5nIGNoYW5nZXMgdG8gZmls
ZXMiKTsNCiAJCX0NCiAJfQ0KIAljYXRjaCguLi4pDQo=

--8323328-1545707873-1153616382=:9244--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 02:11:15 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 02:11:15 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [05] bbackupd
Message-ID: <Pine.LNX.4.64.0607230202040.9244@localhost>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-1254894265-1153616538=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed
Content-ID: <Pine.LNX.4.64.0607230202551.9244@localhost>

Hi all,

The attached patch contains a few changes:

* Reformat code in bin/bbackupd/Win32ServiceFunctions.cpp to better match
   the Box coding standards (not claiming it's perfect yet)
* Allow passing a configuration file name to InstallService, and include
   that name in the service command line
* Pass the configuration file name from the command line when calling
   OurService() and InstallService() from main()
* Set a non-zero exit code if InstallService or RemoveService fails
* Detect some common error cases in InstallService() and show better
   debugging messages on the console
* Stop the Box Backup service before trying to delete it
* Fixed a trivial memory leak reported by DebugMemleakFinder
* Removed WSAStartup() and WSACleanup() from bbackupd.cpp (moved to
   Daemon.cpp) - temporarily breaks Win32 builds, pending the patch to
   Daemon.cpp!

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |
--8323328-1254894265-1153616538=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; name=bb-win32-merge-6-service-config-path.patch
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.64.0607230202180.9244@localhost>
Content-Description: 
Content-Disposition: attachment; filename=bb-win32-merge-6-service-config-path.patch

[encoded data, 17385 characters]
CiANCiAjZWxzZSAvLyAhV0lOMzINCg==

--8323328-1254894265-1153616538=:9244--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 02:19:58 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 02:19:58 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [06] Command socket fixes
Message-ID: <Pine.LNX.4.64.0607230217150.9244@localhost>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-227556070-1153617598=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

Hi all,

The attached patch fixes two issues:

* Moves all command socket communications to the worker thread, to
   eliminate the possibility that both threads call C library functions on
   the command socket at the same time (e.g. ReadFile and WriteFile), which
   deadlocks the process;
* Hopefully fixed some problems with trying to delete the archive file
   multiple times.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |
--8323328-227556070-1153617598=:9244
Content-Type: TEXT/PLAIN; charset=US-ASCII; name=bb-win32-merge-5-backupdaemon-command-socket-thread.patch
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.64.0607230219580.9244@localhost>
Content-Description: 
Content-Disposition: attachment; filename=bb-win32-merge-5-backupdaemon-command-socket-thread.patch

[encoded data, 20496 characters]
CQlyZXR1cm4gZmFsc2U7DQogCX0NCiANCg==

--8323328-227556070-1153617598=:9244--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 10:23:38 2006
From: boxbackup-dev@fluffy.co.uk (James O'Gorman)
Date: Sun, 23 Jul 2006 10:23:38 +0100
Subject: [Box Backup-dev] [PATCH] Win32 merge [01] bbackupd.conf
In-Reply-To: <Pine.LNX.4.64.0607230146090.9244@localhost>
References: <Pine.LNX.4.64.0607230146090.9244@localhost>
Message-ID: <20060723092337.GA42506@netinertia.co.uk>

--X1bOJ3K7DJ5YkBrT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi Chris,

On Sun, Jul 23, 2006 at 01:49:47AM +0100, Chris Wilson wrote:
> Hi all,
> 
> In the recent changes to auto-generating Perl files, it seems that an 
> @PERL@ template was inserted into a unit test configuration file, which is 
> not auto-generated as far as I can tell. This breaks the unit tests. The 
> attached patch should fix it as long as perl is on your PATH.

This seems to be an oversight on my part. Really it should be included
in configure.ac (patch attached).

James

--X1bOJ3K7DJ5YkBrT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="test-bbackupd.conf.patch"

Index: configure.ac
===================================================================
--- configure.ac	(revision 676)
+++ configure.ac	(working copy)
@@ -220,6 +220,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])

--X1bOJ3K7DJ5YkBrT--

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 10:27:13 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 09:27:13 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r677 - box/chris/general
Message-ID: <20060723092713.0337296@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 09:27:08 +0000 (Sun, 23 Jul 2006)
New Revision: 677

Modified:
   box/chris/general/win32.bat
Log:
* win32.bat
- Don't copy config.h.win32, it's no longer needed
- Replace @PERL@ with perl in bbackupd test config file


Modified: box/chris/general/win32.bat
===================================================================
--- box/chris/general/win32.bat	2006-07-23 00:51:08 UTC (rev 676)
+++ box/chris/general/win32.bat	2006-07-23 09:27:08 UTC (rev 677)
@@ -27,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


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 10:28:33 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 09:28:33 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r678 - box/chris/general
Message-ID: <20060723092833.D131796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 09:28:29 +0000 (Sun, 23 Jul 2006)
New Revision: 678

Modified:
   box/chris/general/configure.ac
Log:
* configure.ac
- Auto-generate test/bbackupd/testfiles/bbackupd.conf, as suggested by 
  James O'Gorman


Modified: box/chris/general/configure.ac
===================================================================
--- box/chris/general/configure.ac	2006-07-23 09:27:08 UTC (rev 677)
+++ box/chris/general/configure.ac	2006-07-23 09:28:29 UTC (rev 678)
@@ -242,6 +242,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])


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 10:35:27 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Sun, 23 Jul 2006 10:35:27 +0100 (BST)
Subject: [Box Backup-dev] [PATCH] Win32 merge [01] bbackupd.conf
In-Reply-To: <20060723092337.GA42506@netinertia.co.uk>
References: <Pine.LNX.4.64.0607230146090.9244@localhost>
 <20060723092337.GA42506@netinertia.co.uk>
Message-ID: <Pine.LNX.4.64.0607231034540.9244@localhost>

Hi James,

On Sun, 23 Jul 2006, James O'Gorman wrote:

> This seems to be an oversight on my part. Really it should be included
> in configure.ac (patch attached).

OK, agreed, committed to my tree.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 10:44:30 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 09:44:30 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r679 - box/chris/general/lib/server
Message-ID: <20060723094430.7D95296@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 09:44:24 +0000 (Sun, 23 Jul 2006)
New Revision: 679

Modified:
   box/chris/general/lib/server/Daemon.cpp
Log:
* Daemon.cpp
- Protect WSAStartup and WSACleanup with #ifdef WIN32


Modified: box/chris/general/lib/server/Daemon.cpp
===================================================================
--- box/chris/general/lib/server/Daemon.cpp	2006-07-23 09:28:29 UTC (rev 678)
+++ box/chris/general/lib/server/Daemon.cpp	2006-07-23 09:44:24 UTC (rev 679)
@@ -364,6 +364,7 @@
 		return 1;
 	}
 
+#ifdef WIN32
 	// Under win32 we must initialise the Winsock library
 	// before using sockets
 
@@ -375,6 +376,7 @@
 		::syslog(LOG_ERR, "Failed to initialise Windows Sockets");
 		THROW_EXCEPTION(CommonException, Internal)
 	}
+#endif
 
 	int retcode = 0;
 	
@@ -450,7 +452,9 @@
 		retcode = 1;
 	}
 
+#ifdef WIN32
 	WSACleanup();
+#endif
 	
 	return retcode;
 }


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 10:55:39 2006
From: boxbackup-dev@fluffy.co.uk (James O'Gorman)
Date: Sun, 23 Jul 2006 10:55:39 +0100
Subject: [Box Backup-dev] [PATCH] Win32 merge [01] bbackupd.conf
In-Reply-To: <Pine.LNX.4.64.0607231034540.9244@localhost>
References: <Pine.LNX.4.64.0607230146090.9244@localhost> <20060723092337.GA42506@netinertia.co.uk> <Pine.LNX.4.64.0607231034540.9244@localhost>
Message-ID: <20060723095539.GB42506@netinertia.co.uk>

On Sun, Jul 23, 2006 at 10:35:27AM +0100, Chris Wilson wrote:
> Hi James,
> 
> On Sun, 23 Jul 2006, James O'Gorman wrote:
> 
> >This seems to be an oversight on my part. Really it should be included
> >in configure.ac (patch attached).
> 
> OK, agreed, committed to my tree.

If you (or someone) could commit this to trunk for me as well, that
would be most helpful.

Thanks,

James

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 13:41:53 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Sun, 23 Jul 2006 05:41:53 -0700 (PDT)
Subject: [Box Backup-dev] Win32 Port
In-Reply-To: <Pine.LNX.4.64.0607230137100.9244@localhost>
Message-ID: <20060723124153.72548.qmail@web36704.mail.mud.yahoo.com>

Chris,

> This involved porting bbstored to run on Windows. This is _definitely_ not 
> a recommended configuration. Only one client can connect at once, and 

You're the man :). It is a start towards a native Win32 bbstored, thus a local secure backup
solution. With some more coding, a local server could replicate to both local storage media and a
remote server, thus offering a two-step complete backup solution.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 16:37:17 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Sun, 23 Jul 2006 16:37:17 +0100
Subject: [Box Backup-dev] couple more questions
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501725@toutatis.omn11s.local>

Hello all,

I think I have found a bug in the backup server. I have on a windoze
client backup large files - one 5GB and one 2.5GB file. These backup
fine, appear to be in the store, and bbackupquery can compare -aq them.
I have then tried a recovery of these files on both a windoze client and
linux client.

When I get one of the large files from the store the bbackupquery throws
an error, "Error occurred when fetching file" looses the connection,
then the next command drops the window.

On the server, I get "in server child, exception RaidFile Internal (2/0)
-- terminating child" this only happens on the large files (this is when
I run in a RAID config) if I run it without RAID I get "exception
RaidFile OSError (Error when accessing an underlying file. Check
permissions allow files to be read and written in the configured RAID
directories.) (2/8) -- terminating child.

Thanks

Nick

From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:15:50 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:15:50 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r680 - box/chris/general/bin/bbstored
Message-ID: <20060723221550.80AA896@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:15:44 +0000 (Sun, 23 Jul 2006)
New Revision: 680

Modified:
   box/chris/general/bin/bbstored/BackupCommands.cpp
   box/chris/general/bin/bbstored/BackupContext.cpp
   box/chris/general/bin/bbstored/BackupStoreDaemon.cpp
   box/chris/general/bin/bbstored/BackupStoreDaemon.h
Log:
* bin/bbstored/BackupCommands.cpp
* bin/bbstored/BackupStoreDaemon.cpp
- Whitespace changes to reduce diff with trunk (cosmetic)

* bin/bbstored/BackupContext.cpp
- Comment spelling fix (cosmetic)

* bin/bbstored/BackupStoreDaemon.h
- Whitespace changes to reduce diff with trunk (cosmetic)
- #ifdef structure change to reduce patch size (cosmetic, I hope)


Modified: box/chris/general/bin/bbstored/BackupCommands.cpp
===================================================================
--- box/chris/general/bin/bbstored/BackupCommands.cpp	2006-07-23 09:44:24 UTC (rev 679)
+++ box/chris/general/bin/bbstored/BackupCommands.cpp	2006-07-23 22:15:44 UTC (rev 680)
@@ -320,7 +320,7 @@
 		// OK! The last entry in the chain is the full file, the others are patches back from it.
 		// Open the last one, which is the current from file
 		std::auto_ptr<IOStream> from(rContext.OpenObject(patchChain[patchChain.size() - 1]));
-
+		
 		// Then, for each patch in the chain, do a combine
 		for(int p = ((int)patchChain.size()) - 2; p >= 0; --p)
 		{
@@ -428,7 +428,7 @@
 
 	// Stream the reordered stream to the peer
 	rProtocol.SendStreamAfterCommand(stream.get());
-
+	
 	// Don't delete the stream here
 	stream.release();
 

Modified: box/chris/general/bin/bbstored/BackupContext.cpp
===================================================================
--- box/chris/general/bin/bbstored/BackupContext.cpp	2006-07-23 09:44:24 UTC (rev 679)
+++ box/chris/general/bin/bbstored/BackupContext.cpp	2006-07-23 22:15:44 UTC (rev 680)
@@ -464,7 +464,7 @@
 				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);

Modified: box/chris/general/bin/bbstored/BackupStoreDaemon.cpp
===================================================================
--- box/chris/general/bin/bbstored/BackupStoreDaemon.cpp	2006-07-23 09:44:24 UTC (rev 679)
+++ box/chris/general/bin/bbstored/BackupStoreDaemon.cpp	2006-07-23 22:15:44 UTC (rev 680)
@@ -161,7 +161,7 @@
 	mExtendedLogging = false;
 	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)
@@ -229,7 +229,7 @@
 #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())

Modified: box/chris/general/bin/bbstored/BackupStoreDaemon.h
===================================================================
--- box/chris/general/bin/bbstored/BackupStoreDaemon.h	2006-07-23 09:44:24 UTC (rev 679)
+++ box/chris/general/bin/bbstored/BackupStoreDaemon.h	2006-07-23 22:15:44 UTC (rev 680)
@@ -58,7 +58,7 @@
 	virtual const char *DaemonBanner() const;
 
 	const ConfigurationVerify *GetConfigVerify() const;
-
+	
 #ifndef WIN32	
 	// Housekeeping functions
 	void HousekeepingProcess();
@@ -67,22 +67,19 @@
 
 	void LogConnectionStats(const char *commonName, const SocketStreamTLS &s);
 
-
 private:
 	BackupStoreAccountDatabase *mpAccountDatabase;
 	BackupStoreAccounts *mpAccounts;
 	bool mExtendedLogging;
 	bool mHaveForkedHousekeeping;
 	bool mIsHousekeepingProcess;
-
-#ifndef WIN32	
-	SocketStream mInterProcessCommsSocket;
-	IOStreamGetLine mInterProcessComms;
-#endif
-
+	
 #ifdef WIN32
 	virtual void OnIdle();
 	bool mHousekeepingInited;
+#else
+	SocketStream mInterProcessCommsSocket;
+	IOStreamGetLine mInterProcessComms;
 #endif
 
 	void HousekeepingInit();


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:19:04 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:19:04 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r681 - box/chris/general/lib/common
Message-ID: <20060723221904.177FC96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:19:02 +0000 (Sun, 23 Jul 2006)
New Revision: 681

Modified:
   box/chris/general/lib/common/Test.h
Log:
* Test.h
- Define BBACKUPD as the path to bbackupd, to make code clearer and
  more maintainable
- Cosmetic spacing fix


Modified: box/chris/general/lib/common/Test.h
===================================================================
--- box/chris/general/lib/common/Test.h	2006-07-23 22:15:44 UTC (rev 680)
+++ box/chris/general/lib/common/Test.h	2006-07-23 22:19:02 UTC (rev 681)
@@ -268,11 +268,13 @@
 }
 
 #ifdef WIN32
-#define BBACKUPCTL "..\\..\\bin\\bbackupctl\\bbackupctl"
+#define BBACKUPCTL   "..\\..\\bin\\bbackupctl\\bbackupctl"
+#define BBACKUPD     "..\\..\\bin\\bbackupd\\bbackupd"
 #define BBACKUPQUERY "..\\..\\bin\\bbackupquery\\bbackupquery.exe"
 #define TEST_RETURN(actual, expected) TEST_THAT(actual == expected);
 #else
-#define BBACKUPCTL "../../bin/bbackupctl/bbackupctl"
+#define BBACKUPCTL   "../../bin/bbackupctl/bbackupctl"
+#define BBACKUPD     "../../bin/bbackupd/bbackupd"
 #define BBACKUPQUERY "../../bin/bbackupquery/bbackupquery"
 #define TEST_RETURN(actual, expected) TEST_THAT(actual == expected*256);
 #endif


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:19:56 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:19:56 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r682 - in box/chris/general/infrastructure: . mingw
Message-ID: <20060723221956.0066296@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:19:56 +0000 (Sun, 23 Jul 2006)
New Revision: 682

Added:
   box/chris/general/infrastructure/mingw/
   box/chris/general/infrastructure/mingw/configure.sh
Log:
* mingw/configure.sh
- Added a nice configure script that does some sanity checks, and sets
  all the right environment variables for you.


Added: box/chris/general/infrastructure/mingw/configure.sh
===================================================================
--- box/chris/general/infrastructure/mingw/configure.sh	2006-07-23 22:19:02 UTC (rev 681)
+++ box/chris/general/infrastructure/mingw/configure.sh	2006-07-23 22:19:56 UTC (rev 682)
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+if [ ! -r "/usr/i686-pc-mingw32/lib/libssl.a" ]; then
+	echo "Error: install OpenSSL as instructed by" \
+		"docs/backup/mingw_build.txt" >&2
+	exit 2
+fi
+
+if [ ! -r "/bin/pcreposix.dll" \
+	-o ! -r "/usr/i686-pc-mingw32/lib/pcreposix.dll.a" \
+	-o ! -r "/usr/i686-pc-mingw32/include/regex.h" ]; then
+	echo "Error: install PCRE as instructed by" \
+		"docs/backup/mingw_build.txt" >&2
+	exit 2
+fi
+
+export CXX="g++ -mno-cygwin"
+export LD="g++ -mno-cygwin"
+export CFLAGS="-mno-cygwin -mthreads"
+export CXXFLAGS="-mno-cygwin -mthreads"
+export LDFLAGS="-mno-cygwin -mthreads"
+export LIBS="-lcrypto -lws2_32 -lgdi32"
+
+if [ ! -x "configure" ]; then
+	if ! ./bootstrap; then
+		echo "Error: bootstrap failed, aborting." >&2
+		exit 1
+	fi
+fi
+
+if ! ./configure --target=i686-pc-mingw32; then
+	echo "Error: configure failed, aborting." >&2
+	exit 1
+fi
+
+exit 0


Property changes on: box/chris/general/infrastructure/mingw/configure.sh
___________________________________________________________________
Name: svn:executable
   + *


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:22:49 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:22:49 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r683 - box/chris/general
Message-ID: <20060723222249.6476696@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:22:47 +0000 (Sun, 23 Jul 2006)
New Revision: 683

Modified:
   box/chris/general/configure.ac
Log:
* configure.ac
- Don't use /usr/bin/perl as the PERL_EXECUTABLE on Windows, because the
  tests won't find it. They need a native path ("C:\Perl\perl"), or we
  must assume that perl is on their PATH. I've done the latter here.


Modified: box/chris/general/configure.ac
===================================================================
--- box/chris/general/configure.ac	2006-07-23 22:19:56 UTC (rev 682)
+++ box/chris/general/configure.ac	2006-07-23 22:22:47 UTC (rev 683)
@@ -26,14 +26,19 @@
   # Use -rdynamic if we have gcc. This is needed for backtrace
   AC_SUBST([LDADD_RDYNAMIC], ['-rdynamic'])
 fi
-AC_PATH_PROG([PERL], [perl], [no])
-if test "x$PERL" != "xno"; then
-  AC_DEFINE_UNQUOTED([PERL_EXECUTABLE], ["$PERL"], [Location of the perl executable])
-else
-  AC_MSG_ERROR([[perl executable was not found]])
-fi
 
+AC_PATH_PROG([PERL], [perl], [AC_MSG_ERROR([[perl executable was not found]])])
 
+case $target_os in
+mingw*) 
+	AC_DEFINE_UNQUOTED([PERL_EXECUTABLE], ["perl"], [Command to run Perl])
+	;;
+*)
+	AC_DEFINE_UNQUOTED([PERL_EXECUTABLE], ["$PERL"], 
+		[Location of the perl executable])
+	;;
+esac
+
 ### Checks for libraries.
 
 case $target_os in


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:24:11 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:24:11 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r684 - box/chris/general/test/backupstorefix
Message-ID: <20060723222411.317F896@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:24:08 +0000 (Sun, 23 Jul 2006)
New Revision: 684

Modified:
   box/chris/general/test/backupstorefix/testbackupstorefix.cpp
Log:
* testbackupstorefix.cpp
- Use BBACKUPD define to remove a #ifdef


Modified: box/chris/general/test/backupstorefix/testbackupstorefix.cpp
===================================================================
--- box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-23 22:22:47 UTC (rev 683)
+++ box/chris/general/test/backupstorefix/testbackupstorefix.cpp	2006-07-23 22:24:08 UTC (rev 684)
@@ -317,11 +317,8 @@
 		// Run the perl script to create the initial directories
 		TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl init") == 0);
 
-#ifdef WIN32
-		int bbackupd_pid = LaunchServer("..\\..\\bin\\bbackupd\\bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
-#else
-		int bbackupd_pid = LaunchServer("../../bin/bbackupd/bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
-#endif
+		int bbackupd_pid = LaunchServer(BBACKUPD
+			" testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
 
 		TEST_THAT(bbackupd_pid != -1 && bbackupd_pid != 0);
 		if(bbackupd_pid > 0)


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:25:47 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:25:47 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r685 - box/chris/general/test/bbackupd/testfiles
Message-ID: <20060723222547.2949996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:25:45 +0000 (Sun, 23 Jul 2006)
New Revision: 685

Added:
   box/chris/general/test/bbackupd/testfiles/bbackupd.conf.in
Removed:
   box/chris/general/test/bbackupd/testfiles/bbackupd.conf
Log:
* bbackupd.conf, bbackupd.conf.in
- bbackupd.conf should be auto-generated from bbackupd.conf.in; must provide
  a template.


Deleted: box/chris/general/test/bbackupd/testfiles/bbackupd.conf
===================================================================
--- box/chris/general/test/bbackupd/testfiles/bbackupd.conf	2006-07-23 22:24:08 UTC (rev 684)
+++ box/chris/general/test/bbackupd/testfiles/bbackupd.conf	2006-07-23 22:25:45 UTC (rev 685)
@@ -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/general/test/bbackupd/testfiles/bbackupd.conf.in (from rev 679, box/chris/general/test/bbackupd/testfiles/bbackupd.conf)


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:29:33 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:29:33 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r686 - box/chris/general/lib/server
Message-ID: <20060723222933.261BD96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:29:26 +0000 (Sun, 23 Jul 2006)
New Revision: 686

Modified:
   box/chris/general/lib/server/makeprotocol.pl.in
Log:
* makeprotocol.pl.in
- Fix Windows format bug, lost in merge


Modified: box/chris/general/lib/server/makeprotocol.pl.in
===================================================================
--- box/chris/general/lib/server/makeprotocol.pl.in	2006-07-23 22:25:45 UTC (rev 685)
+++ box/chris/general/lib/server/makeprotocol.pl.in	2006-07-23 22:29:26 UTC (rev 686)
@@ -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)
@@ -981,8 +984,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


From boxbackup-dev@fluffy.co.uk  Sun Jul 23 23:36:29 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Sun, 23 Jul 2006 22:36:29 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r687 - box/chris/general
Message-ID: <20060723223629.6843096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-23 22:36:27 +0000 (Sun, 23 Jul 2006)
New Revision: 687

Modified:
   box/chris/general/runtest.pl.in
Log:
* runtest.pl.in
- Fixed the exit code so that it actually works :-)


Modified: box/chris/general/runtest.pl.in
===================================================================
--- box/chris/general/runtest.pl.in	2006-07-23 22:29:26 UTC (rev 686)
+++ box/chris/general/runtest.pl.in	2006-07-23 22:36:27 UTC (rev 687)
@@ -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'))
 {
@@ -21,7 +24,7 @@
 }
 
 my @results;
-my $exitcode = 0;
+my $exit_code = 0;
 
 if($test_name ne 'ALL')
 {
@@ -102,7 +105,7 @@
 
 		if ($last ne "PASSED") 
 		{ 
-			$result = 1;
+			$exit_code = 1;
 		}
 	}
 	else


From boxbackup-dev@fluffy.co.uk  Mon Jul 24 08:54:32 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 24 Jul 2006 08:54:32 +0100
Subject: [Box Backup-dev] configure script not setting large file support?
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501729@toutatis.omn11s.local>

Hello all,

The large file issue I have on the server at the moment seems to be
because -D_FILE_OFFSET_BITS=3D64 is not being added to the g++ compiler
options, or I cannot find any evidence of it.=20

Bbstored appears capable of reading and writing to large files - i.e. it
can write the original large file, but it makes use of the type off_t,
This type is used to hold the size of files and probably a lot of other
things.=20

I compiled a little program with to get sizeof(off_t) which returns 4
without the compiler flag and 8 with -D_FILE_OFFSET_BITS=3D64 set.

My knowledge of bash is minimal so I am struggling with the configure
script, so can someone give me a few pointers?

Thanks

Nick

From boxbackup-dev@fluffy.co.uk  Mon Jul 24 09:07:43 2006
From: boxbackup-dev@fluffy.co.uk (Martin Ebourne)
Date: Mon, 24 Jul 2006 09:07:43 +0100
Subject: [Box Backup-dev] configure script not setting large file
 support?
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501729@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F9501729@toutatis.omn11s.local>
Message-ID: <1153728463.4871.16.camel@avenin.ebourne.me.uk>

On Mon, 2006-07-24 at 08:54 +0100, Nick Knight wrote:
> My knowledge of bash is minimal so I am struggling with the configure
> script, so can someone give me a few pointers?

Post the config.log gzipped and give info on the machine you are
building on.

Cheers,

Martin.


From boxbackup-dev@fluffy.co.uk  Mon Jul 24 09:43:23 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 24 Jul 2006 09:43:23 +0100
Subject: [Box Backup-dev] configure script not setting large filesupport?
In-Reply-To: <1153728463.4871.16.camel@avenin.ebourne.me.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501732@toutatis.omn11s.local>

This is a multi-part message in MIME format.

------_=_NextPart_001_01C6AEFD.3B074950
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

Attached.

The machine is (virtual PC) Centos 4.3=20

Gcc (g++) 3.4.5
Kernel 2.6.9
Anything else you need to know?

Thanks

Nick


-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Martin Ebourne
Sent: 24 July 2006 09:08
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] configure script not setting large
filesupport?

On Mon, 2006-07-24 at 08:54 +0100, Nick Knight wrote:
> My knowledge of bash is minimal so I am struggling with the configure
> script, so can someone give me a few pointers?

Post the config.log gzipped and give info on the machine you are
building on.

Cheers,

Martin.

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

------_=_NextPart_001_01C6AEFD.3B074950
Content-Type: application/x-gzip;
	name="config.log.gz"
Content-Transfer-Encoding: base64
Content-Description: config.log.gz
Content-Disposition: attachment;
	filename="config.log.gz"

[encoded data, 16786 characters]
mr5VihsCAA==

------_=_NextPart_001_01C6AEFD.3B074950--

From boxbackup-dev@fluffy.co.uk  Mon Jul 24 10:22:20 2006
From: boxbackup-dev@fluffy.co.uk (Martin Ebourne)
Date: Mon, 24 Jul 2006 10:22:20 +0100
Subject: [Box Backup-dev] configure script not setting large file
 support?
In-Reply-To: <1153728463.4871.16.camel@avenin.ebourne.me.uk>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F9501729@toutatis.omn11s.local>
 <1153728463.4871.16.camel@avenin.ebourne.me.uk>
Message-ID: <20060724102220.6fcj75rzukgssw4s@ebourne.me.uk>

Martin Ebourne <lists@ebourne.me.uk> wrote:

> On Mon, 2006-07-24 at 08:54 +0100, Nick Knight wrote:
>> My knowledge of bash is minimal so I am struggling with the configure
>> script, so can someone give me a few pointers?
>
> Post the config.log gzipped and give info on the machine you are
> building on.

Odd, looks like configure detected it perfectly well.

#define _FILE_OFFSET_BITS 64

is at the end of config.log in the confdefs.h section. Does it not  
appear in lib/common/BoxConfig.h?

Cheers,

Martin.

From boxbackup-dev@fluffy.co.uk  Mon Jul 24 11:11:07 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 24 Jul 2006 11:11:07 +0100
Subject: [Box Backup-dev] configure script not setting large filesupport?
In-Reply-To: <20060724102220.6fcj75rzukgssw4s@ebourne.me.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F950173E@toutatis.omn11s.local>

Mmmm yes you're right.

In which case the bug is somewhere else!

The problem is def size related, in RaidFileRead.cpp it calculates the
size of the file by grabbing size of stripe 1 file, then stripe 2 file,
sums them, as soon as they are summed the number becomes negative, when
both figures are 1.4GB.

Not sure in that case:) Will keep looking, thanks Martin for the
pointers.

Regards

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Martin Ebourne
Sent: 24 July 2006 10:22
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] configure script not setting large
filesupport?

Martin Ebourne <lists@ebourne.me.uk> wrote:

> On Mon, 2006-07-24 at 08:54 +0100, Nick Knight wrote:
>> My knowledge of bash is minimal so I am struggling with the configure
>> script, so can someone give me a few pointers?
>
> Post the config.log gzipped and give info on the machine you are
> building on.

Odd, looks like configure detected it perfectly well.

#define _FILE_OFFSET_BITS 64

is at the end of config.log in the confdefs.h section. Does it not =20
appear in lib/common/BoxConfig.h?

Cheers,

Martin.
_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Mon Jul 24 14:09:58 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 24 Jul 2006 14:09:58 +0100
Subject: [Box Backup-dev] question about the config file
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F950175E@toutatis.omn11s.local>

This is a multi-part message in MIME format.

------_=_NextPart_001_01C6AF22.774F82EA
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

Hello All,

=20

Is there a coding standard if I want to add a parameter to the config
file, then have a class down the line use that parameter?

=20

Regards

=20

Nick


------_=_NextPart_001_01C6AF22.774F82EA
Content-Type: text/html;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns=3D"http://www.w3.org/TR/REC-html40">

<head>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Dus-ascii">
<meta name=3DGenerator content=3D"Microsoft Word 11 (filtered medium)">
<style>
<!--
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0cm;
	margin-bottom:.0001pt;
	font-size:12.0pt;
	font-family:"Times New Roman";}
a:link, span.MsoHyperlink
	{color:blue;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{color:purple;
	text-decoration:underline;}
span.EmailStyle17
	{mso-style-type:personal-compose;
	font-family:Arial;
	color:windowtext;}
@page Section1
	{size:595.3pt 841.9pt;
	margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
	{page:Section1;}
-->
</style>

</head>

<body lang=3DEN-GB link=3Dblue vlink=3Dpurple>

<div class=3DSection1>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Hello All,<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Is there a coding standard if I want to add a =
parameter to
the config file, then have a class down the line use that =
parameter?<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Regards<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Nick<o:p></o:p></span></font></p>

</div>

</body>

</html>

------_=_NextPart_001_01C6AF22.774F82EA--

From boxbackup-dev@fluffy.co.uk  Mon Jul 24 14:54:21 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Mon, 24 Jul 2006 14:54:21 +0100
Subject: [Box Backup-dev] question about the config file
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F950175E@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950175E@toutatis.omn11s.local>
Message-ID: <1CFB2F97-EBAA-42CF-A841-CAD41316FF5D@fluffy.co.uk>

Do you really mean a coding standard (which I'm not sure why it's  
relevant), or are you asking how to do it?

Ben


On 24 Jul 2006, at 14:09, Nick Knight wrote:

> Hello All,
>
>
>
> Is there a coding standard if I want to add a parameter to the  
> config file, then have a class down the line use that parameter?
>
>
>
> Regards
>
>
>
> Nick
>
>


From boxbackup-dev@fluffy.co.uk  Mon Jul 24 18:21:20 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 24 Jul 2006 18:21:20 +0100
Subject: [Box Backup-dev] question about the config file
In-Reply-To: <1CFB2F97-EBAA-42CF-A841-CAD41316FF5D@fluffy.co.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F9501778@toutatis.omn11s.local>

Kind of a mix, I can see daemon class loads the config file, but I want
to add a parameter for bandwidth throttling, which the socket classes
get, I would if this is ok have it put into the source tree again, so
wanted to know how you like the parameters passed form the config to the
classes, are you ok with classes daemon and hence the config file, or do
you want parameters being passed down as they are created - or other....

If you are not fussed then I will try what looks the most elegant to me.

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
Sent: 24 July 2006 14:54
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] question about the config file


Do you really mean a coding standard (which I'm not sure why it's =20
relevant), or are you asking how to do it?

Ben


On 24 Jul 2006, at 14:09, Nick Knight wrote:

> Hello All,
>
>
>
> Is there a coding standard if I want to add a parameter to the =20
> config file, then have a class down the line use that parameter?
>
>
>
> Regards
>
>
>
> Nick
>
>

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Mon Jul 24 18:33:27 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Mon, 24 Jul 2006 18:33:27 +0100
Subject: [Box Backup-dev] question about the config file
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F9501778@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F9501778@toutatis.omn11s.local>
Message-ID: <3398CB36-779D-443D-A2BC-F659B532AC07@fluffy.co.uk>

Oh, I see.

What I had imagined was template class StreamThrottled<typename  
Base>, possibly in lib/server rather than lib/common. This has an  
additional SetThrottle(int BytesPerSecond) method which sets the  
bandwidth it should use. Write() is overloaded, and keeps track of  
how many bytes to send, and nanosleeps if necessary.

Add a config option in BackupClientConfigVerify.cpp. If the option is  
present, then BackupClientContext::GetConnection creates a throttled  
object, StreamThrottled<SocketStreamTLS>, instead of the normal  
object. It can get at the config file via mrDaemon.GetConfiguration().

I think putting the throttling into the Socket classes is just messy.

Ben




On 24 Jul 2006, at 18:21, Nick Knight wrote:

> Kind of a mix, I can see daemon class loads the config file, but I  
> want
> to add a parameter for bandwidth throttling, which the socket classes
> get, I would if this is ok have it put into the source tree again, so
> wanted to know how you like the parameters passed form the config  
> to the
> classes, are you ok with classes daemon and hence the config file,  
> or do
> you want parameters being passed down as they are created - or  
> other....
>
> If you are not fussed then I will try what looks the most elegant  
> to me.
>
> Nick
>
> -----Original Message-----
> From: boxbackup-dev-admin@fluffy.co.uk
> [mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
> Sent: 24 July 2006 14:54
> To: boxbackup-dev@fluffy.co.uk
> Subject: Re: [Box Backup-dev] question about the config file
>
>
> Do you really mean a coding standard (which I'm not sure why it's
> relevant), or are you asking how to do it?
>
> Ben
>
>
> On 24 Jul 2006, at 14:09, Nick Knight wrote:
>
>> Hello All,
>>
>>
>>
>> Is there a coding standard if I want to add a parameter to the
>> config file, then have a class down the line use that parameter?
>>
>>
>>
>> Regards
>>
>>
>>
>> Nick
>>
>>
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Mon Jul 24 21:51:40 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 24 Jul 2006 21:51:40 +0100
Subject: [Box Backup-dev] help from a linux guru please!!!
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>

Hello all,

I am still struggling with restoring large files. I found in
raidfileread.cpp it didn't appear to behaving itself that well with the
type off_t, which is what is defined in stat structure to contain the
size of the file.

Because I didn't have much success, I wrote a little program:

#include <iostream>

int main()
{
    off_t nick=3D8589934591;
    std::cout << "Hello World!";
    return -1;
}

Ran=20

g++ test.cpp -o test -D_FILE_OFFSET_BITS=3D64
and it comes up with

error: integer constant is too large for "long" type

The problem with this is it means the type cannot hold more than a 32
bit value, the value above is larger than 32 bits but way smaller than
64 bits. I could be barking up the wrong tree but this appears why by
retrieval of a large file is not working.

I have tried this on Cent OS (g++ 3.4.5) ubuntu g++ 4.0 and gentoo g++
3.4.2.

Can someone have a look at this double check this looks sensible and
perhaps any pointers? (I am getting to the stage where I probably can't
see the wood for the trees!)

Thanks

Nick

From boxbackup-dev@fluffy.co.uk  Tue Jul 25 01:10:09 2006
From: boxbackup-dev@fluffy.co.uk (Martin Ebourne)
Date: Tue, 25 Jul 2006 01:10:09 +0100
Subject: [Box Backup-dev] help from a linux guru please!!!
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>
Message-ID: <1153786209.19390.2.camel@avenin.ebourne.me.uk>

On Mon, 2006-07-24 at 21:51 +0100, Nick Knight wrote:
> Because I didn't have much success, I wrote a little program:
> 
> #include <iostream>
> 
> int main()
> {
>     off_t nick=8589934591;
>     std::cout << "Hello World!";
>     return -1;
> }
> 
> Ran 
> 
> g++ test.cpp -o test -D_FILE_OFFSET_BITS=64
> and it comes up with
> 
> error: integer constant is too large for "long" type

Works fine on my machine (FC5, gcc 4.1.1). But my machine is x86_64 so
it probably would.

I can try on a 32 bit machine tomorrow (well, today actually, must be
bedtime!).

You could try suffixing LL onto the long number, see if that helps.

Cheers,

Martin.


From boxbackup-dev@fluffy.co.uk  Tue Jul 25 09:21:17 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Tue, 25 Jul 2006 09:21:17 +0100 (BST)
Subject: [Box Backup-dev] help from a linux guru please!!!
In-Reply-To: <1153786209.19390.2.camel@avenin.ebourne.me.uk>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>
 <1153786209.19390.2.camel@avenin.ebourne.me.uk>
Message-ID: <Pine.LNX.4.62.0607250919530.18881@top.qwarx.com>

Hiya both,

>> g++ test.cpp -o test -D_FILE_OFFSET_BITS=64
>> and it comes up with
>>
>> error: integer constant is too large for "long" type
>
> Works fine on my machine (FC5, gcc 4.1.1). But my machine is x86_64 so
> it probably would.
>
> I can try on a 32 bit machine tomorrow (well, today actually, must be
> bedtime!).

Fails for me on 32-bit. __off_t is "long int" according to gcc -E, I'm 
investigating why.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Tue Jul 25 09:47:18 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Tue, 25 Jul 2006 09:47:18 +0100 (BST)
Subject: [Box Backup-dev] help from a linux guru please!!!
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>
Message-ID: <Pine.LNX.4.62.0607250939120.18881@top.qwarx.com>

Hi Nick,

> int main()
> {
>    off_t nick=8589934591;
>    std::cout << "Hello World!";
>    return -1;
> }

The problem, as Martin correctly suggested, is the missing LL after the 
numeric constant. With that, it compiles fine on my 32-bit box.

Cheers, Chris.
-- 
_ ___ __     _
  / __/ / ,__(_)_  | 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 |


From boxbackup-dev@fluffy.co.uk  Tue Jul 25 10:30:55 2006
From: boxbackup-dev@fluffy.co.uk (Martin Ebourne)
Date: Tue, 25 Jul 2006 10:30:55 +0100
Subject: [Box Backup-dev] help from a linux guru please!!!
In-Reply-To: <Pine.LNX.4.62.0607250939120.18881@top.qwarx.com>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950177E@toutatis.omn11s.local>
 <Pine.LNX.4.62.0607250939120.18881@top.qwarx.com>
Message-ID: <20060725103055.m719e1ugpsg0s0gw@ebourne.me.uk>

>> int main()
>> {
>>   off_t nick=8589934591;
>>   std::cout << "Hello World!";
>>   return -1;
>> }
>
> The problem, as Martin correctly suggested, is the missing LL after the
> numeric constant. With that, it compiles fine on my 32-bit box.

Nick,

I don't see how this helps you. I'm pretty sure that there's no large  
file offsets built into the source code as literals. Would be rather  
odd. So this can't be your problem.

Have you tried adding:
    ASSERT(sizeof(off_t)==8);
and running a debug build?

If that failed I'd suspect order of header file inclusion. BoxConfig.h  
must be included first (via Box.h IIRC).

Cheers,

Martin.

From boxbackup-dev@fluffy.co.uk  Tue Jul 25 12:06:30 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Tue, 25 Jul 2006 12:06:30 +0100
Subject: [Box Backup-dev] observation with client side cached state file
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F950179D@toutatis.omn11s.local>

Hello all,

This is an observation I have had over the last day or so, if I set up
the bbackupd to cache its state in a file, then if you have a problem on
the server with corruption or whatever, then it can be a little
misleading - unless you delete the cache file for it to get it from the
server again, it will not re-backup any file now missing from the store.

My thoughts on this are for a backup system could be a little dangerous?

Thoughts?

Regards

Nick



From boxbackup-dev@fluffy.co.uk  Tue Jul 25 12:25:03 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Tue, 25 Jul 2006 12:25:03 +0100
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F950179D@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F950179D@toutatis.omn11s.local>
Message-ID: <E7BFA764-92B5-4B10-99BD-05411790EFBD@fluffy.co.uk>

Could you tell us a bit more about the corruption on the server?

Did you run bbstoreaccounts to fix the account? If it changed  
anything, it would have reset the client store marker which would  
have caused bbackupd to rescan the entire store next time it connected.

Ben


On 25 Jul 2006, at 12:06, Nick Knight wrote:

> Hello all,
>
> This is an observation I have had over the last day or so, if I set up
> the bbackupd to cache its state in a file, then if you have a  
> problem on
> the server with corruption or whatever, then it can be a little
> misleading - unless you delete the cache file for it to get it from  
> the
> server again, it will not re-backup any file now missing from the  
> store.
>
> My thoughts on this are for a backup system could be a little  
> dangerous?
>
> Thoughts?
>
> Regards
>
> Nick
>
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Tue Jul 25 12:56:53 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Tue, 25 Jul 2006 12:56:53 +0100
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <E7BFA764-92B5-4B10-99BD-05411790EFBD@fluffy.co.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95017A4@toutatis.omn11s.local>

I cannot remember exactly what I did now, I was doing a lot of playing
around with different sized files to sort out large file issues.

One of the things I did do was delete the contents of the account,
remove is from accounts.txt, then recreate the account, the next time
the client reconnected it didn't do a backup until I deleted the
bbackupd.state file.

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
Sent: 25 July 2006 12:25
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] observation with client side cached state
file


Could you tell us a bit more about the corruption on the server?

Did you run bbstoreaccounts to fix the account? If it changed =20
anything, it would have reset the client store marker which would =20
have caused bbackupd to rescan the entire store next time it connected.

Ben


On 25 Jul 2006, at 12:06, Nick Knight wrote:

> Hello all,
>
> This is an observation I have had over the last day or so, if I set up
> the bbackupd to cache its state in a file, then if you have a =20
> problem on
> the server with corruption or whatever, then it can be a little
> misleading - unless you delete the cache file for it to get it from =20
> the
> server again, it will not re-backup any file now missing from the =20
> store.
>
> My thoughts on this are for a backup system could be a little =20
> dangerous?
>
> Thoughts?
>
> Regards
>
> Nick
>
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Tue Jul 25 13:32:06 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Tue, 25 Jul 2006 05:32:06 -0700 (PDT)
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F950179D@toutatis.omn11s.local>
Message-ID: <20060725123206.79340.qmail@web36707.mail.mud.yahoo.com>

Nick,

> the server with corruption or whatever, then it can be a little
> misleading - unless you delete the cache file for it to get it from the
> server again, it will not re-backup any file now missing from the store.

Exactly the same thing will happen even if you disable the cache file, but keep the bbackupd
running on the client side - it will use its runtime cache until restarted, when that information
is lost. So, considering the fact that bbackupd is designed to keep running around the clock and
NOT rely on a complete re-scan when restarted, the problem is there with or without a cache file.
There is no way for bbackupd to know that store contents have changed, unless either the server
informs it of this.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Tue Jul 25 13:42:51 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Tue, 25 Jul 2006 13:42:51 +0100
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <20060725123206.79340.qmail@web36707.mail.mud.yahoo.com>
References: <20060725123206.79340.qmail@web36707.mail.mud.yahoo.com>
Message-ID: <8C7AD0F2-1460-46E4-92D9-9144178CB433@fluffy.co.uk>

On 25 Jul 2006, at 13:32, G. wrote:

> Nick,
>
>> the server with corruption or whatever, then it can be a little
>> misleading - unless you delete the cache file for it to get it  
>> from the
>> server again, it will not re-backup any file now missing from the  
>> store.
>
> Exactly the same thing will happen even if you disable the cache  
> file, but keep the bbackupd
> running on the client side - it will use its runtime cache until  
> restarted, when that information
> is lost. So, considering the fact that bbackupd is designed to keep  
> running around the clock and
> NOT rely on a complete re-scan when restarted, the problem is there  
> with or without a cache file.
> There is no way for bbackupd to know that store contents have  
> changed, unless either the server
> informs it of this.

The client store marker is the way that the server informs the  
clients of unexpected changes to the store. A recreation of the  
account will change this.

However, if nothing changed on the client, then bbackupd wouldn't  
have contacted the store and so wouldn't have learnt of the change.

What happens if you repeat your experiment, but this time, touch one  
of the test files after the server account has been wiped?

Ben








From boxbackup-dev@fluffy.co.uk  Tue Jul 25 23:48:51 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Tue, 25 Jul 2006 22:48:51 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r688 - box/chris/general/lib/win32
Message-ID: <20060725224851.EDD3096@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-25 22:48:48 +0000 (Tue, 25 Jul 2006)
New Revision: 688

Modified:
   box/chris/general/lib/win32/emu.cpp
   box/chris/general/lib/win32/emu.h
Log:
* emu.cpp, emu.h
- Added a real emulated utimes() function (although it sets the file 
  creation time rather than the last access time).
- OpenFileByNameUtf8 takes the desired access rights as a parameter,
  so that emu_utimes() can use it
- Fixed some compiler warnings
- Added a ConvertTime_tToFileTime() function


Modified: box/chris/general/lib/win32/emu.cpp
===================================================================
--- box/chris/general/lib/win32/emu.cpp	2006-07-23 22:36:27 UTC (rev 687)
+++ box/chris/general/lib/win32/emu.cpp	2006-07-25 22:48:48 UTC (rev 688)
@@ -516,16 +516,16 @@
 
 	if (flags & O_WRONLY)
 	{
-		accessRights = FILE_WRITE_ATTRIBUTES 
-			| FILE_WRITE_DATA | FILE_WRITE_EA;
+		accessRights = FILE_WRITE_DATA;
 		shareMode = FILE_SHARE_WRITE;
 	}
-	if (flags & (O_RDWR | O_CREAT))
+	else if (flags & (O_RDWR | O_CREAT))
 	{
 		accessRights |= FILE_WRITE_ATTRIBUTES 
 			| FILE_WRITE_DATA | FILE_WRITE_EA;
 		shareMode |= FILE_SHARE_WRITE;
 	}
+
 	if (flags & O_CREAT)
 	{
 		createDisposition = OPEN_ALWAYS;
@@ -595,7 +595,7 @@
 
 	memset(st, 0, sizeof(*st));
 
-	// This next example is how we get our INODE (equivalent) information
+	// This is how we get our INODE (equivalent) information
 	ULARGE_INTEGER conv;
 	conv.HighPart = fi.nFileIndexHigh;
 	conv.LowPart = fi.nFileIndexLow;
@@ -670,7 +670,7 @@
 //		Created: 10th December 2004
 //
 // --------------------------------------------------------------------------
-HANDLE OpenFileByNameUtf8(const char* pFileName)
+HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags)
 {
 	std::string AbsPathWithUnicode = 
 		ConvertPathToAbsoluteUnicode(pFileName);
@@ -691,8 +691,7 @@
 	}
 
 	HANDLE handle = CreateFileW(pBuffer, 
-		FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA |
-		READ_CONTROL, 
+		flags,
 		FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, 
 		NULL, 
 		OPEN_EXISTING, 
@@ -706,7 +705,7 @@
 		// at least one process must have the file open - 
 		// in this case someone else does.
 		handle = CreateFileW(pBuffer, 
-			READ_CONTROL, 
+			READ_CONTROL,
 			FILE_SHARE_READ, 
 			NULL, 
 			OPEN_EXISTING, 
@@ -749,7 +748,8 @@
 // --------------------------------------------------------------------------
 int emu_stat(const char * pName, struct stat * st)
 {
-	HANDLE handle = OpenFileByNameUtf8(pName);
+	HANDLE handle = OpenFileByNameUtf8(pName, 
+		FILE_READ_ATTRIBUTES | FILE_READ_EA);
 
 	if (handle == NULL)
 	{
@@ -782,7 +782,8 @@
 // --------------------------------------------------------------------------
 int statfs(const char * pName, struct statfs * s)
 {
-	HANDLE handle = OpenFileByNameUtf8(pName);
+	HANDLE handle = OpenFileByNameUtf8(pName,
+		FILE_READ_ATTRIBUTES | FILE_READ_EA);
 
 	if (handle == NULL)
 	{
@@ -814,6 +815,49 @@
 // --------------------------------------------------------------------------
 //
 // Function
+//		Name:    emu_fstat
+//		Purpose: replacement for fstat supply a windows handle
+//		Created: 25th October 2004
+//
+// --------------------------------------------------------------------------
+int emu_utimes(const char * pName, const struct timeval times[])
+{
+	FILETIME creationTime;
+	if (!ConvertTime_tToFileTime(times[0].tv_sec, &creationTime))
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	FILETIME modificationTime;
+	if (!ConvertTime_tToFileTime(times[1].tv_sec, &modificationTime))
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	HANDLE handle = OpenFileByNameUtf8(pName, FILE_WRITE_ATTRIBUTES);
+
+	if (handle == NULL)
+	{
+		// errno already set and error logged by OpenFileByNameUtf8()
+		return -1;
+	}
+
+	if (!SetFileTime(handle, &creationTime, NULL, &modificationTime))
+	{
+		::syslog(LOG_ERR, "Failed to set times on '%s': error %d",
+			pName, GetLastError());
+		CloseHandle(handle);
+		return 1;
+	}
+
+	return 0;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
 //		Name:    opendir
 //		Purpose: replacement for unix function, uses win32 findfirst routines
 //		Created: 25th October 2004
@@ -1227,7 +1271,14 @@
 	va_start(args, frmt);
 
 	int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args);
-	assert(len < sizeof(buffer));
+	assert(len >= 0);
+	if (len < 0) 
+	{
+		printf("%s\r\n", buffer);
+		return;
+	}
+	
+	assert((size_t)len < sizeof(buffer));
 	buffer[sizeof(buffer)-1] = 0;
 
 	va_end(args);
@@ -1305,7 +1356,7 @@
 		return NULL;
 	}
 
-	if (len > BufSize)
+	if ((int)len > BufSize)
 	{
 		errno = ENAMETOOLONG;
 		return NULL;

Modified: box/chris/general/lib/win32/emu.h
===================================================================
--- box/chris/general/lib/win32/emu.h	2006-07-23 22:36:27 UTC (rev 687)
+++ box/chris/general/lib/win32/emu.h	2006-07-25 22:48:48 UTC (rev 688)
@@ -91,14 +91,7 @@
 	#define S_ISDIR(x) (S_IFDIR & x)
 #endif
 
-inline int utimes(const char * Filename, timeval[])
-{
-	//again I am guessing this is quite important to
-	//be functioning, as large restores would be a problem
 
-	//indicate success
-	return 0;
-}
 inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid)
 {
 	//important - this needs implementing
@@ -118,7 +111,10 @@
 int   emu_chdir (const char* pDirName);
 int   emu_unlink(const char* pFileName);
 char* emu_getcwd(char* pBuffer, int BufSize);
+int   emu_utimes(const char* pName, const struct timeval[]);
 
+#define utimes(buffer, times) emu_utimes(buffer, times)
+
 #ifdef _MSC_VER
 	inline int emu_chmod(const char * Filename, int mode)
 	{
@@ -126,10 +122,10 @@
 		return 0;
 	}
 
-	#define chmod(file, mode)    emu_chmod(file, mode)
-	#define chdir(directory)     emu_chdir(directory)
-	#define unlink(file)         emu_unlink(file)
-	#define getcwd(buffer, size) emu_getcwd(buffer, size)
+	#define chmod(file, mode)     emu_chmod(file, mode)
+	#define chdir(directory)      emu_chdir(directory)
+	#define unlink(file)          emu_unlink(file)
+	#define getcwd(buffer, size)  emu_getcwd(buffer, size)
 #else
 	inline int chmod(const char * Filename, int mode)
 	{
@@ -328,7 +324,7 @@
 int emu_fstat(HANDLE file, struct stat * st);
 int statfs(const char * name, struct statfs * s);
 
-//need this for converstions
+// need this for conversions
 inline time_t ConvertFileTimeToTime_t(FILETIME *fileTime)
 {
 	SYSTEMTIME stUTC;
@@ -336,7 +332,6 @@
 
 	// Convert the last-write time to local time.
 	FileTimeToSystemTime(fileTime, &stUTC);
-	// SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
 
 	memset(&timeinfo, 0, sizeof(timeinfo));	
 	timeinfo.tm_sec = stUTC.wSecond;
@@ -352,6 +347,38 @@
 	return retVal;
 }
 
+inline bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo)
+{
+	time_t adjusted = from + _timezone;
+	struct tm *time_breakdown = gmtime(&adjusted);
+	if (time_breakdown == NULL)
+	{
+		::syslog(LOG_ERR, "Error: failed to convert time format: "
+			"%d is not a valid time\n", from);
+		return false;
+	}
+
+	SYSTEMTIME stUTC;
+	stUTC.wSecond       = time_breakdown->tm_sec;
+	stUTC.wMinute       = time_breakdown->tm_min;
+	stUTC.wHour         = time_breakdown->tm_hour;
+	stUTC.wDay          = time_breakdown->tm_mday;
+	stUTC.wDayOfWeek    = time_breakdown->tm_wday;
+	stUTC.wMonth        = time_breakdown->tm_mon  + 1;
+	stUTC.wYear         = time_breakdown->tm_year + 1900;
+	stUTC.wMilliseconds = 0;
+
+	// Convert the last-write time to local time.
+	if (!SystemTimeToFileTime(&stUTC, pTo))
+	{
+		syslog(LOG_ERR, "Failed to convert between time formats: "
+			"error %d", GetLastError());
+		return false;
+	}
+
+	return true;
+}
+
 #ifdef _MSC_VER
 	#define stat(filename,  struct) emu_stat (filename, struct)
 	#define lstat(filename, struct) emu_stat (filename, struct)


From boxbackup-dev@fluffy.co.uk  Tue Jul 25 23:51:05 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Tue, 25 Jul 2006 22:51:05 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r689 - in box/chris/general: . test/bbackupd/testfiles
Message-ID: <20060725225105.0C7EA96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-25 22:51:02 +0000 (Tue, 25 Jul 2006)
New Revision: 689

Modified:
   box/chris/general/configure.ac
   box/chris/general/test/bbackupd/testfiles/bbackupd.conf.in
Log:
* configure.ac
- Substitute PERL_NATIVE as "perl" on Win32, $PERL on all other platforms

* test/bbackupd/testfiles/bbackupd.conf.in
- Use PERL_NATIVE substitution to get the path that bbackupd should run
  to execute the Perl notify script


Modified: box/chris/general/configure.ac
===================================================================
--- box/chris/general/configure.ac	2006-07-25 22:48:48 UTC (rev 688)
+++ box/chris/general/configure.ac	2006-07-25 22:51:02 UTC (rev 689)
@@ -32,6 +32,8 @@
 case $target_os in
 mingw*) 
 	AC_DEFINE_UNQUOTED([PERL_EXECUTABLE], ["perl"], [Command to run Perl])
+	PERL_NATIVE=perl
+	AC_SUBST([PERL_NATIVE])
 	;;
 *)
 	AC_DEFINE_UNQUOTED([PERL_EXECUTABLE], ["$PERL"], 

Modified: box/chris/general/test/bbackupd/testfiles/bbackupd.conf.in
===================================================================
--- box/chris/general/test/bbackupd/testfiles/bbackupd.conf.in	2006-07-25 22:48:48 UTC (rev 688)
+++ box/chris/general/test/bbackupd/testfiles/bbackupd.conf.in	2006-07-25 22:51:02 UTC (rev 689)
@@ -23,7 +23,7 @@
 
 CommandSocket = testfiles/bbackupd.sock
 
-NotifyScript = @PERL@ testfiles/notifyscript.pl
+NotifyScript = @PERL_NATIVE@ testfiles/notifyscript.pl
 
 Server
 {


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 00:04:22 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Tue, 25 Jul 2006 23:04:22 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r690 - box/chris/general/lib/win32
Message-ID: <20060725230422.5FD9996@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-25 23:04:20 +0000 (Tue, 25 Jul 2006)
New Revision: 690

Modified:
   box/chris/general/lib/win32/emu.cpp
Log:
* emu.cpp
- Close forgotten file descriptor


Modified: box/chris/general/lib/win32/emu.cpp
===================================================================
--- box/chris/general/lib/win32/emu.cpp	2006-07-25 22:51:02 UTC (rev 689)
+++ box/chris/general/lib/win32/emu.cpp	2006-07-25 23:04:20 UTC (rev 690)
@@ -852,6 +852,7 @@
 		return 1;
 	}
 
+	CloseHandle(handle);
 	return 0;
 }
 


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 01:27:29 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Tue, 25 Jul 2006 17:27:29 -0700 (PDT)
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <8C7AD0F2-1460-46E4-92D9-9144178CB433@fluffy.co.uk>
Message-ID: <20060726002729.54802.qmail@web36710.mail.mud.yahoo.com>

> However, if nothing changed on the client, then bbackupd wouldn't  
> have contacted the store and so wouldn't have learnt of the change.

If that is the case, it would be beneficial to modify bbackupd to check the marker before it tries
to run a cycle (to be on the safe side).

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 09:00:26 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 26 Jul 2006 09:00:26 +0100
Subject: [Box Backup-dev] more linux guru help please!!
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95017E3@toutatis.omn11s.local>

Hello all,

I have resorted to try and debug the server using gdb, which I am a
complete newbie at! My life is spent in the save old world of MSVC IDE:)

I have tried so far using gdb and ddd, but I have a lot of problems

1. When I start the program it immediately exit's as the program forks
off, (in MSVC in would carry on for you), how do I get it to debug all
child processes
2. Because of the problem in 1, I connected from the client, noted the
process ID, attached the debugger, but as soon as I attached and
continued running, the server died (or that process) with a TLS error.

Does anyone have any tips for running it up in a debugger?

Thanks

Nick

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 09:06:40 2006
From: boxbackup-dev@fluffy.co.uk (Stefan Norlin)
Date: Wed, 26 Jul 2006 10:06:40 +0200
Subject: [Box Backup-dev] more linux guru help please!!
References: <A1501BC8C03ACC44B4C56ADC68B1C7F95017E3@toutatis.omn11s.local>
Message-ID: <036901c6b08a$6d2d7970$0101050a@stenorhem>

> 1. When I start the program it immediately exit's as the program forks
> off, (in MSVC in would carry on for you), how do I get it to debug all
> child processes

You can debug a running process.

http://dirac.org/linux/gdb/06-Debugging_A_Running_Process.php

Stefan


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 09:07:18 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 26 Jul 2006 09:07:18 +0100
Subject: [Box Backup-dev] more linux guru help please!!
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F95017E3@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F95017E3@toutatis.omn11s.local>
Message-ID: <9B955F19-CF31-408D-A0AA-E2801A4F3F4D@fluffy.co.uk>

In gdb...

set follow-fork-mode child
r <config_file> SINGLEPROCESS

The first line gets gdb to go into the forked child. The second runs  
the process with an argument which avoids the first couple of forks  
to daemonise.

Ben




On 26 Jul 2006, at 09:00, Nick Knight wrote:

> Hello all,
>
> I have resorted to try and debug the server using gdb, which I am a
> complete newbie at! My life is spent in the save old world of MSVC  
> IDE:)
>
> I have tried so far using gdb and ddd, but I have a lot of problems
>
> 1. When I start the program it immediately exit's as the program forks
> off, (in MSVC in would carry on for you), how do I get it to debug all
> child processes
> 2. Because of the problem in 1, I connected from the client, noted the
> process ID, attached the debugger, but as soon as I attached and
> continued running, the server died (or that process) with a TLS error.
>
> Does anyone have any tips for running it up in a debugger?
>
> Thanks
>
> Nick
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 10:20:28 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 26 Jul 2006 10:20:28 +0100
Subject: [Box Backup-dev] more linux guru help please!!
In-Reply-To: <9B955F19-CF31-408D-A0AA-E2801A4F3F4D@fluffy.co.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95017EE@toutatis.omn11s.local>

Thanks Ben,

That seem s to keep hold of the process, the problem I know have is
break points do not appear to work.

I have set them in various place I am confident that is being run, and
they do not get caught, is there anything I should be looking for?

For example in RaidFileRead.cpp:119 it works, but when I try and catch
the exception which is being thrown in that function the break point
does nothing - and the exception is still being thrown. I have tried
putting another line (syslog) before the exception macro but this
doesn't break either.

Thanks

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
Sent: 26 July 2006 09:07
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] more linux guru help please!!


In gdb...

set follow-fork-mode child
r <config_file> SINGLEPROCESS

The first line gets gdb to go into the forked child. The second runs =20
the process with an argument which avoids the first couple of forks =20
to daemonise.

Ben




On 26 Jul 2006, at 09:00, Nick Knight wrote:

> Hello all,
>
> I have resorted to try and debug the server using gdb, which I am a
> complete newbie at! My life is spent in the save old world of MSVC =20
> IDE:)
>
> I have tried so far using gdb and ddd, but I have a lot of problems
>
> 1. When I start the program it immediately exit's as the program forks
> off, (in MSVC in would carry on for you), how do I get it to debug all
> child processes
> 2. Because of the problem in 1, I connected from the client, noted the
> process ID, attached the debugger, but as soon as I attached and
> continued running, the server died (or that process) with a TLS error.
>
> Does anyone have any tips for running it up in a debugger?
>
> Thanks
>
> Nick
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 11:06:04 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 26 Jul 2006 11:06:04 +0100
Subject: [Box Backup-dev] more linux guru help please!!
In-Reply-To: <036901c6b08a$6d2d7970$0101050a@stenorhem>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F95017F3@toutatis.omn11s.local>

Hello Stephan,

I already found that page and tried it; the problem with attaching to a
process is it appears to kill the connection for some reason.

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Stefan Norlin
Sent: 26 July 2006 09:07
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] more linux guru help please!!

> 1. When I start the program it immediately exit's as the program forks
> off, (in MSVC in would carry on for you), how do I get it to debug all
> child processes

You can debug a running process.

http://dirac.org/linux/gdb/06-Debugging_A_Running_Process.php

Stefan

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 11:16:43 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 26 Jul 2006 11:16:43 +0100
Subject: [Box Backup-dev] more linux guru help please!!
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F95017EE@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F95017EE@toutatis.omn11s.local>
Message-ID: <DACC662F-D010-4A7F-9324-4BB4A556F973@fluffy.co.uk>

Try stepping over the fork statement (into the child), then setting  
the breakpoints.

Ben


On 26 Jul 2006, at 10:20, Nick Knight wrote:

> Thanks Ben,
>
> That seem s to keep hold of the process, the problem I know have is
> break points do not appear to work.
>
> I have set them in various place I am confident that is being run, and
> they do not get caught, is there anything I should be looking for?
>
> For example in RaidFileRead.cpp:119 it works, but when I try and catch
> the exception which is being thrown in that function the break point
> does nothing - and the exception is still being thrown. I have tried
> putting another line (syslog) before the exception macro but this
> doesn't break either.
>
> Thanks
>
> Nick
>
> -----Original Message-----
> From: boxbackup-dev-admin@fluffy.co.uk
> [mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
> Sent: 26 July 2006 09:07
> To: boxbackup-dev@fluffy.co.uk
> Subject: Re: [Box Backup-dev] more linux guru help please!!
>
>
> In gdb...
>
> set follow-fork-mode child
> r <config_file> SINGLEPROCESS
>
> The first line gets gdb to go into the forked child. The second runs
> the process with an argument which avoids the first couple of forks
> to daemonise.
>
> Ben
>
>
>
>
> On 26 Jul 2006, at 09:00, Nick Knight wrote:
>
>> Hello all,
>>
>> I have resorted to try and debug the server using gdb, which I am a
>> complete newbie at! My life is spent in the save old world of MSVC
>> IDE:)
>>
>> I have tried so far using gdb and ddd, but I have a lot of problems
>>
>> 1. When I start the program it immediately exit's as the program  
>> forks
>> off, (in MSVC in would carry on for you), how do I get it to debug  
>> all
>> child processes
>> 2. Because of the problem in 1, I connected from the client, noted  
>> the
>> process ID, attached the debugger, but as soon as I attached and
>> continued running, the server died (or that process) with a TLS  
>> error.
>>
>> Does anyone have any tips for running it up in a debugger?
>>
>> Thanks
>>
>> Nick
>> _______________________________________________
>> Boxbackup-dev mailing list
>> Boxbackup-dev@fluffy.co.uk
>> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 11:24:06 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 26 Jul 2006 11:24:06 +0100
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <20060726002729.54802.qmail@web36710.mail.mud.yahoo.com>
References: <20060726002729.54802.qmail@web36710.mail.mud.yahoo.com>
Message-ID: <46321B3A-AE1E-40DF-B0ED-59F651AB5788@fluffy.co.uk>

On 26 Jul 2006, at 01:27, G. wrote:

>> However, if nothing changed on the client, then bbackupd wouldn't
>> have contacted the store and so wouldn't have learnt of the change.
>
> If that is the case, it would be beneficial to modify bbackupd to  
> check the marker before it tries
> to run a cycle (to be on the safe side).

So you're suggesting that the daemon connects at the beginning of  
every sync, at the very least?

This is only going to be a problem if the files on the client never  
change or change very infrequently. Should we be worried about this  
scenario?

One of the design criteria for the system is that you trust the  
server to keep hold of your encrypted data (but that's the only trust  
you put in it).

Ben






From boxbackup-dev@fluffy.co.uk  Wed Jul 26 13:44:21 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 26 Jul 2006 13:44:21 +0100
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <46321B3A-AE1E-40DF-B0ED-59F651AB5788@fluffy.co.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F955B15D@toutatis.omn11s.local>

I think you should trust the server to do this so I agree, however you
do need to make allowances for corruption on the server (or other
extreme scenarios), this even in the best laid out plans will happen.

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
Sent: 26 July 2006 11:24
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] observation with client side cached state
file


On 26 Jul 2006, at 01:27, G. wrote:

>> However, if nothing changed on the client, then bbackupd wouldn't
>> have contacted the store and so wouldn't have learnt of the change.
>
> If that is the case, it would be beneficial to modify bbackupd to =20
> check the marker before it tries
> to run a cycle (to be on the safe side).

So you're suggesting that the daemon connects at the beginning of =20
every sync, at the very least?

This is only going to be a problem if the files on the client never =20
change or change very infrequently. Should we be worried about this =20
scenario?

One of the design criteria for the system is that you trust the =20
server to keep hold of your encrypted data (but that's the only trust =20
you put in it).

Ben





_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 13:49:06 2006
From: boxbackup-dev@fluffy.co.uk (G.)
Date: Wed, 26 Jul 2006 05:49:06 -0700 (PDT)
Subject: [Box Backup-dev] observation with client side cached state file
In-Reply-To: <46321B3A-AE1E-40DF-B0ED-59F651AB5788@fluffy.co.uk>
Message-ID: <20060726124906.58889.qmail@web36706.mail.mud.yahoo.com>

Ben,

> So you're suggesting that the daemon connects at the beginning of  
> every sync, at the very least?
> 
> This is only going to be a problem if the files on the client never  
> change or change very infrequently. Should we be worried about this  
> scenario?

I see your point, but should a server store blow up, an admin has no way to force a backup from
all users. Hmmmmmm. I would say let's stick to the old and well-proven Linux methodology: when in
doubt, make it a user option.

Gary


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 14:06:59 2006
From: boxbackup-dev@fluffy.co.uk (Martin Ebourne)
Date: Wed, 26 Jul 2006 14:06:59 +0100
Subject: [Box Backup-dev] observation with client side cached state
 file
In-Reply-To: <20060726124906.58889.qmail@web36706.mail.mud.yahoo.com>
References: <20060726124906.58889.qmail@web36706.mail.mud.yahoo.com>
Message-ID: <20060726140659.978saloe044s480o@ebourne.me.uk>

"G." <gniemcew@yahoo.com> wrote:
> I see your point, but should a server store blow up, an admin has no  
>  way to force a backup from
> all users. Hmmmmmm. I would say let's stick to the old and   
> well-proven Linux methodology: when in
> doubt, make it a user option.

No, that's a bad idea in this case. Where there's more than one right  
way to do it, make it configurable. Where this is not the case do the  
right thing only.

I don't really see the harm in bbackupd always connecting. The amount  
of data transfer is minimal and it gives you an early warning if  
there's any kind of communication issue. Also reassuring from the  
server side that all clients are operational. This was discussed  
previously about adding a client heartbeat so the server knows it is  
alive.

Cheers,

Martin.

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 14:33:23 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 26 Jul 2006 14:33:23 +0100
Subject: [Box Backup-dev] blocks
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F955B165@toutatis.omn11s.local>

This is a multi-part message in MIME format.

------_=_NextPart_001_01C6B0B8.11EFE7FF
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

Hello all,

=20

Can someone spare a minute and provide me with a small tutorial on what
a block under box backup is.

=20

I am trying to figure out new portions of code to me, and It looks like
the windows version is calculating them wrongly but not sure why.

=20

It appears that the client decides on the block size for a given file, I
always thought it was fixed as the server allocates a number of blocks
for an account...

=20

Thanks

=20

Nick


------_=_NextPart_001_01C6B0B8.11EFE7FF
Content-Type: text/html;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns=3D"http://www.w3.org/TR/REC-html40">

<head>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Dus-ascii">
<meta name=3DGenerator content=3D"Microsoft Word 11 (filtered medium)">
<style>
<!--
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0cm;
	margin-bottom:.0001pt;
	font-size:12.0pt;
	font-family:"Times New Roman";}
a:link, span.MsoHyperlink
	{color:blue;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{color:purple;
	text-decoration:underline;}
span.EmailStyle17
	{mso-style-type:personal-compose;
	font-family:Arial;
	color:windowtext;}
@page Section1
	{size:595.3pt 841.9pt;
	margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
	{page:Section1;}
-->
</style>

</head>

<body lang=3DEN-GB link=3Dblue vlink=3Dpurple>

<div class=3DSection1>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Hello all,<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Can someone spare a minute and provide me with a =
small
tutorial on what a block under box backup =
is.<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>I am trying to figure out new portions of code to me, =
and It
looks like the windows version is calculating them wrongly but not sure =
why.<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>It appears that the client decides on the block size =
for a
given file, I always thought it was fixed as the server allocates a =
number of
blocks for an account&#8230;<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Thanks<o:p></o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'><o:p>&nbsp;</o:p></span></font></p>

<p class=3DMsoNormal><font size=3D2 face=3DArial><span =
style=3D'font-size:10.0pt;
font-family:Arial'>Nick<o:p></o:p></span></font></p>

</div>

</body>

</html>

------_=_NextPart_001_01C6B0B8.11EFE7FF--

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 14:58:31 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 26 Jul 2006 14:58:31 +0100
Subject: [Box Backup-dev] blocks
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F955B165@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F955B165@toutatis.omn11s.local>
Message-ID: <FBE8AFFB-D148-4C1E-AE5E-79E6ACE9269B@fluffy.co.uk>

Within a BackupStoreFile, a block is an arbitrarily sized chunk of =20
data, from 1 byte upwards. (You can get 1 byte blocks if you insert 1 =20=

byte within a file and it gets diffed.)

On the server, regarding the storage limits, a block is whatever size =20=

is set in raidfile.conf.

Both are separate concepts, and refer to completely different things =20
which aren't used together.

Ben





On 26 Jul 2006, at 14:33, Nick Knight wrote:

> Hello all,
>
>
>
> Can someone spare a minute and provide me with a small tutorial on =20
> what a block under box backup is.
>
>
>
> I am trying to figure out new portions of code to me, and It looks =20
> like the windows version is calculating them wrongly but not sure why.
>
>
>
> It appears that the client decides on the block size for a given =20
> file, I always thought it was fixed as the server allocates a =20
> number of blocks for an account=85
>
>
>
> Thanks
>
>
>
> Nick
>
>


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 15:24:11 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Wed, 26 Jul 2006 15:24:11 +0100
Subject: [Box Backup-dev] blocks
In-Reply-To: <FBE8AFFB-D148-4C1E-AE5E-79E6ACE9269B@fluffy.co.uk>
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F955B16D@toutatis.omn11s.local>

Is a client sided block stored on the server as a complete file? Also
does the file contain information about the block as a header?

Thanks again

Nick

-----Original Message-----
From: boxbackup-dev-admin@fluffy.co.uk
[mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
Sent: 26 July 2006 14:59
To: boxbackup-dev@fluffy.co.uk
Subject: Re: [Box Backup-dev] blocks

Within a BackupStoreFile, a block is an arbitrarily sized chunk of =20
data, from 1 byte upwards. (You can get 1 byte blocks if you insert 1 =20
byte within a file and it gets diffed.)

On the server, regarding the storage limits, a block is whatever size =20
is set in raidfile.conf.

Both are separate concepts, and refer to completely different things =20
which aren't used together.

Ben





On 26 Jul 2006, at 14:33, Nick Knight wrote:

> Hello all,
>
>
>
> Can someone spare a minute and provide me with a small tutorial on =20
> what a block under box backup is.
>
>
>
> I am trying to figure out new portions of code to me, and It looks =20
> like the windows version is calculating them wrongly but not sure why.
>
>
>
> It appears that the client decides on the block size for a given =20
> file, I always thought it was fixed as the server allocates a =20
> number of blocks for an account...
>
>
>
> Thanks
>
>
>
> Nick
>
>

_______________________________________________
Boxbackup-dev mailing list
Boxbackup-dev@fluffy.co.uk
http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev

From boxbackup-dev@fluffy.co.uk  Wed Jul 26 15:29:57 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Wed, 26 Jul 2006 15:29:57 +0100
Subject: [Box Backup-dev] blocks
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F955B16D@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F955B16D@toutatis.omn11s.local>
Message-ID: <58688F36-B08D-4571-B95B-119EF836F7BE@fluffy.co.uk>

lib/backupclient/BackupStoreFileWire.h

docs/backup/encrypt_rsync.txt

docs/backup/bin_bbstored.txt


On 26 Jul 2006, at 15:24, Nick Knight wrote:

> Is a client sided block stored on the server as a complete file? Also
> does the file contain information about the block as a header?
>
> Thanks again
>
> Nick
>
> -----Original Message-----
> From: boxbackup-dev-admin@fluffy.co.uk
> [mailto:boxbackup-dev-admin@fluffy.co.uk] On Behalf Of Ben Summers
> Sent: 26 July 2006 14:59
> To: boxbackup-dev@fluffy.co.uk
> Subject: Re: [Box Backup-dev] blocks
>
> Within a BackupStoreFile, a block is an arbitrarily sized chunk of
> data, from 1 byte upwards. (You can get 1 byte blocks if you insert 1
> byte within a file and it gets diffed.)
>
> On the server, regarding the storage limits, a block is whatever size
> is set in raidfile.conf.
>
> Both are separate concepts, and refer to completely different things
> which aren't used together.
>
> Ben
>
>
>
>
>
> On 26 Jul 2006, at 14:33, Nick Knight wrote:
>
>> Hello all,
>>
>>
>>
>> Can someone spare a minute and provide me with a small tutorial on
>> what a block under box backup is.
>>
>>
>>
>> I am trying to figure out new portions of code to me, and It looks
>> like the windows version is calculating them wrongly but not sure  
>> why.
>>
>>
>>
>> It appears that the client decides on the block size for a given
>> file, I always thought it was fixed as the server allocates a
>> number of blocks for an account...
>>
>>
>>
>> Thanks
>>
>>
>>
>> Nick
>>
>>
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 20:09:09 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 19:09:09 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r691 - box/chris/general/lib/backupclient
Message-ID: <20060726190909.5DC9F96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 19:09:05 +0000 (Wed, 26 Jul 2006)
New Revision: 691

Modified:
   box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp
Log:
* BackupClientFileAttributes.cpp
- Restore timestamps on restored files under Win32 (experimental)


Modified: box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp	2006-07-25 23:04:20 UTC (rev 690)
+++ box/chris/general/lib/backupclient/BackupClientFileAttributes.cpp	2006-07-26 19:09:05 UTC (rev 691)
@@ -681,10 +681,24 @@
 	{
 		// Work out times as timevals
 		struct timeval times[2];
+
+		#ifdef WIN32
+		BoxTimeToTimeval(box_ntoh64(pattr->ModificationTime), 
+			times[1]);
+		BoxTimeToTimeval(box_ntoh64(pattr->AttrModificationTime), 
+			times[0]);
+		// Because stat() returns the creation time in the ctime
+		// field under Windows, and this gets saved in the 
+		// AttrModificationTime field of the serialised attributes,
+		// we subvert the first parameter of emu_utimes() to allow
+		// it to be reset to the right value on the restored file.
+		#else
 		BoxTimeToTimeval(modtime, times[1]);
 		// Copy access time as well, why not, got to set it to something
 		times[0] = times[1];
-		// Attr modification time will be changed anyway, nothing that can be done about it
+		// Attr modification time will be changed anyway, 
+		// nothing that can be done about it
+		#endif
 		
 		// Try to apply
 		if(::utimes(Filename, times) != 0)


From boxbackup-dev@fluffy.co.uk  Wed Jul 26 20:10:19 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 19:10:19 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r692 - in box/chris/general: infrastructure lib/common lib/server
Message-ID: <20060726191019.C5FBE96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 19:10:10 +0000 (Wed, 26 Jul 2006)
New Revision: 692

Modified:
   box/chris/general/infrastructure/BoxPlatform.pm.in
   box/chris/general/infrastructure/makebuildenv.pl.in
   box/chris/general/lib/common/makeexception.pl.in
   box/chris/general/lib/server/makeprotocol.pl.in
Log:
* infrastructure/BoxPlatform.pm.in
* infrastructure/makebuildenv.pl.in
* lib/server/makeprotocol.pl.in
* lib/common/makeexception.pl.in
- Don't rewrite auto-generated files unless they have changed, to prevent
  unnecessary rebuilds


Modified: box/chris/general/infrastructure/BoxPlatform.pm.in
===================================================================
--- box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-26 19:09:05 UTC (rev 691)
+++ box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-26 19:10:10 UTC (rev 692)
@@ -1,7 +1,7 @@
 package BoxPlatform;
 use Exporter;
 @ISA = qw/Exporter/;
-@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/;
+@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
 {
@@ -110,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 -u $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/general/infrastructure/makebuildenv.pl.in
===================================================================
--- box/chris/general/infrastructure/makebuildenv.pl.in	2006-07-26 19:09:05 UTC (rev 691)
+++ box/chris/general/infrastructure/makebuildenv.pl.in	2006-07-26 19:10:10 UTC (rev 692)
@@ -114,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;
@@ -296,7 +296,8 @@
 }
 
 # 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
@@ -312,8 +313,8 @@
 #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_deps)
@@ -393,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")
 			{
@@ -420,6 +425,7 @@
 			}
 			print TESTFILE "$runcmd\n";
 			close TESTFILE;
+			update_if_changed($filename);
 		}
 		
 		writetestfile("$mod/_t", 
@@ -487,7 +493,8 @@
 
 	# 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";
@@ -785,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>)
 		{
@@ -798,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";

Modified: box/chris/general/lib/common/makeexception.pl.in
===================================================================
--- box/chris/general/lib/common/makeexception.pl.in	2006-07-26 19:09:05 UTC (rev 691)
+++ box/chris/general/lib/common/makeexception.pl.in	2006-07-26 19:10:10 UTC (rev 692)
@@ -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/general/lib/server/makeprotocol.pl.in
===================================================================
--- box/chris/general/lib/server/makeprotocol.pl.in	2006-07-26 19:09:05 UTC (rev 691)
+++ box/chris/general/lib/server/makeprotocol.pl.in	2006-07-26 19:10:10 UTC (rev 692)
@@ -170,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;
 
@@ -915,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
 {


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 00:11:45 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 23:11:45 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r693 - in box/chris/general: lib/common lib/win32 test/backupdiff test/backupstore
Message-ID: <20060726231145.8E3A596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 23:11:39 +0000 (Wed, 26 Jul 2006)
New Revision: 693

Modified:
   box/chris/general/lib/common/FileStream.cpp
   box/chris/general/lib/win32/emu.cpp
   box/chris/general/lib/win32/emu.h
   box/chris/general/test/backupdiff/testbackupdiff.cpp
   box/chris/general/test/backupstore/testbackupstore.cpp
Log:
* lib/win32/emu.cpp, lib/win32/emu.h
- Added a real emulated chmod() function, but it only sets the READ_ONLY
  attribute on win32
- Moved ConvertFileTime to/from time_t functions out of line and into emu.cpp
- Changed openfile() to return INVALID_HANDLE_VALUE instead of NULL
  when it fails to open a file, for consistency with Win32 API

* test/backupstore/testbackupstore.cpp
* test/backupdiff/testbackupdiff.cpp
* lib/common/FileStream.cpp
- Deal with openfile() returning INVALID_HANDLE_VALUE


Modified: box/chris/general/lib/common/FileStream.cpp
===================================================================
--- box/chris/general/lib/common/FileStream.cpp	2006-07-26 19:10:10 UTC (rev 692)
+++ box/chris/general/lib/common/FileStream.cpp	2006-07-26 23:11:39 UTC (rev 693)
@@ -30,7 +30,7 @@
 	  mIsEOF(false)
 {
 #ifdef WIN32
-	if(mOSFileHandle == 0)
+	if(mOSFileHandle == INVALID_HANDLE_VALUE)
 #else
 	if(mOSFileHandle < 0)
 #endif

Modified: box/chris/general/lib/win32/emu.cpp
===================================================================
--- box/chris/general/lib/win32/emu.cpp	2006-07-26 19:10:10 UTC (rev 692)
+++ box/chris/general/lib/win32/emu.cpp	2006-07-26 23:11:39 UTC (rev 693)
@@ -497,7 +497,7 @@
 	if (AbsPathWithUnicode.size() == 0)
 	{
 		// error already logged by ConvertPathToAbsoluteUnicode()
-		return NULL;
+		return INVALID_HANDLE_VALUE;
 	}
 	
 	WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str());
@@ -506,7 +506,7 @@
 	if (pBuffer == NULL)
 	{
 		// error already logged by ConvertUtf8ToWideString()
-		return NULL;
+		return INVALID_HANDLE_VALUE;
 	}
 
 	// flags could be O_WRONLY | O_CREAT | O_RDONLY
@@ -553,7 +553,7 @@
 	{
 		::syslog(LOG_WARNING, "Failed to open file %s: "
 			"error %i", pFileName, GetLastError());
-		return NULL;
+		return INVALID_HANDLE_VALUE;
 	}
 
 	return hdir;
@@ -641,11 +641,11 @@
 	// all objects get user read (0400)
 	// if it's a directory it gets user execute (0100)
 	// if it's not read-only it gets user write (0200)
-	st->st_mode = 0400;
+	st->st_mode = S_IREAD;
 
 	if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 	{
-		st->st_mode |= S_IFDIR | 0100;
+		st->st_mode |= S_IFDIR | S_IEXEC;
 	}
 	else
 	{
@@ -654,7 +654,7 @@
 
 	if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
 	{
-		st->st_mode |= 0200;
+		st->st_mode |= S_IWRITE;
 	}
 
 	return 0;
@@ -815,9 +815,11 @@
 // --------------------------------------------------------------------------
 //
 // Function
-//		Name:    emu_fstat
-//		Purpose: replacement for fstat supply a windows handle
-//		Created: 25th October 2004
+//		Name:    emu_utimes
+//		Purpose: replacement for the POSIX utimes() function,
+//			works with unicode filenames supplied in utf8 format,
+//			sets creation time instead of last access time.
+//		Created: 25th July 2006
 //
 // --------------------------------------------------------------------------
 int emu_utimes(const char * pName, const struct timeval times[])
@@ -859,6 +861,69 @@
 // --------------------------------------------------------------------------
 //
 // Function
+//		Name:    emu_chmod
+//		Purpose: replacement for the POSIX chmod function,
+//			works with unicode filenames supplied in utf8 format
+//		Created: 26th July 2006
+//
+// --------------------------------------------------------------------------
+int emu_chmod(const char * pName, mode_t mode)
+{
+	std::string AbsPathWithUnicode = 
+		ConvertPathToAbsoluteUnicode(pName);
+	
+	if (AbsPathWithUnicode.size() == 0)
+	{
+		// error already logged by ConvertPathToAbsoluteUnicode()
+		return -1;
+	}
+	
+	WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str());
+	// We are responsible for freeing pBuffer
+	
+	if (pBuffer == NULL)
+	{
+		// error already logged by ConvertUtf8ToWideString()
+		free(pBuffer);
+		return -1;
+	}
+
+	DWORD attribs = GetFileAttributesW(pBuffer);
+	if (attribs == INVALID_FILE_ATTRIBUTES)
+	{
+		::syslog(LOG_ERR, "Failed to get file attributes of '%s': "
+			"error %d", pName, GetLastError());
+		errno = EACCES;
+		free(pBuffer);
+		return -1;
+	}
+
+	if (mode & S_IWRITE)
+	{
+		attribs &= ~FILE_ATTRIBUTE_READONLY;
+	}
+	else
+	{
+		attribs |= FILE_ATTRIBUTE_READONLY;
+	}
+
+	if (!SetFileAttributesW(pBuffer, attribs))
+	{
+		::syslog(LOG_ERR, "Failed to set file attributes of '%s': "
+			"error %d", pName, GetLastError());
+		errno = EACCES;
+		free(pBuffer);
+		return -1;
+	}
+
+	free(pBuffer);
+	return 0;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
 //		Name:    opendir
 //		Purpose: replacement for unix function, uses win32 findfirst routines
 //		Created: 25th October 2004
@@ -1548,4 +1613,60 @@
 	return bytes;
 }
 
+// need this for conversions
+time_t ConvertFileTimeToTime_t(FILETIME *fileTime)
+{
+	SYSTEMTIME stUTC;
+	struct tm timeinfo;
+
+	// Convert the last-write time to local time.
+	FileTimeToSystemTime(fileTime, &stUTC);
+
+	memset(&timeinfo, 0, sizeof(timeinfo));	
+	timeinfo.tm_sec = stUTC.wSecond;
+	timeinfo.tm_min = stUTC.wMinute;
+	timeinfo.tm_hour = stUTC.wHour;
+	timeinfo.tm_mday = stUTC.wDay;
+	timeinfo.tm_wday = stUTC.wDayOfWeek;
+	timeinfo.tm_mon = stUTC.wMonth - 1;
+	// timeinfo.tm_yday = ...;
+	timeinfo.tm_year = stUTC.wYear - 1900;
+
+	time_t retVal = mktime(&timeinfo) - _timezone;
+	return retVal;
+}
+
+bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo)
+{
+	time_t adjusted = from + _timezone;
+	struct tm *time_breakdown = gmtime(&adjusted);
+	if (time_breakdown == NULL)
+	{
+		::syslog(LOG_ERR, "Error: failed to convert time format: "
+			"%d is not a valid time\n", from);
+		return false;
+	}
+
+	SYSTEMTIME stUTC;
+	stUTC.wSecond       = time_breakdown->tm_sec;
+	stUTC.wMinute       = time_breakdown->tm_min;
+	stUTC.wHour         = time_breakdown->tm_hour;
+	stUTC.wDay          = time_breakdown->tm_mday;
+	stUTC.wDayOfWeek    = time_breakdown->tm_wday;
+	stUTC.wMonth        = time_breakdown->tm_mon  + 1;
+	stUTC.wYear         = time_breakdown->tm_year + 1900;
+	stUTC.wMilliseconds = 0;
+
+	// Convert the last-write time to local time.
+	if (!SystemTimeToFileTime(&stUTC, pTo))
+	{
+		syslog(LOG_ERR, "Failed to convert between time formats: "
+			"error %d", GetLastError());
+		return false;
+	}
+
+	return true;
+}
+
+
 #endif // WIN32

Modified: box/chris/general/lib/win32/emu.h
===================================================================
--- box/chris/general/lib/win32/emu.h	2006-07-26 19:10:10 UTC (rev 692)
+++ box/chris/general/lib/win32/emu.h	2006-07-26 23:11:39 UTC (rev 693)
@@ -112,25 +112,19 @@
 int   emu_unlink(const char* pFileName);
 char* emu_getcwd(char* pBuffer, int BufSize);
 int   emu_utimes(const char* pName, const struct timeval[]);
+int   emu_chmod (const char* pName, mode_t mode);
 
 #define utimes(buffer, times) emu_utimes(buffer, times)
 
 #ifdef _MSC_VER
-	inline int emu_chmod(const char * Filename, int mode)
-	{
-		// indicate success
-		return 0;
-	}
-
 	#define chmod(file, mode)     emu_chmod(file, mode)
 	#define chdir(directory)      emu_chdir(directory)
 	#define unlink(file)          emu_unlink(file)
 	#define getcwd(buffer, size)  emu_getcwd(buffer, size)
 #else
-	inline int chmod(const char * Filename, int mode)
+	inline int chmod(const char * pName, mode_t mode)
 	{
-		// indicate success
-		return 0;
+		return emu_chmod(pName, mode);
 	}
 
 	inline int chdir(const char* pDirName)
@@ -325,60 +319,9 @@
 int statfs(const char * name, struct statfs * s);
 
 // need this for conversions
-inline time_t ConvertFileTimeToTime_t(FILETIME *fileTime)
-{
-	SYSTEMTIME stUTC;
-	struct tm timeinfo;
+time_t ConvertFileTimeToTime_t(FILETIME *fileTime);
+bool   ConvertTime_tToFileTime(const time_t from, FILETIME *pTo);
 
-	// Convert the last-write time to local time.
-	FileTimeToSystemTime(fileTime, &stUTC);
-
-	memset(&timeinfo, 0, sizeof(timeinfo));	
-	timeinfo.tm_sec = stUTC.wSecond;
-	timeinfo.tm_min = stUTC.wMinute;
-	timeinfo.tm_hour = stUTC.wHour;
-	timeinfo.tm_mday = stUTC.wDay;
-	timeinfo.tm_wday = stUTC.wDayOfWeek;
-	timeinfo.tm_mon = stUTC.wMonth - 1;
-	// timeinfo.tm_yday = ...;
-	timeinfo.tm_year = stUTC.wYear - 1900;
-
-	time_t retVal = mktime(&timeinfo) - _timezone;
-	return retVal;
-}
-
-inline bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo)
-{
-	time_t adjusted = from + _timezone;
-	struct tm *time_breakdown = gmtime(&adjusted);
-	if (time_breakdown == NULL)
-	{
-		::syslog(LOG_ERR, "Error: failed to convert time format: "
-			"%d is not a valid time\n", from);
-		return false;
-	}
-
-	SYSTEMTIME stUTC;
-	stUTC.wSecond       = time_breakdown->tm_sec;
-	stUTC.wMinute       = time_breakdown->tm_min;
-	stUTC.wHour         = time_breakdown->tm_hour;
-	stUTC.wDay          = time_breakdown->tm_mday;
-	stUTC.wDayOfWeek    = time_breakdown->tm_wday;
-	stUTC.wMonth        = time_breakdown->tm_mon  + 1;
-	stUTC.wYear         = time_breakdown->tm_year + 1900;
-	stUTC.wMilliseconds = 0;
-
-	// Convert the last-write time to local time.
-	if (!SystemTimeToFileTime(&stUTC, pTo))
-	{
-		syslog(LOG_ERR, "Failed to convert between time formats: "
-			"error %d", GetLastError());
-		return false;
-	}
-
-	return true;
-}
-
 #ifdef _MSC_VER
 	#define stat(filename,  struct) emu_stat (filename, struct)
 	#define lstat(filename, struct) emu_stat (filename, struct)

Modified: box/chris/general/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-26 19:10:10 UTC (rev 692)
+++ box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-26 23:11:39 UTC (rev 693)
@@ -68,7 +68,7 @@
 {
 	#ifdef WIN32
 	HANDLE handle = openfile(filename, O_WRONLY | O_CREAT | O_EXCL, 0);
-	TEST_THAT(handle != NULL);
+	TEST_THAT(handle != INVALID_HANDLE_VALUE);
 	SetFilePointer(handle, size, NULL, FILE_BEGIN);
 	TEST_THAT(GetLastError() == NO_ERROR);
 	TEST_THAT(SetEndOfFile(handle) == true);

Modified: box/chris/general/test/backupstore/testbackupstore.cpp
===================================================================
--- box/chris/general/test/backupstore/testbackupstore.cpp	2006-07-26 19:10:10 UTC (rev 692)
+++ box/chris/general/test/backupstore/testbackupstore.cpp	2006-07-26 23:11:39 UTC (rev 693)
@@ -1966,11 +1966,9 @@
 	CloseHandle(h1);
 
 	h1 = openfile("foo", O_CREAT | O_RDWR, 0);
-	assert(h1);
-	TEST_THAT(h1);
+	TEST_THAT(h1 != INVALID_HANDLE_VALUE);
 	h2 = openfile("foo", O_RDWR, 0);
-	assert(h2);
-	TEST_THAT(h2);
+	TEST_THAT(h2 != INVALID_HANDLE_VALUE);
 	CloseHandle(h2);
 	CloseHandle(h1);
 #endif


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 00:13:15 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 23:13:15 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r694 - box/chris/general/test/bbackupd
Message-ID: <20060726231315.B5E9796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 23:13:14 +0000 (Wed, 26 Jul 2006)
New Revision: 694

Modified:
   box/chris/general/test/bbackupd/testbbackupd.cpp
Log:
* testbbackupd.cpp
- Added tests for comparing restored file attributes on Win32
- Re-enabled existing file attribute tests
- Deal appropriately with openfile() returning INVALID_HANDLE_VALUE


Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-26 23:11:39 UTC (rev 693)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2006-07-26 23:13:14 UTC (rev 694)
@@ -560,6 +560,21 @@
 	TestRemoteProcessMemLeaks("bbackupctl.memleaks");
 }
 
+bool set_file_time(const char* filename, FILETIME creationTime, 
+	FILETIME lastModTime, FILETIME lastAccessTime)
+{
+	HANDLE handle = openfile(filename, O_RDWR, 0);
+	TEST_THAT(handle != INVALID_HANDLE_VALUE);
+	if (handle == INVALID_HANDLE_VALUE) return false;
+		
+	BOOL success = SetFileTime(handle, &creationTime, &lastAccessTime,
+		&lastModTime);
+	TEST_THAT(success);
+
+	TEST_THAT(CloseHandle(handle));
+	return success;
+}
+
 int test_bbackupd()
 {
 //	// First, wait for a normal period to make sure the last changes attributes are within a normal backup timeframe.
@@ -985,16 +1000,92 @@
 		// Compare the restored files
 		compareReturnValue = ::system(BBACKUPQUERY " -q "
 			"-c testfiles/bbackupd.conf -l testfiles/query10.log "
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+			"quit");
+		TEST_RETURN(compareReturnValue, 1);
+		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+		
 		#ifdef WIN32
-			"\"compare -cAE Test1 testfiles/restore-Test1\" "
-		#else
+		// make one of the files read-only, expect a compare failure
+		compareReturnValue = ::system("attrib +r "
+			"testfiles\\restore-Test1\\f1.dat");
+		TEST_RETURN(compareReturnValue, 0);
+
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10a.log "
 			"\"compare -cE Test1 testfiles/restore-Test1\" "
-		#endif
 			"quit");
+		TEST_RETURN(compareReturnValue, 2);
+		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+	
+		// set it back, expect no failures
+		compareReturnValue = ::system("attrib -r "
+			"testfiles\\restore-Test1\\f1.dat");
+		TEST_RETURN(compareReturnValue, 0);
 
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10a.log "
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+			"quit");
 		TEST_RETURN(compareReturnValue, 1);
 		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
 
+		// change the timestamp on a file, expect a compare failure
+		char* testfile = "testfiles\\restore-Test1\\f1.dat";
+		HANDLE handle = openfile(testfile, O_RDWR, 0);
+		TEST_THAT(handle != INVALID_HANDLE_VALUE);
+		
+		FILETIME creationTime, lastModTime, lastAccessTime;
+		TEST_THAT(GetFileTime(handle, &creationTime, &lastAccessTime, 
+			&lastModTime) != 0);
+		TEST_THAT(CloseHandle(handle));
+
+		FILETIME dummyTime = lastModTime;
+		dummyTime.dwHighDateTime -= 100;
+
+		// creation time is backed up, so changing it should cause
+		// a compare failure
+		TEST_THAT(set_file_time(testfile, dummyTime, lastModTime,
+			lastAccessTime));
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10a.log "
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+			"quit");
+		TEST_RETURN(compareReturnValue, 2);
+		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+		// last access time is not backed up, so it cannot be compared
+		TEST_THAT(set_file_time(testfile, creationTime, lastModTime,
+			dummyTime));
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10a.log "
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+			"quit");
+		TEST_RETURN(compareReturnValue, 1);
+		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+		// last write time is backed up, so changing it should cause
+		// a compare failure
+		TEST_THAT(set_file_time(testfile, creationTime, dummyTime,
+			lastAccessTime));
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10a.log "
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+			"quit");
+		TEST_RETURN(compareReturnValue, 2);
+		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+		// set back to original values, check that compare succeeds
+		TEST_THAT(set_file_time(testfile, creationTime, lastModTime,
+			lastAccessTime));
+		compareReturnValue = ::system(BBACKUPQUERY " -q "
+			"-c testfiles/bbackupd.conf -l testfiles/query10a.log "
+			"\"compare -cE Test1 testfiles/restore-Test1\" "
+			"quit");
+		TEST_RETURN(compareReturnValue, 1);
+		TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+		#endif
+
 		printf("Add files with current time\n");
 	
 		// Add some more files and modify others
@@ -1164,13 +1255,7 @@
 			compareReturnValue = ::system(BBACKUPQUERY 
 				" -q -c testfiles/bbackupd.conf "
 				"-l testfiles/query11.log "
-				"\"compare "
-			#ifdef WIN32
-				// cannot restore attributes, so don't compare
-				"-cAE "
-			#else
-				"-cE "
-			#endif
+				"\"compare -cE "
 				"Test1/x1 testfiles/restore-Test1-x1-2\" quit");
 			TEST_RETURN(compareReturnValue, 1);
 			TestRemoteProcessMemLeaks("bbackupquery.memleaks");
@@ -1189,9 +1274,9 @@
 		wait_for_sync();
 		// Now we have about three seconds to work
 
-		HANDLE handle = openfile("testfiles/TestDir1/lockedfile",
+		handle = openfile("testfiles/TestDir1/lockedfile",
 			O_CREAT | O_EXCL, 0);
-		TEST_THAT(handle != 0);
+		TEST_THAT(handle != INVALID_HANDLE_VALUE);
 
 		if (handle != 0)
 		{
@@ -1224,7 +1309,7 @@
 			// reports the correct error message (and finishes)
 			handle = openfile("testfiles/TestDir1/lockedfile",
 				O_CREAT | O_EXCL, 0);
-			TEST_THAT(handle != 0);
+			TEST_THAT(handle != INVALID_HANDLE_VALUE);
 
 			compareReturnValue = ::system(BBACKUPQUERY 
 				" -q -c testfiles/bbackupd.conf "


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 00:13:54 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 23:13:54 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r695 - box/chris/general/lib/backupclient
Message-ID: <20060726231354.C7CDC96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 23:13:52 +0000 (Wed, 26 Jul 2006)
New Revision: 695

Modified:
   box/chris/general/lib/backupclient/BackupStoreFile.cpp
Log:
* BackupStoreFile.cpp
- Close the file before setting attributes on it during restore, since
  closing it changes the last modified time attribute


Modified: box/chris/general/lib/backupclient/BackupStoreFile.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupStoreFile.cpp	2006-07-26 23:13:14 UTC (rev 694)
+++ box/chris/general/lib/backupclient/BackupStoreFile.cpp	2006-07-26 23:13:52 UTC (rev 695)
@@ -289,6 +289,8 @@
 			// Copy it out to the file
 			stream->CopyStreamTo(out);
 		}
+
+		out.Close();
 		
 		// Write the attributes
 		stream->GetAttributes().WriteAttributes(DecodedFilename);


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 00:14:16 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 23:14:16 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r696 - box/chris/general/lib/server
Message-ID: <20060726231416.5447796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 23:14:15 +0000 (Wed, 26 Jul 2006)
New Revision: 696

Modified:
   box/chris/general/lib/server/WinNamedPipeStream.cpp
Log:
* WinNamedPipeStream.cpp
- Fixed a compiler warning about comparing signed and unsigned values


Modified: box/chris/general/lib/server/WinNamedPipeStream.cpp
===================================================================
--- box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-26 23:13:52 UTC (rev 695)
+++ box/chris/general/lib/server/WinNamedPipeStream.cpp	2006-07-26 23:14:15 UTC (rev 696)
@@ -218,6 +218,12 @@
 		THROW_EXCEPTION(ConnectionException, SocketShutdownError)
 	}
 
+	// ensure safe to cast NBytes to unsigned
+	if (NBytes < 0)
+	{
+		THROW_EXCEPTION(CommonException, AssertFailed)
+	}
+
 	DWORD NumBytesRead;
 
 	if (mIsServer)
@@ -272,7 +278,7 @@
 		size_t BytesToCopy = NumBytesRead + mBytesInBuffer;
 		size_t BytesRemaining = 0;
 
-		if (BytesToCopy > NBytes)
+		if (BytesToCopy > (size_t)NBytes)
 		{
 			BytesRemaining = BytesToCopy - NBytes;
 			BytesToCopy = NBytes;


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 00:15:04 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Wed, 26 Jul 2006 23:15:04 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r697 - box/chris/general/bin/bbackupquery
Message-ID: <20060726231504.7909596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-26 23:15:01 +0000 (Wed, 26 Jul 2006)
New Revision: 697

Modified:
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
Log:
* BackupQueries.cpp
- Compare the attribute modification time (really the creation time)
  when comparing under Win32
- Fixed a compiler warning about comparing signed and unsigned values


Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-26 23:14:15 UTC (rev 696)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-26 23:15:01 UTC (rev 697)
@@ -897,7 +897,7 @@
 		if(!opts['i'])
 		{
 			// does this remote filename include a path?
-			int index = fileName.rfind('/');
+			std::string::size_type index = fileName.rfind('/');
 			if(index != std::string::npos)
 			{
 				std::string dirName(fileName.substr(0, index));
@@ -1550,9 +1550,17 @@
 						BackupClientFileAttributes localAttr;
 						localAttr.ReadAttributes(localPath.c_str(), false /* don't zero mod times */, &fileModTime);					
 						modifiedAfterLastSync = (fileModTime > rParams.mLatestFileUploadTime);
+						bool ignoreAttrModTime = true;
+
+						#ifdef WIN32
+						// attr mod time is really
+						// creation time, so check it
+						ignoreAttrModTime = false;
+						#endif
+
 						if(!rParams.mIgnoreAttributes &&
 						   !localAttr.Compare(fileOnServerStream->GetAttributes(),
-								true /* ignore attr mod time */,
+								ignoreAttrModTime,
 								fileOnServerStream->IsSymLink() /* ignore modification time if it's a symlink */))
 						{
 							printf("Local file '%s' "


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 21:35:21 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 20:35:21 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r698 - box/chris/general/bin/bbackupquery
Message-ID: <20060727203521.5303C96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 20:35:18 +0000 (Thu, 27 Jul 2006)
New Revision: 698

Modified:
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
Log:
* BackupQueries.cpp
- Restore_TargetPathNotFound should only be used on Win32


Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-26 23:15:01 UTC (rev 697)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-27 20:35:18 UTC (rev 698)
@@ -1895,11 +1895,13 @@
 		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");


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:22:38 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:22:38 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r699 - box/chris/general/test/backupstore/testfiles
Message-ID: <20060727222238.4377396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:22:36 +0000 (Thu, 27 Jul 2006)
New Revision: 699

Modified:
   box/chris/general/test/backupstore/testfiles/bbstored.conf
   box/chris/general/test/backupstore/testfiles/bbstored_multi.conf
   box/chris/general/test/backupstore/testfiles/query.conf
   box/chris/general/test/backupstore/testfiles/raidfile.conf
Log:
* bbstored.conf query.conf bbstored_multi.conf raidfile.conf
- Revert to UNIX paths, which should now work under Win32


Modified: box/chris/general/test/backupstore/testfiles/bbstored.conf
===================================================================
--- box/chris/general/test/backupstore/testfiles/bbstored.conf	2006-07-27 20:35:18 UTC (rev 698)
+++ box/chris/general/test/backupstore/testfiles/bbstored.conf	2006-07-27 22:22:36 UTC (rev 699)
@@ -1,6 +1,6 @@
 
-RaidFileConf = testfiles\raidfile.conf
-AccountDatabase = testfiles\accounts.txt
+RaidFileConf = testfiles/raidfile.conf
+AccountDatabase = testfiles/accounts.txt
 
 ExtendedLogging = yes
 
@@ -8,10 +8,10 @@
 
 Server
 {
-	PidFile = testfiles\bbstored.pid
+	PidFile = testfiles/bbstored.pid
 	ListenAddresses = inet:localhost
-	CertificateFile = testfiles\serverCerts.pem
-	PrivateKeyFile = testfiles\serverPrivKey.pem
-	TrustedCAsFile = testfiles\serverTrustedCAs.pem
+	CertificateFile = testfiles/serverCerts.pem
+	PrivateKeyFile = testfiles/serverPrivKey.pem
+	TrustedCAsFile = testfiles/serverTrustedCAs.pem
 }
 

Modified: box/chris/general/test/backupstore/testfiles/bbstored_multi.conf
===================================================================
--- box/chris/general/test/backupstore/testfiles/bbstored_multi.conf	2006-07-27 20:35:18 UTC (rev 698)
+++ box/chris/general/test/backupstore/testfiles/bbstored_multi.conf	2006-07-27 22:22:36 UTC (rev 699)
@@ -1,16 +1,16 @@
 
-RaidFileConf = testfiles\raidfile.conf
-AccountDatabase = testfiles\accounts.txt
+RaidFileConf = testfiles/raidfile.conf
+AccountDatabase = testfiles/accounts.txt
 
 TimeBetweenHousekeeping = 5
 
 Server
 {
-	PidFile = testfiles\bbstored.pid
+	PidFile = testfiles/bbstored.pid
 	# 0.0.0.0 is the 'any' address, allowing connections from things other than localhost
 	ListenAddresses = inet:0.0.0.0
-	CertificateFile = testfiles\serverCerts.pem
-	PrivateKeyFile = testfiles\serverPrivKey.pem
-	TrustedCAsFile = testfiles\serverTrustedCAs.pem
+	CertificateFile = testfiles/serverCerts.pem
+	PrivateKeyFile = testfiles/serverPrivKey.pem
+	TrustedCAsFile = testfiles/serverTrustedCAs.pem
 }
 

Modified: box/chris/general/test/backupstore/testfiles/query.conf
===================================================================
--- box/chris/general/test/backupstore/testfiles/query.conf	2006-07-27 20:35:18 UTC (rev 698)
+++ box/chris/general/test/backupstore/testfiles/query.conf	2006-07-27 22:22:36 UTC (rev 699)
@@ -2,13 +2,13 @@
 # this is a dummy config file so that bbackupquery can be used
 
 
-CertificateFile = testfiles\clientCerts.pem
-PrivateKeyFile = testfiles\clientPrivKey.pem
-TrustedCAsFile = testfiles\clientTrustedCAs.pem
+CertificateFile = testfiles/clientCerts.pem
+PrivateKeyFile = testfiles/clientPrivKey.pem
+TrustedCAsFile = testfiles/clientTrustedCAs.pem
 
-KeysFile = testfiles\bbackupd.keys
+KeysFile = testfiles/bbackupd.keys
 
-DataDirectory = testfiles\bbackupd-data
+DataDirectory = testfiles/bbackupd-data
 
 StoreHostname = localhost
 AccountNumber = 0x01234567
@@ -20,7 +20,7 @@
 
 Server
 {
-	PidFile = testfiles\bbackupd.pid
+	PidFile = testfiles/bbackupd.pid
 }
 
 # this is just a dummy entry
@@ -28,7 +28,7 @@
 {
 	test_delete
 	{
-		Path = testfiles\test_delete
+		Path = testfiles/test_delete
 	}
 }
 

Modified: box/chris/general/test/backupstore/testfiles/raidfile.conf
===================================================================
--- box/chris/general/test/backupstore/testfiles/raidfile.conf	2006-07-27 20:35:18 UTC (rev 698)
+++ box/chris/general/test/backupstore/testfiles/raidfile.conf	2006-07-27 22:22:36 UTC (rev 699)
@@ -3,8 +3,8 @@
 {
 	SetNumber = 0
 	BlockSize = 2048
-	Dir0 = testfiles\0_0
-	Dir1 = testfiles\0_1
-	Dir2 = testfiles\0_2
+	Dir0 = testfiles/0_0
+	Dir1 = testfiles/0_1
+	Dir2 = testfiles/0_2
 }
 


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:25:05 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:25:05 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r700 - box/chris/general/test/raidfile/testfiles
Message-ID: <20060727222505.9C64F96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:25:04 +0000 (Thu, 27 Jul 2006)
New Revision: 700

Modified:
   box/chris/general/test/raidfile/testfiles/raidfile.conf
Log:
* raidfile.conf
- Revert to UNIX paths, which should now work


Modified: box/chris/general/test/raidfile/testfiles/raidfile.conf
===================================================================
--- box/chris/general/test/raidfile/testfiles/raidfile.conf	2006-07-27 22:22:36 UTC (rev 699)
+++ box/chris/general/test/raidfile/testfiles/raidfile.conf	2006-07-27 22:25:04 UTC (rev 700)
@@ -3,28 +3,27 @@
 {
 	SetNumber = 0
 	BlockSize = 2048
-	Dir0 = testfiles\0_0
-	Dir1 = testfiles\0_1
-	Dir2 = testfiles\0_2
-	# this will break tests on Unix! Fix me!
+	Dir0 = testfiles/0_0
+	Dir1 = testfiles/0_1
+	Dir2 = testfiles/0_2
 }
 
 disc1
 {
 	SetNumber = 1
 	BlockSize = 2048
-	Dir0 = testfiles\1_0
-	Dir1 = testfiles\1_1
-	Dir2 = testfiles\1_2
+	Dir0 = testfiles/1_0
+	Dir1 = testfiles/1_1
+	Dir2 = testfiles/1_2
 }
 
 disc2
 {
 	SetNumber = 2
 	BlockSize = 2048
-	Dir0 = testfiles\2
-	Dir1 = testfiles\2
-	Dir2 = testfiles\2
+	Dir0 = testfiles/2
+	Dir1 = testfiles/2
+	Dir2 = testfiles/2
 }
 
 


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:26:26 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:26:26 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r701 - in box/chris/general: bin/bbstored lib/raidfile test/backupstore
Message-ID: <20060727222626.A853796@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:26:25 +0000 (Thu, 27 Jul 2006)
New Revision: 701

Modified:
   box/chris/general/bin/bbstored/BackupContext.cpp
   box/chris/general/lib/raidfile/RaidFileWrite.cpp
   box/chris/general/test/backupstore/testbackupstore.cpp
Log:
* test/backupstore/testbackupstore.cpp
* lib/raidfile/RaidFileWrite.cpp
* bin/bbstored/BackupContext.cpp
- Cosmetic spacing fixes, to reduce diff between trunk and general


Modified: box/chris/general/bin/bbstored/BackupContext.cpp
===================================================================
--- box/chris/general/bin/bbstored/BackupContext.cpp	2006-07-27 22:25:04 UTC (rev 700)
+++ box/chris/general/bin/bbstored/BackupContext.cpp	2006-07-27 22:26:25 UTC (rev 701)
@@ -527,7 +527,7 @@
 			}
 #endif
 		}
-
+		
 		// Get the blocks used
 		blocksUsed = storeFile.GetDiscUsageInBlocks();
 		

Modified: box/chris/general/lib/raidfile/RaidFileWrite.cpp
===================================================================
--- box/chris/general/lib/raidfile/RaidFileWrite.cpp	2006-07-27 22:25:04 UTC (rev 700)
+++ box/chris/general/lib/raidfile/RaidFileWrite.cpp	2006-07-27 22:26:25 UTC (rev 701)
@@ -277,7 +277,7 @@
 	{
 		THROW_EXCEPTION(RaidFileException, OSError)
 	}
-
+	
 #ifndef WIN32	
 	// Close file...
 	if(::close(mOSFileHandle) != 0)
@@ -331,7 +331,7 @@
 	{
 		THROW_EXCEPTION(RaidFileException, OSError)
 	}
-
+	
 	// reset file handle
 	mOSFileHandle = -1;
 }

Modified: box/chris/general/test/backupstore/testbackupstore.cpp
===================================================================
--- box/chris/general/test/backupstore/testbackupstore.cpp	2006-07-27 22:25:04 UTC (rev 700)
+++ box/chris/general/test/backupstore/testbackupstore.cpp	2006-07-27 22:26:25 UTC (rev 701)
@@ -1630,7 +1630,7 @@
 
 			TEST_THAT(decoded->GetNumBlocks() == 3);
 		}
-
+		
 #ifndef WIN32		
 		// Try out doing this on a symlink
 		{


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:26:50 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:26:50 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r702 - box/chris/general/test/backupdiff
Message-ID: <20060727222650.8A78D96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:26:49 +0000 (Thu, 27 Jul 2006)
New Revision: 702

Modified:
   box/chris/general/test/backupdiff/testbackupdiff.cpp
Log:
* testbackupdiff.cpp
- Revert to old timing under Unix


Modified: box/chris/general/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-27 22:26:25 UTC (rev 701)
+++ box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-27 22:26:49 UTC (rev 702)
@@ -473,7 +473,7 @@
 			TEST_THAT(files_identical("testfiles/f9", "testfiles/f9.testdec.zero"));
 		}
 	}
-
+	
 #ifndef WIN32	
 	// Check that symlinks aren't diffed
 	TEST_THAT(::symlink("f2", "testfiles/f2.symlink") == 0)
@@ -555,7 +555,7 @@
 		#ifdef WIN32
 		TEST_THAT(time(0) < (beginTime + 300));
 		#else
-		TEST_THAT(time(0) < (beginTime + 20));
+		TEST_THAT(time(0) < (beginTime + 40));
 		#endif
 	}
 	// Remove zero-files to save disk space


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:27:16 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:27:16 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r703 - box/chris/general/infrastructure
Message-ID: <20060727222716.2039196@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:27:15 +0000 (Thu, 27 Jul 2006)
New Revision: 703

Modified:
   box/chris/general/infrastructure/BoxPlatform.pm.in
Log:
* BoxPlatform.pm.in
- Change diff type back to brief, since unified output is too verbose


Modified: box/chris/general/infrastructure/BoxPlatform.pm.in
===================================================================
--- box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-27 22:26:49 UTC (rev 702)
+++ box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-27 22:27:15 UTC (rev 703)
@@ -118,7 +118,7 @@
 	if (-r $file)
 	{
 		die "$file.new: not found" unless -r "$file.new";
-		if (system("diff -u $file $file.new") == 0)
+		if (system("diff --brief $file $file.new") == 0)
 		{
 			unlink "$file.new";
 			return;


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:27:34 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:27:34 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r704 - box/chris/general
Message-ID: <20060727222734.32BE396@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:27:33 +0000 (Thu, 27 Jul 2006)
New Revision: 704

Modified:
   box/chris/general/configure.ac
Log:
* configure.ac
- Check whether system headers define O_BINARY


Modified: box/chris/general/configure.ac
===================================================================
--- box/chris/general/configure.ac	2006-07-27 22:27:15 UTC (rev 703)
+++ box/chris/general/configure.ac	2006-07-27 22:27:33 UTC (rev 704)
@@ -135,6 +135,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


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:28:22 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:28:22 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r705 - box/chris/general/lib/server
Message-ID: <20060727222822.8150596@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:28:21 +0000 (Thu, 27 Jul 2006)
New Revision: 705

Modified:
   box/chris/general/lib/server/ServerStream.h
Log:
* ServerStream.h
- Don't define the OnIdle() method except under Windows
- Cosmetic indenting fixes


Modified: box/chris/general/lib/server/ServerStream.h
===================================================================
--- box/chris/general/lib/server/ServerStream.h	2006-07-27 22:27:33 UTC (rev 704)
+++ box/chris/general/lib/server/ServerStream.h	2006-07-27 22:28:21 UTC (rev 705)
@@ -56,7 +56,9 @@
 		return "generic-stream-server";
 	}
 
+	#ifdef WIN32
 	virtual void OnIdle() { }
+	#endif
 
 	virtual void Run()
 	{
@@ -217,7 +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
+						#ifndef WIN32 // no fork on Win32
 						if(ForkToHandleRequests)
 						{
 							pid_t pid = ::fork();
@@ -258,20 +260,20 @@
 						}
 						else
 						{
-#endif // !WIN32
+						#endif // !WIN32
 							// Just handle in this connection
 							SetProcessTitle("handling");
 							HandleConnection(*connection);
 							SetProcessTitle("idle");										
-#ifndef WIN32
+						#ifndef WIN32
 						}
-#endif // !WIN32
+						#endif // !WIN32
 					}
 				}
 
-#ifdef WIN32
+				#ifdef WIN32
 				OnIdle();
-#else // !WIN32
+				#else // !WIN32
 				// Clean up child processes (if forking daemon)
 				if(ForkToHandleRequests)
 				{
@@ -286,7 +288,7 @@
 						}
 					} while(p > 0);
 				}
-#endif // !WIN32
+				#endif // !WIN32
 			}
 		}
 		catch(...)
@@ -311,11 +313,11 @@
 	// depends on the forking model in case someone changes it later.
 	bool WillForkToHandleRequests()
 	{
-#ifdef WIN32
+		#ifdef WIN32
 		return false;
-#else
+		#else
 		return ForkToHandleRequests;
-#endif // WIN32
+		#endif // WIN32
 	}
 
 private:


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:29:32 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:29:32 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r706 - box/chris/general/lib/common
Message-ID: <20060727222932.57CAC96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:29:31 +0000 (Thu, 27 Jul 2006)
New Revision: 706

Modified:
   box/chris/general/lib/common/BoxPlatform.h
Log:
* BoxPlatform.h
- If the platform does not define O_BINARY, we define it ourselves to
  something harmless
- Improved comment about disabling intercepts on Windows


Modified: box/chris/general/lib/common/BoxPlatform.h
===================================================================
--- box/chris/general/lib/common/BoxPlatform.h	2006-07-27 22:28:21 UTC (rev 705)
+++ box/chris/general/lib/common/BoxPlatform.h	2006-07-27 22:29:31 UTC (rev 706)
@@ -45,7 +45,7 @@
 	#endif
 #endif
 
-// Slight hack; disable interception on Darwin within raidfile test
+// 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
@@ -143,6 +143,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


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:40:29 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:40:29 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r707 - box/chris/general/lib/raidfile
Message-ID: <20060727224029.8055D96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:40:28 +0000 (Thu, 27 Jul 2006)
New Revision: 707

Modified:
   box/chris/general/lib/raidfile/RaidFileWrite.cpp
Log:
* RaidFileWrite.cpp
- Unix compile fix


Modified: box/chris/general/lib/raidfile/RaidFileWrite.cpp
===================================================================
--- box/chris/general/lib/raidfile/RaidFileWrite.cpp	2006-07-27 22:29:31 UTC (rev 706)
+++ box/chris/general/lib/raidfile/RaidFileWrite.cpp	2006-07-27 22:40:28 UTC (rev 707)
@@ -326,7 +326,7 @@
 		::unlink(writeFilename.c_str()) != 0)
 #else // !WIN32
 	if (::unlink(writeFilename.c_str()) != 0 ||
-		::close(mOSFileHandle) != 0))
+		::close(mOSFileHandle) != 0)
 #endif // !WIN32
 	{
 		THROW_EXCEPTION(RaidFileException, OSError)


From boxbackup-dev@fluffy.co.uk  Thu Jul 27 23:59:43 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 22:59:43 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r708 - box/chris/general/test/backupdiff
Message-ID: <20060727225943.5C81B96@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 22:59:41 +0000 (Thu, 27 Jul 2006)
New Revision: 708

Modified:
   box/chris/general/test/backupdiff/testbackupdiff.cpp
Log:
* testbackupdiff.cpp
- Fixed truncate on Unix to properly create file of zeroes


Modified: box/chris/general/test/backupdiff/testbackupdiff.cpp
===================================================================
--- box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-27 22:40:28 UTC (rev 707)
+++ box/chris/general/test/backupdiff/testbackupdiff.cpp	2006-07-27 22:59:41 UTC (rev 708)
@@ -74,29 +74,13 @@
 	TEST_THAT(SetEndOfFile(handle) == true);
 	TEST_THAT(CloseHandle(handle)  == true);
 	#else
-	TEST_THAT(truncate(filename, size) == 0);
+	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
 
-	/*
-	static const size_t bs = 0x10000;
-	size_t remSize = size;
-	void *b = malloc(bs);
-	memset(b, 0, bs);
-	FILE *f = fopen(filename, "wb");
-	TEST_THAT(f != NULL);
-
-	// 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);
 }
 


From boxbackup-dev@fluffy.co.uk  Fri Jul 28 00:15:10 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 23:15:10 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r709 - box/chris
Message-ID: <20060727231510.C928896@s0g0.pems.testserver.co.uk>

Author: chris
Date: 2006-07-27 23:15:09 +0000 (Thu, 27 Jul 2006)
New Revision: 709

Added:
   box/chris/merge/
Log:
* http://bbdev.fluffy.co.uk/svn/box/chris/merge
- Created a new branch as a public buffer for the process of merging 
  general win32 into trunk


Copied: box/chris/merge (from rev 708, box/trunk)


From boxbackup-dev@fluffy.co.uk  Fri Jul 28 00:19:12 2006
From: boxbackup-dev@fluffy.co.uk (boxbackup-dev@fluffy.co.uk)
Date: Thu, 27 Jul 2006 23:19:12 +0000 (GMT)
Subject: [Box Backup-dev] COMMIT r710 - in box/chris/merge: . bin/bbackupctl bin/bbackupd bin/bbackupquery bin/bbstored docs/backup infrastructure infrastructure/msvc/2003 lib/backupclient lib/backupstore lib/common lib/raidfile lib/server test/backupdiff test/backupstore test/backupstorefix/testfiles test/backupstorepatch test/basicserver test/bbackupd test/bbackupd/testfiles test/common test/raidfile test/win32
Message-ID: <20060727231912.BCD7B96@s0g0.pems.testserver.co.uk>

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", &currentState) != 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/;
-@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/;
+@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,@md];
+	$module_dependency{$mod} = [@implicit_deps,@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,@modules)
+for(@implicit_deps,@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,@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",@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


From boxbackup-dev@fluffy.co.uk  Fri Jul 28 09:02:03 2006
From: boxbackup-dev@fluffy.co.uk (Chris Wilson)
Date: Fri, 28 Jul 2006 09:02:03 +0100 (BST)
Subject: [Box Backup-dev] Win32 merge
In-Reply-To: <20060727231912.BCD7B96@s0g0.pems.testserver.co.uk>
References: <20060727231912.BCD7B96@s0g0.pems.testserver.co.uk>
Message-ID: <Pine.LNX.4.62.0607280859300.28495@top.qwarx.com>

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@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", &currentState) != 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/;
> -@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/;
> +@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,@md];
> +	$module_dependency{$mod} = [@implicit_deps,@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,@modules)
> +for(@implicit_deps,@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,@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",@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@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 |


From boxbackup-dev@fluffy.co.uk  Fri Jul 28 16:21:53 2006
From: boxbackup-dev@fluffy.co.uk (Andrei)
Date: Fri, 28 Jul 2006 18:21:53 +0300
Subject: [Box Backup-dev] Redundant locations in root directory
Message-ID: <bab9f1d50607280821k59744bds227b4602adb6f5af@mail.gmail.com>

Hello,

The BoxBackup client keeps telling me that the redundant locations in
the root directory will be removed after 172000 seconds. But it never
removes them. I restart the client every day, but I'm using the
feature that saves the state to a file on the disk.

Also, another feature that doesn't work is the "ExcludeFile"
directive. (Others also pointed out that this feature doesn't work).

Thanks

From boxbackup-dev@fluffy.co.uk  Fri Jul 28 18:38:17 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Fri, 28 Jul 2006 18:38:17 +0100
Subject: [Box Backup-dev] Redundant locations in root directory
In-Reply-To: <bab9f1d50607280821k59744bds227b4602adb6f5af@mail.gmail.com>
References: <bab9f1d50607280821k59744bds227b4602adb6f5af@mail.gmail.com>
Message-ID: <4C33DBEC-EF56-45C8-B784-8BFF93059E40@fluffy.co.uk>

On 28 Jul 2006, at 16:21, Andrei wrote:

> Hello,
>
> The BoxBackup client keeps telling me that the redundant locations in
> the root directory will be removed after 172000 seconds. But it never
> removes them. I restart the client every day, but I'm using the
> feature that saves the state to a file on the disk.

That state isn't saved. Don't restart the client every day.

>
> Also, another feature that doesn't work is the "ExcludeFile"
> directive. (Others also pointed out that this feature doesn't work).

You have forgotten to mention which platform you're using. Windows,  
by any chance?

Ben





From boxbackup-dev@fluffy.co.uk  Sun Jul 30 14:43:17 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Sun, 30 Jul 2006 14:43:17 +0100
Subject: [Box Backup-dev] COMMIT r698 - box/chris/general/bin/bbackupquery
In-Reply-To: <20060727203521.5303C96@s0g0.pems.testserver.co.uk>
References: <20060727203521.5303C96@s0g0.pems.testserver.co.uk>
Message-ID: <A9F3BDAE-2BE8-4621-B95F-12382D75BA31@fluffy.co.uk>

On 27 Jul 2006, at 21:35, subversion@fluffy.co.uk wrote:

> Author: chris
> Date: 2006-07-27 20:35:18 +0000 (Thu, 27 Jul 2006)
> New Revision: 698
>
> Modified:
>    box/chris/general/bin/bbackupquery/BackupQueries.cpp
> Log:
> * BackupQueries.cpp
> - Restore_TargetPathNotFound should only be used on Win32


Why? Sounds like it should apply to all platforms.

Ben


>
>
> Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
> ===================================================================
> --- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-26  
> 23:15:01 UTC (rev 697)
> +++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2006-07-27  
> 20:35:18 UTC (rev 698)
> @@ -1895,11 +1895,13 @@
>  		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");
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Sun Jul 30 14:43:50 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Sun, 30 Jul 2006 14:43:50 +0100
Subject: [Box Backup-dev] COMMIT r692 - in box/chris/general: infrastructure lib/common lib/server
In-Reply-To: <20060726191019.C5FBE96@s0g0.pems.testserver.co.uk>
References: <20060726191019.C5FBE96@s0g0.pems.testserver.co.uk>
Message-ID: <83951091-D077-4307-B01D-C640FABF4FE7@fluffy.co.uk>

I'm not totally convinced this is a good idea. Those scripts are  
already too complex.

Ben


On 26 Jul 2006, at 20:10, subversion@fluffy.co.uk wrote:

> Author: chris
> Date: 2006-07-26 19:10:10 +0000 (Wed, 26 Jul 2006)
> New Revision: 692
>
> Modified:
>    box/chris/general/infrastructure/BoxPlatform.pm.in
>    box/chris/general/infrastructure/makebuildenv.pl.in
>    box/chris/general/lib/common/makeexception.pl.in
>    box/chris/general/lib/server/makeprotocol.pl.in
> Log:
> * infrastructure/BoxPlatform.pm.in
> * infrastructure/makebuildenv.pl.in
> * lib/server/makeprotocol.pl.in
> * lib/common/makeexception.pl.in
> - Don't rewrite auto-generated files unless they have changed, to  
> prevent
>   unnecessary rebuilds
>
>
> Modified: box/chris/general/infrastructure/BoxPlatform.pm.in
> ===================================================================
> --- box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-26  
> 19:09:05 UTC (rev 691)
> +++ box/chris/general/infrastructure/BoxPlatform.pm.in	2006-07-26  
> 19:10:10 UTC (rev 692)
> @@ -1,7 +1,7 @@
>  package BoxPlatform;
>  use Exporter;
>  @ISA = qw/Exporter/;
> -@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/;
> +@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
>  {
> @@ -110,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 -u $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/general/infrastructure/makebuildenv.pl.in
> ===================================================================
> --- box/chris/general/infrastructure/makebuildenv.pl.in	2006-07-26  
> 19:09:05 UTC (rev 691)
> +++ box/chris/general/infrastructure/makebuildenv.pl.in	2006-07-26  
> 19:10:10 UTC (rev 692)
> @@ -114,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;
> @@ -296,7 +296,8 @@
>  }
>
>  # 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
> @@ -312,8 +313,8 @@
>  #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_deps)
> @@ -393,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")
>  			{
> @@ -420,6 +425,7 @@
>  			}
>  			print TESTFILE "$runcmd\n";
>  			close TESTFILE;
> +			update_if_changed($filename);
>  		}
>  		
>  		writetestfile("$mod/_t",
> @@ -487,7 +493,8 @@
>
>  	# 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";
> @@ -785,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>)
>  		{
> @@ -798,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";
>
> Modified: box/chris/general/lib/common/makeexception.pl.in
> ===================================================================
> --- box/chris/general/lib/common/makeexception.pl.in	2006-07-26  
> 19:09:05 UTC (rev 691)
> +++ box/chris/general/lib/common/makeexception.pl.in	2006-07-26  
> 19:10:10 UTC (rev 692)
> @@ -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/general/lib/server/makeprotocol.pl.in
> ===================================================================
> --- box/chris/general/lib/server/makeprotocol.pl.in	2006-07-26  
> 19:09:05 UTC (rev 691)
> +++ box/chris/general/lib/server/makeprotocol.pl.in	2006-07-26  
> 19:10:10 UTC (rev 692)
> @@ -170,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;
>
> @@ -915,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
>  {
>
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Mon Jul 31 10:45:51 2006
From: boxbackup-dev@fluffy.co.uk (Nick Knight)
Date: Mon, 31 Jul 2006 10:45:51 +0100
Subject: [Box Backup-dev] Where to put my bug fixes?
Message-ID: <A1501BC8C03ACC44B4C56ADC68B1C7F955B259@toutatis.omn11s.local>

Hello all,

I know have now 3 bugs found in box backup 0.10, 1 specific to Windows
and 2 general. All large file issues, which from my tests means any
platform are not capable of backing up or restoring files >2GB.

I know last time I worked on box I had a branch in SVN for my work, so
where is best to put my work now? This branch is quite old etc.

Also just a suggestion, but in previous development teams I have worked
on, they created branches for areas of work, so for example

 - Win 32 development
 - General bugs for next release
 - Gui branch (etc etc)

Just an idea?

Regards

Nick

PS
I had my fist encounter of GDB during these search for bugs, I have to
say in my opinion the worst debugger I have ever used!!=20

PPS - here are the bugs:

Bugs found

Win32 specific
The emu called into the supplied stat structure, which the size of file
size was only 32 bit. There is a way with the Win32 headers to exclude
their structure and create our own, which support 64 bit addressing.

General

Bug 1.=20

In lib/backupclient/BackupStoreFileEncodeStream.cpp line 270:

	} while(rBlockSizeOut <=3D (BACKUP_FILE_MAX_BLOCK_SIZE/2) &&
rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER);
	//BUG - Nick Knight 24-07-2006
	//Not sure whether this is the fix or the backupstorefile.cpp is
the problem, they
	//certainly do not match...
	//added divide by 2.

This on the client created blocks which the restore did not like the
block size (this could also be fixed on the restore - but it appeared to
be sensible to fix it here.

Bug 2.

In /lib/common/ReadGatherStream.cpp


                // Anything in the current block?
                if(mPositionInCurrentBlock <
mBlocks[mCurrentBlock].mLength)
                {
                        // Read!
                        pos_type s =3D mBlocks[mCurrentBlock].mLength -
mPositionInCurrentBlock;
                        if(s > bytesToRead) s =3D bytesToRead;

                        int r =3D
mComponents[mBlocks[mCurrentBlock].mComponent]->Read(buffer, s,
Timeout);

The pos_type s =3D mBlocks[mCurrentBlock].mLength -
mPositionInCurrentBlock; var s was an int, when the server put a single
large file together, it places the whole file (data) as a single block
into the object, which means any read should be the same addressable
space.

From boxbackup-dev@fluffy.co.uk  Mon Jul 31 15:15:54 2006
From: boxbackup-dev@fluffy.co.uk (Ben Summers)
Date: Mon, 31 Jul 2006 15:15:54 +0100
Subject: [Box Backup-dev] Where to put my bug fixes?
In-Reply-To: <A1501BC8C03ACC44B4C56ADC68B1C7F955B259@toutatis.omn11s.local>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F955B259@toutatis.omn11s.local>
Message-ID: <2AB9BABE-D463-4DA1-8310-088C863ADB42@fluffy.co.uk>

Nick

Please create a new branch off trunk and commit them there. (Not to  
trunk.)

We do sort of have branches for different kinds of work, it's just  
they're named by individuals at the moment. Suggestions for better  
ways of working welcomed.

Thanks

Ben


On 31 Jul 2006, at 10:45, Nick Knight wrote:

> Hello all,
>
> I know have now 3 bugs found in box backup 0.10, 1 specific to Windows
> and 2 general. All large file issues, which from my tests means any
> platform are not capable of backing up or restoring files >2GB.
>
> I know last time I worked on box I had a branch in SVN for my work, so
> where is best to put my work now? This branch is quite old etc.
>
> Also just a suggestion, but in previous development teams I have  
> worked
> on, they created branches for areas of work, so for example
>
>  - Win 32 development
>  - General bugs for next release
>  - Gui branch (etc etc)
>
> Just an idea?
>
> Regards
>
> Nick
>
> PS
> I had my fist encounter of GDB during these search for bugs, I have to
> say in my opinion the worst debugger I have ever used!!
>
> PPS - here are the bugs:
>
> Bugs found
>
> Win32 specific
> The emu called into the supplied stat structure, which the size of  
> file
> size was only 32 bit. There is a way with the Win32 headers to exclude
> their structure and create our own, which support 64 bit addressing.
>
> General
>
> Bug 1.
>
> In lib/backupclient/BackupStoreFileEncodeStream.cpp line 270:
>
> 	} while(rBlockSizeOut <= (BACKUP_FILE_MAX_BLOCK_SIZE/2) &&
> rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER);
> 	//BUG - Nick Knight 24-07-2006
> 	//Not sure whether this is the fix or the backupstorefile.cpp is
> the problem, they
> 	//certainly do not match...
> 	//added divide by 2.
>
> This on the client created blocks which the restore did not like the
> block size (this could also be fixed on the restore - but it  
> appeared to
> be sensible to fix it here.
>
> Bug 2.
>
> In /lib/common/ReadGatherStream.cpp
>
>
>                 // Anything in the current block?
>                 if(mPositionInCurrentBlock <
> mBlocks[mCurrentBlock].mLength)
>                 {
>                         // Read!
>                         pos_type s = mBlocks[mCurrentBlock].mLength -
> mPositionInCurrentBlock;
>                         if(s > bytesToRead) s = bytesToRead;
>
>                         int r =
> mComponents[mBlocks[mCurrentBlock].mComponent]->Read(buffer, s,
> Timeout);
>
> The pos_type s = mBlocks[mCurrentBlock].mLength -
> mPositionInCurrentBlock; var s was an int, when the server put a  
> single
> large file together, it places the whole file (data) as a single block
> into the object, which means any read should be the same addressable
> space.
> _______________________________________________
> Boxbackup-dev mailing list
> Boxbackup-dev@fluffy.co.uk
> http://lists.warhead.org.uk/mailman/listinfo/boxbackup-dev


From boxbackup-dev@fluffy.co.uk  Mon Jul 31 15:40:51 2006
From: boxbackup-dev@fluffy.co.uk (Martin Ebourne)
Date: Mon, 31 Jul 2006 15:40:51 +0100
Subject: [Box Backup-dev] Where to put my bug fixes?
In-Reply-To: <2AB9BABE-D463-4DA1-8310-088C863ADB42@fluffy.co.uk>
References: <A1501BC8C03ACC44B4C56ADC68B1C7F955B259@toutatis.omn11s.local>
 <2AB9BABE-D463-4DA1-8310-088C863ADB42@fluffy.co.uk>
Message-ID: <20060731154051.c4zuz49wyskcw08k@ebourne.me.uk>

Ben Summers <ben@fluffy.co.uk> wrote:
> We do sort of have branches for different kinds of work, it's just
> they're named by individuals at the moment. Suggestions for better ways
> of working welcomed.

That worked fairly well initially because there were several people  
with several changes each, and all had been worked on individually.

It still works well where people are doing their own change or  
creating scratch branches for playing with.

It becomes suboptimal when people start sharing branches or if there's  
a major branch being worked on (eg. Chris's windows dev). Maybe there  
could be a different way of marking 'blessed' branches. Keeping  
'personal' branches in subdirs by name but under a /branches directory  
and putting main branches directly at that level could work.

Cheers,

Martin.

