| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| | 1 | <<<<<<< HEAD |
| 1 | //! Tar archive is single ordinary file which can contain many files (or | 2 | //! Tar archive is single ordinary file which can contain many files (or |
| 2 | //! directories, symlinks, ...). It's build by series of blocks each size of 512 | 3 | //! directories, symlinks, ...). It's build by series of blocks each size of 512 |
| 3 | //! bytes. First block of each entry is header which defines type, name, size | 4 | //! bytes. First block of each entry is header which defines type, name, size |
| ... | @@ -127,6 +128,8 @@ pub const Header = struct { | ... | @@ -127,6 +128,8 @@ pub const Header = struct { |
| 127 | return buffer[0 .. p.len + 1 + n.len]; | 128 | return buffer[0 .. p.len + 1 + n.len]; |
| 128 | } | 129 | } |
| 129 | | 130 | |
| | 131 | /// When kind is symbolic_link linked-to name (target_path) is specified in |
| | 132 | /// the linkname field. |
| 130 | pub fn linkName(header: Header, buffer: *[LINK_NAME_SIZE]u8) []const u8 { | 133 | pub fn linkName(header: Header, buffer: *[LINK_NAME_SIZE]u8) []const u8 { |
| 131 | const link_name = header.str(157, 100); | 134 | const link_name = header.str(157, 100); |
| 132 | if (link_name.len == 0) { | 135 | if (link_name.len == 0) { |
| ... | @@ -619,6 +622,7 @@ fn createDirAndFile(dir: std.fs.Dir, file_name: []const u8) !std.fs.File { | ... | @@ -619,6 +622,7 @@ fn createDirAndFile(dir: std.fs.Dir, file_name: []const u8) !std.fs.File { |
| 619 | return fs_file; | 622 | return fs_file; |
| 620 | } | 623 | } |
| 621 | | 624 | |
| | 625 | // Creates a symbolic link at path `file_name` which points to `link_name`. |
| 622 | fn createDirAndSymlink(dir: std.fs.Dir, link_name: []const u8, file_name: []const u8) !void { | 626 | fn createDirAndSymlink(dir: std.fs.Dir, link_name: []const u8, file_name: []const u8) !void { |
| 623 | dir.symLink(link_name, file_name, .{}) catch |err| { | 627 | dir.symLink(link_name, file_name, .{}) catch |err| { |
| 624 | if (err == error.FileNotFound) { | 628 | if (err == error.FileNotFound) { |
| ... | @@ -841,3 +845,22 @@ test "tar header parse mode" { | ... | @@ -841,3 +845,22 @@ test "tar header parse mode" { |
| 841 | } | 845 | } |
| 842 | } | 846 | } |
| 843 | } | 847 | } |
| | 848 | |
| | 849 | test "create file and symlink" { |
| | 850 | var root = std.testing.tmpDir(.{}); |
| | 851 | defer root.cleanup(); |
| | 852 | |
| | 853 | _ = try createDirAndFile(root.dir, "file1"); |
| | 854 | _ = try createDirAndFile(root.dir, "a/b/c/file2"); |
| | 855 | |
| | 856 | _ = createDirAndSymlink(root.dir, "a/b/c/file2", "symlink1") catch |err| { |
| | 857 | // On Windows when developer mode is not enabled |
| | 858 | if (err == error.AccessDenied) return error.SkipZigTest; |
| | 859 | return err; |
| | 860 | }; |
| | 861 | _ = try createDirAndSymlink(root.dir, "../../../file1", "d/e/f/symlink2"); |
| | 862 | |
| | 863 | // Danglink symlnik, file created later |
| | 864 | _ = try createDirAndSymlink(root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); |
| | 865 | _ = try createDirAndFile(root.dir, "g/h/i/file4"); |
| | 866 | } |