github.com/rawahars/moby@v24.0.4+incompatible/pkg/loopback/loopback.go (about) 1 //go:build linux && cgo 2 // +build linux,cgo 3 4 package loopback // import "github.com/docker/docker/pkg/loopback" 5 6 import ( 7 "fmt" 8 "os" 9 10 "github.com/sirupsen/logrus" 11 "golang.org/x/sys/unix" 12 ) 13 14 func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) { 15 loopInfo, err := unix.IoctlLoopGetStatus64(int(file.Fd())) 16 if err != nil { 17 logrus.Errorf("Error get loopback backing file: %s", err) 18 return 0, 0, ErrGetLoopbackBackingFile 19 } 20 return loopInfo.Device, loopInfo.Inode, nil 21 } 22 23 // SetCapacity reloads the size for the loopback device. 24 func SetCapacity(file *os.File) error { 25 if err := unix.IoctlSetInt(int(file.Fd()), unix.LOOP_SET_CAPACITY, 0); err != nil { 26 logrus.Errorf("Error loopbackSetCapacity: %s", err) 27 return ErrSetCapacity 28 } 29 return nil 30 } 31 32 // FindLoopDeviceFor returns a loopback device file for the specified file which 33 // is backing file of a loop back device. 34 func FindLoopDeviceFor(file *os.File) *os.File { 35 var stat unix.Stat_t 36 err := unix.Stat(file.Name(), &stat) 37 if err != nil { 38 return nil 39 } 40 targetInode := stat.Ino 41 targetDevice := uint64(stat.Dev) //nolint: unconvert // the type is 32bit on mips 42 43 for i := 0; true; i++ { 44 path := fmt.Sprintf("/dev/loop%d", i) 45 46 file, err := os.OpenFile(path, os.O_RDWR, 0) 47 if err != nil { 48 if os.IsNotExist(err) { 49 return nil 50 } 51 52 // Ignore all errors until the first not-exist 53 // we want to continue looking for the file 54 continue 55 } 56 57 dev, inode, err := getLoopbackBackingFile(file) 58 if err == nil && dev == targetDevice && inode == targetInode { 59 return file 60 } 61 file.Close() 62 } 63 64 return nil 65 }