wip: vendor: update buildkit to master@7e4280003fa5

Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
Justin Chadwell
2023-07-11 16:06:39 +01:00
parent a65131f9d3
commit e7bed5b8d3
611 changed files with 85713 additions and 231 deletions

View File

@@ -0,0 +1,3 @@
// Package ociwclayer provides functions for importing and exporting Windows
// container layers from and to their OCI tar representation.
package ociwclayer

View File

@@ -0,0 +1,109 @@
//go:build windows
package ociwclayer
import (
"archive/tar"
"context"
"io"
"path/filepath"
"github.com/Microsoft/go-winio/backuptar"
"github.com/Microsoft/hcsshim/internal/wclayer"
)
// ExportLayerToTar writes an OCI layer tar stream from the provided on-disk layer.
// The caller must specify the parent layers, if any, ordered from lowest to
// highest layer.
//
// The layer will be mounted for this process, so the caller should ensure that
// it is not currently mounted.
func ExportLayerToTar(ctx context.Context, w io.Writer, path string, parentLayerPaths []string) error {
err := wclayer.ActivateLayer(ctx, path)
if err != nil {
return err
}
defer func() {
_ = wclayer.DeactivateLayer(ctx, path)
}()
// Prepare and unprepare the layer to ensure that it has been initialized.
err = wclayer.PrepareLayer(ctx, path, parentLayerPaths)
if err != nil {
return err
}
err = wclayer.UnprepareLayer(ctx, path)
if err != nil {
return err
}
r, err := wclayer.NewLayerReader(ctx, path, parentLayerPaths)
if err != nil {
return err
}
err = writeTarFromLayer(ctx, r, w)
cerr := r.Close()
if err != nil {
return err
}
return cerr
}
func writeTarFromLayer(ctx context.Context, r wclayer.LayerReader, w io.Writer) error {
linkRecords := make(map[[16]byte]string)
t := tar.NewWriter(w)
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
name, size, fileInfo, err := r.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if fileInfo == nil {
// Write a whiteout file.
hdr := &tar.Header{
Name: filepath.ToSlash(filepath.Join(filepath.Dir(name), whiteoutPrefix+filepath.Base(name))),
}
err := t.WriteHeader(hdr)
if err != nil {
return err
}
} else {
numberOfLinks, fileIDInfo, err := r.LinkInfo()
if err != nil {
return err
}
if numberOfLinks > 1 {
if linkName, ok := linkRecords[fileIDInfo.FileID]; ok {
// We've seen this file before, by another name, so put a hardlink in the tar stream.
hdr := backuptar.BasicInfoHeader(name, 0, fileInfo)
hdr.Mode = 0644
hdr.Typeflag = tar.TypeLink
hdr.Linkname = linkName
if err := t.WriteHeader(hdr); err != nil {
return err
}
continue
}
// All subsequent names for this file will be hard-linked to this name
linkRecords[fileIDInfo.FileID] = filepath.ToSlash(name)
}
err = backuptar.WriteTarFileFromBackupStream(t, r, name, size, fileInfo)
if err != nil {
return err
}
}
}
return t.Close()
}

View File

@@ -0,0 +1,150 @@
//go:build windows
package ociwclayer
import (
"archive/tar"
"bufio"
"context"
"io"
"os"
"path"
"path/filepath"
"strings"
winio "github.com/Microsoft/go-winio"
"github.com/Microsoft/go-winio/backuptar"
"github.com/Microsoft/hcsshim/internal/wclayer"
)
const whiteoutPrefix = ".wh."
var (
// mutatedFiles is a list of files that are mutated by the import process
// and must be backed up and restored.
mutatedFiles = map[string]string{
"UtilityVM/Files/EFI/Microsoft/Boot/BCD": "bcd.bak",
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG": "bcd.log.bak",
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak",
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak",
}
)
// ImportLayerFromTar reads a layer from an OCI layer tar stream and extracts it to the
// specified path. The caller must specify the parent layers, if any, ordered
// from lowest to highest layer.
//
// The caller must ensure that the thread or process has acquired backup and
// restore privileges.
//
// This function returns the total size of the layer's files, in bytes.
func ImportLayerFromTar(ctx context.Context, r io.Reader, path string, parentLayerPaths []string) (int64, error) {
err := os.MkdirAll(path, 0)
if err != nil {
return 0, err
}
w, err := wclayer.NewLayerWriter(ctx, path, parentLayerPaths)
if err != nil {
return 0, err
}
n, err := writeLayerFromTar(ctx, r, w, path)
cerr := w.Close()
if err != nil {
return 0, err
}
if cerr != nil {
return 0, cerr
}
return n, nil
}
func writeLayerFromTar(ctx context.Context, r io.Reader, w wclayer.LayerWriter, root string) (int64, error) {
t := tar.NewReader(r)
hdr, err := t.Next()
totalSize := int64(0)
buf := bufio.NewWriter(nil)
for err == nil {
select {
case <-ctx.Done():
return 0, ctx.Err()
default:
}
base := path.Base(hdr.Name)
if strings.HasPrefix(base, whiteoutPrefix) {
name := path.Join(path.Dir(hdr.Name), base[len(whiteoutPrefix):])
err = w.Remove(filepath.FromSlash(name))
if err != nil {
return 0, err
}
hdr, err = t.Next()
} else if hdr.Typeflag == tar.TypeLink {
err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
if err != nil {
return 0, err
}
hdr, err = t.Next()
} else {
var (
name string
size int64
fileInfo *winio.FileBasicInfo
)
name, size, fileInfo, err = backuptar.FileInfoFromHeader(hdr)
if err != nil {
return 0, err
}
err = w.Add(filepath.FromSlash(name), fileInfo)
if err != nil {
return 0, err
}
hdr, err = writeBackupStreamFromTarAndSaveMutatedFiles(buf, w, t, hdr, root)
totalSize += size
}
}
if err != io.EOF {
return 0, err
}
return totalSize, nil
}
// writeBackupStreamFromTarAndSaveMutatedFiles reads data from a tar stream and
// writes it to a backup stream, and also saves any files that will be mutated
// by the import layer process to a backup location.
func writeBackupStreamFromTarAndSaveMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Reader, hdr *tar.Header, root string) (nextHdr *tar.Header, err error) {
var bcdBackup *os.File
var bcdBackupWriter *winio.BackupFileWriter
if backupPath, ok := mutatedFiles[hdr.Name]; ok {
bcdBackup, err = os.Create(filepath.Join(root, backupPath))
if err != nil {
return nil, err
}
defer func() {
cerr := bcdBackup.Close()
if err == nil {
err = cerr
}
}()
bcdBackupWriter = winio.NewBackupFileWriter(bcdBackup, false)
defer func() {
cerr := bcdBackupWriter.Close()
if err == nil {
err = cerr
}
}()
buf.Reset(io.MultiWriter(w, bcdBackupWriter))
} else {
buf.Reset(w)
}
defer func() {
ferr := buf.Flush()
if err == nil {
err = ferr
}
}()
return backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
}