@@ -19,9 +19,7 @@ package archive
1919import (
2020 "archive/tar"
2121 "context"
22- "fmt"
2322 "io"
24- "io/ioutil"
2523 "os"
2624 "path/filepath"
2725 "runtime"
@@ -91,11 +89,6 @@ const (
9189 // archives.
9290 whiteoutMetaPrefix = whiteoutPrefix + whiteoutPrefix
9391
94- // whiteoutLinkDir is a directory AUFS uses for storing hardlink links to other
95- // layers. Normally these should not go into exported archives and all changed
96- // hardlinks should be copied to the top layer.
97- whiteoutLinkDir = whiteoutMetaPrefix + "plnk"
98-
9992 // whiteoutOpaqueDir file means directory has been made opaque - meaning
10093 // readdir calls to this directory do not follow to lower layers.
10194 whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq"
@@ -130,10 +123,6 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
130123 // Used for handling opaque directory markers which
131124 // may occur out of order
132125 unpackedPaths = make (map [string ]struct {})
133-
134- // Used for aufs plink directory
135- aufsTempdir = ""
136- aufsHardlinks = make (map [string ]* tar.Header )
137126 )
138127
139128 // Iterate through the files in the archive.
@@ -201,40 +190,15 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
201190 }
202191 }
203192
204- // Skip AUFS metadata dirs
205- if strings .HasPrefix (hdr .Name , whiteoutMetaPrefix ) {
206- // Regular files inside /.wh..wh.plnk can be used as hardlink targets
207- // We don't want this directory, but we need the files in them so that
208- // such hardlinks can be resolved.
209- if strings .HasPrefix (hdr .Name , whiteoutLinkDir ) && hdr .Typeflag == tar .TypeReg {
210- basename := filepath .Base (hdr .Name )
211- aufsHardlinks [basename ] = hdr
212- if aufsTempdir == "" {
213- if aufsTempdir , err = ioutil .TempDir (os .Getenv ("XDG_RUNTIME_DIR" ), "dockerplnk" ); err != nil {
214- return 0 , err
215- }
216- defer os .RemoveAll (aufsTempdir )
217- }
218- p , err := fs .RootPath (aufsTempdir , basename )
219- if err != nil {
220- return 0 , err
221- }
222- if err := createTarFile (ctx , p , root , hdr , tr ); err != nil {
223- return 0 , err
224- }
225- }
226-
227- if hdr .Name != whiteoutOpaqueDir {
228- continue
229- }
230- }
231-
232- if strings .HasPrefix (base , whiteoutPrefix ) {
193+ // Naive whiteout convert function which handles whiteout files by
194+ // removing the target files.
195+ convertWhiteout := func (hdr * tar.Header , path string ) (bool , error ) {
196+ base := filepath .Base (path )
233197 dir := filepath .Dir (path )
234198 if base == whiteoutOpaqueDir {
235199 _ , err := os .Lstat (dir )
236200 if err != nil {
237- return 0 , err
201+ return false , err
238202 }
239203 err = filepath .Walk (dir , func (path string , info os.FileInfo , err error ) error {
240204 if err != nil {
@@ -252,26 +216,29 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
252216 }
253217 return nil
254218 })
255- if err != nil {
256- return 0 , err
257- }
258- continue
219+ return false , err
259220 }
260221
261- originalBase := base [len (whiteoutPrefix ):]
262- originalPath := filepath .Join (dir , originalBase )
222+ if strings .HasPrefix (base , whiteoutPrefix ) {
223+ originalBase := base [len (whiteoutPrefix ):]
224+ originalPath := filepath .Join (dir , originalBase )
263225
264- // Ensure originalPath is under dir
265- if dir [len (dir )- 1 ] != filepath .Separator {
266- dir += string (filepath .Separator )
267- }
268- if ! strings .HasPrefix (originalPath , dir ) {
269- return 0 , errors .Wrapf (errInvalidArchive , "invalid whiteout name: %v" , base )
226+ return false , os .RemoveAll (originalPath )
270227 }
271228
272- if err := os .RemoveAll (originalPath ); err != nil {
273- return 0 , err
274- }
229+ return true , nil
230+ }
231+ if options .ConvertWhiteout != nil {
232+ convertWhiteout = options .ConvertWhiteout
233+ }
234+ if err := validateWhiteout (path ); err != nil {
235+ return 0 , err
236+ }
237+ writeFile , err := convertWhiteout (hdr , path )
238+ if err != nil {
239+ return 0 , errors .Wrapf (err , "failed to convert whiteout file %q" , hdr .Name )
240+ }
241+ if ! writeFile {
275242 continue
276243 }
277244 // If path exits we almost always just want to remove and replace it.
@@ -289,26 +256,6 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
289256 srcData := io .Reader (tr )
290257 srcHdr := hdr
291258
292- // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so
293- // we manually retarget these into the temporary files we extracted them into
294- if hdr .Typeflag == tar .TypeLink && strings .HasPrefix (filepath .Clean (hdr .Linkname ), whiteoutLinkDir ) {
295- linkBasename := filepath .Base (hdr .Linkname )
296- srcHdr = aufsHardlinks [linkBasename ]
297- if srcHdr == nil {
298- return 0 , fmt .Errorf ("invalid aufs hardlink" )
299- }
300- p , err := fs .RootPath (aufsTempdir , linkBasename )
301- if err != nil {
302- return 0 , err
303- }
304- tmpFile , err := os .Open (p )
305- if err != nil {
306- return 0 , err
307- }
308- defer tmpFile .Close ()
309- srcData = tmpFile
310- }
311-
312259 if err := createTarFile (ctx , path , root , srcHdr , srcData ); err != nil {
313260 return 0 , err
314261 }
@@ -684,3 +631,26 @@ func hardlinkRootPath(root, linkname string) (string, error) {
684631 }
685632 return targetPath , nil
686633}
634+
635+ func validateWhiteout (path string ) error {
636+ base := filepath .Base (path )
637+ dir := filepath .Dir (path )
638+
639+ if base == whiteoutOpaqueDir {
640+ return nil
641+ }
642+
643+ if strings .HasPrefix (base , whiteoutPrefix ) {
644+ originalBase := base [len (whiteoutPrefix ):]
645+ originalPath := filepath .Join (dir , originalBase )
646+
647+ // Ensure originalPath is under dir
648+ if dir [len (dir )- 1 ] != filepath .Separator {
649+ dir += string (filepath .Separator )
650+ }
651+ if ! strings .HasPrefix (originalPath , dir ) {
652+ return errors .Wrapf (errInvalidArchive , "invalid whiteout name: %v" , base )
653+ }
654+ }
655+ return nil
656+ }
0 commit comments