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