OSDN Git Service

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