github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/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) seekInvalidate() { 28 if f.dirinfo == nil { 29 return 30 } 31 // Free cached dirinfo, so we allocate a new one if we 32 // access this file as a directory again. See #35767. 33 f.dirinfo.close() 34 f.dirinfo = nil 35 } 36 37 func (f *File) readdirnames(n int) (names []string, err error) { 38 if f.dirinfo == nil { 39 dir, call, errno := f.pfd.OpenDir() 40 if errno != nil { 41 return nil, wrapSyscallError(call, errno) 42 } 43 f.dirinfo = &dirInfo{ 44 dir: dir, 45 } 46 } 47 d := f.dirinfo 48 49 size := n 50 if size <= 0 { 51 size = 100 52 n = -1 53 } 54 55 names = make([]string, 0, size) 56 var dirent syscall.Dirent 57 var entptr *syscall.Dirent 58 for len(names) < size || n == -1 { 59 if res := readdir_r(d.dir, &dirent, &entptr); res != 0 { 60 return names, wrapSyscallError("readdir", syscall.Errno(res)) 61 } 62 if entptr == nil { // EOF 63 break 64 } 65 if dirent.Ino == 0 { 66 continue 67 } 68 name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:] 69 for i, c := range name { 70 if c == 0 { 71 name = name[:i] 72 break 73 } 74 } 75 // Check for useless names before allocating a string. 76 if string(name) == "." || string(name) == ".." { 77 continue 78 } 79 names = append(names, string(name)) 80 runtime.KeepAlive(f) 81 } 82 if n >= 0 && len(names) == 0 { 83 return names, io.EOF 84 } 85 return names, nil 86 } 87 88 // Implemented in syscall/syscall_darwin.go. 89 90 //go:linkname closedir syscall.closedir 91 func closedir(dir uintptr) (err error) 92 93 //go:linkname readdir_r syscall.readdir_r 94 func readdir_r(dir uintptr, entry *syscall.Dirent, result **syscall.Dirent) (res int)