github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/pkg/fsutils/fsutils_linux.go (about) 1 package fsutils // import "github.com/docker/docker/pkg/fsutils" 2 3 import ( 4 "fmt" 5 "os" 6 "unsafe" 7 8 "golang.org/x/sys/unix" 9 ) 10 11 func locateDummyIfEmpty(path string) (string, error) { 12 children, err := os.ReadDir(path) 13 if err != nil { 14 return "", err 15 } 16 if len(children) != 0 { 17 return "", nil 18 } 19 dummyFile, err := os.CreateTemp(path, "fsutils-dummy") 20 if err != nil { 21 return "", err 22 } 23 name := dummyFile.Name() 24 err = dummyFile.Close() 25 return name, err 26 } 27 28 // SupportsDType returns whether the filesystem mounted on path supports d_type 29 func SupportsDType(path string) (bool, error) { 30 // locate dummy so that we have at least one dirent 31 dummy, err := locateDummyIfEmpty(path) 32 if err != nil { 33 return false, err 34 } 35 if dummy != "" { 36 defer os.Remove(dummy) 37 } 38 39 visited := 0 40 supportsDType := true 41 fn := func(ent *unix.Dirent) bool { 42 visited++ 43 if ent.Type == unix.DT_UNKNOWN { 44 supportsDType = false 45 // stop iteration 46 return true 47 } 48 // continue iteration 49 return false 50 } 51 if err = iterateReadDir(path, fn); err != nil { 52 return false, err 53 } 54 if visited == 0 { 55 return false, fmt.Errorf("did not hit any dirent during iteration %s", path) 56 } 57 return supportsDType, nil 58 } 59 60 func iterateReadDir(path string, fn func(*unix.Dirent) bool) error { 61 d, err := os.Open(path) 62 if err != nil { 63 return err 64 } 65 defer d.Close() 66 fd := int(d.Fd()) 67 buf := make([]byte, 4096) 68 for { 69 nbytes, err := unix.ReadDirent(fd, buf) 70 if err != nil { 71 return err 72 } 73 if nbytes == 0 { 74 break 75 } 76 for off := 0; off < nbytes; { 77 ent := (*unix.Dirent)(unsafe.Pointer(&buf[off])) 78 if stop := fn(ent); stop { 79 return nil 80 } 81 off += int(ent.Reclen) 82 } 83 } 84 return nil 85 }