github.com/hpcng/singularity@v3.1.1+incompatible/pkg/image/sif.go (about)

     1  // Copyright (c) 2018-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 image
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"os"
    12  	"syscall"
    13  
    14  	"github.com/sylabs/sif/pkg/sif"
    15  )
    16  
    17  const (
    18  	sifMagic = "\x53\x49\x46\x5f\x4d\x41\x47\x49\x43"
    19  )
    20  
    21  type sifFormat struct{}
    22  
    23  func (f *sifFormat) initializer(img *Image, fileinfo os.FileInfo) error {
    24  	if fileinfo.IsDir() {
    25  		return fmt.Errorf("not a SIF file image")
    26  	}
    27  	b := make([]byte, bufferSize)
    28  	if n, err := img.File.Read(b); err != nil || n != bufferSize {
    29  		return fmt.Errorf("can't read first %d bytes: %s", bufferSize, err)
    30  	}
    31  	if bytes.Index(b, []byte(sifMagic)) == -1 {
    32  		return fmt.Errorf("SIF magic not found")
    33  	}
    34  
    35  	// Load the SIF file
    36  	fimg, err := sif.LoadContainerFp(img.File, !img.Writable)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	// Get the default system partition image
    42  	part, _, err := fimg.GetPartPrimSys()
    43  	if err != nil {
    44  		return err
    45  	}
    46  
    47  	// record the fs type
    48  	fstype, err := part.GetFsType()
    49  	if err != nil {
    50  		return err
    51  	}
    52  	if fstype == sif.FsSquash {
    53  		img.Partitions[0].Type = SQUASHFS
    54  	} else if fstype == sif.FsExt3 {
    55  		img.Partitions[0].Type = EXT3
    56  	} else {
    57  		return fmt.Errorf("unknown file system type: %v", fstype)
    58  	}
    59  
    60  	img.Partitions[0].Offset = uint64(part.Fileoff)
    61  	img.Partitions[0].Size = uint64(part.Filelen)
    62  	img.Partitions[0].Name = RootFs
    63  
    64  	// store all remaining sections
    65  	img.Sections = make([]Section, 0)
    66  
    67  	for _, desc := range fimg.DescrArr {
    68  		if ptype, err := desc.GetPartType(); err == nil {
    69  			// overlay partitions
    70  			if ptype == sif.PartOverlay && part.Groupid == desc.Groupid && desc.Used {
    71  				fstype, err := desc.GetFsType()
    72  				if err != nil {
    73  					continue
    74  				}
    75  				partition := Section{
    76  					Offset: uint64(desc.Fileoff),
    77  					Size:   uint64(desc.Filelen),
    78  					Name:   desc.GetName(),
    79  				}
    80  				switch fstype {
    81  				case sif.FsSquash:
    82  					partition.Type = SQUASHFS
    83  				case sif.FsExt3:
    84  					partition.Type = EXT3
    85  				}
    86  				img.Partitions = append(img.Partitions, partition)
    87  			}
    88  		} else {
    89  			// anything else
    90  			if desc.Datatype != 0 {
    91  				data := Section{
    92  					Offset: uint64(desc.Fileoff),
    93  					Size:   uint64(desc.Filelen),
    94  					Type:   uint32(desc.Datatype),
    95  					Name:   desc.GetName(),
    96  				}
    97  				img.Sections = append(img.Sections, data)
    98  			}
    99  		}
   100  	}
   101  
   102  	img.Type = SIF
   103  
   104  	// UnloadContainer close image, just want to unmap image
   105  	// from memory
   106  	if fimg.Amodebuf == false {
   107  		if err := syscall.Munmap(fimg.Filedata); err != nil {
   108  			return fmt.Errorf("while calling unmapping SIF file")
   109  		}
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  func (f *sifFormat) openMode(writable bool) int {
   116  	if writable {
   117  		return os.O_RDWR
   118  	}
   119  	return os.O_RDONLY
   120  }