pmbootstrap/pmb/install/losetup.py

82 lines
2.4 KiB
Python

# Copyright 2022 Oliver Smith
# SPDX-License-Identifier: GPL-3.0-or-later
import glob
import json
import logging
import os
import time
import pmb.helpers.mount
import pmb.helpers.run
import pmb.chroot
def init(args):
if not os.path.isdir("/sys/module/loop"):
pmb.helpers.run.root(args, ["modprobe", "loop"])
for loopdevice in glob.glob("/dev/loop*"):
if os.path.isdir(loopdevice):
continue
pmb.helpers.mount.bind_file(args, loopdevice,
args.work + "/chroot_native/" + loopdevice)
def mount(args, img_path):
"""
:param img_path: Path to the img file inside native chroot.
"""
logging.debug("(native) mount " + img_path + " (loop)")
# Try to mount multiple times (let the kernel module initialize #1594)
for i in range(0, 5):
# Retry
if i > 0:
logging.debug("loop module might not be initialized yet, retry in"
" one second...")
time.sleep(1)
# Mount and return on success
init(args)
losetup_cmd = ["losetup", "-f", img_path]
sector_size = args.deviceinfo["rootfs_image_sector_size"]
if sector_size:
losetup_cmd += ["-b", str(int(sector_size))]
pmb.chroot.root(args, losetup_cmd, check=False)
if device_by_back_file(args, img_path):
return
# Failure: raise exception
raise RuntimeError("Failed to mount loop device: " + img_path)
def device_by_back_file(args, back_file, auto_init=True):
"""
Get the /dev/loopX device that points to a specific image file.
"""
# Get list from losetup
losetup_output = pmb.chroot.root(args, ["losetup", "--json", "--list"],
output_return=True, auto_init=auto_init)
if not losetup_output:
return None
# Find the back_file
losetup = json.loads(losetup_output)
for loopdevice in losetup["loopdevices"]:
if loopdevice["back-file"] == back_file:
return loopdevice["name"]
return None
def umount(args, img_path, auto_init=True):
"""
:param img_path: Path to the img file inside native chroot.
"""
device = device_by_back_file(args, img_path, auto_init)
if not device:
return
logging.debug("(native) umount " + device)
pmb.chroot.root(args, ["losetup", "-d", device], auto_init=auto_init)