Esempio n. 1
0
        public static Result IterateDirectoryRecursively(IFileSystem fs, U8Span rootPath, FsIterationTask onEnterDir,
                                                         FsIterationTask onExitDir, FsIterationTask onFile)
        {
            DirectoryEntry entry    = default;
            Span <byte>    workPath = stackalloc byte[PathTools.MaxPathLength + 1];

            return(IterateDirectoryRecursively(fs, rootPath, workPath, ref entry, onEnterDir, onExitDir,
                                               onFile));
        }
Esempio n. 2
0
        private static Result IterateDirectoryRecursivelyImpl(IFileSystem fs, Span <byte> workPath,
                                                              ref DirectoryEntry dirEntry, FsIterationTask onEnterDir, FsIterationTask onExitDir, FsIterationTask onFile)
        {
            Result rc = fs.OpenDirectory(out IDirectory dir, new U8Span(workPath), OpenDirectoryMode.All);

            if (rc.IsFailure())
            {
                return(rc);
            }

            int parentLen = StringUtils.GetLength(workPath);

            // Read and handle entries.
            while (true)
            {
                // Read a single entry.
                rc = dir.Read(out long readCount, SpanHelpers.AsSpan(ref dirEntry));
                if (rc.IsFailure())
                {
                    return(rc);
                }

                // If we're out of entries, we're done.
                if (readCount == 0)
                {
                    break;
                }

                // Validate child path size.
                int  childNameLen  = StringUtils.GetLength(dirEntry.Name);
                bool isDir         = dirEntry.Type == DirectoryEntryType.Directory;
                int  separatorSize = isDir ? 1 : 0;

                if (parentLen + childNameLen + separatorSize >= workPath.Length)
                {
                    return(ResultFs.TooLongPath.Log());
                }

                // Set child path.
                StringUtils.Concat(workPath, dirEntry.Name);
                {
                    if (isDir)
                    {
                        // Enter directory.
                        rc = onEnterDir(new U8Span(workPath), ref dirEntry);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        // Append separator, recurse.
                        StringUtils.Concat(workPath, DirectorySeparator);

                        rc = IterateDirectoryRecursivelyImpl(fs, workPath, ref dirEntry, onEnterDir, onExitDir, onFile);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        // Exit directory.
                        rc = onExitDir(new U8Span(workPath), ref dirEntry);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }
                    else
                    {
                        // Call file handler.
                        rc = onFile(new U8Span(workPath), ref dirEntry);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }
                }

                // Restore parent path.
                workPath[parentLen] = StringTraits.NullTerminator;
            }

            return(Result.Success);
        }
Esempio n. 3
0
 public static Result IterateDirectoryRecursively(IFileSystem fs, FsIterationTask onEnterDir,
                                                  FsIterationTask onExitDir, FsIterationTask onFile)
 {
     return(IterateDirectoryRecursively(fs, RootPath, onEnterDir, onExitDir, onFile));
 }
Esempio n. 4
0
        public static Result IterateDirectoryRecursively(IFileSystem fs, U8Span rootPath, Span <byte> workPath,
                                                         ref DirectoryEntry dirEntry, FsIterationTask onEnterDir, FsIterationTask onExitDir, FsIterationTask onFile)
        {
            Abort.DoAbortUnless(workPath.Length >= PathTool.EntryNameLengthMax + 1);

            // Get size of the root path.
            int rootPathLen = StringUtils.GetLength(rootPath, PathTool.EntryNameLengthMax + 1);

            if (rootPathLen > PathTool.EntryNameLengthMax)
            {
                return(ResultFs.TooLongPath.Log());
            }

            // Copy root path in, add a / if necessary.
            rootPath.Value.Slice(0, rootPathLen).CopyTo(workPath);
            if (!PathTool.IsSeparator(workPath[rootPathLen - 1]))
            {
                workPath[rootPathLen++] = StringTraits.DirectorySeparator;
            }

            // Make sure the result path is still valid.
            if (rootPathLen > PathTool.EntryNameLengthMax)
            {
                return(ResultFs.TooLongPath.Log());
            }

            workPath[rootPathLen] = StringTraits.NullTerminator;

            return(IterateDirectoryRecursivelyImpl(fs, workPath, ref dirEntry, onEnterDir, onExitDir, onFile));
        }