File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -222,7 +222,16 @@ impl Archive<dyn Read + '_> {
222222 file. unpack_in ( dst) ?;
223223 }
224224 }
225- for mut dir in directories {
225+
226+ // Work from leaves up, with the assumption* that entries for
227+ // parent directories preceed their children. Otherwise when
228+ // a parent directory has no write permission, any empty
229+ // subdirectories beneath it cannot be created.
230+ //
231+ // [*] If sufficiently motivated, one can create an archive
232+ // which violates this. In practice, archives typically are
233+ // structured this way.
234+ for mut dir in directories. into_iter ( ) . rev ( ) {
226235 dir. unpack_in ( dst) ?;
227236 }
228237
Original file line number Diff line number Diff line change @@ -1317,6 +1317,33 @@ fn read_only_directory_containing_files() {
13171317 assert ! ( ar. unpack( td. path( ) ) . is_ok( ) ) ;
13181318}
13191319
1320+ #[ test]
1321+ fn read_only_directory_containing_empty_directory ( ) {
1322+ let td = t ! ( TempBuilder :: new( ) . prefix( "tar-rs" ) . tempdir( ) ) ;
1323+
1324+ let mut b = Builder :: new ( Vec :: < u8 > :: new ( ) ) ;
1325+
1326+ let mut h = Header :: new_gnu ( ) ;
1327+ t ! ( h. set_path( "dir/" ) ) ;
1328+ h. set_size ( 0 ) ;
1329+ h. set_entry_type ( EntryType :: dir ( ) ) ;
1330+ h. set_mode ( 0o444 ) ;
1331+ h. set_cksum ( ) ;
1332+ t ! ( b. append( & h, "" . as_bytes( ) ) ) ;
1333+
1334+ let mut h = Header :: new_gnu ( ) ;
1335+ t ! ( h. set_path( "dir/subdir" ) ) ;
1336+ h. set_size ( 0 ) ;
1337+ h. set_entry_type ( EntryType :: dir ( ) ) ;
1338+ h. set_mode ( 0o755 ) ;
1339+ h. set_cksum ( ) ;
1340+ t ! ( b. append( & h, "" . as_bytes( ) ) ) ;
1341+
1342+ let contents = t ! ( b. into_inner( ) ) ;
1343+ let mut ar = Archive :: new ( & contents[ ..] ) ;
1344+ assert ! ( ar. unpack( td. path( ) ) . is_ok( ) ) ;
1345+ }
1346+
13201347// This test was marked linux only due to macOS CI can't handle `set_current_dir` correctly
13211348#[ test]
13221349#[ cfg( target_os = "linux" ) ]
You can’t perform that action at this time.
0 commit comments