@@ -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-
5739var (
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
435252func copyDirInfo (fi os.FileInfo , path string ) error {
0 commit comments