diff options
author | Daniel Wilhelm <daniel@wili.li> | 2016-03-16 21:32:07 +0100 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2016-03-16 21:32:07 +0100 |
commit | ce3574cf7ff2ee68608b4d001f5a6dd1e36b2252 (patch) | |
tree | 576b1741351e1cd34f0fcce49f98df9c17e10912 /zen/file_access.cpp | |
parent | 7.6 (diff) | |
download | FreeFileSync-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.cpp | 35 |
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); |