diff options
author | Chris Wilson <chris+github@qwirx.com> | 2006-10-13 23:03:23 +0000 |
---|---|---|
committer | Chris Wilson <chris+github@qwirx.com> | 2006-10-13 23:03:23 +0000 |
commit | 9635631135e1f0df36a0b038f047384dd9d8c8c0 (patch) | |
tree | 23c91d2ea5ba5b6e00c853bdff67cd222f7c6768 | |
parent | f1ae01e66e6d2ed9072d17943fb04ccea0dbe592 (diff) |
* Added support for Win32 temporary files
* Added InvisibleTempFileStream class and unit tests for it
* Use InvisibleTempFileStream instead of FileStream for temporary files
(refs #3)
-rw-r--r-- | bin/bbstored/BackupCommands.cpp | 22 | ||||
-rw-r--r-- | lib/common/InvisibleTempFileStream.cpp | 39 | ||||
-rw-r--r-- | lib/common/InvisibleTempFileStream.h | 35 | ||||
-rw-r--r-- | lib/win32/emu.cpp | 11 | ||||
-rw-r--r-- | test/common/testcommon.cpp | 49 |
5 files changed, 139 insertions, 17 deletions
diff --git a/bin/bbstored/BackupCommands.cpp b/bin/bbstored/BackupCommands.cpp index 60a660d1..cf8025e4 100644 --- a/bin/bbstored/BackupCommands.cpp +++ b/bin/bbstored/BackupCommands.cpp @@ -29,6 +29,7 @@ #include "BackupStoreInfo.h" #include "RaidFileController.h" #include "FileStream.h" +#include "InvisibleTempFileStream.h" #include "MemLeakFindOn.h" @@ -344,23 +345,14 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetFile::DoCommand(BackupProto { { // 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(...) { diff --git a/lib/common/InvisibleTempFileStream.cpp b/lib/common/InvisibleTempFileStream.cpp new file mode 100644 index 00000000..a7e19ad3 --- /dev/null +++ b/lib/common/InvisibleTempFileStream.cpp @@ -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 +} diff --git a/lib/common/InvisibleTempFileStream.h b/lib/common/InvisibleTempFileStream.h new file mode 100644 index 00000000..a77d05e2 --- /dev/null +++ b/lib/common/InvisibleTempFileStream.h @@ -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 + + diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 91684f1c..6ce1790c 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -521,7 +521,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) 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 @@ HANDLE openfile(const char *pFileName, int flags, int mode) 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; diff --git a/test/common/testcommon.cpp b/test/common/testcommon.cpp index 5565b406..5a88b3f9 100644 --- a/test/common/testcommon.cpp +++ b/test/common/testcommon.cpp @@ -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 @@ ConfigurationVerify verify = 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 { |