dirent.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
  5. // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
  6. package unix
  7. import "unsafe"
  8. // readInt returns the size-bytes unsigned integer in native byte order at offset off.
  9. func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
  10. if len(b) < int(off+size) {
  11. return 0, false
  12. }
  13. if isBigEndian {
  14. return readIntBE(b[off:], size), true
  15. }
  16. return readIntLE(b[off:], size), true
  17. }
  18. func readIntBE(b []byte, size uintptr) uint64 {
  19. switch size {
  20. case 1:
  21. return uint64(b[0])
  22. case 2:
  23. _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
  24. return uint64(b[1]) | uint64(b[0])<<8
  25. case 4:
  26. _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
  27. return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
  28. case 8:
  29. _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
  30. return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
  31. uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
  32. default:
  33. panic("syscall: readInt with unsupported size")
  34. }
  35. }
  36. func readIntLE(b []byte, size uintptr) uint64 {
  37. switch size {
  38. case 1:
  39. return uint64(b[0])
  40. case 2:
  41. _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
  42. return uint64(b[0]) | uint64(b[1])<<8
  43. case 4:
  44. _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
  45. return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
  46. case 8:
  47. _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
  48. return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
  49. uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
  50. default:
  51. panic("syscall: readInt with unsupported size")
  52. }
  53. }
  54. // ParseDirent parses up to max directory entries in buf,
  55. // appending the names to names. It returns the number of
  56. // bytes consumed from buf, the number of entries added
  57. // to names, and the new names slice.
  58. func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
  59. origlen := len(buf)
  60. count = 0
  61. for max != 0 && len(buf) > 0 {
  62. reclen, ok := direntReclen(buf)
  63. if !ok || reclen > uint64(len(buf)) {
  64. return origlen, count, names
  65. }
  66. rec := buf[:reclen]
  67. buf = buf[reclen:]
  68. ino, ok := direntIno(rec)
  69. if !ok {
  70. break
  71. }
  72. if ino == 0 { // File absent in directory.
  73. continue
  74. }
  75. const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
  76. namlen, ok := direntNamlen(rec)
  77. if !ok || namoff+namlen > uint64(len(rec)) {
  78. break
  79. }
  80. name := rec[namoff : namoff+namlen]
  81. for i, c := range name {
  82. if c == 0 {
  83. name = name[:i]
  84. break
  85. }
  86. }
  87. // Check for useless names before allocating a string.
  88. if string(name) == "." || string(name) == ".." {
  89. continue
  90. }
  91. max--
  92. count++
  93. names = append(names, string(name))
  94. }
  95. return origlen - len(buf), count, names
  96. }