@@ -5,8 +5,10 @@ import (
55 "encoding/json"
66 "errors"
77 "fmt"
8+ "io"
89 "os"
910 "path/filepath"
11+ "strings"
1012 "sync"
1113 "syscall"
1214 "time"
@@ -32,6 +34,19 @@ const containerSizeToDiskSizeMultiplier = 2
3234const diskSizeMinimum = 10 * 1024 * 1024 * 1024 // 10GB
3335const imageMetaXattr = "user.bootc.meta"
3436
37+ // tempLosetupWrapperContents is a workaround for https://github.com/containers/bootc/pull/487/commits/89d34c7dbcb8a1fa161f812c6ba0a8b49ccbe00f
38+ const tempLosetupWrapperContents = `#!/bin/bash
39+ set -euo pipefail
40+ args=()
41+ for arg in "$@"; do
42+ case $arg in
43+ --direct-io=*) echo "ignoring: $arg" 1>&2;;
44+ *) args+="$arg" ;;
45+ esac
46+ done
47+ exec /usr/sbin/losetup "$@"
48+ `
49+
3550// DiskImageConfig defines configuration for the
3651type DiskImageConfig struct {
3752 Filesystem string
@@ -278,7 +293,20 @@ func (p *BootcDisk) pullImage() (err error) {
278293
279294// runInstallContainer runs the bootc installer in a container to create a disk image
280295func (p * BootcDisk ) runInstallContainer (quiet bool , config DiskImageConfig ) (err error ) {
281- createResponse , err := p .createInstallContainer (config )
296+ // Create a temporary external shell script with the contents of our losetup wrapper
297+ losetupTemp , err := os .CreateTemp (p .Directory , "losetup-wrapper" )
298+ if err != nil {
299+ return fmt .Errorf ("temp losetup wrapper: %w" , err )
300+ }
301+ defer os .Remove (losetupTemp .Name ())
302+ if _ , err := io .Copy (losetupTemp , strings .NewReader (tempLosetupWrapperContents )); err != nil {
303+ return fmt .Errorf ("temp losetup wrapper copy: %w" , err )
304+ }
305+ if err := losetupTemp .Chmod (0o755 ); err != nil {
306+ return fmt .Errorf ("temp losetup wrapper chmod: %w" , err )
307+ }
308+
309+ createResponse , err := p .createInstallContainer (config , losetupTemp .Name ())
282310 if err != nil {
283311 return fmt .Errorf ("failed to create container: %w" , err )
284312 }
@@ -360,7 +388,7 @@ func (p *BootcDisk) runInstallContainer(quiet bool, config DiskImageConfig) (err
360388}
361389
362390// createInstallContainer creates a container to run the bootc installer
363- func (p * BootcDisk ) createInstallContainer (config DiskImageConfig ) (createResponse types.ContainerCreateResponse , err error ) {
391+ func (p * BootcDisk ) createInstallContainer (config DiskImageConfig , tempLosetup string ) (createResponse types.ContainerCreateResponse , err error ) {
364392 privileged := true
365393 autoRemove := true
366394 labelNested := true
@@ -405,6 +433,13 @@ func (p *BootcDisk) createInstallContainer(config DiskImageConfig) (createRespon
405433 Destination : "/output" ,
406434 Type : "bind" ,
407435 },
436+ {
437+ Source : tempLosetup ,
438+ // Note that the default $PATH has /usr/local/sbin first
439+ Destination : "/usr/local/sbin/losetup" ,
440+ Type : "bind" ,
441+ Options : []string {"ro" },
442+ },
408443 },
409444 },
410445 ContainerSecurityConfig : specgen.ContainerSecurityConfig {
0 commit comments