Source file src/os/dir_darwin.go

Documentation: os

     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) readdirnames(n int) (names []string, err error) {
    28  	if f.dirinfo == nil {
    29  		dir, call, errno := f.pfd.OpenDir()
    30  		if errno != nil {
    31  			return nil, wrapSyscallError(call, errno)
    32  		}
    33  		f.dirinfo = &dirInfo{
    34  			dir: dir,
    35  		}
    36  	}
    37  	d := f.dirinfo
    38  
    39  	size := n
    40  	if size <= 0 {
    41  		size = 100
    42  		n = -1
    43  	}
    44  
    45  	names = make([]string, 0, size)
    46  	var dirent syscall.Dirent
    47  	var entptr *syscall.Dirent
    48  	for len(names) < size || n == -1 {
    49  		if res := readdir_r(d.dir, &dirent, &entptr); res != 0 {
    50  			return names, wrapSyscallError("readdir", syscall.Errno(res))
    51  		}
    52  		if entptr == nil { // EOF
    53  			break
    54  		}
    55  		if dirent.Ino == 0 {
    56  			continue
    57  		}
    58  		name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:]
    59  		for i, c := range name {
    60  			if c == 0 {
    61  				name = name[:i]
    62  				break
    63  			}
    64  		}
    65  		// Check for useless names before allocating a string.
    66  		if string(name) == "." || string(name) == ".." {
    67  			continue
    68  		}
    69  		names = append(names, string(name))
    70  		runtime.KeepAlive(f)
    71  	}
    72  	if n >= 0 && len(names) == 0 {
    73  		return names, io.EOF
    74  	}
    75  	return names, nil
    76  }
    77  
    78  // Implemented in syscall/syscall_darwin.go.
    79  
    80  //go:linkname closedir syscall.closedir
    81  func closedir(dir uintptr) (err error)
    82  
    83  //go:linkname readdir_r syscall.readdir_r
    84  func readdir_r(dir uintptr, entry *syscall.Dirent, result **syscall.Dirent) (res int)
    85  

View as plain text