github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/pkg/loopback/loopback.go (about)

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