diff options
Diffstat (limited to 'zen')
-rwxr-xr-x | zen/file_access.cpp | 72 | ||||
-rwxr-xr-x | zen/file_access.h | 17 | ||||
-rwxr-xr-x | zen/file_traverser.h | 4 | ||||
-rwxr-xr-x | zen/guid.h | 8 |
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 @@ -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()); } } |