@@ -196,6 +196,49 @@ func TestBreakouts(t *testing.T) {
196196 return nil
197197 }
198198 errFileDiff := errors .New ("files differ" )
199+
200+ isSymlinkFile := func (f string ) func (string ) error {
201+ return func (root string ) error {
202+ fi , err := os .Lstat (filepath .Join (root , f ))
203+ if err != nil {
204+ return err
205+ }
206+
207+ if got := fi .Mode () & os .ModeSymlink ; got != os .ModeSymlink {
208+ return errors .Errorf ("%s should be symlink" , fi .Name ())
209+ }
210+ return nil
211+ }
212+ }
213+
214+ sameSymlinkFile := func (f1 , f2 string ) func (string ) error {
215+ checkF1 , checkF2 := isSymlinkFile (f1 ), isSymlinkFile (f2 )
216+ return func (root string ) error {
217+ if err := checkF1 (root ); err != nil {
218+ return err
219+ }
220+
221+ if err := checkF2 (root ); err != nil {
222+ return err
223+ }
224+
225+ t1 , err := os .Readlink (filepath .Join (root , f1 ))
226+ if err != nil {
227+ return err
228+ }
229+
230+ t2 , err := os .Readlink (filepath .Join (root , f2 ))
231+ if err != nil {
232+ return err
233+ }
234+
235+ if t1 != t2 {
236+ return errors .Wrapf (errFileDiff , "%#v and %#v" , t1 , t2 )
237+ }
238+ return nil
239+ }
240+ }
241+
199242 sameFile := func (f1 , f2 string ) func (string ) error {
200243 return func (root string ) error {
201244 p1 , err := fs .RootPath (root , f1 )
@@ -406,6 +449,16 @@ func TestBreakouts(t *testing.T) {
406449 ),
407450 validator : sameFile ("localpasswd" , "/etc/passwd" ),
408451 },
452+ {
453+ name : "HardlinkSymlinkBeforeCreateTarget" ,
454+ w : TarAll (
455+ tc .Dir ("etc" , 0770 ),
456+ tc .Symlink ("/etc/passwd" , "localpasswd" ),
457+ tc .Link ("localpasswd" , "localpasswd-dup" ),
458+ tc .File ("/etc/passwd" , []byte ("after" ), 0644 ),
459+ ),
460+ validator : sameFile ("localpasswd-dup" , "/etc/passwd" ),
461+ },
409462 {
410463 name : "HardlinkSymlinkRelative" ,
411464 w : TarAll (
@@ -414,7 +467,10 @@ func TestBreakouts(t *testing.T) {
414467 tc .Symlink ("../../../../../etc/passwd" , "passwdlink" ),
415468 tc .Link ("/passwdlink" , "localpasswd" ),
416469 ),
417- validator : sameFile ("/localpasswd" , "/etc/passwd" ),
470+ validator : all (
471+ sameSymlinkFile ("/localpasswd" , "/passwdlink" ),
472+ sameFile ("/localpasswd" , "/etc/passwd" ),
473+ ),
418474 },
419475 {
420476 name : "HardlinkSymlinkAbsolute" ,
@@ -424,7 +480,10 @@ func TestBreakouts(t *testing.T) {
424480 tc .Symlink ("/etc/passwd" , "passwdlink" ),
425481 tc .Link ("/passwdlink" , "localpasswd" ),
426482 ),
427- validator : sameFile ("/localpasswd" , "/etc/passwd" ),
483+ validator : all (
484+ sameSymlinkFile ("/localpasswd" , "/passwdlink" ),
485+ sameFile ("/localpasswd" , "/etc/passwd" ),
486+ ),
428487 },
429488 {
430489 name : "SymlinkParentDirectory" ,
0 commit comments