// Copyright 2019 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.//go:build darwin && go1.13// +build darwin,go1.13package uniximport ()//sys closedir(dir uintptr) (err error)//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)func ( int) ( uintptr, error) { , , := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(), 0, 0) = uintptr()if != 0 { = errnoErr() }return}varlibc_fdopendir_trampoline_addruintptr//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"func ( int, []byte, *uintptr) ( int, error) {// Simulate Getdirentries using fdopendir/readdir_r/closedir. // We store the number of entries to skip in the seek // offset of fd. See issue #31368. // It's not the full required semantics, but should handle the case // of calling Getdirentries or ReadDirent repeatedly. // It won't handle assigning the results of lseek to *basep, or handle // the directory being edited underfoot. , := Seek(, 0, 1/* SEEK_CUR */)if != nil {return0, }// We need to duplicate the incoming file descriptor // because the caller expects to retain control of it, but // fdopendir expects to take control of its argument. // Just Dup'ing the file descriptor is not enough, as the // result shares underlying state. Use Openat to make a really // new file descriptor referring to the same directory. , := Openat(, ".", O_RDONLY, 0)if != nil {return0, } , := fdopendir()if != nil {Close()return0, }deferclosedir()varint64for {varDirentvar *Dirent := readdir_r(, &, &)if != 0 {return , errnoErr() }if == nil {break }if > 0 { -- ++continue } := int(.Reclen)if > len() {// Not enough room. Return for now. // The counter will let us know where we should start up again. // Note: this strategy for suspending in the middle and // restarting is O(n^2) in the length of the directory. Oh well.break }// Copy entry into return buffer.var []byte := (*unsafeheader.Slice)(unsafe.Pointer(&)) .Data = unsafe.Pointer(&) .Cap = .Len = copy(, ) = [:] += ++ }// Set the seek offset of the input fd to record // how many files we've already returned. _, = Seek(, , 0/* SEEK_SET */)if != nil {return , }return , nil}
The pages are generated with Goldsv0.3.6. (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.