summaryrefslogtreecommitdiff
path: root/zen/file_access.cpp
diff options
context:
space:
mode:
authorB Stack <bgstack15@gmail.com>2018-12-15 08:58:32 -0500
committerB Stack <bgstack15@gmail.com>2018-12-15 08:58:32 -0500
commitd2c4bc7276ea099ee8fc53ddb918c0f3458b4bb5 (patch)
tree597a84bf090173bfc5f406e9009263875218707d /zen/file_access.cpp
parentMerge branch '10.6' into 'master' (diff)
downloadFreeFileSync-d2c4bc7276ea099ee8fc53ddb918c0f3458b4bb5.tar.gz
FreeFileSync-d2c4bc7276ea099ee8fc53ddb918c0f3458b4bb5.tar.bz2
FreeFileSync-d2c4bc7276ea099ee8fc53ddb918c0f3458b4bb5.zip
10.7
Diffstat (limited to 'zen/file_access.cpp')
-rwxr-xr-xzen/file_access.cpp28
1 files changed, 15 insertions, 13 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index 82c78760..ea19b6c7 100755
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -311,8 +311,8 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro
{
//rename() will never fail with EEXIST, but always (atomically) overwrite!
//=> equivalent to SetFileInformationByHandle() + FILE_RENAME_INFO::ReplaceIfExists or ::MoveFileEx + MOVEFILE_REPLACE_EXISTING
- //=> Linux: renameat2() with RENAME_NOREPLACE -> still new, probably buggy
- //=> OS X: no solution
+ //Linux: renameat2() with RENAME_NOREPLACE -> still new, probably buggy
+ //macOS: no solution
auto throwException = [&](int ec)
{
@@ -326,18 +326,19 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro
throw FileError(errorMsg, errorDescr);
};
- if (!equalFilePath(pathSource, pathTarget)) //exception for OS X: changing file name case is not an "already exists" situation!
- {
- const bool alreadyExists = [&]
- {
- try { /*ItemType type = */getItemType(pathTarget); return true; } /*throw FileError*/
- catch (FileError&) { return false; }
- }();
+ struct ::stat infoSrc = {};
+ if (::lstat(pathSource.c_str(), &infoSrc) != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(pathSource)), L"stat");
- if (alreadyExists)
- throwException(EEXIST);
- //else: nothing exists or other error (hopefully ::rename will also fail!)
- }
+ struct ::stat infoTrg = {};
+ if (::lstat(pathTarget.c_str(), &infoTrg) == 0)
+ {
+ if (infoSrc.st_dev != infoTrg.st_dev ||
+ infoSrc.st_ino != infoTrg.st_ino)
+ throwException(EEXIST); //that's what we're really here for
+ //else: continue with a rename in case
+ }
+ //else: not existing or access error (hopefully ::rename will also fail!)
if (::rename(pathSource.c_str(), pathTarget.c_str()) != 0)
throwException(errno);
@@ -397,6 +398,7 @@ void setWriteTimeNative(const Zstring& itemPath, const struct ::timespec& modTim
struct ::timespec newTimes[2] = {};
newTimes[0].tv_sec = ::time(nullptr); //access time; using UTIME_OMIT for tv_nsec would trigger even more bugs: https://freefilesync.org/forum/viewtopic.php?t=1701
newTimes[1] = modTime; //modification time
+ //test: even modTime == 0 is correctly applied (no NOOP!) test2: same behavior for "utime()"
if (procSl == ProcSymlink::FOLLOW)
{
bgstack15