Windows: Updates Windows Vendoring

Updates windows dependent libraries for vendoing.
This commit is contained in:
Nathan Gieseker
2019-01-23 18:43:18 -08:00
parent a686cc4bd8
commit 9a429d8d25
839 changed files with 282895 additions and 774 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,355 @@
package compactext4
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
"strings"
"testing"
"time"
"github.com/Microsoft/hcsshim/ext4/internal/format"
)
type testFile struct {
Path string
File *File
Data []byte
DataSize int64
Link string
ExpectError bool
}
var (
data []byte
name string
)
func init() {
data = make([]byte, blockSize*2)
for i := range data {
data[i] = uint8(i)
}
nameb := make([]byte, 300)
for i := range nameb {
nameb[i] = byte('0' + i%10)
}
name = string(nameb)
}
type largeData struct {
pos int64
}
func (d *largeData) Read(b []byte) (int, error) {
p := d.pos
var pb [8]byte
for i := range b {
binary.LittleEndian.PutUint64(pb[:], uint64(p+int64(i)))
b[i] = pb[i%8]
}
p += int64(len(b))
return len(b), nil
}
func (tf *testFile) Reader() io.Reader {
if tf.DataSize != 0 {
return io.LimitReader(&largeData{}, tf.DataSize)
}
return bytes.NewReader(tf.Data)
}
func createTestFile(t *testing.T, w *Writer, tf testFile) {
var err error
if tf.File != nil {
tf.File.Size = int64(len(tf.Data))
if tf.File.Size == 0 {
tf.File.Size = tf.DataSize
}
err = w.Create(tf.Path, tf.File)
} else {
err = w.Link(tf.Link, tf.Path)
}
if tf.ExpectError && err == nil {
t.Errorf("%s: expected error", tf.Path)
} else if !tf.ExpectError && err != nil {
t.Error(err)
} else {
_, err := io.Copy(w, tf.Reader())
if err != nil {
t.Error(err)
}
}
}
func expectedMode(f *File) uint16 {
switch f.Mode & format.TypeMask {
case 0:
return f.Mode | S_IFREG
case S_IFLNK:
return f.Mode | 0777
default:
return f.Mode
}
}
func expectedSize(f *File) int64 {
switch f.Mode & format.TypeMask {
case 0, S_IFREG:
return f.Size
case S_IFLNK:
return int64(len(f.Linkname))
default:
return 0
}
}
func xattrsEqual(x1, x2 map[string][]byte) bool {
if len(x1) != len(x2) {
return false
}
for name, value := range x1 {
if !bytes.Equal(x2[name], value) {
return false
}
}
return true
}
func fileEqual(f1, f2 *File) bool {
return f1.Linkname == f2.Linkname &&
expectedSize(f1) == expectedSize(f2) &&
expectedMode(f1) == expectedMode(f2) &&
f1.Uid == f2.Uid &&
f1.Gid == f2.Gid &&
f1.Atime.Equal(f2.Atime) &&
f1.Ctime.Equal(f2.Ctime) &&
f1.Mtime.Equal(f2.Mtime) &&
f1.Crtime.Equal(f2.Crtime) &&
f1.Devmajor == f2.Devmajor &&
f1.Devminor == f2.Devminor &&
xattrsEqual(f1.Xattrs, f2.Xattrs)
}
func runTestsOnFiles(t *testing.T, testFiles []testFile, opts ...Option) {
image := "testfs.img"
imagef, err := os.Create(image)
if err != nil {
t.Fatal(err)
}
defer os.Remove(image)
defer imagef.Close()
w := NewWriter(imagef, opts...)
for _, tf := range testFiles {
createTestFile(t, w, tf)
if !tf.ExpectError && tf.File != nil {
f, err := w.Stat(tf.Path)
if err != nil {
if !strings.Contains(err.Error(), "cannot retrieve") {
t.Error(err)
}
} else if !fileEqual(f, tf.File) {
t.Errorf("%s: stat mismatch: %#v %#v", tf.Path, tf.File, f)
}
}
}
if t.Failed() {
return
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
fsck(t, image)
mountPath := "testmnt"
if mountImage(t, image, mountPath) {
defer unmountImage(t, mountPath)
validated := make(map[string]*testFile)
for i := range testFiles {
tf := testFiles[len(testFiles)-i-1]
if validated[tf.Link] != nil {
// The link target was subsequently replaced. Find the
// earlier instance.
for j := range testFiles[:len(testFiles)-i-1] {
otf := testFiles[j]
if otf.Path == tf.Link && !otf.ExpectError {
tf = otf
break
}
}
}
if !tf.ExpectError && validated[tf.Path] == nil {
verifyTestFile(t, mountPath, tf)
validated[tf.Path] = &tf
}
}
}
}
func TestBasic(t *testing.T) {
now := time.Now()
testFiles := []testFile{
{Path: "empty", File: &File{Mode: 0644}},
{Path: "small", File: &File{Mode: 0644}, Data: data[:40]},
{Path: "time", File: &File{Atime: now, Ctime: now.Add(time.Second), Mtime: now.Add(time.Hour)}},
{Path: "block_1", File: &File{Mode: 0644}, Data: data[:blockSize]},
{Path: "block_2", File: &File{Mode: 0644}, Data: data[:blockSize*2]},
{Path: "symlink", File: &File{Linkname: "block_1", Mode: format.S_IFLNK}},
{Path: "symlink_59", File: &File{Linkname: name[:59], Mode: format.S_IFLNK}},
{Path: "symlink_60", File: &File{Linkname: name[:60], Mode: format.S_IFLNK}},
{Path: "symlink_120", File: &File{Linkname: name[:120], Mode: format.S_IFLNK}},
{Path: "symlink_300", File: &File{Linkname: name[:300], Mode: format.S_IFLNK}},
{Path: "dir", File: &File{Mode: format.S_IFDIR | 0755}},
{Path: "dir/fifo", File: &File{Mode: format.S_IFIFO}},
{Path: "dir/sock", File: &File{Mode: format.S_IFSOCK}},
{Path: "dir/blk", File: &File{Mode: format.S_IFBLK, Devmajor: 0x5678, Devminor: 0x1234}},
{Path: "dir/chr", File: &File{Mode: format.S_IFCHR, Devmajor: 0x5678, Devminor: 0x1234}},
{Path: "dir/hard_link", Link: "small"},
}
runTestsOnFiles(t, testFiles)
}
func TestLargeDirectory(t *testing.T) {
testFiles := []testFile{
{Path: "bigdir", File: &File{Mode: format.S_IFDIR | 0755}},
}
for i := 0; i < 50000; i++ {
testFiles = append(testFiles, testFile{
Path: fmt.Sprintf("bigdir/%d", i), File: &File{Mode: 0644},
})
}
runTestsOnFiles(t, testFiles)
}
func TestInlineData(t *testing.T) {
testFiles := []testFile{
{Path: "inline_30", File: &File{Mode: 0644}, Data: data[:30]},
{Path: "inline_60", File: &File{Mode: 0644}, Data: data[:60]},
{Path: "inline_120", File: &File{Mode: 0644}, Data: data[:120]},
{Path: "inline_full", File: &File{Mode: 0644}, Data: data[:inlineDataSize]},
{Path: "block_min", File: &File{Mode: 0644}, Data: data[:inlineDataSize+1]},
}
runTestsOnFiles(t, testFiles, InlineData)
}
func TestXattrs(t *testing.T) {
testFiles := []testFile{
{Path: "withsmallxattrs",
File: &File{
Mode: format.S_IFREG | 0644,
Xattrs: map[string][]byte{
"user.foo": []byte("test"),
"user.bar": []byte("test2"),
},
},
},
{Path: "withlargexattrs",
File: &File{
Mode: format.S_IFREG | 0644,
Xattrs: map[string][]byte{
"user.foo": data[:100],
"user.bar": data[:50],
},
},
},
}
runTestsOnFiles(t, testFiles)
}
func TestReplace(t *testing.T) {
testFiles := []testFile{
{Path: "lost+found", ExpectError: true, File: &File{}}, // can't change type
{Path: "lost+found", File: &File{Mode: format.S_IFDIR | 0777}},
{Path: "dir", File: &File{Mode: format.S_IFDIR | 0777}},
{Path: "dir/file", File: &File{}},
{Path: "dir", File: &File{Mode: format.S_IFDIR | 0700}},
{Path: "file", File: &File{}},
{Path: "file", File: &File{Mode: 0600}},
{Path: "file2", File: &File{}},
{Path: "link", Link: "file2"},
{Path: "file2", File: &File{Mode: 0600}},
{Path: "nolinks", File: &File{}},
{Path: "nolinks", ExpectError: true, Link: "file"}, // would orphan nolinks
{Path: "onelink", File: &File{}},
{Path: "onelink2", Link: "onelink"},
{Path: "onelink", Link: "file"},
{Path: "", ExpectError: true, File: &File{}},
{Path: "", ExpectError: true, Link: "file"},
{Path: "", File: &File{Mode: format.S_IFDIR | 0777}},
{Path: "smallxattr", File: &File{Xattrs: map[string][]byte{"user.foo": data[:4]}}},
{Path: "smallxattr", File: &File{Xattrs: map[string][]byte{"user.foo": data[:8]}}},
{Path: "smallxattr_delete", File: &File{Xattrs: map[string][]byte{"user.foo": data[:4]}}},
{Path: "smallxattr_delete", File: &File{}},
{Path: "largexattr", File: &File{Xattrs: map[string][]byte{"user.small": data[:8], "user.foo": data[:200]}}},
{Path: "largexattr", File: &File{Xattrs: map[string][]byte{"user.small": data[:12], "user.foo": data[:400]}}},
{Path: "largexattr", File: &File{Xattrs: map[string][]byte{"user.foo": data[:200]}}},
{Path: "largexattr_delete", File: &File{}},
}
runTestsOnFiles(t, testFiles)
}
func TestTime(t *testing.T) {
now := time.Now()
now2 := fsTimeToTime(timeToFsTime(now))
if now.UnixNano() != now2.UnixNano() {
t.Fatalf("%s != %s", now, now2)
}
}
func TestLargeFile(t *testing.T) {
testFiles := []testFile{
{Path: "small", File: &File{}, DataSize: 1024 * 1024}, // can't change type
{Path: "medium", File: &File{}, DataSize: 200 * 1024 * 1024}, // can't change type
{Path: "large", File: &File{}, DataSize: 600 * 1024 * 1024}, // can't change type
}
runTestsOnFiles(t, testFiles)
}
func TestFileLinkLimit(t *testing.T) {
testFiles := []testFile{
{Path: "file", File: &File{}},
}
for i := 0; i < format.MaxLinks; i++ {
testFiles = append(testFiles, testFile{Path: fmt.Sprintf("link%d", i), Link: "file"})
}
testFiles[len(testFiles)-1].ExpectError = true
runTestsOnFiles(t, testFiles)
}
func TestDirLinkLimit(t *testing.T) {
testFiles := []testFile{
{Path: "dir", File: &File{Mode: S_IFDIR}},
}
for i := 0; i < format.MaxLinks-1; i++ {
testFiles = append(testFiles, testFile{Path: fmt.Sprintf("dir/%d", i), File: &File{Mode: S_IFDIR}})
}
testFiles[len(testFiles)-1].ExpectError = true
runTestsOnFiles(t, testFiles)
}
func TestLargeDisk(t *testing.T) {
testFiles := []testFile{
{Path: "file", File: &File{}},
}
runTestsOnFiles(t, testFiles, MaximumDiskSize(maxMaxDiskSize))
}

View File

@ -0,0 +1,248 @@
package compactext4
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path"
"syscall"
"testing"
"time"
"unsafe"
"github.com/Microsoft/hcsshim/ext4/internal/format"
)
func timeEqual(ts syscall.Timespec, t time.Time) bool {
sec, nsec := t.Unix(), t.Nanosecond()
if t.IsZero() {
sec, nsec = 0, 0
}
return ts.Sec == sec && int(ts.Nsec) == nsec
}
func expectedDevice(f *File) uint64 {
return uint64(f.Devminor&0xff | f.Devmajor<<8 | (f.Devminor&0xffffff00)<<12)
}
func llistxattr(path string, b []byte) (int, error) {
pathp := syscall.StringBytePtr(path)
var p unsafe.Pointer
if len(b) > 0 {
p = unsafe.Pointer(&b[0])
}
r, _, e := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(pathp)), uintptr(p), uintptr(len(b)))
if e != 0 {
return 0, &os.PathError{Path: path, Op: "llistxattr", Err: syscall.Errno(e)}
}
return int(r), nil
}
func lgetxattr(path string, name string, b []byte) (int, error) {
pathp := syscall.StringBytePtr(path)
namep := syscall.StringBytePtr(name)
var p unsafe.Pointer
if len(b) > 0 {
p = unsafe.Pointer(&b[0])
}
r, _, e := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathp)), uintptr(unsafe.Pointer(namep)), uintptr(p), uintptr(len(b)), 0, 0)
if e != 0 {
return 0, &os.PathError{Path: path, Op: "lgetxattr", Err: syscall.Errno(e)}
}
return int(r), nil
}
func readXattrs(path string) (map[string][]byte, error) {
xattrs := make(map[string][]byte)
var buf [4096]byte
var buf2 [4096]byte
b := buf[:]
n, err := llistxattr(path, b)
if err != nil {
return nil, err
}
b = b[:n]
for len(b) != 0 {
nn := bytes.IndexByte(b, 0)
name := string(b[:nn])
b = b[nn+1:]
vn, err := lgetxattr(path, name, buf2[:])
if err != nil {
return nil, err
}
value := buf2[:vn]
xattrs[name] = value
}
return xattrs, nil
}
func streamEqual(r1, r2 io.Reader) (bool, error) {
var b [4096]byte
var b2 [4096]byte
for {
n, err := r1.Read(b[:])
if n == 0 {
if err == io.EOF {
break
}
if err == nil {
continue
}
return false, err
}
_, err = io.ReadFull(r2, b2[:n])
if err == io.EOF || err == io.ErrUnexpectedEOF {
return false, nil
}
if err != nil {
return false, err
}
if !bytes.Equal(b[n:], b2[n:]) {
return false, nil
}
}
// Check the tail of r2
_, err := r2.Read(b[:1])
if err == nil {
return false, nil
}
if err != io.EOF {
return false, err
}
return true, nil
}
func verifyTestFile(t *testing.T, mountPath string, tf testFile) {
name := path.Join(mountPath, tf.Path)
fi, err := os.Lstat(name)
if err != nil {
t.Error(err)
return
}
st := fi.Sys().(*syscall.Stat_t)
if tf.File != nil {
if st.Mode != uint32(expectedMode(tf.File)) ||
st.Uid != tf.File.Uid ||
st.Gid != tf.File.Gid ||
(!fi.IsDir() && st.Size != expectedSize(tf.File)) ||
st.Rdev != expectedDevice(tf.File) ||
!timeEqual(st.Atim, tf.File.Atime) ||
!timeEqual(st.Mtim, tf.File.Mtime) ||
!timeEqual(st.Ctim, tf.File.Ctime) {
t.Errorf("%s: stat mismatch, expected: %#v got: %#v", tf.Path, tf.File, st)
}
xattrs, err := readXattrs(name)
if err != nil {
t.Error(err)
} else if !xattrsEqual(xattrs, tf.File.Xattrs) {
t.Errorf("%s: xattr mismatch, expected: %#v got: %#v", tf.Path, tf.File.Xattrs, xattrs)
}
switch tf.File.Mode & format.TypeMask {
case S_IFREG:
if f, err := os.Open(name); err != nil {
t.Error(err)
} else {
same, err := streamEqual(f, tf.Reader())
if err != nil {
t.Error(err)
} else if !same {
t.Errorf("%s: data mismatch", tf.Path)
}
f.Close()
}
case S_IFLNK:
if link, err := os.Readlink(name); err != nil {
t.Error(err)
} else if link != tf.File.Linkname {
t.Errorf("%s: link mismatch, expected: %s got: %s", tf.Path, tf.File.Linkname, link)
}
}
} else {
lfi, err := os.Lstat(path.Join(mountPath, tf.Link))
if err != nil {
t.Error(err)
return
}
lst := lfi.Sys().(*syscall.Stat_t)
if lst.Ino != st.Ino {
t.Errorf("%s: hard link mismatch with %s, expected inode: %d got inode: %d", tf.Path, tf.Link, lst.Ino, st.Ino)
}
}
}
type capHeader struct {
version uint32
pid int
}
type capData struct {
effective uint32
permitted uint32
inheritable uint32
}
const CAP_SYS_ADMIN = 21
type caps struct {
hdr capHeader
data [2]capData
}
func getCaps() (caps, error) {
var c caps
// Get capability version
if _, _, errno := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(&c.hdr)), uintptr(unsafe.Pointer(nil)), 0); errno != 0 {
return c, fmt.Errorf("SYS_CAPGET: %v", errno)
}
// Get current capabilities
if _, _, errno := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(&c.hdr)), uintptr(unsafe.Pointer(&c.data[0])), 0); errno != 0 {
return c, fmt.Errorf("SYS_CAPGET: %v", errno)
}
return c, nil
}
func mountImage(t *testing.T, image string, mountPath string) bool {
caps, err := getCaps()
if err != nil || caps.data[0].effective&(1<<uint(CAP_SYS_ADMIN)) == 0 {
t.Log("cannot mount to run verification tests without CAP_SYS_ADMIN")
return false
}
err = os.MkdirAll(mountPath, 0777)
if err != nil {
t.Fatal(err)
}
out, err := exec.Command("mount", "-o", "loop,ro", "-t", "ext4", image, mountPath).CombinedOutput()
t.Logf("%s", out)
if err != nil {
t.Fatal(err)
}
return true
}
func unmountImage(t *testing.T, mountPath string) {
out, err := exec.Command("umount", mountPath).CombinedOutput()
t.Logf("%s", out)
if err != nil {
t.Log(err)
}
}
func fsck(t *testing.T, image string) {
cmd := exec.Command("e2fsck", "-v", "-f", "-n", image)
out, err := cmd.CombinedOutput()
t.Logf("%s", out)
if err != nil {
t.Fatal(err)
}
}

View File

@ -0,0 +1,18 @@
// +build !linux
package compactext4
import "testing"
func verifyTestFile(t *testing.T, mountPath string, tf testFile) {
}
func mountImage(t *testing.T, image string, mountPath string) bool {
return false
}
func unmountImage(t *testing.T, mountPath string) {
}
func fsck(t *testing.T, image string) {
}