summaryrefslogtreecommitdiff
path: root/shared/file_traverser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shared/file_traverser.cpp')
-rw-r--r--shared/file_traverser.cpp56
1 files changed, 27 insertions, 29 deletions
diff --git a/shared/file_traverser.cpp b/shared/file_traverser.cpp
index aced3487..595b2768 100644
--- a/shared/file_traverser.cpp
+++ b/shared/file_traverser.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "file_traverser.h"
#include <limits>
#include "last_error.h"
@@ -14,6 +14,7 @@
#include <wx/msw/wrapwin.h> //includes "windows.h"
#include "long_path_prefix.h"
#include "dst_hack.h"
+#include "file_update_handle.h"
#elif defined FFS_LINUX
#include <sys/stat.h>
@@ -57,7 +58,7 @@ inline
zen::Int64 filetimeToTimeT(const FILETIME& lastWriteTime)
{
//convert UTC FILETIME to ANSI C format (number of seconds since Jan. 1st 1970 UTC)
- zen::Int64 writeTimeLong = zen::to<zen::Int64>(zen::UInt64(lastWriteTime.dwLowDateTime, lastWriteTime.dwHighDateTime) / 10000000U); //reduce precision to 1 second (FILETIME has unit 10^-7 s)
+ zen::Int64 writeTimeLong = to<zen::Int64>(zen::UInt64(lastWriteTime.dwLowDateTime, lastWriteTime.dwHighDateTime) / 10000000U); //reduce precision to 1 second (FILETIME has unit 10^-7 s)
writeTimeLong -= zen::Int64(3054539008UL, 2); //timeshift between ansi C time and FILETIME in seconds == 11644473600s
return writeTimeLong;
}
@@ -126,14 +127,12 @@ public:
}
private:
- DirTraverser(const DirTraverser&);
- DirTraverser& operator=(const DirTraverser&);
+ DirTraverser(const DirTraverser&);
+ DirTraverser& operator=(const DirTraverser&);
template <bool followSymlinks>
void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level)
{
- using namespace zen;
-
tryReportingError([&](std::wstring& errorMsg) -> bool
{
if (level == 100) //notify endless recursion
@@ -146,19 +145,16 @@ private:
#ifdef FFS_WIN
- //ensure directoryFormatted ends with backslash
- const Zstring& directoryFormatted = directory.EndsWith(FILE_NAME_SEPARATOR) ?
- directory :
- directory + FILE_NAME_SEPARATOR;
-
+ //ensure directoryPf ends with backslash
+ const Zstring& directoryPf = directory.EndsWith(FILE_NAME_SEPARATOR) ?
+ directory :
+ directory + FILE_NAME_SEPARATOR;
WIN32_FIND_DATA fileInfo = {};
HANDLE searchHandle = INVALID_HANDLE_VALUE;
tryReportingError([&](std::wstring& errorMsg) -> bool
{
- searchHandle = ::FindFirstFile(
- applyLongPathPrefix(directoryFormatted + Zchar('*')).c_str(), //__in LPCTSTR lpFileName
- &fileInfo); //__out LPWIN32_FIND_DATA lpFindFileData
+ searchHandle = ::FindFirstFile(applyLongPathPrefix(directoryPf + L'*').c_str(), &fileInfo);
//no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH
if (searchHandle == INVALID_HANDLE_VALUE)
@@ -188,7 +184,7 @@ private:
(shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0')))
continue;
- const Zstring& fullName = directoryFormatted + shortName;
+ const Zstring& fullName = directoryPf + shortName;
const bool isSymbolicLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
@@ -254,7 +250,7 @@ private:
details.fileSize = zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
}
- sink.onFile(shortName, fullName, details);
+ sink.onFile(shortName, fullName, details);
}
}
while ([&]() -> bool
@@ -322,7 +318,7 @@ private:
//don't return "." and ".."
- const Zchar* const shortName = dirEntry->d_name;
+ const char* const shortName = dirEntry->d_name;
if (shortName[0] == '.' &&
(shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0')))
continue;
@@ -421,23 +417,25 @@ private:
const dst::RawTime encodedTime = dst::fatEncodeUtcTime(i->second); //throw (std::runtime_error)
{
- HANDLE hTarget = ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(),
- GENERIC_WRITE, //just FILE_WRITE_ATTRIBUTES may not be enough for some NAS shares!
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- NULL);
- if (hTarget == INVALID_HANDLE_VALUE)
+ //may need to remove the readonly-attribute (e.g. FAT usb drives)
+ FileUpdateHandle updateHandle(i->first, [=]()
+ {
+ return ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(),
+ GENERIC_WRITE, //just FILE_WRITE_ATTRIBUTES may not be enough for some NAS shares!
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ });
+ if (updateHandle.get() == INVALID_HANDLE_VALUE)
{
++failedAttempts;
assert(false); //don't throw exceptions due to dst hack here
continue;
}
- Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hTarget);
- (void)dummy; //silence warning "unused variable"
- if (!::SetFileTime(hTarget,
+ if (!::SetFileTime(updateHandle.get(),
&encodedTime.createTimeRaw,
NULL,
&encodedTime.writeTimeRaw))
@@ -483,7 +481,7 @@ void zen::traverseFolder(const Zstring& directory, bool followSymlinks, Traverse
#ifdef FFS_WIN
try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail)
{
- zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw (FileError)
+ zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError
}
catch (...) {} //don't cause issues in user mode
#endif
bgstack15