<commit_before>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Plan 9 directory marshalling. See intro(5).

package syscall

import "errors"

var (
	ErrShortStat = errors.New("stat buffer too short")
	ErrBadStat   = errors.New("malformed stat buffer")
)

// A Qid represents a 9P server's unique identification for a file.
type Qid struct {
	Path uint64 // the file server's unique identification for the file
	Vers uint32 // version number for given Path
	Type uint8  // the type of the file (syscall.QTDIR for example)
}

// A Dir contains the metadata for a file.
type Dir struct {
	// system-modified data
	Type uint16 // server type
	Dev  uint32 // server subtype

	// file data
	Qid    Qid    // unique id from server
	Mode   uint32 // permissions
	Atime  uint32 // last read time
	Mtime  uint32 // last write time
	Length int64  // file length
	Name   string // last element of path
	Uid    string // owner name
	Gid    string // group name
	Muid   string // last modifier name
}

var nullDir = Dir{
	Type: ^uint16(0),
	Dev:  ^uint32(0),
	Qid: Qid{
		Path: ^uint64(0),
		Vers: ^uint32(0),
		Type: ^uint8(0),
	},
	Mode:   ^uint32(0),
	Atime:  ^uint32(0),
	Mtime:  ^uint32(0),
	Length: ^int64(0),
}

// Null assigns special "don't touch" values to members of d to
// avoid modifiying them during syscall.Wstat.
func (d *Dir) Null() { *d = nullDir }

// Marshal encodes a 9P stat message corresponding to d into b
//
// If there isn't enough space in b for a stat message, ErrShortStat is returned.
func (d *Dir) Marshal(b []byte) (n int, err error) {
	n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
	if n > len(b) {
		return n, ErrShortStat
	}

	b = pbit16(b, uint16(n)-2)
	b = pbit16(b, d.Type)
	b = pbit32(b, d.Dev)
	b = pbit8(b, d.Qid.Type)
	b = pbit32(b, d.Qid.Vers)
	b = pbit64(b, d.Qid.Path)
	b = pbit32(b, d.Mode)
	b = pbit32(b, d.Atime)
	b = pbit32(b, d.Mtime)
	b = pbit64(b, uint64(d.Length))
	b = pstring(b, d.Name)
	b = pstring(b, d.Uid)
	b = pstring(b, d.Gid)
	b = pstring(b, d.Muid)

	return n, nil
}

// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
//
// If b is too small to hold a valid stat message, ErrShortStat is returned.
//
// If the stat message itself is invalid, ErrBadStat is returned.
func UnmarshalDir(b []byte) (*Dir, error) {
	if len(b) < STATFIXLEN {
		return nil, ErrShortStat
	}
	size, buf := gbit16(b)
	if len(b) != int(size)+2 {
		return nil, ErrBadStat
	}
	b = buf

	var d Dir
	d.Type, b = gbit16(b)
	d.Dev, b = gbit32(b)
	d.Qid.Type, b = gbit8(b)
	d.Qid.Vers, b = gbit32(b)
	d.Qid.Path, b = gbit64(b)
	d.Mode, b = gbit32(b)
	d.Atime, b = gbit32(b)
	d.Mtime, b = gbit32(b)

	n, b := gbit64(b)
	d.Length = int64(n)

	var ok bool
	if d.Name, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}
	if d.Uid, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}
	if d.Gid, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}
	if d.Muid, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}

	return &d, nil
}

// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
func pbit8(b []byte, v uint8) []byte {
	b[0] = byte(v)
	return b[1:]
}

// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit16(b []byte, v uint16) []byte {
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	return b[2:]
}

// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit32(b []byte, v uint32) []byte {
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
	return b[4:]
}

// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit64(b []byte, v uint64) []byte {
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
	b[4] = byte(v >> 32)
	b[5] = byte(v >> 40)
	b[6] = byte(v >> 48)
	b[7] = byte(v >> 56)
	return b[8:]
}

// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
// returning the remaining slice of b..
func pstring(b []byte, s string) []byte {
	b = pbit16(b, uint16(len(s)))
	n := copy(b, s)
	return b[n:]
}

// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
func gbit8(b []byte) (uint8, []byte) {
	return uint8(b[0]), b[1:]
}

// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit16(b []byte) (uint16, []byte) {
	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
}

// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit32(b []byte) (uint32, []byte) {
	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
}

// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit64(b []byte) (uint64, []byte) {
	lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
	hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
	return uint64(lo) | uint64(hi)<<32, b[8:]
}

// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
// It returns the string with the remaining slice of b and a boolean. If the length is
// greater than the number of bytes in b, the boolean will be false.
func gstring(b []byte) (string, []byte, bool) {
	n, b := gbit16(b)
	if int(n) > len(b) {
		return "", b, false
	}
	return string(b[:n]), b[n:], true
}
<commit_msg>syscall: disallow slashes in file names on Plan 9<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Plan 9 directory marshalling. See intro(5).

package syscall

import "errors"

var (
	ErrShortStat = errors.New("stat buffer too short")
	ErrBadStat   = errors.New("malformed stat buffer")
	ErrBadName   = errors.New("bad character in file name")
)

// A Qid represents a 9P server's unique identification for a file.
type Qid struct {
	Path uint64 // the file server's unique identification for the file
	Vers uint32 // version number for given Path
	Type uint8  // the type of the file (syscall.QTDIR for example)
}

// A Dir contains the metadata for a file.
type Dir struct {
	// system-modified data
	Type uint16 // server type
	Dev  uint32 // server subtype

	// file data
	Qid    Qid    // unique id from server
	Mode   uint32 // permissions
	Atime  uint32 // last read time
	Mtime  uint32 // last write time
	Length int64  // file length
	Name   string // last element of path
	Uid    string // owner name
	Gid    string // group name
	Muid   string // last modifier name
}

var nullDir = Dir{
	Type: ^uint16(0),
	Dev:  ^uint32(0),
	Qid: Qid{
		Path: ^uint64(0),
		Vers: ^uint32(0),
		Type: ^uint8(0),
	},
	Mode:   ^uint32(0),
	Atime:  ^uint32(0),
	Mtime:  ^uint32(0),
	Length: ^int64(0),
}

// Null assigns special "don't touch" values to members of d to
// avoid modifiying them during syscall.Wstat.
func (d *Dir) Null() { *d = nullDir }

// Marshal encodes a 9P stat message corresponding to d into b
//
// If there isn't enough space in b for a stat message, ErrShortStat is returned.
func (d *Dir) Marshal(b []byte) (n int, err error) {
	n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
	if n > len(b) {
		return n, ErrShortStat
	}

	for _, c := range d.Name {
		if c == '/' {
			return n, ErrBadName
		}
	}

	b = pbit16(b, uint16(n)-2)
	b = pbit16(b, d.Type)
	b = pbit32(b, d.Dev)
	b = pbit8(b, d.Qid.Type)
	b = pbit32(b, d.Qid.Vers)
	b = pbit64(b, d.Qid.Path)
	b = pbit32(b, d.Mode)
	b = pbit32(b, d.Atime)
	b = pbit32(b, d.Mtime)
	b = pbit64(b, uint64(d.Length))
	b = pstring(b, d.Name)
	b = pstring(b, d.Uid)
	b = pstring(b, d.Gid)
	b = pstring(b, d.Muid)

	return n, nil
}

// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
//
// If b is too small to hold a valid stat message, ErrShortStat is returned.
//
// If the stat message itself is invalid, ErrBadStat is returned.
func UnmarshalDir(b []byte) (*Dir, error) {
	if len(b) < STATFIXLEN {
		return nil, ErrShortStat
	}
	size, buf := gbit16(b)
	if len(b) != int(size)+2 {
		return nil, ErrBadStat
	}
	b = buf

	var d Dir
	d.Type, b = gbit16(b)
	d.Dev, b = gbit32(b)
	d.Qid.Type, b = gbit8(b)
	d.Qid.Vers, b = gbit32(b)
	d.Qid.Path, b = gbit64(b)
	d.Mode, b = gbit32(b)
	d.Atime, b = gbit32(b)
	d.Mtime, b = gbit32(b)

	n, b := gbit64(b)
	d.Length = int64(n)

	var ok bool
	if d.Name, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}
	if d.Uid, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}
	if d.Gid, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}
	if d.Muid, b, ok = gstring(b); !ok {
		return nil, ErrBadStat
	}

	return &d, nil
}

// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
func pbit8(b []byte, v uint8) []byte {
	b[0] = byte(v)
	return b[1:]
}

// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit16(b []byte, v uint16) []byte {
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	return b[2:]
}

// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit32(b []byte, v uint32) []byte {
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
	return b[4:]
}

// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit64(b []byte, v uint64) []byte {
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
	b[4] = byte(v >> 32)
	b[5] = byte(v >> 40)
	b[6] = byte(v >> 48)
	b[7] = byte(v >> 56)
	return b[8:]
}

// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
// returning the remaining slice of b..
func pstring(b []byte, s string) []byte {
	b = pbit16(b, uint16(len(s)))
	n := copy(b, s)
	return b[n:]
}

// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
func gbit8(b []byte) (uint8, []byte) {
	return uint8(b[0]), b[1:]
}

// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit16(b []byte) (uint16, []byte) {
	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
}

// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit32(b []byte) (uint32, []byte) {
	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
}

// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit64(b []byte) (uint64, []byte) {
	lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
	hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
	return uint64(lo) | uint64(hi)<<32, b[8:]
}

// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
// It returns the string with the remaining slice of b and a boolean. If the length is
// greater than the number of bytes in b, the boolean will be false.
func gstring(b []byte) (string, []byte, bool) {
	n, b := gbit16(b)
	if int(n) > len(b) {
		return "", b, false
	}
	return string(b[:n]), b[n:], true
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Plan 9 environment variables.

package syscall

import (
	"errors"
	"sync"
)

var (
	// envOnce guards initialization by copyenv, which populates env.
	envOnce sync.Once

	// envLock guards env.
	envLock sync.RWMutex

	// env maps from an environment variable to its value.
	env map[string]string
)

func readenv(key string) (string, error) {
	fd, err := Open("/env/"+key, O_RDONLY)
	if err != nil {
		return "", err
	}
	defer Close(fd)
	l, _ := Seek(fd, 0, 2)
	Seek(fd, 0, 0)
	buf := make([]byte, l)
	n, err := Read(fd, buf)
	if err != nil {
		return "", err
	}
	if n > 0 && buf[n-1] == 0 {
		buf = buf[:n-1]
	}
	return string(buf), nil
}

func writeenv(key, value string) error {
	fd, err := Create("/env/"+key, O_RDWR, 0666)
	if err != nil {
		return err
	}
	defer Close(fd)
	_, err = Write(fd, []byte(value))
	return err
}

func copyenv() {
	env = make(map[string]string)
	fd, err := Open("/env", O_RDONLY)
	if err != nil {
		return
	}
	defer Close(fd)
	files, err := readdirnames(fd)
	if err != nil {
		return
	}
	for _, key := range files {
		v, err := readenv(key)
		if err != nil {
			continue
		}
		env[key] = v
	}
}

func Getenv(key string) (value string, found bool) {
	envOnce.Do(copyenv)
	if len(key) == 0 {
		return "", false
	}

	envLock.RLock()
	defer envLock.RUnlock()

	v, ok := env[key]
	if !ok {
		return "", false
	}
	return v, true
}

func Setenv(key, value string) error {
	envOnce.Do(copyenv)
	if len(key) == 0 {
		return errors.New("zero length key")
	}

	envLock.Lock()
	defer envLock.Unlock()

	err := writeenv(key, value)
	if err != nil {
		return err
	}
	env[key] = value
	return nil
}

func Clearenv() {
	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv

	envLock.Lock()
	defer envLock.Unlock()

	env = make(map[string]string)
	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
}

func Environ() []string {
	envOnce.Do(copyenv)
	envLock.RLock()
	defer envLock.RUnlock()
	a := make([]string, len(env))
	i := 0
	for k, v := range env {
		a[i] = k + "=" + v
		i++
	}
	return a
}
<commit_msg>syscall: lazily populate the environment cache on Plan 9<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Plan 9 environment variables.

package syscall

import (
	"errors"
	"sync"
)

var (
	// envOnce guards copyenv, which populates env.
	envOnce sync.Once

	// envLock guards env.
	envLock sync.RWMutex

	// env maps from an environment variable to its value.
	env = make(map[string]string)

	errZeroLengthKey = errors.New("zero length key")
	errShortWrite    = errors.New("i/o count too small")
)

func readenv(key string) (string, error) {
	fd, err := Open("/env/"+key, O_RDONLY)
	if err != nil {
		return "", err
	}
	defer Close(fd)
	l, _ := Seek(fd, 0, 2)
	Seek(fd, 0, 0)
	buf := make([]byte, l)
	n, err := Read(fd, buf)
	if err != nil {
		return "", err
	}
	if n > 0 && buf[n-1] == 0 {
		buf = buf[:n-1]
	}
	return string(buf), nil
}

func writeenv(key, value string) error {
	fd, err := Create("/env/"+key, O_RDWR, 0666)
	if err != nil {
		return err
	}
	defer Close(fd)
	b := []byte(value)
	n, err := Write(fd, b)
	if err != nil {
		return err
	}
	if n != len(b) {
		return errShortWrite
	}
	return nil
}

func copyenv() {
	fd, err := Open("/env", O_RDONLY)
	if err != nil {
		return
	}
	defer Close(fd)
	files, err := readdirnames(fd)
	if err != nil {
		return
	}
	for _, key := range files {
		v, err := readenv(key)
		if err != nil {
			continue
		}
		env[key] = v
	}
}

func Getenv(key string) (value string, found bool) {
	if len(key) == 0 {
		return "", false
	}

	envLock.RLock()
	defer envLock.RUnlock()

	if v, ok := env[key]; ok {
		return v, true
	}
	v, err := readenv(key)
	if err != nil {
		return "", false
	}
	env[key] = v
	return v, true
}

func Setenv(key, value string) error {
	if len(key) == 0 {
		return errZeroLengthKey
	}

	envLock.Lock()
	defer envLock.Unlock()

	err := writeenv(key, value)
	if err != nil {
		return err
	}
	env[key] = value
	return nil
}

func Clearenv() {
	envLock.Lock()
	defer envLock.Unlock()

	env = make(map[string]string)
	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
}

func Environ() []string {
	envLock.RLock()
	defer envLock.RUnlock()

	envOnce.Do(copyenv)
	a := make([]string, len(env))
	i := 0
	for k, v := range env {
		a[i] = k + "=" + v
		i++
	}
	return a
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"
)

var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")

// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
type InternalBenchmark struct {
	Name string
	F    func(b *B)
}

// B is a type passed to Benchmark functions to manage benchmark
// timing and to specify the number of iterations to run.
type B struct {
	N         int
	benchmark InternalBenchmark
	ns        int64
	bytes     int64
	start     int64
}

// StartTimer starts timing a test.  This function is called automatically
// before a benchmark starts, but it can also used to resume timing after
// a call to StopTimer.
func (b *B) StartTimer() { b.start = time.Nanoseconds() }

// StopTimer stops timing a test.  This can be used to pause the timer
// while performing complex initialization that you don't
// want to measure.
func (b *B) StopTimer() {
	if b.start > 0 {
		b.ns += time.Nanoseconds() - b.start
	}
	b.start = 0
}

// ResetTimer stops the timer and sets the elapsed benchmark time to zero.
func (b *B) ResetTimer() {
	b.start = 0
	b.ns = 0
}

// SetBytes records the number of bytes processed in a single operation.
// If this is called, the benchmark will report ns/op and MB/s.
func (b *B) SetBytes(n int64) { b.bytes = n }

func (b *B) nsPerOp() int64 {
	if b.N <= 0 {
		return 0
	}
	return b.ns / int64(b.N)
}

// runN runs a single benchmark for the specified number of iterations.
func (b *B) runN(n int) {
	// Try to get a comparable environment for each run
	// by clearing garbage from previous runs.
	runtime.GC()
	b.N = n
	b.ResetTimer()
	b.StartTimer()
	b.benchmark.F(b)
	b.StopTimer()
}

func min(x, y int) int {
	if x > y {
		return y
	}
	return x
}

func max(x, y int) int {
	if x < y {
		return y
	}
	return x
}

// roundDown10 rounds a number down to the nearest power of 10.
func roundDown10(n int) int {
	var tens = 0
	// tens = floor(log_10(n))
	for n > 10 {
		n = n / 10
		tens++
	}
	// result = 10^tens
	result := 1
	for i := 0; i < tens; i++ {
		result *= 10
	}
	return result
}

// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
func roundUp(n int) int {
	base := roundDown10(n)
	if n < (2 * base) {
		return 2 * base
	}
	if n < (5 * base) {
		return 5 * base
	}
	return 10 * base
}

// run times the benchmark function.  It gradually increases the number
// of benchmark iterations until the benchmark runs for a second in order
// to get a reasonable measurement.  It prints timing information in this form
//		testing.BenchmarkHello	100000		19 ns/op
func (b *B) run() BenchmarkResult {
	// Run the benchmark for a single iteration in case it's expensive.
	n := 1
	b.runN(n)
	// Run the benchmark for at least the specified amount of time.
	time := int64(*benchTime * 1e9)
	for b.ns < time && n < 1e9 {
		last := n
		// Predict iterations/sec.
		if b.nsPerOp() == 0 {
			n = 1e9
		} else {
			n = int(time / b.nsPerOp())
		}
		// Run more iterations than we think we'll need for a second (1.5x).
		// Don't grow too fast in case we had timing errors previously.
		// Be sure to run at least one more than last time.
		n = max(min(n+n/2, 100*last), last+1)
		// Round up to something easy to read.
		n = roundUp(n)
		b.runN(n)
	}
	return BenchmarkResult{b.N, b.ns, b.bytes}
}

// The results of a benchmark run.
type BenchmarkResult struct {
	N     int   // The number of iterations.
	Ns    int64 // The total time taken.
	Bytes int64 // Bytes processed in one iteration.
}

func (r BenchmarkResult) NsPerOp() int64 {
	if r.N <= 0 {
		return 0
	}
	return r.Ns / int64(r.N)
}

func (r BenchmarkResult) mbPerSec() float64 {
	if r.Bytes <= 0 || r.Ns <= 0 || r.N <= 0 {
		return 0
	}
	return float64(r.Bytes) * float64(r.N) / float64(r.Ns) * 1e3
}

func (r BenchmarkResult) String() string {
	mbs := r.mbPerSec()
	mb := ""
	if mbs != 0 {
		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
	}
	nsop := r.NsPerOp()
	ns := fmt.Sprintf("%10d ns/op", nsop)
	if r.N > 0 && nsop < 100 {
		// The format specifiers here make sure that
		// the ones digits line up for all three possible formats.
		if nsop < 10 {
			ns = fmt.Sprintf("%13.2f ns/op", float64(r.Ns)/float64(r.N))
		} else {
			ns = fmt.Sprintf("%12.1f ns/op", float64(r.Ns)/float64(r.N))
		}
	}
	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
}

// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmarks []InternalBenchmark) {
	// If no flag was specified, don't run benchmarks.
	if len(*matchBenchmarks) == 0 {
		return
	}
	for _, Benchmark := range benchmarks {
		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
		if err != nil {
			println("invalid regexp for -test.bench:", err.String())
			os.Exit(1)
		}
		if !matched {
			continue
		}
		for _, procs := range cpuList {
			runtime.GOMAXPROCS(procs)
			b := &B{benchmark: Benchmark}
			r := b.run()
			benchName := Benchmark.Name
			if procs != 1 {
				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
			}
			print(fmt.Sprintf("%s\t%v\n", benchName, r))
			if p := runtime.GOMAXPROCS(-1); p != procs {
				print(fmt.Sprintf("%s left GOMAXPROCS set to %d\n", benchName, p))
			}
		}
	}
}

// Benchmark benchmarks a single function. Useful for creating
// custom benchmarks that do not use gotest.
func Benchmark(f func(b *B)) BenchmarkResult {
	b := &B{benchmark: InternalBenchmark{"", f}}
	return b.run()
}
<commit_msg>testing: make ResetTimer not start/stop the timer<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"
)

var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")

// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
type InternalBenchmark struct {
	Name string
	F    func(b *B)
}

// B is a type passed to Benchmark functions to manage benchmark
// timing and to specify the number of iterations to run.
type B struct {
	N         int
	benchmark InternalBenchmark
	ns        int64
	bytes     int64
	start     int64
}

// StartTimer starts timing a test.  This function is called automatically
// before a benchmark starts, but it can also used to resume timing after
// a call to StopTimer.
func (b *B) StartTimer() {
	if b.start == 0 {
		b.start = time.Nanoseconds()
	}
}

// StopTimer stops timing a test.  This can be used to pause the timer
// while performing complex initialization that you don't
// want to measure.
func (b *B) StopTimer() {
	if b.start > 0 {
		b.ns += time.Nanoseconds() - b.start
	}
	b.start = 0
}

// ResetTimer sets the elapsed benchmark time to zero.
// It does not affect whether the timer is running.
func (b *B) ResetTimer() {
	if b.start > 0 {
		b.start = time.Nanoseconds()
	}
	b.ns = 0
}

// SetBytes records the number of bytes processed in a single operation.
// If this is called, the benchmark will report ns/op and MB/s.
func (b *B) SetBytes(n int64) { b.bytes = n }

func (b *B) nsPerOp() int64 {
	if b.N <= 0 {
		return 0
	}
	return b.ns / int64(b.N)
}

// runN runs a single benchmark for the specified number of iterations.
func (b *B) runN(n int) {
	// Try to get a comparable environment for each run
	// by clearing garbage from previous runs.
	runtime.GC()
	b.N = n
	b.ResetTimer()
	b.StartTimer()
	b.benchmark.F(b)
	b.StopTimer()
}

func min(x, y int) int {
	if x > y {
		return y
	}
	return x
}

func max(x, y int) int {
	if x < y {
		return y
	}
	return x
}

// roundDown10 rounds a number down to the nearest power of 10.
func roundDown10(n int) int {
	var tens = 0
	// tens = floor(log_10(n))
	for n > 10 {
		n = n / 10
		tens++
	}
	// result = 10^tens
	result := 1
	for i := 0; i < tens; i++ {
		result *= 10
	}
	return result
}

// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
func roundUp(n int) int {
	base := roundDown10(n)
	if n < (2 * base) {
		return 2 * base
	}
	if n < (5 * base) {
		return 5 * base
	}
	return 10 * base
}

// run times the benchmark function.  It gradually increases the number
// of benchmark iterations until the benchmark runs for a second in order
// to get a reasonable measurement.  It prints timing information in this form
//		testing.BenchmarkHello	100000		19 ns/op
func (b *B) run() BenchmarkResult {
	// Run the benchmark for a single iteration in case it's expensive.
	n := 1
	b.runN(n)
	// Run the benchmark for at least the specified amount of time.
	time := int64(*benchTime * 1e9)
	for b.ns < time && n < 1e9 {
		last := n
		// Predict iterations/sec.
		if b.nsPerOp() == 0 {
			n = 1e9
		} else {
			n = int(time / b.nsPerOp())
		}
		// Run more iterations than we think we'll need for a second (1.5x).
		// Don't grow too fast in case we had timing errors previously.
		// Be sure to run at least one more than last time.
		n = max(min(n+n/2, 100*last), last+1)
		// Round up to something easy to read.
		n = roundUp(n)
		b.runN(n)
	}
	return BenchmarkResult{b.N, b.ns, b.bytes}
}

// The results of a benchmark run.
type BenchmarkResult struct {
	N     int   // The number of iterations.
	Ns    int64 // The total time taken.
	Bytes int64 // Bytes processed in one iteration.
}

func (r BenchmarkResult) NsPerOp() int64 {
	if r.N <= 0 {
		return 0
	}
	return r.Ns / int64(r.N)
}

func (r BenchmarkResult) mbPerSec() float64 {
	if r.Bytes <= 0 || r.Ns <= 0 || r.N <= 0 {
		return 0
	}
	return float64(r.Bytes) * float64(r.N) / float64(r.Ns) * 1e3
}

func (r BenchmarkResult) String() string {
	mbs := r.mbPerSec()
	mb := ""
	if mbs != 0 {
		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
	}
	nsop := r.NsPerOp()
	ns := fmt.Sprintf("%10d ns/op", nsop)
	if r.N > 0 && nsop < 100 {
		// The format specifiers here make sure that
		// the ones digits line up for all three possible formats.
		if nsop < 10 {
			ns = fmt.Sprintf("%13.2f ns/op", float64(r.Ns)/float64(r.N))
		} else {
			ns = fmt.Sprintf("%12.1f ns/op", float64(r.Ns)/float64(r.N))
		}
	}
	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
}

// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmarks []InternalBenchmark) {
	// If no flag was specified, don't run benchmarks.
	if len(*matchBenchmarks) == 0 {
		return
	}
	for _, Benchmark := range benchmarks {
		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
		if err != nil {
			println("invalid regexp for -test.bench:", err.String())
			os.Exit(1)
		}
		if !matched {
			continue
		}
		for _, procs := range cpuList {
			runtime.GOMAXPROCS(procs)
			b := &B{benchmark: Benchmark}
			r := b.run()
			benchName := Benchmark.Name
			if procs != 1 {
				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
			}
			print(fmt.Sprintf("%s\t%v\n", benchName, r))
			if p := runtime.GOMAXPROCS(-1); p != procs {
				print(fmt.Sprintf("%s left GOMAXPROCS set to %d\n", benchName, p))
			}
		}
	}
}

// Benchmark benchmarks a single function. Useful for creating
// custom benchmarks that do not use gotest.
func Benchmark(f func(b *B)) BenchmarkResult {
	b := &B{benchmark: InternalBenchmark{"", f}}
	return b.run()
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"flag"
	"fmt"
	"os"
	"time"
)

var matchBenchmarks = flag.String("benchmarks", "", "regular expression to select benchmarks to run")

// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
type InternalBenchmark struct {
	Name string
	F    func(b *B)
}

// B is a type passed to Benchmark functions to manage benchmark
// timing and to specify the number of iterations to run.
type B struct {
	N         int
	benchmark InternalBenchmark
	ns        int64
	bytes     int64
	start     int64
}

// StartTimer starts timing a test.  This function is called automatically
// before a benchmark starts, but it can also used to resume timing after
// a call to StopTimer.
func (b *B) StartTimer() { b.start = time.Nanoseconds() }

// StopTimer stops timing a test.  This can be used to pause the timer
// while performing complex initialization that you don't
// want to measure.
func (b *B) StopTimer() {
	if b.start > 0 {
		b.ns += time.Nanoseconds() - b.start
	}
	b.start = 0
}

// ResetTimer stops the timer and sets the elapsed benchmark time to zero.
func (b *B) ResetTimer() {
	b.start = 0
	b.ns = 0
}

// SetBytes records the number of bytes processed in a single operation.
// If this is called, the benchmark will report ns/op and MB/s.
func (b *B) SetBytes(n int64) { b.bytes = n }

func (b *B) nsPerOp() int64 {
	if b.N <= 0 {
		return 0
	}
	return b.ns / int64(b.N)
}

// runN runs a single benchmark for the specified number of iterations.
func (b *B) runN(n int) {
	b.N = n
	b.ResetTimer()
	b.StartTimer()
	b.benchmark.F(b)
	b.StopTimer()
}

func min(x, y int) int {
	if x > y {
		return y
	}
	return x
}

func max(x, y int) int {
	if x < y {
		return y
	}
	return x
}

// roundDown10 rounds a number down to the nearest power of 10.
func roundDown10(n int) int {
	var tens = 0
	// tens = floor(log_10(n))
	for n > 10 {
		n = n / 10
		tens++
	}
	// result = 10^tens
	result := 1
	for i := 0; i < tens; i++ {
		result *= 10
	}
	return result
}

// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
func roundUp(n int) int {
	base := roundDown10(n)
	if n < (2 * base) {
		return 2 * base
	}
	if n < (5 * base) {
		return 5 * base
	}
	return 10 * base
}

// run times the benchmark function.  It gradually increases the number
// of benchmark iterations until the benchmark runs for a second in order
// to get a reasonable measurement.  It prints timing information in this form
//		testing.BenchmarkHello	100000		19 ns/op
func (b *B) run() BenchmarkResult {
	// Run the benchmark for a single iteration in case it's expensive.
	n := 1
	b.runN(n)
	// Run the benchmark for at least a second.
	for b.ns < 1e9 && n < 1e9 {
		last := n
		// Predict iterations/sec.
		if b.nsPerOp() == 0 {
			n = 1e9
		} else {
			n = 1e9 / int(b.nsPerOp())
		}
		// Run more iterations than we think we'll need for a second (1.5x).
		// Don't grow too fast in case we had timing errors previously.
		// Be sure to run at least one more than last time.
		n = max(min(n+n/2, 100*last), last+1)
		// Round up to something easy to read.
		n = roundUp(n)
		b.runN(n)
	}
	return BenchmarkResult{b.N, b.ns, b.bytes}

}

// The results of a benchmark run.
type BenchmarkResult struct {
	N     int   // The number of iterations.
	Ns    int64 // The total time taken.
	Bytes int64 // The total number of bytes processed.
}

func (r BenchmarkResult) NsPerOp() int64 {
	if r.N <= 0 {
		return 0
	}
	return r.Ns / int64(r.N)
}

func (r BenchmarkResult) String() string {
	ns := r.NsPerOp()
	mb := ""
	if ns > 0 && r.Bytes > 0 {
		mb = fmt.Sprintf("\t%7.2f MB/s", (float64(r.Bytes)/1e6)/(float64(ns)/1e9))
	}
	return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, ns, mb)
}

// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmarks []InternalBenchmark) {
	// If no flag was specified, don't run benchmarks.
	if len(*matchBenchmarks) == 0 {
		return
	}
	for _, Benchmark := range benchmarks {
		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
		if err != nil {
			println("invalid regexp for -benchmarks:", err)
			os.Exit(1)
		}
		if !matched {
			continue
		}
		b := &B{benchmark: Benchmark}
		r := b.run()
		fmt.Printf("%s\t%v\n", Benchmark.Name, r)
	}
}

// Benchmark benchmarks a single function. Useful for creating
// custom benchmarks that do not use gotest.
func Benchmark(name string, f func(b *B)) BenchmarkResult {
	b := &B{benchmark: InternalBenchmark{name, f}}
	return b.run()
}
<commit_msg>testing: delete redundant name argument to Benchmark(). [it was a carry over from the previous iteration]<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"flag"
	"fmt"
	"os"
	"time"
)

var matchBenchmarks = flag.String("benchmarks", "", "regular expression to select benchmarks to run")

// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
type InternalBenchmark struct {
	Name string
	F    func(b *B)
}

// B is a type passed to Benchmark functions to manage benchmark
// timing and to specify the number of iterations to run.
type B struct {
	N         int
	benchmark InternalBenchmark
	ns        int64
	bytes     int64
	start     int64
}

// StartTimer starts timing a test.  This function is called automatically
// before a benchmark starts, but it can also used to resume timing after
// a call to StopTimer.
func (b *B) StartTimer() { b.start = time.Nanoseconds() }

// StopTimer stops timing a test.  This can be used to pause the timer
// while performing complex initialization that you don't
// want to measure.
func (b *B) StopTimer() {
	if b.start > 0 {
		b.ns += time.Nanoseconds() - b.start
	}
	b.start = 0
}

// ResetTimer stops the timer and sets the elapsed benchmark time to zero.
func (b *B) ResetTimer() {
	b.start = 0
	b.ns = 0
}

// SetBytes records the number of bytes processed in a single operation.
// If this is called, the benchmark will report ns/op and MB/s.
func (b *B) SetBytes(n int64) { b.bytes = n }

func (b *B) nsPerOp() int64 {
	if b.N <= 0 {
		return 0
	}
	return b.ns / int64(b.N)
}

// runN runs a single benchmark for the specified number of iterations.
func (b *B) runN(n int) {
	b.N = n
	b.ResetTimer()
	b.StartTimer()
	b.benchmark.F(b)
	b.StopTimer()
}

func min(x, y int) int {
	if x > y {
		return y
	}
	return x
}

func max(x, y int) int {
	if x < y {
		return y
	}
	return x
}

// roundDown10 rounds a number down to the nearest power of 10.
func roundDown10(n int) int {
	var tens = 0
	// tens = floor(log_10(n))
	for n > 10 {
		n = n / 10
		tens++
	}
	// result = 10^tens
	result := 1
	for i := 0; i < tens; i++ {
		result *= 10
	}
	return result
}

// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
func roundUp(n int) int {
	base := roundDown10(n)
	if n < (2 * base) {
		return 2 * base
	}
	if n < (5 * base) {
		return 5 * base
	}
	return 10 * base
}

// run times the benchmark function.  It gradually increases the number
// of benchmark iterations until the benchmark runs for a second in order
// to get a reasonable measurement.  It prints timing information in this form
//		testing.BenchmarkHello	100000		19 ns/op
func (b *B) run() BenchmarkResult {
	// Run the benchmark for a single iteration in case it's expensive.
	n := 1
	b.runN(n)
	// Run the benchmark for at least a second.
	for b.ns < 1e9 && n < 1e9 {
		last := n
		// Predict iterations/sec.
		if b.nsPerOp() == 0 {
			n = 1e9
		} else {
			n = 1e9 / int(b.nsPerOp())
		}
		// Run more iterations than we think we'll need for a second (1.5x).
		// Don't grow too fast in case we had timing errors previously.
		// Be sure to run at least one more than last time.
		n = max(min(n+n/2, 100*last), last+1)
		// Round up to something easy to read.
		n = roundUp(n)
		b.runN(n)
	}
	return BenchmarkResult{b.N, b.ns, b.bytes}

}

// The results of a benchmark run.
type BenchmarkResult struct {
	N     int   // The number of iterations.
	Ns    int64 // The total time taken.
	Bytes int64 // The total number of bytes processed.
}

func (r BenchmarkResult) NsPerOp() int64 {
	if r.N <= 0 {
		return 0
	}
	return r.Ns / int64(r.N)
}

func (r BenchmarkResult) String() string {
	ns := r.NsPerOp()
	mb := ""
	if ns > 0 && r.Bytes > 0 {
		mb = fmt.Sprintf("\t%7.2f MB/s", (float64(r.Bytes)/1e6)/(float64(ns)/1e9))
	}
	return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, ns, mb)
}

// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmarks []InternalBenchmark) {
	// If no flag was specified, don't run benchmarks.
	if len(*matchBenchmarks) == 0 {
		return
	}
	for _, Benchmark := range benchmarks {
		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
		if err != nil {
			println("invalid regexp for -benchmarks:", err)
			os.Exit(1)
		}
		if !matched {
			continue
		}
		b := &B{benchmark: Benchmark}
		r := b.run()
		fmt.Printf("%s\t%v\n", Benchmark.Name, r)
	}
}

// Benchmark benchmarks a single function. Useful for creating
// custom benchmarks that do not use gotest.
func Benchmark(f func(b *B)) BenchmarkResult {
	b := &B{benchmark: InternalBenchmark{"", f}}
	return b.run()
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// +build windows

package dokan

/*
#include "bridge.h"
*/
import "C"

import (
	"errors"
	"syscall"
	"time"
)

func packTime(t time.Time) C.FILETIME {
	ft := syscall.NsecToFiletime(t.UnixNano())
	return C.FILETIME{dwLowDateTime: C.DWORD(ft.LowDateTime), dwHighDateTime: C.DWORD(ft.HighDateTime)}
}
func unpackTime(c C.FILETIME) time.Time {
	ft := syscall.Filetime{LowDateTime: uint32(c.dwLowDateTime), HighDateTime: uint32(c.dwHighDateTime)}
	// This is valid, see docs and code for package time.
	return time.Unix(0, ft.Nanoseconds())
}

func getfs(fi C.PDOKAN_FILE_INFO) FileSystem {
	return fsTableGet(uint32(fi.DokanOptions.GlobalContext))
}

func getfi(fi C.PDOKAN_FILE_INFO) File {
	return fiTableGetFile(uint32(fi.Context))
}

func fiStore(pfi C.PDOKAN_FILE_INFO, fi File, err error) C.NTSTATUS {
	debug("->", fi, err)
	if fi != nil {
		pfi.Context = C.ULONG64(fiTableStoreFile(uint32(pfi.DokanOptions.GlobalContext), fi))
	}
	return errToNT(err)
}

func errToNT(err error) C.NTSTATUS {
	// NTSTATUS constants are defined as unsigned but the type is signed
	// and the values overflow on purpose. This is horrible.
	var code uint32
	if err != nil {
		debug("ERROR:", err)
		n, ok := err.(NtError)
		if ok {
			code = uint32(n)
		} else {
			code = uint32(0xC0000001)
		}
	}
	return C.NTSTATUS(code)
}

type dokanCtx struct {
	ptr  *C.struct_kbfs_libdokan_ctx
	slot uint32
}

func allocCtx(slot uint32) *dokanCtx {
	return &dokanCtx{C.kbfs_libdokan_alloc_ctx(C.ULONG64(slot)), slot}
}

func (ctx *dokanCtx) Run(driveLetter byte) error {
	if isDebug {
		ctx.ptr.dokan_options.Options |= C.kbfs_libdokan_debug
	}
	C.kbfs_libdokan_set_drive_letter(ctx.ptr, (C.char)(driveLetter))
	ec := C.kbfs_libdokan_run(ctx.ptr)
	if ec != 0 {
		return errors.New("Dokan failed")
	}
	return nil
}

func (ctx *dokanCtx) Free() {
	debug("dokanCtx.Free")
	C.kbfs_libdokan_free(ctx.ptr)
	fsTableFree(ctx.slot)
}
<commit_msg>dokan: Change default error to access denied<commit_after>// Copyright 2015 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// +build windows

package dokan

/*
#include "bridge.h"
*/
import "C"

import (
	"errors"
	"syscall"
	"time"
)

func packTime(t time.Time) C.FILETIME {
	ft := syscall.NsecToFiletime(t.UnixNano())
	return C.FILETIME{dwLowDateTime: C.DWORD(ft.LowDateTime), dwHighDateTime: C.DWORD(ft.HighDateTime)}
}
func unpackTime(c C.FILETIME) time.Time {
	ft := syscall.Filetime{LowDateTime: uint32(c.dwLowDateTime), HighDateTime: uint32(c.dwHighDateTime)}
	// This is valid, see docs and code for package time.
	return time.Unix(0, ft.Nanoseconds())
}

func getfs(fi C.PDOKAN_FILE_INFO) FileSystem {
	return fsTableGet(uint32(fi.DokanOptions.GlobalContext))
}

func getfi(fi C.PDOKAN_FILE_INFO) File {
	return fiTableGetFile(uint32(fi.Context))
}

func fiStore(pfi C.PDOKAN_FILE_INFO, fi File, err error) C.NTSTATUS {
	debug("->", fi, err)
	if fi != nil {
		pfi.Context = C.ULONG64(fiTableStoreFile(uint32(pfi.DokanOptions.GlobalContext), fi))
	}
	return errToNT(err)
}

func errToNT(err error) C.NTSTATUS {
	// NTSTATUS constants are defined as unsigned but the type is signed
	// and the values overflow on purpose. This is horrible.
	var code uint32
	if err != nil {
		debug("ERROR:", err)
		n, ok := err.(NtError)
		if ok {
			code = uint32(n)
		} else {
			code = uint32(ErrAccessDenied)
		}
	}
	return C.NTSTATUS(code)
}

type dokanCtx struct {
	ptr  *C.struct_kbfs_libdokan_ctx
	slot uint32
}

func allocCtx(slot uint32) *dokanCtx {
	return &dokanCtx{C.kbfs_libdokan_alloc_ctx(C.ULONG64(slot)), slot}
}

func (ctx *dokanCtx) Run(driveLetter byte) error {
	if isDebug {
		ctx.ptr.dokan_options.Options |= C.kbfs_libdokan_debug
	}
	C.kbfs_libdokan_set_drive_letter(ctx.ptr, (C.char)(driveLetter))
	ec := C.kbfs_libdokan_run(ctx.ptr)
	if ec != 0 {
		return errors.New("Dokan failed")
	}
	return nil
}

func (ctx *dokanCtx) Free() {
	debug("dokanCtx.Free")
	C.kbfs_libdokan_free(ctx.ptr)
	fsTableFree(ctx.slot)
}
<|endoftext|>


<commit_before>package dos

import "fmt"
import "io"
import "os"
import "syscall"

func Truncate(folder string, out io.Writer) error {
	fd, fdErr := os.Open(folder)
	if fdErr != nil {
		return fdErr
	}
	fi, fiErr := fd.Readdir(-1)
	fd.Close()
	if fiErr != nil {
		return fiErr
	}
	for _, f := range fi {
		if f.Name() == "." || f.Name() == ".." {
			continue
		}
		fullpath := Join(folder, f.Name())
		var err error
		if f.IsDir() {
			fmt.Fprintf(out, "%s\\\n", fullpath)
			err = Truncate(fullpath, out)
		} else {
			fmt.Fprintln(out, fullpath)
			SetFileAttributes(fullpath, FILE_ATTRIBUTE_NORMAL)
			err = syscall.Unlink(fullpath)
		}
		if err != nil {
			return fmt.Errorf("%s: %s", fullpath, err.Error())
		}
	}
	if err := syscall.Rmdir(folder); err != nil {
		return fmt.Errorf("%s: %s", folder, err.Error())
	}
	return nil
}
<commit_msg>'rmdir /s' does not remove files under junctions<commit_after>package dos

import "fmt"
import "io"
import "os"
import "syscall"

func Truncate(folder string, out io.Writer) error {
	attr, attrErr := GetFileAttributes(folder)
	if attrErr != nil {
		return fmt.Errorf("%s: %s", folder, attrErr)
	}
	if (attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0 {
		// Only not junction, delete files under folder.
		fd, fdErr := os.Open(folder)
		if fdErr != nil {
			return fdErr
		}
		fi, fiErr := fd.Readdir(-1)
		fd.Close()
		if fiErr != nil {
			return fiErr
		}
		for _, f := range fi {
			if f.Name() == "." || f.Name() == ".." {
				continue
			}
			fullpath := Join(folder, f.Name())
			var err error
			if f.IsDir() {
				fmt.Fprintf(out, "%s\\\n", fullpath)
				err = Truncate(fullpath, out)
			} else {
				fmt.Fprintln(out, fullpath)
				SetFileAttributes(fullpath, FILE_ATTRIBUTE_NORMAL)
				err = syscall.Unlink(fullpath)
			}
			if err != nil {
				return fmt.Errorf("%s: %s", fullpath, err.Error())
			}
		}
	}
	if err := syscall.Rmdir(folder); err != nil {
		return fmt.Errorf("%s: %s", folder, err.Error())
	}
	return nil
}
<|endoftext|>


<commit_before>package irc

import (
	"strings"
	"fmt"
	"time"
	"strconv"
)

func (irc *IRCConnection) AddCallback(eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		// TODO: Grow this dynamically
		event = event[0 : len(event)+1]
		event[len(event)-1] = callback
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) RunCallbacks(event *IRCEvent) {
	if event.Code == "PRIVMSG" && event.Message[0] == '\x01' {
		event.Code = "CTCP" //Unknown CTCP
		if i := strings.LastIndex(event.Message, "\x01"); i > -1 {
			event.Message = event.Message[1:i]
		}
		if event.Message == "VERSION" {
			event.Code = "CTCP_VERSION"
		} else if event.Message == "TIME" {
			event.Code = "CTCP_TIME"
		} else if event.Message[0:4] == "PING" {
			event.Code = "CTCP_PING"
		} else if event.Message == "USERINFO" {
			event.Code = "CTCP_USERINFO"
		} else if event.Message == "CLIENTINFO" {
			event.Code = "CTCP_CLIENTINFO"
		}
	}
	if callbacks, ok := irc.events[event.Code]; ok {
		for _, callback := range callbacks {
			go callback(event)
		}
	} else {
		fmt.Printf("No callback for: %#v\n", event)
	}
}

func (irc *IRCConnection) setupCallbacks() {
	irc.events = make(map[string][]func(*IRCEvent))

	//Handle ping events
	irc.AddCallback("PING", func(e *IRCEvent) { irc.SendRaw("PONG :" + e.Message) })

	//Version handler
	irc.AddCallback("CTCP_VERSION", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01", e.Nick, VERSION))
	})

	irc.AddCallback("CTCP_USERINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user))
	})

	irc.AddCallback("CTCP_CLIENTINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick))
	})

	irc.AddCallback("CTCP_TIME", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", e.Nick, time.LocalTime().Format("ANSIC")))
	})

	irc.AddCallback("CTCP_PING", func(e *IRCEvent) { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick, e.Message)) })

	irc.AddCallback("437", func(e *IRCEvent) {
		irc.nick = irc.nick + "_"
		irc.SendRaw(fmt.Sprintf("NICK %s", irc.nick))
	})

	irc.AddCallback("PONG", func(e *IRCEvent) {
		ns, _ := strconv.Atoi64(e.Message)
		fmt.Printf("Lag: %fs\n", float((time.Nanoseconds()-ns))/1000/1000/1000)
	})
}
<commit_msg>Add ReplaceCallback<commit_after>package irc

import (
	"strings"
	"fmt"
	"time"
	"strconv"
)

func (irc *IRCConnection) AddCallback(eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		// TODO: Grow this dynamically
		event = event[0 : len(event)+1]
		event[len(event)-1] = callback
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) ReplaceCallback(i uint8, eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		event[i] = callback;
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) RunCallbacks(event *IRCEvent) {
	if event.Code == "PRIVMSG" && event.Message[0] == '\x01' {
		event.Code = "CTCP" //Unknown CTCP
		if i := strings.LastIndex(event.Message, "\x01"); i > -1 {
			event.Message = event.Message[1:i]
		}
		if event.Message == "VERSION" {
			event.Code = "CTCP_VERSION"
		} else if event.Message == "TIME" {
			event.Code = "CTCP_TIME"
		} else if event.Message[0:4] == "PING" {
			event.Code = "CTCP_PING"
		} else if event.Message == "USERINFO" {
			event.Code = "CTCP_USERINFO"
		} else if event.Message == "CLIENTINFO" {
			event.Code = "CTCP_CLIENTINFO"
		}
	}
	if callbacks, ok := irc.events[event.Code]; ok {
		for _, callback := range callbacks {
			go callback(event)
		}
	} else {
		fmt.Printf("No callback for: %#v\n", event)
	}
}

func (irc *IRCConnection) setupCallbacks() {
	irc.events = make(map[string][]func(*IRCEvent))

	//Handle ping events
	irc.AddCallback("PING", func(e *IRCEvent) { irc.SendRaw("PONG :" + e.Message) })

	//Version handler
	irc.AddCallback("CTCP_VERSION", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01", e.Nick, VERSION))
	})

	irc.AddCallback("CTCP_USERINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user))
	})

	irc.AddCallback("CTCP_CLIENTINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick))
	})

	irc.AddCallback("CTCP_TIME", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", e.Nick, time.LocalTime().Format("ANSIC")))
	})

	irc.AddCallback("CTCP_PING", func(e *IRCEvent) { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick, e.Message)) })

	irc.AddCallback("437", func(e *IRCEvent) {
		irc.nick = irc.nick + "_"
		irc.SendRaw(fmt.Sprintf("NICK %s", irc.nick))
	})

	irc.AddCallback("PONG", func(e *IRCEvent) {
		ns, _ := strconv.Atoi64(e.Message)
		fmt.Printf("Lag: %fs\n", float((time.Nanoseconds()-ns))/1000/1000/1000)
	})
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes 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 ipwhitelist

import (
	"reflect"
	"testing"

	api "k8s.io/api/core/v1"
	extensions "k8s.io/api/extensions/v1beta1"
	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	"k8s.io/ingress/core/pkg/ingress/defaults"
	"k8s.io/ingress/core/pkg/ingress/errors"
)

func buildIngress() *extensions.Ingress {
	defaultBackend := extensions.IngressBackend{
		ServiceName: "default-backend",
		ServicePort: intstr.FromInt(80),
	}

	return &extensions.Ingress{
		ObjectMeta: meta_v1.ObjectMeta{
			Name:      "foo",
			Namespace: api.NamespaceDefault,
		},
		Spec: extensions.IngressSpec{
			Backend: &extensions.IngressBackend{
				ServiceName: "default-backend",
				ServicePort: intstr.FromInt(80),
			},
			Rules: []extensions.IngressRule{
				{
					Host: "foo.bar.com",
					IngressRuleValue: extensions.IngressRuleValue{
						HTTP: &extensions.HTTPIngressRuleValue{
							Paths: []extensions.HTTPIngressPath{
								{
									Path:    "/foo",
									Backend: defaultBackend,
								},
							},
						},
					},
				},
			},
		},
	}
}

type mockBackend struct {
	defaults.Backend
}

func (m mockBackend) GetDefaultBackend() defaults.Backend {
	return m.Backend
}

func TestParseAnnotations(t *testing.T) {
	// TODO: convert test cases to tables
	ing := buildIngress()

	testNet := "10.0.0.0/24"
	enet := []string{testNet}

	data := map[string]string{}
	data[whitelist] = testNet
	ing.SetAnnotations(data)

	expected := &SourceRange{
		CIDR: enet,
	}

	p := NewParser(mockBackend{})

	i, err := p.Parse(ing)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	sr, ok := i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}

	if !reflect.DeepEqual(sr, expected) {
		t.Errorf("expected %v but returned %s", sr, expected)
	}

	data[whitelist] = "www"
	_, err = p.Parse(ing)
	if err == nil {
		t.Errorf("expected error parsing an invalid cidr")
	}

	if !errors.IsLocationDenied(err) {
		t.Errorf("expected LocationDenied error: %+v", err)
	}

	delete(data, whitelist)
	i, err = p.Parse(ing)

	if err != nil {
		t.Errorf("unexpected error when no annotation present: %v", err)
	}

	sr, ok = i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}
	if !strsEquals(sr.CIDR, []string{}) {
		t.Errorf("expected empty CIDR but %v returned", sr.CIDR)
	}

	i, _ = p.Parse(&extensions.Ingress{})
	sr, ok = i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}
	if !strsEquals(sr.CIDR, []string{}) {
		t.Errorf("expected empty CIDR but %v returned", sr.CIDR)
	}

	data[whitelist] = "2.2.2.2/32,1.1.1.1/32,3.3.3.0/24"
	i, _ = p.Parse(ing)
	sr, ok = i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}
	ecidr := []string{"1.1.1.1/32", "2.2.2.2/32", "3.3.3.0/24"}
	if !strsEquals(sr.CIDR, ecidr) {
		t.Errorf("Expected %v CIDR but %v returned", ecidr, sr.CIDR)
	}
}

// Test that when we have a whitelist set on the Backend that is used when we
// don't have the annotation
func TestParseAnnotationsWithDefaultConfig(t *testing.T) {
	// TODO: convert test cases to tables
	ing := buildIngress()

	mockBackend := mockBackend{}
	mockBackend.Backend.WhitelistSourceRange = []string{"4.4.4.0/24", "1.2.3.4/32"}
	testNet := "10.0.0.0/24"
	enet := []string{testNet}

	data := map[string]string{}
	data[whitelist] = testNet
	ing.SetAnnotations(data)

	expected := &SourceRange{
		CIDR: enet,
	}

	p := NewParser(mockBackend)

	i, err := p.Parse(ing)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	sr, ok := i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}

	if !reflect.DeepEqual(sr, expected) {
		t.Errorf("expected %v but returned %s", sr, expected)
	}

	data[whitelist] = "www"
	_, err = p.Parse(ing)
	if err == nil {
		t.Errorf("expected error parsing an invalid cidr")
	}
	if !errors.IsLocationDenied(err) {
		t.Errorf("expected LocationDenied error: %+v", err)
	}

	delete(data, whitelist)
	i, err = p.Parse(ing)

	if err != nil {
		t.Errorf("unexpected error when no annotation present: %v", err)
	}

	sr, ok = i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}
	if !strsEquals(sr.CIDR, mockBackend.WhitelistSourceRange) {
		t.Errorf("expected fallback CIDR but %v returned", sr.CIDR)
	}

	i, _ = p.Parse(&extensions.Ingress{})
	sr, ok = i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}
	if !strsEquals(sr.CIDR, mockBackend.WhitelistSourceRange) {
		t.Errorf("expected fallback CIDR but %v returned", sr.CIDR)
	}

	data[whitelist] = "2.2.2.2/32,1.1.1.1/32,3.3.3.0/24"
	i, _ = p.Parse(ing)
	sr, ok = i.(*SourceRange)
	if !ok {
		t.Errorf("expected a SourceRange type")
	}
	ecidr := []string{"1.1.1.1/32", "2.2.2.2/32", "3.3.3.0/24"}
	if !strsEquals(sr.CIDR, ecidr) {
		t.Errorf("Expected %v CIDR but %v returned", ecidr, sr.CIDR)
	}
}

func strsEquals(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}
<commit_msg>Fix Todo:convert sequence to table<commit_after>/*
Copyright 2016 The Kubernetes 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 ipwhitelist

import (
	"testing"

	api "k8s.io/api/core/v1"
	extensions "k8s.io/api/extensions/v1beta1"
	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	"k8s.io/ingress/core/pkg/ingress/defaults"
)

func buildIngress() *extensions.Ingress {
	defaultBackend := extensions.IngressBackend{
		ServiceName: "default-backend",
		ServicePort: intstr.FromInt(80),
	}

	return &extensions.Ingress{
		ObjectMeta: meta_v1.ObjectMeta{
			Name:      "foo",
			Namespace: api.NamespaceDefault,
		},
		Spec: extensions.IngressSpec{
			Backend: &extensions.IngressBackend{
				ServiceName: "default-backend",
				ServicePort: intstr.FromInt(80),
			},
			Rules: []extensions.IngressRule{
				{
					Host: "foo.bar.com",
					IngressRuleValue: extensions.IngressRuleValue{
						HTTP: &extensions.HTTPIngressRuleValue{
							Paths: []extensions.HTTPIngressPath{
								{
									Path:    "/foo",
									Backend: defaultBackend,
								},
							},
						},
					},
				},
			},
		},
	}
}

type mockBackend struct {
	defaults.Backend
}

func (m mockBackend) GetDefaultBackend() defaults.Backend {
	return m.Backend
}

func TestParseAnnotations(t *testing.T) {
	ing := buildIngress()
	tests := map[string]struct {
		net        string
		expectCidr []string
		expectErr  bool
		errOut     string
	}{
		"test parse a valid net": {
			net:        "10.0.0.0/24",
			expectCidr: []string{"10.0.0.0/24"},
			expectErr:  false,
		},
		"test parse a invalid net": {
			net:       "ww",
			expectErr: true,
			errOut:    "the annotation does not contain a valid IP address or network: invalid CIDR address: ww",
		},
		"test parse a empty net": {
			net:       "",
			expectErr: true,
			errOut:    "the annotation does not contain a valid IP address or network: invalid CIDR address: ",
		},
		"test parse multiple valid cidr": {
			net:        "2.2.2.2/32,1.1.1.1/32,3.3.3.0/24",
			expectCidr: []string{"1.1.1.1/32", "2.2.2.2/32", "3.3.3.0/24"},
			expectErr:  false,
		},
	}

	for testName, test := range tests {
		data := map[string]string{}
		data[whitelist] = test.net
		ing.SetAnnotations(data)
		p := NewParser(mockBackend{})
		i, err := p.Parse(ing)
		if err != nil && !test.expectErr {
			t.Errorf("%v:unexpected error: %v", testName, err)
		}
		if test.expectErr {
			if err.Error() != test.errOut {
				t.Errorf("%v:expected error: %v but %v return", testName, test.errOut, err.Error())
			}
		}
		if !test.expectErr {
			sr, ok := i.(*SourceRange)
			if !ok {
				t.Errorf("%v:expected a SourceRange type", testName)
			}
			if !strsEquals(sr.CIDR, test.expectCidr) {
				t.Errorf("%v:expected %v CIDR but %v returned", testName, test.expectCidr, sr.CIDR)
			}
		}
	}
}

// Test that when we have a whitelist set on the Backend that is used when we
// don't have the annotation
func TestParseAnnotationsWithDefaultConfig(t *testing.T) {
	ing := buildIngress()
	mockBackend := mockBackend{}
	mockBackend.Backend.WhitelistSourceRange = []string{"4.4.4.0/24", "1.2.3.4/32"}
	tests := map[string]struct {
		net        string
		expectCidr []string
		expectErr  bool
		errOut     string
	}{
		"test parse a valid net": {
			net:        "10.0.0.0/24",
			expectCidr: []string{"10.0.0.0/24"},
			expectErr:  false,
		},
		"test parse a invalid net": {
			net:       "ww",
			expectErr: true,
			errOut:    "the annotation does not contain a valid IP address or network: invalid CIDR address: ww",
		},
		"test parse a empty net": {
			net:       "",
			expectErr: true,
			errOut:    "the annotation does not contain a valid IP address or network: invalid CIDR address: ",
		},
		"test parse multiple valid cidr": {
			net:        "2.2.2.2/32,1.1.1.1/32,3.3.3.0/24",
			expectCidr: []string{"1.1.1.1/32", "2.2.2.2/32", "3.3.3.0/24"},
			expectErr:  false,
		},
	}

	for testName, test := range tests {
		data := map[string]string{}
		data[whitelist] = test.net
		ing.SetAnnotations(data)
		p := NewParser(mockBackend)
		i, err := p.Parse(ing)
		if err != nil && !test.expectErr {
			t.Errorf("%v:unexpected error: %v", testName, err)
		}
		if test.expectErr {
			if err.Error() != test.errOut {
				t.Errorf("%v:expected error: %v but %v return", testName, test.errOut, err.Error())
			}
		}
		if !test.expectErr {
			sr, ok := i.(*SourceRange)
			if !ok {
				t.Errorf("%v:expected a SourceRange type", testName)
			}
			if !strsEquals(sr.CIDR, test.expectCidr) {
				t.Errorf("%v:expected %v CIDR but %v returned", testName, test.expectCidr, sr.CIDR)
			}
		}
	}
}

func strsEquals(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package binenv

import (
	"errors"
	"strings"
)

func Load(asset func(string) ([]byte, error)) (envMap map[string]string, err error) {
	data, err := asset(".env")
	if err != nil {
		return nil, err
	}
	envData, err := readRawString(string(data))
	if err != nil {
		return nil, err
	}
	return envData, nil
}

func readRawString(rawString string) (envMap map[string]string, err error) {
	envMap = make(map[string]string)

	var lines []string
	lines = strings.Split(rawString, "\n")

	for _, fullLine := range lines {
		if !isIgnoredLine(fullLine) {
			key, value, err := parseLine(fullLine)

			if err == nil {
				envMap[key] = value
			}
		}
	}
	return
}

func parseLine(line string) (key string, value string, err error) {
	if len(line) == 0 {
		err = errors.New("zero length string")
		return
	}

	// ditch the comments (but keep quoted hashes)
	if strings.Contains(line, "#") {
		segmentsBetweenHashes := strings.Split(line, "#")
		quotesAreOpen := false
		var segmentsToKeep []string
		for _, segment := range segmentsBetweenHashes {
			if strings.Count(segment, "\"") == 1 || strings.Count(segment, "'") == 1 {
				if quotesAreOpen {
					quotesAreOpen = false
					segmentsToKeep = append(segmentsToKeep, segment)
				} else {
					quotesAreOpen = true
				}
			}

			if len(segmentsToKeep) == 0 || quotesAreOpen {
				segmentsToKeep = append(segmentsToKeep, segment)
			}
		}

		line = strings.Join(segmentsToKeep, "#")
	}

	// now split key from value
	splitString := strings.SplitN(line, "=", 2)

	if len(splitString) != 2 {
		// try yaml mode!
		splitString = strings.SplitN(line, ":", 2)
	}

	if len(splitString) != 2 {
		err = errors.New("Can't separate key from value")
		return
	}

	// Parse the key
	key = splitString[0]
	if strings.HasPrefix(key, "export") {
		key = strings.TrimPrefix(key, "export")
	}
	key = strings.Trim(key, " ")

	// Parse the value
	value = splitString[1]
	// trim
	value = strings.Trim(value, " ")

	// check if we've got quoted values
	if strings.Count(value, "\"") == 2 || strings.Count(value, "'") == 2 {
		// pull the quotes off the edges
		value = strings.Trim(value, "\"'")

		// expand quotes
		value = strings.Replace(value, "\\\"", "\"", -1)
		// expand newlines
		value = strings.Replace(value, "\\n", "\n", -1)
	}

	return
}

func isIgnoredLine(line string) bool {
	trimmedLine := strings.Trim(line, " \n\t")
	return len(trimmedLine) == 0 || strings.HasPrefix(trimmedLine, "#")
}
<commit_msg>add ENV type<commit_after>package binenv

import (
	"errors"
	"strings"
)

type ENV map[string]string

func Load(asset func(string) ([]byte, error)) (envMap map[string]string, err error) {
	data, err := asset(".env")
	if err != nil {
		return nil, err
	}
	envData, err := readRawString(string(data))
	if err != nil {
		return nil, err
	}
	return envData, nil
}

func readRawString(rawString string) (envMap map[string]string, err error) {
	envMap = make(map[string]string)

	var lines []string
	lines = strings.Split(rawString, "\n")

	for _, fullLine := range lines {
		if !isIgnoredLine(fullLine) {
			key, value, err := parseLine(fullLine)

			if err == nil {
				envMap[key] = value
			}
		}
	}
	return
}

func parseLine(line string) (key string, value string, err error) {
	if len(line) == 0 {
		err = errors.New("zero length string")
		return
	}

	// ditch the comments (but keep quoted hashes)
	if strings.Contains(line, "#") {
		segmentsBetweenHashes := strings.Split(line, "#")
		quotesAreOpen := false
		var segmentsToKeep []string
		for _, segment := range segmentsBetweenHashes {
			if strings.Count(segment, "\"") == 1 || strings.Count(segment, "'") == 1 {
				if quotesAreOpen {
					quotesAreOpen = false
					segmentsToKeep = append(segmentsToKeep, segment)
				} else {
					quotesAreOpen = true
				}
			}

			if len(segmentsToKeep) == 0 || quotesAreOpen {
				segmentsToKeep = append(segmentsToKeep, segment)
			}
		}

		line = strings.Join(segmentsToKeep, "#")
	}

	// now split key from value
	splitString := strings.SplitN(line, "=", 2)

	if len(splitString) != 2 {
		// try yaml mode!
		splitString = strings.SplitN(line, ":", 2)
	}

	if len(splitString) != 2 {
		err = errors.New("Can't separate key from value")
		return
	}

	// Parse the key
	key = splitString[0]
	if strings.HasPrefix(key, "export") {
		key = strings.TrimPrefix(key, "export")
	}
	key = strings.Trim(key, " ")

	// Parse the value
	value = splitString[1]
	// trim
	value = strings.Trim(value, " ")

	// check if we've got quoted values
	if strings.Count(value, "\"") == 2 || strings.Count(value, "'") == 2 {
		// pull the quotes off the edges
		value = strings.Trim(value, "\"'")

		// expand quotes
		value = strings.Replace(value, "\\\"", "\"", -1)
		// expand newlines
		value = strings.Replace(value, "\\n", "\n", -1)
	}

	return
}

func isIgnoredLine(line string) bool {
	trimmedLine := strings.Trim(line, " \n\t")
	return len(trimmedLine) == 0 || strings.HasPrefix(trimmedLine, "#")
}
<|endoftext|>


<commit_before>package openstack

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	s "strings"
	"time"

	"github.com/Jeffail/gabs"
)

const (
	KeystonePort = "5000"
	ComputePort  = "8774"
	NetworkPort  = "9696"
)

type Config struct {
	Urlauth          string
	Apiverauth       string
	Apivernet        string
	Urlcomp          string
	Urlnet           string
	Apivercomp       string
	InstallscriptURL string
}

// Credentials to be used for accessing the AI
type Credentials struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

// Openstack auth structure
type Auth struct {
	Body struct {
		Credentials Credentials `json:"passwordCredentials"`
		Tenant      string      `json:"tenantId"`
	} `json:"auth"`
}

// Client for provisioning machines on Openstack
type Client struct {
	Token   string    `json:"token"`
	Expires time.Time `json:"expires"`
}

//Openstack server info structure
type serverData struct {
	Server struct {
		Name            string     `json:"name"`
		User_data       string     `json:"user_data"`
		Key_name        string     `json:"key_name,omitempty"`
		ImageRef        string     `json:"imageRef"`
		FlavorRef       string     `json:"flavorRef"`
		Networks        []network  `json:"networks"`
		Security_groups []secgroup `json:"security_groups"`
	} `json:"server"`
}

type network struct {
	Uuid string `json:"uuid"`
}

type secgroup struct {
	Name string `json:"name"`
}

type floatingIPAction struct {
	AddFloatingIp struct {
		Address string `json:"address"`
	} `json:"addFloatingIp"`
}

func isValidJSON(s string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(s), &js) == nil
}

func (c *Client) login(a Auth, conf Config) (string, error) {
	fmt.Println("auth", a)
	var fileName = a.Body.Credentials.Username + ".token"
	dat, readerr := ioutil.ReadFile(fileName)
	fmt.Println("Opened token file", len(dat), readerr)
	if readerr == nil && dat != nil && len(dat) > 0 {
		fmt.Printf("Opened token file with content %s", string(dat))
		var savedCreds Client
		deserr := json.Unmarshal(dat, &savedCreds)
		fmt.Printf("Deserialized token file", deserr, savedCreds)
		if deserr == nil {
			now := time.Now()
			exptime := savedCreds.Expires
			fmt.Println("Checking expiration", exptime)
			if now.Before(exptime) {
				c.Token = savedCreds.Token
				fmt.Println("Will use old token", c.Token)
				return c.Token, nil
			}
		}
	}

	fmt.Errorf("Token file %s does not exist ", fileName)

	url := conf.Urlauth + conf.Apiverauth + "/tokens"
	fmt.Println("Openstack URL:>", url)

	jsonStr, parseErr := json.Marshal(a)
	if parseErr != nil {
		fmt.Errorf("Something is wrong with auth body", parseErr)
		return "", fmt.Errorf("Something is wrong with auth body: %v", parseErr)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)

	body, _ := ioutil.ReadAll(resp.Body)

	jsonParsed, err := gabs.ParseJSON(body)

	c.Token = jsonParsed.Path("access.token.id").String()
	c.Token = s.Trim(c.Token, "\"")
	var exp string = jsonParsed.Path("access.token.expires").String()
	exp = s.Trim(exp, "\"")
	fmt.Println("Expiration", exp)
	layout := "2006-01-02T15:04:05Z"
	c.Expires, _ = time.Parse(layout, exp)
	fmt.Println("Time object", c.Expires)
	fmt.Println("login results:", c.Token)
	credsJson, _ := json.Marshal(*c)
	fmt.Println("Marshaled creds", string(credsJson))
	errwrite := ioutil.WriteFile(fileName, credsJson, 0644)
	if errwrite != nil {
		fmt.Errorf("Issues serializing token file %v\n", errwrite)
	}

	return c.Token, err
}

func (c *Client) getAPIClient(auth Auth, conf Config) error {
	if c.Token == "" {
		token, err := c.login(auth, conf)
		if err != nil {
			return fmt.Errorf("Error with credentials provided: %v", err)
		}
		fmt.Printf("Returned token %s \n", token)

	}
	return nil
}

func (c *Client) buildNode(auth Auth, conf Config, nodeData serverData, nodeType string) (string, error) {
	token, err := c.login(auth, conf)
	if err != nil {
		return "", fmt.Errorf("Error with auth: %v", err)
	}

	var url = conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/servers"

	fmt.Println("After login returned with token", token)

	jsonStr, parseErr := json.Marshal(nodeData)
	if parseErr != nil {
		return "", fmt.Errorf("Error with server data format: %v", parseErr)
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("X-Auth-Token", token)
	req.Header.Set("Content-Type", "application/json")

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}

	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)

	body, _ := ioutil.ReadAll(resp.Body)

	if isValidJSON(string(body)) == false {
		return "", errors.New("Not a valid JSON response: " + string(body))
	}

	jsonParsed, err := gabs.ParseJSON(body)

	var message, nodeID string

	if jsonParsed.Exists("overLimit", "code") {
		var code = jsonParsed.Path("overLimit.code").String()
		if code == "413" {
			message = "Out of space"
			fmt.Println("message:", message)
		}
	}

	if jsonParsed.Exists("badRequest") {
		message = jsonParsed.Path("badRequest.message").String()
		fmt.Println("message:", message)

	}
	if jsonParsed.Exists("server", "id") {
		nodeID = jsonParsed.Path("server.id").String()
		fmt.Println("nodeID:", nodeID)
	}
	if nodeID == "" {
		message = "Unknown error"
	}
	if message != "" {
		return "", errors.New(message)
	}

	return nodeID, nil

}

func (c *Client) downloadInitScript(url string) (string, error) {

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	return string(body), nil

}

func (c *Client) parseObj(body []byte, objNode string, idfield string, namefield string) (map[string]string, error) {
	var objMap map[string]string = make(map[string]string)
	jsonParsed, err := gabs.ParseJSON(body)
	if err != nil {
		return nil, err
	}
	if jsonParsed.Exists(objNode) {
		ids := s.TrimLeft(jsonParsed.Path(fmt.Sprintf("%s.%s", objNode, idfield)).String(), "[")
		ids = s.TrimRight(ids, "]")
		idarray := s.Split(ids, ",")
		names := s.TrimLeft(jsonParsed.Path(fmt.Sprintf("%s.%s", objNode, namefield)).String(), "[")
		names = s.TrimRight(names, "]")
		namearray := s.Split(names, ",")
		count := len(idarray)
		for i := 0; i < count; i++ {
			objMap[idarray[i]] = namearray[i]
		}
	}
	return objMap, nil
}

func (c *Client) listImages(auth Auth, conf Config) (map[string]string, error) {
	objType := "images"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load images. %v", err))
	}
	objMap, errParse := c.parseObj(body, "images", "id", "name")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) listFlavors(auth Auth, conf Config) (map[string]string, error) {
	objType := "flavors"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load flavors. %v", err))
	}

	objMap, errParse := c.parseObj(body, "flavors", "id", "name")
	if errParse != nil {
		return nil, errParse
	}
	return objMap, nil
}

func (c *Client) listNetworks(auth Auth, conf Config) (map[string]string, error) {
	objType := "networks"
	url := conf.Urlnet + conf.Apivernet + "/" + objType
	fmt.Println("Network URL", url)
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load networks. %v", err))
	}

	objMap, errParse := c.parseObj(body, "networks", "id", "name")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) listSecGroups(auth Auth, conf Config) (map[string]string, error) {
	objType := "os-security-groups"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load security groups. %v", err))
	}
	objMap, errParse := c.parseObj(body, "security_groups", "id", "name")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) listFloatingIPs(auth Auth, conf Config) (map[string]string, error) {
	objType := "os-floating-ips"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load security groups. %v", err))
	}
	objMap, errParse := c.parseObj(body, "floating_ips", "ip", "ip")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) assignFloatingIP(auth Auth, conf Config, serverID string, ip string) error {
	token, err := c.login(auth, conf)
	if err != nil {
		return fmt.Errorf("Error with auth: %v", err)
	}

	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/servers/" + serverID + "/action/"
	fmt.Println("Action URL:>", url)

	var actionObj floatingIPAction
	actionObj.AddFloatingIp.Address = ip

	jsonStr, parseErr := json.Marshal(actionObj)
	log.Println("Serialized floating IP structure", string(jsonStr))
	if parseErr != nil {
		log.Println("Something is wrong with action body", parseErr)
		return fmt.Errorf("Something is wrong with auth body: %v", parseErr)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("X-Auth-Token", token)
	req.Header.Set("Content-Type", "application/json")

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}
	resp, err := client.Do(req)
	body, _ := ioutil.ReadAll(resp.Body)
	log.Println("Floating IP resp", string(body), err)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	return err
}

func (c *Client) listObjects(auth Auth, conf Config, url string, objType string) ([]byte, error) {
	token, err := c.login(auth, conf)
	if err != nil {
		return nil, fmt.Errorf("Error with auth: %v", err)
	}

	req, err := http.NewRequest("GET", url, nil)
	req.Header.Set("X-Auth-Token", token)

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}

	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)

	body, _ := ioutil.ReadAll(resp.Body)

	if isValidJSON(string(body)) == false {
		return nil, errors.New("Not a valid JSON response: " + string(body))
	}
	return body, nil
}
<commit_msg>Assign floating IP logging<commit_after>package openstack

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	s "strings"
	"time"

	"github.com/Jeffail/gabs"
)

const (
	KeystonePort = "5000"
	ComputePort  = "8774"
	NetworkPort  = "9696"
)

type Config struct {
	Urlauth          string
	Apiverauth       string
	Apivernet        string
	Urlcomp          string
	Urlnet           string
	Apivercomp       string
	InstallscriptURL string
}

// Credentials to be used for accessing the AI
type Credentials struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

// Openstack auth structure
type Auth struct {
	Body struct {
		Credentials Credentials `json:"passwordCredentials"`
		Tenant      string      `json:"tenantId"`
	} `json:"auth"`
}

// Client for provisioning machines on Openstack
type Client struct {
	Token   string    `json:"token"`
	Expires time.Time `json:"expires"`
}

//Openstack server info structure
type serverData struct {
	Server struct {
		Name            string     `json:"name"`
		User_data       string     `json:"user_data"`
		Key_name        string     `json:"key_name,omitempty"`
		ImageRef        string     `json:"imageRef"`
		FlavorRef       string     `json:"flavorRef"`
		Networks        []network  `json:"networks"`
		Security_groups []secgroup `json:"security_groups"`
	} `json:"server"`
}

type network struct {
	Uuid string `json:"uuid"`
}

type secgroup struct {
	Name string `json:"name"`
}

type floatingIPAction struct {
	AddFloatingIp struct {
		Address string `json:"address"`
	} `json:"addFloatingIp"`
}

func isValidJSON(s string) bool {
	var js map[string]interface{}
	return json.Unmarshal([]byte(s), &js) == nil
}

func (c *Client) login(a Auth, conf Config) (string, error) {
	fmt.Println("auth", a)
	var fileName = a.Body.Credentials.Username + ".token"
	dat, readerr := ioutil.ReadFile(fileName)
	fmt.Println("Opened token file", len(dat), readerr)
	if readerr == nil && dat != nil && len(dat) > 0 {
		fmt.Printf("Opened token file with content %s", string(dat))
		var savedCreds Client
		deserr := json.Unmarshal(dat, &savedCreds)
		fmt.Printf("Deserialized token file", deserr, savedCreds)
		if deserr == nil {
			now := time.Now()
			exptime := savedCreds.Expires
			fmt.Println("Checking expiration", exptime)
			if now.Before(exptime) {
				c.Token = savedCreds.Token
				fmt.Println("Will use old token", c.Token)
				return c.Token, nil
			}
		}
	}

	fmt.Errorf("Token file %s does not exist ", fileName)

	url := conf.Urlauth + conf.Apiverauth + "/tokens"
	fmt.Println("Openstack URL:>", url)

	jsonStr, parseErr := json.Marshal(a)
	if parseErr != nil {
		fmt.Errorf("Something is wrong with auth body", parseErr)
		return "", fmt.Errorf("Something is wrong with auth body: %v", parseErr)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)

	body, _ := ioutil.ReadAll(resp.Body)

	jsonParsed, err := gabs.ParseJSON(body)

	c.Token = jsonParsed.Path("access.token.id").String()
	c.Token = s.Trim(c.Token, "\"")
	var exp string = jsonParsed.Path("access.token.expires").String()
	exp = s.Trim(exp, "\"")
	fmt.Println("Expiration", exp)
	layout := "2006-01-02T15:04:05Z"
	c.Expires, _ = time.Parse(layout, exp)
	fmt.Println("Time object", c.Expires)
	fmt.Println("login results:", c.Token)
	credsJson, _ := json.Marshal(*c)
	fmt.Println("Marshaled creds", string(credsJson))
	errwrite := ioutil.WriteFile(fileName, credsJson, 0644)
	if errwrite != nil {
		fmt.Errorf("Issues serializing token file %v\n", errwrite)
	}

	return c.Token, err
}

func (c *Client) getAPIClient(auth Auth, conf Config) error {
	if c.Token == "" {
		token, err := c.login(auth, conf)
		if err != nil {
			return fmt.Errorf("Error with credentials provided: %v", err)
		}
		fmt.Printf("Returned token %s \n", token)

	}
	return nil
}

func (c *Client) buildNode(auth Auth, conf Config, nodeData serverData, nodeType string) (string, error) {
	token, err := c.login(auth, conf)
	if err != nil {
		return "", fmt.Errorf("Error with auth: %v", err)
	}

	var url = conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/servers"

	fmt.Println("After login returned with token", token)

	jsonStr, parseErr := json.Marshal(nodeData)
	if parseErr != nil {
		return "", fmt.Errorf("Error with server data format: %v", parseErr)
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("X-Auth-Token", token)
	req.Header.Set("Content-Type", "application/json")

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}

	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)

	body, _ := ioutil.ReadAll(resp.Body)

	if isValidJSON(string(body)) == false {
		return "", errors.New("Not a valid JSON response: " + string(body))
	}

	jsonParsed, err := gabs.ParseJSON(body)

	var message, nodeID string

	if jsonParsed.Exists("overLimit", "code") {
		var code = jsonParsed.Path("overLimit.code").String()
		if code == "413" {
			message = "Out of space"
			fmt.Println("message:", message)
		}
	}

	if jsonParsed.Exists("badRequest") {
		message = jsonParsed.Path("badRequest.message").String()
		fmt.Println("message:", message)

	}
	if jsonParsed.Exists("server", "id") {
		nodeID = jsonParsed.Path("server.id").String()
		fmt.Println("nodeID:", nodeID)
	}
	if nodeID == "" {
		message = "Unknown error"
	}
	if message != "" {
		return "", errors.New(message)
	}

	return nodeID, nil

}

func (c *Client) downloadInitScript(url string) (string, error) {

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	return string(body), nil

}

func (c *Client) parseObj(body []byte, objNode string, idfield string, namefield string) (map[string]string, error) {
	var objMap map[string]string = make(map[string]string)
	jsonParsed, err := gabs.ParseJSON(body)
	if err != nil {
		return nil, err
	}
	if jsonParsed.Exists(objNode) {
		ids := s.TrimLeft(jsonParsed.Path(fmt.Sprintf("%s.%s", objNode, idfield)).String(), "[")
		ids = s.TrimRight(ids, "]")
		idarray := s.Split(ids, ",")
		names := s.TrimLeft(jsonParsed.Path(fmt.Sprintf("%s.%s", objNode, namefield)).String(), "[")
		names = s.TrimRight(names, "]")
		namearray := s.Split(names, ",")
		count := len(idarray)
		for i := 0; i < count; i++ {
			objMap[idarray[i]] = namearray[i]
		}
	}
	return objMap, nil
}

func (c *Client) listImages(auth Auth, conf Config) (map[string]string, error) {
	objType := "images"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load images. %v", err))
	}
	objMap, errParse := c.parseObj(body, "images", "id", "name")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) listFlavors(auth Auth, conf Config) (map[string]string, error) {
	objType := "flavors"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load flavors. %v", err))
	}

	objMap, errParse := c.parseObj(body, "flavors", "id", "name")
	if errParse != nil {
		return nil, errParse
	}
	return objMap, nil
}

func (c *Client) listNetworks(auth Auth, conf Config) (map[string]string, error) {
	objType := "networks"
	url := conf.Urlnet + conf.Apivernet + "/" + objType
	fmt.Println("Network URL", url)
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load networks. %v", err))
	}

	objMap, errParse := c.parseObj(body, "networks", "id", "name")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) listSecGroups(auth Auth, conf Config) (map[string]string, error) {
	objType := "os-security-groups"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load security groups. %v", err))
	}
	objMap, errParse := c.parseObj(body, "security_groups", "id", "name")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) listFloatingIPs(auth Auth, conf Config) (map[string]string, error) {
	objType := "os-floating-ips"
	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/" + objType
	body, err := c.listObjects(auth, conf, url, objType)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Cannot load security groups. %v", err))
	}
	objMap, errParse := c.parseObj(body, "floating_ips", "ip", "ip")
	if errParse != nil {
		return nil, errParse
	}

	return objMap, nil
}

func (c *Client) assignFloatingIP(auth Auth, conf Config, serverID string, ip string) error {
	token, err := c.login(auth, conf)
	if err != nil {
		return fmt.Errorf("Error with auth: %v", err)
	}

	url := conf.Urlcomp + conf.Apivercomp + "/" + auth.Body.Tenant + "/servers/" + serverID + "/action"
	fmt.Println("Action URL:>", url)

	var actionObj floatingIPAction
	actionObj.AddFloatingIp.Address = ip

	jsonStr, parseErr := json.Marshal(actionObj)
	log.Println("Serialized floating IP structure", string(jsonStr))
	if parseErr != nil {
		log.Println("Something is wrong with action body", parseErr)
		return fmt.Errorf("Something is wrong with auth body: %v", parseErr)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("X-Auth-Token", token)
	req.Header.Set("Content-Type", "application/json")

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}
	resp, err := client.Do(req)
	body, _ := ioutil.ReadAll(resp.Body)
	log.Println("Floating IP resp", string(body), err)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	return err
}

func (c *Client) listObjects(auth Auth, conf Config, url string, objType string) ([]byte, error) {
	token, err := c.login(auth, conf)
	if err != nil {
		return nil, fmt.Errorf("Error with auth: %v", err)
	}

	req, err := http.NewRequest("GET", url, nil)
	req.Header.Set("X-Auth-Token", token)

	tr := http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: &tr,
		Timeout:   30 * time.Second,
	}

	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)

	body, _ := ioutil.ReadAll(resp.Body)

	if isValidJSON(string(body)) == false {
		return nil, errors.New("Not a valid JSON response: " + string(body))
	}
	return body, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"restic/backend"
	"restic/debug"
	"restic/pack"
	"restic/repository"
	"restic/worker"
)

type CmdRebuildIndex struct {
	global *GlobalOptions

	repo *repository.Repository
}

func init() {
	_, err := parser.AddCommand("rebuild-index",
		"rebuild the index",
		"The rebuild-index command builds a new index",
		&CmdRebuildIndex{global: &globalOpts})
	if err != nil {
		panic(err)
	}
}

const rebuildIndexWorkers = 10

func loadBlobsFromPacks(repo *repository.Repository) (packs map[backend.ID][]pack.Blob) {
	done := make(chan struct{})
	defer close(done)

	f := func(job worker.Job, done <-chan struct{}) (interface{}, error) {
		return repo.ListPack(job.Data.(backend.ID))
	}

	jobCh := make(chan worker.Job)
	resCh := make(chan worker.Job)
	wp := worker.New(rebuildIndexWorkers, f, jobCh, resCh)

	go func() {
		for id := range repo.List(backend.Data, done) {
			jobCh <- worker.Job{Data: id}
		}
		close(jobCh)
	}()

	packs = make(map[backend.ID][]pack.Blob)
	for job := range resCh {
		id := job.Data.(backend.ID)

		if job.Error != nil {
			fmt.Fprintf(os.Stderr, "error for pack %v: %v\n", id, job.Error)
			continue
		}

		entries := job.Result.([]pack.Blob)
		packs[id] = entries
	}

	wp.Wait()

	return packs
}

func listIndexIDs(repo *repository.Repository) (list backend.IDs) {
	done := make(chan struct{})
	for id := range repo.List(backend.Index, done) {
		list = append(list, id)
	}

	return list
}

func (cmd CmdRebuildIndex) rebuildIndex() error {
	debug.Log("RebuildIndex.RebuildIndex", "start rebuilding index")

	packs := loadBlobsFromPacks(cmd.repo)
	cmd.global.Verbosef("loaded blobs from %d packs\n", len(packs))

	idx := repository.NewIndex()
	for packID, entries := range packs {
		for _, entry := range entries {
			pb := repository.PackedBlob{
				ID:     entry.ID,
				Type:   entry.Type,
				Length: entry.Length,
				Offset: entry.Offset,
				PackID: packID,
			}
			idx.Store(pb)
		}
	}

	oldIndexes := listIndexIDs(cmd.repo)
	idx.AddToSupersedes(oldIndexes...)
	cmd.global.Printf("  saving new index\n")
	id, err := repository.SaveIndex(cmd.repo, idx)
	if err != nil {
		debug.Log("RebuildIndex.RebuildIndex", "error saving index: %v", err)
		return err
	}
	debug.Log("RebuildIndex.RebuildIndex", "new index saved as %v", id.Str())

	for _, indexID := range oldIndexes {
		err := cmd.repo.Backend().Remove(backend.Index, indexID.String())
		if err != nil {
			cmd.global.Warnf("unable to remove index %v: %v\n", indexID.Str(), err)
		}
	}

	return nil
}

func (cmd CmdRebuildIndex) Execute(args []string) error {
	repo, err := cmd.global.OpenRepository()
	if err != nil {
		return err
	}
	cmd.repo = repo

	lock, err := lockRepoExclusive(repo)
	defer unlockRepo(lock)
	if err != nil {
		return err
	}

	return cmd.rebuildIndex()
}
<commit_msg>Make `rebuild-index` use the code in package repository<commit_after>package main

import "restic/repository"

type CmdRebuildIndex struct {
	global *GlobalOptions

	repo *repository.Repository
}

func init() {
	_, err := parser.AddCommand("rebuild-index",
		"rebuild the index",
		"The rebuild-index command builds a new index",
		&CmdRebuildIndex{global: &globalOpts})
	if err != nil {
		panic(err)
	}
}

func (cmd CmdRebuildIndex) Execute(args []string) error {
	repo, err := cmd.global.OpenRepository()
	if err != nil {
		return err
	}
	cmd.repo = repo

	lock, err := lockRepoExclusive(repo)
	defer unlockRepo(lock)
	if err != nil {
		return err
	}

	return repository.RebuildIndex(repo)
}
<|endoftext|>