private Win32FileSystemEnumerableIterator(string fullPath, string normalizedSearchPath, string searchCriteria, string userPath, SearchOption searchOption, SearchResultHandler <TSource> resultHandler) { _fullPath = fullPath; _normalizedSearchPath = normalizedSearchPath; _searchCriteria = searchCriteria; _resultHandler = resultHandler; _userPath = userPath; _searchOption = searchOption; if (searchCriteria != null) { PathInternal.CheckInvalidPathChars(fullPath); if (PathInternal.HasWildCardCharacters(fullPath)) { throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(fullPath)); } _searchData = new PathPair(userPath, normalizedSearchPath); CommonInit(); } else { _empty = true; } }
internal FileSystemEnumerable( string userPath, string searchPattern, SearchOption searchOption, SearchTarget searchTarget, Func <string, bool, T> translateResult) { // Basic validation of the input path if (userPath == null) { throw new ArgumentNullException("path"); } if (string.IsNullOrWhiteSpace(userPath)) { throw new ArgumentException(SR.Argument_EmptyPath, "path"); } // Validate and normalize the search pattern. If after doing so it's empty, // matching Win32 behavior we can skip all additional validation and effectively // return an empty enumerable. searchPattern = NormalizeSearchPattern(searchPattern); if (searchPattern.Length > 0) { PathHelpers.CheckSearchPattern(searchPattern); PathHelpers.ThrowIfEmptyOrRootedPath(searchPattern); // If the search pattern contains any paths, make sure we factor those into // the user path, and then trim them off. int lastSlash = searchPattern.LastIndexOf(Path.DirectorySeparatorChar); if (lastSlash >= 0) { if (lastSlash >= 1) { userPath = Path.Combine(userPath, searchPattern.Substring(0, lastSlash)); } searchPattern = searchPattern.Substring(lastSlash + 1); } string fullPath = Path.GetFullPath(userPath); // Store everything for the enumerator _initialDirectory = new PathPair(userPath, fullPath); _searchPattern = searchPattern; _searchOption = searchOption; _includeFiles = (searchTarget & SearchTarget.Files) != 0; _includeDirectories = (searchTarget & SearchTarget.Directories) != 0; _translateResult = translateResult; } // Open the first enumerator so that any errors are propagated synchronously. _firstEnumerator = Enumerate(); }
private Win32FileSystemEnumerableIterator(string fullPath, string normalizedSearchPath, string searchCriteria, string userPath, SearchOption searchOption, SearchResultHandler <TSource> resultHandler) { _fullPath = fullPath; _normalizedSearchPath = normalizedSearchPath; _searchCriteria = searchCriteria; _resultHandler = resultHandler; _userPath = userPath; _searchOption = searchOption; if (searchCriteria != null) { PathInternal.CheckInvalidPathChars(fullPath, true); _searchData = new PathPair(userPath, normalizedSearchPath); CommonInit(); } else { _empty = true; } }
internal Win32FileSystemEnumerableIterator(string path, string originalUserPath, string searchPattern, SearchOption searchOption, SearchResultHandler <TSource> resultHandler) { Contract.Requires(path != null); Contract.Requires(originalUserPath != null); Contract.Requires(searchPattern != null); Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly); Contract.Requires(resultHandler != null); _oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); string normalizedSearchPattern = PathHelpers.NormalizeSearchPattern(searchPattern); if (normalizedSearchPattern.Length == 0) { _empty = true; } else { _resultHandler = resultHandler; _searchOption = searchOption; _fullPath = Path.GetFullPath(path); string fullSearchString = PathHelpers.GetFullSearchString(_fullPath, normalizedSearchPattern); _normalizedSearchPath = Path.GetDirectoryName(fullSearchString); // normalize search criteria _searchCriteria = GetNormalizedSearchCriteria(fullSearchString, _normalizedSearchPath); // fix up user path string searchPatternDirName = Path.GetDirectoryName(normalizedSearchPattern); _userPath = string.IsNullOrEmpty(searchPatternDirName) ? originalUserPath : Path.Combine(originalUserPath, searchPatternDirName); _searchData = new PathPair(_userPath, _normalizedSearchPath); CommonInit(); } }
private IEnumerator <T> Enumerate(Interop.libc.SafeDirHandle dirHandle) { if (dirHandle == null) { // Empty search yield break; } Debug.Assert(!dirHandle.IsInvalid); Debug.Assert(!dirHandle.IsClosed); // Maintain a stack of the directories to explore, in the case of SearchOption.AllDirectories // Lazily-initialized only if we find subdirectories that will be explored. Stack <PathPair> toExplore = null; PathPair dirPath = _initialDirectory; while (dirHandle != null) { try { // Read each entry from the enumerator IntPtr curEntry; while ((curEntry = Interop.libc.readdir(dirHandle)) != IntPtr.Zero) // no validation needed for readdir { string name = Interop.libc.GetDirEntName(curEntry); // Get from the dir entry whether the entry is a file or directory. // We classify everything as a file unless we know it to be a directory, // e.g. a FIFO will be classified as a file. bool isDir; switch (Interop.libc.GetDirEntType(curEntry)) { case Interop.libc.DType.DT_DIR: // We know it's a directory. isDir = true; break; case Interop.libc.DType.DT_LNK: case Interop.libc.DType.DT_UNKNOWN: // It's a symlink or unknown: stat to it to see if we can resolve it to a directory. // If we can't (e.g.symlink to a file, broken symlink, etc.), we'll just treat it as a file. Interop.ErrorInfo errnoIgnored; isDir = DirectoryExists(Path.Combine(dirPath.FullPath, name), out errnoIgnored); break; default: // Otherwise, treat it as a file. This includes regular files, // FIFOs, etc. isDir = false; break; } // Yield the result if the user has asked for it. In the case of directories, // always explore it by pushing it onto the stack, regardless of whether // we're returning directories. if (isDir) { if (!ShouldIgnoreDirectory(name)) { if (_includeDirectories && Interop.libc.fnmatch(_searchPattern, name, Interop.libc.FnmatchFlags.None) == 0) { yield return(_translateResult(Path.Combine(dirPath.UserPath, name), /*isDirectory*/ true)); } if (_searchOption == SearchOption.AllDirectories) { if (toExplore == null) { toExplore = new Stack <PathPair>(); } toExplore.Push(new PathPair(Path.Combine(dirPath.UserPath, name), Path.Combine(dirPath.FullPath, name))); } } } else if (_includeFiles && Interop.libc.fnmatch(_searchPattern, name, Interop.libc.FnmatchFlags.None) == 0) { yield return(_translateResult(Path.Combine(dirPath.UserPath, name), /*isDirectory*/ false)); } } } finally { // Close the directory enumerator dirHandle.Dispose(); dirHandle = null; } if (toExplore != null && toExplore.Count > 0) { // Open the next directory. dirPath = toExplore.Pop(); dirHandle = OpenDirectory(dirPath.FullPath); } } }
[SecurityCritical] // auto-generated private void AddSearchableDirsToList(PathPair localSearchData) { string searchPath = Path.Combine(localSearchData.FullPath, "*"); SafeFindHandle hnd = null; Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); try { // Get all files and dirs hnd = Interop.mincore.FindFirstFile(searchPath, ref data); if (hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); // This could happen if the dir doesn't contain any files. // Continue with the recursive search though, eventually // _searchList will become empty if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NO_MORE_FILES || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { return; } HandleError(errorCode, localSearchData.FullPath); } // Add subdirs to _searchList. Exempt ReparsePoints as appropriate int initialCount = _searchList.Count; do { if (Win32FileSystemEnumerableHelpers.IsDir(ref data)) { Debug.Assert(data.cFileName.Length != 0 && !Path.IsPathRooted(data.cFileName), "Expected file system enumeration to not have empty file/directory name and not have rooted name"); string tempFullPath = Path.Combine(localSearchData.FullPath, data.cFileName); string tempUserPath = Path.Combine(localSearchData.UserPath, data.cFileName); // Setup search data for the sub directory and push it into the list PathPair searchDataSubDir = new PathPair(tempUserPath, tempFullPath); Debug.Assert(_searchList != null, "_searchList should not be null"); _searchList.Add(searchDataSubDir); } } while (Interop.mincore.FindNextFile(hnd, ref data)); // Reverse the items just added to maintain FIFO order if (_searchList.Count > initialCount) { _searchList.Reverse(initialCount, _searchList.Count - initialCount); } // We don't care about errors here } finally { if (hnd != null) { hnd.Dispose(); } } }
public override bool MoveNext() { Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); switch (state) { case STATE_INIT: { if (_empty) { state = STATE_FINISH; goto case STATE_FINISH; } if (_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: { Debug.Assert(_searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly"); Debug.Assert(_searchList != null, "_searchList should not be null"); // Traverse directory structure. We need to get '*' while (_searchList.Count > 0) { int index = _searchList.Count - 1; _searchData = _searchList[index]; Debug.Assert((_searchData.FullPath != null), "fullpath can't be null!"); _searchList.RemoveAt(index); // Traverse the subdirs AddSearchableDirsToList(_searchData); // Execute searchCriteria against the current directory string searchPath = Path.Combine(_searchData.FullPath, _searchCriteria); // Open a Find handle _hnd = Interop.mincore.FindFirstFile(searchPath, ref data); if (_hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NO_MORE_FILES || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { continue; } _hnd.Dispose(); HandleError(errorCode, _searchData.FullPath); } state = STATE_FIND_NEXT_FILE; TSource result; if (IsResultIncluded(ref data, out result)) { current = result; return(true); } else { goto case STATE_FIND_NEXT_FILE; } } state = STATE_FINISH; goto case STATE_FINISH; } case STATE_FIND_NEXT_FILE: { if (_hnd != null) { // Keep asking for more matching files/dirs, add it to the list while (Interop.mincore.FindNextFile(_hnd, ref data)) { TSource result; if (IsResultIncluded(ref data, out result)) { current = result; return(true); } } // Make sure we quit with a sensible error. int errorCode = Marshal.GetLastWin32Error(); if (_hnd != null) { _hnd.Dispose(); } // ERROR_FILE_NOT_FOUND is valid here because if the top level // dir doesn't contain any subdirs and matching files then // we will get here with this errorcode from the _searchList walk if ((errorCode != 0) && (errorCode != Interop.mincore.Errors.ERROR_NO_MORE_FILES) && (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND)) { HandleError(errorCode, _searchData.FullPath); } } if (_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); }
private IEnumerator <T> Enumerate(Microsoft.Win32.SafeHandles.SafeDirectoryHandle dirHandle) { if (dirHandle == null) { // Empty search yield break; } Debug.Assert(!dirHandle.IsInvalid); Debug.Assert(!dirHandle.IsClosed); // Maintain a stack of the directories to explore, in the case of SearchOption.AllDirectories // Lazily-initialized only if we find subdirectories that will be explored. Stack <PathPair> toExplore = null; PathPair dirPath = _initialDirectory; while (dirHandle != null) { try { // Read each entry from the enumerator Interop.Sys.DirectoryEntry dirent; while (Interop.Sys.ReadDir(dirHandle, out dirent) == 0) { // Get from the dir entry whether the entry is a file or directory. // We classify everything as a file unless we know it to be a directory. bool isDir; if (dirent.InodeType == Interop.Sys.NodeType.DT_DIR) { // We know it's a directory. isDir = true; } else if (dirent.InodeType == Interop.Sys.NodeType.DT_LNK || dirent.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) { // It's a symlink or unknown: stat to it to see if we can resolve it to a directory. // If we can't (e.g. symlink to a file, broken symlink, etc.), we'll just treat it as a file. Interop.ErrorInfo errnoIgnored; isDir = DirectoryExists(Path.Combine(dirPath.FullPath, dirent.InodeName), out errnoIgnored); } else { // Otherwise, treat it as a file. This includes regular files, FIFOs, etc. isDir = false; } // Yield the result if the user has asked for it. In the case of directories, // always explore it by pushing it onto the stack, regardless of whether // we're returning directories. if (isDir) { if (!ShouldIgnoreDirectory(dirent.InodeName)) { string userPath = null; if (_searchOption == SearchOption.AllDirectories) { if (toExplore == null) { toExplore = new Stack <PathPair>(); } userPath = Path.Combine(dirPath.UserPath, dirent.InodeName); toExplore.Push(new PathPair(userPath, Path.Combine(dirPath.FullPath, dirent.InodeName))); } if (_includeDirectories && Interop.Sys.FnMatch(_searchPattern, dirent.InodeName, Interop.Sys.FnMatchFlags.FNM_NONE) == 0) { yield return(_translateResult(userPath ?? Path.Combine(dirPath.UserPath, dirent.InodeName), /*isDirectory*/ true)); } } } else if (_includeFiles && Interop.Sys.FnMatch(_searchPattern, dirent.InodeName, Interop.Sys.FnMatchFlags.FNM_NONE) == 0) { yield return(_translateResult(Path.Combine(dirPath.UserPath, dirent.InodeName), /*isDirectory*/ false)); } } } finally { // Close the directory enumerator dirHandle.Dispose(); dirHandle = null; } if (toExplore != null && toExplore.Count > 0) { // Open the next directory. dirPath = toExplore.Pop(); dirHandle = OpenDirectory(dirPath.FullPath); } } }
private IEnumerator <T> Enumerate(Interop.libc.SafeDirHandle dirHandle) { if (dirHandle == null) { // Empty search yield break; } Debug.Assert(!dirHandle.IsInvalid); Debug.Assert(!dirHandle.IsClosed); // Maintain a stack of the directories to explore, in the case of SearchOption.AllDirectories // Lazily-initialized only if we find subdirectories that will be explored. Stack <PathPair> toExplore = null; PathPair dirPath = _initialDirectory; while (dirHandle != null) { try { // Read each entry from the enumerator IntPtr curEntry; while ((curEntry = Interop.libc.readdir(dirHandle)) != IntPtr.Zero) // no validation needed for readdir { string name = Interop.libc.GetDirEntName(curEntry); // Get from the dir entry whether the entry is a file or directory. // If we're not sure from the dir entry itself, stat to the entry. bool isDir = false, isFile = false; switch (Interop.libc.GetDirEntType(curEntry)) { case Interop.libc.DType.DT_DIR: isDir = true; break; case Interop.libc.DType.DT_REG: isFile = true; break; case Interop.libc.DType.DT_LNK: case Interop.libc.DType.DT_UNKNOWN: string fullPath = Path.Combine(dirPath.FullPath, name); Interop.libcoreclrpal.fileinfo fileinfo; while (Interop.CheckIo(Interop.libcoreclrpal.GetFileInformationFromPath(fullPath, out fileinfo), fullPath)) { ; } isDir = (fileinfo.mode & Interop.libcoreclrpal.FileTypes.S_IFMT) == Interop.libcoreclrpal.FileTypes.S_IFDIR; isFile = (fileinfo.mode & Interop.libcoreclrpal.FileTypes.S_IFMT) == Interop.libcoreclrpal.FileTypes.S_IFREG; break; } bool matchesSearchPattern = (isFile || isDir) && Interop.libc.fnmatch(_searchPattern, name, Interop.libc.FnmatchFlags.None) == 0; // Yield the result if the user has asked for it. In the case of directories, // always explore it by pushing it onto the stack, regardless of whether // we're returning directories. if (isDir && !ShouldIgnoreDirectory(name)) { if (_includeDirectories && matchesSearchPattern) { yield return(_translateResult(Path.Combine(dirPath.UserPath, name), /*isDirectory*/ true)); } if (_searchOption == SearchOption.AllDirectories) { if (toExplore == null) { toExplore = new Stack <PathPair>(); } toExplore.Push(new PathPair(Path.Combine(dirPath.UserPath, name), Path.Combine(dirPath.FullPath, name))); } } else if (isFile && _includeFiles && matchesSearchPattern) { yield return(_translateResult(Path.Combine(dirPath.UserPath, name), /*isDirectory*/ false)); } } } finally { // Close the directory enumerator dirHandle.Dispose(); dirHandle = null; } if (toExplore != null && toExplore.Count > 0) { // Open the next directory. dirPath = toExplore.Pop(); dirHandle = OpenDirectory(dirPath.FullPath); } } }
internal FileSystemEnumerable( string userPath, string searchPattern, SearchOption searchOption, SearchTarget searchTarget, Func <string, bool, T> translateResult) { // Basic validation of the input path if (userPath == null) { throw new ArgumentNullException("path"); } if (string.IsNullOrEmpty(userPath)) { throw new ArgumentException(SR.Argument_EmptyPath, "path"); } // Validate and normalize the search pattern. If after doing so it's empty, // matching Win32 behavior we can skip all additional validation and effectively // return an empty enumerable. searchPattern = NormalizeSearchPattern(searchPattern); if (searchPattern.Length > 0) { PathHelpers.ThrowIfEmptyOrRootedPath(searchPattern); // If the search pattern contains any paths, make sure we factor those into // the user path, and then trim them off. int lastSlash = searchPattern.LastIndexOf(Path.DirectorySeparatorChar); if (lastSlash >= 0) { if (lastSlash >= 1) { userPath = Path.Combine(userPath, searchPattern.Substring(0, lastSlash)); } searchPattern = searchPattern.Substring(lastSlash + 1); } // Typically we shouldn't see either of these cases, an upfront check is much faster foreach (char c in searchPattern) { if (c == '\\' || c == '[') { // We need to escape any escape characters in the search pattern searchPattern = searchPattern.Replace(@"\", @"\\"); // And then escape '[' to prevent it being picked up as a wildcard searchPattern = searchPattern.Replace(@"[", @"\["); break; } } string fullPath = Path.GetFullPath(userPath); // Store everything for the enumerator _initialDirectory = new PathPair(userPath, fullPath); _searchPattern = searchPattern; _searchOption = searchOption; _includeFiles = (searchTarget & SearchTarget.Files) != 0; _includeDirectories = (searchTarget & SearchTarget.Directories) != 0; _translateResult = translateResult; } // Open the first enumerator so that any errors are propagated synchronously. _firstEnumerator = Enumerate(); }
public WatcherItem(PathPair file, WatcherItemType type) { m_type = type; m_sFullPathFileName = file.m_sFull_FileName; m_sParsedFileName = file.m_sMatch_FileName; if (type == WatcherItemType.Added) fileInfo = new FileInfo(file.m_sFull_FileName); LogMyFilms.Debug("File monitor: " + m_sParsedFileName + " " + m_type); }