dirwalk.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package dirwalk contains code to walk a directory.
  4. package dirwalk
  5. import (
  6. "io"
  7. "io/fs"
  8. "os"
  9. "go4.org/mem"
  10. )
  11. var osWalkShallow func(name mem.RO, fn WalkFunc) error
  12. // WalkFunc is the callback type used with WalkShallow.
  13. //
  14. // The name and de are only valid for the duration of func's call
  15. // and should not be retained.
  16. type WalkFunc func(name mem.RO, de fs.DirEntry) error
  17. // WalkShallow reads the entries in the named directory and calls fn for each.
  18. // It does not recurse into subdirectories.
  19. //
  20. // If fn returns an error, iteration stops and WalkShallow returns that value.
  21. //
  22. // On Linux, WalkShallow does not allocate, so long as certain methods on the
  23. // WalkFunc's DirEntry are not called which necessarily allocate.
  24. func WalkShallow(dirName mem.RO, fn WalkFunc) error {
  25. if f := osWalkShallow; f != nil {
  26. return f(dirName, fn)
  27. }
  28. of, err := os.Open(dirName.StringCopy())
  29. if err != nil {
  30. return err
  31. }
  32. defer of.Close()
  33. for {
  34. fis, err := of.ReadDir(100)
  35. for _, de := range fis {
  36. if err := fn(mem.S(de.Name()), de); err != nil {
  37. return err
  38. }
  39. }
  40. if err != nil {
  41. if err == io.EOF {
  42. return nil
  43. }
  44. return err
  45. }
  46. }
  47. }