...
1
2
3 package ociwclayer
4
5 import (
6 "archive/tar"
7 "context"
8 "io"
9 "path/filepath"
10
11 "github.com/Microsoft/go-winio/backuptar"
12 "github.com/Microsoft/hcsshim/internal/wclayer"
13 )
14
15
16
17
18
19
20
21 func ExportLayerToTar(ctx context.Context, w io.Writer, path string, parentLayerPaths []string) error {
22 err := wclayer.ActivateLayer(ctx, path)
23 if err != nil {
24 return err
25 }
26 defer func() {
27 _ = wclayer.DeactivateLayer(ctx, path)
28 }()
29
30
31 err = wclayer.PrepareLayer(ctx, path, parentLayerPaths)
32 if err != nil {
33 return err
34 }
35 err = wclayer.UnprepareLayer(ctx, path)
36 if err != nil {
37 return err
38 }
39
40 r, err := wclayer.NewLayerReader(ctx, path, parentLayerPaths)
41 if err != nil {
42 return err
43 }
44
45 err = writeTarFromLayer(ctx, r, w)
46 cerr := r.Close()
47 if err != nil {
48 return err
49 }
50 return cerr
51 }
52
53 func writeTarFromLayer(ctx context.Context, r wclayer.LayerReader, w io.Writer) error {
54 linkRecords := make(map[[16]byte]string)
55
56 t := tar.NewWriter(w)
57 for {
58 select {
59 case <-ctx.Done():
60 return ctx.Err()
61 default:
62 }
63
64 name, size, fileInfo, err := r.Next()
65 if err == io.EOF {
66 break
67 }
68 if err != nil {
69 return err
70 }
71 if fileInfo == nil {
72
73 hdr := &tar.Header{
74 Name: filepath.ToSlash(filepath.Join(filepath.Dir(name), whiteoutPrefix+filepath.Base(name))),
75 }
76 err := t.WriteHeader(hdr)
77 if err != nil {
78 return err
79 }
80 } else {
81 numberOfLinks, fileIDInfo, err := r.LinkInfo()
82 if err != nil {
83 return err
84 }
85 if numberOfLinks > 1 {
86 if linkName, ok := linkRecords[fileIDInfo.FileID]; ok {
87
88 hdr := backuptar.BasicInfoHeader(name, 0, fileInfo)
89 hdr.Mode = 0644
90 hdr.Typeflag = tar.TypeLink
91 hdr.Linkname = linkName
92 if err := t.WriteHeader(hdr); err != nil {
93 return err
94 }
95 continue
96 }
97
98
99 linkRecords[fileIDInfo.FileID] = filepath.ToSlash(name)
100 }
101
102 err = backuptar.WriteTarFileFromBackupStream(t, r, name, size, fileInfo)
103 if err != nil {
104 return err
105 }
106 }
107 }
108 return t.Close()
109 }
110
View as plain text