Exemple #1
0
 private static Interop.libc.SafeDirHandle OpenDirectory(string fullPath)
 {
     Interop.libc.SafeDirHandle handle = Interop.libc.opendir(fullPath);
     if (handle.IsInvalid)
     {
         throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), fullPath, isDirectory: true);
     }
     return(handle);
 }
Exemple #2
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);
                    }
                }
            }
Exemple #3
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);
                    }
                }
            }