X Tutup
Skip to content

Commit 3e47cdf

Browse files
committed
Use go-winio tar-application code instead of our own
applyFunc now takes an io.Reader instead of a tar.Reader because I'm trying to mirror the API of the not-yet-exposed implementation of this same behaviour in github.com/Microsoft/hcsshim/internal/ociwclayer, with an eye to later moving to that implementation it is ever exposed. Signed-off-by: Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
1 parent 0564725 commit 3e47cdf

File tree

8 files changed

+496
-216
lines changed

8 files changed

+496
-216
lines changed

archive/tar.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,18 @@ func Apply(ctx context.Context, root string, r io.Reader, opts ...ApplyOpt) (int
114114
options.applyFunc = applyNaive
115115
}
116116

117-
return options.applyFunc(ctx, root, tar.NewReader(r), options)
117+
return options.applyFunc(ctx, root, r, options)
118118
}
119119

120120
// applyNaive applies a tar stream of an OCI style diff tar to a directory
121121
// applying each file as either a whole file or whiteout.
122122
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
123-
func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
123+
func applyNaive(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
124124
var (
125125
dirs []*tar.Header
126126

127+
tr = tar.NewReader(r)
128+
127129
// Used for handling opaque directory markers which
128130
// may occur out of order
129131
unpackedPaths = make(map[string]struct{})

archive/tar_opts.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package archive
1919
import (
2020
"archive/tar"
2121
"context"
22+
"io"
2223
)
2324

2425
// ApplyOptions provides additional options for an Apply operation
@@ -27,7 +28,7 @@ type ApplyOptions struct {
2728
ConvertWhiteout ConvertWhiteout // Convert whiteout files
2829
Parents []string // Parent directories to handle inherited attributes without CoW
2930

30-
applyFunc func(context.Context, string, *tar.Reader, ApplyOptions) (int64, error)
31+
applyFunc func(context.Context, string, io.Reader, ApplyOptions) (int64, error)
3132
}
3233

3334
// ApplyOpt allows setting mutable archive apply properties on creation

archive/tar_windows.go

Lines changed: 5 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -22,38 +22,20 @@ import (
2222
"archive/tar"
2323
"bufio"
2424
"context"
25-
"encoding/base64"
2625
"fmt"
2726
"io"
2827
"os"
2928
"path"
3029
"path/filepath"
31-
"strconv"
3230
"strings"
33-
"syscall"
3431

3532
"github.com/Microsoft/go-winio"
33+
"github.com/Microsoft/go-winio/backuptar"
3634
"github.com/Microsoft/hcsshim"
3735
"github.com/containerd/containerd/sys"
3836
"github.com/pkg/errors"
3937
)
4038

41-
const (
42-
// MSWINDOWS pax vendor extensions
43-
hdrMSWindowsPrefix = "MSWINDOWS."
44-
45-
hdrFileAttributes = hdrMSWindowsPrefix + "fileattr"
46-
hdrSecurityDescriptor = hdrMSWindowsPrefix + "sd"
47-
hdrRawSecurityDescriptor = hdrMSWindowsPrefix + "rawsd"
48-
hdrMountPoint = hdrMSWindowsPrefix + "mountpoint"
49-
hdrEaPrefix = hdrMSWindowsPrefix + "xattr."
50-
51-
// LIBARCHIVE pax vendor extensions
52-
hdrLibArchivePrefix = "LIBARCHIVE."
53-
54-
hdrCreateTime = hdrLibArchivePrefix + "creationtime"
55-
)
56-
5739
var (
5840
// mutatedFiles is a list of files that are mutated by the import process
5941
// and must be backed up and restored.
@@ -152,7 +134,7 @@ func setxattr(path, key, value string) error {
152134
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows
153135
// layer using the hcsshim layer writer and backup streams.
154136
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
155-
func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
137+
func applyWindowsLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
156138
home, id := filepath.Split(root)
157139
info := hcsshim.DriverInfo{
158140
HomeDir: home,
@@ -172,6 +154,7 @@ func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options
172154
}
173155
}()
174156

157+
tr := tar.NewReader(r)
175158
buf := bufio.NewWriter(nil)
176159
hdr, nextErr := tr.Next()
177160
// Iterate through the files in the archive.
@@ -208,7 +191,7 @@ func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options
208191
}
209192
hdr, nextErr = tr.Next()
210193
} else {
211-
name, fileSize, fileInfo, err := fileInfoFromHeader(hdr)
194+
name, fileSize, fileInfo, err := backuptar.FileInfoFromHeader(hdr)
212195
if err != nil {
213196
return 0, err
214197
}
@@ -223,42 +206,6 @@ func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options
223206
return
224207
}
225208

226-
// fileInfoFromHeader retrieves basic Win32 file information from a tar header, using the additional metadata written by
227-
// WriteTarFileFromBackupStream.
228-
func fileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *winio.FileBasicInfo, err error) {
229-
name = hdr.Name
230-
if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA {
231-
size = hdr.Size
232-
}
233-
fileInfo = &winio.FileBasicInfo{
234-
LastAccessTime: syscall.NsecToFiletime(hdr.AccessTime.UnixNano()),
235-
LastWriteTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()),
236-
ChangeTime: syscall.NsecToFiletime(hdr.ChangeTime.UnixNano()),
237-
238-
// Default CreationTime to ModTime, updated below if MSWINDOWS.createtime exists
239-
CreationTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()),
240-
}
241-
if attrStr, ok := hdr.PAXRecords[hdrFileAttributes]; ok {
242-
attr, err := strconv.ParseUint(attrStr, 10, 32)
243-
if err != nil {
244-
return "", 0, nil, err
245-
}
246-
fileInfo.FileAttributes = uint32(attr)
247-
} else {
248-
if hdr.Typeflag == tar.TypeDir {
249-
fileInfo.FileAttributes |= syscall.FILE_ATTRIBUTE_DIRECTORY
250-
}
251-
}
252-
if createStr, ok := hdr.PAXRecords[hdrCreateTime]; ok {
253-
createTime, err := parsePAXTime(createStr)
254-
if err != nil {
255-
return "", 0, nil, err
256-
}
257-
fileInfo.CreationTime = syscall.NsecToFiletime(createTime.UnixNano())
258-
}
259-
return
260-
}
261-
262209
// tarToBackupStreamWithMutatedFiles reads data from a tar stream and
263210
// writes it to a backup stream, and also saves any files that will be mutated
264211
// by the import layer process to a backup location.
@@ -299,137 +246,7 @@ func tarToBackupStreamWithMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Re
299246
}
300247
}()
301248

302-
return writeBackupStreamFromTarFile(buf, t, hdr)
303-
}
304-
305-
// writeBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple
306-
// tar file entries in order to collect all the alternate data streams for the file, it returns the next
307-
// tar file that was not processed, or io.EOF is there are no more.
308-
func writeBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (*tar.Header, error) {
309-
bw := winio.NewBackupStreamWriter(w)
310-
var sd []byte
311-
var err error
312-
// Maintaining old SDDL-based behavior for backward compatibility. All new tar headers written
313-
// by this library will have raw binary for the security descriptor.
314-
if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok {
315-
sd, err = winio.SddlToSecurityDescriptor(sddl)
316-
if err != nil {
317-
return nil, err
318-
}
319-
}
320-
if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok {
321-
sd, err = base64.StdEncoding.DecodeString(sdraw)
322-
if err != nil {
323-
return nil, err
324-
}
325-
}
326-
if len(sd) != 0 {
327-
bhdr := winio.BackupHeader{
328-
Id: winio.BackupSecurity,
329-
Size: int64(len(sd)),
330-
}
331-
err := bw.WriteHeader(&bhdr)
332-
if err != nil {
333-
return nil, err
334-
}
335-
_, err = bw.Write(sd)
336-
if err != nil {
337-
return nil, err
338-
}
339-
}
340-
var eas []winio.ExtendedAttribute
341-
for k, v := range hdr.PAXRecords {
342-
if !strings.HasPrefix(k, hdrEaPrefix) {
343-
continue
344-
}
345-
data, err := base64.StdEncoding.DecodeString(v)
346-
if err != nil {
347-
return nil, err
348-
}
349-
eas = append(eas, winio.ExtendedAttribute{
350-
Name: k[len(hdrEaPrefix):],
351-
Value: data,
352-
})
353-
}
354-
if len(eas) != 0 {
355-
eadata, err := winio.EncodeExtendedAttributes(eas)
356-
if err != nil {
357-
return nil, err
358-
}
359-
bhdr := winio.BackupHeader{
360-
Id: winio.BackupEaData,
361-
Size: int64(len(eadata)),
362-
}
363-
err = bw.WriteHeader(&bhdr)
364-
if err != nil {
365-
return nil, err
366-
}
367-
_, err = bw.Write(eadata)
368-
if err != nil {
369-
return nil, err
370-
}
371-
}
372-
if hdr.Typeflag == tar.TypeSymlink {
373-
_, isMountPoint := hdr.PAXRecords[hdrMountPoint]
374-
rp := winio.ReparsePoint{
375-
Target: filepath.FromSlash(hdr.Linkname),
376-
IsMountPoint: isMountPoint,
377-
}
378-
reparse := winio.EncodeReparsePoint(&rp)
379-
bhdr := winio.BackupHeader{
380-
Id: winio.BackupReparseData,
381-
Size: int64(len(reparse)),
382-
}
383-
err := bw.WriteHeader(&bhdr)
384-
if err != nil {
385-
return nil, err
386-
}
387-
_, err = bw.Write(reparse)
388-
if err != nil {
389-
return nil, err
390-
}
391-
}
392-
393-
buf := bufPool.Get().(*[]byte)
394-
defer bufPool.Put(buf)
395-
396-
if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA {
397-
bhdr := winio.BackupHeader{
398-
Id: winio.BackupData,
399-
Size: hdr.Size,
400-
}
401-
err := bw.WriteHeader(&bhdr)
402-
if err != nil {
403-
return nil, err
404-
}
405-
_, err = io.CopyBuffer(bw, t, *buf)
406-
if err != nil {
407-
return nil, err
408-
}
409-
}
410-
// Copy all the alternate data streams and return the next non-ADS header.
411-
for {
412-
ahdr, err := t.Next()
413-
if err != nil {
414-
return nil, err
415-
}
416-
if ahdr.Typeflag != tar.TypeReg || !strings.HasPrefix(ahdr.Name, hdr.Name+":") {
417-
return ahdr, nil
418-
}
419-
bhdr := winio.BackupHeader{
420-
Id: winio.BackupAlternateData,
421-
Size: ahdr.Size,
422-
Name: ahdr.Name[len(hdr.Name):] + ":$DATA",
423-
}
424-
err = bw.WriteHeader(&bhdr)
425-
if err != nil {
426-
return nil, err
427-
}
428-
_, err = io.CopyBuffer(bw, t, *buf)
429-
if err != nil {
430-
return nil, err
431-
}
432-
}
249+
return backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
433250
}
434251

435252
func copyDirInfo(fi os.FileInfo, path string) error {

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt
2828
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
2929
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3030
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
31+
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
32+
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
33+
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
34+
github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
3135
github.com/Microsoft/go-winio v0.4.15 h1:qkLXKzb1QoVatRyd/YlXZ/Kg0m5K3SPuoD82jjSOaBc=
3236
github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
3337
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=

vendor/github.com/Microsoft/go-winio/backuptar/noop.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

archive/strconv.go renamed to vendor/github.com/Microsoft/go-winio/backuptar/strconv.go

Lines changed: 25 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
X Tutup