mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-01 00:23:56 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			136 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package wclayer
 | |
| 
 | |
| import (
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 
 | |
| 	"github.com/Microsoft/go-winio"
 | |
| 	"github.com/Microsoft/hcsshim/internal/hcserror"
 | |
| 	"github.com/Microsoft/hcsshim/internal/safefile"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| // ImportLayer will take the contents of the folder at importFolderPath and import
 | |
| // that into a layer with the id layerId.  Note that in order to correctly populate
 | |
| // the layer and interperet the transport format, all parent layers must already
 | |
| // be present on the system at the paths provided in parentLayerPaths.
 | |
| func ImportLayer(path string, importFolderPath string, parentLayerPaths []string) (err error) {
 | |
| 	title := "hcsshim::ImportLayer"
 | |
| 	fields := logrus.Fields{
 | |
| 		"path":             path,
 | |
| 		"importFolderPath": importFolderPath,
 | |
| 	}
 | |
| 	logrus.WithFields(fields).Debug(title)
 | |
| 	defer func() {
 | |
| 		if err != nil {
 | |
| 			fields[logrus.ErrorKey] = err
 | |
| 			logrus.WithFields(fields).Error(err)
 | |
| 		} else {
 | |
| 			logrus.WithFields(fields).Debug(title + " - succeeded")
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	// Generate layer descriptors
 | |
| 	layers, err := layerPathsToDescriptors(parentLayerPaths)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	err = importLayer(&stdDriverInfo, path, importFolderPath, layers)
 | |
| 	if err != nil {
 | |
| 		return hcserror.New(err, title+" - failed", "")
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // LayerWriter is an interface that supports writing a new container image layer.
 | |
| type LayerWriter interface {
 | |
| 	// Add adds a file to the layer with given metadata.
 | |
| 	Add(name string, fileInfo *winio.FileBasicInfo) error
 | |
| 	// AddLink adds a hard link to the layer. The target must already have been added.
 | |
| 	AddLink(name string, target string) error
 | |
| 	// Remove removes a file that was present in a parent layer from the layer.
 | |
| 	Remove(name string) error
 | |
| 	// Write writes data to the current file. The data must be in the format of a Win32
 | |
| 	// backup stream.
 | |
| 	Write(b []byte) (int, error)
 | |
| 	// Close finishes the layer writing process and releases any resources.
 | |
| 	Close() error
 | |
| }
 | |
| 
 | |
| type legacyLayerWriterWrapper struct {
 | |
| 	*legacyLayerWriter
 | |
| 	path             string
 | |
| 	parentLayerPaths []string
 | |
| }
 | |
| 
 | |
| func (r *legacyLayerWriterWrapper) Close() error {
 | |
| 	defer os.RemoveAll(r.root.Name())
 | |
| 	defer r.legacyLayerWriter.CloseRoots()
 | |
| 	err := r.legacyLayerWriter.Close()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err = ImportLayer(r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	for _, name := range r.Tombstones {
 | |
| 		if err = safefile.RemoveRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	// Add any hard links that were collected.
 | |
| 	for _, lnk := range r.PendingLinks {
 | |
| 		if err = safefile.RemoveRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) {
 | |
| 			return err
 | |
| 		}
 | |
| 		if err = safefile.LinkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	// Prepare the utility VM for use if one is present in the layer.
 | |
| 	if r.HasUtilityVM {
 | |
| 		err := safefile.EnsureNotReparsePointRelative("UtilityVM", r.destRoot)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM"))
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // NewLayerWriter returns a new layer writer for creating a layer on disk.
 | |
| // The caller must have taken the SeBackupPrivilege and SeRestorePrivilege privileges
 | |
| // to call this and any methods on the resulting LayerWriter.
 | |
| func NewLayerWriter(path string, parentLayerPaths []string) (LayerWriter, error) {
 | |
| 	if len(parentLayerPaths) == 0 {
 | |
| 		// This is a base layer. It gets imported differently.
 | |
| 		f, err := safefile.OpenRoot(path)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		return &baseLayerWriter{
 | |
| 			root: f,
 | |
| 		}, nil
 | |
| 	}
 | |
| 
 | |
| 	importPath, err := ioutil.TempDir("", "hcs")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &legacyLayerWriterWrapper{
 | |
| 		legacyLayerWriter: w,
 | |
| 		path:              importPath,
 | |
| 		parentLayerPaths:  parentLayerPaths,
 | |
| 	}, nil
 | |
| }
 | 
