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;
            }
        }
Ejemplo n.º 2
0
            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();
            }
Ejemplo n.º 3
0
        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();
            }
        }
Ejemplo n.º 5
0
            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);
        }
Ejemplo n.º 8
0
            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);
                    }
                }
            }
Ejemplo n.º 9
0
            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);
                    }
                }
            }
Ejemplo n.º 10
0
            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();
            }
Ejemplo n.º 11
0
 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);
 }