github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/pkg/loopback/loopback.go (about) 1 // +build linux,cgo 2 3 package loopback // import "github.com/demonoid81/moby/pkg/loopback" 4 5 import ( 6 "fmt" 7 "os" 8 9 "github.com/sirupsen/logrus" 10 "golang.org/x/sys/unix" 11 ) 12 13 func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) { 14 loopInfo, err := ioctlLoopGetStatus64(file.Fd()) 15 if err != nil { 16 logrus.Errorf("Error get loopback backing file: %s", err) 17 return 0, 0, ErrGetLoopbackBackingFile 18 } 19 return loopInfo.Device, loopInfo.Inode, nil 20 } 21 22 // SetCapacity reloads the size for the loopback device. 23 func SetCapacity(file *os.File) error { 24 if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil { 25 logrus.Errorf("Error loopbackSetCapacity: %s", err) 26 return ErrSetCapacity 27 } 28 return nil 29 } 30 31 // FindLoopDeviceFor returns a loopback device file for the specified file which 32 // is backing file of a loop back device. 33 func FindLoopDeviceFor(file *os.File) *os.File { 34 var stat unix.Stat_t 35 err := unix.Stat(file.Name(), &stat) 36 if err != nil { 37 return nil 38 } 39 targetInode := stat.Ino 40 // the type is 32bit on mips 41 targetDevice := uint64(stat.Dev) // nolint: unconvert 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 }