...

Source file src/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go

Documentation: github.com/Microsoft/hcsshim/internal/wclayer

     1  //go:build windows
     2  
     3  package wclayer
     4  
     5  import (
     6  	"context"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/Microsoft/go-winio"
    11  	"github.com/Microsoft/hcsshim/internal/hcserror"
    12  	"github.com/Microsoft/hcsshim/internal/oc"
    13  	"go.opencensus.io/trace"
    14  )
    15  
    16  // ExportLayer will create a folder at exportFolderPath and fill that folder with
    17  // the transport format version of the layer identified by layerId. This transport
    18  // format includes any metadata required for later importing the layer (using
    19  // ImportLayer), and requires the full list of parent layer paths in order to
    20  // perform the export.
    21  func ExportLayer(ctx context.Context, path string, exportFolderPath string, parentLayerPaths []string) (err error) {
    22  	title := "hcsshim::ExportLayer"
    23  	ctx, span := oc.StartSpan(ctx, title)
    24  	defer span.End()
    25  	defer func() { oc.SetSpanStatus(span, err) }()
    26  	span.AddAttributes(
    27  		trace.StringAttribute("path", path),
    28  		trace.StringAttribute("exportFolderPath", exportFolderPath),
    29  		trace.StringAttribute("parentLayerPaths", strings.Join(parentLayerPaths, ", ")))
    30  
    31  	// Generate layer descriptors
    32  	layers, err := layerPathsToDescriptors(ctx, parentLayerPaths)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	err = exportLayer(&stdDriverInfo, path, exportFolderPath, layers)
    38  	if err != nil {
    39  		return hcserror.New(err, title, "")
    40  	}
    41  	return nil
    42  }
    43  
    44  // LayerReader is an interface that supports reading an existing container image layer.
    45  type LayerReader interface {
    46  	// Next advances to the next file and returns the name, size, and file info
    47  	Next() (string, int64, *winio.FileBasicInfo, error)
    48  	// LinkInfo returns the number of links and the file identifier for the current file.
    49  	LinkInfo() (uint32, *winio.FileIDInfo, error)
    50  	// Read reads data from the current file, in the format of a Win32 backup stream, and
    51  	// returns the number of bytes read.
    52  	Read(b []byte) (int, error)
    53  	// Close finishes the layer reading process and releases any resources.
    54  	Close() error
    55  }
    56  
    57  // NewLayerReader returns a new layer reader for reading the contents of an on-disk layer.
    58  // The caller must have taken the SeBackupPrivilege privilege
    59  // to call this and any methods on the resulting LayerReader.
    60  func NewLayerReader(ctx context.Context, path string, parentLayerPaths []string) (_ LayerReader, err error) {
    61  	ctx, span := oc.StartSpan(ctx, "hcsshim::NewLayerReader")
    62  	defer func() {
    63  		if err != nil {
    64  			oc.SetSpanStatus(span, err)
    65  			span.End()
    66  		}
    67  	}()
    68  	span.AddAttributes(
    69  		trace.StringAttribute("path", path),
    70  		trace.StringAttribute("parentLayerPaths", strings.Join(parentLayerPaths, ", ")))
    71  
    72  	if len(parentLayerPaths) == 0 {
    73  		// This is a base layer. It gets exported differently.
    74  		return newBaseLayerReader(path, span), nil
    75  	}
    76  
    77  	exportPath, err := os.MkdirTemp("", "hcs")
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	err = ExportLayer(ctx, path, exportPath, parentLayerPaths)
    82  	if err != nil {
    83  		os.RemoveAll(exportPath)
    84  		return nil, err
    85  	}
    86  	return &legacyLayerReaderWrapper{
    87  		ctx:               ctx,
    88  		s:                 span,
    89  		legacyLayerReader: newLegacyLayerReader(exportPath),
    90  	}, nil
    91  }
    92  
    93  type legacyLayerReaderWrapper struct {
    94  	ctx context.Context
    95  	s   *trace.Span
    96  
    97  	*legacyLayerReader
    98  }
    99  
   100  func (r *legacyLayerReaderWrapper) Close() (err error) {
   101  	defer r.s.End()
   102  	defer func() { oc.SetSpanStatus(r.s, err) }()
   103  
   104  	err = r.legacyLayerReader.Close()
   105  	os.RemoveAll(r.root)
   106  	return err
   107  }
   108  

View as plain text