github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/pkg/archive/archive_unix_test.go (about)

     1  // +build !windows
     2  
     3  package archive
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"syscall"
    12  	"testing"
    13  
    14  	"github.com/docker/docker/pkg/system"
    15  )
    16  
    17  func TestCanonicalTarNameForPath(t *testing.T) {
    18  	cases := []struct{ in, expected string }{
    19  		{"foo", "foo"},
    20  		{"foo/bar", "foo/bar"},
    21  		{"foo/dir/", "foo/dir/"},
    22  	}
    23  	for _, v := range cases {
    24  		if out, err := CanonicalTarNameForPath(v.in); err != nil {
    25  			t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err)
    26  		} else if out != v.expected {
    27  			t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out)
    28  		}
    29  	}
    30  }
    31  
    32  func TestCanonicalTarName(t *testing.T) {
    33  	cases := []struct {
    34  		in       string
    35  		isDir    bool
    36  		expected string
    37  	}{
    38  		{"foo", false, "foo"},
    39  		{"foo", true, "foo/"},
    40  		{"foo/bar", false, "foo/bar"},
    41  		{"foo/bar", true, "foo/bar/"},
    42  	}
    43  	for _, v := range cases {
    44  		if out, err := canonicalTarName(v.in, v.isDir); err != nil {
    45  			t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err)
    46  		} else if out != v.expected {
    47  			t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out)
    48  		}
    49  	}
    50  }
    51  
    52  func TestChmodTarEntry(t *testing.T) {
    53  	cases := []struct {
    54  		in, expected os.FileMode
    55  	}{
    56  		{0000, 0000},
    57  		{0777, 0777},
    58  		{0644, 0644},
    59  		{0755, 0755},
    60  		{0444, 0444},
    61  	}
    62  	for _, v := range cases {
    63  		if out := chmodTarEntry(v.in); out != v.expected {
    64  			t.Fatalf("wrong chmod. expected:%v got:%v", v.expected, out)
    65  		}
    66  	}
    67  }
    68  
    69  func TestTarWithHardLink(t *testing.T) {
    70  	origin, err := ioutil.TempDir("", "docker-test-tar-hardlink")
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	defer os.RemoveAll(origin)
    75  	if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	if err := os.Link(filepath.Join(origin, "1"), filepath.Join(origin, "2")); err != nil {
    79  		t.Fatal(err)
    80  	}
    81  
    82  	var i1, i2 uint64
    83  	if i1, err = getNlink(filepath.Join(origin, "1")); err != nil {
    84  		t.Fatal(err)
    85  	}
    86  	// sanity check that we can hardlink
    87  	if i1 != 2 {
    88  		t.Skipf("skipping since hardlinks don't work here; expected 2 links, got %d", i1)
    89  	}
    90  
    91  	dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest")
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	defer os.RemoveAll(dest)
    96  
    97  	// we'll do this in two steps to separate failure
    98  	fh, err := Tar(origin, Uncompressed)
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  
   103  	// ensure we can read the whole thing with no error, before writing back out
   104  	buf, err := ioutil.ReadAll(fh)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  
   109  	bRdr := bytes.NewReader(buf)
   110  	err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed})
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	if i1, err = getInode(filepath.Join(dest, "1")); err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	if i2, err = getInode(filepath.Join(dest, "2")); err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	if i1 != i2 {
   123  		t.Errorf("expected matching inodes, but got %d and %d", i1, i2)
   124  	}
   125  }
   126  
   127  func getNlink(path string) (uint64, error) {
   128  	stat, err := os.Stat(path)
   129  	if err != nil {
   130  		return 0, err
   131  	}
   132  	statT, ok := stat.Sys().(*syscall.Stat_t)
   133  	if !ok {
   134  		return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
   135  	}
   136  	// We need this conversion on ARM64
   137  	return uint64(statT.Nlink), nil
   138  }
   139  
   140  func getInode(path string) (uint64, error) {
   141  	stat, err := os.Stat(path)
   142  	if err != nil {
   143  		return 0, err
   144  	}
   145  	statT, ok := stat.Sys().(*syscall.Stat_t)
   146  	if !ok {
   147  		return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
   148  	}
   149  	return statT.Ino, nil
   150  }
   151  
   152  func TestTarWithBlockCharFifo(t *testing.T) {
   153  	origin, err := ioutil.TempDir("", "docker-test-tar-hardlink")
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  	defer os.RemoveAll(origin)
   158  	if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	if err := system.Mknod(filepath.Join(origin, "2"), syscall.S_IFBLK, int(system.Mkdev(int64(12), int64(5)))); err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	if err := system.Mknod(filepath.Join(origin, "3"), syscall.S_IFCHR, int(system.Mkdev(int64(12), int64(5)))); err != nil {
   165  		t.Fatal(err)
   166  	}
   167  	if err := system.Mknod(filepath.Join(origin, "4"), syscall.S_IFIFO, int(system.Mkdev(int64(12), int64(5)))); err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest")
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	defer os.RemoveAll(dest)
   176  
   177  	// we'll do this in two steps to separate failure
   178  	fh, err := Tar(origin, Uncompressed)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	// ensure we can read the whole thing with no error, before writing back out
   184  	buf, err := ioutil.ReadAll(fh)
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  
   189  	bRdr := bytes.NewReader(buf)
   190  	err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed})
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  
   195  	changes, err := ChangesDirs(origin, dest)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	if len(changes) > 0 {
   200  		t.Fatalf("Tar with special device (block, char, fifo) should keep them (recreate them when untar) : %v", changes)
   201  	}
   202  }
   203  
   204  // TestTarUntarWithXattr is Unix as Lsetxattr is not supported on Windows
   205  func TestTarUntarWithXattr(t *testing.T) {
   206  	origin, err := ioutil.TempDir("", "docker-test-untar-origin")
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  	defer os.RemoveAll(origin)
   211  	if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
   212  		t.Fatal(err)
   213  	}
   214  	if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil {
   215  		t.Fatal(err)
   216  	}
   217  	if err := ioutil.WriteFile(filepath.Join(origin, "3"), []byte("will be ignored"), 0700); err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if err := system.Lsetxattr(filepath.Join(origin, "2"), "security.capability", []byte{0x00}, 0); err != nil {
   221  		t.Fatal(err)
   222  	}
   223  
   224  	for _, c := range []Compression{
   225  		Uncompressed,
   226  		Gzip,
   227  	} {
   228  		changes, err := tarUntar(t, origin, &TarOptions{
   229  			Compression:     c,
   230  			ExcludePatterns: []string{"3"},
   231  		})
   232  
   233  		if err != nil {
   234  			t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err)
   235  		}
   236  
   237  		if len(changes) != 1 || changes[0].Path != "/3" {
   238  			t.Fatalf("Unexpected differences after tarUntar: %v", changes)
   239  		}
   240  		capability, _ := system.Lgetxattr(filepath.Join(origin, "2"), "security.capability")
   241  		if capability == nil && capability[0] != 0x00 {
   242  			t.Fatalf("Untar should have kept the 'security.capability' xattr.")
   243  		}
   244  	}
   245  }