diff options
Diffstat (limited to 'zen/file_traverser.cpp')
-rw-r--r-- | zen/file_traverser.cpp | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp index 3eb284e1..ef6d255c 100644 --- a/zen/file_traverser.cpp +++ b/zen/file_traverser.cpp @@ -28,8 +28,8 @@ using namespace zen; void zen::traverseFolder(const Zstring& dirPath, const std::function<void (const FileInfo& fi)>& onFile, - const std::function<void (const DirInfo& di)>& onDir, - const std::function<void (const SymlinkInfo& si)>& onLink, + const std::function<void (const FolderInfo& fi)>& onFolder, + const std::function<void (const SymlinkInfo& si)>& onSymlink, const std::function<void (const std::wstring& errorMsg)>& onError) { try @@ -41,12 +41,15 @@ void zen::traverseFolder(const Zstring& dirPath, { const DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls! if (ec == ERROR_FILE_NOT_FOUND) - { - //1. directory may not exist *or* 2. it is completely empty: not all directories contain "., .." entries, e.g. a drive's root directory; NetDrive - // -> FindFirstFile() is a nice example of violation of API design principle of single responsibility - if (dirExists(dirPath)) //yes, a race-condition, still the best we can do - return; - } + try + { + //1. directory may not exist *or* 2. it is completely empty: not all directories contain "., .." entries, e.g. a drive's root directory; NetDrive + // -> FindFirstFile() is a nice example of violating the API design principle of single responsibility + if (getItemType(dirPath) == ItemType::FOLDER) //throw FileError + return; + } + catch (FileError&) {} //previous exception is more relevant + throw FileError(replaceCpy(_("Cannot open directory %x."), L"%x", fmtPath(dirPath)), formatSystemError(L"FindFirstFile", ec)); } ZEN_ON_SCOPE_EXIT(::FindClose(hDir)); @@ -75,22 +78,23 @@ void zen::traverseFolder(const Zstring& dirPath, if (itemNameRaw[0] == 0) throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), L"FindNextFile: Data corruption; item with empty name."); - const Zstring& itemPath = appendSeparator(dirPath) + itemNameRaw; + const Zstring& itemName = itemNameRaw; + const Zstring& itemPath = appendSeparator(dirPath) + itemName; if (zen::isSymlink(findData)) //check first! { - if (onLink) - onLink({ itemPath, filetimeToTimeT(findData.ftLastWriteTime) }); + if (onSymlink) + onSymlink({ itemName, itemPath, filetimeToTimeT(findData.ftLastWriteTime) }); } else if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - if (onDir) - onDir({ itemPath }); + if (onFolder) + onFolder({ itemName, itemPath }); } else //a file { if (onFile) - onFile({ itemPath, get64BitUInt(findData.nFileSizeLow, findData.nFileSizeHigh), filetimeToTimeT(findData.ftLastWriteTime) }); + onFile({ itemName, itemPath, get64BitUInt(findData.nFileSizeLow, findData.nFileSizeHigh), filetimeToTimeT(findData.ftLastWriteTime) }); } } @@ -159,18 +163,18 @@ void zen::traverseFolder(const Zstring& dirPath, if (S_ISLNK(statData.st_mode)) //on Linux there is no distinction between file and directory symlinks! { - if (onLink) - onLink({ itemPath, statData.st_mtime}); + if (onSymlink) + onSymlink({ itemName, itemPath, statData.st_mtime}); } else if (S_ISDIR(statData.st_mode)) //a directory { - if (onDir) - onDir({ itemPath }); + if (onFolder) + onFolder({ itemName, itemPath }); } else //a file or named pipe, ect. { if (onFile) - onFile({ itemPath, makeUnsigned(statData.st_size), statData.st_mtime }); + onFile({ itemName, itemPath, makeUnsigned(statData.st_size), statData.st_mtime }); } /* It may be a good idea to not check "S_ISREG(statData.st_mode)" explicitly and to not issue an error message on other types to support these scenarios: |