summaryrefslogtreecommitdiff
path: root/vendor/github.com/Microsoft/hcsshim/internal/wclayer
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/Microsoft/hcsshim/internal/wclayer')
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go25
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go173
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go23
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go31
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go22
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go23
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go22
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go68
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go49
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go26
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go24
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go127
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go25
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go13
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go96
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go815
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go24
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go40
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go23
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go23
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go27
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go457
22 files changed, 2156 insertions, 0 deletions
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go
new file mode 100644
index 000000000..3a0d4bc58
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go
@@ -0,0 +1,25 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// ActivateLayer will find the layer with the given id and mount it's filesystem.
+// For a read/write layer, the mounted filesystem will appear as a volume on the
+// host, while a read-only layer is generally expected to be a no-op.
+// An activated layer must later be deactivated via DeactivateLayer.
+func ActivateLayer(path string) error {
+ title := "hcsshim::ActivateLayer "
+ logrus.Debugf(title+"path %s", path)
+
+ err := activateLayer(&stdDriverInfo, path)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+" - succeeded path=%s", path)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go
new file mode 100644
index 000000000..5784241df
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go
@@ -0,0 +1,173 @@
+package wclayer
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "syscall"
+
+ "github.com/Microsoft/go-winio"
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/Microsoft/hcsshim/internal/safefile"
+)
+
+type baseLayerWriter struct {
+ root *os.File
+ f *os.File
+ bw *winio.BackupFileWriter
+ err error
+ hasUtilityVM bool
+ dirInfo []dirInfo
+}
+
+type dirInfo struct {
+ path string
+ fileInfo winio.FileBasicInfo
+}
+
+// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
+// after processing of the directory tree has completed. The times are expected
+// to be ordered such that parent directories come before child directories.
+func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error {
+ for i := range dis {
+ di := &dis[len(dis)-i-1] // reverse order: process child directories first
+ f, err := safefile.OpenRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_OPEN, safefile.FILE_DIRECTORY_FILE)
+ if err != nil {
+ return err
+ }
+
+ err = winio.SetFileBasicInfo(f, &di.fileInfo)
+ f.Close()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (w *baseLayerWriter) closeCurrentFile() error {
+ if w.f != nil {
+ err := w.bw.Close()
+ err2 := w.f.Close()
+ w.f = nil
+ w.bw = nil
+ if err != nil {
+ return err
+ }
+ if err2 != nil {
+ return err2
+ }
+ }
+ return nil
+}
+
+func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err error) {
+ defer func() {
+ if err != nil {
+ w.err = err
+ }
+ }()
+
+ err = w.closeCurrentFile()
+ if err != nil {
+ return err
+ }
+
+ if filepath.ToSlash(name) == `UtilityVM/Files` {
+ w.hasUtilityVM = true
+ }
+
+ var f *os.File
+ defer func() {
+ if f != nil {
+ f.Close()
+ }
+ }()
+
+ extraFlags := uint32(0)
+ if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+ extraFlags |= safefile.FILE_DIRECTORY_FILE
+ if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
+ w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo})
+ }
+ }
+
+ mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
+ f, err = safefile.OpenRelative(name, w.root, mode, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, extraFlags)
+ if err != nil {
+ return hcserror.New(err, "Failed to safefile.OpenRelative", name)
+ }
+
+ err = winio.SetFileBasicInfo(f, fileInfo)
+ if err != nil {
+ return hcserror.New(err, "Failed to SetFileBasicInfo", name)
+ }
+
+ w.f = f
+ w.bw = winio.NewBackupFileWriter(f, true)
+ f = nil
+ return nil
+}
+
+func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
+ defer func() {
+ if err != nil {
+ w.err = err
+ }
+ }()
+
+ err = w.closeCurrentFile()
+ if err != nil {
+ return err
+ }
+
+ return safefile.LinkRelative(target, w.root, name, w.root)
+}
+
+func (w *baseLayerWriter) Remove(name string) error {
+ return errors.New("base layer cannot have tombstones")
+}
+
+func (w *baseLayerWriter) Write(b []byte) (int, error) {
+ n, err := w.bw.Write(b)
+ if err != nil {
+ w.err = err
+ }
+ return n, err
+}
+
+func (w *baseLayerWriter) Close() error {
+ defer func() {
+ w.root.Close()
+ w.root = nil
+ }()
+ err := w.closeCurrentFile()
+ if err != nil {
+ return err
+ }
+ if w.err == nil {
+ // Restore the file times of all the directories, since they may have
+ // been modified by creating child directories.
+ err = reapplyDirectoryTimes(w.root, w.dirInfo)
+ if err != nil {
+ return err
+ }
+
+ err = ProcessBaseLayer(w.root.Name())
+ if err != nil {
+ return err
+ }
+
+ if w.hasUtilityVM {
+ err := safefile.EnsureNotReparsePointRelative("UtilityVM", w.root)
+ if err != nil {
+ return err
+ }
+ err = ProcessUtilityVMImage(filepath.Join(w.root.Name(), "UtilityVM"))
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return w.err
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
new file mode 100644
index 000000000..d15817730
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
@@ -0,0 +1,23 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// CreateLayer creates a new, empty, read-only layer on the filesystem based on
+// the parent layer provided.
+func CreateLayer(path, parent string) error {
+ title := "hcsshim::CreateLayer "
+ logrus.Debugf(title+"ID %s parent %s", path, parent)
+
+ err := createLayer(&stdDriverInfo, path, parent)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"- succeeded path=%s parent=%s", path, parent)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go
new file mode 100644
index 000000000..bf2fece19
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go
@@ -0,0 +1,31 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// CreateScratchLayer creates and populates new read-write layer for use by a container.
+// This requires both the id of the direct parent layer, as well as the full list
+// of paths to all parent layers up to the base (and including the direct parent
+// whose id was provided).
+func CreateScratchLayer(path string, parentLayerPaths []string) error {
+ title := "hcsshim::CreateScratchLayer "
+ logrus.Debugf(title+"path %s", path)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ err = createSandboxLayer(&stdDriverInfo, path, 0, layers)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"- succeeded path=%s", path)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go
new file mode 100644
index 000000000..b998f8a19
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go
@@ -0,0 +1,22 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// DeactivateLayer will dismount a layer that was mounted via ActivateLayer.
+func DeactivateLayer(path string) error {
+ title := "hcsshim::DeactivateLayer "
+ logrus.Debugf(title+"path %s", path)
+
+ err := deactivateLayer(&stdDriverInfo, path)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s", path)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go
new file mode 100644
index 000000000..dc14cecc4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go
@@ -0,0 +1,23 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// DestroyLayer will remove the on-disk files representing the layer with the given
+// path, including that layer's containing folder, if any.
+func DestroyLayer(path string) error {
+ title := "hcsshim::DestroyLayer "
+ logrus.Debugf(title+"path %s", path)
+
+ err := destroyLayer(&stdDriverInfo, path)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s", path)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
new file mode 100644
index 000000000..7832bb452
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go
@@ -0,0 +1,22 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// ExpandScratchSize expands the size of a layer to at least size bytes.
+func ExpandScratchSize(path string, size uint64) error {
+ title := "hcsshim::ExpandScratchSize "
+ logrus.Debugf(title+"path=%s size=%d", path, size)
+
+ err := expandSandboxSize(&stdDriverInfo, path, size)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s size=%d", path, size)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"- succeeded path=%s size=%d", path, size)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go
new file mode 100644
index 000000000..d43e941ee
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go
@@ -0,0 +1,68 @@
+package wclayer
+
+import (
+ "io/ioutil"
+ "os"
+
+ "github.com/Microsoft/go-winio"
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// ExportLayer will create a folder at exportFolderPath and fill that folder with
+// the transport format version of the layer identified by layerId. This transport
+// format includes any metadata required for later importing the layer (using
+// ImportLayer), and requires the full list of parent layer paths in order to
+// perform the export.
+func ExportLayer(path string, exportFolderPath string, parentLayerPaths []string) error {
+ title := "hcsshim::ExportLayer "
+ logrus.Debugf(title+"path %s folder %s", path, exportFolderPath)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ err = exportLayer(&stdDriverInfo, path, exportFolderPath, layers)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s folder=%s", path, exportFolderPath)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s folder=%s", path, exportFolderPath)
+ return nil
+}
+
+type LayerReader interface {
+ Next() (string, int64, *winio.FileBasicInfo, error)
+ Read(b []byte) (int, error)
+ Close() error
+}
+
+// NewLayerReader returns a new layer reader for reading the contents of an on-disk layer.
+// The caller must have taken the SeBackupPrivilege privilege
+// to call this and any methods on the resulting LayerReader.
+func NewLayerReader(path string, parentLayerPaths []string) (LayerReader, error) {
+ exportPath, err := ioutil.TempDir("", "hcs")
+ if err != nil {
+ return nil, err
+ }
+ err = ExportLayer(path, exportPath, parentLayerPaths)
+ if err != nil {
+ os.RemoveAll(exportPath)
+ return nil, err
+ }
+ return &legacyLayerReaderWrapper{newLegacyLayerReader(exportPath)}, nil
+}
+
+type legacyLayerReaderWrapper struct {
+ *legacyLayerReader
+}
+
+func (r *legacyLayerReaderWrapper) Close() error {
+ err := r.legacyLayerReader.Close()
+ os.RemoveAll(r.root)
+ return err
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go
new file mode 100644
index 000000000..8c37549a0
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go
@@ -0,0 +1,49 @@
+package wclayer
+
+import (
+ "syscall"
+
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// GetLayerMountPath will look for a mounted layer with the given path and return
+// the path at which that layer can be accessed. This path may be a volume path
+// if the layer is a mounted read-write layer, otherwise it is expected to be the
+// folder path at which the layer is stored.
+func GetLayerMountPath(path string) (string, error) {
+ title := "hcsshim::GetLayerMountPath "
+ logrus.Debugf(title+"path %s", path)
+
+ var mountPathLength uintptr
+ mountPathLength = 0
+
+ // Call the procedure itself.
+ logrus.Debugf("Calling proc (1)")
+ err := getLayerMountPath(&stdDriverInfo, path, &mountPathLength, nil)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "(first call) path=%s", path)
+ logrus.Error(err)
+ return "", err
+ }
+
+ // Allocate a mount path of the returned length.
+ if mountPathLength == 0 {
+ return "", nil
+ }
+ mountPathp := make([]uint16, mountPathLength)
+ mountPathp[0] = 0
+
+ // Call the procedure again
+ logrus.Debugf("Calling proc (2)")
+ err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, &mountPathp[0])
+ if err != nil {
+ err = hcserror.Errorf(err, title, "(second call) path=%s", path)
+ logrus.Error(err)
+ return "", err
+ }
+
+ mountPath := syscall.UTF16ToString(mountPathp[0:])
+ logrus.Debugf(title+"succeeded path=%s mountPath=%s", path, mountPath)
+ return mountPath, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go
new file mode 100644
index 000000000..10899c68a
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go
@@ -0,0 +1,26 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/Microsoft/hcsshim/internal/interop"
+ "github.com/sirupsen/logrus"
+)
+
+// GetSharedBaseImages will enumerate the images stored in the common central
+// image store and return descriptive info about those images for the purpose
+// of registering them with the graphdriver, graph, and tagstore.
+func GetSharedBaseImages() (imageData string, err error) {
+ title := "hcsshim::GetSharedBaseImages "
+
+ logrus.Debugf("Calling proc")
+ var buffer *uint16
+ err = getBaseImages(&buffer)
+ if err != nil {
+ err = hcserror.New(err, title, "")
+ logrus.Error(err)
+ return
+ }
+ imageData = interop.ConvertAndFreeCoTaskMemString(buffer)
+ logrus.Debugf(title+" - succeeded output=%s", imageData)
+ return
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go
new file mode 100644
index 000000000..d86e67827
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go
@@ -0,0 +1,24 @@
+package wclayer
+
+import (
+ "fmt"
+
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// GrantVmAccess adds access to a file for a given VM
+func GrantVmAccess(vmid string, filepath string) error {
+ title := fmt.Sprintf("hcsshim::GrantVmAccess id:%s path:%s ", vmid, filepath)
+ logrus.Debugf(title)
+
+ err := grantVmAccess(vmid, filepath)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", filepath)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title + " - succeeded")
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go
new file mode 100644
index 000000000..486d55470
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go
@@ -0,0 +1,127 @@
+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) error {
+ title := "hcsshim::ImportLayer "
+ logrus.Debugf(title+"path %s folder %s", path, importFolderPath)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ err = importLayer(&stdDriverInfo, path, importFolderPath, layers)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s folder=%s", path, importFolderPath)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s folder=%s", path, importFolderPath)
+ 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
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go
new file mode 100644
index 000000000..71287ff8a
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go
@@ -0,0 +1,25 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// LayerExists will return true if a layer with the given id exists and is known
+// to the system.
+func LayerExists(path string) (bool, error) {
+ title := "hcsshim::LayerExists "
+ logrus.Debugf(title+"path %s", path)
+
+ // Call the procedure itself.
+ var exists uint32
+ err := layerExists(&stdDriverInfo, path, &exists)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return false, err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s exists=%d", path, exists)
+ return exists != 0, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go
new file mode 100644
index 000000000..90df3bedc
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go
@@ -0,0 +1,13 @@
+package wclayer
+
+import (
+ "path/filepath"
+
+ "github.com/Microsoft/hcsshim/internal/guid"
+)
+
+// LayerID returns the layer ID of a layer on disk.
+func LayerID(path string) (guid.GUID, error) {
+ _, file := filepath.Split(path)
+ return NameToGuid(file)
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go
new file mode 100644
index 000000000..a1b8b9882
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go
@@ -0,0 +1,96 @@
+package wclayer
+
+// This file contains utility functions to support storage (graph) related
+// functionality.
+
+import (
+ "syscall"
+
+ "github.com/Microsoft/hcsshim/internal/guid"
+ "github.com/sirupsen/logrus"
+)
+
+/* To pass into syscall, we need a struct matching the following:
+enum GraphDriverType
+{
+ DiffDriver,
+ FilterDriver
+};
+
+struct DriverInfo {
+ GraphDriverType Flavour;
+ LPCWSTR HomeDir;
+};
+*/
+
+type driverInfo struct {
+ Flavour int
+ HomeDirp *uint16
+}
+
+var (
+ utf16EmptyString uint16
+ stdDriverInfo = driverInfo{1, &utf16EmptyString}
+)
+
+/* To pass into syscall, we need a struct matching the following:
+typedef struct _WC_LAYER_DESCRIPTOR {
+
+ //
+ // The ID of the layer
+ //
+
+ GUID LayerId;
+
+ //
+ // Additional flags
+ //
+
+ union {
+ struct {
+ ULONG Reserved : 31;
+ ULONG Dirty : 1; // Created from sandbox as a result of snapshot
+ };
+ ULONG Value;
+ } Flags;
+
+ //
+ // Path to the layer root directory, null-terminated
+ //
+
+ PCWSTR Path;
+
+} WC_LAYER_DESCRIPTOR, *PWC_LAYER_DESCRIPTOR;
+*/
+type WC_LAYER_DESCRIPTOR struct {
+ LayerId guid.GUID
+ Flags uint32
+ Pathp *uint16
+}
+
+func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, error) {
+ // Array of descriptors that gets constructed.
+ var layers []WC_LAYER_DESCRIPTOR
+
+ for i := 0; i < len(parentLayerPaths); i++ {
+ g, err := LayerID(parentLayerPaths[i])
+ if err != nil {
+ logrus.Debugf("Failed to convert name to guid %s", err)
+ return nil, err
+ }
+
+ p, err := syscall.UTF16PtrFromString(parentLayerPaths[i])
+ if err != nil {
+ logrus.Debugf("Failed conversion of parentLayerPath to pointer %s", err)
+ return nil, err
+ }
+
+ layers = append(layers, WC_LAYER_DESCRIPTOR{
+ LayerId: g,
+ Flags: 0,
+ Pathp: p,
+ })
+ }
+
+ return layers, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go
new file mode 100644
index 000000000..b8ea5d263
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go
@@ -0,0 +1,815 @@
+package wclayer
+
+import (
+ "bufio"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "syscall"
+
+ "github.com/Microsoft/go-winio"
+ "github.com/Microsoft/hcsshim/internal/longpath"
+ "github.com/Microsoft/hcsshim/internal/safefile"
+)
+
+var errorIterationCanceled = errors.New("")
+
+var mutatedUtilityVMFiles = map[string]bool{
+ `EFI\Microsoft\Boot\BCD`: true,
+ `EFI\Microsoft\Boot\BCD.LOG`: true,
+ `EFI\Microsoft\Boot\BCD.LOG1`: true,
+ `EFI\Microsoft\Boot\BCD.LOG2`: true,
+}
+
+const (
+ filesPath = `Files`
+ hivesPath = `Hives`
+ utilityVMPath = `UtilityVM`
+ utilityVMFilesPath = `UtilityVM\Files`
+)
+
+func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os.File, err error) {
+ return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition)
+}
+
+func hasPathPrefix(p, prefix string) bool {
+ return strings.HasPrefix(p, prefix) && len(p) > len(prefix) && p[len(prefix)] == '\\'
+}
+
+type fileEntry struct {
+ path string
+ fi os.FileInfo
+ err error
+}
+
+type legacyLayerReader struct {
+ root string
+ result chan *fileEntry
+ proceed chan bool
+ currentFile *os.File
+ backupReader *winio.BackupFileReader
+}
+
+// newLegacyLayerReader returns a new LayerReader that can read the Windows
+// container layer transport format from disk.
+func newLegacyLayerReader(root string) *legacyLayerReader {
+ r := &legacyLayerReader{
+ root: root,
+ result: make(chan *fileEntry),
+ proceed: make(chan bool),
+ }
+ go r.walk()
+ return r
+}
+
+func readTombstones(path string) (map[string]([]string), error) {
+ tf, err := os.Open(filepath.Join(path, "tombstones.txt"))
+ if err != nil {
+ return nil, err
+ }
+ defer tf.Close()
+ s := bufio.NewScanner(tf)
+ if !s.Scan() || s.Text() != "\xef\xbb\xbfVersion 1.0" {
+ return nil, errors.New("Invalid tombstones file")
+ }
+
+ ts := make(map[string]([]string))
+ for s.Scan() {
+ t := filepath.Join(filesPath, s.Text()[1:]) // skip leading `\`
+ dir := filepath.Dir(t)
+ ts[dir] = append(ts[dir], t)
+ }
+ if err = s.Err(); err != nil {
+ return nil, err
+ }
+
+ return ts, nil
+}
+
+func (r *legacyLayerReader) walkUntilCancelled() error {
+ root, err := longpath.LongAbs(r.root)
+ if err != nil {
+ return err
+ }
+
+ r.root = root
+ ts, err := readTombstones(r.root)
+ if err != nil {
+ return err
+ }
+
+ err = filepath.Walk(r.root, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ // Indirect fix for https://github.com/moby/moby/issues/32838#issuecomment-343610048.
+ // Handle failure from what may be a golang bug in the conversion of
+ // UTF16 to UTF8 in files which are left in the recycle bin. Os.Lstat
+ // which is called by filepath.Walk will fail when a filename contains
+ // unicode characters. Skip the recycle bin regardless which is goodness.
+ if strings.EqualFold(path, filepath.Join(r.root, `Files\$Recycle.Bin`)) && info.IsDir() {
+ return filepath.SkipDir
+ }
+
+ if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") {
+ return nil
+ }
+
+ r.result <- &fileEntry{path, info, nil}
+ if !<-r.proceed {
+ return errorIterationCanceled
+ }
+
+ // List all the tombstones.
+ if info.IsDir() {
+ relPath, err := filepath.Rel(r.root, path)
+ if err != nil {
+ return err
+ }
+ if dts, ok := ts[relPath]; ok {
+ for _, t := range dts {
+ r.result <- &fileEntry{filepath.Join(r.root, t), nil, nil}
+ if !<-r.proceed {
+ return errorIterationCanceled
+ }
+ }
+ }
+ }
+ return nil
+ })
+ if err == errorIterationCanceled {
+ return nil
+ }
+ if err == nil {
+ return io.EOF
+ }
+ return err
+}
+
+func (r *legacyLayerReader) walk() {
+ defer close(r.result)
+ if !<-r.proceed {
+ return
+ }
+
+ err := r.walkUntilCancelled()
+ if err != nil {
+ for {
+ r.result <- &fileEntry{err: err}
+ if !<-r.proceed {
+ return
+ }
+ }
+ }
+}
+
+func (r *legacyLayerReader) reset() {
+ if r.backupReader != nil {
+ r.backupReader.Close()
+ r.backupReader = nil
+ }
+ if r.currentFile != nil {
+ r.currentFile.Close()
+ r.currentFile = nil
+ }
+}
+
+func findBackupStreamSize(r io.Reader) (int64, error) {
+ br := winio.NewBackupStreamReader(r)
+ for {
+ hdr, err := br.Next()
+ if err != nil {
+ if err == io.EOF {
+ err = nil
+ }
+ return 0, err
+ }
+ if hdr.Id == winio.BackupData {
+ return hdr.Size, nil
+ }
+ }
+}
+
+func (r *legacyLayerReader) Next() (path string, size int64, fileInfo *winio.FileBasicInfo, err error) {
+ r.reset()
+ r.proceed <- true
+ fe := <-r.result
+ if fe == nil {
+ err = errors.New("LegacyLayerReader closed")
+ return
+ }
+ if fe.err != nil {
+ err = fe.err
+ return
+ }
+
+ path, err = filepath.Rel(r.root, fe.path)
+ if err != nil {
+ return
+ }
+
+ if fe.fi == nil {
+ // This is a tombstone. Return a nil fileInfo.
+ return
+ }
+
+ if fe.fi.IsDir() && hasPathPrefix(path, filesPath) {
+ fe.path += ".$wcidirs$"
+ }
+
+ f, err := openFileOrDir(fe.path, syscall.GENERIC_READ, syscall.OPEN_EXISTING)
+ if err != nil {
+ return
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ }
+ }()
+
+ fileInfo, err = winio.GetFileBasicInfo(f)
+ if err != nil {
+ return
+ }
+
+ if !hasPathPrefix(path, filesPath) {
+ size = fe.fi.Size()
+ r.backupReader = winio.NewBackupFileReader(f, false)
+ if path == hivesPath || path == filesPath {
+ // The Hives directory has a non-deterministic file time because of the
+ // nature of the import process. Use the times from System_Delta.
+ var g *os.File
+ g, err = os.Open(filepath.Join(r.root, hivesPath, `System_Delta`))
+ if err != nil {
+ return
+ }
+ attr := fileInfo.FileAttributes
+ fileInfo, err = winio.GetFileBasicInfo(g)
+ g.Close()
+ if err != nil {
+ return
+ }
+ fileInfo.FileAttributes = attr
+ }
+
+ // The creation time and access time get reset for files outside of the Files path.
+ fileInfo.CreationTime = fileInfo.LastWriteTime
+ fileInfo.LastAccessTime = fileInfo.LastWriteTime
+
+ } else {
+ // The file attributes are written before the backup stream.
+ var attr uint32
+ err = binary.Read(f, binary.LittleEndian, &attr)
+ if err != nil {
+ return
+ }
+ fileInfo.FileAttributes = attr
+ beginning := int64(4)
+
+ // Find the accurate file size.
+ if !fe.fi.IsDir() {
+ size, err = findBackupStreamSize(f)
+ if err != nil {
+ err = &os.PathError{Op: "findBackupStreamSize", Path: fe.path, Err: err}
+ return
+ }
+ }
+
+ // Return back to the beginning of the backup stream.
+ _, err = f.Seek(beginning, 0)
+ if err != nil {
+ return
+ }
+ }
+
+ r.currentFile = f
+ f = nil
+ return
+}
+
+func (r *legacyLayerReader) Read(b []byte) (int, error) {
+ if r.backupReader == nil {
+ if r.currentFile == nil {
+ return 0, io.EOF
+ }
+ return r.currentFile.Read(b)
+ }
+ return r.backupReader.Read(b)
+}
+
+func (r *legacyLayerReader) Seek(offset int64, whence int) (int64, error) {
+ if r.backupReader == nil {
+ if r.currentFile == nil {
+ return 0, errors.New("no current file")
+ }
+ return r.currentFile.Seek(offset, whence)
+ }
+ return 0, errors.New("seek not supported on this stream")
+}
+
+func (r *legacyLayerReader) Close() error {
+ r.proceed <- false
+ <-r.result
+ r.reset()
+ return nil
+}
+
+type pendingLink struct {
+ Path, Target string
+ TargetRoot *os.File
+}
+
+type pendingDir struct {
+ Path string
+ Root *os.File
+}
+
+type legacyLayerWriter struct {
+ root *os.File
+ destRoot *os.File
+ parentRoots []*os.File
+ currentFile *os.File
+ bufWriter *bufio.Writer
+ currentFileName string
+ currentFileRoot *os.File
+ backupWriter *winio.BackupFileWriter
+ Tombstones []string
+ HasUtilityVM bool
+ uvmDi []dirInfo
+ addedFiles map[string]bool
+ PendingLinks []pendingLink
+ pendingDirs []pendingDir
+ currentIsDir bool
+}
+
+// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
+// transport format to disk.
+func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w *legacyLayerWriter, err error) {
+ w = &legacyLayerWriter{
+ addedFiles: make(map[string]bool),
+ }
+ defer func() {
+ if err != nil {
+ w.CloseRoots()
+ w = nil
+ }
+ }()
+ w.root, err = safefile.OpenRoot(root)
+ if err != nil {
+ return
+ }
+ w.destRoot, err = safefile.OpenRoot(destRoot)
+ if err != nil {
+ return
+ }
+ for _, r := range parentRoots {
+ f, err := safefile.OpenRoot(r)
+ if err != nil {
+ return w, err
+ }
+ w.parentRoots = append(w.parentRoots, f)
+ }
+ w.bufWriter = bufio.NewWriterSize(ioutil.Discard, 65536)
+ return
+}
+
+func (w *legacyLayerWriter) CloseRoots() {
+ if w.root != nil {
+ w.root.Close()
+ w.root = nil
+ }
+ if w.destRoot != nil {
+ w.destRoot.Close()
+ w.destRoot = nil
+ }
+ for i := range w.parentRoots {
+ w.parentRoots[i].Close()
+ }
+ w.parentRoots = nil
+}
+
+func (w *legacyLayerWriter) initUtilityVM() error {
+ if !w.HasUtilityVM {
+ err := safefile.MkdirRelative(utilityVMPath, w.destRoot)
+ if err != nil {
+ return err
+ }
+ // Server 2016 does not support multiple layers for the utility VM, so
+ // clone the utility VM from the parent layer into this layer. Use hard
+ // links to avoid unnecessary copying, since most of the files are
+ // immutable.
+ err = cloneTree(w.parentRoots[0], w.destRoot, utilityVMFilesPath, mutatedUtilityVMFiles)
+ if err != nil {
+ return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
+ }
+ w.HasUtilityVM = true
+ }
+ return nil
+}
+
+func (w *legacyLayerWriter) reset() error {
+ err := w.bufWriter.Flush()
+ if err != nil {
+ return err
+ }
+ w.bufWriter.Reset(ioutil.Discard)
+ if w.currentIsDir {
+ r := w.currentFile
+ br := winio.NewBackupStreamReader(r)
+ // Seek to the beginning of the backup stream, skipping the fileattrs
+ if _, err := r.Seek(4, io.SeekStart); err != nil {
+ return err
+ }
+
+ for {
+ bhdr, err := br.Next()
+ if err == io.EOF {
+ // end of backupstream data
+ break
+ }
+ if err != nil {
+ return err
+ }
+ switch bhdr.Id {
+ case winio.BackupReparseData:
+ // The current file is a `.$wcidirs$` metadata file that
+ // describes a directory reparse point. Delete the placeholder
+ // directory to prevent future files being added into the
+ // destination of the reparse point during the ImportLayer call
+ if err := safefile.RemoveRelative(w.currentFileName, w.currentFileRoot); err != nil {
+ return err
+ }
+ w.pendingDirs = append(w.pendingDirs, pendingDir{Path: w.currentFileName, Root: w.currentFileRoot})
+ default:
+ // ignore all other stream types, as we only care about directory reparse points
+ }
+ }
+ w.currentIsDir = false
+ }
+ if w.backupWriter != nil {
+ w.backupWriter.Close()
+ w.backupWriter = nil
+ }
+ if w.currentFile != nil {
+ w.currentFile.Close()
+ w.currentFile = nil
+ w.currentFileName = ""
+ w.currentFileRoot = nil
+ }
+ return nil
+}
+
+// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata
+func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) {
+ src, err := safefile.OpenRelative(
+ subPath,
+ srcRoot,
+ syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY,
+ syscall.FILE_SHARE_READ,
+ safefile.FILE_OPEN,
+ safefile.FILE_OPEN_REPARSE_POINT)
+ if err != nil {
+ return nil, err
+ }
+ defer src.Close()
+ srcr := winio.NewBackupFileReader(src, true)
+ defer srcr.Close()
+
+ fileInfo, err = winio.GetFileBasicInfo(src)
+ if err != nil {
+ return nil, err
+ }
+
+ extraFlags := uint32(0)
+ if isDir {
+ extraFlags |= safefile.FILE_DIRECTORY_FILE
+ }
+ dest, err := safefile.OpenRelative(
+ subPath,
+ destRoot,
+ syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY,
+ syscall.FILE_SHARE_READ,
+ safefile.FILE_CREATE,
+ extraFlags)
+ if err != nil {
+ return nil, err
+ }
+ defer dest.Close()
+
+ err = winio.SetFileBasicInfo(dest, fileInfo)
+ if err != nil {
+ return nil, err
+ }
+
+ destw := winio.NewBackupFileWriter(dest, true)
+ defer func() {
+ cerr := destw.Close()
+ if err == nil {
+ err = cerr
+ }
+ }()
+
+ _, err = io.Copy(destw, srcr)
+ if err != nil {
+ return nil, err
+ }
+
+ return fileInfo, nil
+}
+
+// cloneTree clones a directory tree using hard links. It skips hard links for
+// the file names in the provided map and just copies those files.
+func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles map[string]bool) error {
+ var di []dirInfo
+ err := safefile.EnsureNotReparsePointRelative(subPath, srcRoot)
+ if err != nil {
+ return err
+ }
+ err = filepath.Walk(filepath.Join(srcRoot.Name(), subPath), func(srcFilePath string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ relPath, err := filepath.Rel(srcRoot.Name(), srcFilePath)
+ if err != nil {
+ return err
+ }
+
+ fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
+ // Directories, reparse points, and files that will be mutated during
+ // utility VM import must be copied. All other files can be hard linked.
+ isReparsePoint := fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0
+ // In go1.9, FileInfo.IsDir() returns false if the directory is also a symlink.
+ // See: https://github.com/golang/go/commit/1989921aef60c83e6f9127a8448fb5ede10e9acc
+ // Fixes the problem by checking syscall.FILE_ATTRIBUTE_DIRECTORY directly
+ isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
+
+ if isDir || isReparsePoint || mutatedFiles[relPath] {
+ fi, err := copyFileWithMetadata(srcRoot, destRoot, relPath, isDir)
+ if err != nil {
+ return err
+ }
+ if isDir && !isReparsePoint {
+ di = append(di, dirInfo{path: relPath, fileInfo: *fi})
+ }
+ } else {
+ err = safefile.LinkRelative(relPath, srcRoot, relPath, destRoot)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ return reapplyDirectoryTimes(destRoot, di)
+}
+
+func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
+ if err := w.reset(); err != nil {
+ return err
+ }
+
+ if name == utilityVMPath {
+ return w.initUtilityVM()
+ }
+
+ name = filepath.Clean(name)
+ if hasPathPrefix(name, utilityVMPath) {
+ if !w.HasUtilityVM {
+ return errors.New("missing UtilityVM directory")
+ }
+ if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
+ return errors.New("invalid UtilityVM layer")
+ }
+ createDisposition := uint32(safefile.FILE_OPEN)
+ if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
+ st, err := safefile.LstatRelative(name, w.destRoot)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ if st != nil {
+ // Delete the existing file/directory if it is not the same type as this directory.
+ existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes
+ if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
+ if err = safefile.RemoveAllRelative(name, w.destRoot); err != nil {
+ return err
+ }
+ st = nil
+ }
+ }
+ if st == nil {
+ if err = safefile.MkdirRelative(name, w.destRoot); err != nil {
+ return err
+ }
+ }
+ if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
+ w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo})
+ }
+ } else {
+ // Overwrite any existing hard link.
+ err := safefile.RemoveRelative(name, w.destRoot)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ createDisposition = safefile.FILE_CREATE
+ }
+
+ f, err := safefile.OpenRelative(
+ name,
+ w.destRoot,
+ syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY,
+ syscall.FILE_SHARE_READ,
+ createDisposition,
+ safefile.FILE_OPEN_REPARSE_POINT,
+ )
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ safefile.RemoveRelative(name, w.destRoot)
+ }
+ }()
+
+ err = winio.SetFileBasicInfo(f, fileInfo)
+ if err != nil {
+ return err
+ }
+
+ w.backupWriter = winio.NewBackupFileWriter(f, true)
+ w.bufWriter.Reset(w.backupWriter)
+ w.currentFile = f
+ w.currentFileName = name
+ w.currentFileRoot = w.destRoot
+ w.addedFiles[name] = true
+ f = nil
+ return nil
+ }
+
+ fname := name
+ if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
+ err := safefile.MkdirRelative(name, w.root)
+ if err != nil {
+ return err
+ }
+ fname += ".$wcidirs$"
+ w.currentIsDir = true
+ }
+
+ f, err := safefile.OpenRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, 0)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ safefile.RemoveRelative(fname, w.root)
+ }
+ }()
+
+ strippedFi := *fileInfo
+ strippedFi.FileAttributes = 0
+ err = winio.SetFileBasicInfo(f, &strippedFi)
+ if err != nil {
+ return err
+ }
+
+ if hasPathPrefix(name, hivesPath) {
+ w.backupWriter = winio.NewBackupFileWriter(f, false)
+ w.bufWriter.Reset(w.backupWriter)
+ } else {
+ w.bufWriter.Reset(f)
+ // The file attributes are written before the stream.
+ err = binary.Write(w.bufWriter, binary.LittleEndian, uint32(fileInfo.FileAttributes))
+ if err != nil {
+ w.bufWriter.Reset(ioutil.Discard)
+ return err
+ }
+ }
+
+ w.currentFile = f
+ w.currentFileName = name
+ w.currentFileRoot = w.root
+ w.addedFiles[name] = true
+ f = nil
+ return nil
+}
+
+func (w *legacyLayerWriter) AddLink(name string, target string) error {
+ if err := w.reset(); err != nil {
+ return err
+ }
+
+ target = filepath.Clean(target)
+ var roots []*os.File
+ if hasPathPrefix(target, filesPath) {
+ // Look for cross-layer hard link targets in the parent layers, since
+ // nothing is in the destination path yet.
+ roots = w.parentRoots
+ } else if hasPathPrefix(target, utilityVMFilesPath) {
+ // Since the utility VM is fully cloned into the destination path
+ // already, look for cross-layer hard link targets directly in the
+ // destination path.
+ roots = []*os.File{w.destRoot}
+ }
+
+ if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
+ return errors.New("invalid hard link in layer")
+ }
+
+ // Find to try the target of the link in a previously added file. If that
+ // fails, search in parent layers.
+ var selectedRoot *os.File
+ if _, ok := w.addedFiles[target]; ok {
+ selectedRoot = w.destRoot
+ } else {
+ for _, r := range roots {
+ if _, err := safefile.LstatRelative(target, r); err != nil {
+ if !os.IsNotExist(err) {
+ return err
+ }
+ } else {
+ selectedRoot = r
+ break
+ }
+ }
+ if selectedRoot == nil {
+ return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
+ }
+ }
+
+ // The link can't be written until after the ImportLayer call.
+ w.PendingLinks = append(w.PendingLinks, pendingLink{
+ Path: name,
+ Target: target,
+ TargetRoot: selectedRoot,
+ })
+ w.addedFiles[name] = true
+ return nil
+}
+
+func (w *legacyLayerWriter) Remove(name string) error {
+ name = filepath.Clean(name)
+ if hasPathPrefix(name, filesPath) {
+ w.Tombstones = append(w.Tombstones, name)
+ } else if hasPathPrefix(name, utilityVMFilesPath) {
+ err := w.initUtilityVM()
+ if err != nil {
+ return err
+ }
+ // Make sure the path exists; os.RemoveAll will not fail if the file is
+ // already gone, and this needs to be a fatal error for diagnostics
+ // purposes.
+ if _, err := safefile.LstatRelative(name, w.destRoot); err != nil {
+ return err
+ }
+ err = safefile.RemoveAllRelative(name, w.destRoot)
+ if err != nil {
+ return err
+ }
+ } else {
+ return fmt.Errorf("invalid tombstone %s", name)
+ }
+
+ return nil
+}
+
+func (w *legacyLayerWriter) Write(b []byte) (int, error) {
+ if w.backupWriter == nil && w.currentFile == nil {
+ return 0, errors.New("closed")
+ }
+ return w.bufWriter.Write(b)
+}
+
+func (w *legacyLayerWriter) Close() error {
+ if err := w.reset(); err != nil {
+ return err
+ }
+ if err := safefile.RemoveRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ for _, pd := range w.pendingDirs {
+ err := safefile.MkdirRelative(pd.Path, pd.Root)
+ if err != nil {
+ return err
+ }
+ }
+ if w.HasUtilityVM {
+ err := reapplyDirectoryTimes(w.destRoot, w.uvmDi)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go
new file mode 100644
index 000000000..741994ba4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go
@@ -0,0 +1,24 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/guid"
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// NameToGuid converts the given string into a GUID using the algorithm in the
+// Host Compute Service, ensuring GUIDs generated with the same string are common
+// across all clients.
+func NameToGuid(name string) (id guid.GUID, err error) {
+ title := "hcsshim::NameToGuid "
+
+ err = nameToGuid(name, &id)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "name=%s", name)
+ logrus.Error(err)
+ return
+ }
+
+ logrus.Debugf(title+"name:%s guid:%s", name, id.String())
+ return
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go
new file mode 100644
index 000000000..bd4005dc4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go
@@ -0,0 +1,40 @@
+package wclayer
+
+import (
+ "sync"
+
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+var prepareLayerLock sync.Mutex
+
+// PrepareLayer finds a mounted read-write layer matching path and enables the
+// the filesystem filter for use on that layer. This requires the paths to all
+// parent layers, and is necessary in order to view or interact with the layer
+// as an actual filesystem (reading and writing files, creating directories, etc).
+// Disabling the filter must be done via UnprepareLayer.
+func PrepareLayer(path string, parentLayerPaths []string) error {
+ title := "hcsshim::PrepareLayer "
+ logrus.Debugf(title+"path %s", path)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ // This lock is a temporary workaround for a Windows bug. Only allowing one
+ // call to prepareLayer at a time vastly reduces the chance of a timeout.
+ prepareLayerLock.Lock()
+ defer prepareLayerLock.Unlock()
+ err = prepareLayer(&stdDriverInfo, path, layers)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s", path)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go
new file mode 100644
index 000000000..884207c3e
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go
@@ -0,0 +1,23 @@
+package wclayer
+
+import "os"
+
+// ProcessBaseLayer post-processes a base layer that has had its files extracted.
+// The files should have been extracted to <path>\Files.
+func ProcessBaseLayer(path string) error {
+ err := processBaseImage(path)
+ if err != nil {
+ return &os.PathError{Op: "ProcessBaseLayer", Path: path, Err: err}
+ }
+ return nil
+}
+
+// ProcessUtilityVMImage post-processes a utility VM image that has had its files extracted.
+// The files should have been extracted to <path>\Files.
+func ProcessUtilityVMImage(path string) error {
+ err := processUtilityImage(path)
+ if err != nil {
+ return &os.PathError{Op: "ProcessUtilityVMImage", Path: path, Err: err}
+ }
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go
new file mode 100644
index 000000000..5f1b4f4f4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go
@@ -0,0 +1,23 @@
+package wclayer
+
+import (
+ "github.com/Microsoft/hcsshim/internal/hcserror"
+ "github.com/sirupsen/logrus"
+)
+
+// UnprepareLayer disables the filesystem filter for the read-write layer with
+// the given id.
+func UnprepareLayer(path string) error {
+ title := "hcsshim::UnprepareLayer "
+ logrus.Debugf(title+"path %s", path)
+
+ err := unprepareLayer(&stdDriverInfo, path)
+ if err != nil {
+ err = hcserror.Errorf(err, title, "path=%s", path)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded path=%s", path)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go
new file mode 100644
index 000000000..78f2aacd8
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go
@@ -0,0 +1,27 @@
+package wclayer
+
+import "github.com/Microsoft/hcsshim/internal/guid"
+
+//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go wclayer.go
+
+//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer?
+//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer?
+//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer?
+//sys createSandboxLayer(info *driverInfo, id string, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer?
+//sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize?
+//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer?
+//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer?
+//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer?
+//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath?
+//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages?
+//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer?
+//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists?
+//sys nameToGuid(name string, guid *_guid) (hr error) = vmcompute.NameToGuid?
+//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer?
+//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer?
+//sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage?
+//sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage?
+
+//sys grantVmAccess(vmid string, filepath string) (hr error) = vmcompute.GrantVmAccess?
+
+type _guid = guid.GUID
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go
new file mode 100644
index 000000000..2105703dc
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go
@@ -0,0 +1,457 @@
+// Code generated mksyscall_windows.exe DO NOT EDIT
+
+package wclayer
+
+import (
+ "syscall"
+ "unsafe"
+
+ "github.com/Microsoft/hcsshim/internal/interop"
+ "golang.org/x/sys/windows"
+)
+
+var _ unsafe.Pointer
+
+// Do the interface allocations only once for common
+// Errno values.
+const (
+ errnoERROR_IO_PENDING = 997
+)
+
+var (
+ errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e syscall.Errno) error {
+ switch e {
+ case 0:
+ return nil
+ case errnoERROR_IO_PENDING:
+ return errERROR_IO_PENDING
+ }
+ // TODO: add more here, after collecting data on the common
+ // error values see on Windows. (perhaps when running
+ // all.bat?)
+ return e
+}
+
+var (
+ modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
+
+ procActivateLayer = modvmcompute.NewProc("ActivateLayer")
+ procCopyLayer = modvmcompute.NewProc("CopyLayer")
+ procCreateLayer = modvmcompute.NewProc("CreateLayer")
+ procCreateSandboxLayer = modvmcompute.NewProc("CreateSandboxLayer")
+ procExpandSandboxSize = modvmcompute.NewProc("ExpandSandboxSize")
+ procDeactivateLayer = modvmcompute.NewProc("DeactivateLayer")
+ procDestroyLayer = modvmcompute.NewProc("DestroyLayer")
+ procExportLayer = modvmcompute.NewProc("ExportLayer")
+ procGetLayerMountPath = modvmcompute.NewProc("GetLayerMountPath")
+ procGetBaseImages = modvmcompute.NewProc("GetBaseImages")
+ procImportLayer = modvmcompute.NewProc("ImportLayer")
+ procLayerExists = modvmcompute.NewProc("LayerExists")
+ procNameToGuid = modvmcompute.NewProc("NameToGuid")
+ procPrepareLayer = modvmcompute.NewProc("PrepareLayer")
+ procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer")
+ procProcessBaseImage = modvmcompute.NewProc("ProcessBaseImage")
+ procProcessUtilityImage = modvmcompute.NewProc("ProcessUtilityImage")
+ procGrantVmAccess = modvmcompute.NewProc("GrantVmAccess")
+)
+
+func activateLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _activateLayer(info, _p0)
+}
+
+func _activateLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procActivateLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(srcId)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(dstId)
+ if hr != nil {
+ return
+ }
+ return _copyLayer(info, _p0, _p1, descriptors)
+}
+
+func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procCopyLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func createLayer(info *driverInfo, id string, parent string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(parent)
+ if hr != nil {
+ return
+ }
+ return _createLayer(info, _p0, _p1)
+}
+
+func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) {
+ if hr = procCreateLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent)))
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func createSandboxLayer(info *driverInfo, id string, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _createSandboxLayer(info, _p0, parent, descriptors)
+}
+
+func _createSandboxLayer(info *driverInfo, id *uint16, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p1 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p1 = &descriptors[0]
+ }
+ if hr = procCreateSandboxLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(parent), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _expandSandboxSize(info, _p0, size)
+}
+
+func _expandSandboxSize(info *driverInfo, id *uint16, size uint64) (hr error) {
+ if hr = procExpandSandboxSize.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procExpandSandboxSize.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(size))
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func deactivateLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _deactivateLayer(info, _p0)
+}
+
+func _deactivateLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procDeactivateLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func destroyLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _destroyLayer(info, _p0)
+}
+
+func _destroyLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procDestroyLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _exportLayer(info, _p0, _p1, descriptors)
+}
+
+func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procExportLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _getLayerMountPath(info, _p0, length, buffer)
+}
+
+func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) {
+ if hr = procGetLayerMountPath.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func getBaseImages(buffer **uint16) (hr error) {
+ if hr = procGetBaseImages.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _importLayer(info, _p0, _p1, descriptors)
+}
+
+func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procImportLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func layerExists(info *driverInfo, id string, exists *uint32) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _layerExists(info, _p0, exists)
+}
+
+func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) {
+ if hr = procLayerExists.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists)))
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func nameToGuid(name string, guid *_guid) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(name)
+ if hr != nil {
+ return
+ }
+ return _nameToGuid(_p0, guid)
+}
+
+func _nameToGuid(name *uint16, guid *_guid) (hr error) {
+ if hr = procNameToGuid.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _prepareLayer(info, _p0, descriptors)
+}
+
+func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p1 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p1 = &descriptors[0]
+ }
+ if hr = procPrepareLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func unprepareLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _unprepareLayer(info, _p0)
+}
+
+func _unprepareLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procUnprepareLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func processBaseImage(path string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _processBaseImage(_p0)
+}
+
+func _processBaseImage(path *uint16) (hr error) {
+ if hr = procProcessBaseImage.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procProcessBaseImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func processUtilityImage(path string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _processUtilityImage(_p0)
+}
+
+func _processUtilityImage(path *uint16) (hr error) {
+ if hr = procProcessUtilityImage.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procProcessUtilityImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}
+
+func grantVmAccess(vmid string, filepath string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(vmid)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(filepath)
+ if hr != nil {
+ return
+ }
+ return _grantVmAccess(_p0, _p1)
+}
+
+func _grantVmAccess(vmid *uint16, filepath *uint16) (hr error) {
+ if hr = procGrantVmAccess.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procGrantVmAccess.Addr(), 2, uintptr(unsafe.Pointer(vmid)), uintptr(unsafe.Pointer(filepath)), 0)
+ if int32(r0) < 0 {
+ hr = interop.Win32FromHresult(r0)
+ }
+ return
+}