summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
authorDaniel Wilhelm <shieldwed@outlook.com>2018-05-08 23:58:22 +0200
committerDaniel Wilhelm <shieldwed@outlook.com>2018-05-08 23:58:22 +0200
commitd9af47022b5eb44effe5bfb6e2acfa8dff54a7a6 (patch)
tree0e492ea3976c5908c7323cac3e73ebb6fdd65085 /zen
parent9.1 (diff)
downloadFreeFileSync-d9af47022b5eb44effe5bfb6e2acfa8dff54a7a6.tar.gz
FreeFileSync-d9af47022b5eb44effe5bfb6e2acfa8dff54a7a6.tar.bz2
FreeFileSync-d9af47022b5eb44effe5bfb6e2acfa8dff54a7a6.zip
9.2
Diffstat (limited to 'zen')
-rwxr-xr-xzen/file_access.cpp72
-rwxr-xr-xzen/file_access.h17
-rwxr-xr-xzen/file_traverser.h4
-rwxr-xr-xzen/guid.h8
4 files changed, 47 insertions, 54 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index b894645c..7d57045d 100755
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -15,6 +15,7 @@
#include "file_id_def.h"
#include "file_io.h"
#include "crc.h"
+#include "guid.h"
#include <sys/vfs.h> //statfs
#include <sys/time.h> //lutimes
@@ -315,7 +316,7 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro
if (!equalFilePath(pathSource, pathTarget)) //exception for OS X: changing file name case is not an "already exists" situation!
{
bool alreadyExists = true;
- try { /*ItemType type = */getItemType(pathTarget); } /*throw FileError*/ catch (FileError&) { alreadyExists = false; }
+ try { /*ItemType type = */getItemType(pathTarget); } /*throw FileError*/ catch (FileError&) { alreadyExists = false; }
if (alreadyExists)
throwException(EEXIST);
@@ -408,7 +409,7 @@ void setWriteTimeNative(const Zstring& itemPath, const struct ::timespec& modTim
}
-void zen::setFileTime(const Zstring& filePath, int64_t modTime, ProcSymlink procSl) //throw FileError
+void zen::setFileTime(const Zstring& filePath, time_t modTime, ProcSymlink procSl) //throw FileError
{
struct ::timespec writeTime = {};
writeTime.tv_sec = modTime;
@@ -470,10 +471,11 @@ void copySecurityContext(const Zstring& source, const Zstring& target, ProcSymli
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write security context of %x."), L"%x", fmtPath(target)), L"setfilecon");
}
#endif
+}
//copy permissions for files, directories or symbolic links: requires admin rights
-void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, ProcSymlink procSl) //throw FileError
+void zen::copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, ProcSymlink procSl) //throw FileError
{
#ifdef HAVE_SELINUX //copy SELinux security context
@@ -507,6 +509,24 @@ void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, P
}
}
+
+
+void zen::createDirectory(const Zstring& dirPath) //throw FileError, ErrorTargetExisting
+{
+ const mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; //0777, default for newly created directories
+
+ if (::mkdir(dirPath.c_str(), mode) != 0)
+ {
+ const int lastError = errno; //copy before directly or indirectly making other system calls!
+ const std::wstring errorMsg = replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(dirPath));
+ const std::wstring errorDescr = formatSystemError(L"mkdir", lastError);
+
+ if (lastError == EEXIST)
+ throw ErrorTargetExisting(errorMsg, errorDescr);
+ //else if (lastError == ENOENT)
+ // throw ErrorTargetPathMissing(errorMsg, errorDescr);
+ throw FileError(errorMsg, errorDescr);
+ }
}
@@ -517,7 +537,7 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File
try
{
- copyNewDirectory(Zstring(), dirPath, false /*copyFilePermissions*/); //throw FileError, ErrorTargetExisting
+ createDirectory(dirPath); //throw FileError, ErrorTargetExisting
}
catch (FileError&)
{
@@ -525,13 +545,15 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File
try { pd = getPathStatus(dirPath); /*throw FileError*/ }
catch (FileError&) {} //previous exception is more relevant
- if (pd && pd->existingType != ItemType::FILE)
+ if (pd &&
+ pd->existingType != ItemType::FILE &&
+ pd->relPath.size() != 1) //don't repeat the very same createDirectory() call from above!
{
Zstring intermediatePath = pd->existingPath;
for (const Zstring& itemName : pd->relPath)
{
intermediatePath = appendSeparator(intermediatePath) + itemName;
- copyNewDirectory(Zstring(), intermediatePath, false /*copyFilePermissions*/); //throw FileError, (ErrorTargetExisting)
+ createDirectory(intermediatePath); //throw FileError, (ErrorTargetExisting)
}
return;
}
@@ -540,44 +562,8 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File
}
-//source path is optional (may be empty)
-void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, //throw FileError, ErrorTargetExisting
- bool copyFilePermissions)
+void zen::tryCopyDirectoryAttributes(const Zstring& sourcePath, const Zstring& targetPath) //throw FileError
{
- mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; //0777, default for newly created directories
-
- struct ::stat dirInfo = {};
- if (!sourcePath.empty())
- if (::stat(sourcePath.c_str(), &dirInfo) == 0)
- {
- 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
-
- if (::mkdir(targetPath.c_str(), mode) != 0)
- {
- const int lastError = errno; //copy before directly or indirectly making other system calls!
- const std::wstring errorMsg = replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(targetPath));
- const std::wstring errorDescr = formatSystemError(L"mkdir", lastError);
-
- if (lastError == EEXIST)
- throw ErrorTargetExisting(errorMsg, errorDescr);
- //else if (lastError == ENOENT)
- // throw ErrorTargetPathMissing(errorMsg, errorDescr);
- throw FileError(errorMsg, errorDescr);
- }
-
- if (!sourcePath.empty())
- {
-
- ZEN_ON_SCOPE_FAIL(try { removeDirectoryPlain(targetPath); }
- catch (FileError&) {}); //ensure cleanup:
-
- //enforce copying file permissions: it's advertized on GUI...
- if (copyFilePermissions)
- copyItemPermissions(sourcePath, targetPath, ProcSymlink::FOLLOW); //throw FileError
- }
}
diff --git a/zen/file_access.h b/zen/file_access.h
index a06e5b17..0a9b2d0c 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 modTime, ProcSymlink procSl); //throw FileError
+void setFileTime(const Zstring& filePath, time_t modTime, ProcSymlink procSl); //throw FileError
//symlink handling: always evaluate target
uint64_t getFileSize(const Zstring& filePath); //throw FileError
@@ -73,22 +73,27 @@ void removeDirectoryPlainRecursion(const Zstring& dirPath); //throw FileError; E
//rename file or directory: no copying!!!
void renameFile(const Zstring& itemPathOld, const Zstring& itemPathNew); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
-bool supportsPermissions(const Zstring& dirPath); //throw FileError, dereferences symlinks
+bool supportsPermissions(const Zstring& dirPath); //throw FileError, follows symlinks
+//copy permissions for files, directories or symbolic links: requires admin rights
+void copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPath, ProcSymlink procSl); //throw FileError
+
+void createDirectory(const Zstring& dirPath); //throw FileError, ErrorTargetExisting
//- no error if already existing
//- create recursively if parent directory is not existing
void createDirectoryIfMissingRecursion(const Zstring& dirPath); //throw FileError
-//fail if already existing or parent directory not existing:
-//source path is optional (may be empty)
-void copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath, bool copyFilePermissions); //throw FileError, ErrorTargetExisting
+//symlink handling: follow link!
+//expects existing source/target directories
+//reports note-worthy errors only
+void tryCopyDirectoryAttributes(const Zstring& sourcePath, const Zstring& targetPath); //throw FileError
void copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool copyFilePermissions); //throw FileError
struct FileCopyResult
{
uint64_t fileSize = 0;
- int64_t modTime = 0; //time_t-compatible (UTC)
+ time_t modTime = 0; //number of seconds since Jan. 1st 1970 UTC
FileId sourceFileId;
FileId targetFileId;
Opt<FileError> errorModTime; //failure to set modification time
diff --git a/zen/file_traverser.h b/zen/file_traverser.h
index e2085698..1f7142de 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 modTime; //number of seconds since Jan. 1st 1970 UTC
+ time_t modTime; //number of seconds since Jan. 1st 1970 UTC
};
struct FolderInfo
@@ -32,7 +32,7 @@ struct SymlinkInfo
{
Zstring itemName;
Zstring fullPath;
- int64_t modTime; //number of seconds since Jan. 1st 1970 UTC
+ time_t modTime; //number of seconds since Jan. 1st 1970 UTC
};
//- non-recursive
diff --git a/zen/guid.h b/zen/guid.h
index d88578a6..b34c3cbf 100755
--- a/zen/guid.h
+++ b/zen/guid.h
@@ -20,9 +20,11 @@ namespace zen
inline
std::string generateGUID() //creates a 16-byte GUID
{
- boost::uuids::uuid nativeRep = boost::uuids::random_generator()();
- //generator is only thread-safe like an int, so we keep it local until we need to optimize perf
- //perf: generator: 0.22ms per call; retrieve GUID: 0.12µs per call
+ //perf: generator: 0.38ms per creation;
+ // retrieve GUID: 0.13µs per call
+ //generator is only thread-safe like an int => keep thread-local
+ thread_local boost::uuids::random_generator gen;
+ const boost::uuids::uuid nativeRep = gen();
return std::string(nativeRep.begin(), nativeRep.end());
}
}
bgstack15