summaryrefslogtreecommitdiff
path: root/zen/file_handling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zen/file_handling.cpp')
-rw-r--r--zen/file_handling.cpp102
1 files changed, 46 insertions, 56 deletions
diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp
index 8c5584db..563a07ce 100644
--- a/zen/file_handling.cpp
+++ b/zen/file_handling.cpp
@@ -14,7 +14,7 @@
#include "file_io.h"
#include "assert_static.h"
#include "file_id_def.h"
-#include <boost/thread/tss.hpp>
+//#include <boost/thread/tss.hpp>
#ifdef ZEN_WIN
#include <Aclapi.h>
@@ -1303,36 +1303,42 @@ void zen::makeDirectoryPlain(const Zstring& directory, //throw FileError, ErrorT
::SetFileAttributes(applyLongPathPrefix(directory).c_str(), dirInfo.dwFileAttributes);
//copy "read-only and system attributes": http://blogs.msdn.com/b/oldnewthing/archive/2003/09/30/55100.aspx
- const bool isCompressed = (dirInfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) != 0;
const bool isEncrypted = (dirInfo.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0;
+ const bool isCompressed = (dirInfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) != 0;
if (isEncrypted)
::EncryptFile(directory.c_str()); //seems no long path is required (check passed!)
- if (isCompressed)
+ HANDLE hDirTrg = ::CreateFile(applyLongPathPrefix(directory).c_str(),
+ GENERIC_READ | GENERIC_WRITE, //read access required for FSCTL_SET_COMPRESSION
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ nullptr);
+ if (hDirTrg != INVALID_HANDLE_VALUE)
{
- HANDLE hDirTrg = ::CreateFile(applyLongPathPrefix(directory).c_str(),
- GENERIC_READ | GENERIC_WRITE, //read access required for FSCTL_SET_COMPRESSION
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- nullptr,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- nullptr);
- if (hDirTrg != INVALID_HANDLE_VALUE)
- {
- ZEN_ON_SCOPE_EXIT(::CloseHandle(hDirTrg));
+ ZEN_ON_SCOPE_EXIT(::CloseHandle(hDirTrg));
+ if (isCompressed)
+ {
USHORT cmpState = COMPRESSION_FORMAT_DEFAULT;
DWORD bytesReturned = 0;
- ::DeviceIoControl(hDirTrg, //handle to file or directory
- FSCTL_SET_COMPRESSION, //dwIoControlCode
- &cmpState, //input buffer
- sizeof(cmpState), //size of input buffer
- nullptr, //lpOutBuffer
- 0, //OutBufferSize
- &bytesReturned, //number of bytes returned
- nullptr); //OVERLAPPED structure
+ /*bool rv = */::DeviceIoControl(hDirTrg, //handle to file or directory
+ FSCTL_SET_COMPRESSION, //dwIoControlCode
+ &cmpState, //input buffer
+ sizeof(cmpState), //size of input buffer
+ nullptr, //lpOutBuffer
+ 0, //OutBufferSize
+ &bytesReturned, //number of bytes returned
+ nullptr); //OVERLAPPED structure
}
+
+ //(try to) set creation and modification time
+ /*bool rv = */::SetFileTime(hDirTrg, //_In_ HANDLE hFile,
+ &dirInfo.ftCreationTime, //_Out_opt_ LPFILETIME lpCreationTime,
+ nullptr, //_Out_opt_ LPFILETIME lpLastAccessTime,
+ &dirInfo.ftLastWriteTime); //_Out_opt_ LPFILETIME lpLastWriteTime
}
}
}
@@ -1783,12 +1789,12 @@ public:
throw ErrorShouldCopyAsSparse(L"sparse dummy value");
if (exceptionInUserCallback)
- try
- {
- exceptionInUserCallback(0); //should throw again!!!
- assert(false);
- }
- catch (...) { throw; }
+ try
+ {
+ exceptionInUserCallback(0); //should throw again!!!
+ assert(false);
+ }
+ catch (...) { throw; }
if (!errorMsg.first.empty())
throw FileError(errorMsg.first, errorMsg.second);
@@ -2171,19 +2177,6 @@ void copyFileLinuxMac(const Zstring& sourceFile,
}
#endif
-
-Zstring findUnusedTempName(const Zstring& filename)
-{
- Zstring output = filename + zen::TEMP_FILE_ENDING;
-
- //ensure uniqueness (+ minor file system race condition!)
- for (int i = 1; somethingExists(output); ++i)
- output = filename + Zchar('_') + numberTo<Zstring>(i) + zen::TEMP_FILE_ENDING;
-
- return output;
-}
-
-
/*
------------------
|File Copy Layers|
@@ -2225,25 +2218,22 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
{
if (transactionalCopy)
{
- Zstring temporary = targetFile + zen::TEMP_FILE_ENDING; //use temporary file until a correct date has been set
+ Zstring tmpTarget = targetFile + TEMP_FILE_ENDING; //use temporary file until a correct date has been set
//raw file copy
- try
- {
- copyFileSelectOs(sourceFile, temporary, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
- }
- catch (ErrorTargetExisting&)
- {
- //determine non-used temp file name "first":
- //using optimistic strategy: assume everything goes well, but recover on error -> minimize file accesses
- temporary = findUnusedTempName(targetFile);
-
- //retry
- copyFileSelectOs(sourceFile, temporary, onUpdateCopyStatus, sourceAttr); //throw FileError
- }
+ for (int i = 1;; ++i)
+ try
+ {
+ copyFileSelectOs(sourceFile, tmpTarget, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
+ break;
+ }
+ catch (const ErrorTargetExisting&) //using optimistic strategy: assume everything goes well, but recover on error -> minimize file accesses
+ {
+ tmpTarget = targetFile + Zchar('_') + numberTo<Zstring>(i) + TEMP_FILE_ENDING;
+ }
//transactional behavior: ensure cleanup; not needed before copyFileSelectOs() which is already transactional
- zen::ScopeGuard guardTempFile = zen::makeGuard([&] { try { removeFile(temporary); } catch (FileError&) {} });
+ zen::ScopeGuard guardTempFile = zen::makeGuard([&] { try { removeFile(tmpTarget); } catch (FileError&) {} });
//have target file deleted (after read access on source and target has been confirmed) => allow for almost transactional overwrite
if (onDeleteTargetFile)
@@ -2251,7 +2241,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
//rename temporary file:
//perf: this call is REALLY expensive on unbuffered volumes! ~40% performance decrease on FAT USB stick!
- renameFile(temporary, targetFile); //throw FileError
+ renameFile(tmpTarget, targetFile); //throw FileError
/*
CAVEAT on FAT/FAT32: the sequence of deleting the target file and renaming "file.txt.ffs_tmp" to "file.txt" does
bgstack15