diff --git a/far/changelog b/far/changelog index eb72891522..6c6882d00f 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,9 @@ +drkns 30.09.2017 23:23:55 +0100 - build 5054 + +1. С форума: Search stops after folder (symlink) excluded in filter. + +2. Уточнение поиска в альтернативных потоках. + zg 01.10.2017 00:05:03 +0300 - build 5053 1. ошибочная посылка DN_CONTROLINPUT с Param1=-1 на любое передвижение мыши, если в первый раз вернули TRUE. diff --git a/far/findfile.cpp b/far/findfile.cpp index 0a58786103..53ec0f0476 100644 --- a/far/findfile.cpp +++ b/far/findfile.cpp @@ -2185,99 +2185,59 @@ void background_searcher::DoScanTree(const string& strRoot) while (!Stopped() && ScTree.GetNextName(FindData, strFullName)) { - os::fs::enum_streams StreamsEnumerator(strFullName); - os::fs::enum_streams::const_iterator StreamsIterator; - Sleep(0); PauseEvent.wait(); - bool bContinue=false; - string strFindDataFileName=FindData.strFileName; - - // process default stream first - bool ProcessAlternateStreams = false; - while (!Stopped()) + const auto& ProcessStream = [&](const string& FullStreamName) { - auto strFullStreamName = strFullName; - - if (ProcessAlternateStreams) + enumFileInFilterType foundType; + if (UseFilter && !m_Owner->GetFilter()->FileInFilter(FindData, &foundType, &FullStreamName)) { - StreamsIterator = StreamsIterator? std::next(StreamsIterator) : StreamsEnumerator.cbegin(); - - if (StreamsIterator != StreamsEnumerator.cend()) - { - const auto& StreamData = *StreamsIterator; - - const auto NameBegin = StreamData.cStreamName + 1; - const auto NameEnd = wcschr(NameBegin, L':'); - const string_view StreamName(NameBegin, NameEnd? NameEnd - NameBegin : wcslen(NameBegin)); - - if (StreamName.empty()) // default stream has already been processed - continue; + // сюда заходим, если не попали в фильтр или попали в Exclude-фильтр + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && foundType == FIFT_EXCLUDE) + ScTree.SkipDir(); // скипаем только по Exclude-фильтру, т.к. глубже тоже нужно просмотреть + return; + } - append(strFullStreamName, L':', StreamName); - FindData.strFileName = strFindDataFileName + StreamName; - FindData.nFileSize = StreamData.StreamSize.QuadPart; - FindData.dwFileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; - } - else - { - if (bContinue) - { - break; - } - } + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + m_Owner->itd->SetFindMessage(FullStreamName); } - if (UseFilter) + if (IsFileIncluded(nullptr, FullStreamName, FindData.dwFileAttributes, strFullName)) { - enumFileInFilterType foundType; + m_Owner->m_Messages.emplace(FullStreamName, FindData, nullptr, nullptr, nullptr); + } - if (!m_Owner->GetFilter()->FileInFilter(FindData, &foundType, &strFullName)) - { - // сюда заходим, если не попали в фильтр или попали в Exclude-фильтр - if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && foundType==FIFT_EXCLUDE) - ScTree.SkipDir(); // скипаем только по Exclude-фильтру, т.к. глубже тоже нужно просмотреть + if (SearchInArchives) + ArchiveSearch(FullStreamName); + }; - { - bContinue=true; + // default stream first: + ProcessStream(strFullName); - if (ProcessAlternateStreams) - { - continue; - } - else - { - break; - } - } - } - } + // now the rest: + if (Global->Opt->FindOpt.FindAlternateStreams) + { + const auto FindDataFileName = FindData.strFileName; - if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + for(const auto& StreamData: os::fs::enum_streams(strFullName)) { - m_Owner->itd->SetFindMessage(strFullName); - } + const auto NameBegin = StreamData.cStreamName + 1; + const auto NameEnd = wcschr(NameBegin, L':'); + const string_view StreamName(NameBegin, NameEnd? NameEnd - NameBegin : wcslen(NameBegin)); - if (IsFileIncluded(nullptr,strFullStreamName,FindData.dwFileAttributes,strFullName)) - { - m_Owner->m_Messages.emplace(strFullStreamName, FindData, nullptr, nullptr, nullptr); - } + if (StreamName.empty()) // default stream has already been processed + continue; - ProcessAlternateStreams = Global->Opt->FindOpt.FindAlternateStreams; - if (!ProcessAlternateStreams || StreamsIterator == StreamsEnumerator.cend()) - { - break; - } - } + const auto FullStreamName = concat(strFullName, L':', StreamName); + FindData.strFileName = concat(FindDataFileName, L':', StreamName); + FindData.nFileSize = StreamData.StreamSize.QuadPart; + FindData.dwFileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; - if (bContinue) - { - continue; + ProcessStream(FullStreamName); + } } - - if (SearchInArchives) - ArchiveSearch(strFullName); } if (SearchMode!=FINDAREA_SELECTED) diff --git a/far/scantree.cpp b/far/scantree.cpp index 2aa73fd534..f866d3c095 100644 --- a/far/scantree.cpp +++ b/far/scantree.cpp @@ -80,26 +80,31 @@ ScanTree::ScanTree(bool RetUpDir, bool Recurse, int ScanJunction) Flags.Change(FSCANTREE_SCANSYMLINK, ScanJunction == -1? Global->Opt->ScanJunction.Get() : ScanJunction != 0); } -ScanTree::~ScanTree() -{ -} +ScanTree::~ScanTree() = default; void ScanTree::SetFindPath(const string& Path,const string& Mask, const DWORD NewScanFlags) { ScanItems.clear(); - ScanItems.emplace_back(); + Flags.Clear(FSCANTREE_FILESFIRST); + strFindMask = Mask; - strFindPath = Path; - strFindPathOriginal = strFindPath; + + strFindPathOriginal = Path; AddEndSlash(strFindPathOriginal); - strFindPath = ConvertNameToReal(strFindPath); - strFindPath = NTPath(strFindPath); - ScanItems.back().RealPath = strFindPath; - ScanItems.back().ActiveDirectories.emplace(strFindPath); + + strFindPath = NTPath(ConvertNameToReal(Path)); + + scantree_item Item; + Item.RealPath = strFindPath; + Item.ActiveDirectories.emplace(strFindPath); + AddEndSlash(strFindPath); strFindPath += strFindMask; + Flags.Set((Flags.Flags()&0x0000FFFF)|(NewScanFlags&0xFFFF0000)); + + ScanItems.emplace_back(std::move(Item)); } bool ScanTree::GetNextName(os::fs::find_data& fdata,string &strFullName) @@ -249,6 +254,21 @@ void ScanTree::SkipDir() if (ScanItems.empty()) return; + { + const auto& Current = ScanItems.back(); + if (!Flags.Check(FSCANTREE_SCANSYMLINK) && + Current.Find && + Current.Iterator != Current.Find->end() && + (Current.Iterator->dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT) + ) + { + // The current item is a directory link but we don't treat it as a directory so it's nothing to skip + // (perhaps it could have been better to add a special flag for this case rather than the quite complex condition above, + // but these flags is already a mess). + return; + } + } + ScanItems.pop_back(); if (ScanItems.empty()) diff --git a/far/vbuild.m4 b/far/vbuild.m4 index 1b219aad57..92045eb70e 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -m4_define(BUILD,5053)m4_dnl +m4_define(BUILD,5054)m4_dnl