loopback.go 1.9 KB

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