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
// 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 darwin
// +build arm arm64
 
package os
 
import (
   "io"
   "runtime"
   "syscall"
   "unsafe"
)
 
// Auxiliary information if the File describes a directory
type dirInfo struct {
   dir uintptr // Pointer to DIR structure from dirent.h
}
 
func (d *dirInfo) close() {
   if d.dir == 0 {
       return
   }
   closedir(d.dir)
   d.dir = 0
}
 
func (f *File) readdirnames(n int) (names []string, err error) {
   if f.dirinfo == nil {
       dir, call, errno := f.pfd.OpenDir()
       if errno != nil {
           return nil, wrapSyscallError(call, errno)
       }
       f.dirinfo = &dirInfo{
           dir: dir,
       }
   }
   d := f.dirinfo
 
   size := n
   if size <= 0 {
       size = 100
       n = -1
   }
 
   names = make([]string, 0, size)
   var dirent syscall.Dirent
   var entptr uintptr
   for len(names) < size {
       if res := readdir_r(d.dir, uintptr(unsafe.Pointer(&dirent)), uintptr(unsafe.Pointer(&entptr))); res != 0 {
           return names, wrapSyscallError("readdir", syscall.Errno(res))
       }
       if entptr == 0 { // EOF
           break
       }
       if dirent.Ino == 0 {
           continue
       }
       name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:]
       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
       }
       names = append(names, string(name))
       runtime.KeepAlive(f)
   }
   if n >= 0 && len(names) == 0 {
       return names, io.EOF
   }
   return names, nil
}
 
// Implemented in syscall/syscall_darwin.go.
 
//go:linkname closedir syscall.closedir
func closedir(dir uintptr) (err error)
 
//go:linkname readdir_r syscall.readdir_r
func readdir_r(dir, entry, result uintptr) (res int)