diff options
Diffstat (limited to 'vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go')
-rw-r--r-- | vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go b/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go new file mode 100644 index 0000000..f911617 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go | |||
@@ -0,0 +1,101 @@ | |||
1 | // Copyright 2019 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,go1.13 | ||
6 | |||
7 | package unix | ||
8 | |||
9 | import "unsafe" | ||
10 | |||
11 | //sys closedir(dir uintptr) (err error) | ||
12 | //sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) | ||
13 | |||
14 | func fdopendir(fd int) (dir uintptr, err error) { | ||
15 | r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0) | ||
16 | dir = uintptr(r0) | ||
17 | if e1 != 0 { | ||
18 | err = errnoErr(e1) | ||
19 | } | ||
20 | return | ||
21 | } | ||
22 | |||
23 | func libc_fdopendir_trampoline() | ||
24 | |||
25 | //go:linkname libc_fdopendir libc_fdopendir | ||
26 | //go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib" | ||
27 | |||
28 | func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { | ||
29 | // Simulate Getdirentries using fdopendir/readdir_r/closedir. | ||
30 | // We store the number of entries to skip in the seek | ||
31 | // offset of fd. See issue #31368. | ||
32 | // It's not the full required semantics, but should handle the case | ||
33 | // of calling Getdirentries or ReadDirent repeatedly. | ||
34 | // It won't handle assigning the results of lseek to *basep, or handle | ||
35 | // the directory being edited underfoot. | ||
36 | skip, err := Seek(fd, 0, 1 /* SEEK_CUR */) | ||
37 | if err != nil { | ||
38 | return 0, err | ||
39 | } | ||
40 | |||
41 | // We need to duplicate the incoming file descriptor | ||
42 | // because the caller expects to retain control of it, but | ||
43 | // fdopendir expects to take control of its argument. | ||
44 | // Just Dup'ing the file descriptor is not enough, as the | ||
45 | // result shares underlying state. Use Openat to make a really | ||
46 | // new file descriptor referring to the same directory. | ||
47 | fd2, err := Openat(fd, ".", O_RDONLY, 0) | ||
48 | if err != nil { | ||
49 | return 0, err | ||
50 | } | ||
51 | d, err := fdopendir(fd2) | ||
52 | if err != nil { | ||
53 | Close(fd2) | ||
54 | return 0, err | ||
55 | } | ||
56 | defer closedir(d) | ||
57 | |||
58 | var cnt int64 | ||
59 | for { | ||
60 | var entry Dirent | ||
61 | var entryp *Dirent | ||
62 | e := readdir_r(d, &entry, &entryp) | ||
63 | if e != 0 { | ||
64 | return n, errnoErr(e) | ||
65 | } | ||
66 | if entryp == nil { | ||
67 | break | ||
68 | } | ||
69 | if skip > 0 { | ||
70 | skip-- | ||
71 | cnt++ | ||
72 | continue | ||
73 | } | ||
74 | reclen := int(entry.Reclen) | ||
75 | if reclen > len(buf) { | ||
76 | // Not enough room. Return for now. | ||
77 | // The counter will let us know where we should start up again. | ||
78 | // Note: this strategy for suspending in the middle and | ||
79 | // restarting is O(n^2) in the length of the directory. Oh well. | ||
80 | break | ||
81 | } | ||
82 | // Copy entry into return buffer. | ||
83 | s := struct { | ||
84 | ptr unsafe.Pointer | ||
85 | siz int | ||
86 | cap int | ||
87 | }{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen} | ||
88 | copy(buf, *(*[]byte)(unsafe.Pointer(&s))) | ||
89 | buf = buf[reclen:] | ||
90 | n += reclen | ||
91 | cnt++ | ||
92 | } | ||
93 | // Set the seek offset of the input fd to record | ||
94 | // how many files we've already returned. | ||
95 | _, err = Seek(fd, cnt, 0 /* SEEK_SET */) | ||
96 | if err != nil { | ||
97 | return n, err | ||
98 | } | ||
99 | |||
100 | return n, nil | ||
101 | } | ||