github.com/charlievieth/fastwalk@v1.0.3/dirent.go (about)

     1  package fastwalk
     2  
     3  import (
     4  	"io/fs"
     5  	"os"
     6  	"sync"
     7  	"sync/atomic"
     8  	"unsafe"
     9  )
    10  
    11  type fileInfo struct {
    12  	once sync.Once
    13  	fs.FileInfo
    14  	err error
    15  }
    16  
    17  func loadFileInfo(pinfo **fileInfo) *fileInfo {
    18  	ptr := (*unsafe.Pointer)(unsafe.Pointer(pinfo))
    19  	fi := (*fileInfo)(atomic.LoadPointer(ptr))
    20  	if fi == nil {
    21  		fi = &fileInfo{}
    22  		if !atomic.CompareAndSwapPointer(
    23  			(*unsafe.Pointer)(unsafe.Pointer(pinfo)), // adrr
    24  			nil,                                      // old
    25  			unsafe.Pointer(fi),                       // new
    26  		) {
    27  			fi = (*fileInfo)(atomic.LoadPointer(ptr))
    28  		}
    29  	}
    30  	return fi
    31  }
    32  
    33  // StatDirEntry returns the fs.FileInfo for the file or subdirectory described
    34  // by the entry.  If the entry is a symbolic link, StatDirEntry returns the
    35  // fs.FileInfo for the file the line references (os.Stat).
    36  // If fs.DirEntry de is a fastwalk.DirEntry it's Stat() method is used and the
    37  // returned fs.FileInfo may be a previously cached result.
    38  func StatDirEntry(path string, de fs.DirEntry) (fs.FileInfo, error) {
    39  	if de.Type()&os.ModeSymlink == 0 {
    40  		return de.Info()
    41  	}
    42  	if d, ok := de.(DirEntry); ok {
    43  		return d.Stat()
    44  	}
    45  	return os.Stat(path)
    46  }