[Box Backup-commit] COMMIT r1016 - in box/chris/merge: bin/bbstored lib/common lib/win32 test/common

boxbackup-dev@fluffy.co.uk boxbackup-dev@fluffy.co.uk
Sat, 14 Oct 2006 00:03:23 +0100


Author: chris
Date: 2006-10-14 00:03:23 +0100 (Sat, 14 Oct 2006)
New Revision: 1016

Added:
   box/chris/merge/lib/common/InvisibleTempFileStream.cpp
   box/chris/merge/lib/common/InvisibleTempFileStream.h
Modified:
   box/chris/merge/bin/bbstored/BackupCommands.cpp
   box/chris/merge/lib/win32/emu.cpp
   box/chris/merge/test/common/testcommon.cpp
Log:
 * Added support for Win32 temporary files
 * Added InvisibleTempFileStream class and unit tests for it 
 * Use InvisibleTempFileStream instead of FileStream for temporary files
   (refs #3)


Modified: box/chris/merge/bin/bbstored/BackupCommands.cpp
===================================================================
--- box/chris/merge/bin/bbstored/BackupCommands.cpp	2006-10-13 23:00:29 UTC (rev 1015)
+++ box/chris/merge/bin/bbstored/BackupCommands.cpp	2006-10-13 23:03:23 UTC (rev 1016)
@@ -29,6 +29,7 @@
 #include "BackupStoreInfo.h"
 #include "RaidFileController.h"
 #include "FileStream.h"
+#include "InvisibleTempFileStream.h"
 
 #include "MemLeakFindOn.h"
 
@@ -344,23 +345,14 @@
 			{
 				{
 					// 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));
+					std::auto_ptr<IOStream> t(
+						new InvisibleTempFileStream(
+							tempFn.c_str(), 
+							O_RDWR | O_CREAT | 
+							O_EXCL | O_BINARY | 
+							O_TRUNC));
 					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(...)
 			{

Copied: box/chris/merge/lib/common/InvisibleTempFileStream.cpp (from rev 1012, box/chris/general/lib/common/InvisibleTempFileStream.cpp)
===================================================================
--- box/chris/merge/lib/common/InvisibleTempFileStream.cpp	                        (rev 0)
+++ box/chris/merge/lib/common/InvisibleTempFileStream.cpp	2006-10-13 23:03:23 UTC (rev 1016)
@@ -0,0 +1,39 @@
+// --------------------------------------------------------------------------
+//
+// File
+//		Name:    InvisibleTempFileStream.cpp
+//		Purpose: IOStream interface to temporary files that
+//			delete themselves
+//		Created: 2006/10/13
+//
+// --------------------------------------------------------------------------
+
+#include "Box.h"
+#include "InvisibleTempFileStream.h"
+
+#include "MemLeakFindOn.h"
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    InvisibleTempFileStream::InvisibleTempFileStream
+//			(const char *, int, int)
+//		Purpose: Constructor, opens invisible file
+//		Created: 2006/10/13
+//
+// --------------------------------------------------------------------------
+InvisibleTempFileStream::InvisibleTempFileStream(const char *Filename, int flags, int mode)
+#ifdef WIN32
+	: FileStream(::openfile(Filename, flags | O_TEMPORARY, mode))
+#else
+	: FileStream(::open(Filename, flags, mode))
+#endif
+{
+	#ifndef WIN32
+	if(unlink(Filename) != 0)
+	{
+		MEMLEAKFINDER_NOT_A_LEAK(this);
+		THROW_EXCEPTION(CommonException, OSFileOpenError)
+	}
+	#endif
+}


Property changes on: box/chris/merge/lib/common/InvisibleTempFileStream.cpp
___________________________________________________________________
Name: svn:eol-style
   + native

Copied: box/chris/merge/lib/common/InvisibleTempFileStream.h (from rev 1012, box/chris/general/lib/common/InvisibleTempFileStream.h)
===================================================================
--- box/chris/merge/lib/common/InvisibleTempFileStream.h	                        (rev 0)
+++ box/chris/merge/lib/common/InvisibleTempFileStream.h	2006-10-13 23:03:23 UTC (rev 1016)
@@ -0,0 +1,35 @@
+// --------------------------------------------------------------------------
+//
+// File
+//		Name:    InvisibleTempFileStream.h
+//		Purpose: FileStream interface to temporary files that 
+//			delete themselves
+//		Created: 2006/10/13
+//
+// --------------------------------------------------------------------------
+
+#ifndef INVISIBLETEMPFILESTREAM__H
+#define INVISIBLETEMPFILESTREAM__H
+
+#include "FileStream.h"
+
+class InvisibleTempFileStream : public FileStream
+{
+public:
+	InvisibleTempFileStream(const char *Filename, 
+#ifdef WIN32
+		int flags = (O_RDONLY | O_BINARY),
+#else
+		int flags = O_RDONLY,
+#endif
+		int mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH));
+
+private:	
+	InvisibleTempFileStream(const InvisibleTempFileStream &rToCopy) 
+	: FileStream(INVALID_FILE)
+	{ /* do not call */ }
+};
+
+#endif // INVISIBLETEMPFILESTREAM__H
+
+


Property changes on: box/chris/merge/lib/common/InvisibleTempFileStream.h
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: box/chris/merge/lib/win32/emu.cpp
===================================================================
--- box/chris/merge/lib/win32/emu.cpp	2006-10-13 23:00:29 UTC (rev 1015)
+++ box/chris/merge/lib/win32/emu.cpp	2006-10-13 23:03:23 UTC (rev 1016)
@@ -521,7 +521,7 @@
 		accessRights = FILE_WRITE_DATA;
 		shareMode = FILE_SHARE_WRITE;
 	}
-	else if (flags & (O_RDWR | O_CREAT))
+	else if (flags & O_RDWR)
 	{
 		accessRights |= FILE_WRITE_ATTRIBUTES 
 			| FILE_WRITE_DATA | FILE_WRITE_EA;
@@ -541,12 +541,19 @@
 		shareMode = 0;
 	}
 
+	DWORD winFlags = FILE_FLAG_BACKUP_SEMANTICS;
+	if (flags & O_TEMPORARY)
+	{
+		winFlags  |= FILE_FLAG_DELETE_ON_CLOSE;
+		shareMode |= FILE_SHARE_DELETE;
+	}
+
 	HANDLE hdir = CreateFileW(pBuffer, 
 		accessRights, 
 		shareMode, 
 		NULL, 
 		createDisposition, 
-		FILE_FLAG_BACKUP_SEMANTICS,
+		winFlags,
 		NULL);
 	
 	delete [] pBuffer;

Modified: box/chris/merge/test/common/testcommon.cpp
===================================================================
--- box/chris/merge/test/common/testcommon.cpp	2006-10-13 23:00:29 UTC (rev 1015)
+++ box/chris/merge/test/common/testcommon.cpp	2006-10-13 23:03:23 UTC (rev 1016)
@@ -16,6 +16,7 @@
 #include "FdGetLine.h"
 #include "Guards.h"
 #include "FileStream.h"
+#include "InvisibleTempFileStream.h"
 #include "IOStreamGetLine.h"
 #include "NamedLock.h"
 #include "ReadGatherStream.h"
@@ -134,6 +135,54 @@
 
 int test(int argc, const char *argv[])
 {
+	// Test self-deleting temporary file streams
+	std::string tempfile("testfiles/tempfile");
+	TEST_CHECK_THROWS(InvisibleTempFileStream fs(tempfile.c_str()), 
+		CommonException, OSFileOpenError);
+	InvisibleTempFileStream fs(tempfile.c_str(), O_CREAT);
+
+#ifdef WIN32
+	// file is still visible under Windows
+	TEST_THAT(TestFileExists(tempfile.c_str()));
+
+	// opening it again should work
+	InvisibleTempFileStream fs2(tempfile.c_str());
+	TEST_THAT(TestFileExists(tempfile.c_str()));
+
+	// opening it to create should work
+	InvisibleTempFileStream fs3(tempfile.c_str(), O_CREAT);
+	TEST_THAT(TestFileExists(tempfile.c_str()));
+
+	// opening it to create exclusively should fail
+	TEST_CHECK_THROWS(InvisibleTempFileStream fs4(tempfile.c_str(), 
+		O_CREAT | O_EXCL), CommonException, OSFileOpenError);
+
+#else
+	// file is not visible under Unix
+	TEST_THAT(!TestFileExists(tempfile.c_str()));
+
+	// opening it again should fail
+	TEST_CHECK_THROWS(InvisibleTempFileStream fs2(tempfile.c_str()),
+		CommonException, OSFileOpenError);
+
+	// opening it to create should work
+	InvisibleTempFileStream fs3(tempfile.c_str(), O_CREAT);
+	TEST_THAT(!TestFileExists(tempfile.c_str()));
+
+	// opening it to create exclusively should work
+	InvisibleTempFileStream fs4(tempfile.c_str(), O_CREAT | O_EXCL);
+	TEST_THAT(!TestFileExists(tempfile.c_str()));
+
+	fs4.Close();
+#endif
+
+	fs.Close();
+	fs2.Close();
+	fs3.Close();
+
+	// now that it's closed, it should be invisible on all platforms
+	TEST_THAT(!TestFileExists(tempfile.c_str()));
+
 	// Test memory leak detection
 #ifdef BOX_MEMORY_LEAK_TESTING
 	{