summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
Diffstat (limited to 'zen')
-rwxr-xr-xzen/file_access.cpp72
-rwxr-xr-xzen/file_access.h13
-rwxr-xr-xzen/file_id_def.h2
-rwxr-xr-xzen/file_traverser.h4
-rwxr-xr-xzen/symlink_target.h4
5 files changed, 51 insertions, 44 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index ed66aac4..273616e3 100755
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -91,25 +91,22 @@ PathStatus zen::getPathStatus(const Zstring& itemPath) //throw FileError
const Zstring itemName = afterLast(itemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
assert(!itemName.empty());
- PathStatus pd = getPathStatus(*parentPath); //throw FileError
- if (!pd.relPath.empty())
- {
- pd.relPath.push_back(itemName);
- return { pd.existingType, pd.existingPath, pd.relPath };
- }
-
- try
- {
- traverseFolder(*parentPath,
- [&](const FileInfo& fi) { if (equalFilePath(fi.itemName, itemName)) throw ItemType::FILE; },
- [&](const FolderInfo& fi) { if (equalFilePath(fi.itemName, itemName)) throw ItemType::FOLDER; },
- [&](const SymlinkInfo& si) { if (equalFilePath(si.itemName, itemName)) throw ItemType::SYMLINK; },
- [](const std::wstring& errorMsg) { throw FileError(errorMsg); });
-
- return { pd.existingType, *parentPath, { itemName } }; //throw FileError
- }
- catch (const ItemType& type) { return { type, itemPath, {} }; } //yes, exceptions for control-flow are bad design... but, but...
+ PathStatus ps = getPathStatus(*parentPath); //throw FileError
+ if (ps.relPath.empty() &&
+ ps.existingType != ItemType::FILE) //obscure, but possible (and not an error)
+ try
+ {
+ traverseFolder(*parentPath,
+ [&](const FileInfo& fi) { if (equalFilePath(fi.itemName, itemName)) throw ItemType::FILE; },
+ [&](const FolderInfo& fi) { if (equalFilePath(fi.itemName, itemName)) throw ItemType::FOLDER; },
+ [&](const SymlinkInfo& si) { if (equalFilePath(si.itemName, itemName)) throw ItemType::SYMLINK; },
+ [](const std::wstring& errorMsg) { throw FileError(errorMsg); });
+ }
+ catch (const ItemType& type) { return { type, itemPath, {} }; } //yes, exceptions for control-flow are bad design... but, but...
//we're not CPU-bound here and finding the item after getItemType() previously failed is exceptional (even C:\pagefile.sys should be found)
+
+ ps.relPath.push_back(itemName);
+ return ps;
}
@@ -337,7 +334,7 @@ void zen::renameFile(const Zstring& pathSource, const Zstring& pathTarget) //thr
{
renameFile_sub(pathSource, pathTarget); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
}
- catch (const ErrorTargetExisting&)
+ catch (ErrorTargetExisting&)
{
throw;
}
@@ -388,7 +385,7 @@ void setWriteTimeNative(const Zstring& itemPath, const struct ::timespec& modTim
}
-
+warn_static("remove after test")
void zen::setFileTime(const Zstring& filePath, int64_t modTime, ProcSymlink procSl) //throw FileError
{
struct ::timespec writeTime = {};
@@ -588,9 +585,9 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool
namespace
{
-InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile, //throw FileError, ErrorTargetExisting
- const Zstring& targetFile,
- const IOCallback& notifyUnbufferedIO)
+FileCopyResult copyFileOsSpecific(const Zstring& sourceFile, //throw FileError, ErrorTargetExisting
+ const Zstring& targetFile,
+ const IOCallback& notifyUnbufferedIO)
{
int64_t totalUnbufferedIO = 0;
@@ -631,19 +628,28 @@ InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile, //throw FileError
//close output file handle before setting file time; also good place to catch errors when closing stream!
fileOut.finalize(); //throw FileError, (X) essentially a close() since buffers were already flushed
+Opt<FileError> errorModTime;
+ try
+ {
//we cannot set the target file times (::futimes) while the file descriptor is still open after a write operation:
//this triggers bugs on samba shares where the modification time is set to current time instead.
//Linux: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340236
// http://comments.gmane.org/gmane.linux.file-systems.cifs/2854
//OS X: http://www.freefilesync.org/forum/viewtopic.php?t=356
setWriteTimeNative(targetFile, sourceInfo.st_mtim, ProcSymlink::FOLLOW); //throw FileError
+ }
+ catch (const FileError& e)
+ {
+ errorModTime = FileError(e.toString()); //avoid slicing
+ }
- InSyncAttributes newAttrib;
- newAttrib.fileSize = sourceInfo.st_size;
- newAttrib.modificationTime = sourceInfo.st_mtim.tv_sec; //
- newAttrib.sourceFileId = extractFileId(sourceInfo);
- newAttrib.targetFileId = extractFileId(targetInfo);
- return newAttrib;
+ FileCopyResult result;
+ result.fileSize = sourceInfo.st_size;
+ result.modTime = sourceInfo.st_mtim.tv_sec; //
+ result.sourceFileId = extractFileId(sourceInfo);
+ result.targetFileId = extractFileId(targetInfo);
+ result.errorModTime = errorModTime;
+ return result;
}
/* ------------------
@@ -660,10 +666,10 @@ copyFileWindowsDefault(::CopyFileEx) copyFileWindowsStream(::BackupRead/::Backu
}
-InSyncAttributes zen::copyNewFile(const Zstring& sourceFile, const Zstring& targetFile, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
- const IOCallback& notifyUnbufferedIO)
+FileCopyResult zen::copyNewFile(const Zstring& sourceFile, const Zstring& targetFile, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ const IOCallback& notifyUnbufferedIO)
{
- const InSyncAttributes attr = copyFileOsSpecific(sourceFile, targetFile, notifyUnbufferedIO); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ const FileCopyResult result = copyFileOsSpecific(sourceFile, targetFile, notifyUnbufferedIO); //throw FileError, ErrorTargetExisting, ErrorFileLocked
//at this point we know we created a new file, so it's fine to delete it for cleanup!
ZEN_ON_SCOPE_FAIL(try { removeFilePlain(targetFile); }
@@ -672,5 +678,5 @@ InSyncAttributes zen::copyNewFile(const Zstring& sourceFile, const Zstring& targ
if (copyFilePermissions)
copyItemPermissions(sourceFile, targetFile, ProcSymlink::FOLLOW); //throw FileError
- return attr;
+ return result;
}
diff --git a/zen/file_access.h b/zen/file_access.h
index ee33da93..a06e5b17 100755
--- a/zen/file_access.h
+++ b/zen/file_access.h
@@ -56,7 +56,7 @@ enum class ProcSymlink
DIRECT,
FOLLOW
};
-void setFileTime(const Zstring& filePath, int64_t modificationTime, ProcSymlink procSl); //throw FileError
+void setFileTime(const Zstring& filePath, int64_t modTime, ProcSymlink procSl); //throw FileError
//symlink handling: always evaluate target
uint64_t getFileSize(const Zstring& filePath); //throw FileError
@@ -85,17 +85,18 @@ void copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, bool
void copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool copyFilePermissions); //throw FileError
-struct InSyncAttributes
+struct FileCopyResult
{
uint64_t fileSize = 0;
- int64_t modificationTime = 0; //time_t UTC compatible
+ int64_t modTime = 0; //time_t-compatible (UTC)
FileId sourceFileId;
FileId targetFileId;
+ Opt<FileError> errorModTime; //failure to set modification time
};
-InSyncAttributes copyNewFile(const Zstring& sourceFile, const Zstring& targetFile, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
- //accummulated delta != file size! consider ADS, sparse, compressed files
- const IOCallback& notifyUnbufferedIO); //may be nullptr; throw X!
+FileCopyResult copyNewFile(const Zstring& sourceFile, const Zstring& targetFile, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ //accummulated delta != file size! consider ADS, sparse, compressed files
+ const IOCallback& notifyUnbufferedIO); //may be nullptr; throw X!
}
#endif //FILE_ACCESS_H_8017341345614857
diff --git a/zen/file_id_def.h b/zen/file_id_def.h
index 3dcd21b9..8d429fbc 100755
--- a/zen/file_id_def.h
+++ b/zen/file_id_def.h
@@ -20,7 +20,7 @@ using VolumeId = decltype(impl::StatDummy::st_dev);
using FileIndex = decltype(impl::StatDummy::st_ino);
-struct FileId //always available on Linux, and *generally* available on Windows)
+struct FileId //always available on Linux, and *generally* available on Windows)
{
FileId() {}
FileId(VolumeId volId, FileIndex fIdx) : volumeId(volId), fileIndex(fIdx) {}
diff --git a/zen/file_traverser.h b/zen/file_traverser.h
index 79bcae11..e2085698 100755
--- a/zen/file_traverser.h
+++ b/zen/file_traverser.h
@@ -19,7 +19,7 @@ struct FileInfo
Zstring itemName;
Zstring fullPath;
uint64_t fileSize; //[bytes]
- int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC
+ int64_t modTime; //number of seconds since Jan. 1st 1970 UTC
};
struct FolderInfo
@@ -32,7 +32,7 @@ struct SymlinkInfo
{
Zstring itemName;
Zstring fullPath;
- int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC
+ int64_t modTime; //number of seconds since Jan. 1st 1970 UTC
};
//- non-recursive
diff --git a/zen/symlink_target.h b/zen/symlink_target.h
index 84b8452a..6ff7f327 100755
--- a/zen/symlink_target.h
+++ b/zen/symlink_target.h
@@ -17,7 +17,7 @@
namespace zen
{
-Zstring getResolvedSymlinkPath(const Zstring& linkPath); //throw FileError; Win: requires Vista or later!
+Zstring getSymlinkResolvedPath(const Zstring& linkPath); //throw FileError; Win: requires Vista or later!
Zstring getSymlinkTargetRaw (const Zstring& linkPath); //throw FileError
}
@@ -68,7 +68,7 @@ inline
Zstring getSymlinkTargetRaw(const Zstring& linkPath) { return getSymlinkRawTargetString_impl(linkPath); }
inline
-Zstring getResolvedSymlinkPath(const Zstring& linkPath) { return getResolvedSymlinkPath_impl(linkPath); }
+Zstring getSymlinkResolvedPath(const Zstring& linkPath) { return getResolvedSymlinkPath_impl(linkPath); }
}
bgstack15