summaryrefslogtreecommitdiff
path: root/zen/file_access.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2016-03-16 21:32:07 +0100
committerDaniel Wilhelm <daniel@wili.li>2016-03-16 21:32:07 +0100
commitce3574cf7ff2ee68608b4d001f5a6dd1e36b2252 (patch)
tree576b1741351e1cd34f0fcce49f98df9c17e10912 /zen/file_access.cpp
parent7.6 (diff)
downloadFreeFileSync-ce3574cf7ff2ee68608b4d001f5a6dd1e36b2252.tar.gz
FreeFileSync-ce3574cf7ff2ee68608b4d001f5a6dd1e36b2252.tar.bz2
FreeFileSync-ce3574cf7ff2ee68608b4d001f5a6dd1e36b2252.zip
7.7
Diffstat (limited to 'zen/file_access.cpp')
-rw-r--r--zen/file_access.cpp35
1 files changed, 26 insertions, 9 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index 2ca373aa..a66cbc6b 100644
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -828,7 +828,7 @@ void setFileTimeRaw(const Zstring& filePath,
throw FileError(errorMsg, formatSystemError(L"SetFileTime", ec));
}
}
-#ifndef NDEBUG //verify written data: mainly required to check consistency of DST hack
+#ifndef NDEBUG //verify written data
FILETIME creationTimeDbg = {};
FILETIME lastWriteTimeDbg = {};
@@ -1347,9 +1347,9 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath,
bool copyFilePermissions)
{
#ifdef ZEN_WIN
-auto getErrorMsg = [](const Zstring& path){ return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(path)); };
+ auto getErrorMsg = [](const Zstring& path) { return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(path)); };
-//special handling for volume root: trying to create existing root directory results in ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS!
+ //special handling for volume root: trying to create existing root directory results in ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS!
Zstring dirTmp = removeLongPathPrefix(endsWith(targetPath, FILE_NAME_SEPARATOR) ?
beforeLast(targetPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) :
targetPath);
@@ -1359,7 +1359,7 @@ auto getErrorMsg = [](const Zstring& path){ return replaceCpy(_("Cannot create d
dirTmp += FILE_NAME_SEPARATOR; //we do not support "C:" to represent a relative path!
const DWORD ec = somethingExists(dirTmp) ? ERROR_ALREADY_EXISTS : ERROR_PATH_NOT_FOUND; //don't use dirExists() => harmonize with ErrorTargetExisting!
- const std::wstring errorDescr = formatSystemError(L"CreateDirectory", ec);
+ const std::wstring errorDescr = formatSystemError(L"CreateDirectory", ec);
if (ec == ERROR_ALREADY_EXISTS)
throw ErrorTargetExisting(getErrorMsg(dirTmp), errorDescr);
@@ -1412,7 +1412,7 @@ auto getErrorMsg = [](const Zstring& path){ return replaceCpy(_("Cannot create d
if (!sourcePath.empty())
if (::stat(sourcePath.c_str(), &dirInfo) == 0)
{
- mode = dirInfo.st_mode; //analog to "cp" which copies "mode" (considering umask) by default
+ mode = dirInfo.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); //analog to "cp" which copies "mode" (considering umask) by default
mode |= S_IRWXU; //FFS only: we need full access to copy child items! "cp" seems to apply permissions *after* copying child items
}
//=> need copyItemPermissions() only for "chown" and umask-agnostic permissions
@@ -1783,8 +1783,8 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw
//create targetFile and open it for writing
HANDLE hFileTarget = ::CreateFile(applyLongPathPrefix(targetFile).c_str(), //_In_ LPCTSTR lpFileName,
- GENERIC_READ | GENERIC_WRITE, //_In_ DWORD dwDesiredAccess,
- //read access required for FSCTL_SET_COMPRESSION
+ GENERIC_READ | GENERIC_WRITE | DELETE, //_In_ DWORD dwDesiredAccess,
+ //GENERIC_READ required for FSCTL_SET_COMPRESSION, DELETE for ::SetFileInformationByHandle(),FileDispositionInfo
FILE_SHARE_DELETE, //_In_ DWORD dwShareMode,
//FILE_SHARE_DELETE is required to rename file while handle is open!
nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
@@ -1808,10 +1808,27 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw
throw FileError(errorMsg, errorDescr);
}
+#ifndef ZEN_WIN_VISTA_AND_LATER
ZEN_ON_SCOPE_FAIL(try { removeFile(targetFile); }
- catch (FileError&) {} ); //transactional behavior: guard just after opening target and before managing hFileTarget
+ catch (FileError&) {} ); //transactional behavior: guard just after opening target and before managing hFileTarget
+#endif
+
ZEN_ON_SCOPE_EXIT(::CloseHandle(hFileTarget));
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ //no need for ::DeleteFile(), we already have an open handle! Maybe this also prevents needless buffer-flushing in ::CloseHandle()??? Anyway, same behavior like ::CopyFileEx()
+ ZEN_ON_SCOPE_FAIL
+ (
+ FILE_DISPOSITION_INFO di = {};
+ di.DeleteFile = true;
+ if (!::SetFileInformationByHandle(hFileTarget, //_In_ HANDLE hFile,
+ FileDispositionInfo, //_In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
+ &di, //_In_ LPVOID lpFileInformation,
+ sizeof(di))) //_In_ DWORD dwBufferSize
+ assert(false);
+ );
+#endif
+
//----------------------------------------------------------------------
BY_HANDLE_FILE_INFORMATION fileInfoTarget = {};
if (!::GetFileInformationByHandle(hFileTarget, &fileInfoTarget))
@@ -1820,7 +1837,7 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw
//return up-to-date file attributes
InSyncAttributes newAttrib;
newAttrib.fileSize = get64BitUInt(fileInfoSource.nFileSizeLow, fileInfoSource.nFileSizeHigh);
- newAttrib.modificationTime = filetimeToTimeT(fileInfoSource.ftLastWriteTime); //no DST hack (yet)
+ newAttrib.modificationTime = filetimeToTimeT(fileInfoSource.ftLastWriteTime);
newAttrib.sourceFileId = extractFileId(fileInfoSource);
newAttrib.targetFileId = extractFileId(fileInfoTarget);
bgstack15