github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/go/os/dir.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 "sync/atomic" 10 "syscall" 11 "unsafe" 12 ) 13 14 //extern opendir 15 func libc_opendir(*byte) *syscall.DIR 16 17 //extern closedir 18 func libc_closedir(*syscall.DIR) int 19 20 // FIXME: pathconf returns long, not int. 21 //extern pathconf 22 func libc_pathconf(*byte, int) int 23 24 func clen(n []byte) int { 25 for i := 0; i < len(n); i++ { 26 if n[i] == 0 { 27 return i 28 } 29 } 30 return len(n) 31 } 32 33 var nameMax int32 34 35 func (file *File) readdirnames(n int) (names []string, err error) { 36 if file.dirinfo == nil { 37 p, err := syscall.BytePtrFromString(file.name) 38 if err != nil { 39 return nil, err 40 } 41 42 elen := int(atomic.LoadInt32(&nameMax)) 43 if elen == 0 { 44 syscall.Entersyscall() 45 plen := libc_pathconf(p, syscall.PC_NAME_MAX) 46 syscall.Exitsyscall() 47 if plen < 1024 { 48 plen = 1024 49 } 50 var dummy syscall.Dirent 51 elen = int(unsafe.Offsetof(dummy.Name)) + plen + 1 52 atomic.StoreInt32(&nameMax, int32(elen)) 53 } 54 55 syscall.Entersyscall() 56 r := libc_opendir(p) 57 errno := syscall.GetErrno() 58 syscall.Exitsyscall() 59 if r == nil { 60 return nil, &PathError{"opendir", file.name, errno} 61 } 62 63 file.dirinfo = new(dirInfo) 64 file.dirinfo.buf = make([]byte, elen) 65 file.dirinfo.dir = r 66 } 67 68 entryDirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0])) 69 70 size := n 71 if size <= 0 { 72 size = 100 73 n = -1 74 } 75 76 names = make([]string, 0, size) // Empty with room to grow. 77 78 for n != 0 { 79 var dirent *syscall.Dirent 80 pr := &dirent 81 syscall.Entersyscall() 82 i := libc_readdir_r(file.dirinfo.dir, entryDirent, pr) 83 syscall.Exitsyscall() 84 if i != 0 { 85 return names, NewSyscallError("readdir_r", i) 86 } 87 if dirent == nil { 88 break // EOF 89 } 90 bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) 91 var name = string(bytes[0:clen(bytes[:])]) 92 if name == "." || name == ".." { // Useless names 93 continue 94 } 95 names = append(names, name) 96 n-- 97 } 98 if n >= 0 && len(names) == 0 { 99 return names, io.EOF 100 } 101 return names, nil 102 }