diff --git a/docs/manpage.md b/docs/manpage.md index aba7ed6e..c820db99 100644 --- a/docs/manpage.md +++ b/docs/manpage.md @@ -142,6 +142,7 @@ Device reference has one of the following values: * `/dev/XXX` path to specific device file, it can be either a path to real device/partition like `/dev/sda1`, `/dev/nvme0n1` or path to dm-mapper virtual device like `/dev/mapper/root` or `/dev/vg_mesos/lv_mesos_containers`. + * If the path does not start with `/dev/` and represents a regular file then booster will assume it is an image file of the root filesystem (e.g. erofs inside of an ISO). Booster will try to setup a loopback device and then mount it as a root filesystem. * `UUID=$UUID` or `/dev/disk/by-uuid/$UUID` references device by its filesystem/LUKS UUID. See notes about UUID formatting rules below. * `LABEL=$LABEL` or `/dev/disk/by-label/$LABEL` references device by its filesystem/LUKS label. * `PARTUUID=$UUID` or `/dev/disk/by-partuuid/$UUID` references device by GPT partition UUID. diff --git a/go.mod b/go.mod index 315ec37a..51373086 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/anatol/tang.go v0.0.0-20220716012326-2fda8b4503da github.com/anatol/vmtest v0.0.0-20230711210602-87511df0d4bc github.com/cavaliergopher/cpio v1.0.1 + github.com/freddierice/go-losetup/v2 v2.0.1 github.com/google/go-tpm v0.9.0 github.com/google/renameio/v2 v2.0.0 github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df diff --git a/go.sum b/go.sum index 7f9345a8..f97acce7 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etly github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d h1:CPqTNIigGweVPT4CYb+OO2E6XyRKFOmvTHwWRLgCAlE= github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d/go.mod h1:QX5ZVULjAfZJux/W62Y91HvCh9hyW6enAwcrrv/sLj0= +github.com/freddierice/go-losetup/v2 v2.0.1 h1:wPDx/Elu9nDV8y/CvIbEDz5Xi5Zo80y4h7MKbi3XaAI= +github.com/freddierice/go-losetup/v2 v2.0.1/go.mod h1:TEyBrvlOelsPEhfWD5rutNXDmUszBXuFnwT1kIQF4J8= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= diff --git a/init/blkinfo_test.go b/init/blkinfo_test.go index fa95ff92..3eed8757 100644 --- a/init/blkinfo_test.go +++ b/init/blkinfo_test.go @@ -62,11 +62,6 @@ func shell(script string, env ...string) error { return sh.Run() } -func fileExists(file string) bool { - _, err := os.Stat(file) - return err == nil -} - func TestBlkInfoFAT(t *testing.T) { checkFs(t, "fat", "fat", "2a341c62", "FATLBL", 10, "mkfs.vfat -F32 -n $LABEL -i $UUID $OUTPUT", nil) } diff --git a/init/main.go b/init/main.go index 200176e4..03de62a8 100644 --- a/init/main.go +++ b/init/main.go @@ -15,6 +15,7 @@ import ( "time" "unsafe" + "github.com/freddierice/go-losetup/v2" "github.com/yookoala/realpath" "golang.org/x/sys/unix" "gopkg.in/yaml.v3" @@ -856,6 +857,23 @@ func boost() error { } } + if cmdRoot.format == refPath { + rootFS := cmdRoot.data.(string) + if !strings.HasPrefix(rootFS, "/dev/") && fileExists(rootFS) { + // there is a special case when a root filesystem is a filesystem image rather than a device (e.g. in case of erofs inside of an ISO) + // so if it is just a regular file then we create a loopback device for it and then try to mount + dev, err := losetup.Attach(rootFS, 0, rootRw) + if err != nil { + return err + } + cmdRoot.data = dev.Path() + + if err := addBlockDevice(dev.Path(), true, nil); err != nil { + return err + } + } + } + if config.MountTimeout != 0 { // TODO: cancellable, timeout context? timeout := waitTimeout(&rootMounted, time.Duration(config.MountTimeout)*time.Second) diff --git a/init/util.go b/init/util.go index e619ad01..f088ca55 100644 --- a/init/util.go +++ b/init/util.go @@ -174,3 +174,8 @@ func unwrapExitError(err error) error { } return err } + +func fileExists(file string) bool { + _, err := os.Stat(file) + return err == nil +}