Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -850,89 +850,6 @@ func TestTarWithBlockCharFifo(t *testing.T) {
|
| 850 | 850 |
} |
| 851 | 851 |
} |
| 852 | 852 |
|
| 853 |
-func TestTarWithHardLink(t *testing.T) {
|
|
| 854 |
- origin, err := ioutil.TempDir("", "docker-test-tar-hardlink")
|
|
| 855 |
- if err != nil {
|
|
| 856 |
- t.Fatal(err) |
|
| 857 |
- } |
|
| 858 |
- defer os.RemoveAll(origin) |
|
| 859 |
- if err := ioutil.WriteFile(path.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
|
|
| 860 |
- t.Fatal(err) |
|
| 861 |
- } |
|
| 862 |
- if err := os.Link(path.Join(origin, "1"), path.Join(origin, "2")); err != nil {
|
|
| 863 |
- t.Fatal(err) |
|
| 864 |
- } |
|
| 865 |
- |
|
| 866 |
- var i1, i2 uint64 |
|
| 867 |
- if i1, err = getNlink(path.Join(origin, "1")); err != nil {
|
|
| 868 |
- t.Fatal(err) |
|
| 869 |
- } |
|
| 870 |
- // sanity check that we can hardlink |
|
| 871 |
- if i1 != 2 {
|
|
| 872 |
- t.Skipf("skipping since hardlinks don't work here; expected 2 links, got %d", i1)
|
|
| 873 |
- } |
|
| 874 |
- |
|
| 875 |
- dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest")
|
|
| 876 |
- if err != nil {
|
|
| 877 |
- t.Fatal(err) |
|
| 878 |
- } |
|
| 879 |
- defer os.RemoveAll(dest) |
|
| 880 |
- |
|
| 881 |
- // we'll do this in two steps to separate failure |
|
| 882 |
- fh, err := Tar(origin, Uncompressed) |
|
| 883 |
- if err != nil {
|
|
| 884 |
- t.Fatal(err) |
|
| 885 |
- } |
|
| 886 |
- |
|
| 887 |
- // ensure we can read the whole thing with no error, before writing back out |
|
| 888 |
- buf, err := ioutil.ReadAll(fh) |
|
| 889 |
- if err != nil {
|
|
| 890 |
- t.Fatal(err) |
|
| 891 |
- } |
|
| 892 |
- |
|
| 893 |
- bRdr := bytes.NewReader(buf) |
|
| 894 |
- err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed})
|
|
| 895 |
- if err != nil {
|
|
| 896 |
- t.Fatal(err) |
|
| 897 |
- } |
|
| 898 |
- |
|
| 899 |
- if i1, err = getInode(path.Join(dest, "1")); err != nil {
|
|
| 900 |
- t.Fatal(err) |
|
| 901 |
- } |
|
| 902 |
- if i2, err = getInode(path.Join(dest, "2")); err != nil {
|
|
| 903 |
- t.Fatal(err) |
|
| 904 |
- } |
|
| 905 |
- |
|
| 906 |
- if i1 != i2 {
|
|
| 907 |
- t.Errorf("expected matching inodes, but got %d and %d", i1, i2)
|
|
| 908 |
- } |
|
| 909 |
-} |
|
| 910 |
- |
|
| 911 |
-func getNlink(path string) (uint64, error) {
|
|
| 912 |
- stat, err := os.Stat(path) |
|
| 913 |
- if err != nil {
|
|
| 914 |
- return 0, err |
|
| 915 |
- } |
|
| 916 |
- statT, ok := stat.Sys().(*syscall.Stat_t) |
|
| 917 |
- if !ok {
|
|
| 918 |
- return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
|
|
| 919 |
- } |
|
| 920 |
- // We need this conversion on ARM64 |
|
| 921 |
- return uint64(statT.Nlink), nil |
|
| 922 |
-} |
|
| 923 |
- |
|
| 924 |
-func getInode(path string) (uint64, error) {
|
|
| 925 |
- stat, err := os.Stat(path) |
|
| 926 |
- if err != nil {
|
|
| 927 |
- return 0, err |
|
| 928 |
- } |
|
| 929 |
- statT, ok := stat.Sys().(*syscall.Stat_t) |
|
| 930 |
- if !ok {
|
|
| 931 |
- return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
|
|
| 932 |
- } |
|
| 933 |
- return statT.Ino, nil |
|
| 934 |
-} |
|
| 935 |
- |
|
| 936 | 853 |
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
|
| 937 | 854 |
fileData := []byte("fooo")
|
| 938 | 855 |
for n := 0; n < numberOfFiles; n++ {
|
| ... | ... |
@@ -3,7 +3,12 @@ |
| 3 | 3 |
package archive |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "bytes" |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io/ioutil" |
|
| 6 | 9 |
"os" |
| 10 |
+ "path" |
|
| 11 |
+ "syscall" |
|
| 7 | 12 |
"testing" |
| 8 | 13 |
) |
| 9 | 14 |
|
| ... | ... |
@@ -58,3 +63,86 @@ func TestChmodTarEntry(t *testing.T) {
|
| 58 | 58 |
} |
| 59 | 59 |
} |
| 60 | 60 |
} |
| 61 |
+ |
|
| 62 |
+func TestTarWithHardLink(t *testing.T) {
|
|
| 63 |
+ origin, err := ioutil.TempDir("", "docker-test-tar-hardlink")
|
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ t.Fatal(err) |
|
| 66 |
+ } |
|
| 67 |
+ defer os.RemoveAll(origin) |
|
| 68 |
+ if err := ioutil.WriteFile(path.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
|
|
| 69 |
+ t.Fatal(err) |
|
| 70 |
+ } |
|
| 71 |
+ if err := os.Link(path.Join(origin, "1"), path.Join(origin, "2")); err != nil {
|
|
| 72 |
+ t.Fatal(err) |
|
| 73 |
+ } |
|
| 74 |
+ |
|
| 75 |
+ var i1, i2 uint64 |
|
| 76 |
+ if i1, err = getNlink(path.Join(origin, "1")); err != nil {
|
|
| 77 |
+ t.Fatal(err) |
|
| 78 |
+ } |
|
| 79 |
+ // sanity check that we can hardlink |
|
| 80 |
+ if i1 != 2 {
|
|
| 81 |
+ t.Skipf("skipping since hardlinks don't work here; expected 2 links, got %d", i1)
|
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
+ dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest")
|
|
| 85 |
+ if err != nil {
|
|
| 86 |
+ t.Fatal(err) |
|
| 87 |
+ } |
|
| 88 |
+ defer os.RemoveAll(dest) |
|
| 89 |
+ |
|
| 90 |
+ // we'll do this in two steps to separate failure |
|
| 91 |
+ fh, err := Tar(origin, Uncompressed) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ t.Fatal(err) |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ // ensure we can read the whole thing with no error, before writing back out |
|
| 97 |
+ buf, err := ioutil.ReadAll(fh) |
|
| 98 |
+ if err != nil {
|
|
| 99 |
+ t.Fatal(err) |
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ bRdr := bytes.NewReader(buf) |
|
| 103 |
+ err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed})
|
|
| 104 |
+ if err != nil {
|
|
| 105 |
+ t.Fatal(err) |
|
| 106 |
+ } |
|
| 107 |
+ |
|
| 108 |
+ if i1, err = getInode(path.Join(dest, "1")); err != nil {
|
|
| 109 |
+ t.Fatal(err) |
|
| 110 |
+ } |
|
| 111 |
+ if i2, err = getInode(path.Join(dest, "2")); err != nil {
|
|
| 112 |
+ t.Fatal(err) |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ if i1 != i2 {
|
|
| 116 |
+ t.Errorf("expected matching inodes, but got %d and %d", i1, i2)
|
|
| 117 |
+ } |
|
| 118 |
+} |
|
| 119 |
+ |
|
| 120 |
+func getNlink(path string) (uint64, error) {
|
|
| 121 |
+ stat, err := os.Stat(path) |
|
| 122 |
+ if err != nil {
|
|
| 123 |
+ return 0, err |
|
| 124 |
+ } |
|
| 125 |
+ statT, ok := stat.Sys().(*syscall.Stat_t) |
|
| 126 |
+ if !ok {
|
|
| 127 |
+ return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
|
|
| 128 |
+ } |
|
| 129 |
+ // We need this conversion on ARM64 |
|
| 130 |
+ return uint64(statT.Nlink), nil |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 133 |
+func getInode(path string) (uint64, error) {
|
|
| 134 |
+ stat, err := os.Stat(path) |
|
| 135 |
+ if err != nil {
|
|
| 136 |
+ return 0, err |
|
| 137 |
+ } |
|
| 138 |
+ statT, ok := stat.Sys().(*syscall.Stat_t) |
|
| 139 |
+ if !ok {
|
|
| 140 |
+ return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
|
|
| 141 |
+ } |
|
| 142 |
+ return statT.Ino, nil |
|
| 143 |
+} |