Update hcsshim to v0.6.10
Signed-off-by: Darren Stahl <darst@microsoft.com>
This commit is contained in:
parent
cfba048bec
commit
07d8716004
@ -34,7 +34,7 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
|||||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
||||||
github.com/Microsoft/go-winio v0.4.5
|
github.com/Microsoft/go-winio v0.4.5
|
||||||
github.com/Microsoft/hcsshim v0.6.7
|
github.com/Microsoft/hcsshim v0.6.10
|
||||||
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
|
54
vendor/github.com/Microsoft/hcsshim/baselayer.go
generated
vendored
54
vendor/github.com/Microsoft/hcsshim/baselayer.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type baseLayerWriter struct {
|
type baseLayerWriter struct {
|
||||||
root string
|
root *os.File
|
||||||
f *os.File
|
f *os.File
|
||||||
bw *winio.BackupFileWriter
|
bw *winio.BackupFileWriter
|
||||||
err error
|
err error
|
||||||
@ -26,10 +26,10 @@ type dirInfo struct {
|
|||||||
// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
|
// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
|
||||||
// after processing of the directory tree has completed. The times are expected
|
// after processing of the directory tree has completed. The times are expected
|
||||||
// to be ordered such that parent directories come before child directories.
|
// to be ordered such that parent directories come before child directories.
|
||||||
func reapplyDirectoryTimes(dis []dirInfo) error {
|
func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error {
|
||||||
for i := range dis {
|
for i := range dis {
|
||||||
di := &dis[len(dis)-i-1] // reverse order: process child directories first
|
di := &dis[len(dis)-i-1] // reverse order: process child directories first
|
||||||
f, err := winio.OpenForBackup(di.path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, syscall.OPEN_EXISTING)
|
f, err := openRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_OPEN, _FILE_DIRECTORY_FILE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -75,12 +75,6 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e
|
|||||||
w.hasUtilityVM = true
|
w.hasUtilityVM = true
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(w.root, name)
|
|
||||||
path, err = makeLongAbsPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var f *os.File
|
var f *os.File
|
||||||
defer func() {
|
defer func() {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
@ -88,27 +82,23 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
createmode := uint32(syscall.CREATE_NEW)
|
extraFlags := uint32(0)
|
||||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||||
err := os.Mkdir(path, 0)
|
extraFlags |= _FILE_DIRECTORY_FILE
|
||||||
if err != nil && !os.IsExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
createmode = syscall.OPEN_EXISTING
|
|
||||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
||||||
w.dirInfo = append(w.dirInfo, dirInfo{path, *fileInfo})
|
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)
|
mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
|
||||||
f, err = winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createmode)
|
f, err = openRelative(name, w.root, mode, syscall.FILE_SHARE_READ, _FILE_CREATE, extraFlags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return makeError(err, "Failed to OpenForBackup", path)
|
return makeError(err, "Failed to openRelative", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = winio.SetFileBasicInfo(f, fileInfo)
|
err = winio.SetFileBasicInfo(f, fileInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return makeError(err, "Failed to SetFileBasicInfo", path)
|
return makeError(err, "Failed to SetFileBasicInfo", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.f = f
|
w.f = f
|
||||||
@ -129,17 +119,7 @@ func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
linkpath, err := makeLongAbsPath(filepath.Join(w.root, name))
|
return linkRelative(target, w.root, name, w.root)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
linktarget, err := makeLongAbsPath(filepath.Join(w.root, target))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.Link(linktarget, linkpath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *baseLayerWriter) Remove(name string) error {
|
func (w *baseLayerWriter) Remove(name string) error {
|
||||||
@ -155,6 +135,10 @@ func (w *baseLayerWriter) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *baseLayerWriter) Close() error {
|
func (w *baseLayerWriter) Close() error {
|
||||||
|
defer func() {
|
||||||
|
w.root.Close()
|
||||||
|
w.root = nil
|
||||||
|
}()
|
||||||
err := w.closeCurrentFile()
|
err := w.closeCurrentFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -162,18 +146,22 @@ func (w *baseLayerWriter) Close() error {
|
|||||||
if w.err == nil {
|
if w.err == nil {
|
||||||
// Restore the file times of all the directories, since they may have
|
// Restore the file times of all the directories, since they may have
|
||||||
// been modified by creating child directories.
|
// been modified by creating child directories.
|
||||||
err = reapplyDirectoryTimes(w.dirInfo)
|
err = reapplyDirectoryTimes(w.root, w.dirInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ProcessBaseLayer(w.root)
|
err = ProcessBaseLayer(w.root.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.hasUtilityVM {
|
if w.hasUtilityVM {
|
||||||
err = ProcessUtilityVMImage(filepath.Join(w.root, "UtilityVM"))
|
err := ensureNotReparsePointRelative("UtilityVM", w.root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ProcessUtilityVMImage(filepath.Join(w.root.Name(), "UtilityVM"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/Microsoft/hcsshim/hcsshim.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/hcsshim.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go
|
//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go safeopen.go
|
||||||
|
|
||||||
//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree
|
//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree
|
||||||
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
|
//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
|
||||||
|
38
vendor/github.com/Microsoft/hcsshim/importlayer.go
generated
vendored
38
vendor/github.com/Microsoft/hcsshim/importlayer.go
generated
vendored
@ -129,37 +129,39 @@ type legacyLayerWriterWrapper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *legacyLayerWriterWrapper) Close() error {
|
func (r *legacyLayerWriterWrapper) Close() error {
|
||||||
defer os.RemoveAll(r.root)
|
defer os.RemoveAll(r.root.Name())
|
||||||
|
defer r.legacyLayerWriter.CloseRoots()
|
||||||
err := r.legacyLayerWriter.Close()
|
err := r.legacyLayerWriter.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the original path here because ImportLayer does not support long paths for the source in TP5.
|
|
||||||
// But do use a long path for the destination to work around another bug with directories
|
|
||||||
// with MAX_PATH - 12 < length < MAX_PATH.
|
|
||||||
info := r.info
|
info := r.info
|
||||||
fullPath, err := makeLongAbsPath(filepath.Join(info.HomeDir, r.layerID))
|
info.HomeDir = ""
|
||||||
if err != nil {
|
if err = ImportLayer(info, r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, name := range r.Tombstones {
|
||||||
info.HomeDir = ""
|
if err = removeRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) {
|
||||||
if err = ImportLayer(info, fullPath, r.path, r.parentLayerPaths); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Add any hard links that were collected.
|
// Add any hard links that were collected.
|
||||||
for _, lnk := range r.PendingLinks {
|
for _, lnk := range r.PendingLinks {
|
||||||
if err = os.Remove(lnk.Path); err != nil && !os.IsNotExist(err) {
|
if err = removeRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = os.Link(lnk.Target, lnk.Path); err != nil {
|
if err = linkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Prepare the utility VM for use if one is present in the layer.
|
// Prepare the utility VM for use if one is present in the layer.
|
||||||
if r.HasUtilityVM {
|
if r.HasUtilityVM {
|
||||||
err = ProcessUtilityVMImage(filepath.Join(fullPath, "UtilityVM"))
|
err := ensureNotReparsePointRelative("UtilityVM", r.destRoot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -173,8 +175,12 @@ func (r *legacyLayerWriterWrapper) Close() error {
|
|||||||
func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) {
|
func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) {
|
||||||
if len(parentLayerPaths) == 0 {
|
if len(parentLayerPaths) == 0 {
|
||||||
// This is a base layer. It gets imported differently.
|
// This is a base layer. It gets imported differently.
|
||||||
|
f, err := openRoot(filepath.Join(info.HomeDir, layerID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &baseLayerWriter{
|
return &baseLayerWriter{
|
||||||
root: filepath.Join(info.HomeDir, layerID),
|
root: f,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,8 +191,12 @@ func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
w, err := newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &legacyLayerWriterWrapper{
|
return &legacyLayerWriterWrapper{
|
||||||
legacyLayerWriter: newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)),
|
legacyLayerWriter: w,
|
||||||
info: info,
|
info: info,
|
||||||
layerID: layerID,
|
layerID: layerID,
|
||||||
path: path,
|
path: path,
|
||||||
|
271
vendor/github.com/Microsoft/hcsshim/legacy.go
generated
vendored
271
vendor/github.com/Microsoft/hcsshim/legacy.go
generated
vendored
@ -121,6 +121,16 @@ func (r *legacyLayerReader) walkUntilCancelled() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 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$") {
|
if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -326,59 +336,79 @@ func (r *legacyLayerReader) Close() error {
|
|||||||
|
|
||||||
type pendingLink struct {
|
type pendingLink struct {
|
||||||
Path, Target string
|
Path, Target string
|
||||||
|
TargetRoot *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
type pendingDir struct {
|
||||||
|
Path string
|
||||||
|
Root *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
type legacyLayerWriter struct {
|
type legacyLayerWriter struct {
|
||||||
root string
|
root *os.File
|
||||||
parentRoots []string
|
destRoot *os.File
|
||||||
destRoot string
|
parentRoots []*os.File
|
||||||
currentFile *os.File
|
currentFile *os.File
|
||||||
|
currentFileName string
|
||||||
|
currentFileRoot *os.File
|
||||||
backupWriter *winio.BackupFileWriter
|
backupWriter *winio.BackupFileWriter
|
||||||
tombstones []string
|
Tombstones []string
|
||||||
pathFixed bool
|
|
||||||
HasUtilityVM bool
|
HasUtilityVM bool
|
||||||
uvmDi []dirInfo
|
uvmDi []dirInfo
|
||||||
addedFiles map[string]bool
|
addedFiles map[string]bool
|
||||||
PendingLinks []pendingLink
|
PendingLinks []pendingLink
|
||||||
|
pendingDirs []pendingDir
|
||||||
|
currentIsDir bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
|
// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
|
||||||
// transport format to disk.
|
// transport format to disk.
|
||||||
func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) *legacyLayerWriter {
|
func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w *legacyLayerWriter, err error) {
|
||||||
return &legacyLayerWriter{
|
w = &legacyLayerWriter{
|
||||||
root: root,
|
|
||||||
parentRoots: parentRoots,
|
|
||||||
destRoot: destRoot,
|
|
||||||
addedFiles: make(map[string]bool),
|
addedFiles: make(map[string]bool),
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
w.CloseRoots()
|
||||||
|
w = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
w.root, err = openRoot(root)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.destRoot, err = openRoot(destRoot)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, r := range parentRoots {
|
||||||
|
f, err := openRoot(r)
|
||||||
|
if err != nil {
|
||||||
|
return w, err
|
||||||
|
}
|
||||||
|
w.parentRoots = append(w.parentRoots, f)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) init() error {
|
func (w *legacyLayerWriter) CloseRoots() {
|
||||||
if !w.pathFixed {
|
if w.root != nil {
|
||||||
path, err := makeLongAbsPath(w.root)
|
w.root.Close()
|
||||||
if err != nil {
|
w.root = nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
for i, p := range w.parentRoots {
|
if w.destRoot != nil {
|
||||||
w.parentRoots[i], err = makeLongAbsPath(p)
|
w.destRoot.Close()
|
||||||
if err != nil {
|
w.destRoot = nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
for i := range w.parentRoots {
|
||||||
|
w.parentRoots[i].Close()
|
||||||
}
|
}
|
||||||
destPath, err := makeLongAbsPath(w.destRoot)
|
w.parentRoots = nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.root = path
|
|
||||||
w.destRoot = destPath
|
|
||||||
w.pathFixed = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) initUtilityVM() error {
|
func (w *legacyLayerWriter) initUtilityVM() error {
|
||||||
if !w.HasUtilityVM {
|
if !w.HasUtilityVM {
|
||||||
err := os.Mkdir(filepath.Join(w.destRoot, utilityVMPath), 0)
|
err := mkdirRelative(utilityVMPath, w.destRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -386,7 +416,7 @@ func (w *legacyLayerWriter) initUtilityVM() error {
|
|||||||
// clone the utility VM from the parent layer into this layer. Use hard
|
// clone the utility VM from the parent layer into this layer. Use hard
|
||||||
// links to avoid unnecessary copying, since most of the files are
|
// links to avoid unnecessary copying, since most of the files are
|
||||||
// immutable.
|
// immutable.
|
||||||
err = cloneTree(filepath.Join(w.parentRoots[0], utilityVMFilesPath), filepath.Join(w.destRoot, utilityVMFilesPath), mutatedUtilityVMFiles)
|
err = cloneTree(w.parentRoots[0], w.destRoot, utilityVMFilesPath, mutatedUtilityVMFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
|
return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
|
||||||
}
|
}
|
||||||
@ -395,7 +425,40 @@ func (w *legacyLayerWriter) initUtilityVM() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) reset() {
|
func (w *legacyLayerWriter) reset() error {
|
||||||
|
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 := 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 {
|
if w.backupWriter != nil {
|
||||||
w.backupWriter.Close()
|
w.backupWriter.Close()
|
||||||
w.backupWriter = nil
|
w.backupWriter = nil
|
||||||
@ -403,21 +466,21 @@ func (w *legacyLayerWriter) reset() {
|
|||||||
if w.currentFile != nil {
|
if w.currentFile != nil {
|
||||||
w.currentFile.Close()
|
w.currentFile.Close()
|
||||||
w.currentFile = nil
|
w.currentFile = nil
|
||||||
|
w.currentFileName = ""
|
||||||
|
w.currentFileRoot = nil
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata
|
// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata
|
||||||
func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) {
|
func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) {
|
||||||
createDisposition := uint32(syscall.CREATE_NEW)
|
src, err := openRelative(
|
||||||
if isDir {
|
subPath,
|
||||||
err = os.Mkdir(destPath, 0)
|
srcRoot,
|
||||||
if err != nil {
|
syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY,
|
||||||
return nil, err
|
syscall.FILE_SHARE_READ,
|
||||||
}
|
_FILE_OPEN,
|
||||||
createDisposition = syscall.OPEN_EXISTING
|
_FILE_OPEN_REPARSE_POINT)
|
||||||
}
|
|
||||||
|
|
||||||
src, err := openFileOrDir(srcPath, syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, syscall.OPEN_EXISTING)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -430,7 +493,17 @@ func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dest, err := openFileOrDir(destPath, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition)
|
extraFlags := uint32(0)
|
||||||
|
if isDir {
|
||||||
|
extraFlags |= _FILE_DIRECTORY_FILE
|
||||||
|
}
|
||||||
|
dest, err := openRelative(
|
||||||
|
subPath,
|
||||||
|
destRoot,
|
||||||
|
syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY,
|
||||||
|
syscall.FILE_SHARE_READ,
|
||||||
|
_FILE_CREATE,
|
||||||
|
extraFlags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -459,18 +532,21 @@ func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio
|
|||||||
|
|
||||||
// cloneTree clones a directory tree using hard links. It skips hard links for
|
// 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.
|
// the file names in the provided map and just copies those files.
|
||||||
func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
|
func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles map[string]bool) error {
|
||||||
var di []dirInfo
|
var di []dirInfo
|
||||||
err := filepath.Walk(srcPath, func(srcFilePath string, info os.FileInfo, err error) error {
|
err := 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
relPath, err := filepath.Rel(srcPath, srcFilePath)
|
relPath, err := filepath.Rel(srcRoot.Name(), srcFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
destFilePath := filepath.Join(destPath, relPath)
|
|
||||||
|
|
||||||
fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||||
// Directories, reparse points, and files that will be mutated during
|
// Directories, reparse points, and files that will be mutated during
|
||||||
@ -482,15 +558,15 @@ func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
|
|||||||
isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
|
isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
|
||||||
|
|
||||||
if isDir || isReparsePoint || mutatedFiles[relPath] {
|
if isDir || isReparsePoint || mutatedFiles[relPath] {
|
||||||
fi, err := copyFileWithMetadata(srcFilePath, destFilePath, isDir)
|
fi, err := copyFileWithMetadata(srcRoot, destRoot, relPath, isDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if isDir && !isReparsePoint {
|
if isDir && !isReparsePoint {
|
||||||
di = append(di, dirInfo{path: destFilePath, fileInfo: *fi})
|
di = append(di, dirInfo{path: relPath, fileInfo: *fi})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = os.Link(srcFilePath, destFilePath)
|
err = linkRelative(relPath, srcRoot, relPath, destRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -508,13 +584,11 @@ func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return reapplyDirectoryTimes(di)
|
return reapplyDirectoryTimes(destRoot, di)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
|
func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
|
||||||
w.reset()
|
if err := w.reset(); err != nil {
|
||||||
err := w.init()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,6 +596,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
return w.initUtilityVM()
|
return w.initUtilityVM()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = filepath.Clean(name)
|
||||||
if hasPathPrefix(name, utilityVMPath) {
|
if hasPathPrefix(name, utilityVMPath) {
|
||||||
if !w.HasUtilityVM {
|
if !w.HasUtilityVM {
|
||||||
return errors.New("missing UtilityVM directory")
|
return errors.New("missing UtilityVM directory")
|
||||||
@ -529,10 +604,9 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
|
if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
|
||||||
return errors.New("invalid UtilityVM layer")
|
return errors.New("invalid UtilityVM layer")
|
||||||
}
|
}
|
||||||
path := filepath.Join(w.destRoot, name)
|
createDisposition := uint32(_FILE_OPEN)
|
||||||
createDisposition := uint32(syscall.OPEN_EXISTING)
|
|
||||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||||
st, err := os.Lstat(path)
|
st, err := lstatRelative(name, w.destRoot)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -540,37 +614,44 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
// Delete the existing file/directory if it is not the same type as this directory.
|
// Delete the existing file/directory if it is not the same type as this directory.
|
||||||
existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||||
if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
||||||
if err = os.RemoveAll(path); err != nil {
|
if err = removeAllRelative(name, w.destRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
st = nil
|
st = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if st == nil {
|
if st == nil {
|
||||||
if err = os.Mkdir(path, 0); err != nil {
|
if err = mkdirRelative(name, w.destRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
|
||||||
w.uvmDi = append(w.uvmDi, dirInfo{path: path, fileInfo: *fileInfo})
|
w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Overwrite any existing hard link.
|
// Overwrite any existing hard link.
|
||||||
err = os.Remove(path)
|
err := removeRelative(name, w.destRoot)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
createDisposition = syscall.CREATE_NEW
|
createDisposition = _FILE_CREATE
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition)
|
f, err := 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,
|
||||||
|
_FILE_OPEN_REPARSE_POINT,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
os.Remove(path)
|
removeRelative(name, w.destRoot)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -581,28 +662,31 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
|
|
||||||
w.backupWriter = winio.NewBackupFileWriter(f, true)
|
w.backupWriter = winio.NewBackupFileWriter(f, true)
|
||||||
w.currentFile = f
|
w.currentFile = f
|
||||||
|
w.currentFileName = name
|
||||||
|
w.currentFileRoot = w.destRoot
|
||||||
w.addedFiles[name] = true
|
w.addedFiles[name] = true
|
||||||
f = nil
|
f = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(w.root, name)
|
fname := name
|
||||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||||
err := os.Mkdir(path, 0)
|
err := mkdirRelative(name, w.root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
path += ".$wcidirs$"
|
fname += ".$wcidirs$"
|
||||||
|
w.currentIsDir = true
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.CREATE_NEW)
|
f, err := openRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, _FILE_CREATE, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
os.Remove(path)
|
removeRelative(fname, w.root)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -624,19 +708,20 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.currentFile = f
|
w.currentFile = f
|
||||||
|
w.currentFileName = name
|
||||||
|
w.currentFileRoot = w.root
|
||||||
w.addedFiles[name] = true
|
w.addedFiles[name] = true
|
||||||
f = nil
|
f = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
||||||
w.reset()
|
if err := w.reset(); err != nil {
|
||||||
err := w.init()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var roots []string
|
target = filepath.Clean(target)
|
||||||
|
var roots []*os.File
|
||||||
if hasPathPrefix(target, filesPath) {
|
if hasPathPrefix(target, filesPath) {
|
||||||
// Look for cross-layer hard link targets in the parent layers, since
|
// Look for cross-layer hard link targets in the parent layers, since
|
||||||
// nothing is in the destination path yet.
|
// nothing is in the destination path yet.
|
||||||
@ -645,7 +730,7 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
|||||||
// Since the utility VM is fully cloned into the destination path
|
// Since the utility VM is fully cloned into the destination path
|
||||||
// already, look for cross-layer hard link targets directly in the
|
// already, look for cross-layer hard link targets directly in the
|
||||||
// destination path.
|
// destination path.
|
||||||
roots = []string{w.destRoot}
|
roots = []*os.File{w.destRoot}
|
||||||
}
|
}
|
||||||
|
|
||||||
if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
|
if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
|
||||||
@ -654,12 +739,12 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
|||||||
|
|
||||||
// Find to try the target of the link in a previously added file. If that
|
// Find to try the target of the link in a previously added file. If that
|
||||||
// fails, search in parent layers.
|
// fails, search in parent layers.
|
||||||
var selectedRoot string
|
var selectedRoot *os.File
|
||||||
if _, ok := w.addedFiles[target]; ok {
|
if _, ok := w.addedFiles[target]; ok {
|
||||||
selectedRoot = w.destRoot
|
selectedRoot = w.destRoot
|
||||||
} else {
|
} else {
|
||||||
for _, r := range roots {
|
for _, r := range roots {
|
||||||
if _, err = os.Lstat(filepath.Join(r, target)); err != nil {
|
if _, err := lstatRelative(target, r); err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -668,22 +753,25 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if selectedRoot == "" {
|
if selectedRoot == nil {
|
||||||
return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
|
return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The link can't be written until after the ImportLayer call.
|
// The link can't be written until after the ImportLayer call.
|
||||||
w.PendingLinks = append(w.PendingLinks, pendingLink{
|
w.PendingLinks = append(w.PendingLinks, pendingLink{
|
||||||
Path: filepath.Join(w.destRoot, name),
|
Path: name,
|
||||||
Target: filepath.Join(selectedRoot, target),
|
Target: target,
|
||||||
|
TargetRoot: selectedRoot,
|
||||||
})
|
})
|
||||||
w.addedFiles[name] = true
|
w.addedFiles[name] = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) Remove(name string) error {
|
func (w *legacyLayerWriter) Remove(name string) error {
|
||||||
|
name = filepath.Clean(name)
|
||||||
if hasPathPrefix(name, filesPath) {
|
if hasPathPrefix(name, filesPath) {
|
||||||
w.tombstones = append(w.tombstones, name[len(filesPath)+1:])
|
w.Tombstones = append(w.Tombstones, name)
|
||||||
} else if hasPathPrefix(name, utilityVMFilesPath) {
|
} else if hasPathPrefix(name, utilityVMFilesPath) {
|
||||||
err := w.initUtilityVM()
|
err := w.initUtilityVM()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -692,11 +780,10 @@ func (w *legacyLayerWriter) Remove(name string) error {
|
|||||||
// Make sure the path exists; os.RemoveAll will not fail if the file is
|
// 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
|
// already gone, and this needs to be a fatal error for diagnostics
|
||||||
// purposes.
|
// purposes.
|
||||||
path := filepath.Join(w.destRoot, name)
|
if _, err := lstatRelative(name, w.destRoot); err != nil {
|
||||||
if _, err := os.Lstat(path); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.RemoveAll(path)
|
err = removeAllRelative(name, w.destRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -718,28 +805,20 @@ func (w *legacyLayerWriter) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *legacyLayerWriter) Close() error {
|
func (w *legacyLayerWriter) Close() error {
|
||||||
w.reset()
|
if err := w.reset(); err != nil {
|
||||||
err := w.init()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tf, err := os.Create(filepath.Join(w.root, "tombstones.txt"))
|
if err := removeRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer tf.Close()
|
for _, pd := range w.pendingDirs {
|
||||||
_, err = tf.Write([]byte("\xef\xbb\xbfVersion 1.0\n"))
|
err := mkdirRelative(pd.Path, pd.Root)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, t := range w.tombstones {
|
|
||||||
_, err = tf.Write([]byte(filepath.Join(`\`, t) + "\n"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if w.HasUtilityVM {
|
if w.HasUtilityVM {
|
||||||
err = reapplyDirectoryTimes(w.uvmDi)
|
err := reapplyDirectoryTimes(w.destRoot, w.uvmDi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
427
vendor/github.com/Microsoft/hcsshim/safeopen.go
generated
vendored
Normal file
427
vendor/github.com/Microsoft/hcsshim/safeopen.go
generated
vendored
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
package hcsshim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
winio "github.com/Microsoft/go-winio"
|
||||||
|
)
|
||||||
|
|
||||||
|
//sys ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) = ntdll.NtCreateFile
|
||||||
|
//sys ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) = ntdll.NtSetInformationFile
|
||||||
|
//sys rtlNtStatusToDosError(status uint32) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||||
|
//sys localAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc
|
||||||
|
//sys localFree(ptr uintptr) = kernel32.LocalFree
|
||||||
|
|
||||||
|
type ioStatusBlock struct {
|
||||||
|
Status, Information uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type objectAttributes struct {
|
||||||
|
Length uintptr
|
||||||
|
RootDirectory uintptr
|
||||||
|
ObjectName uintptr
|
||||||
|
Attributes uintptr
|
||||||
|
SecurityDescriptor uintptr
|
||||||
|
SecurityQoS uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type unicodeString struct {
|
||||||
|
Length uint16
|
||||||
|
MaximumLength uint16
|
||||||
|
Buffer uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileLinkInformation struct {
|
||||||
|
ReplaceIfExists bool
|
||||||
|
RootDirectory uintptr
|
||||||
|
FileNameLength uint32
|
||||||
|
FileName [1]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileDispositionInformationEx struct {
|
||||||
|
Flags uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
_FileLinkInformation = 11
|
||||||
|
_FileDispositionInformationEx = 64
|
||||||
|
|
||||||
|
_FILE_READ_ATTRIBUTES = 0x0080
|
||||||
|
_FILE_WRITE_ATTRIBUTES = 0x0100
|
||||||
|
_DELETE = 0x10000
|
||||||
|
|
||||||
|
_FILE_OPEN = 1
|
||||||
|
_FILE_CREATE = 2
|
||||||
|
|
||||||
|
_FILE_DIRECTORY_FILE = 0x00000001
|
||||||
|
_FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020
|
||||||
|
_FILE_DELETE_ON_CLOSE = 0x00001000
|
||||||
|
_FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000
|
||||||
|
_FILE_OPEN_REPARSE_POINT = 0x00200000
|
||||||
|
|
||||||
|
_FILE_DISPOSITION_DELETE = 0x00000001
|
||||||
|
|
||||||
|
_OBJ_DONT_REPARSE = 0x1000
|
||||||
|
|
||||||
|
_STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B
|
||||||
|
)
|
||||||
|
|
||||||
|
func openRoot(path string) (*os.File, error) {
|
||||||
|
longpath, err := makeLongAbsPath(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return winio.OpenForBackup(longpath, syscall.GENERIC_READ, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, syscall.OPEN_EXISTING)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ntRelativePath(path string) ([]uint16, error) {
|
||||||
|
path = filepath.Clean(path)
|
||||||
|
if strings.Contains(":", path) {
|
||||||
|
// Since alternate data streams must follow the file they
|
||||||
|
// are attached to, finding one here (out of order) is invalid.
|
||||||
|
return nil, errors.New("path contains invalid character `:`")
|
||||||
|
}
|
||||||
|
fspath := filepath.FromSlash(path)
|
||||||
|
if len(fspath) > 0 && fspath[0] == '\\' {
|
||||||
|
return nil, errors.New("expected relative path")
|
||||||
|
}
|
||||||
|
|
||||||
|
path16 := utf16.Encode(([]rune)(fspath))
|
||||||
|
if len(path16) > 32767 {
|
||||||
|
return nil, syscall.ENAMETOOLONG
|
||||||
|
}
|
||||||
|
|
||||||
|
return path16, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// openRelativeInternal opens a relative path from the given root, failing if
|
||||||
|
// any of the intermediate path components are reparse points.
|
||||||
|
func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) {
|
||||||
|
var (
|
||||||
|
h uintptr
|
||||||
|
iosb ioStatusBlock
|
||||||
|
oa objectAttributes
|
||||||
|
)
|
||||||
|
|
||||||
|
path16, err := ntRelativePath(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if root == nil || root.Fd() == 0 {
|
||||||
|
return nil, errors.New("missing root directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
upathBuffer := localAlloc(0, int(unsafe.Sizeof(unicodeString{}))+len(path16)*2)
|
||||||
|
defer localFree(upathBuffer)
|
||||||
|
|
||||||
|
upath := (*unicodeString)(unsafe.Pointer(upathBuffer))
|
||||||
|
upath.Length = uint16(len(path16) * 2)
|
||||||
|
upath.MaximumLength = upath.Length
|
||||||
|
upath.Buffer = upathBuffer + unsafe.Sizeof(*upath)
|
||||||
|
copy((*[32768]uint16)(unsafe.Pointer(upath.Buffer))[:], path16)
|
||||||
|
|
||||||
|
oa.Length = unsafe.Sizeof(oa)
|
||||||
|
oa.ObjectName = upathBuffer
|
||||||
|
oa.RootDirectory = uintptr(root.Fd())
|
||||||
|
oa.Attributes = _OBJ_DONT_REPARSE
|
||||||
|
status := ntCreateFile(
|
||||||
|
&h,
|
||||||
|
accessMask|syscall.SYNCHRONIZE,
|
||||||
|
&oa,
|
||||||
|
&iosb,
|
||||||
|
nil,
|
||||||
|
0,
|
||||||
|
shareFlags,
|
||||||
|
createDisposition,
|
||||||
|
_FILE_OPEN_FOR_BACKUP_INTENT|_FILE_SYNCHRONOUS_IO_NONALERT|flags,
|
||||||
|
nil,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if status != 0 {
|
||||||
|
return nil, rtlNtStatusToDosError(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPath, err := makeLongAbsPath(filepath.Join(root.Name(), path))
|
||||||
|
if err != nil {
|
||||||
|
syscall.Close(syscall.Handle(h))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.NewFile(h, fullPath), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// openRelative opens a relative path from the given root, failing if
|
||||||
|
// any of the intermediate path components are reparse points.
|
||||||
|
func openRelative(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) {
|
||||||
|
f, err := openRelativeInternal(path, root, accessMask, shareFlags, createDisposition, flags)
|
||||||
|
if err != nil {
|
||||||
|
err = &os.PathError{Op: "open", Path: filepath.Join(root.Name(), path), Err: err}
|
||||||
|
}
|
||||||
|
return f, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// linkRelative creates a hard link from oldname to newname (relative to oldroot
|
||||||
|
// and newroot), failing if any of the intermediate path components are reparse
|
||||||
|
// points.
|
||||||
|
func linkRelative(oldname string, oldroot *os.File, newname string, newroot *os.File) error {
|
||||||
|
// Open the old file.
|
||||||
|
oldf, err := openRelativeInternal(
|
||||||
|
oldname,
|
||||||
|
oldroot,
|
||||||
|
syscall.FILE_WRITE_ATTRIBUTES,
|
||||||
|
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||||
|
_FILE_OPEN,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return &os.LinkError{Op: "link", Old: filepath.Join(oldroot.Name(), oldname), New: filepath.Join(newroot.Name(), newname), Err: err}
|
||||||
|
}
|
||||||
|
defer oldf.Close()
|
||||||
|
|
||||||
|
// Open the parent of the new file.
|
||||||
|
var parent *os.File
|
||||||
|
parentPath := filepath.Dir(newname)
|
||||||
|
if parentPath != "." {
|
||||||
|
parent, err = openRelativeInternal(
|
||||||
|
parentPath,
|
||||||
|
newroot,
|
||||||
|
syscall.GENERIC_READ,
|
||||||
|
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||||
|
_FILE_OPEN,
|
||||||
|
_FILE_DIRECTORY_FILE)
|
||||||
|
if err != nil {
|
||||||
|
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: err}
|
||||||
|
}
|
||||||
|
defer parent.Close()
|
||||||
|
|
||||||
|
fi, err := winio.GetFileBasicInfo(parent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if (fi.FileAttributes & syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
||||||
|
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: rtlNtStatusToDosError(_STATUS_REPARSE_POINT_ENCOUNTERED)}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
parent = newroot
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue an NT call to create the link. This will be safe because NT will
|
||||||
|
// not open any more directories to create the link, so it cannot walk any
|
||||||
|
// more reparse points.
|
||||||
|
newbase := filepath.Base(newname)
|
||||||
|
newbase16, err := ntRelativePath(newbase)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
size := int(unsafe.Offsetof(fileLinkInformation{}.FileName)) + len(newbase16)*2
|
||||||
|
linkinfoBuffer := localAlloc(0, size)
|
||||||
|
defer localFree(linkinfoBuffer)
|
||||||
|
linkinfo := (*fileLinkInformation)(unsafe.Pointer(linkinfoBuffer))
|
||||||
|
linkinfo.RootDirectory = parent.Fd()
|
||||||
|
linkinfo.FileNameLength = uint32(len(newbase16) * 2)
|
||||||
|
copy((*[32768]uint16)(unsafe.Pointer(&linkinfo.FileName[0]))[:], newbase16)
|
||||||
|
|
||||||
|
var iosb ioStatusBlock
|
||||||
|
status := ntSetInformationFile(
|
||||||
|
oldf.Fd(),
|
||||||
|
&iosb,
|
||||||
|
linkinfoBuffer,
|
||||||
|
uint32(size),
|
||||||
|
_FileLinkInformation,
|
||||||
|
)
|
||||||
|
if status != 0 {
|
||||||
|
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(parent.Name(), newbase), Err: rtlNtStatusToDosError(status)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteOnClose marks a file to be deleted when the handle is closed.
|
||||||
|
func deleteOnClose(f *os.File) error {
|
||||||
|
disposition := fileDispositionInformationEx{Flags: _FILE_DISPOSITION_DELETE}
|
||||||
|
var iosb ioStatusBlock
|
||||||
|
status := ntSetInformationFile(
|
||||||
|
f.Fd(),
|
||||||
|
&iosb,
|
||||||
|
uintptr(unsafe.Pointer(&disposition)),
|
||||||
|
uint32(unsafe.Sizeof(disposition)),
|
||||||
|
_FileDispositionInformationEx,
|
||||||
|
)
|
||||||
|
if status != 0 {
|
||||||
|
return rtlNtStatusToDosError(status)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// clearReadOnly clears the readonly attribute on a file.
|
||||||
|
func clearReadOnly(f *os.File) error {
|
||||||
|
bi, err := winio.GetFileBasicInfo(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if bi.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sbi := winio.FileBasicInfo{
|
||||||
|
FileAttributes: bi.FileAttributes &^ syscall.FILE_ATTRIBUTE_READONLY,
|
||||||
|
}
|
||||||
|
if sbi.FileAttributes == 0 {
|
||||||
|
sbi.FileAttributes = syscall.FILE_ATTRIBUTE_NORMAL
|
||||||
|
}
|
||||||
|
return winio.SetFileBasicInfo(f, &sbi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeRelative removes a file or directory relative to a root, failing if any
|
||||||
|
// intermediate path components are reparse points.
|
||||||
|
func removeRelative(path string, root *os.File) error {
|
||||||
|
f, err := openRelativeInternal(
|
||||||
|
path,
|
||||||
|
root,
|
||||||
|
_FILE_READ_ATTRIBUTES|_FILE_WRITE_ATTRIBUTES|_DELETE,
|
||||||
|
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||||
|
_FILE_OPEN,
|
||||||
|
_FILE_OPEN_REPARSE_POINT)
|
||||||
|
if err == nil {
|
||||||
|
defer f.Close()
|
||||||
|
err = deleteOnClose(f)
|
||||||
|
if err == syscall.ERROR_ACCESS_DENIED {
|
||||||
|
// Maybe the file is marked readonly. Clear the bit and retry.
|
||||||
|
clearReadOnly(f)
|
||||||
|
err = deleteOnClose(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return &os.PathError{Op: "remove", Path: filepath.Join(root.Name(), path), Err: err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeAllRelative removes a directory tree relative to a root, failing if any
|
||||||
|
// intermediate path components are reparse points.
|
||||||
|
func removeAllRelative(path string, root *os.File) error {
|
||||||
|
fi, err := lstatRelative(path, root)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fileAttributes := fi.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||||
|
if fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 || fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||||
|
// If this is a reparse point, it can't have children. Simple remove will do.
|
||||||
|
err := removeRelative(path, root)
|
||||||
|
if err == nil || os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is necessary to use os.Open as Readdirnames does not work with
|
||||||
|
// openRelative. This is safe because the above lstatrelative fails
|
||||||
|
// if the target is outside the root, and we know this is not a
|
||||||
|
// symlink from the above FILE_ATTRIBUTE_REPARSE_POINT check.
|
||||||
|
fd, err := os.Open(filepath.Join(root.Name(), path))
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// Race. It was deleted between the Lstat and Open.
|
||||||
|
// Return nil per RemoveAll's docs.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove contents & return first error.
|
||||||
|
for {
|
||||||
|
names, err1 := fd.Readdirnames(100)
|
||||||
|
for _, name := range names {
|
||||||
|
err1 := removeAllRelative(path+string(os.PathSeparator)+name, root)
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err1 == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// If Readdirnames returned an error, use it.
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
if len(names) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fd.Close()
|
||||||
|
|
||||||
|
// Remove directory.
|
||||||
|
err1 := removeRelative(path, root)
|
||||||
|
if err1 == nil || os.IsNotExist(err1) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// mkdirRelative creates a directory relative to a root, failing if any
|
||||||
|
// intermediate path components are reparse points.
|
||||||
|
func mkdirRelative(path string, root *os.File) error {
|
||||||
|
f, err := openRelativeInternal(
|
||||||
|
path,
|
||||||
|
root,
|
||||||
|
0,
|
||||||
|
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||||
|
_FILE_CREATE,
|
||||||
|
_FILE_DIRECTORY_FILE)
|
||||||
|
if err == nil {
|
||||||
|
f.Close()
|
||||||
|
} else {
|
||||||
|
err = &os.PathError{Op: "mkdir", Path: filepath.Join(root.Name(), path), Err: err}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// lstatRelative performs a stat operation on a file relative to a root, failing
|
||||||
|
// if any intermediate path components are reparse points.
|
||||||
|
func lstatRelative(path string, root *os.File) (os.FileInfo, error) {
|
||||||
|
f, err := openRelativeInternal(
|
||||||
|
path,
|
||||||
|
root,
|
||||||
|
_FILE_READ_ATTRIBUTES,
|
||||||
|
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||||
|
_FILE_OPEN,
|
||||||
|
_FILE_OPEN_REPARSE_POINT)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &os.PathError{Op: "stat", Path: filepath.Join(root.Name(), path), Err: err}
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return f.Stat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensureNotReparsePointRelative validates that a given file (relative to a
|
||||||
|
// root) and all intermediate path components are not a reparse points.
|
||||||
|
func ensureNotReparsePointRelative(path string, root *os.File) error {
|
||||||
|
// Perform an open with OBJ_DONT_REPARSE but without specifying FILE_OPEN_REPARSE_POINT.
|
||||||
|
f, err := openRelative(
|
||||||
|
path,
|
||||||
|
root,
|
||||||
|
0,
|
||||||
|
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||||
|
_FILE_OPEN,
|
||||||
|
0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
return nil
|
||||||
|
}
|
38
vendor/github.com/Microsoft/hcsshim/zhcsshim.go
generated
vendored
38
vendor/github.com/Microsoft/hcsshim/zhcsshim.go
generated
vendored
@ -41,6 +41,8 @@ var (
|
|||||||
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||||
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
||||||
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
|
modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
|
||||||
|
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
|
||||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||||
procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
|
procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
|
||||||
@ -94,6 +96,11 @@ var (
|
|||||||
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
||||||
procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
|
procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
|
||||||
procHNSCall = modvmcompute.NewProc("HNSCall")
|
procHNSCall = modvmcompute.NewProc("HNSCall")
|
||||||
|
procNtCreateFile = modntdll.NewProc("NtCreateFile")
|
||||||
|
procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile")
|
||||||
|
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||||
|
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||||
|
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||||
)
|
)
|
||||||
|
|
||||||
func coTaskMemFree(buffer unsafe.Pointer) {
|
func coTaskMemFree(buffer unsafe.Pointer) {
|
||||||
@ -1040,3 +1047,34 @@ func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16)
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) {
|
||||||
|
r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(accessMask), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(fileAttributes), uintptr(shareAccess), uintptr(createDisposition), uintptr(createOptions), uintptr(unsafe.Pointer(eaBuffer)), uintptr(eaLength), 0)
|
||||||
|
status = uint32(r0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) {
|
||||||
|
r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(information), uintptr(length), uintptr(class), 0)
|
||||||
|
status = uint32(r0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func rtlNtStatusToDosError(status uint32) (winerr error) {
|
||||||
|
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||||
|
if r0 != 0 {
|
||||||
|
winerr = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func localAlloc(flags uint32, size int) (ptr uintptr) {
|
||||||
|
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(size), 0)
|
||||||
|
ptr = uintptr(r0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func localFree(ptr uintptr) {
|
||||||
|
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(ptr), 0, 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user