mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #26842 from jstarks/fix_save
Windows: Back up files mutated during layer import
This commit is contained in:
commit
5039d9aa6c
2 changed files with 57 additions and 78 deletions
|
@ -31,7 +31,6 @@ import (
|
|||
"github.com/docker/docker/pkg/longpath"
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/vbatts/tar-split/tar/storage"
|
||||
)
|
||||
|
||||
// filterDriver is an HCSShim driver type for the Windows Filter driver.
|
||||
|
@ -41,6 +40,15 @@ var (
|
|||
vmcomputedll = syscall.NewLazyDLL("vmcompute.dll")
|
||||
hcsExpandSandboxSize = vmcomputedll.NewProc("ExpandSandboxSize")
|
||||
hcsSandboxSizeSupported = hcsExpandSandboxSize.Find() == nil
|
||||
|
||||
// mutatedFiles is a list of files that are mutated by the import process
|
||||
// and must be backed up and restored.
|
||||
mutatedFiles = map[string]string{
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD": "bcd.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG": "bcd.log.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak",
|
||||
}
|
||||
)
|
||||
|
||||
// init registers the windows graph drivers to the register.
|
||||
|
@ -532,7 +540,48 @@ func (d *Driver) exportLayer(id string, parentLayerPaths []string) (archive.Arch
|
|||
return archive, nil
|
||||
}
|
||||
|
||||
func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter) (int64, error) {
|
||||
// writeBackupStreamFromTarAndSaveMutatedFiles reads data from a tar stream and
|
||||
// writes it to a backup stream, and also saves any files that will be mutated
|
||||
// by the import layer process to a backup location.
|
||||
func writeBackupStreamFromTarAndSaveMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Reader, hdr *tar.Header, root string) (nextHdr *tar.Header, err error) {
|
||||
var bcdBackup *os.File
|
||||
var bcdBackupWriter *winio.BackupFileWriter
|
||||
if backupPath, ok := mutatedFiles[hdr.Name]; ok {
|
||||
bcdBackup, err = os.Create(filepath.Join(root, backupPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := bcdBackup.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
bcdBackupWriter = winio.NewBackupFileWriter(bcdBackup, false)
|
||||
defer func() {
|
||||
cerr := bcdBackupWriter.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
buf.Reset(io.MultiWriter(w, bcdBackupWriter))
|
||||
} else {
|
||||
buf.Reset(w)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
ferr := buf.Flush()
|
||||
if err == nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
|
||||
return backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
|
||||
}
|
||||
|
||||
func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter, root string) (int64, error) {
|
||||
t := tar.NewReader(r)
|
||||
hdr, err := t.Next()
|
||||
totalSize := int64(0)
|
||||
|
@ -566,13 +615,7 @@ func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter) (int64, error) {
|
|||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
buf.Reset(w)
|
||||
|
||||
hdr, err = backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
|
||||
ferr := buf.Flush()
|
||||
if ferr != nil {
|
||||
err = ferr
|
||||
}
|
||||
hdr, err = writeBackupStreamFromTarAndSaveMutatedFiles(buf, w, t, hdr, root)
|
||||
totalSize += size
|
||||
}
|
||||
}
|
||||
|
@ -582,46 +625,6 @@ func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter) (int64, error) {
|
|||
return totalSize, nil
|
||||
}
|
||||
|
||||
func addAceToSddlDacl(sddl, ace string) (string, bool) {
|
||||
daclStart := strings.Index(sddl, "D:")
|
||||
if daclStart < 0 {
|
||||
return sddl, false
|
||||
}
|
||||
|
||||
dacl := sddl[daclStart:]
|
||||
daclEnd := strings.Index(dacl, "S:")
|
||||
if daclEnd < 0 {
|
||||
daclEnd = len(dacl)
|
||||
}
|
||||
dacl = dacl[:daclEnd]
|
||||
|
||||
if strings.Contains(dacl, ace) {
|
||||
return sddl, true
|
||||
}
|
||||
|
||||
i := 2
|
||||
for i+1 < len(dacl) {
|
||||
if dacl[i] != '(' {
|
||||
return sddl, false
|
||||
}
|
||||
|
||||
if dacl[i+1] == 'A' {
|
||||
break
|
||||
}
|
||||
|
||||
i += 2
|
||||
for p := 1; i < len(dacl) && p > 0; i++ {
|
||||
if dacl[i] == '(' {
|
||||
p++
|
||||
} else if dacl[i] == ')' {
|
||||
p--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sddl[:daclStart+i] + ace + sddl[daclStart+i:], true
|
||||
}
|
||||
|
||||
// importLayer adds a new layer to the tag and graph store based on the given data.
|
||||
func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPaths []string) (size int64, err error) {
|
||||
cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...)
|
||||
|
@ -663,7 +666,7 @@ func writeLayer() {
|
|||
return err
|
||||
}
|
||||
|
||||
size, err := writeLayerFromTar(os.Stdin, w)
|
||||
size, err := writeLayerFromTar(os.Stdin, w, filepath.Join(home, id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -743,6 +746,10 @@ type fileGetCloserWithBackupPrivileges struct {
|
|||
}
|
||||
|
||||
func (fg *fileGetCloserWithBackupPrivileges) Get(filename string) (io.ReadCloser, error) {
|
||||
if backupPath, ok := mutatedFiles[filename]; ok {
|
||||
return os.Open(filepath.Join(fg.path, backupPath))
|
||||
}
|
||||
|
||||
var f *os.File
|
||||
// Open the file while holding the Windows backup privilege. This ensures that the
|
||||
// file can be opened even if the caller does not actually have access to it according
|
||||
|
@ -767,16 +774,6 @@ func (fg *fileGetCloserWithBackupPrivileges) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type fileGetDestroyCloser struct {
|
||||
storage.FileGetter
|
||||
path string
|
||||
}
|
||||
|
||||
func (f *fileGetDestroyCloser) Close() error {
|
||||
// TODO: activate layers and release here?
|
||||
return os.RemoveAll(f.path)
|
||||
}
|
||||
|
||||
// DiffGetter returns a FileGetCloser that can read files from the directory that
|
||||
// contains files for the layer differences. Used for direct access for tar-split.
|
||||
func (d *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package windows
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestAddAceToSddlDacl(t *testing.T) {
|
||||
cases := [][3]string{
|
||||
{"D:", "(A;;;)", "D:(A;;;)"},
|
||||
{"D:(A;;;)", "(A;;;)", "D:(A;;;)"},
|
||||
{"O:D:(A;;;stuff)", "(A;;;new)", "O:D:(A;;;new)(A;;;stuff)"},
|
||||
{"O:D:(D;;;no)(A;;;stuff)", "(A;;;new)", "O:D:(D;;;no)(A;;;new)(A;;;stuff)"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
if newSddl, worked := addAceToSddlDacl(c[0], c[1]); !worked || newSddl != c[2] {
|
||||
t.Errorf("%s + %s == %s, expected %s (%v)", c[0], c[1], newSddl, c[2], worked)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue