github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/build/sources/packer_ext3_linux.go (about)

     1  // Copyright (c) 2019, Sylabs Inc. All rights reserved.
     2  // This software is licensed under a 3-clause BSD license. Please consult the
     3  // LICENSE.md file distributed with the sources of this project regarding your
     4  // rights to use or distribute this software.
     5  
     6  package sources
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"os/exec"
    14  	"syscall"
    15  
    16  	args "github.com/sylabs/singularity/internal/pkg/runtime/engines/singularity/rpc"
    17  	"github.com/sylabs/singularity/internal/pkg/sylog"
    18  	"github.com/sylabs/singularity/pkg/build/types"
    19  	"github.com/sylabs/singularity/pkg/util/loop"
    20  )
    21  
    22  // Pack puts relevant objects in a Bundle!
    23  func (p *Ext3Packer) Pack() (*types.Bundle, error) {
    24  	rootfs := p.srcfile
    25  
    26  	err := p.unpackExt3(p.b, p.info, rootfs)
    27  	if err != nil {
    28  		sylog.Errorf("unpackExt3 Failed: %s", err)
    29  		return nil, err
    30  	}
    31  
    32  	return p.b, nil
    33  }
    34  
    35  // unpackExt3 mounts the ext3 image using a loop device and then copies its contents to the bundle
    36  func (p *Ext3Packer) unpackExt3(b *types.Bundle, info *loop.Info64, rootfs string) error {
    37  	tmpmnt, err := ioutil.TempDir(p.b.Path, "mnt")
    38  	if err != nil {
    39  		return fmt.Errorf("While making tmp mount point: %v", err)
    40  	}
    41  
    42  	var number int
    43  	info.Flags = loop.FlagsAutoClear
    44  	arguments := &args.LoopArgs{
    45  		Image: rootfs,
    46  		Mode:  os.O_RDONLY,
    47  		Info:  *info,
    48  	}
    49  	if err := getLoopDevice(arguments); err != nil {
    50  		return err
    51  	}
    52  
    53  	path := fmt.Sprintf("/dev/loop%d", number)
    54  	sylog.Debugf("Mounting loop device %s to %s\n", path, tmpmnt)
    55  	err = syscall.Mount(path, tmpmnt, "ext3", syscall.MS_NOSUID|syscall.MS_RDONLY|syscall.MS_NODEV, "errors=remount-ro")
    56  	if err != nil {
    57  		return fmt.Errorf("While mounting image: %v", err)
    58  	}
    59  	defer syscall.Unmount(tmpmnt, 0)
    60  
    61  	// copy filesystem into bundle rootfs
    62  	sylog.Debugf("Copying filesystem from %s to %s in Bundle\n", tmpmnt, b.Rootfs())
    63  	var stderr bytes.Buffer
    64  	cmd := exec.Command("cp", "-r", tmpmnt+`/.`, b.Rootfs())
    65  	cmd.Stderr = &stderr
    66  	if err := cmd.Run(); err != nil {
    67  		return fmt.Errorf("While copying files: %v: %v", err, stderr.String())
    68  	}
    69  
    70  	return err
    71  }
    72  
    73  // getLoopDevice attaches a loop device with the specified arguments
    74  func getLoopDevice(arguments *args.LoopArgs) error {
    75  	var reply int
    76  	reply = 1
    77  	loopdev := new(loop.Device)
    78  	loopdev.MaxLoopDevices = 256
    79  	loopdev.Info = &arguments.Info
    80  	loopdev.Shared = arguments.Shared
    81  
    82  	return loopdev.AttachFromPath(arguments.Image, arguments.Mode, &reply)
    83  }