github.com/skanehira/moby@v17.12.1-ce-rc2+incompatible/pkg/loopback/loopback.go (about) 1 // +build linux,cgo 2 3 package 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.loDevice, loopInfo.loInode, 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 targetDevice := stat.Dev 41 42 for i := 0; true; i++ { 43 path := fmt.Sprintf("/dev/loop%d", i) 44 45 file, err := os.OpenFile(path, os.O_RDWR, 0) 46 if err != nil { 47 if os.IsNotExist(err) { 48 return nil 49 } 50 51 // Ignore all errors until the first not-exist 52 // we want to continue looking for the file 53 continue 54 } 55 56 dev, inode, err := getLoopbackBackingFile(file) 57 if err == nil && dev == targetDevice && inode == targetInode { 58 return file 59 } 60 file.Close() 61 } 62 63 return nil 64 }