<commit_before>package search_test

import (
	"github.com/hanjos/nexus"
	"github.com/hanjos/nexus/credentials"
	"github.com/hanjos/nexus/search"

	"testing"
)

func TestAllImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.All).(search.Criteria); !ok {
		t.Errorf("search.All does not implement Criteria!")
	}
}

func TestByCoordinatesImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByCoordinates{}).(search.Criteria); !ok {
		t.Errorf("search.ByCoordinates does not implement Criteria!")
	}
}

func TestByClassnameImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByClassname("")).(search.Criteria); !ok {
		t.Errorf("search.ByClassname does not implement Criteria!")
	}
}

func TestByChecksumImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByChecksum("")).(search.Criteria); !ok {
		t.Errorf("search.ByChecksum does not implement Criteria!")
	}
}

func TestByKeywordImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByKeyword("")).(search.Criteria); !ok {
		t.Errorf("search.ByKeyword does not implement Criteria!")
	}
}

func TestByRepositoryImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByRepository("")).(search.Criteria); !ok {
		t.Errorf("search.ByRepository does not implement Criteria!")
	}
}

func TestInRepositoryImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.InRepository{}).(search.Criteria); !ok {
		t.Errorf("search.InRepository does not implement Criteria!")
	}
}

// Examples

func ExampleByKeyword() {
	n := nexus.New("https://maven.java.net", credentials.None)

	// Return all artifacts with javax.enterprise somewhere.
	n.Artifacts(search.ByKeyword("javax.enterprise*"))

	// This search may or may not return an error, depending on the version of
	// the Nexus being accessed. On newer Nexuses (sp?) "*" searches are
	// invalid.
	n.Artifacts(search.ByKeyword("*"))
}

func ExampleByCoordinates() {
	n := nexus.New("https://maven.java.net", credentials.None)

	// Returns all artifacts with a groupId starting with com.sun. Due to Go's
	// struct syntax, we don't need to specify all the coordinates; they
	// default to string's zero value (""), which Nexus ignores.
	n.Artifacts(search.ByCoordinates{GroupId: "com.sun*"})

	// A coordinate search requires specifying at least either a groupId, an
	// artifactId or a version. This search will (after some time), return
	// nothing. This doesn't mean there are no projects with packaging "pom";
	// this is a limitation of Nexus' search.
	n.Artifacts(search.ByCoordinates{Packaging: "pom"})

	// This search may or may not return an error, depending on the version of
	// the Nexus being accessed. On newer Nexuses (sp?) "*" searches are
	// invalid.
	n.Artifacts(search.ByCoordinates{GroupId: "*", Packaging: "pom"})

	// ByCoordinates searches in Maven *projects*, not artifacts. So this
	// search will return all com.sun* artifacts in projects with packaging
	// "pom", not all POM artifacts with groupId com.sun*! Packaging is not
	// the same as extension.
	n.Artifacts(search.ByCoordinates{GroupId: "com*", Packaging: "pom"})
}

func ExampleInRepository() {
	n := nexus.New("https://maven.java.net", credentials.None)

	// Returns all artifacts in the repository releases with groupId starting
	// with com.sun and whose project has packaging "pom".
	n.Artifacts(
		search.InRepository{
			"releases",
			search.ByCoordinates{GroupId: "com.sun*", Packaging: "pom"},
		})

	// Nexus doesn't support * in the repository ID parameter, so this search
	// will return an error.
	n.Artifacts(
		search.InRepository{
			"releases*",
			search.ByCoordinates{GroupId: "com.sun*", Packaging: "pom"},
		})
}
<commit_msg>More tests for search.<commit_after>package search_test

import (
	"github.com/hanjos/nexus"
	"github.com/hanjos/nexus/credentials"
	"github.com/hanjos/nexus/search"

	"testing"
)

func checkMap(t *testing.T, expected map[string]string, actual map[string]string) {
	if len(expected) != len(actual) {
		t.Errorf("Wrong number of fields: expected %v, got %v", len(expected), len(actual))
	}

	for k, v := range actual {
		vExp, ok := expected[k]

		if !ok {
			t.Errorf("Unexpected field %q", k)
		} else if vExp != v {
			t.Errorf("Expected value %q for field %q, got %q", vExp, k, v)
		}
	}
}

func TestAllImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.All).(search.Criteria); !ok {
		t.Errorf("search.All does not implement Criteria!")
	}
}

func TestAllProvidesNoCriteria(t *testing.T) {
	criteria := search.All.Parameters()
	if len(criteria) != 0 {
		t.Errorf("expected an empty map, got %v", criteria)
	}
}

func TestByCoordinatesImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByCoordinates{}).(search.Criteria); !ok {
		t.Errorf("search.ByCoordinates does not implement Criteria!")
	}
}

type pair struct {
	expected string
	actual   string
}

func TestByCoordinatesSetsTheProperFields(t *testing.T) {
	criteria := search.ByCoordinates{GroupId: "g", ArtifactId: "a", Version: "v", Packaging: "p", Classifier: "c"}.Parameters()

	expected := []string{"g", "a", "v", "p", "c"}
	missing := []string{}
	wrong := []pair{}

	for _, exp := range expected {
		v, ok := criteria[exp]

		if !ok {
			missing = append(missing, exp)
		}
		if v != exp {
			wrong = append(wrong, pair{exp, v})
		}
	}

	if len(missing) != 0 {
		t.Errorf("Missing fields %v", missing)
	}

	if len(wrong) != 0 {
		t.Errorf("Fields with wrong values:\n")
		for _, p := range wrong {
			t.Errorf("Field %q expected value %q, got %q", p.expected, p.expected, p.actual)
		}
	}
}

func TestByCoordinatesSetsOnlyTheGivenFields(t *testing.T) {
	criteria := search.ByCoordinates{GroupId: "g", ArtifactId: "a"}.Parameters()

	checkMap(t, map[string]string{"g": "g", "a": "a"}, criteria)
}

func TestByClassnameImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByClassname("")).(search.Criteria); !ok {
		t.Errorf("search.ByClassname does not implement Criteria!")
	}
}

func TestByClassnameSetsTheProperFields(t *testing.T) {
	criteria := search.ByClassname("cn").Parameters()

	checkMap(t, map[string]string{"cn": "cn"}, criteria)
}

func TestByChecksumImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByChecksum("")).(search.Criteria); !ok {
		t.Errorf("search.ByChecksum does not implement Criteria!")
	}
}

func TestByChecksumSetsTheProperFields(t *testing.T) {
	criteria := search.ByChecksum("sha1").Parameters()

	checkMap(t, map[string]string{"sha1": "sha1"}, criteria)
}

func TestByKeywordImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByKeyword("")).(search.Criteria); !ok {
		t.Errorf("search.ByKeyword does not implement Criteria!")
	}
}

func TestByKeywordSetsTheProperFields(t *testing.T) {
	criteria := search.ByKeyword("q").Parameters()

	checkMap(t, map[string]string{"q": "q"}, criteria)
}

func TestByRepositoryImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.ByRepository("")).(search.Criteria); !ok {
		t.Errorf("search.ByRepository does not implement Criteria!")
	}
}

func TestByRepositorySetsTheProperFields(t *testing.T) {
	criteria := search.ByRepository("repositoryId").Parameters()

	checkMap(t, map[string]string{"repositoryId": "repositoryId"}, criteria)
}

func TestInRepositoryImplementsCriteria(t *testing.T) {
	if _, ok := interface{}(search.InRepository{}).(search.Criteria); !ok {
		t.Errorf("search.InRepository does not implement Criteria!")
	}
}

func TestInRepositorySetsTheProperFields(t *testing.T) {
	criteria := search.InRepository{"repositoryId", search.ByChecksum("sha1")}.Parameters()

	checkMap(t, map[string]string{"repositoryId": "repositoryId", "sha1": "sha1"}, criteria)
}

// Examples

func ExampleByKeyword() {
	n := nexus.New("https://maven.java.net", credentials.None)

	// Return all artifacts with javax.enterprise somewhere.
	n.Artifacts(search.ByKeyword("javax.enterprise*"))

	// This search may or may not return an error, depending on the version of
	// the Nexus being accessed. On newer Nexuses (sp?) "*" searches are
	// invalid.
	n.Artifacts(search.ByKeyword("*"))
}

func ExampleByCoordinates() {
	n := nexus.New("https://maven.java.net", credentials.None)

	// Returns all artifacts with a groupId starting with com.sun. Due to Go's
	// struct syntax, we don't need to specify all the coordinates; they
	// default to string's zero value (""), which Nexus ignores.
	n.Artifacts(search.ByCoordinates{GroupId: "com.sun*"})

	// A coordinate search requires specifying at least either a groupId, an
	// artifactId or a version. This search will (after some time), return
	// nothing. This doesn't mean there are no projects with packaging "pom";
	// this is a limitation of Nexus' search.
	n.Artifacts(search.ByCoordinates{Packaging: "pom"})

	// This search may or may not return an error, depending on the version of
	// the Nexus being accessed. On newer Nexuses (sp?) "*" searches are
	// invalid.
	n.Artifacts(search.ByCoordinates{GroupId: "*", Packaging: "pom"})

	// ByCoordinates searches in Maven *projects*, not artifacts. So this
	// search will return all com.sun* artifacts in projects with packaging
	// "pom", not all POM artifacts with groupId com.sun*! Packaging is not
	// the same as extension.
	n.Artifacts(search.ByCoordinates{GroupId: "com*", Packaging: "pom"})
}

func ExampleInRepository() {
	n := nexus.New("https://maven.java.net", credentials.None)

	// Returns all artifacts in the repository releases with groupId starting
	// with com.sun and whose project has packaging "pom".
	n.Artifacts(
		search.InRepository{
			"releases",
			search.ByCoordinates{GroupId: "com.sun*", Packaging: "pom"},
		})

	// Nexus doesn't support * in the repository ID parameter, so this search
	// will return an error.
	n.Artifacts(
		search.InRepository{
			"releases*",
			search.ByCoordinates{GroupId: "com.sun*", Packaging: "pom"},
		})
}
<|endoftext|>


<commit_before>// Package keccak implements the Keccak (SHA-3) hash algorithm.
// http://keccak.noekeon.org / FIPS 202 draft.
package keccak

import (
	"hash"
)

const (
	domainNone  = 1
	domainSHA3  = 0x06
	domainSHAKE = 0x1f
)

const rounds = 24

var roundConstants = []uint64{
	0x0000000000000001, 0x0000000000008082,
	0x800000000000808A, 0x8000000080008000,
	0x000000000000808B, 0x0000000080000001,
	0x8000000080008081, 0x8000000000008009,
	0x000000000000008A, 0x0000000000000088,
	0x0000000080008009, 0x000000008000000A,
	0x000000008000808B, 0x800000000000008B,
	0x8000000000008089, 0x8000000000008003,
	0x8000000000008002, 0x8000000000000080,
	0x000000000000800A, 0x800000008000000A,
	0x8000000080008081, 0x8000000000008080,
	0x0000000080000001, 0x8000000080008008,
}

var rotationConstants = [24]uint{
	1, 3, 6, 10, 15, 21, 28, 36,
	45, 55, 2, 14, 27, 41, 56, 8,
	25, 43, 62, 18, 39, 61, 20, 44,
}

var piLane = [24]uint{
	10, 7, 11, 17, 18, 3, 5, 16,
	8, 21, 24, 4, 15, 23, 19, 13,
	12, 2, 20, 14, 22, 9, 6, 1,
}

type keccak struct {
	S         [25]uint64
	size      int
	blockSize int
	buf       []byte
	domain    byte
}

func newKeccak(capacity, output int, domain byte) hash.Hash {
	var h keccak
	h.size = output / 8
	h.blockSize = (200 - capacity/8)
	h.domain = domain
	return &h
}

func New224() hash.Hash {
	return newKeccak(224*2, 224, domainNone)
}

func New256() hash.Hash {
	return newKeccak(256*2, 256, domainNone)
}

func New384() hash.Hash {
	return newKeccak(384*2, 384, domainNone)
}

func New512() hash.Hash {
	return newKeccak(512*2, 512, domainNone)
}

func (k *keccak) Write(b []byte) (int, error) {
	n := len(b)

	if len(k.buf) > 0 {
		x := k.blockSize - len(k.buf)
		if x > len(b) {
			x = len(b)
		}
		k.buf = append(k.buf, b[:x]...)
		b = b[x:]

		if len(k.buf) < k.blockSize {
			return n, nil
		}

		k.absorb(k.buf)
		k.buf = nil
	}

	for len(b) >= k.blockSize {
		k.absorb(b[:k.blockSize])
		b = b[k.blockSize:]
	}

	k.buf = b

	return n, nil
}

func (k0 *keccak) Sum(b []byte) []byte {
	k := *k0
	k.final()
	return k.squeeze(b)
}

func (k *keccak) Reset() {
	for i := range k.S {
		k.S[i] = 0
	}
	k.buf = nil
}

func (k *keccak) Size() int {
	return k.size
}

func (k *keccak) BlockSize() int {
	return k.blockSize
}

func (k *keccak) absorb(block []byte) {
	if len(block) != k.blockSize {
		panic("absorb() called with invalid block size")
	}

	for i := 0; i < k.blockSize/8; i++ {
		k.S[i] ^= uint64le(block[i*8:])
	}
	keccakf(&k.S)
}

func (k *keccak) pad(block []byte) []byte {

	padded := make([]byte, k.blockSize)

	copy(padded, k.buf)
	padded[len(k.buf)] = k.domain
	padded[len(padded)-1] |= 0x80

	return padded
}

func (k *keccak) final() {
	last := k.pad(k.buf)
	k.absorb(last)
}

func (k *keccak) squeeze(b []byte) []byte {
	buf := make([]byte, 8*len(k.S))
	n := k.size
	for {
		for i := range k.S {
			putUint64le(buf[i*8:], k.S[i])
		}
		if n <= k.blockSize {
			b = append(b, buf[:n]...)
			break
		}
		b = append(b, buf[:k.blockSize]...)
		n -= k.blockSize
		keccakf(&k.S)
	}
	return b
}

func keccakf(S *[25]uint64) {
	var bc [5]uint64
	var tmp uint64

	for r := 0; r < rounds; r++ {
		// theta
		bc[0] = S[0] ^ S[5] ^ S[10] ^ S[15] ^ S[20]
		bc[1] = S[1] ^ S[6] ^ S[11] ^ S[16] ^ S[21]
		bc[2] = S[2] ^ S[7] ^ S[12] ^ S[17] ^ S[22]
		bc[3] = S[3] ^ S[8] ^ S[13] ^ S[18] ^ S[23]
		bc[4] = S[4] ^ S[9] ^ S[14] ^ S[19] ^ S[24]
		tmp = bc[4] ^ rotl64(bc[1], 1)
		S[0] ^= tmp
		S[5] ^= tmp
		S[10] ^= tmp
		S[15] ^= tmp
		S[20] ^= tmp
		tmp = bc[0] ^ rotl64(bc[2], 1)
		S[1] ^= tmp
		S[6] ^= tmp
		S[11] ^= tmp
		S[16] ^= tmp
		S[21] ^= tmp
		tmp = bc[1] ^ rotl64(bc[3], 1)
		S[2] ^= tmp
		S[7] ^= tmp
		S[12] ^= tmp
		S[17] ^= tmp
		S[22] ^= tmp
		tmp = bc[2] ^ rotl64(bc[4], 1)
		S[3] ^= tmp
		S[8] ^= tmp
		S[13] ^= tmp
		S[18] ^= tmp
		S[23] ^= tmp
		tmp = bc[3] ^ rotl64(bc[0], 1)
		S[4] ^= tmp
		S[9] ^= tmp
		S[14] ^= tmp
		S[19] ^= tmp
		S[24] ^= tmp

		// rho phi
		tmp = S[1]
		tmp, S[10] = S[10], rotl64(tmp, 1)
		tmp, S[7] = S[7], rotl64(tmp, 3)
		tmp, S[11] = S[11], rotl64(tmp, 6)
		tmp, S[17] = S[17], rotl64(tmp, 10)
		tmp, S[18] = S[18], rotl64(tmp, 15)
		tmp, S[3] = S[3], rotl64(tmp, 21)
		tmp, S[5] = S[5], rotl64(tmp, 28)
		tmp, S[16] = S[16], rotl64(tmp, 36)
		tmp, S[8] = S[8], rotl64(tmp, 45)
		tmp, S[21] = S[21], rotl64(tmp, 55)
		tmp, S[24] = S[24], rotl64(tmp, 2)
		tmp, S[4] = S[4], rotl64(tmp, 14)
		tmp, S[15] = S[15], rotl64(tmp, 27)
		tmp, S[23] = S[23], rotl64(tmp, 41)
		tmp, S[19] = S[19], rotl64(tmp, 56)
		tmp, S[13] = S[13], rotl64(tmp, 8)
		tmp, S[12] = S[12], rotl64(tmp, 25)
		tmp, S[2] = S[2], rotl64(tmp, 43)
		tmp, S[20] = S[20], rotl64(tmp, 62)
		tmp, S[14] = S[14], rotl64(tmp, 18)
		tmp, S[22] = S[22], rotl64(tmp, 39)
		tmp, S[9] = S[9], rotl64(tmp, 61)
		tmp, S[6] = S[6], rotl64(tmp, 20)
		S[1] = rotl64(tmp, 44)

		// chi
		bc[0] = S[0]
		bc[1] = S[1]
		bc[2] = S[2]
		bc[3] = S[3]
		bc[4] = S[4]
		S[0] ^= (^bc[1]) & bc[2]
		S[1] ^= (^bc[2]) & bc[3]
		S[2] ^= (^bc[3]) & bc[4]
		S[3] ^= (^bc[4]) & bc[0]
		S[4] ^= (^bc[0]) & bc[1]
		bc[0] = S[5]
		bc[1] = S[6]
		bc[2] = S[7]
		bc[3] = S[8]
		bc[4] = S[9]
		S[5] ^= (^bc[1]) & bc[2]
		S[6] ^= (^bc[2]) & bc[3]
		S[7] ^= (^bc[3]) & bc[4]
		S[8] ^= (^bc[4]) & bc[0]
		S[9] ^= (^bc[0]) & bc[1]
		bc[0] = S[10]
		bc[1] = S[11]
		bc[2] = S[12]
		bc[3] = S[13]
		bc[4] = S[14]
		S[10] ^= (^bc[1]) & bc[2]
		S[11] ^= (^bc[2]) & bc[3]
		S[12] ^= (^bc[3]) & bc[4]
		S[13] ^= (^bc[4]) & bc[0]
		S[14] ^= (^bc[0]) & bc[1]
		bc[0] = S[15]
		bc[1] = S[16]
		bc[2] = S[17]
		bc[3] = S[18]
		bc[4] = S[19]
		S[15] ^= (^bc[1]) & bc[2]
		S[16] ^= (^bc[2]) & bc[3]
		S[17] ^= (^bc[3]) & bc[4]
		S[18] ^= (^bc[4]) & bc[0]
		S[19] ^= (^bc[0]) & bc[1]
		bc[0] = S[20]
		bc[1] = S[21]
		bc[2] = S[22]
		bc[3] = S[23]
		bc[4] = S[24]
		S[20] ^= (^bc[1]) & bc[2]
		S[21] ^= (^bc[2]) & bc[3]
		S[22] ^= (^bc[3]) & bc[4]
		S[23] ^= (^bc[4]) & bc[0]
		S[24] ^= (^bc[0]) & bc[1]

		// iota
		S[0] ^= roundConstants[r]
	}
}

func rotl64(x uint64, n uint) uint64 {
	return (x << n) | (x >> (64 - n))
}

func uint64le(v []byte) uint64 {
	return uint64(v[0]) |
		uint64(v[1])<<8 |
		uint64(v[2])<<16 |
		uint64(v[3])<<24 |
		uint64(v[4])<<32 |
		uint64(v[5])<<40 |
		uint64(v[6])<<48 |
		uint64(v[7])<<56

}

func putUint64le(v []byte, x uint64) {
	v[0] = byte(x)
	v[1] = byte(x >> 8)
	v[2] = byte(x >> 16)
	v[3] = byte(x >> 24)
	v[4] = byte(x >> 32)
	v[5] = byte(x >> 40)
	v[6] = byte(x >> 48)
	v[7] = byte(x >> 56)
}
<commit_msg>1.49x speedup<commit_after>// Package keccak implements the Keccak (SHA-3) hash algorithm.
// http://keccak.noekeon.org / FIPS 202 draft.
package keccak

import (
	"hash"
)

const (
	domainNone  = 1
	domainSHA3  = 0x06
	domainSHAKE = 0x1f
)

const rounds = 24

var roundConstants = []uint64{
	0x0000000000000001, 0x0000000000008082,
	0x800000000000808A, 0x8000000080008000,
	0x000000000000808B, 0x0000000080000001,
	0x8000000080008081, 0x8000000000008009,
	0x000000000000008A, 0x0000000000000088,
	0x0000000080008009, 0x000000008000000A,
	0x000000008000808B, 0x800000000000008B,
	0x8000000000008089, 0x8000000000008003,
	0x8000000000008002, 0x8000000000000080,
	0x000000000000800A, 0x800000008000000A,
	0x8000000080008081, 0x8000000000008080,
	0x0000000080000001, 0x8000000080008008,
}

var rotationConstants = [24]uint{
	1, 3, 6, 10, 15, 21, 28, 36,
	45, 55, 2, 14, 27, 41, 56, 8,
	25, 43, 62, 18, 39, 61, 20, 44,
}

var piLane = [24]uint{
	10, 7, 11, 17, 18, 3, 5, 16,
	8, 21, 24, 4, 15, 23, 19, 13,
	12, 2, 20, 14, 22, 9, 6, 1,
}

type keccak struct {
	S         [25]uint64
	size      int
	blockSize int
	buf       []byte
	domain    byte
}

func newKeccak(capacity, output int, domain byte) hash.Hash {
	var h keccak
	h.size = output / 8
	h.blockSize = (200 - capacity/8)
	h.domain = domain
	return &h
}

func New224() hash.Hash {
	return newKeccak(224*2, 224, domainNone)
}

func New256() hash.Hash {
	return newKeccak(256*2, 256, domainNone)
}

func New384() hash.Hash {
	return newKeccak(384*2, 384, domainNone)
}

func New512() hash.Hash {
	return newKeccak(512*2, 512, domainNone)
}

func (k *keccak) Write(b []byte) (int, error) {
	n := len(b)

	if len(k.buf) > 0 {
		x := k.blockSize - len(k.buf)
		if x > len(b) {
			x = len(b)
		}
		k.buf = append(k.buf, b[:x]...)
		b = b[x:]

		if len(k.buf) < k.blockSize {
			return n, nil
		}

		k.absorb(k.buf)
		k.buf = nil
	}

	for len(b) >= k.blockSize {
		k.absorb(b[:k.blockSize])
		b = b[k.blockSize:]
	}

	k.buf = b

	return n, nil
}

func (k0 *keccak) Sum(b []byte) []byte {
	k := *k0
	k.final()
	return k.squeeze(b)
}

func (k *keccak) Reset() {
	for i := range k.S {
		k.S[i] = 0
	}
	k.buf = nil
}

func (k *keccak) Size() int {
	return k.size
}

func (k *keccak) BlockSize() int {
	return k.blockSize
}

func (k *keccak) absorb(block []byte) {
	if len(block) != k.blockSize {
		panic("absorb() called with invalid block size")
	}

	for i := 0; i < k.blockSize/8; i++ {
		k.S[i] ^= uint64le(block[i*8:])
	}
	keccakf(&k.S)
}

func (k *keccak) pad(block []byte) []byte {

	padded := make([]byte, k.blockSize)

	copy(padded, k.buf)
	padded[len(k.buf)] = k.domain
	padded[len(padded)-1] |= 0x80

	return padded
}

func (k *keccak) final() {
	last := k.pad(k.buf)
	k.absorb(last)
}

func (k *keccak) squeeze(b []byte) []byte {
	buf := make([]byte, 8*len(k.S))
	n := k.size
	for {
		for i := range k.S {
			putUint64le(buf[i*8:], k.S[i])
		}
		if n <= k.blockSize {
			b = append(b, buf[:n]...)
			break
		}
		b = append(b, buf[:k.blockSize]...)
		n -= k.blockSize
		keccakf(&k.S)
	}
	return b
}

func keccakf(S *[25]uint64) {
	var bc [5]uint64
	var tmp uint64

	for r := 0; r < rounds; r++ {
		// theta
		bc[0] = S[0] ^ S[5] ^ S[10] ^ S[15] ^ S[20]
		bc[1] = S[1] ^ S[6] ^ S[11] ^ S[16] ^ S[21]
		bc[2] = S[2] ^ S[7] ^ S[12] ^ S[17] ^ S[22]
		bc[3] = S[3] ^ S[8] ^ S[13] ^ S[18] ^ S[23]
		bc[4] = S[4] ^ S[9] ^ S[14] ^ S[19] ^ S[24]
		tmp = bc[4] ^ (bc[1]<<1 | bc[1]>>(64-1))
		S[0] ^= tmp
		S[5] ^= tmp
		S[10] ^= tmp
		S[15] ^= tmp
		S[20] ^= tmp
		tmp = bc[0] ^(bc[2]<<1 | bc[2]>>(64-1))
		S[1] ^= tmp
		S[6] ^= tmp
		S[11] ^= tmp
		S[16] ^= tmp
		S[21] ^= tmp
		tmp = bc[1] ^ (bc[3]<<1 | bc[3]>>(64-1))
		S[2] ^= tmp
		S[7] ^= tmp
		S[12] ^= tmp
		S[17] ^= tmp
		S[22] ^= tmp
		tmp = bc[2] ^  (bc[4]<<1 | bc[4]>>(64-1))
		S[3] ^= tmp
		S[8] ^= tmp
		S[13] ^= tmp
		S[18] ^= tmp
		S[23] ^= tmp
		tmp = bc[3] ^ (bc[0]<<1 | bc[0]>>(64-1))
		S[4] ^= tmp
		S[9] ^= tmp
		S[14] ^= tmp
		S[19] ^= tmp
		S[24] ^= tmp

		// rho phi
		tmp = S[1]
		tmp, S[10] = S[10], tmp << 1 | tmp >> (64- 1)
		tmp, S[7] = S[7],   tmp << 3 | tmp >> (64- 3)
		tmp, S[11] = S[11], tmp << 6 | tmp >> (64- 6)
		tmp, S[17] = S[17], tmp << 10 | tmp >> (64- 10)
		tmp, S[18] = S[18], tmp << 15 | tmp >> (64- 15)
		tmp, S[3] = S[3],   tmp << 21 | tmp >> (64- 21)
		tmp, S[5] = S[5],   tmp << 28 | tmp >> (64- 28)
		tmp, S[16] = S[16], tmp << 36 | tmp >> (64- 36)
		tmp, S[8] = S[8],   tmp << 45 | tmp >> (64- 45)
		tmp, S[21] = S[21], tmp << 55 | tmp >> (64- 55)
		tmp, S[24] = S[24], tmp << 2 | tmp >> (64- 2)
		tmp, S[4] = S[4],   tmp << 14 | tmp >> (64- 14)
		tmp, S[15] = S[15], tmp << 27 | tmp >> (64- 27)
		tmp, S[23] = S[23], tmp << 41 | tmp >> (64- 41)
		tmp, S[19] = S[19], tmp << 56 | tmp >> (64- 56)
		tmp, S[13] = S[13], tmp << 8 | tmp >> (64- 8)
		tmp, S[12] = S[12], tmp << 25 | tmp >> (64- 25)
		tmp, S[2] = S[2],   tmp << 43 | tmp >> (64- 43)
		tmp, S[20] = S[20], tmp << 62 | tmp >> (64- 62)
		tmp, S[14] = S[14], tmp << 18 | tmp >> (64- 18)
		tmp, S[22] = S[22], tmp << 39 | tmp >> (64- 39)
		tmp, S[9] = S[9],   tmp << 61 | tmp >> (64- 61)
		tmp, S[6] = S[6],   tmp << 20 | tmp >> (64- 20)
		S[1] =              tmp << 44 | tmp >> (64- 44)

		// chi
		bc[0] = S[0]
		bc[1] = S[1]
		bc[2] = S[2]
		bc[3] = S[3]
		bc[4] = S[4]
		S[0] ^= (^bc[1]) & bc[2]
		S[1] ^= (^bc[2]) & bc[3]
		S[2] ^= (^bc[3]) & bc[4]
		S[3] ^= (^bc[4]) & bc[0]
		S[4] ^= (^bc[0]) & bc[1]
		bc[0] = S[5]
		bc[1] = S[6]
		bc[2] = S[7]
		bc[3] = S[8]
		bc[4] = S[9]
		S[5] ^= (^bc[1]) & bc[2]
		S[6] ^= (^bc[2]) & bc[3]
		S[7] ^= (^bc[3]) & bc[4]
		S[8] ^= (^bc[4]) & bc[0]
		S[9] ^= (^bc[0]) & bc[1]
		bc[0] = S[10]
		bc[1] = S[11]
		bc[2] = S[12]
		bc[3] = S[13]
		bc[4] = S[14]
		S[10] ^= (^bc[1]) & bc[2]
		S[11] ^= (^bc[2]) & bc[3]
		S[12] ^= (^bc[3]) & bc[4]
		S[13] ^= (^bc[4]) & bc[0]
		S[14] ^= (^bc[0]) & bc[1]
		bc[0] = S[15]
		bc[1] = S[16]
		bc[2] = S[17]
		bc[3] = S[18]
		bc[4] = S[19]
		S[15] ^= (^bc[1]) & bc[2]
		S[16] ^= (^bc[2]) & bc[3]
		S[17] ^= (^bc[3]) & bc[4]
		S[18] ^= (^bc[4]) & bc[0]
		S[19] ^= (^bc[0]) & bc[1]
		bc[0] = S[20]
		bc[1] = S[21]
		bc[2] = S[22]
		bc[3] = S[23]
		bc[4] = S[24]
		S[20] ^= (^bc[1]) & bc[2]
		S[21] ^= (^bc[2]) & bc[3]
		S[22] ^= (^bc[3]) & bc[4]
		S[23] ^= (^bc[4]) & bc[0]
		S[24] ^= (^bc[0]) & bc[1]

		// iota
		S[0] ^= roundConstants[r]
	}
}

func rotl64(x uint64, n uint) uint64 {
	return (x << n) | (x >> (64 - n))
}

func uint64le(v []byte) uint64 {
	return uint64(v[0]) |
		uint64(v[1])<<8 |
		uint64(v[2])<<16 |
		uint64(v[3])<<24 |
		uint64(v[4])<<32 |
		uint64(v[5])<<40 |
		uint64(v[6])<<48 |
		uint64(v[7])<<56

}

func putUint64le(v []byte, x uint64) {
	v[0] = byte(x)
	v[1] = byte(x >> 8)
	v[2] = byte(x >> 16)
	v[3] = byte(x >> 24)
	v[4] = byte(x >> 32)
	v[5] = byte(x >> 40)
	v[6] = byte(x >> 48)
	v[7] = byte(x >> 56)
}
<|endoftext|>


<commit_before>package kezban

import (
	"time"
	"github.com/revel/revel"
	"reflect"
	"fmt"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/mgo.v2"
	"errors"
)

type KezQu struct {
	Query interface{}
	Limit int
}

type Model struct {
	model          interface{}
	Id             bson.ObjectId `bson:"_id,omitempty" json:"id"`
	CreatedAt      time.Time `json:"created_at" bson:"created_at,omitempty"`
	UpdatedAt      time.Time `json:"updated_at" bson:"updated_at,omitempty"`
	collectionName string

}

var Database *mgo.Session = nil

func Initialize(uri string) {
	database, err := mgo.Dial(uri)
	if err != nil {
		revel.ERROR.Println("Database initialization failed!!")
		return
	}
	database.SetMode(mgo.Monotonic, true)
	Database = database
	revel.INFO.Println("Database initialization is completed.")
}

func (self *Model) SetItself(model interface{}) {
	self.model = model
}

func (self *Model) Test() {

}

func (self *Model) uniqueFieldCheck() error {
	uniqueMap := GetFields(self.model, "unique")
	revel.INFO.Println("map:",uniqueMap)
	/**
	* TODO: Unique check will be implemented via func (*Collection) EnsureIndex
	*/
	if len(uniqueMap) > 0 {
		newModel := createEmptyStruct(self.model)
		FillStruct(newModel, uniqueMap)
		revel.INFO.Println("Val: ", newModel)
		err := self.FindOne(newModel, newModel)
		revel.INFO.Println(err, newModel)
		if err != nil {
			if err.Error() == "not found" {
				return nil
			} else {
				return err
			}
		}
		return errors.New("unique field duplicate")
	} else {
		return nil
	}

}

func (self *Model) Save() (*Model, error) {
	self.UpdatedAt = time.Now()
	if !self.checkAndSetCollectionName() {
		revel.ERROR.Println("Something went wrong while trying to fetch collection name.")
		return nil, errors.New("Something went wrong while trying to fetch collection name.")
	}
	if err := self.uniqueFieldCheck(); err != nil {
		revel.ERROR.Println(err.Error())
		return nil, err
	}
	if !self.Id.Valid() { // first time creation
		self.Id = bson.NewObjectId()
		self.CreatedAt = time.Now()
		err := Database.DB(revel.AppName).C(self.collectionName).Insert(&self.model)
		bdata, errr := docToBson(self.model)
		fmt.Println(bdata, errr)
		if err != nil {
			revel.ERROR.Println(err)
			return nil, err
		}
	} else {
		err := Database.DB(revel.AppName).C(self.collectionName).Update(
			bson.M{"_id" : self.Id},
			self.model,
		)
		if err != nil {
			revel.ERROR.Println(err)
			return nil, err
		}
	}
	return self, nil
}

func (self *Model) FindOne(query interface{}, model interface{}) (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var q *mgo.Query
	if q, err = self.constructQuery(query); err != nil {
		return err
	}
	revel.INFO.Println("FindOne: q=", q, "self=", self)
	return q.One(model)
}

/*
 * @param query for specific filters
 * @param models needs to be pointer of model array
 * @return err
 */
func (self *Model) FindAll(query KezQu, models interface{}) (error) {
	mQuery, err := self.constructQuery(query.Query);
	revel.INFO.Println("FindAll: mQuery=", mQuery)
	if err != nil {
		return err
	}
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) Search(query KezQu, indexes []string, models interface{}) (error) {
	mQuery := self.constructSearchQuery(query.Query.(bson.M), indexes)
	revel.INFO.Println("Search: mQuery=", mQuery)
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) getMethodViaReflection(methodName string) (reflect.Value, string) {
	modelVal := reflect.ValueOf(self.model)
	function := modelVal.Elem().Addr().MethodByName(methodName)
	if function.IsValid() {
		return function, ""
	}
	return reflect.Zero(reflect.TypeOf(function)), methodName + " is invalid"
}

func (self *Model) constructSearchQuery(query bson.M, indexes []string) (*mgo.Query) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	c := Database.DB(revel.AppName).C(self.collectionName)
	index := mgo.Index{
		Key: indexes,
	}
	c.EnsureIndex(index)
	return c.Find(query)
}

func (self *Model) constructQuery(queryDoc interface{}) (*mgo.Query, error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var query bson.M
	var err error

	if queryDoc == nil {
		queryDoc = self.model
	}
	if query, err = docToBson(queryDoc); err != nil {
		return nil, err
	}
	revel.INFO.Println("constructQuery:", query, revel.AppName, self.collectionName)
	return Database.DB(revel.AppName).C(self.collectionName).Find(query), nil
}

func (self *Model) checkAndSetCollectionName() bool {
	if self.collectionName == "" {
		fn, err := self.getMethodViaReflection("GetCollectionName")
		if err != "" {
			panic(err)
		}
		result := fn.Call(nil)

		if len(result) > 0 && result[0].String() != "" {
			self.collectionName = result[0].String()
			return true
		}
		return false
	} else {
		return true
	}
}

func docToBson(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}

func ToBSON(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}<commit_msg>test function removed<commit_after>package kezban

import (
	"time"
	"github.com/revel/revel"
	"reflect"
	"fmt"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/mgo.v2"
	"errors"
)

type KezQu struct {
	Query interface{}
	Limit int
}

type Model struct {
	model          interface{}
	Id             bson.ObjectId `bson:"_id,omitempty" json:"id"`
	CreatedAt      time.Time `json:"created_at" bson:"created_at,omitempty"`
	UpdatedAt      time.Time `json:"updated_at" bson:"updated_at,omitempty"`
	collectionName string

}

var Database *mgo.Session = nil

func Initialize(uri string) {
	database, err := mgo.Dial(uri)
	if err != nil {
		revel.ERROR.Println("Database initialization failed!!")
		return
	}
	database.SetMode(mgo.Monotonic, true)
	Database = database
	revel.INFO.Println("Database initialization is completed.")
}

func (self *Model) SetItself(model interface{}) {
	self.model = model
}

func (self *Model) uniqueFieldCheck() error {
	uniqueMap := GetFields(self.model, "unique")
	revel.INFO.Println("map:",uniqueMap)
	/**
	* TODO: Unique check will be implemented via func (*Collection) EnsureIndex
	*/
	if len(uniqueMap) > 0 {
		newModel := createEmptyStruct(self.model)
		FillStruct(newModel, uniqueMap)
		revel.INFO.Println("Val: ", newModel)
		err := self.FindOne(newModel, newModel)
		revel.INFO.Println(err, newModel)
		if err != nil {
			if err.Error() == "not found" {
				return nil
			} else {
				return err
			}
		}
		return errors.New("unique field duplicate")
	} else {
		return nil
	}

}

func (self *Model) Save() (*Model, error) {
	self.UpdatedAt = time.Now()
	if !self.checkAndSetCollectionName() {
		revel.ERROR.Println("Something went wrong while trying to fetch collection name.")
		return nil, errors.New("Something went wrong while trying to fetch collection name.")
	}
	if err := self.uniqueFieldCheck(); err != nil {
		revel.ERROR.Println(err.Error())
		return nil, err
	}
	if !self.Id.Valid() { // first time creation
		self.Id = bson.NewObjectId()
		self.CreatedAt = time.Now()
		err := Database.DB(revel.AppName).C(self.collectionName).Insert(&self.model)
		bdata, errr := docToBson(self.model)
		fmt.Println(bdata, errr)
		if err != nil {
			revel.ERROR.Println(err)
			return nil, err
		}
	} else {
		err := Database.DB(revel.AppName).C(self.collectionName).Update(
			bson.M{"_id" : self.Id},
			self.model,
		)
		if err != nil {
			revel.ERROR.Println(err)
			return nil, err
		}
	}
	return self, nil
}

func (self *Model) FindOne(query interface{}, model interface{}) (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var q *mgo.Query
	if q, err = self.constructQuery(query); err != nil {
		return err
	}
	revel.INFO.Println("FindOne: q=", q, "self=", self)
	return q.One(model)
}

/*
 * @param query for specific filters
 * @param models needs to be pointer of model array
 * @return err
 */
func (self *Model) FindAll(query KezQu, models interface{}) (error) {
	mQuery, err := self.constructQuery(query.Query);
	revel.INFO.Println("FindAll: mQuery=", mQuery)
	if err != nil {
		return err
	}
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) Search(query KezQu, indexes []string, models interface{}) (error) {
	mQuery := self.constructSearchQuery(query.Query.(bson.M), indexes)
	revel.INFO.Println("Search: mQuery=", mQuery)
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) getMethodViaReflection(methodName string) (reflect.Value, string) {
	modelVal := reflect.ValueOf(self.model)
	function := modelVal.Elem().Addr().MethodByName(methodName)
	if function.IsValid() {
		return function, ""
	}
	return reflect.Zero(reflect.TypeOf(function)), methodName + " is invalid"
}

func (self *Model) constructSearchQuery(query bson.M, indexes []string) (*mgo.Query) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	c := Database.DB(revel.AppName).C(self.collectionName)
	index := mgo.Index{
		Key: indexes,
	}
	c.EnsureIndex(index)
	return c.Find(query)
}

func (self *Model) constructQuery(queryDoc interface{}) (*mgo.Query, error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var query bson.M
	var err error

	if queryDoc == nil {
		queryDoc = self.model
	}
	if query, err = docToBson(queryDoc); err != nil {
		return nil, err
	}
	revel.INFO.Println("constructQuery:", query, revel.AppName, self.collectionName)
	return Database.DB(revel.AppName).C(self.collectionName).Find(query), nil
}

func (self *Model) checkAndSetCollectionName() bool {
	if self.collectionName == "" {
		fn, err := self.getMethodViaReflection("GetCollectionName")
		if err != "" {
			panic(err)
		}
		result := fn.Call(nil)

		if len(result) > 0 && result[0].String() != "" {
			self.collectionName = result[0].String()
			return true
		}
		return false
	} else {
		return true
	}
}

func docToBson(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}

func ToBSON(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}<|endoftext|>


<commit_before>package renter

import (
	"testing"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
)

func TestNegotiateContract(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestNegotiateContract")
	if err != nil {
		t.Fatal(err)
	}

	payout := types.NewCurrency64(1e16)

	fc := types.FileContract{
		FileSize:       0,
		FileMerkleRoot: crypto.Hash{}, // no proof possible without data
		WindowStart:    100,
		WindowEnd:      1000,
		Payout:         payout,
		ValidProofOutputs: []types.SiacoinOutput{
			{Value: payout, UnlockHash: types.UnlockHash{}},
			{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
		},
		MissedProofOutputs: []types.SiacoinOutput{
			// same as above
			{Value: payout, UnlockHash: types.UnlockHash{}},
			// goes to the void, not the renter
			{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
		},
		UnlockHash:     types.UnlockHash{},
		RevisionNumber: 0,
	}
	fc.ValidProofOutputs[0].Value = fc.ValidProofOutputs[0].Value.Sub(fc.Tax())
	fc.MissedProofOutputs[0].Value = fc.MissedProofOutputs[0].Value.Sub(fc.Tax())

	txnBuilder := rt.wallet.StartTransaction()
	err = txnBuilder.FundSiacoins(fc.Payout)
	if err != nil {
		t.Fatal(err)
	}
	txnBuilder.AddFileContract(fc)
	signedTxnSet, err := txnBuilder.Sign(true)
	if err != nil {
		t.Fatal(err)
	}

	err = rt.tpool.AcceptTransactionSet(signedTxnSet)
	if err != nil {
		t.Fatal(err)
	}

}

func TestReviseContract(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestNegotiateContract")
	if err != nil {
		t.Fatal(err)
	}

	// generate keys
	sk, pk, err := crypto.GenerateSignatureKeys()
	if err != nil {
		t.Fatal(err)
	}
	renterPubKey := types.SiaPublicKey{
		Algorithm: types.SignatureEd25519,
		Key:       pk[:],
	}

	uc := types.UnlockConditions{
		PublicKeys:         []types.SiaPublicKey{renterPubKey, renterPubKey},
		SignaturesRequired: 1,
	}

	// create revision
	fcid := types.FileContractID{1}
	rev := types.FileContractRevision{
		ParentID:         fcid,
		UnlockConditions: uc,
		NewFileSize:      10,
		NewWindowStart:   100,
		NewWindowEnd:     1000,
	}

	// create transaction containing the revision
	signedTxn := types.Transaction{
		FileContractRevisions: []types.FileContractRevision{rev},
		TransactionSignatures: []types.TransactionSignature{{
			ParentID:       crypto.Hash(fcid),
			CoveredFields:  types.CoveredFields{FileContractRevisions: []uint64{0}},
			PublicKeyIndex: 0, // renter key is always first -- see negotiateContract
		}},
	}

	// sign the transaction
	encodedSig, err := crypto.SignHash(signedTxn.SigHash(0), sk)
	if err != nil {
		t.Fatal(err)
	}
	signedTxn.TransactionSignatures[0].Signature = encodedSig[:]

	err = signedTxn.StandaloneValid(rt.renter.blockHeight)
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>improve revision test<commit_after>package renter

import (
	"testing"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
)

func TestNegotiateContract(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestNegotiateContract")
	if err != nil {
		t.Fatal(err)
	}

	payout := types.NewCurrency64(1e16)

	fc := types.FileContract{
		FileSize:       0,
		FileMerkleRoot: crypto.Hash{}, // no proof possible without data
		WindowStart:    100,
		WindowEnd:      1000,
		Payout:         payout,
		ValidProofOutputs: []types.SiacoinOutput{
			{Value: payout, UnlockHash: types.UnlockHash{}},
			{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
		},
		MissedProofOutputs: []types.SiacoinOutput{
			// same as above
			{Value: payout, UnlockHash: types.UnlockHash{}},
			// goes to the void, not the renter
			{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
		},
		UnlockHash:     types.UnlockHash{},
		RevisionNumber: 0,
	}
	fc.ValidProofOutputs[0].Value = fc.ValidProofOutputs[0].Value.Sub(fc.Tax())
	fc.MissedProofOutputs[0].Value = fc.MissedProofOutputs[0].Value.Sub(fc.Tax())

	txnBuilder := rt.wallet.StartTransaction()
	err = txnBuilder.FundSiacoins(fc.Payout)
	if err != nil {
		t.Fatal(err)
	}
	txnBuilder.AddFileContract(fc)
	signedTxnSet, err := txnBuilder.Sign(true)
	if err != nil {
		t.Fatal(err)
	}

	err = rt.tpool.AcceptTransactionSet(signedTxnSet)
	if err != nil {
		t.Fatal(err)
	}

}

func TestReviseContract(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestNegotiateContract")
	if err != nil {
		t.Fatal(err)
	}

	// get an address
	ourAddr, err := rt.wallet.NextAddress()
	if err != nil {
		t.Fatal(err)
	}

	// generate keys
	sk, pk, err := crypto.GenerateSignatureKeys()
	if err != nil {
		t.Fatal(err)
	}
	renterPubKey := types.SiaPublicKey{
		Algorithm: types.SignatureEd25519,
		Key:       pk[:],
	}

	uc := types.UnlockConditions{
		PublicKeys:         []types.SiaPublicKey{renterPubKey, renterPubKey},
		SignaturesRequired: 1,
	}

	// create file contract
	payout := types.NewCurrency64(1e16)

	fc := types.FileContract{
		FileSize:       0,
		FileMerkleRoot: crypto.Hash{}, // no proof possible without data
		WindowStart:    100,
		WindowEnd:      1000,
		Payout:         payout,
		UnlockHash:     uc.UnlockHash(),
		RevisionNumber: 0,
	}
	// outputs need account for tax
	fc.ValidProofOutputs = []types.SiacoinOutput{
		{Value: payout.Sub(fc.Tax()), UnlockHash: ourAddr.UnlockHash()},
		{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}}, // no collateral
	}
	fc.MissedProofOutputs = []types.SiacoinOutput{
		// same as above
		fc.ValidProofOutputs[0],
		// goes to the void, not the renter
		{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
	}

	txnBuilder := rt.wallet.StartTransaction()
	err = txnBuilder.FundSiacoins(fc.Payout)
	if err != nil {
		t.Fatal(err)
	}
	txnBuilder.AddFileContract(fc)
	signedTxnSet, err := txnBuilder.Sign(true)
	if err != nil {
		t.Fatal(err)
	}

	// submit contract
	err = rt.tpool.AcceptTransactionSet(signedTxnSet)
	if err != nil {
		t.Fatal(err)
	}

	// create revision
	fcid := signedTxnSet[len(signedTxnSet)-1].FileContractID(0)
	rev := types.FileContractRevision{
		ParentID:              fcid,
		UnlockConditions:      uc,
		NewFileSize:           10,
		NewWindowStart:        100,
		NewWindowEnd:          1000,
		NewRevisionNumber:     1,
		NewValidProofOutputs:  fc.ValidProofOutputs,
		NewMissedProofOutputs: fc.MissedProofOutputs,
	}

	// create transaction containing the revision
	signedTxn := types.Transaction{
		FileContractRevisions: []types.FileContractRevision{rev},
		TransactionSignatures: []types.TransactionSignature{{
			ParentID:       crypto.Hash(fcid),
			CoveredFields:  types.CoveredFields{FileContractRevisions: []uint64{0}},
			PublicKeyIndex: 0, // renter key is always first -- see negotiateContract
		}},
	}

	// sign the transaction
	encodedSig, err := crypto.SignHash(signedTxn.SigHash(0), sk)
	if err != nil {
		t.Fatal(err)
	}
	signedTxn.TransactionSignatures[0].Signature = encodedSig[:]

	err = signedTxn.StandaloneValid(rt.renter.blockHeight)
	if err != nil {
		t.Fatal(err)
	}

	// submit revision
	err = rt.tpool.AcceptTransactionSet([]types.Transaction{signedTxn})
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package oci

import (
	specs "github.com/opencontainers/runtime-spec/specs-go"
)

func defaultMounts() []specs.Mount {
	return []specs.Mount{
		{
			Destination: "/dev",
			Type:        "devfs",
			Source:      "devfs",
			Options:     []string{"ruleset=4"},
		},
		{
			Destination: "/dev/fd",
			Type:        "fdescfs",
			Source:      "fdescfs",
			Options:     []string{},
		},
	}
}
<commit_msg>oci: Remove empty mount option slice for FreeBSD<commit_after>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package oci

import (
	specs "github.com/opencontainers/runtime-spec/specs-go"
)

func defaultMounts() []specs.Mount {
	return []specs.Mount{
		{
			Destination: "/dev",
			Type:        "devfs",
			Source:      "devfs",
			Options:     []string{"ruleset=4"},
		},
		{
			Destination: "/dev/fd",
			Type:        "fdescfs",
			Source:      "fdescfs",
		},
	}
}
<|endoftext|>


<commit_before>package middleware

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/webx-top/echo"
)

type (
	StaticOptions struct {
		Path   string `json:"path"` //UrlPath
		Root   string `json:"root"`
		Index  string `json:"index"`
		Browse bool   `json:"browse"`
	}
)

func Static(options ...*StaticOptions) echo.MiddlewareFunc {
	// Default options
	opts := new(StaticOptions)
	if len(options) > 0 {
		opts = options[0]
	}
	if opts.Index == "" {
		opts.Index = "index.html"
	}

	opts.Root, _ = filepath.Abs(opts.Root)
	length := len(opts.Path)

	return func(next echo.Handler) echo.Handler {
		return echo.HandlerFunc(func(c echo.Context) error {
			file := c.Request().URL().Path()
			if len(file) < length || file[0:length] != opts.Path {
				return next.Handle(c)
			}
			file = filepath.Clean(file[length:])
			absFile := filepath.Join(opts.Root, file)
			if !strings.HasPrefix(absFile, opts.Root) {
				return next.Handle(c)
			}
			fi, err := os.Stat(absFile)
			if err != nil {
				return next.Handle(c)
			}
			w := c.Response()
			if fi.IsDir() {
				// Index file
				indexFile := filepath.Join(absFile, opts.Index)
				fi, err = os.Stat(indexFile)
				if err != nil || fi.IsDir() {
					if opts.Browse {
						fs := http.Dir(opts.Root)
						d, err := fs.Open(file)
						if err != nil {
							return echo.ErrNotFound
						}
						defer d.Close()
						dirs, err := d.Readdir(-1)
						if err != nil {
							return err
						}

						// Create a directory index
						w.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8)
						if _, err = fmt.Fprintf(w, "
\n"); err != nil {
							return err
						}
						for _, d := range dirs {
							name := d.Name()
							color := "#212121"
							if d.IsDir() {
								color = "#e91e63"
								name += "/"
							}
							if _, err = fmt.Fprintf(w, "%s\n", name, color, name); err != nil {
								return err
							}
						}
						_, err = fmt.Fprintf(w, "
\n")
						return err
					}
					return next.Handle(c)
				} else {
					absFile = indexFile
				}
			}
			w.ServeFile(absFile)
			return nil
		})
	}
}

// Favicon serves the default favicon - GET /favicon.ico.
func Favicon() echo.HandlerFunc {
	return func(c echo.Context) error {
		return nil
	}
}
<commit_msg>improved<commit_after>package middleware

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/webx-top/echo"
)

type (
	StaticOptions struct {
		Path   string `json:"path"` //UrlPath
		Root   string `json:"root"`
		Index  string `json:"index"`
		Browse bool   `json:"browse"`
	}
)

func Static(options ...*StaticOptions) echo.MiddlewareFunc {
	// Default options
	opts := new(StaticOptions)
	if len(options) > 0 {
		opts = options[0]
	}
	if opts.Index == "" {
		opts.Index = "index.html"
	}

	opts.Root, _ = filepath.Abs(opts.Root)
	length := len(opts.Path)

	return func(next echo.Handler) echo.Handler {
		return echo.HandlerFunc(func(c echo.Context) error {
			file := c.Request().URL().Path()
			if len(file) < length || file[0:length] != opts.Path {
				return next.Handle(c)
			}
			file = filepath.Clean(file[length:])
			absFile := filepath.Join(opts.Root, file)
			if !strings.HasPrefix(absFile, opts.Root) {
				return next.Handle(c)
			}
			fi, err := os.Stat(absFile)
			if err != nil {
				return next.Handle(c)
			}
			w := c.Response()
			if fi.IsDir() {
				// Index file
				indexFile := filepath.Join(absFile, opts.Index)
				fi, err = os.Stat(indexFile)
				if err != nil || fi.IsDir() {
					if opts.Browse {
						fs := http.Dir(opts.Root)
						d, err := fs.Open(file)
						if err != nil {
							return echo.ErrNotFound
						}
						defer d.Close()
						dirs, err := d.Readdir(-1)
						if err != nil {
							return err
						}

						// Create a directory index
						w.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8)
						if _, err = fmt.Fprintf(w, "
\n"); err != nil {
							return err
						}
						for _, d := range dirs {
							name := d.Name()
							color := "#212121"
							if d.IsDir() {
								color = "#e91e63"
								name += "/"
							}
							if _, err = fmt.Fprintf(w, "%s\n", name, color, name); err != nil {
								return err
							}
						}
						_, err = fmt.Fprintf(w, "
\n")
						return err
					}
					return next.Handle(c)
				}
				absFile = indexFile
			}
			w.ServeFile(absFile)
			return nil
		})
	}
}

// Favicon serves the default favicon - GET /favicon.ico.
func Favicon() echo.HandlerFunc {
	return func(c echo.Context) error {
		return nil
	}
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package csrf offers stateless protection against CSRF attacks using
// the HTTP Origin header and falling back to HMAC tokens stored on secured
// and HTTP-only cookies.
package csrf

import (
	"errors"
	"net/http"
	"net/url"
	"time"

	"golang.org/x/net/xsrftoken"
)

// handler is a private struct which contains the handler's configurable options.
type handler struct {
	name   string
	domain string
	secret string
	userID string
}

// WithName allows configuring the CSRF cookie name.
func WithName(n string) Option {
	return func(h *handler) {
		h.name = n
	}
}

// WithSecret configures the secret cryptographic key for signing the token.
func WithSecret(s string) Option {
	return func(h *handler) {
		h.secret = s
	}
}

// WithUserID allows to configure a random and unique user ID identifier used to generate the CSRF token.
func WithUserID(s string) Option {
	return func(h *handler) {
		h.userID = s
	}
}

// WithDomain configures the domain under which the CSRF cookie is going to be set.
func WithDomain(d string) Option {
	return func(h *handler) {
		h.domain = d
	}
}

var (
	// We are purposely being ambiguous on the HTTP error messages to avoid giving clues to potential attackers
	// other than 403 Forbidden messages
	errForbidden = "Forbidden"
	// Development time messages
	errSecretRequired = errors.New("csrf: a secret key must be provided")
	errDomainRequired = errors.New("csrf: a domain name is required")
)

// Option implements http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
type Option func(*handler)

// Handler checks Origin header first, if not set or has value "null" it validates using
// a HMAC CSRF token. For enabling Single Page Applications to send the XSRF cookie using
// async HTTP requests, use CORS and make sure Access-Control-Allow-Credential is enabled.
func Handler(h http.Handler, opts ...Option) http.Handler {
	// Sets default options
	csrf := &handler{
		name: "xt",
	}

	for _, opt := range opts {
		opt(csrf)
	}

	if csrf.secret == "" {
		panic(errSecretRequired)
	}

	if csrf.domain == "" {
		panic(errDomainRequired)
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Re-enables browser's XSS filter if it was disabled
		w.Header().Set("x-xss-protection", "1; mode=block")

		if csrf.userID == "" {
			http.Error(w, errForbidden, http.StatusForbidden)
			return
		}

		// Set the token on the response to GET and HEAD requests
		switch r.Method {
		case "GET":
		case "HEAD":
		case "OPTIONS":
			setToken(w, csrf.name, csrf.secret, csrf.userID, csrf.domain)
			h.ServeHTTP(w, r)
			return
		}

		// Verify using origin header first
		// Details about Origin header can be found at https://wiki.mozilla.org/Security/Origin
		originValue := r.Header.Get("origin")
		if originValue != "" {
			originURL, err := url.ParseRequestURI(originValue)
			if err == nil && originURL.Host == r.Host {
				setToken(w, csrf.name, csrf.secret, csrf.userID, csrf.domain)
				h.ServeHTTP(w, r)
				return
			}
			// log.Printf("csrf: %+v\n", err)
		}

		// If origin is not supported or came back empty or null, verify cookie instead.
		cookie, err := r.Cookie(csrf.name)
		if err != nil {
			http.Error(w, errForbidden, http.StatusForbidden)
			return
		}

		if !xsrftoken.Valid(cookie.Value, csrf.secret, csrf.userID, "Global") {
			http.Error(w, errForbidden, http.StatusForbidden)
			return
		}

		setToken(w, csrf.name, csrf.secret, csrf.userID, csrf.domain)
		h.ServeHTTP(w, r)
	})
}

func setToken(w http.ResponseWriter, name, secret, userID, domain string) {
	token := xsrftoken.Generate(secret, userID, "Global")

	http.SetCookie(w, &http.Cookie{
		Name:     name,
		Value:    token,
		Path:     "/",
		Domain:   domain,
		Expires:  time.Now().Add(xsrftoken.Timeout),
		MaxAge:   int(xsrftoken.Timeout.Seconds()),
		Secure:   true,
		HttpOnly: true,
	})
}
<commit_msg>csrf: domain is not required<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package csrf offers stateless protection against CSRF attacks using
// the HTTP Origin header and falling back to HMAC tokens stored on secured
// and HTTP-only cookies.
package csrf

import (
	"errors"
	"net/http"
	"net/url"
	"time"

	"golang.org/x/net/xsrftoken"
)

// handler is a private struct which contains the handler's configurable options.
type handler struct {
	name   string
	domain string
	secret string
	userID string
}

// WithName allows configuring the CSRF cookie name.
func WithName(n string) Option {
	return func(h *handler) {
		h.name = n
	}
}

// WithSecret configures the secret cryptographic key for signing the token.
func WithSecret(s string) Option {
	return func(h *handler) {
		h.secret = s
	}
}

// WithUserID allows to configure a random and unique user ID identifier used to generate the CSRF token.
func WithUserID(s string) Option {
	return func(h *handler) {
		h.userID = s
	}
}

// WithDomain configures the domain under which the CSRF cookie is going to be set.
func WithDomain(d string) Option {
	return func(h *handler) {
		h.domain = d
	}
}

var (
	// We are purposely being ambiguous on the HTTP error messages to avoid giving clues to potential attackers
	// other than 403 Forbidden messages
	errForbidden = "Forbidden"
	// Development time messages
	errSecretRequired = errors.New("csrf: a secret key must be provided")
)

// Option implements http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
type Option func(*handler)

// Handler checks Origin header first, if not set or has value "null" it validates using
// a HMAC CSRF token. For enabling Single Page Applications to send the XSRF cookie using
// async HTTP requests, use CORS and make sure Access-Control-Allow-Credential is enabled.
func Handler(h http.Handler, opts ...Option) http.Handler {
	// Sets default options
	csrf := &handler{
		name: "xt",
	}

	for _, opt := range opts {
		opt(csrf)
	}

	if csrf.secret == "" {
		panic(errSecretRequired)
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Re-enables browser's XSS filter if it was disabled
		w.Header().Set("x-xss-protection", "1; mode=block")

		// Set the token on the response to GET and HEAD requests
		switch r.Method {
		case "GET":
		case "HEAD":
		case "OPTIONS":
			setToken(w, csrf.name, csrf.secret, csrf.userID, csrf.domain)
			h.ServeHTTP(w, r)
			return
		}

		// Verify using origin header first
		// Details about Origin header can be found at https://wiki.mozilla.org/Security/Origin
		originValue := r.Header.Get("origin")
		if originValue != "" {
			originURL, err := url.ParseRequestURI(originValue)
			if err == nil && originURL.Host == r.Host {
				setToken(w, csrf.name, csrf.secret, csrf.userID, csrf.domain)
				h.ServeHTTP(w, r)
				return
			}
			// log.Printf("csrf: %+v\n", err)
		}

		// If origin is not supported or came back empty or null, verify cookie instead.
		cookie, err := r.Cookie(csrf.name)
		if err != nil {
			http.Error(w, errForbidden, http.StatusForbidden)
			return
		}

		if !xsrftoken.Valid(cookie.Value, csrf.secret, csrf.userID, "Global") {
			http.Error(w, errForbidden, http.StatusForbidden)
			return
		}

		setToken(w, csrf.name, csrf.secret, csrf.userID, csrf.domain)
		h.ServeHTTP(w, r)
	})
}

func setToken(w http.ResponseWriter, name, secret, userID, domain string) {
	token := xsrftoken.Generate(secret, userID, "Global")

	http.SetCookie(w, &http.Cookie{
		Name:     name,
		Value:    token,
		Path:     "/",
		Domain:   domain,
		Expires:  time.Now().Add(xsrftoken.Timeout),
		MaxAge:   int(xsrftoken.Timeout.Seconds()),
		Secure:   true,
		HttpOnly: true,
	})
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Handler for Docker containers.
package docker

import (
	"fmt"
	"io/ioutil"
	"math"
	"path"
	"strings"
	"time"

	"github.com/google/cadvisor/container"
	containerlibcontainer "github.com/google/cadvisor/container/libcontainer"
	"github.com/google/cadvisor/fs"
	info "github.com/google/cadvisor/info/v1"
	"github.com/google/cadvisor/utils"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/opencontainers/runc/libcontainer/cgroups"
	cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
	libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)

const (
	// The read write layers exist here.
	aufsRWLayer = "diff"
	// Path to the directory where docker stores log files if the json logging driver is enabled.
	pathToContainersDir = "containers"
)

type dockerContainerHandler struct {
	client             *docker.Client
	name               string
	id                 string
	aliases            []string
	machineInfoFactory info.MachineInfoFactory

	// Absolute path to the cgroup hierarchies of this container.
	// (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test")
	cgroupPaths map[string]string

	// Manager of this container's cgroups.
	cgroupManager cgroups.Manager

	storageDriver    storageDriver
	fsInfo           fs.FsInfo
	rootfsStorageDir string

	// Time at which this container was created.
	creationTime time.Time

	// Metadata associated with the container.
	labels map[string]string
	envs   map[string]string

	// The container PID used to switch namespaces as required
	pid int

	// Image name used for this container.
	image string

	// The host root FS to read
	rootFs string

	// The network mode of the container
	networkMode string

	// Filesystem handler.
	fsHandler fsHandler

	ignoreMetrics container.MetricSet
}

func getRwLayerID(containerID, storageDir string, sd storageDriver, dockerVersion []int) (string, error) {
	const (
		// Docker version >=1.10.0 have a randomized ID for the root fs of a container.
		randomizedRWLayerMinorVersion = 10
		rwLayerIDFile                 = "mount-id"
	)
	if (dockerVersion[0] <= 1) && (dockerVersion[1] < randomizedRWLayerMinorVersion) {
		return containerID, nil
	}

	bytes, err := ioutil.ReadFile(path.Join(storageDir, "image", string(sd), "layerdb", "mounts", containerID, rwLayerIDFile))
	if err != nil {
		return "", fmt.Errorf("failed to identify the read-write layer ID for container %q. - %v", containerID, err)
	}
	return string(bytes), err
}

func newDockerContainerHandler(
	client *docker.Client,
	name string,
	machineInfoFactory info.MachineInfoFactory,
	fsInfo fs.FsInfo,
	storageDriver storageDriver,
	storageDir string,
	cgroupSubsystems *containerlibcontainer.CgroupSubsystems,
	inHostNamespace bool,
	metadataEnvs []string,
	dockerVersion []int,
	ignoreMetrics container.MetricSet,
) (container.ContainerHandler, error) {
	// Create the cgroup paths.
	cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints))
	for key, val := range cgroupSubsystems.MountPoints {
		cgroupPaths[key] = path.Join(val, name)
	}

	// Generate the equivalent cgroup manager for this container.
	cgroupManager := &cgroupfs.Manager{
		Cgroups: &libcontainerconfigs.Cgroup{
			Name: name,
		},
		Paths: cgroupPaths,
	}

	rootFs := "/"
	if !inHostNamespace {
		rootFs = "/rootfs"
		storageDir = path.Join(rootFs, storageDir)
	}

	id := ContainerNameToDockerId(name)

	// Add the Containers dir where the log files are stored.
	// FIXME: Give `otherStorageDir` a more descriptive name.
	otherStorageDir := path.Join(storageDir, pathToContainersDir, id)

	rwLayerID, err := getRwLayerID(id, storageDir, storageDriver, dockerVersion)
	if err != nil {
		return nil, err
	}
	var rootfsStorageDir string
	switch storageDriver {
	case aufsStorageDriver:
		rootfsStorageDir = path.Join(storageDir, string(aufsStorageDriver), aufsRWLayer, rwLayerID)
	case overlayStorageDriver:
		rootfsStorageDir = path.Join(storageDir, string(overlayStorageDriver), rwLayerID)
	}

	handler := &dockerContainerHandler{
		id:                 id,
		client:             client,
		name:               name,
		machineInfoFactory: machineInfoFactory,
		cgroupPaths:        cgroupPaths,
		cgroupManager:      cgroupManager,
		storageDriver:      storageDriver,
		fsInfo:             fsInfo,
		rootFs:             rootFs,
		rootfsStorageDir:   rootfsStorageDir,
		envs:               make(map[string]string),
		ignoreMetrics:      ignoreMetrics,
	}

	if !ignoreMetrics.Has(container.DiskUsageMetrics) {
		handler.fsHandler = newFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo)
	}

	// We assume that if Inspect fails then the container is not known to docker.
	ctnr, err := client.InspectContainer(id)
	if err != nil {
		return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
	}
	handler.creationTime = ctnr.Created
	handler.pid = ctnr.State.Pid

	// Add the name and bare ID as aliases of the container.
	handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id)
	handler.labels = ctnr.Config.Labels
	handler.image = ctnr.Config.Image
	handler.networkMode = ctnr.HostConfig.NetworkMode

	// split env vars to get metadata map.
	for _, exposedEnv := range metadataEnvs {
		for _, envVar := range ctnr.Config.Env {
			splits := strings.SplitN(envVar, "=", 2)
			if splits[0] == exposedEnv {
				handler.envs[strings.ToLower(exposedEnv)] = splits[1]
			}
		}
	}

	return handler, nil
}

func (self *dockerContainerHandler) Start() {
	// Start the filesystem handler.
	if self.fsHandler != nil {
		self.fsHandler.start()
	}
}

func (self *dockerContainerHandler) Cleanup() {
	if self.fsHandler != nil {
		self.fsHandler.stop()
	}
}

func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
	return info.ContainerReference{
		Id:        self.id,
		Name:      self.name,
		Aliases:   self.aliases,
		Namespace: DockerNamespace,
		Labels:    self.labels,
	}, nil
}

func (self *dockerContainerHandler) readLibcontainerConfig() (*libcontainerconfigs.Config, error) {
	config, err := containerlibcontainer.ReadConfig(*dockerRootDir, *dockerRunDir, self.id)
	if err != nil {
		return nil, fmt.Errorf("failed to read libcontainer config: %v", err)
	}

	// Replace cgroup parent and name with our own since we may be running in a different context.
	if config.Cgroups == nil {
		config.Cgroups = new(libcontainerconfigs.Cgroup)
	}
	config.Cgroups.Name = self.name
	config.Cgroups.Parent = "/"

	return config, nil
}

func libcontainerConfigToContainerSpec(config *libcontainerconfigs.Config, mi *info.MachineInfo) info.ContainerSpec {
	var spec info.ContainerSpec
	spec.HasMemory = true
	spec.Memory.Limit = math.MaxUint64
	spec.Memory.SwapLimit = math.MaxUint64

	if config.Cgroups.Resources != nil {
		if config.Cgroups.Resources.Memory > 0 {
			spec.Memory.Limit = uint64(config.Cgroups.Resources.Memory)
		}
		if config.Cgroups.Resources.MemorySwap > 0 {
			spec.Memory.SwapLimit = uint64(config.Cgroups.Resources.MemorySwap)
		}

		// Get CPU info
		spec.HasCpu = true
		spec.Cpu.Limit = 1024
		if config.Cgroups.Resources.CpuShares != 0 {
			spec.Cpu.Limit = uint64(config.Cgroups.Resources.CpuShares)
		}
		spec.Cpu.Mask = utils.FixCpuMask(config.Cgroups.Resources.CpusetCpus, mi.NumCores)
	}

	spec.HasDiskIo = true

	return spec
}

func (self *dockerContainerHandler) needNet() bool {
	if !self.ignoreMetrics.Has(container.NetworkUsageMetrics) {
		return !strings.HasPrefix(self.networkMode, "container:")
	}
	return false
}

func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return info.ContainerSpec{}, err
	}
	libcontainerConfig, err := self.readLibcontainerConfig()
	if err != nil {
		return info.ContainerSpec{}, err
	}

	spec := libcontainerConfigToContainerSpec(libcontainerConfig, mi)
	spec.CreationTime = self.creationTime

	if !self.ignoreMetrics.Has(container.DiskUsageMetrics) {
		switch self.storageDriver {
		case aufsStorageDriver, overlayStorageDriver, zfsStorageDriver:
			spec.HasFilesystem = true
		}
	}

	spec.Labels = self.labels
	spec.Envs = self.envs
	spec.Image = self.image
	spec.HasNetwork = self.needNet()

	return spec, err
}

func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error {
	if self.ignoreMetrics.Has(container.DiskUsageMetrics) {
		return nil
	}
	switch self.storageDriver {
	case aufsStorageDriver, overlayStorageDriver, zfsStorageDriver:
	default:
		return nil
	}

	deviceInfo, err := self.fsInfo.GetDirFsDevice(self.rootfsStorageDir)
	if err != nil {
		return err
	}

	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return err
	}
	var (
		limit  uint64
		fsType string
	)

	// Docker does not impose any filesystem limits for containers. So use capacity as limit.
	for _, fs := range mi.Filesystems {
		if fs.Device == deviceInfo.Device {
			limit = fs.Capacity
			fsType = fs.Type
			break
		}
	}

	fsStat := info.FsStats{Device: deviceInfo.Device, Type: fsType, Limit: limit}

	fsStat.BaseUsage, fsStat.Usage = self.fsHandler.usage()
	stats.Filesystem = append(stats.Filesystem, fsStat)

	return nil
}

// TODO(vmarmol): Get from libcontainer API instead of cgroup manager when we don't have to support older Dockers.
func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
	stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid, self.ignoreMetrics)
	if err != nil {
		return stats, err
	}
	// Clean up stats for containers that don't have their own network - this
	// includes containers running in Kubernetes pods that use the network of the
	// infrastructure container. This stops metrics being reported multiple times
	// for each container in a pod.
	if !self.needNet() {
		stats.Network = info.NetworkStats{}
	}

	// Get filesystem stats.
	err = self.getFsStats(stats)
	if err != nil {
		return stats, err
	}

	return stats, nil
}

func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
	// No-op for Docker driver.
	return []info.ContainerReference{}, nil
}

func (self *dockerContainerHandler) GetCgroupPath(resource string) (string, error) {
	path, ok := self.cgroupPaths[resource]
	if !ok {
		return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name)
	}
	return path, nil
}

func (self *dockerContainerHandler) ListThreads(listType container.ListType) ([]int, error) {
	// TODO(vmarmol): Implement.
	return nil, nil
}

func (self *dockerContainerHandler) GetContainerLabels() map[string]string {
	return self.labels
}

func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
	return containerlibcontainer.GetProcesses(self.cgroupManager)
}

func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error {
	return fmt.Errorf("watch is unimplemented in the Docker container driver")
}

func (self *dockerContainerHandler) StopWatchingSubcontainers() error {
	// No-op for Docker driver.
	return nil
}

func (self *dockerContainerHandler) Exists() bool {
	return containerlibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id)
}

func DockerInfo() (map[string]string, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	info, err := client.Info()
	if err != nil {
		return nil, err
	}
	return info.Map(), nil
}

func DockerImages() ([]docker.APIImages, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	images, err := client.ListImages(docker.ListImagesOptions{All: false})
	if err != nil {
		return nil, err
	}
	return images, nil
}
<commit_msg>Set spec.hasFilesystem to true by default for docker containers.<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Handler for Docker containers.
package docker

import (
	"fmt"
	"io/ioutil"
	"math"
	"path"
	"strings"
	"time"

	"github.com/google/cadvisor/container"
	containerlibcontainer "github.com/google/cadvisor/container/libcontainer"
	"github.com/google/cadvisor/fs"
	info "github.com/google/cadvisor/info/v1"
	"github.com/google/cadvisor/utils"

	docker "github.com/fsouza/go-dockerclient"
	"github.com/opencontainers/runc/libcontainer/cgroups"
	cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
	libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)

const (
	// The read write layers exist here.
	aufsRWLayer = "diff"
	// Path to the directory where docker stores log files if the json logging driver is enabled.
	pathToContainersDir = "containers"
)

type dockerContainerHandler struct {
	client             *docker.Client
	name               string
	id                 string
	aliases            []string
	machineInfoFactory info.MachineInfoFactory

	// Absolute path to the cgroup hierarchies of this container.
	// (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test")
	cgroupPaths map[string]string

	// Manager of this container's cgroups.
	cgroupManager cgroups.Manager

	storageDriver    storageDriver
	fsInfo           fs.FsInfo
	rootfsStorageDir string

	// Time at which this container was created.
	creationTime time.Time

	// Metadata associated with the container.
	labels map[string]string
	envs   map[string]string

	// The container PID used to switch namespaces as required
	pid int

	// Image name used for this container.
	image string

	// The host root FS to read
	rootFs string

	// The network mode of the container
	networkMode string

	// Filesystem handler.
	fsHandler fsHandler

	ignoreMetrics container.MetricSet
}

func getRwLayerID(containerID, storageDir string, sd storageDriver, dockerVersion []int) (string, error) {
	const (
		// Docker version >=1.10.0 have a randomized ID for the root fs of a container.
		randomizedRWLayerMinorVersion = 10
		rwLayerIDFile                 = "mount-id"
	)
	if (dockerVersion[0] <= 1) && (dockerVersion[1] < randomizedRWLayerMinorVersion) {
		return containerID, nil
	}

	bytes, err := ioutil.ReadFile(path.Join(storageDir, "image", string(sd), "layerdb", "mounts", containerID, rwLayerIDFile))
	if err != nil {
		return "", fmt.Errorf("failed to identify the read-write layer ID for container %q. - %v", containerID, err)
	}
	return string(bytes), err
}

func newDockerContainerHandler(
	client *docker.Client,
	name string,
	machineInfoFactory info.MachineInfoFactory,
	fsInfo fs.FsInfo,
	storageDriver storageDriver,
	storageDir string,
	cgroupSubsystems *containerlibcontainer.CgroupSubsystems,
	inHostNamespace bool,
	metadataEnvs []string,
	dockerVersion []int,
	ignoreMetrics container.MetricSet,
) (container.ContainerHandler, error) {
	// Create the cgroup paths.
	cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints))
	for key, val := range cgroupSubsystems.MountPoints {
		cgroupPaths[key] = path.Join(val, name)
	}

	// Generate the equivalent cgroup manager for this container.
	cgroupManager := &cgroupfs.Manager{
		Cgroups: &libcontainerconfigs.Cgroup{
			Name: name,
		},
		Paths: cgroupPaths,
	}

	rootFs := "/"
	if !inHostNamespace {
		rootFs = "/rootfs"
		storageDir = path.Join(rootFs, storageDir)
	}

	id := ContainerNameToDockerId(name)

	// Add the Containers dir where the log files are stored.
	// FIXME: Give `otherStorageDir` a more descriptive name.
	otherStorageDir := path.Join(storageDir, pathToContainersDir, id)

	rwLayerID, err := getRwLayerID(id, storageDir, storageDriver, dockerVersion)
	if err != nil {
		return nil, err
	}
	var rootfsStorageDir string
	switch storageDriver {
	case aufsStorageDriver:
		rootfsStorageDir = path.Join(storageDir, string(aufsStorageDriver), aufsRWLayer, rwLayerID)
	case overlayStorageDriver:
		rootfsStorageDir = path.Join(storageDir, string(overlayStorageDriver), rwLayerID)
	}

	handler := &dockerContainerHandler{
		id:                 id,
		client:             client,
		name:               name,
		machineInfoFactory: machineInfoFactory,
		cgroupPaths:        cgroupPaths,
		cgroupManager:      cgroupManager,
		storageDriver:      storageDriver,
		fsInfo:             fsInfo,
		rootFs:             rootFs,
		rootfsStorageDir:   rootfsStorageDir,
		envs:               make(map[string]string),
		ignoreMetrics:      ignoreMetrics,
	}

	if !ignoreMetrics.Has(container.DiskUsageMetrics) {
		handler.fsHandler = newFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo)
	}

	// We assume that if Inspect fails then the container is not known to docker.
	ctnr, err := client.InspectContainer(id)
	if err != nil {
		return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
	}
	handler.creationTime = ctnr.Created
	handler.pid = ctnr.State.Pid

	// Add the name and bare ID as aliases of the container.
	handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id)
	handler.labels = ctnr.Config.Labels
	handler.image = ctnr.Config.Image
	handler.networkMode = ctnr.HostConfig.NetworkMode

	// split env vars to get metadata map.
	for _, exposedEnv := range metadataEnvs {
		for _, envVar := range ctnr.Config.Env {
			splits := strings.SplitN(envVar, "=", 2)
			if splits[0] == exposedEnv {
				handler.envs[strings.ToLower(exposedEnv)] = splits[1]
			}
		}
	}

	return handler, nil
}

func (self *dockerContainerHandler) Start() {
	// Start the filesystem handler.
	if self.fsHandler != nil {
		self.fsHandler.start()
	}
}

func (self *dockerContainerHandler) Cleanup() {
	if self.fsHandler != nil {
		self.fsHandler.stop()
	}
}

func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
	return info.ContainerReference{
		Id:        self.id,
		Name:      self.name,
		Aliases:   self.aliases,
		Namespace: DockerNamespace,
		Labels:    self.labels,
	}, nil
}

func (self *dockerContainerHandler) readLibcontainerConfig() (*libcontainerconfigs.Config, error) {
	config, err := containerlibcontainer.ReadConfig(*dockerRootDir, *dockerRunDir, self.id)
	if err != nil {
		return nil, fmt.Errorf("failed to read libcontainer config: %v", err)
	}

	// Replace cgroup parent and name with our own since we may be running in a different context.
	if config.Cgroups == nil {
		config.Cgroups = new(libcontainerconfigs.Cgroup)
	}
	config.Cgroups.Name = self.name
	config.Cgroups.Parent = "/"

	return config, nil
}

func libcontainerConfigToContainerSpec(config *libcontainerconfigs.Config, mi *info.MachineInfo) info.ContainerSpec {
	var spec info.ContainerSpec
	spec.HasMemory = true
	spec.Memory.Limit = math.MaxUint64
	spec.Memory.SwapLimit = math.MaxUint64

	if config.Cgroups.Resources != nil {
		if config.Cgroups.Resources.Memory > 0 {
			spec.Memory.Limit = uint64(config.Cgroups.Resources.Memory)
		}
		if config.Cgroups.Resources.MemorySwap > 0 {
			spec.Memory.SwapLimit = uint64(config.Cgroups.Resources.MemorySwap)
		}

		// Get CPU info
		spec.HasCpu = true
		spec.Cpu.Limit = 1024
		if config.Cgroups.Resources.CpuShares != 0 {
			spec.Cpu.Limit = uint64(config.Cgroups.Resources.CpuShares)
		}
		spec.Cpu.Mask = utils.FixCpuMask(config.Cgroups.Resources.CpusetCpus, mi.NumCores)
	}

	spec.HasDiskIo = true

	return spec
}

func (self *dockerContainerHandler) needNet() bool {
	if !self.ignoreMetrics.Has(container.NetworkUsageMetrics) {
		return !strings.HasPrefix(self.networkMode, "container:")
	}
	return false
}

func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return info.ContainerSpec{}, err
	}
	libcontainerConfig, err := self.readLibcontainerConfig()
	if err != nil {
		return info.ContainerSpec{}, err
	}

	spec := libcontainerConfigToContainerSpec(libcontainerConfig, mi)
	spec.CreationTime = self.creationTime

	if !self.ignoreMetrics.Has(container.DiskUsageMetrics) {
		spec.HasFilesystem = true
	}

	spec.Labels = self.labels
	spec.Envs = self.envs
	spec.Image = self.image
	spec.HasNetwork = self.needNet()

	return spec, err
}

func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error {
	if self.ignoreMetrics.Has(container.DiskUsageMetrics) {
		return nil
	}
	switch self.storageDriver {
	case aufsStorageDriver, overlayStorageDriver, zfsStorageDriver:
	default:
		return nil
	}

	deviceInfo, err := self.fsInfo.GetDirFsDevice(self.rootfsStorageDir)
	if err != nil {
		return err
	}

	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return err
	}
	var (
		limit  uint64
		fsType string
	)

	// Docker does not impose any filesystem limits for containers. So use capacity as limit.
	for _, fs := range mi.Filesystems {
		if fs.Device == deviceInfo.Device {
			limit = fs.Capacity
			fsType = fs.Type
			break
		}
	}

	fsStat := info.FsStats{Device: deviceInfo.Device, Type: fsType, Limit: limit}

	fsStat.BaseUsage, fsStat.Usage = self.fsHandler.usage()
	stats.Filesystem = append(stats.Filesystem, fsStat)

	return nil
}

// TODO(vmarmol): Get from libcontainer API instead of cgroup manager when we don't have to support older Dockers.
func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
	stats, err := containerlibcontainer.GetStats(self.cgroupManager, self.rootFs, self.pid, self.ignoreMetrics)
	if err != nil {
		return stats, err
	}
	// Clean up stats for containers that don't have their own network - this
	// includes containers running in Kubernetes pods that use the network of the
	// infrastructure container. This stops metrics being reported multiple times
	// for each container in a pod.
	if !self.needNet() {
		stats.Network = info.NetworkStats{}
	}

	// Get filesystem stats.
	err = self.getFsStats(stats)
	if err != nil {
		return stats, err
	}

	return stats, nil
}

func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
	// No-op for Docker driver.
	return []info.ContainerReference{}, nil
}

func (self *dockerContainerHandler) GetCgroupPath(resource string) (string, error) {
	path, ok := self.cgroupPaths[resource]
	if !ok {
		return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name)
	}
	return path, nil
}

func (self *dockerContainerHandler) ListThreads(listType container.ListType) ([]int, error) {
	// TODO(vmarmol): Implement.
	return nil, nil
}

func (self *dockerContainerHandler) GetContainerLabels() map[string]string {
	return self.labels
}

func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
	return containerlibcontainer.GetProcesses(self.cgroupManager)
}

func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error {
	return fmt.Errorf("watch is unimplemented in the Docker container driver")
}

func (self *dockerContainerHandler) StopWatchingSubcontainers() error {
	// No-op for Docker driver.
	return nil
}

func (self *dockerContainerHandler) Exists() bool {
	return containerlibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id)
}

func DockerInfo() (map[string]string, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	info, err := client.Info()
	if err != nil {
		return nil, err
	}
	return info.Map(), nil
}

func DockerImages() ([]docker.APIImages, error) {
	client, err := Client()
	if err != nil {
		return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	images, err := client.ListImages(docker.ListImagesOptions{All: false})
	if err != nil {
		return nil, err
	}
	return images, nil
}
<|endoftext|>


<commit_before>package container_daemon

import (
	"fmt"
	"io"
	"os"

	"io/ioutil"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/garden-linux/container_daemon/unix_socket"
	"github.com/cloudfoundry-incubator/garden-linux/containerizer/system"
	"github.com/docker/docker/pkg/term"
)

const UnknownExitStatus = 255

type Process struct {
	Connector  Connector
	Term       system.Term
	SigwinchCh <-chan os.Signal
	Spec       *garden.ProcessSpec
	Pidfile    PidfileWriter
	IO         *garden.ProcessIO

	// assigned after Start() is called
	pid      int
	state    *term.State
	exitCode <-chan int
}

type PidfileWriter interface {
	Write(pid int) error
	Remove()
}

//go:generate counterfeiter -o fake_connector/FakeConnector.go . Connector
type Connector interface {
	Connect(msg interface{}) ([]unix_socket.Fd, int, error)
}

func (p *Process) Start() error {
	fds, pid, err := p.Connector.Connect(p.Spec)
	if err != nil {
		return fmt.Errorf("container_daemon: connect to socket: %s", err)
	}

	if err := p.Pidfile.Write(pid); err != nil {
		return fmt.Errorf("container_daemon: write pidfile: %s", err)
	}

	if p.Spec.TTY != nil {
		p.setupPty(fds[0])
		fwdOverPty(fds[0], p.IO)
		p.exitCode = waitForExit(fds[1])
	} else {
		fwdNoninteractive(fds[0], fds[1], fds[2], p.IO)
		p.exitCode = waitForExit(fds[3])
	}

	return nil
}

func (p *Process) setupPty(ptyFd unix_socket.Fd) error {
	p.state, _ = p.Term.SetRawTerminal(os.Stdin.Fd())

	go p.sigwinchLoop(ptyFd)
	return p.syncWindowSize(ptyFd)
}

func (p *Process) sigwinchLoop(ptyFd unix_socket.Fd) {
	for {
		select {
		case <-p.SigwinchCh:
			p.syncWindowSize(ptyFd)
		}
	}
}

func (p *Process) syncWindowSize(ptyFd unix_socket.Fd) error {
	winsize, _ := p.Term.GetWinsize(os.Stdin.Fd())
	return p.Term.SetWinsize(ptyFd.Fd(), winsize)
}

func fwdOverPty(ptyFd io.ReadWriteCloser, processIO *garden.ProcessIO) {
	if processIO == nil {
		return
	}

	if processIO.Stdout != nil {
		go io.Copy(processIO.Stdout, ptyFd)
	}

	if processIO.Stdin != nil {
		go io.Copy(ptyFd, processIO.Stdin)
	}
}

func fwdNoninteractive(stdinFd, stdoutFd, stderrFd io.ReadWriteCloser, processIO *garden.ProcessIO) {
	if processIO != nil && processIO.Stdin != nil {
		go copyAndClose(stdinFd, processIO.Stdin) // Ignore error
		//		go diagnosticCopyAndClose(stdinFd, processIO.Stdin) // Ignore error
	}

	if processIO != nil && processIO.Stdout != nil {
		go io.Copy(processIO.Stdout, stdoutFd) // Ignore error
	}

	if processIO != nil && processIO.Stderr != nil {
		//		go io.Copy(processIO.Stderr, stderrFd)       // Ignore error
		go copyWithClose(processIO.Stderr, stderrFd) // Ignore error
		//		go diagnosticCopy(processIO.Stderr, stderrFd, "stderr-diagnosticCopyLog") // Ignore error
	}
}

func copyAndClose(dst io.WriteCloser, src io.Reader) error {
	_, err := io.Copy(dst, src)
	dst.Close() // Ignore error
	return err
}

func copyWithClose(dst io.Writer, src io.Reader) error {
	_, err := io.Copy(dst, src)
	if wc, ok := dst.(io.WriteCloser); ok {
		return wc.Close()
	}
	return err
}

func diagnosticCopyAndClose(dst io.WriteCloser, src io.Reader) error {
	err := diagnosticCopy(dst, src, "stdin-diagnosticCopyLog")
	dst.Close() // Ignore error
	return err
}

func diagnosticCopy(dst io.Writer, src io.Reader, logFileName string) error {
	log, oe := ioutil.TempFile("/tmp", logFileName)
	if oe != nil {
		return oe
	}
	defer log.Close()

	var err error = nil
	buf := make([]byte, 32*1024)
	for {
		nr, er := src.Read(buf)
		fmt.Fprintln(log, `!!!!! diagnosticCopy received "`, string(buf[0:nr]), `"`)
		if nr > 0 {
			nw, ew := dst.Write(buf[0:nr])
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return err
}

func (p *Process) Cleanup() {
	if p.state != nil {
		p.Term.RestoreTerminal(os.Stdin.Fd(), p.state)
	}
}

func (p *Process) Wait() (int, error) {
	defer p.Pidfile.Remove()

	return <-p.exitCode, nil
}

func waitForExit(exitFd io.ReadWriteCloser) chan int {
	exitChan := make(chan int)
	go func(exitFd io.Reader, exitChan chan<- int) {
		b := make([]byte, 1)
		n, err := exitFd.Read(b)
		if n == 0 && err != nil {
			b[0] = UnknownExitStatus
		}

		exitChan <- int(b[0])
	}(exitFd, exitChan)

	return exitChan
}
<commit_msg>wip fix<commit_after>package container_daemon

import (
	"fmt"
	"io"
	"os"
	"sync"

	"io/ioutil"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/garden-linux/container_daemon/unix_socket"
	"github.com/cloudfoundry-incubator/garden-linux/containerizer/system"
	"github.com/docker/docker/pkg/term"
)

const UnknownExitStatus = 255

type Process struct {
	Connector  Connector
	Term       system.Term
	SigwinchCh <-chan os.Signal
	Spec       *garden.ProcessSpec
	Pidfile    PidfileWriter
	IO         *garden.ProcessIO

	// assigned after Start() is called
	pid       int
	state     *term.State
	exitCode  <-chan int
	streaming *sync.WaitGroup
}

type PidfileWriter interface {
	Write(pid int) error
	Remove()
}

//go:generate counterfeiter -o fake_connector/FakeConnector.go . Connector
type Connector interface {
	Connect(msg interface{}) ([]unix_socket.Fd, int, error)
}

func (p *Process) Start() error {
	fds, pid, err := p.Connector.Connect(p.Spec)
	if err != nil {
		return fmt.Errorf("container_daemon: connect to socket: %s", err)
	}

	if err := p.Pidfile.Write(pid); err != nil {
		return fmt.Errorf("container_daemon: write pidfile: %s", err)
	}

	p.streaming = &sync.WaitGroup{}

	if p.Spec.TTY != nil {
		p.setupPty(fds[0])
		fwdOverPty(fds[0], p.IO, p.streaming)
		p.exitCode = waitForExit(fds[1], p.streaming)
	} else {
		fwdNoninteractive(fds[0], fds[1], fds[2], p.IO, p.streaming)
		p.exitCode = waitForExit(fds[3], p.streaming)
	}

	return nil
}

func (p *Process) setupPty(ptyFd unix_socket.Fd) error {
	p.state, _ = p.Term.SetRawTerminal(os.Stdin.Fd())

	go p.sigwinchLoop(ptyFd)
	return p.syncWindowSize(ptyFd)
}

func (p *Process) sigwinchLoop(ptyFd unix_socket.Fd) {
	for {
		select {
		case <-p.SigwinchCh:
			p.syncWindowSize(ptyFd)
		}
	}
}

func (p *Process) syncWindowSize(ptyFd unix_socket.Fd) error {
	winsize, _ := p.Term.GetWinsize(os.Stdin.Fd())
	return p.Term.SetWinsize(ptyFd.Fd(), winsize)
}

func fwdOverPty(ptyFd io.ReadWriteCloser, processIO *garden.ProcessIO, streaming *sync.WaitGroup) {
	if processIO == nil {
		return
	}

	if processIO.Stdout != nil {
		streaming.Add(1)
		go func() {
			io.Copy(processIO.Stdout, ptyFd)
			streaming.Done()
		}()
	}

	if processIO.Stdin != nil {
		go io.Copy(ptyFd, processIO.Stdin)
	}
}

func fwdNoninteractive(stdinFd, stdoutFd, stderrFd io.ReadWriteCloser, processIO *garden.ProcessIO, streaming *sync.WaitGroup) {
	if processIO != nil && processIO.Stdin != nil {
		go copyAndClose(stdinFd, processIO.Stdin) // Ignore error
		//		go diagnosticCopyAndClose(stdinFd, processIO.Stdin) // Ignore error
	}

	if processIO != nil && processIO.Stdout != nil {
		streaming.Add(1)
		go func() {
			io.Copy(processIO.Stdout, stdoutFd) // Ignore error
			streaming.Done()
		}()
	}

	if processIO != nil && processIO.Stderr != nil {
		streaming.Add(1)
		go func() {
			//		io.Copy(processIO.Stderr, stderrFd)       // Ignore error
			copyWithClose(processIO.Stderr, stderrFd) // Ignore error
			//		diagnosticCopy(processIO.Stderr, stderrFd, "stderr-diagnosticCopyLog") // Ignore error
			streaming.Done()
		}()
	}
}

func copyAndClose(dst io.WriteCloser, src io.Reader) error {
	_, err := io.Copy(dst, src)
	dst.Close() // Ignore error
	return err
}

func copyWithClose(dst io.Writer, src io.Reader) error {
	_, err := io.Copy(dst, src)
	if wc, ok := dst.(io.WriteCloser); ok {
		return wc.Close()
	}
	return err
}

func diagnosticCopyAndClose(dst io.WriteCloser, src io.Reader) error {
	err := diagnosticCopy(dst, src, "stdin-diagnosticCopyLog")
	dst.Close() // Ignore error
	return err
}

func diagnosticCopy(dst io.Writer, src io.Reader, logFileName string) error {
	log, oe := ioutil.TempFile("/tmp", logFileName)
	if oe != nil {
		return oe
	}
	defer log.Close()

	var err error = nil
	buf := make([]byte, 32*1024)
	for {
		nr, er := src.Read(buf)
		fmt.Fprintln(log, `!!!!! diagnosticCopy received "`, string(buf[0:nr]), `"`)
		if nr > 0 {
			nw, ew := dst.Write(buf[0:nr])
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return err
}

func (p *Process) Cleanup() {
	if p.state != nil {
		p.Term.RestoreTerminal(os.Stdin.Fd(), p.state)
	}
}

func (p *Process) Wait() (int, error) {
	defer p.Pidfile.Remove()

	return <-p.exitCode, nil
}

func waitForExit(exitFd io.ReadWriteCloser, streaming *sync.WaitGroup) chan int {
	exitChan := make(chan int)
	go func(exitFd io.Reader, exitChan chan<- int, streaming *sync.WaitGroup) {
		streaming.Wait()
		b := make([]byte, 1)
		n, err := exitFd.Read(b)
		if n == 0 && err != nil {
			b[0] = UnknownExitStatus
		}

		exitChan <- int(b[0])
	}(exitFd, exitChan, streaming)

	return exitChan
}
<|endoftext|>


<commit_before>/*
 * Network packet analysis framework.
 *
 * Copyright (c) 2014, Alessandro Ghedini
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package packet

import "encoding/binary"
import "io"

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// It's based on the bytes.Buffer code provided by the standard library, but
// implements additional convenience methods.
//
// This used internally to provide packet encoding and decoding, and should not
// be used directly.
type Buffer struct {
	buf       []byte
	off       int
	chkoff    int
	bootstrap [64]byte
}

// Initialize the buffer with the given slice.
func (b *Buffer) Init(buf []byte) {
	b.buf = buf
}

// Return the buffer as slice.
func (b *Buffer) Bytes() []byte {
	return b.buf[b.off:]
}

// Return the number of bytes of the unread portion of the buffer.
func (b *Buffer) Len() int {
	return len(b.buf) - b.off
}

// Set the checkpoint to the current buffer offset.
func (b *Buffer) Checkpoint() {
	b.chkoff = b.Len()
}

// Return the buffer starting from the last checkpoint, as slice.
func (b *Buffer) BytesOff() []byte {
	return b.buf[b.chkoff:]
}

// Return the number of bytes of the buffer since the last checkpoint.
func (b *Buffer) LenOff() int {
	return len(b.buf) - b.chkoff
}

// Discard all but the first n unread bytes from the buffer.
func (b *Buffer) Truncate(n int) {
	switch {
	case n < 0 || n > b.Len():
		panic("OOR")

	case n == 0:
		b.off = 0
	}

	b.buf = b.buf[0 : b.off+n]
}

func (b *Buffer) grow(n int) int {
	m := b.Len()

	if m == 0 && b.off != 0 {
		b.Truncate(0)
	}

	if len(b.buf)+n > cap(b.buf) {
		var buf []byte

		if b.buf == nil && n <= len(b.bootstrap) {
			buf = b.bootstrap[0:]
		} else if m+n <= cap(b.buf) / 2 {
			copy(b.buf[:], b.buf[b.off:])
			buf = b.buf[:m]
		} else {
			// not enough space anywhere
			buf = makeSlice(2 * cap(b.buf) + n)
			copy(buf, b.buf[b.off:])
		}

		b.buf = buf
		b.off = 0
	}

	b.buf = b.buf[0 : b.off + m + n]

	return b.off + m
}

// Append the contents of p to the buffer, growing the buffer as needed.
func (b *Buffer) Write(p []byte) (n int, err error) {
	m := b.grow(len(p))
	return copy(b.buf[m:], p), nil
}

// Append the binary representation of data in big endian order to the buffer,
// growing the buffer as needed.
func (b *Buffer) WriteI(data interface{}) error {
	return binary.Write(b, binary.BigEndian, data)
}

func (b *Buffer) PutUint16Off(off int, data uint16) {
	binary.BigEndian.PutUint16(b.buf[b.chkoff + off:], data)
}

func makeSlice(n int) []byte {
	defer func() {
		if recover() != nil {
			panic("OOM")
		}
	}()
	return make([]byte, n)
}

// Read the next len(p) bytes from the buffer or until the buffer is drained.
func (b *Buffer) Read(p []byte) (n int, err error) {
	if b.off >= len(b.buf) {
		b.Truncate(0)
		if len(p) == 0 {
			return
		}
		return 0, io.EOF
	}
	n = copy(p, b.buf[b.off:])
	b.off += n
	return
}

// Read structured big endian binary data from r into data.
func (p *Buffer) ReadI(data interface{}) error {
	return binary.Read(p, binary.BigEndian, data)
}

// Return a slice containing the next n bytes from the buffer, advancing the
// buffer as if the bytes had been returned by Read
func (b *Buffer) Next(n int) []byte {
	m := b.Len()
	if n > m {
		n = m
	}
	data := b.buf[b.off : b.off+n]
	b.off += n
	return data
}
<commit_msg>buffer.go: fix typo<commit_after>/*
 * Network packet analysis framework.
 *
 * Copyright (c) 2014, Alessandro Ghedini
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package packet

import "encoding/binary"
import "io"

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// It's based on the bytes.Buffer code provided by the standard library, but
// implements additional convenience methods.
//
// This is used internally to provide packet encoding and decoding, and should
// not be used directly.
type Buffer struct {
	buf       []byte
	off       int
	chkoff    int
	bootstrap [64]byte
}

// Initialize the buffer with the given slice.
func (b *Buffer) Init(buf []byte) {
	b.buf = buf
}

// Return the buffer as slice.
func (b *Buffer) Bytes() []byte {
	return b.buf[b.off:]
}

// Return the number of bytes of the unread portion of the buffer.
func (b *Buffer) Len() int {
	return len(b.buf) - b.off
}

// Set the checkpoint to the current buffer offset.
func (b *Buffer) Checkpoint() {
	b.chkoff = b.Len()
}

// Return the buffer starting from the last checkpoint, as slice.
func (b *Buffer) BytesOff() []byte {
	return b.buf[b.chkoff:]
}

// Return the number of bytes of the buffer since the last checkpoint.
func (b *Buffer) LenOff() int {
	return len(b.buf) - b.chkoff
}

// Discard all but the first n unread bytes from the buffer.
func (b *Buffer) Truncate(n int) {
	switch {
	case n < 0 || n > b.Len():
		panic("OOR")

	case n == 0:
		b.off = 0
	}

	b.buf = b.buf[0 : b.off+n]
}

func (b *Buffer) grow(n int) int {
	m := b.Len()

	if m == 0 && b.off != 0 {
		b.Truncate(0)
	}

	if len(b.buf)+n > cap(b.buf) {
		var buf []byte

		if b.buf == nil && n <= len(b.bootstrap) {
			buf = b.bootstrap[0:]
		} else if m+n <= cap(b.buf) / 2 {
			copy(b.buf[:], b.buf[b.off:])
			buf = b.buf[:m]
		} else {
			// not enough space anywhere
			buf = makeSlice(2 * cap(b.buf) + n)
			copy(buf, b.buf[b.off:])
		}

		b.buf = buf
		b.off = 0
	}

	b.buf = b.buf[0 : b.off + m + n]

	return b.off + m
}

// Append the contents of p to the buffer, growing the buffer as needed.
func (b *Buffer) Write(p []byte) (n int, err error) {
	m := b.grow(len(p))
	return copy(b.buf[m:], p), nil
}

// Append the binary representation of data in big endian order to the buffer,
// growing the buffer as needed.
func (b *Buffer) WriteI(data interface{}) error {
	return binary.Write(b, binary.BigEndian, data)
}

func (b *Buffer) PutUint16Off(off int, data uint16) {
	binary.BigEndian.PutUint16(b.buf[b.chkoff + off:], data)
}

func makeSlice(n int) []byte {
	defer func() {
		if recover() != nil {
			panic("OOM")
		}
	}()
	return make([]byte, n)
}

// Read the next len(p) bytes from the buffer or until the buffer is drained.
func (b *Buffer) Read(p []byte) (n int, err error) {
	if b.off >= len(b.buf) {
		b.Truncate(0)
		if len(p) == 0 {
			return
		}
		return 0, io.EOF
	}
	n = copy(p, b.buf[b.off:])
	b.off += n
	return
}

// Read structured big endian binary data from r into data.
func (p *Buffer) ReadI(data interface{}) error {
	return binary.Read(p, binary.BigEndian, data)
}

// Return a slice containing the next n bytes from the buffer, advancing the
// buffer as if the bytes had been returned by Read
func (b *Buffer) Next(n int) []byte {
	m := b.Len()
	if n > m {
		n = m
	}
	data := b.buf[b.off : b.off+n]
	b.off += n
	return data
}
<|endoftext|>