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