dirent.go 3.0 KB

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