77 "errors"
88 "fmt"
99 "io"
10+ "io/fs"
1011 "os"
1112 "os/exec"
1213 "path/filepath"
@@ -1216,7 +1217,7 @@ func TestTempArchiveCloseMultipleTimes(t *testing.T) {
12161217 }
12171218}
12181219
1219- // TestXGlobalNoParent is a regression test to check parent directories are not crated for PAX headers
1220+ // TestXGlobalNoParent is a regression test to check parent directories are not created for PAX headers
12201221func TestXGlobalNoParent (t * testing.T ) {
12211222 buf := & bytes.Buffer {}
12221223 w := tar .NewWriter (buf )
@@ -1236,6 +1237,53 @@ func TestXGlobalNoParent(t *testing.T) {
12361237 assert .Check (t , errors .Is (err , os .ErrNotExist ))
12371238}
12381239
1240+ // TestImpliedDirectoryPermissions ensures that directories implied by paths in the tar file, but without their own
1241+ // header entries are created recursively with the default mode (permissions) stored in ImpliedDirectoryMode. This test
1242+ // also verifies that the permissions of explicit directories are respected.
1243+ func TestImpliedDirectoryPermissions (t * testing.T ) {
1244+ skip .If (t , runtime .GOOS == "windows" , "skipping test that requires Unix permissions" )
1245+
1246+ buf := & bytes.Buffer {}
1247+ headers := []tar.Header {{
1248+ Name : "deeply/nested/and/implied" ,
1249+ }, {
1250+ Name : "explicit/" ,
1251+ Mode : 0644 ,
1252+ }, {
1253+ Name : "explicit/permissions/" ,
1254+ Mode : 0600 ,
1255+ }, {
1256+ Name : "explicit/permissions/specified" ,
1257+ Mode : 0400 ,
1258+ }}
1259+
1260+ w := tar .NewWriter (buf )
1261+ for _ , header := range headers {
1262+ err := w .WriteHeader (& header )
1263+ assert .NilError (t , err )
1264+ }
1265+
1266+ tmpDir := t .TempDir ()
1267+
1268+ err := Untar (buf , tmpDir , nil )
1269+ assert .NilError (t , err )
1270+
1271+ assertMode := func (path string , expected uint32 ) {
1272+ t .Helper ()
1273+ stat , err := os .Lstat (filepath .Join (tmpDir , path ))
1274+ assert .Check (t , err )
1275+ assert .Check (t , is .Equal (stat .Mode ().Perm (), fs .FileMode (expected )))
1276+ }
1277+
1278+ assertMode ("deeply" , ImpliedDirectoryMode )
1279+ assertMode ("deeply/nested" , ImpliedDirectoryMode )
1280+ assertMode ("deeply/nested/and" , ImpliedDirectoryMode )
1281+
1282+ assertMode ("explicit" , 0644 )
1283+ assertMode ("explicit/permissions" , 0600 )
1284+ assertMode ("explicit/permissions/specified" , 0400 )
1285+ }
1286+
12391287func TestReplaceFileTarWrapper (t * testing.T ) {
12401288 filesInArchive := 20
12411289 testcases := []struct {
0 commit comments