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