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 }