// 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.//go:build aix || dragonfly || freebsd || (js && wasm) || wasip1 || linux || netbsd || openbsd || solarispackage osimport ()// Auxiliary information if the File describes a directorytype dirInfo struct { mu sync.Mutex buf *[]byte// buffer for directory I/O nbuf int// length of buf; return value from Getdirentries bufp int// location of next record in buf.}const (// More than 5760 to work around https://golang.org/issue/24015. blockSize = 8192)var dirBufPool = sync.Pool{New: func() any {// The buffer must be at least a block long. := make([]byte, blockSize)return & },}func ( *dirInfo) () {if .buf != nil {dirBufPool.Put(.buf) .buf = nil }}func ( *File) ( int, readdirMode) ( []string, []DirEntry, []FileInfo, error) {// If this file has no dirInfo, create one. := .dirinfo.Load()if == nil { = new(dirInfo) .dirinfo.Store() } .mu.Lock()defer .mu.Unlock()if .buf == nil { .buf = dirBufPool.Get().(*[]byte) }// Change the meaning of n for the implementation below. // // The n above was for the public interface of "if n <= 0, // Readdir returns all the FileInfo from the directory in a // single slice". // // But below, we use only negative to mean looping until the // end and positive to mean bounded, with positive // terminating at 0.if == 0 { = -1 }for != 0 {// Refill the buffer if necessaryif .bufp >= .nbuf { .bufp = 0varerror .nbuf, = .pfd.ReadDirent(*.buf)runtime.KeepAlive()if != nil {return , , , &PathError{Op: "readdirent", Path: .name, Err: } }if .nbuf <= 0 {// Optimization: we can return the buffer to the pool, there is nothing else to read.dirBufPool.Put(.buf) .buf = nilbreak// EOF } }// Drain the buffer := (*.buf)[.bufp:.nbuf] , := direntReclen()if ! || > uint64(len()) {break } := [:] .bufp += int() , := direntIno()if ! {break }// When building to wasip1, the host runtime might be running on Windows // or might expose a remote file system which does not have the concept // of inodes. Therefore, we cannot make the assumption that it is safe // to skip entries with zero inodes.if == 0 && runtime.GOOS != "wasip1" {continue }const = uint64(unsafe.Offsetof(syscall.Dirent{}.Name)) , := direntNamlen()if ! || + > uint64(len()) {break } := [ : +]for , := range {if == 0 { = [:]break } }// Check for useless names before allocating a string.ifstring() == "." || string() == ".." {continue }if > 0 { // see 'n == 0' comment above -- }if == readdirName { = append(, string()) } elseif == readdirDirEntry { , := newUnixDirent(.name, string(), direntType())ifIsNotExist() {// File disappeared between readdir and stat. // Treat as if it didn't exist.continue }if != nil {returnnil, , nil, } = append(, ) } else { , := lstat(.name + "/" + string())ifIsNotExist() {// File disappeared between readdir + stat. // Treat as if it didn't exist.continue }if != nil {returnnil, nil, , } = append(, ) } }if > 0 && len()+len()+len() == 0 {returnnil, nil, nil, io.EOF }return , , , nil}// readInt returns the size-bytes unsigned integer in native byte order at offset off.func readInt( []byte, , uintptr) ( uint64, bool) {iflen() < int(+) {return0, false }ifgoarch.BigEndian {returnreadIntBE([:], ), true }returnreadIntLE([:], ), true}func readIntBE( []byte, uintptr) uint64 {switch {case1:returnuint64([0])case2:returnuint64(byteorder.BeUint16())case4:returnuint64(byteorder.BeUint32())case8:returnuint64(byteorder.BeUint64())default:panic("syscall: readInt with unsupported size") }}func readIntLE( []byte, uintptr) uint64 {switch {case1:returnuint64([0])case2:returnuint64(byteorder.LeUint16())case4:returnuint64(byteorder.LeUint32())case8:returnuint64(byteorder.LeUint64())default:panic("syscall: readInt with unsupported size") }}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux 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 @zigo_101 (reachable from the left QR code) to get the latest news of Golds.