| ... | ... | @@ -369,3 +369,60 @@ const Md5Writer = struct { |
| 369 | 369 | return std.fmt.bytesToHex(s, .lower); |
| 370 | 370 | } |
| 371 | 371 | }; |
| 372 | |
| 373 | test "tar should not overwrite existing file" { |
| 374 | // Starting from this folder structure: |
| 375 | // $ tree root |
| 376 | // root |
| 377 | // ├── a |
| 378 | // │   └── b |
| 379 | // │   └── c |
| 380 | // │   └── file.txt |
| 381 | // └── d |
| 382 | // └── b |
| 383 | // └── c |
| 384 | // └── file.txt |
| 385 | // |
| 386 | // Packed with command: |
| 387 | // $ cd root; tar cf overwrite_file.tar * |
| 388 | // Resulting tar has following structure: |
| 389 | // $ tar tvf overwrite_file.tar |
| 390 | // size path |
| 391 | // 0 a/ |
| 392 | // 0 a/b/ |
| 393 | // 0 a/b/c/ |
| 394 | // 2 a/b/c/file.txt |
| 395 | // 0 d/ |
| 396 | // 0 d/b/ |
| 397 | // 0 d/b/c/ |
| 398 | // 2 d/b/c/file.txt |
| 399 | // |
| 400 | // Note that there is no root folder in archive. |
| 401 | // |
| 402 | // With strip_components = 1 resulting unpacked folder was: |
| 403 | // root |
| 404 | // └── b |
| 405 | // └── c |
| 406 | // └── file.txt |
| 407 | // |
| 408 | // a/b/c/file.txt is overwritten with d/b/c/file.txt !!! |
| 409 | // This ensures that file is not overwritten. |
| 410 | // |
| 411 | const data = @embedFile("testdata/overwrite_file.tar"); |
| 412 | var fsb = std.io.fixedBufferStream(data); |
| 413 | |
| 414 | // Unpack with strip_components = 1 should fail |
| 415 | var root = std.testing.tmpDir(.{}); |
| 416 | defer root.cleanup(); |
| 417 | try testing.expectError( |
| 418 | error.PathAlreadyExists, |
| 419 | tar.pipeToFileSystem(root.dir, fsb.reader(), .{ .mode_mode = .ignore, .strip_components = 1 }), |
| 420 | ); |
| 421 | |
| 422 | // Unpack with strip_components = 0 should pass |
| 423 | fsb.reset(); |
| 424 | var root2 = std.testing.tmpDir(.{}); |
| 425 | defer root2.cleanup(); |
| 426 | try tar.pipeToFileSystem(root2.dir, fsb.reader(), .{ .mode_mode = .ignore, .strip_components = 0 }); |
| 427 | } |
| 428 | |