private void CommonInit() { Contract.Assert(searchCriteria != null && searchData != null, "searchCriteria and searchData should be initialized"); // Execute searchCriteria against the current directory String searchPath = Path.InternalCombine(searchData.fullPath, searchCriteria); Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); // Open a Find handle #if MONO int error; _hnd = new SafeFindHandle(MonoIO.FindFirstFile(searchPath, out data.cFileName, out data.dwFileAttributes, out error)); #else _hnd = Win32Native.FindFirstFile(searchPath, data); #endif if (_hnd.IsInvalid) { #if MONO int hr = error; #else int hr = Marshal.GetLastWin32Error(); #endif if (hr != Win32Native.ERROR_FILE_NOT_FOUND && hr != Win32Native.ERROR_NO_MORE_FILES) { HandleError(hr, searchData.fullPath); } else { // flag this as empty only if we're searching just top directory // Used in fast path for top directory only empty = searchData.searchOption == SearchOption.TopDirectoryOnly; } } // fast path for TopDirectoryOnly. If we have a result, go ahead and set it to // current. If empty, dispose handle. if (searchData.searchOption == SearchOption.TopDirectoryOnly) { if (empty) { _hnd.Dispose(); } else { SearchResult searchResult = CreateSearchResult(searchData, data); if (_resultHandler.IsResultIncluded(searchResult)) { current = _resultHandler.CreateObject(searchResult); } } } // for AllDirectories, we first recurse into dirs, so cleanup and add searchData // to the stack else { _hnd.Dispose(); searchStack.Add(searchData); } }
[System.Security.SecurityCritical] // auto-generated private void AddSearchableDirsToStack(Directory.SearchData localSearchData) { Contract.Requires(localSearchData != null); String searchPath = Path.InternalCombine(localSearchData.fullPath, "*"); SafeFindHandle hnd = null; Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); try { // Get all files and dirs #if MONO int error; hnd = new SafeFindHandle(MonoIO.FindFirstFile(searchPath, out data.cFileName, out data.dwFileAttributes, out error)); #else hnd = Win32Native.FindFirstFile(searchPath, data); #endif if (hnd.IsInvalid) { #if MONO int hr = error; #else int hr = Marshal.GetLastWin32Error(); #endif // This could happen if the dir doesn't contain any files. // Continue with the recursive search though, eventually // searchStack will become empty if (hr == Win32Native.ERROR_FILE_NOT_FOUND || hr == Win32Native.ERROR_NO_MORE_FILES || hr == Win32Native.ERROR_PATH_NOT_FOUND) { return; } HandleError(hr, localSearchData.fullPath); } // Add subdirs to searchStack. Exempt ReparsePoints as appropriate int incr = 0; do { if (FileSystemEnumerableHelpers.IsDir(data)) { String tempFullPath = Path.InternalCombine(localSearchData.fullPath, data.cFileName); String tempUserPath = Path.InternalCombine(localSearchData.userPath, data.cFileName); SearchOption option = localSearchData.searchOption; #if EXCLUDE_REPARSEPOINTS // Traverse reparse points depending on the searchoption specified if ((searchDataSubDir.searchOption == SearchOption.AllDirectories) && (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_REPARSE_POINT))) { option = SearchOption.TopDirectoryOnly; } #endif // Setup search data for the sub directory and push it into the stack Directory.SearchData searchDataSubDir = new Directory.SearchData(tempFullPath, tempUserPath, option); searchStack.Insert(incr++, searchDataSubDir); } #if MONO } while (MonoIO.FindNextFile(hnd.DangerousGetHandle(), out data.cFileName, out data.dwFileAttributes, out error)); #else } while (Win32Native.FindNextFile(hnd, data)); #endif // We don't care about errors here }
public override bool MoveNext() { Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); switch (state) { case STATE_INIT: { if (empty) { state = STATE_FINISH; goto case STATE_FINISH; } if (searchData.searchOption == SearchOption.TopDirectoryOnly) { state = STATE_FIND_NEXT_FILE; if (current != null) { return(true); } else { goto case STATE_FIND_NEXT_FILE; } } else { state = STATE_SEARCH_NEXT_DIR; goto case STATE_SEARCH_NEXT_DIR; } } case STATE_SEARCH_NEXT_DIR: { Contract.Assert(searchData.searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly"); // Traverse directory structure. We need to get '*' while (searchStack.Count > 0) { searchData = searchStack[0]; Contract.Assert((searchData.fullPath != null), "fullpath can't be null!"); searchStack.RemoveAt(0); // Traverse the subdirs AddSearchableDirsToStack(searchData); // Execute searchCriteria against the current directory String searchPath = Path.InternalCombine(searchData.fullPath, searchCriteria); // Open a Find handle #if MONO int error; _hnd = new SafeFindHandle(MonoIO.FindFirstFile(searchPath, out data.cFileName, out data.dwFileAttributes, out error)); #else _hnd = Win32Native.FindFirstFile(searchPath, data); #endif if (_hnd.IsInvalid) { #if MONO int hr = error; #else int hr = Marshal.GetLastWin32Error(); #endif if (hr == Win32Native.ERROR_FILE_NOT_FOUND || hr == Win32Native.ERROR_NO_MORE_FILES || hr == Win32Native.ERROR_PATH_NOT_FOUND) { continue; } _hnd.Dispose(); HandleError(hr, searchData.fullPath); } state = STATE_FIND_NEXT_FILE; needsParentPathDiscoveryDemand = true; SearchResult searchResult = CreateSearchResult(searchData, data); if (_resultHandler.IsResultIncluded(searchResult)) { if (needsParentPathDiscoveryDemand) { DoDemand(searchData.fullPath); needsParentPathDiscoveryDemand = false; } current = _resultHandler.CreateObject(searchResult); return(true); } else { goto case STATE_FIND_NEXT_FILE; } } state = STATE_FINISH; goto case STATE_FINISH; } case STATE_FIND_NEXT_FILE: { if (searchData != null && _hnd != null) { // Keep asking for more matching files/dirs, add it to the list #if MONO int error; while (MonoIO.FindNextFile(_hnd.DangerousGetHandle(), out data.cFileName, out data.dwFileAttributes, out error)) #else while (Win32Native.FindNextFile(_hnd, data)) #endif { SearchResult searchResult = CreateSearchResult(searchData, data); if (_resultHandler.IsResultIncluded(searchResult)) { if (needsParentPathDiscoveryDemand) { DoDemand(searchData.fullPath); needsParentPathDiscoveryDemand = false; } current = _resultHandler.CreateObject(searchResult); return(true); } } #if MONO int hr = error; #else // Make sure we quit with a sensible error. int hr = Marshal.GetLastWin32Error(); #endif if (_hnd != null) { _hnd.Dispose(); } // ERROR_FILE_NOT_FOUND is valid here because if the top level // dir doen't contain any subdirs and matching files then // we will get here with this errorcode from the searchStack walk if ((hr != 0) && (hr != Win32Native.ERROR_NO_MORE_FILES) && (hr != Win32Native.ERROR_FILE_NOT_FOUND)) { HandleError(hr, searchData.fullPath); } } if (searchData.searchOption == SearchOption.TopDirectoryOnly) { state = STATE_FINISH; goto case STATE_FINISH; } else { state = STATE_SEARCH_NEXT_DIR; goto case STATE_SEARCH_NEXT_DIR; } } case STATE_FINISH: { Dispose(); break; } } return(false); }
static internal IEnumerable <FileSystemInfo> EnumerateFileSystemInfos(string basePath, string searchPattern, SearchOption searchOption) { Path.Validate(basePath); SafeFindHandle findHandle = null; try { string filePath; int nativeAttrs; string basePathWithPattern = Path.Combine(basePath, searchPattern); int nativeError; try {} finally { findHandle = new SafeFindHandle(MonoIO.FindFirstFile(basePathWithPattern, out filePath, out nativeAttrs, out nativeError)); } if (findHandle.IsInvalid) { MonoIOError error = (MonoIOError)nativeError; if (error != MonoIOError.ERROR_FILE_NOT_FOUND) { throw MonoIO.GetException(Path.GetDirectoryName(basePathWithPattern), error); } yield break; } do { if (filePath == null) { yield break; } if (filePath == "." || filePath == "..") { continue; } FileAttributes attrs = (FileAttributes)nativeAttrs; string fullPath = Path.Combine(basePath, filePath); if ((attrs & FileAttributes.ReparsePoint) == 0) { if ((attrs & FileAttributes.Directory) != 0) { yield return(new DirectoryInfo(fullPath)); } else { yield return(new FileInfo(fullPath)); } } if ((attrs & FileAttributes.Directory) != 0 && searchOption == SearchOption.AllDirectories) { foreach (FileSystemInfo child in EnumerateFileSystemInfos(fullPath, searchPattern, searchOption)) { yield return(child); } } } while (MonoIO.FindNextFile(findHandle.DangerousGetHandle(), out filePath, out nativeAttrs, out int _)); } finally { if (findHandle != null) { findHandle.Dispose(); } } }