github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/os/dir_darwin.go (about) 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 package os 6 7 import ( 8 "io" 9 "runtime" 10 "syscall" 11 "unsafe" 12 ) 13 14 // Auxiliary information if the File describes a directory 15 type dirInfo struct { 16 dir uintptr // Pointer to DIR structure from dirent.h 17 } 18 19 func (d *dirInfo) close() { 20 if d.dir == 0 { 21 return 22 } 23 closedir(d.dir) 24 d.dir = 0 25 } 26 27 func (f *File) readdirnames(n int) (names []string, err error) { 28 if f.dirinfo == nil { 29 dir, call, errno := f.pfd.OpenDir() 30 if errno != nil { 31 return nil, wrapSyscallError(call, errno) 32 } 33 f.dirinfo = &dirInfo{ 34 dir: dir, 35 } 36 } 37 d := f.dirinfo 38 39 size := n 40 if size <= 0 { 41 size = 100 42 n = -1 43 } 44 45 names = make([]string, 0, size) 46 var dirent syscall.Dirent 47 var entptr *syscall.Dirent 48 for len(names) < size || n == -1 { 49 if res := readdir_r(d.dir, &dirent, &entptr); res != 0 { 50 return names, wrapSyscallError("readdir", syscall.Errno(res)) 51 } 52 if entptr == nil { // EOF 53 break 54 } 55 if dirent.Ino == 0 { 56 continue 57 } 58 name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:] 59 for i, c := range name { 60 if c == 0 { 61 name = name[:i] 62 break 63 } 64 } 65 // Check for useless names before allocating a string. 66 if string(name) == "." || string(name) == ".." { 67 continue 68 } 69 names = append(names, string(name)) 70 runtime.KeepAlive(f) 71 } 72 if n >= 0 && len(names) == 0 { 73 return names, io.EOF 74 } 75 return names, nil 76 } 77 78 // Implemented in syscall/syscall_darwin.go. 79 80 //go:linkname closedir syscall.closedir 81 func closedir(dir uintptr) (err error) 82 83 //go:linkname readdir_r syscall.readdir_r 84 func readdir_r(dir uintptr, entry *syscall.Dirent, result **syscall.Dirent) (res int)