<commit_before>package eng

import (
	gl "github.com/chsc/gogl/gl21"
	"image"
	"image/draw"
	_ "image/png"
	"io"
	"log"
	"os"
)

type Texture struct {
	id     gl.Uint
	width  int
	height int
}

func NewTexture(data interface{}) *Texture {
	var reader io.Reader

	switch data := data.(type) {
	default:
		log.Fatal("NewTexture needs a string or io.Reader")
	case string:
		file, err := os.Open(data)
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()
		reader = file
	case io.Reader:
		reader = data
	}

	m, _, err := image.Decode(reader)
	if err != nil {
		panic(err)
	}

	b := m.Bounds()
	newm := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
	draw.Draw(newm, newm.Bounds(), m, b.Min, draw.Src)

	width := m.Bounds().Max.X
	height := m.Bounds().Max.Y

	var id gl.Uint
	gl.GenTextures(1, &id)

	gl.Enable(gl.TEXTURE_2D)
	gl.BindTexture(gl.TEXTURE_2D, id)

	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(width), gl.Sizei(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&newm.Pix[0]))

	gl.Disable(gl.TEXTURE_2D)

	return &Texture{id, width, height}
}

func (t *Texture) Split(w, h int) []*Region {
	x := 0
	y := 0
	width := t.Width()
	height := t.Height()

	rows := height / h
	cols := width / w

	startX := x
	tiles := make([]*Region, 0)
	for row := 0; row < rows; row++ {
		x = startX
		for col := 0; col < cols; col++ {
			tiles = append(tiles, NewRegion(t, x, y, w, h))
			x += w
		}
		y += h
	}

	return tiles
}

func (t *Texture) Delete() {
	gl.DeleteTextures(1, &t.id)
}

func (t *Texture) Bind() {
	gl.BindTexture(gl.TEXTURE_2D, t.id)
}

func (t *Texture) Unbind() {
	gl.BindTexture(gl.TEXTURE_2D, 0)
}

func (t *Texture) Width() int {
	return t.width
}

func (t *Texture) Height() int {
	return t.height
}
<commit_msg>Added setting and getting texture filter and wrap<commit_after>package eng

import (
	gl "github.com/chsc/gogl/gl21"
	"image"
	"image/draw"
	_ "image/png"
	"io"
	"log"
	"os"
)

const (
	FilterNearest      = gl.NEAREST
	FilterLinear       = gl.LINEAR
	WrapClampToEdge    = gl.CLAMP_TO_EDGE
	WrapRepeat         = gl.REPEAT
	WrapMirroredRepeat = gl.MIRRORED_REPEAT
)

type Texture struct {
	id        gl.Uint
	width     int
	height    int
	minFilter gl.Int
	maxFilter gl.Int
	uWrap     gl.Int
	vWrap     gl.Int
}

func NewTexture(data interface{}) *Texture {
	var reader io.Reader

	switch data := data.(type) {
	default:
		log.Fatal("NewTexture needs a string or io.Reader")
	case string:
		file, err := os.Open(data)
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()
		reader = file
	case io.Reader:
		reader = data
	}

	m, _, err := image.Decode(reader)
	if err != nil {
		panic(err)
	}

	b := m.Bounds()
	newm := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
	draw.Draw(newm, newm.Bounds(), m, b.Min, draw.Src)

	width := m.Bounds().Max.X
	height := m.Bounds().Max.Y

	var id gl.Uint
	gl.GenTextures(1, &id)

	gl.Enable(gl.TEXTURE_2D)
	gl.BindTexture(gl.TEXTURE_2D, id)

	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)

	gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(width), gl.Sizei(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&newm.Pix[0]))

	gl.Disable(gl.TEXTURE_2D)

	return &Texture{id, width, height, gl.NEAREST, gl.NEAREST, gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE}
}

func (t *Texture) Split(w, h int) []*Region {
	x := 0
	y := 0
	width := t.Width()
	height := t.Height()

	rows := height / h
	cols := width / w

	startX := x
	tiles := make([]*Region, 0)
	for row := 0; row < rows; row++ {
		x = startX
		for col := 0; col < cols; col++ {
			tiles = append(tiles, NewRegion(t, x, y, w, h))
			x += w
		}
		y += h
	}

	return tiles
}

func (t *Texture) Delete() {
	gl.DeleteTextures(1, &t.id)
}

func (t *Texture) Bind() {
	gl.BindTexture(gl.TEXTURE_2D, t.id)
}

func (t *Texture) Unbind() {
	gl.BindTexture(gl.TEXTURE_2D, 0)
}

func (t *Texture) Width() int {
	return t.width
}

func (t *Texture) Height() int {
	return t.height
}

func (t *Texture) SetFilter(min, max gl.Int) {
	t.minFilter = min
	t.maxFilter = max
	t.Bind()
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, min)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, max)
}

func (t *Texture) Filter() (gl.Int, gl.Int) {
	return t.minFilter, t.maxFilter
}

func (t *Texture) SetWrap(u, v gl.Int) {
	t.uWrap = u
	t.vWrap = v
	t.Bind()
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, u)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, v)
}

func (t *Texture) Wrap() (gl.Int, gl.Int) {
	return t.uWrap, t.vWrap
}
<|endoftext|>


<commit_before>package main

import "github.com/nsf/gothic"
import "big"

var args [2]*big.Int
var lastOp string
var afterOp = true

func applyOp(op string, text *gothic.StringVar) {
	num := text.Get()
	if args[0] == nil {
		if op != "=" {
			args[0] = big.NewInt(0)
			args[0].SetString(num, 10)
		}
	} else {
		args[1] = big.NewInt(0)
		args[1].SetString(num, 10)
	}

	afterOp = true

	if args[1] == nil {
		lastOp = op
		return
	}

	switch lastOp {
	case "+":
		args[0] = args[0].Add(args[0], args[1])
	case "-":
		args[0] = args[0].Sub(args[0], args[1])
	case "/":
		args[0] = args[0].Div(args[0], args[1])
	case "*":
		args[0] = args[0].Mul(args[0], args[1])
	}

	lastOp = op
	args[1] = nil

	text.Set(args[0].String())
	if op == "=" {
		args[0] = nil
	}
}

func main() {
	ir, err := gothic.NewInterpreter()
	if err != nil {
		panic(err)
	}

	lastOpVar := ir.NewStringVar("lastOp")
	calcTextVar := ir.NewStringVar("calcText")
	calcTextVar.Set("0")

	ir.RegisterCallback("appendNum", func(n string) {
		if afterOp {
			afterOp = false
			calcTextVar.Set("")
		}
		calcTextVar.Set(calcTextVar.Get() + n)
	})

	ir.RegisterCallback("applyOp", func(op string) {
		if afterOp {
			return
		}
		applyOp(op, calcTextVar)
		lastOpVar.Set(lastOp)
	})

	ir.RegisterCallback("clearAll", func() {
		args[0] = nil
		args[1] = nil
		afterOp = true
		lastOp = ""
		lastOpVar.Set("")
		calcTextVar.Set("0")
	})

	ir.RegisterCallback("plusMinus", func() {
		text := calcTextVar.Get()
		if len(text) == 0 || text[0] == '0' {
			return
		}

		if text[0] == '-' {
			calcTextVar.Set(text[1:])
		} else {
			calcTextVar.Set("-" + text)
		}
	})

	ir.Eval(`
wm title . "GoCalculator"
grid [ttk::frame .f] -column 0 -row 0 -columnspan 3 -sticky we
grid [ttk::entry .f.lastop -textvariable lastOp -justify center -state readonly -width 3] -column 0 -row 0 -sticky we
grid [ttk::entry .f.entry -textvariable calcText -justify right -state readonly] -column 1 -row 0 -sticky we
grid columnconfigure .f 0 -weight 0
grid columnconfigure .f 1 -weight 1
grid [ttk::button .0 -text 0 -command { appendNum 0 }] -column 0 -row 4 -sticky nwes
grid [ttk::button .1 -text 1 -command { appendNum 1 }] -column 0 -row 3 -sticky nwes
grid [ttk::button .2 -text 2 -command { appendNum 2 }] -column 1 -row 3 -sticky nwes
grid [ttk::button .3 -text 3 -command { appendNum 3 }] -column 2 -row 3 -sticky nwes
grid [ttk::button .4 -text 4 -command { appendNum 4 }] -column 0 -row 2 -sticky nwes
grid [ttk::button .5 -text 5 -command { appendNum 5 }] -column 1 -row 2 -sticky nwes
grid [ttk::button .6 -text 6 -command { appendNum 6 }] -column 2 -row 2 -sticky nwes
grid [ttk::button .7 -text 7 -command { appendNum 7 }] -column 0 -row 1 -sticky nwes
grid [ttk::button .8 -text 8 -command { appendNum 8 }] -column 1 -row 1 -sticky nwes
grid [ttk::button .9 -text 9 -command { appendNum 9 }] -column 2 -row 1 -sticky nwes
grid [ttk::button .pm    -text +/- -command plusMinus]   -column 1 -row 4 -sticky nwes
grid [ttk::button .clear -text C -command clearAll]      -column 2 -row 4 -sticky nwes
grid [ttk::button .eq    -text = -command { applyOp = }] -column 3 -row 4 -sticky nwes
grid [ttk::button .plus  -text + -command { applyOp + }] -column 3 -row 3 -sticky nwes
grid [ttk::button .minus -text - -command { applyOp - }] -column 3 -row 2 -sticky nwes
grid [ttk::button .mul   -text * -command { applyOp * }] -column 3 -row 1 -sticky nwes
grid [ttk::button .div   -text / -command { applyOp / }] -column 3 -row 0 -sticky nwes

foreach w [winfo children .] {grid configure $w -padx 3 -pady 3}

grid rowconfigure . 0 -weight 0
grid rowconfigure . 1 -weight 1
grid rowconfigure . 2 -weight 1
grid rowconfigure . 3 -weight 1
grid rowconfigure . 4 -weight 1
grid columnconfigure . 0 -weight 1
grid columnconfigure . 1 -weight 1
grid columnconfigure . 2 -weight 1
grid columnconfigure . 3 -weight 1

bind . 0             { appendNum 0 }
bind . 1             { appendNum 1 }
bind . 2             { appendNum 2 }
bind . 3             { appendNum 3 }
bind . 4             { appendNum 4 }
bind . 5             { appendNum 5 }
bind . 6             { appendNum 6 }
bind . 7             { appendNum 7 }
bind . 8             { appendNum 8 }
bind . 9             { appendNum 9 }
bind . <KP_Insert>   { appendNum 0 }
bind . <KP_End>      { appendNum 1 }
bind . <KP_Down>     { appendNum 2 }
bind . <KP_Next>     { appendNum 3 }
bind . <KP_Left>     { appendNum 4 }
bind . <KP_Begin>    { appendNum 5 }
bind . <KP_Right>    { appendNum 6 }
bind . <KP_Home>     { appendNum 7 }
bind . <KP_Up>       { appendNum 8 }
bind . <KP_Prior>    { appendNum 9 }
bind . <KP_Add>      { applyOp + }
bind . <KP_Subtract> { applyOp - }
bind . <KP_Multiply> { applyOp * }
bind . <KP_Divide>   { applyOp / }
bind . <KP_Enter>    { applyOp = }
bind . <BackSpace>   { clearAll }
	`)
	ir.MainLoop()
}
<commit_msg>Fix wrong behaviour in calc example.<commit_after>package main

import "github.com/nsf/gothic"
import "big"

var args [2]*big.Int
var lastOp string
var afterOp = true

func applyOp(op string, text *gothic.StringVar) {
	num := text.Get()
	if args[0] == nil {
		if op != "=" {
			args[0] = big.NewInt(0)
			args[0].SetString(num, 10)
		}
	} else {
		args[1] = big.NewInt(0)
		args[1].SetString(num, 10)
	}

	afterOp = true

	if args[1] == nil {
		lastOp = op
		return
	}

	switch lastOp {
	case "+":
		args[0] = args[0].Add(args[0], args[1])
	case "-":
		args[0] = args[0].Sub(args[0], args[1])
	case "/":
		args[0] = args[0].Div(args[0], args[1])
	case "*":
		args[0] = args[0].Mul(args[0], args[1])
	}

	lastOp = op
	args[1] = nil

	text.Set(args[0].String())
	if op == "=" {
		args[0] = nil
	}
}

func main() {
	ir, err := gothic.NewInterpreter()
	if err != nil {
		panic(err)
	}

	lastOpVar := ir.NewStringVar("lastOp")
	calcTextVar := ir.NewStringVar("calcText")
	calcTextVar.Set("0")

	ir.RegisterCallback("appendNum", func(n string) {
		if afterOp {
			afterOp = false
			calcTextVar.Set("")
		}
		calcTextVar.Set(calcTextVar.Get() + n)
	})

	ir.RegisterCallback("applyOp", func(op string) {
		if afterOp && lastOp != "=" {
			return
		}
		applyOp(op, calcTextVar)
		lastOpVar.Set(lastOp)
	})

	ir.RegisterCallback("clearAll", func() {
		args[0] = nil
		args[1] = nil
		afterOp = true
		lastOp = ""
		lastOpVar.Set("")
		calcTextVar.Set("0")
	})

	ir.RegisterCallback("plusMinus", func() {
		text := calcTextVar.Get()
		if len(text) == 0 || text[0] == '0' {
			return
		}

		if text[0] == '-' {
			calcTextVar.Set(text[1:])
		} else {
			calcTextVar.Set("-" + text)
		}
	})

	ir.Eval(`
wm title . "GoCalculator"
grid [ttk::frame .f] -column 0 -row 0 -columnspan 3 -sticky we
grid [ttk::entry .f.lastop -textvariable lastOp -justify center -state readonly -width 3] -column 0 -row 0 -sticky we
grid [ttk::entry .f.entry -textvariable calcText -justify right -state readonly] -column 1 -row 0 -sticky we
grid columnconfigure .f 0 -weight 0
grid columnconfigure .f 1 -weight 1
grid [ttk::button .0 -text 0 -command { appendNum 0 }] -column 0 -row 4 -sticky nwes
grid [ttk::button .1 -text 1 -command { appendNum 1 }] -column 0 -row 3 -sticky nwes
grid [ttk::button .2 -text 2 -command { appendNum 2 }] -column 1 -row 3 -sticky nwes
grid [ttk::button .3 -text 3 -command { appendNum 3 }] -column 2 -row 3 -sticky nwes
grid [ttk::button .4 -text 4 -command { appendNum 4 }] -column 0 -row 2 -sticky nwes
grid [ttk::button .5 -text 5 -command { appendNum 5 }] -column 1 -row 2 -sticky nwes
grid [ttk::button .6 -text 6 -command { appendNum 6 }] -column 2 -row 2 -sticky nwes
grid [ttk::button .7 -text 7 -command { appendNum 7 }] -column 0 -row 1 -sticky nwes
grid [ttk::button .8 -text 8 -command { appendNum 8 }] -column 1 -row 1 -sticky nwes
grid [ttk::button .9 -text 9 -command { appendNum 9 }] -column 2 -row 1 -sticky nwes
grid [ttk::button .pm    -text +/- -command plusMinus]   -column 1 -row 4 -sticky nwes
grid [ttk::button .clear -text C -command clearAll]      -column 2 -row 4 -sticky nwes
grid [ttk::button .eq    -text = -command { applyOp = }] -column 3 -row 4 -sticky nwes
grid [ttk::button .plus  -text + -command { applyOp + }] -column 3 -row 3 -sticky nwes
grid [ttk::button .minus -text - -command { applyOp - }] -column 3 -row 2 -sticky nwes
grid [ttk::button .mul   -text * -command { applyOp * }] -column 3 -row 1 -sticky nwes
grid [ttk::button .div   -text / -command { applyOp / }] -column 3 -row 0 -sticky nwes

foreach w [winfo children .] {grid configure $w -padx 3 -pady 3}

grid rowconfigure . 0 -weight 0
grid rowconfigure . 1 -weight 1
grid rowconfigure . 2 -weight 1
grid rowconfigure . 3 -weight 1
grid rowconfigure . 4 -weight 1
grid columnconfigure . 0 -weight 1
grid columnconfigure . 1 -weight 1
grid columnconfigure . 2 -weight 1
grid columnconfigure . 3 -weight 1

bind . 0             { appendNum 0 }
bind . 1             { appendNum 1 }
bind . 2             { appendNum 2 }
bind . 3             { appendNum 3 }
bind . 4             { appendNum 4 }
bind . 5             { appendNum 5 }
bind . 6             { appendNum 6 }
bind . 7             { appendNum 7 }
bind . 8             { appendNum 8 }
bind . 9             { appendNum 9 }
bind . <KP_Insert>   { appendNum 0 }
bind . <KP_End>      { appendNum 1 }
bind . <KP_Down>     { appendNum 2 }
bind . <KP_Next>     { appendNum 3 }
bind . <KP_Left>     { appendNum 4 }
bind . <KP_Begin>    { appendNum 5 }
bind . <KP_Right>    { appendNum 6 }
bind . <KP_Home>     { appendNum 7 }
bind . <KP_Up>       { appendNum 8 }
bind . <KP_Prior>    { appendNum 9 }
bind . <KP_Add>      { applyOp + }
bind . <KP_Subtract> { applyOp - }
bind . <KP_Multiply> { applyOp * }
bind . <KP_Divide>   { applyOp / }
bind . <KP_Enter>    { applyOp = }
bind . <BackSpace>   { clearAll }
	`)
	ir.MainLoop()
}
<|endoftext|>


<commit_before>package brew

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"strings"

	"github.com/alecthomas/template"
	"github.com/google/go-github/github"
	"github.com/goreleaser/releaser/config"
	"golang.org/x/oauth2"
)

const formulae = `class {{ .Name }} < Formula
  desc "{{ .Desc }}"
  homepage "{{ .Homepage }}"
  url "https://github.com/{{ .Repo }}/releases/download/{{ .Tag }}/{{ .BinaryName }}_Darwin_x86_64.tar.gz"
  head "https://github.com/{{ .Repo }}.git"

  def install
    bin.install "{{ .BinaryName }}"
  end
end
`

type templateData struct {
	Name, Desc, Homepage, Repo, Tag, BinaryName string
}

func Brew(version string, config config.ProjectConfig) error {
	fmt.Println("Updating brew formulae...")
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config.Token},
	)
	tc := oauth2.NewClient(context.Background(), ts)
	client := github.NewClient(tc)
	parts := strings.Split(config.Brew.Repo, "/")

	tmpl, err := template.New(config.BinaryName).Parse(formulae)
	if err != nil {
		return err
	}

	data, err := dataFor(version, config, client)
	if err != nil {
		return err
	}

	var out bytes.Buffer
	tmpl.Execute(&out, data)

	_, _, err = client.Repositories.UpdateFile(
		parts[0],
		parts[1],
		config.BinaryName+".rb",
		&github.RepositoryContentFileOptions{
			Committer: &github.CommitAuthor{
				Name:  github.String("goreleaserbot"),
				Email: github.String("bot@goreleaser"),
			},
			Content: out.Bytes(),
			Message: github.String(config.BinaryName + " version " + version),
			SHA:     github.String(fmt.Sprintf("%s", sha256.Sum256(out.Bytes()))),
		},
	)
	return err
}

func dataFor(version string, config config.ProjectConfig, client *github.Client) (result templateData, err error) {
	var homepage string
	var description string
	parts := strings.Split(config.Repo, "/")
	rep, _, err := client.Repositories.Get(parts[0], parts[1])
	if err != nil {
		return result, err
	}
	if rep.Homepage == nil {
		homepage = *rep.HTMLURL
	} else {
		homepage = *rep.Homepage
	}
	if rep.Description == nil {
		description = "TODO"
	} else {
		description = *rep.Description
	}
	return templateData{
		Name:       strings.Title(config.BinaryName),
		Desc:       description,
		Homepage:   homepage,
		Repo:       config.Repo,
		Tag:        version,
		BinaryName: config.BinaryName,
	}, err
}
<commit_msg>fix import<commit_after>package brew

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"html/template"
	"strings"

	"github.com/google/go-github/github"
	"github.com/goreleaser/releaser/config"
	"golang.org/x/oauth2"
)

const formulae = `class {{ .Name }} < Formula
  desc "{{ .Desc }}"
  homepage "{{ .Homepage }}"
  url "https://github.com/{{ .Repo }}/releases/download/{{ .Tag }}/{{ .BinaryName }}_Darwin_x86_64.tar.gz"
  head "https://github.com/{{ .Repo }}.git"

  def install
    bin.install "{{ .BinaryName }}"
  end
end
`

type templateData struct {
	Name, Desc, Homepage, Repo, Tag, BinaryName string
}

func Brew(version string, config config.ProjectConfig) error {
	fmt.Println("Updating brew formulae...")
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config.Token},
	)
	tc := oauth2.NewClient(context.Background(), ts)
	client := github.NewClient(tc)
	parts := strings.Split(config.Brew.Repo, "/")

	tmpl, err := template.New(config.BinaryName).Parse(formulae)
	if err != nil {
		return err
	}

	data, err := dataFor(version, config, client)
	if err != nil {
		return err
	}

	var out bytes.Buffer
	tmpl.Execute(&out, data)

	_, _, err = client.Repositories.UpdateFile(
		parts[0],
		parts[1],
		config.BinaryName+".rb",
		&github.RepositoryContentFileOptions{
			Committer: &github.CommitAuthor{
				Name:  github.String("goreleaserbot"),
				Email: github.String("bot@goreleaser"),
			},
			Content: out.Bytes(),
			Message: github.String(config.BinaryName + " version " + version),
			SHA:     github.String(fmt.Sprintf("%s", sha256.Sum256(out.Bytes()))),
		},
	)
	return err
}

func dataFor(version string, config config.ProjectConfig, client *github.Client) (result templateData, err error) {
	var homepage string
	var description string
	parts := strings.Split(config.Repo, "/")
	rep, _, err := client.Repositories.Get(parts[0], parts[1])
	if err != nil {
		return result, err
	}
	if rep.Homepage == nil {
		homepage = *rep.HTMLURL
	} else {
		homepage = *rep.Homepage
	}
	if rep.Description == nil {
		description = "TODO"
	} else {
		description = *rep.Description
	}
	return templateData{
		Name:       strings.Title(config.BinaryName),
		Desc:       description,
		Homepage:   homepage,
		Repo:       config.Repo,
		Tag:        version,
		BinaryName: config.BinaryName,
	}, err
}
<|endoftext|>


<commit_before>package glplus

import (
	"fmt"
	"image"
	"image/draw"
	_ "image/png" // just because
	"os"

	gl "github.com/go-gl/gl/v4.1-core/gl"
)

// Texture ...
type Texture struct {
	texture uint32
	Size    image.Point
}

// GenTexture ...
func GenTexture(size image.Point) (texture *Texture) {
	var t uint32
	gl.GenTextures(1, &t)
	texture = &Texture{t, size}
	return texture
}

// Handle ...
func (t *Texture) Handle() uint32 {
	return t.texture
}

// DeleteTexture ...
func (t *Texture) DeleteTexture() {
	if t.texture != 0 {
		gl.DeleteTextures(1, &t.texture)
	}
}

// BindTexture ...
func (t *Texture) BindTexture(unit uint32) {
	gl.ActiveTexture(gl.TEXTURE0 + unit)
	gl.BindTexture(gl.TEXTURE_2D, t.texture)
}

// UnbindTexture ...
func (t *Texture) UnbindTexture(unit uint32) {
	gl.ActiveTexture(gl.TEXTURE0 + unit)
	gl.BindTexture(gl.TEXTURE_2D, 0)
}

// NewTexture ...
func NewTexture(file string, linear bool, repeat bool) (texture *Texture, img image.Image, err error) {
	var imgFile *os.File
	if imgFile, err = os.Open(file); err != nil {
		return nil, img, err
	}
	defer imgFile.Close()

	if img, _, err = image.Decode(imgFile); err != nil {
		return nil, img, err
	}

	var rgba *image.RGBA

	rgba = image.NewRGBA(img.Bounds())
	if rgba.Stride != rgba.Rect.Size().X*4 {
		return nil, img, fmt.Errorf("unsupported stride")
	}
	draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)

	texture = GenTexture(rgba.Rect.Size())

	texture.BindTexture(0)
	if linear {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	} else {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	}
	if repeat {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
	} else {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	}
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0,
		gl.RGBA,
		int32(rgba.Rect.Size().X),
		int32(rgba.Rect.Size().Y),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(rgba.Pix))

	return texture, img, nil
}
<commit_msg>NewRGBATexture<commit_after>package glplus

import (
	"fmt"
	"image"
	"image/draw"
	_ "image/png" // just because
	"os"

	gl "github.com/go-gl/gl/v4.1-core/gl"
)

// Texture ...
type Texture struct {
	texture uint32
	Size    image.Point
}

// GenTexture ...
func GenTexture(size image.Point) (texture *Texture) {
	var t uint32
	gl.GenTextures(1, &t)
	texture = &Texture{t, size}
	return texture
}

// Handle ...
func (t *Texture) Handle() uint32 {
	return t.texture
}

// DeleteTexture ...
func (t *Texture) DeleteTexture() {
	if t.texture != 0 {
		gl.DeleteTextures(1, &t.texture)
	}
}

// BindTexture ...
func (t *Texture) BindTexture(unit uint32) {
	gl.ActiveTexture(gl.TEXTURE0 + unit)
	gl.BindTexture(gl.TEXTURE_2D, t.texture)
}

// UnbindTexture ...
func (t *Texture) UnbindTexture(unit uint32) {
	gl.ActiveTexture(gl.TEXTURE0 + unit)
	gl.BindTexture(gl.TEXTURE_2D, 0)
}

// NewRGBATexture ...
func NewRGBATexture(rgba *image.RGBA, linear, repeat bool) (texture *Texture, err error) {
	if rgba.Stride != rgba.Rect.Size().X*4 {
		return nil, fmt.Errorf("unsupported stride")
	}

	texture = GenTexture(rgba.Rect.Size())

	texture.BindTexture(0)
	if linear {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	} else {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
	}
	if repeat {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
	} else {
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	}
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0,
		gl.RGBA,
		int32(rgba.Rect.Size().X),
		int32(rgba.Rect.Size().Y),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(rgba.Pix))
	texture.UnbindTexture(0)

	return texture, nil
}

// LoadTexture ...
func LoadTexture(file string, linear, repeat bool) (texture *Texture, img image.Image, err error) {
	var imgFile *os.File
	if imgFile, err = os.Open(file); err != nil {
		return nil, img, err
	}
	defer imgFile.Close()

	if img, _, err = image.Decode(imgFile); err != nil {
		return nil, img, err
	}

	var rgba *image.RGBA

	rgba = image.NewRGBA(img.Bounds())
	draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)

	if texture, err = NewRGBATexture(rgba, linear, repeat); err != nil {
		return nil, img, err
	}

	return texture, img, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	"github.com/coreos/go-tspi/tspi"
	"github.com/coreos/go-tspi/tspiconst"
)

var wellKnown [20]byte

func main () {
	enable := []byte("6")
	activate := []byte("3")
	val, err := ioutil.ReadFile("/sys/class/tpm/tpm0/device/enabled")
	if os.IsNotExist(err) {
		log.Fatalf("System has no tpm")
	}

	if bytes.Equal(val, []byte("0\n")) {
		ioutil.WriteFile("/sys/class/tpm/tpm0/device/ppi/request", enable, 0664)
		exec.Command("reboot", "").Run()
	}

	val, err = ioutil.ReadFile("/sys/class/tpm/tpm0/device/active")

	if  bytes.Equal(val, []byte("0\n")) {
		ioutil.WriteFile("/sys/class/tpm/tpm0/device/ppi/request", activate, 0664)
		exec.Command("reboot", "").Run()
	}

	val, err = ioutil.ReadFile("/sys/class/tpm/tpm0/device/owned")
	if  bytes.Equal(val, []byte("0\n")) {
		context, err := tspi.NewContext()
		if err != nil {
			log.Fatalf("Unable to create TSS context")
		}

		context.Connect()
		tpm := context.GetTPM()
		tpmpolicy, err := tpm.GetPolicy(tspiconst.TSS_POLICY_USAGE)
		if err != nil {
			log.Fatalf("Unable to obtain TPM policy")
		}
		err = tpmpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
		if err != nil {
			log.Fatalf("Unable to set TPM policy")
		}

		srk, err := context.CreateKey(tspiconst.TSS_KEY_TSP_SRK | tspiconst.TSS_KEY_AUTHORIZATION)
		if err != nil {
			log.Fatalf("Unable to create SRK")
		}
		keypolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
		if err != nil {
			log.Fatalf("Unable to obtain SRK policy")
		}
		err = keypolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
		if err != nil {
			log.Fatalf("Unable to set SRK policy")
		}

		err = tpm.TakeOwnership(srk)

		if err != nil {
			log.Fatalf("Unable to take ownership of TPM")
		}
	}

}
<commit_msg>Print the error on failure<commit_after>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	"github.com/coreos/go-tspi/tspi"
	"github.com/coreos/go-tspi/tspiconst"
)

var wellKnown [20]byte

func main () {
	enable := []byte("6")
	activate := []byte("3")
	val, err := ioutil.ReadFile("/sys/class/tpm/tpm0/device/enabled")
	if os.IsNotExist(err) {
		log.Fatalf("System has no tpm")
	}

	if bytes.Equal(val, []byte("0\n")) {
		ioutil.WriteFile("/sys/class/tpm/tpm0/device/ppi/request", enable, 0664)
		exec.Command("reboot", "").Run()
	}

	val, err = ioutil.ReadFile("/sys/class/tpm/tpm0/device/active")

	if  bytes.Equal(val, []byte("0\n")) {
		ioutil.WriteFile("/sys/class/tpm/tpm0/device/ppi/request", activate, 0664)
		exec.Command("reboot", "").Run()
	}

	val, err = ioutil.ReadFile("/sys/class/tpm/tpm0/device/owned")
	if  bytes.Equal(val, []byte("0\n")) {
		context, err := tspi.NewContext()
		if err != nil {
			log.Fatalf("Unable to create TSS context")
		}

		context.Connect()
		tpm := context.GetTPM()
		tpmpolicy, err := tpm.GetPolicy(tspiconst.TSS_POLICY_USAGE)
		if err != nil {
			log.Fatalf("Unable to obtain TPM policy")
		}
		err = tpmpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
		if err != nil {
			log.Fatalf("Unable to set TPM policy")
		}

		srk, err := context.CreateKey(tspiconst.TSS_KEY_TSP_SRK | tspiconst.TSS_KEY_AUTHORIZATION)
		if err != nil {
			log.Fatalf("Unable to create SRK")
		}
		keypolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
		if err != nil {
			log.Fatalf("Unable to obtain SRK policy")
		}
		err = keypolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
		if err != nil {
			log.Fatalf("Unable to set SRK policy")
		}

		err = tpm.TakeOwnership(srk)

		if err != nil {
			log.Fatalf("Unable to take ownership of TPM: %v", err)
		}
	}

}
<|endoftext|>


<commit_before>package printer

import (
	"bytes"
	"fmt"
	"github.com/tinylib/msgp/gen"
	"github.com/tinylib/msgp/parse"
	"github.com/ttacon/chalk"
	"golang.org/x/tools/imports"
	"io"
	"io/ioutil"
	"strings"
)

func infof(s string, v ...interface{}) {
	fmt.Printf(chalk.Magenta.Color(s), v...)
}

// PrintFile prints the methods for the provided list
// of elements to the given file name and canonical
// package path.
func PrintFile(file string, f *parse.FileSet, mode gen.Method) error {
	out, tests, err := generate(f, mode)
	if err != nil {
		return err
	}
	err = format(file, out.Bytes())
	if err != nil {
		return err
	}
	infof(">>> Wrote and formatted \"%s\"\n", file)
	if tests != nil {
		testfile := strings.TrimSuffix(file, ".go") + "_test.go"
		err = format(testfile, tests.Bytes())
		if err != nil {
			return err
		}
		infof(">>> Wrote and formatted \"%s\"\n", testfile)
	}
	infof(">>> Done.\n")
	return nil
}

func format(file string, data []byte) error {
	out, err := imports.Process(file, data, nil)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, out, 0600)
}

func generate(f *parse.FileSet, mode gen.Method) (*bytes.Buffer, *bytes.Buffer, error) {
	outbuf := bytes.NewBuffer(make([]byte, 0, 4096))
	writePkgHeader(outbuf, f.Package)
	writeImportHeader(outbuf, "github.com/tinylib/msgp/msgp")

	var testbuf *bytes.Buffer
	var testwr io.Writer
	if mode&gen.Test == gen.Test {
		testbuf = bytes.NewBuffer(make([]byte, 0, 4096))
		writePkgHeader(testbuf, f.Package)
		if mode&(gen.Encode|gen.Decode) != 0 {
			writeImportHeader(testbuf, "bytes", "github.com/tinylib/msgp/msgp", "testing")
		} else {
			writeImportHeader(testbuf, "github.com/tinylib/msgp/msgp", "testing")
		}
		testwr = testbuf
	}
	return outbuf, testbuf, f.PrintTo(gen.NewPrinter(mode, outbuf, testwr))
}

func writePkgHeader(b *bytes.Buffer, name string) {
	b.WriteString("package ")
	b.WriteString(name)
	b.WriteByte('\n')
	b.WriteString("// NOTE: THIS FILE WAS PRODUCED BY THE\n// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)\n// DO NOT EDIT\n\n")
}

func writeImportHeader(b *bytes.Buffer, imports ...string) {
	b.WriteString("import (\n")
	for _, im := range imports {
		fmt.Fprintf(b, "\t%q\n", im)
	}
	b.WriteString(")\n\n")
}
<commit_msg>run goimports in parallel<commit_after>package printer

import (
	"bytes"
	"fmt"
	"github.com/tinylib/msgp/gen"
	"github.com/tinylib/msgp/parse"
	"github.com/ttacon/chalk"
	"golang.org/x/tools/imports"
	"io"
	"io/ioutil"
	"strings"
)

func infof(s string, v ...interface{}) {
	fmt.Printf(chalk.Magenta.Color(s), v...)
}

// PrintFile prints the methods for the provided list
// of elements to the given file name and canonical
// package path.
func PrintFile(file string, f *parse.FileSet, mode gen.Method) error {
	out, tests, err := generate(f, mode)
	if err != nil {
		return err
	}

	// we'll run goimports on the main file
	// in another goroutine, and run it here
	// for the test file. empirically, this
	// takes about the same amount of time as
	// doing them in serial when GOMAXPROCS=1,
	// and faster otherwise.
	res := goformat(file, out.Bytes())
	if tests != nil {
		testfile := strings.TrimSuffix(file, ".go") + "_test.go"
		err = format(testfile, tests.Bytes())
		if err != nil {
			return err
		}
		infof(">>> Wrote and formatted \"%s\"\n", testfile)
	}
	err = <-res
	if err != nil {
		return err
	}
	infof(">>> Done.\n")
	return nil
}

func format(file string, data []byte) error {
	out, err := imports.Process(file, data, nil)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, out, 0600)
}

func goformat(file string, data []byte) <-chan error {
	out := make(chan error, 1)
	go func(file string, data []byte, end chan error) {
		end <- format(file, data)
		infof(">>> Wrote and formatted \"%s\"\n", file)
	}(file, data, out)
	return out
}

func generate(f *parse.FileSet, mode gen.Method) (*bytes.Buffer, *bytes.Buffer, error) {
	outbuf := bytes.NewBuffer(make([]byte, 0, 4096))
	writePkgHeader(outbuf, f.Package)
	writeImportHeader(outbuf, "github.com/tinylib/msgp/msgp")

	var testbuf *bytes.Buffer
	var testwr io.Writer
	if mode&gen.Test == gen.Test {
		testbuf = bytes.NewBuffer(make([]byte, 0, 4096))
		writePkgHeader(testbuf, f.Package)
		if mode&(gen.Encode|gen.Decode) != 0 {
			writeImportHeader(testbuf, "bytes", "github.com/tinylib/msgp/msgp", "testing")
		} else {
			writeImportHeader(testbuf, "github.com/tinylib/msgp/msgp", "testing")
		}
		testwr = testbuf
	}
	return outbuf, testbuf, f.PrintTo(gen.NewPrinter(mode, outbuf, testwr))
}

func writePkgHeader(b *bytes.Buffer, name string) {
	b.WriteString("package ")
	b.WriteString(name)
	b.WriteByte('\n')
	b.WriteString("// NOTE: THIS FILE WAS PRODUCED BY THE\n// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)\n// DO NOT EDIT\n\n")
}

func writeImportHeader(b *bytes.Buffer, imports ...string) {
	b.WriteString("import (\n")
	for _, im := range imports {
		fmt.Fprintf(b, "\t%q\n", im)
	}
	b.WriteString(")\n\n")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

var paths []string

var root string

func main() {
	fmt.Println("Tharsis Documentation Service")

	root = "/Users/ali/mockumentation/src"
	filepath.Walk(root, visit)
}

func visit(path string, f os.FileInfo, err error) error {

	p := strings.TrimPrefix(path, root)
	if strings.HasSuffix(p, ".md") {
		fmt.Printf("Found: %s\n", p)
		paths = append(paths, p)
	}

	return nil
}
<commit_msg>Removed hardcoded directory<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

var paths []string

var root string

func main() {
	fmt.Println("Tharsis Documentation Service")

	src := flag.String("src", "", "Source directory for markdown documentation")
	// out := flag.String("out", "", "HTML Output directory")
	flag.Parse()

	if *src == "" {
		fmt.Println("src directory is required")
		return
	}

	filepath.Walk(*src, visit)
}

func visit(path string, f os.FileInfo, err error) error {

	p := strings.TrimPrefix(path, root)
	if strings.HasSuffix(p, ".md") {
		fmt.Printf("Found: %s\n", p)
		paths = append(paths, p)
	}

	return nil
}
<|endoftext|>


<commit_before>package procfs

import (
	"io/ioutil"
	"os"
	"path"
	"strconv"
)

const procfsdir = "/proc"

type Filler interface {
	Fill()
}

type Lister interface {
	List(string)
}

type Getter interface {
	Get(string)
}

type ProcFS struct {
	Processes map[int]*Process
	Self      int
}

const (
	PROCFS_PROCESSES = "Processes"
	PROCFS_SELF = "Self"
)

func (pfs *ProcFS) Fill() {
	pfs.List(PROCFS_PROCESSES)
	pfs.Get(PROCFS_SELF)
}

func (pfs *ProcFS) List(k string) {
	switch k {
	case PROCFS_PROCESSES:
		if !exists(procfsdir) {
			return
		}
		pfs.Processes = make(map[int]*Process)
		ds, err := ioutil.ReadDir(procfsdir)
		if err != nil {
			return
		}
		// get all numeric entries
		for _, d := range ds {
			n := d.Name
			id, err := strconv.Atoi(n)
			if isNumeric(n) && err != nil {
				proc := Process{PID: id}
				pfs.Processes[id] = &proc
			}
		}
	}
}

func (pfs *ProcFS) Get(k string) {
	switch k {
	case PROCFS_SELF:
		var selfdir = path.Join(procfsdir, "self")
		if !exists(selfdir) {
			return
		}
		fi, _ := os.Readlink(selfdir)
		pfs.Self, _ = strconv.Atoi(fi)
	}
}

type Process struct {
	PID     int
	Auxv    []byte
	Cmdline []string
	Cwd     string
	Environ map[string]string
	Exe     string
	Fds     map[int]*Fd
	Root    string
	Status  map[string]string
	Threads map[int]*Thread
}
// TODO limits, maps, mem, mountinfo, mounts, mountstats, ns, smaps, stat

const (
	PROCFS_PROC_AUXV = "Process.Auxv"
	PROCFS_PROC_CMDLINE = "Process.Cmdline"
	PROCFS_PROC_CWD = "Process.Cwd"
	PROCFS_PROC_ENVIRON = "Process.Environ"
	PROCFS_PROC_EXE = "Process.Exe"
	PROCFS_PROC_ROOT = "Process.Root"
	PROCFS_PROC_STATUS = "Process.Status"

	PROCFS_PROC_FDS = "Process.Fds"
	PROCFS_PROC_THREADS = "Process.Threads"
)

func (p *Process) Fill() {
	p.Get(PROCFS_PROC_AUXV)
	p.Get(PROCFS_PROC_CMDLINE)
	p.Get(PROCFS_PROC_CWD)
	p.Get(PROCFS_PROC_ENVIRON)
	p.Get(PROCFS_PROC_EXE)
	p.Get(PROCFS_PROC_ROOT)
	p.Get(PROCFS_PROC_STATUS)

	// Fds
	p.List(PROCFS_PROC_FDS)
	for _, f := range p.Fds {
		f.Fill()
	}

	// Threads
	p.List(PROCFS_PROC_THREADS)
	for _, t := range p.Threads {
		t.Fill()
	}
}

func (p *Process) List(k string) {

}

func (p *Process) Get(k string) {
	pdir := path.Join(procfsdir, strconv.Itoa(p.PID))
	switch k {
	case PROCFS_PROC_AUXV:
		p.Auxv, _ = ioutil.ReadFile(path.Join(pdir, "auxv"))
	case PROCFS_PROC_CMDLINE:
		cl, err := ioutil.ReadFile(path.Join(pdir, "cmdline"))
		if err == nil {
			p.Cmdline = splitNull(cl)
		}
	case PROCFS_PROC_CWD:
		p.Cwd, _ = os.Readlink(path.Join(pdir, "cwd"))
	case PROCFS_PROC_ENVIRON:
	}
}

type Fd struct {
	Path  string
	Pos   int
	Flags int
}

const (
	PROCFS_PROC_FD_PATH = "Process.Fd.Path"
	PROCFS_PROC_FD_POS = "Process.Fd.Pos"
	PROCFS_PROC_FD_FLAGS = "Process.Fd.Flags"
)

func (f *Fd) Fill() {
	f.Get(PROCFS_PROC_FD_PATH)
	f.Get(PROCFS_PROC_FD_POS)
	f.Get(PROCFS_PROC_FD_FLAGS)
}

func (f *Fd) Get(k string) {
	switch k {

	}
}

type Thread struct {
	// TODO
}

func (t *Thread) Fill() {

}

func (t *Thread) Get(k string) {

}
<commit_msg>Changing the type of the process map to map[string]*Process<commit_after>package procfs

import (
	"io/ioutil"
	"os"
	"path"
	"strconv"
)

const procfsdir = "/proc"

type Filler interface {
	Fill()
}

type Lister interface {
	List(string)
}

type Getter interface {
	Get(string)
}

type ProcFS struct {
	Processes map[string]*Process
	Self      string
}

const (
	PROCFS_PROCESSES = "Processes"
	PROCFS_SELF = "Self"
)

func (pfs *ProcFS) Fill() {
	pfs.List(PROCFS_PROCESSES)
	pfs.Get(PROCFS_SELF)
}

func (pfs *ProcFS) List(k string) {
	switch k {
	case PROCFS_PROCESSES:
		if !exists(procfsdir) {
			return
		}
		pfs.Processes = make(map[string]*Process)
		ds, err := ioutil.ReadDir(procfsdir)
		if err != nil {
			return
		}
		// get all numeric entries
		for _, d := range ds {
			n := d.Name
			id, err := strconv.Atoi(n)
			if isNumeric(n) && err != nil {
				proc := Process{PID: id}
				pfs.Processes[n] = &proc
			}
		}
	}
}

func (pfs *ProcFS) Get(k string) {
	switch k {
	case PROCFS_SELF:
		var selfdir = path.Join(procfsdir, "self")
		if !exists(selfdir) {
			return
		}
		fi, _ := os.Readlink(selfdir)
		pfs.Self = fi
	}
}

type Process struct {
	PID     int
	Auxv    []byte
	Cmdline []string
	Cwd     string
	Environ map[string]string
	Exe     string
	Fds     map[int]*Fd
	Root    string
	Status  map[string]string
	Threads map[int]*Thread
}
// TODO limits, maps, mem, mountinfo, mounts, mountstats, ns, smaps, stat

const (
	PROCFS_PROC_AUXV = "Process.Auxv"
	PROCFS_PROC_CMDLINE = "Process.Cmdline"
	PROCFS_PROC_CWD = "Process.Cwd"
	PROCFS_PROC_ENVIRON = "Process.Environ"
	PROCFS_PROC_EXE = "Process.Exe"
	PROCFS_PROC_ROOT = "Process.Root"
	PROCFS_PROC_STATUS = "Process.Status"

	PROCFS_PROC_FDS = "Process.Fds"
	PROCFS_PROC_THREADS = "Process.Threads"
)

func (p *Process) Fill() {
	p.Get(PROCFS_PROC_AUXV)
	p.Get(PROCFS_PROC_CMDLINE)
	p.Get(PROCFS_PROC_CWD)
	p.Get(PROCFS_PROC_ENVIRON)
	p.Get(PROCFS_PROC_EXE)
	p.Get(PROCFS_PROC_ROOT)
	p.Get(PROCFS_PROC_STATUS)

	// Fds
	p.List(PROCFS_PROC_FDS)
	for _, f := range p.Fds {
		f.Fill()
	}

	// Threads
	p.List(PROCFS_PROC_THREADS)
	for _, t := range p.Threads {
		t.Fill()
	}
}

func (p *Process) List(k string) {

}

func (p *Process) Get(k string) {
	pdir := path.Join(procfsdir, strconv.Itoa(p.PID))
	switch k {
	case PROCFS_PROC_AUXV:
		p.Auxv, _ = ioutil.ReadFile(path.Join(pdir, "auxv"))
	case PROCFS_PROC_CMDLINE:
		cl, err := ioutil.ReadFile(path.Join(pdir, "cmdline"))
		if err == nil {
			p.Cmdline = splitNull(cl)
		}
	case PROCFS_PROC_CWD:
		p.Cwd, _ = os.Readlink(path.Join(pdir, "cwd"))
	case PROCFS_PROC_ENVIRON:
	}
}

type Fd struct {
	Path  string
	Pos   int
	Flags int
}

const (
	PROCFS_PROC_FD_PATH = "Process.Fd.Path"
	PROCFS_PROC_FD_POS = "Process.Fd.Pos"
	PROCFS_PROC_FD_FLAGS = "Process.Fd.Flags"
)

func (f *Fd) Fill() {
	f.Get(PROCFS_PROC_FD_PATH)
	f.Get(PROCFS_PROC_FD_POS)
	f.Get(PROCFS_PROC_FD_FLAGS)
}

func (f *Fd) Get(k string) {
	switch k {

	}
}

type Thread struct {
	// TODO
}

func (t *Thread) Fill() {

}

func (t *Thread) Get(k string) {

}
<|endoftext|>


<commit_before>// Copyright (c) 2017 - 2017 badassops
// 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.
//	* Neither the name of the <organization> nor the
//	names of its contributors may be used to endorse or promote products
//	derived from this software without specific prior written permission.
//
// 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 PURPOSEcw
// ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
//
// Version		:	0.1
//
// Date			:	July 1, 2017
//
// History	:
// 	Date:			Author:		Info:
//	July 1, 2017	LIS			First Go release
//
// TODO:

package procfs

// https://github.com/prometheus/procfs
// https://unix.stackexchange.com/questions/7870/how-to-check-how-long-a-process-has-been-running

// SYS:
// Meminfo
// Stat
// Uptime
// Zoneinfo
// Loadavg
// Partitions

// PID:
// Comm
// Cmdline
// Smaps
// Stat
// Limits
<commit_msg>added procfs for futher work<commit_after>// Copyright (c) 2017 - 2017 badassops
// 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.
//	* Neither the name of the <organization> nor the
//	names of its contributors may be used to endorse or promote products
//	derived from this software without specific prior written permission.
//
// 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 PURPOSEcw
// ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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.
//
// Version		:	0.1
//
// Date			:	July 1, 2017
//
// History	:
// 	Date:			Author:		Info:
//	July 1, 2017	LIS			First Go release
//
// TODO:

package procfs

const (
	sysHZ	= 100
	minPid	= 300
)

// NOTE We only get the fields that are importants

// from the /proc/stat and then a single cpu line stats
type cpuStat struct {
	user		float64		`json:"user"`
	nice		float64		`json:"nice"`
	system		float64		`json:"system"`
	idle		float64		`json:"idle"`
	ioWait		float64		`json:"iowait"`
	irq			float64		`json:"irq"`
	softIRQ		float64		`json:"softirq"`
	steal		float64		`json:"steal"`
	guest		float64		`json:"guest"`
	guestNice float64		`json:"guestnice"`
}

type sysStat struct {
	bootTime	uint64		`json:"boottime"`
	cpuTotal	cpuStat		`json:"cputotal"`
	cpu			[]cpuStat	`json:"cpu"`
	cntxtSwitch	uint64		`json:"cntxtswitch"`
	procRunning	uint64		`json:"procrunning"`
	procBlocked	uint64		`json:"procblocked"`
}

type sysMemInfo struct {
	memTotal		uint64	`json:"memtotal"`
	memFree			uint64	`json:"memfree"`
	memAvailable	uint64	`json:"memavailable"`
	buffers			uint64	`json:"buffers"`
	cached			uint64	`json:"cached"`
	swapCached		uint64	`json:"swapcached"`
	swapTotal		uint64	`json:"swapTotal"`
	swapFree		uint64	`json:"swapTotal"`
}

type sysUptime struct {
	upTime			float64	`json:"uptime"`
	idleTime		float64	`json:"idletime"`
}

type sysLoadavg struct {
	load1Avg		uint	`json:"load1navg"`
	load5Avg		uint	`json:"load5avg"`
	load10Avg		uint	`json:"load10avg"`
	execProc		uint	`json:"execproc"`
	execQueue		uint	`json:"execqueue"`
	lastPid			uint	`json:"lastpid"`
}

type sysMounts struct {
	device			string	`json:"device"`
	mountpoint		string	`json:"mount"`
	fsType			string	`json:"fstype"`
	mountState		string	`json:"state"`
}

type procComm struct {
	command		string	`json:"command"`
}

type procCmdline struct {
	cmdArgs		string	`json:"cmdargs"`
}

type procSmaps struct {
	rss				uint64	`json:"rss"`
	pss				uint64	`json:"pss"`
	shared			uint64	`json:"shared"`
	sharedClean		uint64	`json:"sharedclean"`
	sharedDirty		uint64	`json:"shareddirty"`
	private			uint64	`json:"private"`
	privateClean	uint64	`json:"privateclean"`
	privateDirty	uint64	`json:"privatedirty"`
	swap			uint64	`json:"swap"`
}

// has 52 fields we only want these
type procStat struct {
	pid				uint	`json:"pid"`		// 1
	comm			string	`json:"comm"`		// 2
	state			string	`json:"state"`		// 3
			// R Running
			// S Sleeping in an interruptible wait
			// D Waiting in uninterruptible disk sleep
			// Z Zombie
			// T Stopped (on a signal) or (before Linux 2.6.33)
			// t Tracing stop (Linux 2.6.33 onward)
			// W Paging (only before Linux 2.6.0)
			// X Dead (from Linux 2.6.0 onward)
			// x Dead (Linux 2.6.33 to 3.13 only)
			// K Wakekill (Linux 2.6.33 to 3.13 only)
			// W Waking (Linux 2.6.33 to 3.13 only)
			// P Parked (Linux 3.9 to 3.13 only)
	ppid			uint	`json:"ppid"`		// 4
	tty_nr			uint	`json:"ttynr"`		// 7
	minflt			uint64	`json:"minflt"`		// 10
	cminflt			uint64	`json:"cminflt"`	// 11
	majflt			uint64	`json:"majflt"`		// 12
	cmajflt			uint64	`json:"cmajflt"`	// 13
	priority		uint64	`json:"priority"`	// 18
	nice			uint64	`json:"noce"`		// 19
	num_threads		uint64	`json:"numthreads"`	// 20
	starttime		uint64	`json:"cstarttime"`	// 22
	vsize			uint64	`json:"vsize"`		// 23
	rss				uint64	`json:"rss"`		// 24
	rsslim			uint64	`json:"rsslim"`		// 25
}

// -1 == unlimited
type procLimits struct {
	cpuTime				int64	`json:"cputime"`			// seconds
	fileSize			int64	`json:"filesize"`			// bytes
	dataSize			int64	`json:"datasize"`			// bytes
	stackSize			int64	`json:"stacKSize"`			// bytes
	coreFileSize		int64	`json:"corefilesize"`		// bytes
	residentSet			int64	`json:"residentset"`		// bytes
	processes			int64	`json:"processes"`			// processes
	openFiles			int64	`json:"openfiles"`			// files
	lockedMemory		int64	`json:"lockedmemory"`		// bytes
	addressSpace		int64	`json:"addressspace"`		// bytes
	fileLocks			int64	`json:"filelocks"`			// locks
	pendingSignals		int64	`json:"pendingsignals"`		// signals
	msgqueueeSize		int64	`json:"msgqueueesize"`		// bytes
	nicePriority		int		`json:"nicepriority"`
	realtimePriority	int		`json:"realtimepriority"`
	realtimeTimeout		int64	`json:"realtimetimeout"`	// usecs
}

// System
type systemProc struct {
	stat	*sysStat
	meminfo	*sysMemInfo
	uptime	*sysUptime
	loadavg	*sysLoadavg
	mounts	*sysMounts
	process	*map[string]*processProc
}

// Single process
type processProc struct {
	comm	*procComm
	cmdline	*procCmdline
	smaps	*procSmaps
	stat	*procStat
	limit	*procLimits
}

var (
	// for system
	sysStatRegex	= `^(btime|cpu|ctxt|procs_running|procs_blocked)`
	sysMeminfoRegex	= `^(MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapCached|SwapTotal|SwapFree)`
	sysMountsRegex	= `^(/dev/)(xvd|sd|disk|mapper)`
	// for process
	smapsRegex	= `^(Rss:|Pss:|Shared_Clean:|Shared_Dirty:|Private_Clean:|Private_Dirty:|Swap:)`
	limitsRegex	= `^Max(cpu time|file size|data size|stack size|core file size|resident set|processes|open files|locked memory|address space|file locks|pending signals|msgqueue size|nice priority|realtime priority|realtime timeout)`
	// for disks
	symRegex		= `^(/dev/)(disk|mapper)`
)
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"path"
	"syscall"
	"time"

	"github.com/jweslley/procker"
)

const defaultEnvfile = ".env"

var (
	cmdStart = &command{
		desc: "Start application's processes",
		help: `Usage: procker start [options] [process name]...

Start the processes specified by a Procfile

Available options:`,
		exec: start,
		flag: startFlags}

	// flags
	startFlags    = flag.NewFlagSet("start", flag.ExitOnError)
	startProcfile = startFlags.String("f", "Procfile",
		"Procfile declaring commands to run")
	startEnvfile = startFlags.String("e", defaultEnvfile,
		"File containing environment variables to be used")
	startBasePort = startFlags.Int("p", 5000,
		"Base port to be used by processes")
	startStopTimeout = startFlags.Int("t", 5,
		"Time (in seconds) for graceful stop of processes")
)

func start(args []string) {
	processes := parseProfile(*startProcfile)
	env := parseEnv(*startEnvfile)
	dir := path.Dir(*startProcfile)
	padding := longestName(processes)
	log.SetFlags(0)
	log.SetOutput(procker.NewPrefixedWriter(os.Stdout, prefix(programName, padding)))
	process := buildProcess(args, processes, dir, env, *startBasePort, padding)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		stopping := false
		for sig := range c {
			if stopping {
				log.Printf("%v signal received, killing processes and exiting.", sig)
				process.Signal(syscall.SIGKILL)
			} else {
				log.Printf("%v signal received, stopping processes and exiting.", sig)
				stopping = true
				go func() {
					process.Stop(time.Duration(*startStopTimeout) * time.Second)
				}()
			}
		}
	}()

	err := process.Start()
	failIf(err)

	process.Wait()
}

func buildProcess(
	processNames []string,
	processes map[string]string,
	dir string,
	env []string,
	port, padding int) procker.Process {

	p := []procker.Process{}
	for name, command := range processes {
		if !mustStart(processNames, name) {
			continue
		}

		process := &procker.SysProcess{
			Command:     command,
			Dir:         dir,
			Env:         append(env, fmt.Sprintf("PORT=%d", port)),
			Stdout:      procker.NewPrefixedWriter(os.Stdout, prefix(name, padding)),
			Stderr:      procker.NewPrefixedWriter(os.Stderr, prefix(name, padding)),
			SysProcAttr: sysProcAttrs(),
		}

		log.Printf("starting %s on port %d", name, port)
		p = append(p, process)
		port++
	}

	if len(p) == 0 {
		fail("no process to run\n")
	}

	return procker.NewProcessGroup(p...)
}

func mustStart(processNames []string, name string) bool {
	if len(processNames) == 0 {
		return true
	}

	for _, process := range processNames {
		if process == name {
			return true
		}
	}
	return false
}

func parseProfile(filepath string) map[string]string {
	file, err := os.Open(filepath)
	failIf(err)
	defer file.Close()

	processes, err := procker.ParseProcfile(file)
	failIf(err)
	return processes
}

func parseEnv(filepath string) []string {
	file, err := os.Open(filepath)
	if err != nil {
		if filepath == defaultEnvfile {
			return []string{}
		} else {
			failIf(err)
		}
	}
	defer file.Close()

	env, err := procker.ParseEnv(file)
	failIf(err)
	return env
}

func longestName(processes map[string]string) int {
	max := len(programName)
	for name := range processes {
		if len(name) > max {
			max = len(name)
		}
	}
	return max
}

func prefix(prefix string, padding int) string {
	return fmt.Sprintf(fmt.Sprintf("%%%ds | ", -padding), prefix)
}
<commit_msg>load system's env in both 'start' and 'run' commands<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"path"
	"syscall"
	"time"

	"github.com/jweslley/procker"
)

const defaultEnvfile = ".env"

var (
	cmdStart = &command{
		desc: "Start application's processes",
		help: `Usage: procker start [options] [process name]...

Start the processes specified by a Procfile

Available options:`,
		exec: start,
		flag: startFlags}

	// flags
	startFlags    = flag.NewFlagSet("start", flag.ExitOnError)
	startProcfile = startFlags.String("f", "Procfile",
		"Procfile declaring commands to run")
	startEnvfile = startFlags.String("e", defaultEnvfile,
		"File containing environment variables to be used")
	startBasePort = startFlags.Int("p", 5000,
		"Base port to be used by processes")
	startStopTimeout = startFlags.Int("t", 5,
		"Time (in seconds) for graceful stop of processes")
)

func start(args []string) {
	processes := parseProfile(*startProcfile)
	env := parseEnv(*startEnvfile)
	dir := path.Dir(*startProcfile)
	padding := longestName(processes)
	log.SetFlags(0)
	log.SetOutput(procker.NewPrefixedWriter(os.Stdout, prefix(programName, padding)))
	process := buildProcess(args, processes, dir, env, *startBasePort, padding)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		stopping := false
		for sig := range c {
			if stopping {
				log.Printf("%v signal received, killing processes and exiting.", sig)
				process.Signal(syscall.SIGKILL)
			} else {
				log.Printf("%v signal received, stopping processes and exiting.", sig)
				stopping = true
				go func() {
					process.Stop(time.Duration(*startStopTimeout) * time.Second)
				}()
			}
		}
	}()

	err := process.Start()
	failIf(err)

	process.Wait()
}

func buildProcess(
	processNames []string,
	processes map[string]string,
	dir string,
	env []string,
	port, padding int) procker.Process {

	p := []procker.Process{}
	for name, command := range processes {
		if !mustStart(processNames, name) {
			continue
		}

		process := &procker.SysProcess{
			Command:     command,
			Dir:         dir,
			Env:         append(env, fmt.Sprintf("PORT=%d", port)),
			Stdout:      procker.NewPrefixedWriter(os.Stdout, prefix(name, padding)),
			Stderr:      procker.NewPrefixedWriter(os.Stderr, prefix(name, padding)),
			SysProcAttr: sysProcAttrs(),
		}

		log.Printf("starting %s on port %d", name, port)
		p = append(p, process)
		port++
	}

	if len(p) == 0 {
		fail("no process to run\n")
	}

	return procker.NewProcessGroup(p...)
}

func mustStart(processNames []string, name string) bool {
	if len(processNames) == 0 {
		return true
	}

	for _, process := range processNames {
		if process == name {
			return true
		}
	}
	return false
}

func parseProfile(filepath string) map[string]string {
	file, err := os.Open(filepath)
	failIf(err)
	defer file.Close()

	processes, err := procker.ParseProcfile(file)
	failIf(err)
	return processes
}

func parseEnv(filepath string) []string {
	file, err := os.Open(filepath)
	if err != nil {
		if filepath == defaultEnvfile {
			return os.Environ()
		} else {
			failIf(err)
		}
	}
	defer file.Close()

	env, err := procker.ParseEnv(file)
	failIf(err)
	return append(os.Environ(), env...)
}

func longestName(processes map[string]string) int {
	max := len(programName)
	for name := range processes {
		if len(name) > max {
			max = len(name)
		}
	}
	return max
}

func prefix(prefix string, padding int) string {
	return fmt.Sprintf(fmt.Sprintf("%%%ds | ", -padding), prefix)
}
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Conservative resource-related analysis of programs.
// The analysis figures out what files descriptors are [potentially] opened
// at a particular point in program, what pages are [potentially] mapped,
// what files were already referenced in calls, etc.

package prog

import (
	"fmt"

	"github.com/google/syzkaller/sys"
)

const (
	maxPages = 4 << 10
)

type state struct {
	ct        *ChoiceTable
	files     map[string]bool
	resources map[string][]*Arg
	strings   map[string]bool
	pages     [maxPages]bool
}

// analyze analyzes the program p up to but not including call c.
func analyze(ct *ChoiceTable, p *Prog, c *Call) *state {
	s := newState(ct)
	for _, c1 := range p.Calls {
		if c1 == c {
			break
		}
		s.analyze(c1)
	}
	return s
}

func newState(ct *ChoiceTable) *state {
	s := &state{
		ct:        ct,
		files:     make(map[string]bool),
		resources: make(map[string][]*Arg),
		strings:   make(map[string]bool),
	}
	return s
}

func (s *state) analyze(c *Call) {
	foreachArgArray(&c.Args, c.Ret, func(arg, base *Arg, _ *[]*Arg) {
		switch typ := arg.Type.(type) {
		case *sys.ResourceType:
			if arg.Type.Dir() != sys.DirIn {
				s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], arg)
				// TODO: negative PIDs and add them as well (that's process groups).
			}
		case *sys.BufferType:
			if arg.Type.Dir() != sys.DirOut && arg.Kind == ArgData && len(arg.Data) != 0 {
				switch typ.Kind {
				case sys.BufferString:
					s.strings[string(arg.Data)] = true
				case sys.BufferFilename:
					s.files[string(arg.Data)] = true
				}
			}
		}
	})
	switch c.Meta.Name {
	case "mmap":
		// Filter out only very wrong arguments.
		length := c.Args[1]
		if length.AddrPage == 0 && length.AddrOffset == 0 {
			break
		}
		if flags, fd := c.Args[4], c.Args[3]; flags.Val&sys.MAP_ANONYMOUS == 0 && fd.Kind == ArgConst && fd.Val == sys.InvalidFD {
			break
		}
		s.addressable(c.Args[0], length, true)
	case "munmap":
		s.addressable(c.Args[0], c.Args[1], false)
	case "mremap":
		s.addressable(c.Args[4], c.Args[2], true)
	case "io_submit":
		if arr := c.Args[2].Res; arr != nil {
			for _, ptr := range arr.Inner {
				if ptr.Kind == ArgPointer {
					if ptr.Res != nil && ptr.Res.Type.Name() == "iocb" {
						s.resources["iocbptr"] = append(s.resources["iocbptr"], ptr)
					}
				}
			}
		}
	}
}

func (s *state) addressable(addr, size *Arg, ok bool) {
	if addr.Kind != ArgPointer || size.Kind != ArgPageSize {
		panic("mmap/munmap/mremap args are not pages")
	}
	n := size.AddrPage
	if size.AddrOffset != 0 {
		n++
	}
	if addr.AddrPage+n > uintptr(len(s.pages)) {
		panic(fmt.Sprintf("address is out of bounds: page=%v len=%v (%v, %v) bound=%v, addr: %+v, size: %+v",
			addr.AddrPage, n, size.AddrPage, size.AddrOffset, len(s.pages), addr, size))
	}
	for i := uintptr(0); i < n; i++ {
		s.pages[addr.AddrPage+i] = ok
	}
}

func foreachSubargImpl(arg *Arg, parent *[]*Arg, f func(arg, base *Arg, parent *[]*Arg)) {
	var rec func(arg, base *Arg, parent *[]*Arg)
	rec = func(arg, base *Arg, parent *[]*Arg) {
		f(arg, base, parent)
		for _, arg1 := range arg.Inner {
			parent1 := parent
			if _, ok := arg.Type.(*sys.StructType); ok {
				parent1 = &arg.Inner
			}
			rec(arg1, base, parent1)
		}
		if arg.Kind == ArgPointer && arg.Res != nil {
			rec(arg.Res, arg, parent)
		}
		if arg.Kind == ArgUnion {
			rec(arg.Option, base, parent)
		}
	}
	rec(arg, nil, parent)
}

func foreachSubarg(arg *Arg, f func(arg, base *Arg, parent *[]*Arg)) {
	foreachSubargImpl(arg, nil, f)
}

func foreachArgArray(args *[]*Arg, ret *Arg, f func(arg, base *Arg, parent *[]*Arg)) {
	for _, arg := range *args {
		foreachSubargImpl(arg, args, f)
	}
	if ret != nil {
		foreachSubargImpl(ret, nil, f)
	}
}

func foreachArg(c *Call, f func(arg, base *Arg, parent *[]*Arg)) {
	foreachArgArray(&c.Args, nil, f)
}

func generateSize(arg *Arg, lenType *sys.LenType) *Arg {
	if arg == nil {
		// Arg is an optional pointer, set size to 0.
		return constArg(lenType, 0)
	}

	switch arg.Type.(type) {
	case *sys.VmaType:
		return pageSizeArg(lenType, arg.AddrPagesNum, 0)
	case *sys.ArrayType:
		if lenType.ByteSize {
			return constArg(lenType, arg.Size())
		} else {
			return constArg(lenType, uintptr(len(arg.Inner)))
		}
	default:
		return constArg(lenType, arg.Size())
	}
}

func assignSizes(args []*Arg) {
	// Create a map of args and calculate size of the whole struct.
	argsMap := make(map[string]*Arg)
	var parentSize uintptr
	for _, arg := range args {
		parentSize += arg.Size()
		if sys.IsPad(arg.Type) {
			continue
		}
		argsMap[arg.Type.Name()] = arg
	}

	// Fill in size arguments.
	for _, arg := range args {
		if arg = arg.InnerArg(); arg == nil {
			continue // Pointer to optional len field, no need to fill in value.
		}
		if typ, ok := arg.Type.(*sys.LenType); ok {
			if typ.Buf == "parent" {
				arg.Val = parentSize
				continue
			}

			buf, ok := argsMap[typ.Buf]
			if !ok {
				panic(fmt.Sprintf("len field '%v' references non existent field '%v', argsMap: %+v",
					typ.Name(), typ.Buf, argsMap))
			}

			*arg = *generateSize(buf.InnerArg(), typ)
		}
	}
}

func assignSizesCall(c *Call) {
	assignSizes(c.Args)
	foreachArg(c, func(arg, base *Arg, parent *[]*Arg) {
		if _, ok := arg.Type.(*sys.StructType); ok {
			assignSizes(arg.Inner)
		}
	})
}

func sanitizeCall(c *Call) {
	switch c.Meta.CallName {
	case "mmap":
		// Add MAP_FIXED flag, otherwise it produces non-deterministic results.
		addr := c.Args[0]
		if addr.Kind != ArgPointer {
			panic("mmap address is not ArgPointer")
		}
		length := c.Args[1]
		if length.Kind != ArgPageSize {
			panic("mmap length is not ArgPageSize")
		}
		flags := c.Args[3]
		if flags.Kind != ArgConst {
			panic("mmap flag arg is not const")
		}
		flags.Val |= sys.MAP_FIXED
	case "mremap":
		// Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
		flags := c.Args[3]
		if flags.Kind != ArgConst {
			panic("mremap flag arg is not const")
		}
		if flags.Val&sys.MREMAP_MAYMOVE != 0 {
			flags.Val |= sys.MREMAP_FIXED
		}
	case "mknod":
		mode := c.Args[1]
		if mode.Kind != ArgConst {
			panic("mknod mode is not const")
		}
		// Char and block devices read/write io ports, kernel memory and do other nasty things.
		// TODO: not required if executor drops privileges.
		if mode.Val != sys.S_IFREG && mode.Val != sys.S_IFIFO && mode.Val != sys.S_IFSOCK {
			mode.Val = sys.S_IFIFO
		}
	case "syslog":
		cmd := c.Args[0]
		// These disable console output, but we need it.
		if cmd.Val == sys.SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == sys.SYSLOG_ACTION_CONSOLE_ON {
			cmd.Val = sys.SYSLOG_ACTION_SIZE_UNREAD
		}
	case "ioctl":
		cmd := c.Args[1]
		// Freeze kills machine. Though, it is an interesting functions,
		// so we need to test it somehow.
		// TODO: not required if executor drops privileges.
		if uint32(cmd.Val) == sys.FIFREEZE {
			cmd.Val = sys.FITHAW
		}
	case "ptrace":
		// PTRACE_TRACEME leads to unkillable processes, see:
		// https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
		if c.Args[0].Val == sys.PTRACE_TRACEME {
			c.Args[0].Val = ^uintptr(0)
		}
	case "exit", "exit_group":
		code := c.Args[0]
		// These codes are reserved by executor.
		if code.Val%128 == 67 || code.Val%128 == 68 {
			code.Val = 1
		}
	}
}
<commit_msg>prog: sanitize mknodat the same way as mknod<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Conservative resource-related analysis of programs.
// The analysis figures out what files descriptors are [potentially] opened
// at a particular point in program, what pages are [potentially] mapped,
// what files were already referenced in calls, etc.

package prog

import (
	"fmt"

	"github.com/google/syzkaller/sys"
)

const (
	maxPages = 4 << 10
)

type state struct {
	ct        *ChoiceTable
	files     map[string]bool
	resources map[string][]*Arg
	strings   map[string]bool
	pages     [maxPages]bool
}

// analyze analyzes the program p up to but not including call c.
func analyze(ct *ChoiceTable, p *Prog, c *Call) *state {
	s := newState(ct)
	for _, c1 := range p.Calls {
		if c1 == c {
			break
		}
		s.analyze(c1)
	}
	return s
}

func newState(ct *ChoiceTable) *state {
	s := &state{
		ct:        ct,
		files:     make(map[string]bool),
		resources: make(map[string][]*Arg),
		strings:   make(map[string]bool),
	}
	return s
}

func (s *state) analyze(c *Call) {
	foreachArgArray(&c.Args, c.Ret, func(arg, base *Arg, _ *[]*Arg) {
		switch typ := arg.Type.(type) {
		case *sys.ResourceType:
			if arg.Type.Dir() != sys.DirIn {
				s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], arg)
				// TODO: negative PIDs and add them as well (that's process groups).
			}
		case *sys.BufferType:
			if arg.Type.Dir() != sys.DirOut && arg.Kind == ArgData && len(arg.Data) != 0 {
				switch typ.Kind {
				case sys.BufferString:
					s.strings[string(arg.Data)] = true
				case sys.BufferFilename:
					s.files[string(arg.Data)] = true
				}
			}
		}
	})
	switch c.Meta.Name {
	case "mmap":
		// Filter out only very wrong arguments.
		length := c.Args[1]
		if length.AddrPage == 0 && length.AddrOffset == 0 {
			break
		}
		if flags, fd := c.Args[4], c.Args[3]; flags.Val&sys.MAP_ANONYMOUS == 0 && fd.Kind == ArgConst && fd.Val == sys.InvalidFD {
			break
		}
		s.addressable(c.Args[0], length, true)
	case "munmap":
		s.addressable(c.Args[0], c.Args[1], false)
	case "mremap":
		s.addressable(c.Args[4], c.Args[2], true)
	case "io_submit":
		if arr := c.Args[2].Res; arr != nil {
			for _, ptr := range arr.Inner {
				if ptr.Kind == ArgPointer {
					if ptr.Res != nil && ptr.Res.Type.Name() == "iocb" {
						s.resources["iocbptr"] = append(s.resources["iocbptr"], ptr)
					}
				}
			}
		}
	}
}

func (s *state) addressable(addr, size *Arg, ok bool) {
	if addr.Kind != ArgPointer || size.Kind != ArgPageSize {
		panic("mmap/munmap/mremap args are not pages")
	}
	n := size.AddrPage
	if size.AddrOffset != 0 {
		n++
	}
	if addr.AddrPage+n > uintptr(len(s.pages)) {
		panic(fmt.Sprintf("address is out of bounds: page=%v len=%v (%v, %v) bound=%v, addr: %+v, size: %+v",
			addr.AddrPage, n, size.AddrPage, size.AddrOffset, len(s.pages), addr, size))
	}
	for i := uintptr(0); i < n; i++ {
		s.pages[addr.AddrPage+i] = ok
	}
}

func foreachSubargImpl(arg *Arg, parent *[]*Arg, f func(arg, base *Arg, parent *[]*Arg)) {
	var rec func(arg, base *Arg, parent *[]*Arg)
	rec = func(arg, base *Arg, parent *[]*Arg) {
		f(arg, base, parent)
		for _, arg1 := range arg.Inner {
			parent1 := parent
			if _, ok := arg.Type.(*sys.StructType); ok {
				parent1 = &arg.Inner
			}
			rec(arg1, base, parent1)
		}
		if arg.Kind == ArgPointer && arg.Res != nil {
			rec(arg.Res, arg, parent)
		}
		if arg.Kind == ArgUnion {
			rec(arg.Option, base, parent)
		}
	}
	rec(arg, nil, parent)
}

func foreachSubarg(arg *Arg, f func(arg, base *Arg, parent *[]*Arg)) {
	foreachSubargImpl(arg, nil, f)
}

func foreachArgArray(args *[]*Arg, ret *Arg, f func(arg, base *Arg, parent *[]*Arg)) {
	for _, arg := range *args {
		foreachSubargImpl(arg, args, f)
	}
	if ret != nil {
		foreachSubargImpl(ret, nil, f)
	}
}

func foreachArg(c *Call, f func(arg, base *Arg, parent *[]*Arg)) {
	foreachArgArray(&c.Args, nil, f)
}

func generateSize(arg *Arg, lenType *sys.LenType) *Arg {
	if arg == nil {
		// Arg is an optional pointer, set size to 0.
		return constArg(lenType, 0)
	}

	switch arg.Type.(type) {
	case *sys.VmaType:
		return pageSizeArg(lenType, arg.AddrPagesNum, 0)
	case *sys.ArrayType:
		if lenType.ByteSize {
			return constArg(lenType, arg.Size())
		} else {
			return constArg(lenType, uintptr(len(arg.Inner)))
		}
	default:
		return constArg(lenType, arg.Size())
	}
}

func assignSizes(args []*Arg) {
	// Create a map of args and calculate size of the whole struct.
	argsMap := make(map[string]*Arg)
	var parentSize uintptr
	for _, arg := range args {
		parentSize += arg.Size()
		if sys.IsPad(arg.Type) {
			continue
		}
		argsMap[arg.Type.Name()] = arg
	}

	// Fill in size arguments.
	for _, arg := range args {
		if arg = arg.InnerArg(); arg == nil {
			continue // Pointer to optional len field, no need to fill in value.
		}
		if typ, ok := arg.Type.(*sys.LenType); ok {
			if typ.Buf == "parent" {
				arg.Val = parentSize
				continue
			}

			buf, ok := argsMap[typ.Buf]
			if !ok {
				panic(fmt.Sprintf("len field '%v' references non existent field '%v', argsMap: %+v",
					typ.Name(), typ.Buf, argsMap))
			}

			*arg = *generateSize(buf.InnerArg(), typ)
		}
	}
}

func assignSizesCall(c *Call) {
	assignSizes(c.Args)
	foreachArg(c, func(arg, base *Arg, parent *[]*Arg) {
		if _, ok := arg.Type.(*sys.StructType); ok {
			assignSizes(arg.Inner)
		}
	})
}

func sanitizeCall(c *Call) {
	switch c.Meta.CallName {
	case "mmap":
		// Add MAP_FIXED flag, otherwise it produces non-deterministic results.
		addr := c.Args[0]
		if addr.Kind != ArgPointer {
			panic("mmap address is not ArgPointer")
		}
		length := c.Args[1]
		if length.Kind != ArgPageSize {
			panic("mmap length is not ArgPageSize")
		}
		flags := c.Args[3]
		if flags.Kind != ArgConst {
			panic("mmap flag arg is not const")
		}
		flags.Val |= sys.MAP_FIXED
	case "mremap":
		// Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
		flags := c.Args[3]
		if flags.Kind != ArgConst {
			panic("mremap flag arg is not const")
		}
		if flags.Val&sys.MREMAP_MAYMOVE != 0 {
			flags.Val |= sys.MREMAP_FIXED
		}
	case "mknod", "mknodat":
		mode := c.Args[1]
		if c.Meta.CallName == "mknodat" {
			mode = c.Args[2]
		}
		if mode.Kind != ArgConst {
			panic("mknod mode is not const")
		}
		// Char and block devices read/write io ports, kernel memory and do other nasty things.
		// TODO: not required if executor drops privileges.
		if mode.Val != sys.S_IFREG && mode.Val != sys.S_IFIFO && mode.Val != sys.S_IFSOCK {
			mode.Val = sys.S_IFIFO
		}
	case "syslog":
		cmd := c.Args[0]
		// These disable console output, but we need it.
		if cmd.Val == sys.SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == sys.SYSLOG_ACTION_CONSOLE_ON {
			cmd.Val = sys.SYSLOG_ACTION_SIZE_UNREAD
		}
	case "ioctl":
		cmd := c.Args[1]
		// Freeze kills machine. Though, it is an interesting functions,
		// so we need to test it somehow.
		// TODO: not required if executor drops privileges.
		if uint32(cmd.Val) == sys.FIFREEZE {
			cmd.Val = sys.FITHAW
		}
	case "ptrace":
		// PTRACE_TRACEME leads to unkillable processes, see:
		// https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
		if c.Args[0].Val == sys.PTRACE_TRACEME {
			c.Args[0].Val = ^uintptr(0)
		}
	case "exit", "exit_group":
		code := c.Args[0]
		// These codes are reserved by executor.
		if code.Val%128 == 67 || code.Val%128 == 68 {
			code.Val = 1
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Conservative resource-related analysis of programs.
// The analysis figures out what files descriptors are [potentially] opened
// at a particular point in program, what pages are [potentially] mapped,
// what files were already referenced in calls, etc.

package prog

import (
	"fmt"
)

type state struct {
	target    *Target
	ct        *ChoiceTable
	corpus    []*Prog
	files     map[string]bool
	resources map[string][]*ResultArg
	strings   map[string]bool
	ma        *memAlloc
	va        *vmaAlloc
}

// analyze analyzes the program p up to but not including call c.
func analyze(ct *ChoiceTable, corpus []*Prog, p *Prog, c *Call) *state {
	s := newState(p.Target, ct, corpus)
	resources := true
	for _, c1 := range p.Calls {
		if c1 == c {
			resources = false
		}
		s.analyzeImpl(c1, resources)
	}
	return s
}

func newState(target *Target, ct *ChoiceTable, corpus []*Prog) *state {
	s := &state{
		target:    target,
		ct:        ct,
		corpus:    corpus,
		files:     make(map[string]bool),
		resources: make(map[string][]*ResultArg),
		strings:   make(map[string]bool),
		ma:        newMemAlloc(target.NumPages * target.PageSize),
		va:        newVmaAlloc(target.NumPages),
	}
	return s
}

func (s *state) analyze(c *Call) {
	s.analyzeImpl(c, true)
}

func (s *state) analyzeImpl(c *Call, resources bool) {
	ForeachArg(c, func(arg Arg, _ *ArgCtx) {
		switch a := arg.(type) {
		case *PointerArg:
			switch {
			case a.IsSpecial():
			case a.VmaSize != 0:
				s.va.noteAlloc(a.Address/s.target.PageSize, a.VmaSize/s.target.PageSize)
			case a.Res != nil:
				s.ma.noteAlloc(a.Address, a.Res.Size())
			}
		}
		switch typ := arg.Type().(type) {
		case *ResourceType:
			a := arg.(*ResultArg)
			if resources && a.Dir() != DirIn {
				s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], a)
				// TODO: negative PIDs and add them as well (that's process groups).
			}
		case *BufferType:
			a := arg.(*DataArg)
			if a.Dir() != DirOut && len(a.Data()) != 0 {
				val := string(a.Data())
				// Remove trailing zero padding.
				for len(val) >= 2 && val[len(val)-1] == 0 && val[len(val)-2] == 0 {
					val = val[:len(val)-1]
				}
				switch typ.Kind {
				case BufferString:
					s.strings[val] = true
				case BufferFilename:
					if len(val) < 3 || escapingFilename(val) {
						// This is not our file, probalby one of specialFiles.
						return
					}
					if val[len(val)-1] == 0 {
						val = val[:len(val)-1]
					}
					s.files[val] = true
				}
			}
		}
	})
}

type ArgCtx struct {
	Parent *[]Arg      // GroupArg.Inner (for structs) or Call.Args containing this arg
	Fields []Field     // Fields of the parent struct/syscall
	Base   *PointerArg // pointer to the base of the heap object containing this arg
	Offset uint64      // offset of this arg from the base
	Stop   bool        // if set by the callback, subargs of this arg are not visited
}

func ForeachSubArg(arg Arg, f func(Arg, *ArgCtx)) {
	foreachArgImpl(arg, ArgCtx{}, f)
}

func ForeachArg(c *Call, f func(Arg, *ArgCtx)) {
	ctx := ArgCtx{}
	if c.Ret != nil {
		foreachArgImpl(c.Ret, ctx, f)
	}
	ctx.Parent = &c.Args
	ctx.Fields = c.Meta.Args
	for _, arg := range c.Args {
		foreachArgImpl(arg, ctx, f)
	}
}

func foreachArgImpl(arg Arg, ctx ArgCtx, f func(Arg, *ArgCtx)) {
	f(arg, &ctx)
	if ctx.Stop {
		return
	}
	switch a := arg.(type) {
	case *GroupArg:
		if typ, ok := a.Type().(*StructType); ok {
			ctx.Parent = &a.Inner
			ctx.Fields = typ.Fields
		}
		var totalSize uint64
		for _, arg1 := range a.Inner {
			foreachArgImpl(arg1, ctx, f)
			size := arg1.Size()
			ctx.Offset += size
			totalSize += size
		}
		claimedSize := a.Size()
		varlen := a.Type().Varlen()
		if varlen && totalSize > claimedSize || !varlen && totalSize != claimedSize {
			panic(fmt.Sprintf("bad group arg size %v, should be <= %v for %#v type %#v",
				totalSize, claimedSize, a, a.Type()))
		}
	case *PointerArg:
		if a.Res != nil {
			ctx.Base = a
			ctx.Offset = 0
			foreachArgImpl(a.Res, ctx, f)
		}
	case *UnionArg:
		foreachArgImpl(a.Option, ctx, f)
	}
}

func RequiredFeatures(p *Prog) (bitmasks, csums bool) {
	for _, c := range p.Calls {
		ForeachArg(c, func(arg Arg, _ *ArgCtx) {
			if a, ok := arg.(*ConstArg); ok {
				if a.Type().BitfieldOffset() != 0 || a.Type().BitfieldLength() != 0 {
					bitmasks = true
				}
			}
			if _, ok := arg.Type().(*CsumType); ok {
				csums = true
			}
		})
	}
	return
}

type CallFlags int

const (
	CallExecuted CallFlags = 1 << iota // was started at all
	CallFinished                       // finished executing (rather than blocked forever)
	CallBlocked                        // finished but blocked during execution
)

type CallInfo struct {
	Flags  CallFlags
	Errno  int
	Signal []uint32
}

const (
	fallbackSignalErrno = iota
	fallbackSignalErrnoBlocked
	fallbackSignalCtor
	fallbackSignalFlags
	fallbackCallMask = 0x1fff
)

func (p *Prog) FallbackSignal(info []CallInfo) {
	resources := make(map[*ResultArg]*Call)
	for i, c := range p.Calls {
		inf := &info[i]
		if inf.Flags&CallExecuted == 0 {
			continue
		}
		id := c.Meta.ID
		typ := fallbackSignalErrno
		if inf.Flags&CallFinished != 0 && inf.Flags&CallBlocked != 0 {
			typ = fallbackSignalErrnoBlocked
		}
		inf.Signal = append(inf.Signal, encodeFallbackSignal(typ, id, inf.Errno))
		if c.Meta.Attrs.BreaksReturns {
			break
		}
		if inf.Errno != 0 {
			continue
		}
		ForeachArg(c, func(arg Arg, _ *ArgCtx) {
			if a, ok := arg.(*ResultArg); ok {
				resources[a] = c
			}
		})
		// Specifically look only at top-level arguments,
		// deeper arguments can produce too much false signal.
		flags := 0
		for _, arg := range c.Args {
			flags = extractArgSignal(arg, id, flags, inf, resources)
		}
		if flags != 0 {
			inf.Signal = append(inf.Signal,
				encodeFallbackSignal(fallbackSignalFlags, id, flags))
		}
	}
}

func extractArgSignal(arg Arg, callID, flags int, inf *CallInfo, resources map[*ResultArg]*Call) int {
	switch a := arg.(type) {
	case *ResultArg:
		flags <<= 1
		if a.Res != nil {
			ctor := resources[a.Res]
			if ctor != nil {
				inf.Signal = append(inf.Signal,
					encodeFallbackSignal(fallbackSignalCtor, callID, ctor.Meta.ID))
			}
		} else {
			if a.Val != a.Type().(*ResourceType).SpecialValues()[0] {
				flags |= 1
			}
		}
	case *ConstArg:
		const width = 3
		flags <<= width
		switch typ := a.Type().(type) {
		case *FlagsType:
			if typ.BitMask {
				for i, v := range typ.Vals {
					if a.Val&v != 0 {
						flags ^= 1 << (uint(i) % width)
					}
				}
			} else {
				for i, v := range typ.Vals {
					if a.Val == v {
						flags |= i % (1 << width)
						break
					}
				}
			}
		case *LenType:
			flags <<= 1
			if a.Val == 0 {
				flags |= 1
			}
		}
	case *PointerArg:
		flags <<= 1
		if a.IsSpecial() {
			flags |= 1
		}
	}
	return flags
}

func DecodeFallbackSignal(s uint32) (callID, errno int) {
	typ, id, aux := decodeFallbackSignal(s)
	switch typ {
	case fallbackSignalErrno, fallbackSignalErrnoBlocked:
		return id, aux
	case fallbackSignalCtor, fallbackSignalFlags:
		return id, 0
	default:
		panic(fmt.Sprintf("bad fallback signal type %v", typ))
	}
}

func encodeFallbackSignal(typ, id, aux int) uint32 {
	if typ & ^7 != 0 {
		panic(fmt.Sprintf("bad fallback signal type %v", typ))
	}
	if id & ^fallbackCallMask != 0 {
		panic(fmt.Sprintf("bad call id in fallback signal %v", id))
	}
	return uint32(typ) | uint32(id&fallbackCallMask)<<3 | uint32(aux)<<16
}

func decodeFallbackSignal(s uint32) (typ, id, aux int) {
	return int(s & 7), int((s >> 3) & fallbackCallMask), int(s >> 16)
}
<commit_msg>prog: speed up foreachArgImpl<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Conservative resource-related analysis of programs.
// The analysis figures out what files descriptors are [potentially] opened
// at a particular point in program, what pages are [potentially] mapped,
// what files were already referenced in calls, etc.

package prog

import (
	"fmt"
)

type state struct {
	target    *Target
	ct        *ChoiceTable
	corpus    []*Prog
	files     map[string]bool
	resources map[string][]*ResultArg
	strings   map[string]bool
	ma        *memAlloc
	va        *vmaAlloc
}

// analyze analyzes the program p up to but not including call c.
func analyze(ct *ChoiceTable, corpus []*Prog, p *Prog, c *Call) *state {
	s := newState(p.Target, ct, corpus)
	resources := true
	for _, c1 := range p.Calls {
		if c1 == c {
			resources = false
		}
		s.analyzeImpl(c1, resources)
	}
	return s
}

func newState(target *Target, ct *ChoiceTable, corpus []*Prog) *state {
	s := &state{
		target:    target,
		ct:        ct,
		corpus:    corpus,
		files:     make(map[string]bool),
		resources: make(map[string][]*ResultArg),
		strings:   make(map[string]bool),
		ma:        newMemAlloc(target.NumPages * target.PageSize),
		va:        newVmaAlloc(target.NumPages),
	}
	return s
}

func (s *state) analyze(c *Call) {
	s.analyzeImpl(c, true)
}

func (s *state) analyzeImpl(c *Call, resources bool) {
	ForeachArg(c, func(arg Arg, _ *ArgCtx) {
		switch a := arg.(type) {
		case *PointerArg:
			switch {
			case a.IsSpecial():
			case a.VmaSize != 0:
				s.va.noteAlloc(a.Address/s.target.PageSize, a.VmaSize/s.target.PageSize)
			case a.Res != nil:
				s.ma.noteAlloc(a.Address, a.Res.Size())
			}
		}
		switch typ := arg.Type().(type) {
		case *ResourceType:
			a := arg.(*ResultArg)
			if resources && a.Dir() != DirIn {
				s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], a)
				// TODO: negative PIDs and add them as well (that's process groups).
			}
		case *BufferType:
			a := arg.(*DataArg)
			if a.Dir() != DirOut && len(a.Data()) != 0 {
				val := string(a.Data())
				// Remove trailing zero padding.
				for len(val) >= 2 && val[len(val)-1] == 0 && val[len(val)-2] == 0 {
					val = val[:len(val)-1]
				}
				switch typ.Kind {
				case BufferString:
					s.strings[val] = true
				case BufferFilename:
					if len(val) < 3 || escapingFilename(val) {
						// This is not our file, probalby one of specialFiles.
						return
					}
					if val[len(val)-1] == 0 {
						val = val[:len(val)-1]
					}
					s.files[val] = true
				}
			}
		}
	})
}

type ArgCtx struct {
	Parent *[]Arg      // GroupArg.Inner (for structs) or Call.Args containing this arg
	Fields []Field     // Fields of the parent struct/syscall
	Base   *PointerArg // pointer to the base of the heap object containing this arg
	Offset uint64      // offset of this arg from the base
	Stop   bool        // if set by the callback, subargs of this arg are not visited
}

func ForeachSubArg(arg Arg, f func(Arg, *ArgCtx)) {
	foreachArgImpl(arg, &ArgCtx{}, f)
}

func ForeachArg(c *Call, f func(Arg, *ArgCtx)) {
	ctx := &ArgCtx{}
	if c.Ret != nil {
		foreachArgImpl(c.Ret, ctx, f)
	}
	ctx.Parent = &c.Args
	ctx.Fields = c.Meta.Args
	for _, arg := range c.Args {
		foreachArgImpl(arg, ctx, f)
	}
}

func foreachArgImpl(arg Arg, ctx *ArgCtx, f func(Arg, *ArgCtx)) {
	ctx0 := *ctx
	defer func() { *ctx = ctx0 }()
	f(arg, ctx)
	if ctx.Stop {
		return
	}
	switch a := arg.(type) {
	case *GroupArg:
		if typ, ok := a.Type().(*StructType); ok {
			ctx.Parent = &a.Inner
			ctx.Fields = typ.Fields
		}
		var totalSize uint64
		for _, arg1 := range a.Inner {
			foreachArgImpl(arg1, ctx, f)
			size := arg1.Size()
			ctx.Offset += size
			totalSize += size
		}
		claimedSize := a.Size()
		varlen := a.Type().Varlen()
		if varlen && totalSize > claimedSize || !varlen && totalSize != claimedSize {
			panic(fmt.Sprintf("bad group arg size %v, should be <= %v for %#v type %#v",
				totalSize, claimedSize, a, a.Type()))
		}
	case *PointerArg:
		if a.Res != nil {
			ctx.Base = a
			ctx.Offset = 0
			foreachArgImpl(a.Res, ctx, f)
		}
	case *UnionArg:
		foreachArgImpl(a.Option, ctx, f)
	}
}

func RequiredFeatures(p *Prog) (bitmasks, csums bool) {
	for _, c := range p.Calls {
		ForeachArg(c, func(arg Arg, _ *ArgCtx) {
			if a, ok := arg.(*ConstArg); ok {
				if a.Type().BitfieldOffset() != 0 || a.Type().BitfieldLength() != 0 {
					bitmasks = true
				}
			}
			if _, ok := arg.Type().(*CsumType); ok {
				csums = true
			}
		})
	}
	return
}

type CallFlags int

const (
	CallExecuted CallFlags = 1 << iota // was started at all
	CallFinished                       // finished executing (rather than blocked forever)
	CallBlocked                        // finished but blocked during execution
)

type CallInfo struct {
	Flags  CallFlags
	Errno  int
	Signal []uint32
}

const (
	fallbackSignalErrno = iota
	fallbackSignalErrnoBlocked
	fallbackSignalCtor
	fallbackSignalFlags
	fallbackCallMask = 0x1fff
)

func (p *Prog) FallbackSignal(info []CallInfo) {
	resources := make(map[*ResultArg]*Call)
	for i, c := range p.Calls {
		inf := &info[i]
		if inf.Flags&CallExecuted == 0 {
			continue
		}
		id := c.Meta.ID
		typ := fallbackSignalErrno
		if inf.Flags&CallFinished != 0 && inf.Flags&CallBlocked != 0 {
			typ = fallbackSignalErrnoBlocked
		}
		inf.Signal = append(inf.Signal, encodeFallbackSignal(typ, id, inf.Errno))
		if c.Meta.Attrs.BreaksReturns {
			break
		}
		if inf.Errno != 0 {
			continue
		}
		ForeachArg(c, func(arg Arg, _ *ArgCtx) {
			if a, ok := arg.(*ResultArg); ok {
				resources[a] = c
			}
		})
		// Specifically look only at top-level arguments,
		// deeper arguments can produce too much false signal.
		flags := 0
		for _, arg := range c.Args {
			flags = extractArgSignal(arg, id, flags, inf, resources)
		}
		if flags != 0 {
			inf.Signal = append(inf.Signal,
				encodeFallbackSignal(fallbackSignalFlags, id, flags))
		}
	}
}

func extractArgSignal(arg Arg, callID, flags int, inf *CallInfo, resources map[*ResultArg]*Call) int {
	switch a := arg.(type) {
	case *ResultArg:
		flags <<= 1
		if a.Res != nil {
			ctor := resources[a.Res]
			if ctor != nil {
				inf.Signal = append(inf.Signal,
					encodeFallbackSignal(fallbackSignalCtor, callID, ctor.Meta.ID))
			}
		} else {
			if a.Val != a.Type().(*ResourceType).SpecialValues()[0] {
				flags |= 1
			}
		}
	case *ConstArg:
		const width = 3
		flags <<= width
		switch typ := a.Type().(type) {
		case *FlagsType:
			if typ.BitMask {
				for i, v := range typ.Vals {
					if a.Val&v != 0 {
						flags ^= 1 << (uint(i) % width)
					}
				}
			} else {
				for i, v := range typ.Vals {
					if a.Val == v {
						flags |= i % (1 << width)
						break
					}
				}
			}
		case *LenType:
			flags <<= 1
			if a.Val == 0 {
				flags |= 1
			}
		}
	case *PointerArg:
		flags <<= 1
		if a.IsSpecial() {
			flags |= 1
		}
	}
	return flags
}

func DecodeFallbackSignal(s uint32) (callID, errno int) {
	typ, id, aux := decodeFallbackSignal(s)
	switch typ {
	case fallbackSignalErrno, fallbackSignalErrnoBlocked:
		return id, aux
	case fallbackSignalCtor, fallbackSignalFlags:
		return id, 0
	default:
		panic(fmt.Sprintf("bad fallback signal type %v", typ))
	}
}

func encodeFallbackSignal(typ, id, aux int) uint32 {
	if typ & ^7 != 0 {
		panic(fmt.Sprintf("bad fallback signal type %v", typ))
	}
	if id & ^fallbackCallMask != 0 {
		panic(fmt.Sprintf("bad call id in fallback signal %v", id))
	}
	return uint32(typ) | uint32(id&fallbackCallMask)<<3 | uint32(aux)<<16
}

func decodeFallbackSignal(s uint32) (typ, id, aux int) {
	return int(s & 7), int((s >> 3) & fallbackCallMask), int(s >> 16)
}
<|endoftext|>


<commit_before>package rest_test

import (
	"fmt"
	"net/http"
	"os"

	"github.com/geotrace/rest"
)

var c = new(rest.Context) // test context

func ExampleContex_DataSet() {
	type myType byte
	var myData myType = 1

	c.DataSet(myData, "Test data")
	str := c.DataGet(myData).(string)
	fmt.Println(str)
	// Output: Test data
}

func ExampleContext_Body() {
	file, err := os.Open("README.md")
	if err != nil {
		panic(err)
	}
	c.ContentType = "text/markdown; charset=UTF-8"
	c.Body(file) // отдаст содержимое файла
}

func ExampleContext_Code() {
	c.Code(404).Body(nil)
}

func ExampleContext_ParseBody() {
	obj := make(map[string]interface{})
	if err := c.ParseBody(&obj); err != nil {
		panic(err)
	}
}

func ExampleContext_SetHeader() {
	c.SetHeader("ETag", "ab0138")
}

func ExampleHandlers() {
	var mux rest.ServeMux
	mux.Handles(rest.Handlers{
		"/user/:id": {
			"GET": rest.HandlerFunc(func(c *rest.Context) {
				c.Body(rest.JSON{"user": c.Get("id")})
			}),
			"POST": rest.HandlerFunc(func(c *rest.Context) {
				var data = make(rest.JSON)
				if err := c.ParseBody(&data); err != nil {
					c.Code(500).Body(err)
					return
				}
				c.Body(rest.JSON{
					"user": c.Get("id"),
					"data": data,
				})
			}),
		},
		"/message/:text": {
			"GET": rest.HandlerFunc(func(c *rest.Context) {
				c.Body(rest.JSON{"message": c.Get("text")})
			}),
		},
	})
}

func ExampleServeMux_Handle() {
	var mux rest.ServeMux
	mux.Handle("GET", "/message/:text", rest.HandlerFunc(func(c *rest.Context) {
		c.Body(rest.JSON{"message": c.Get("text")})
	}))
}

func ExampleServeMux_Handler() {
	var mux rest.ServeMux
	mux.Handler("GET", "/tmpfiles/",
		http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

func ExampleServeMux_ServeHTTP() {
	var mux rest.ServeMux
	mux.Handle("GET", "/message/:text", rest.HandlerFunc(func(c *rest.Context) {
		c.Body(rest.JSON{"message": c.Get("text")})
	}))
	http.ListenAndServe(":8080", mux)
}
<commit_msg>examples<commit_after>package rest_test

import (
	"fmt"
	"net/http"
	"os"

	"github.com/geotrace/rest"
)

var c = new(rest.Context) // test context

func ExampleContext_DataSet() {
	type myType byte
	var myData myType = 1

	c.DataSet(myData, "Test data")
	str := c.DataGet(myData).(string)
	fmt.Println(str)
	// Output: Test data
}

func ExampleContext_Body() {
	file, err := os.Open("README.md")
	if err != nil {
		panic(err)
	}
	c.ContentType = "text/markdown; charset=UTF-8"
	c.Body(file) // отдаст содержимое файла
}

func ExampleContext_Code() {
	c.Code(404).Body(nil)
}

func ExampleContext_ParseBody() {
	obj := make(map[string]interface{})
	if err := c.ParseBody(&obj); err != nil {
		panic(err)
	}
}

func ExampleContext_SetHeader() {
	c.SetHeader("ETag", "ab0138")
}

func ExampleHandlers() {
	var mux rest.ServeMux
	mux.Handles(rest.Handlers{
		"/user/:id": {
			"GET": rest.HandlerFunc(func(c *rest.Context) {
				c.Body(rest.JSON{"user": c.Get("id")})
			}),
			"POST": rest.HandlerFunc(func(c *rest.Context) {
				var data = make(rest.JSON)
				if err := c.ParseBody(&data); err != nil {
					c.Code(500).Body(err)
					return
				}
				c.Body(rest.JSON{
					"user": c.Get("id"),
					"data": data,
				})
			}),
		},
		"/message/:text": {
			"GET": rest.HandlerFunc(func(c *rest.Context) {
				c.Body(rest.JSON{"message": c.Get("text")})
			}),
		},
	})
}

func ExampleServeMux_Handle() {
	var mux rest.ServeMux
	mux.Handle("GET", "/message/:text", rest.HandlerFunc(func(c *rest.Context) {
		c.Body(rest.JSON{"message": c.Get("text")})
	}))
}

func ExampleServeMux_Handler() {
	var mux rest.ServeMux
	mux.Handler("GET", "/tmpfiles/",
		http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

func ExampleServeMux_ServeHTTP() {
	var mux rest.ServeMux
	mux.Handle("GET", "/message/:text", rest.HandlerFunc(func(c *rest.Context) {
		c.Body(rest.JSON{"message": c.Get("text")})
	}))
	http.ListenAndServe(":8080", mux)
}
<|endoftext|>


<commit_before>// Copyright 2014 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

package ecbrates

import (
	"strconv"
	"testing"
)

func TestFetchExchangeRates(t *testing.T) {
	r, err := New()
	if err != nil {
		t.Error(err)
	}
	if r.Date == "" {
		t.Error("Date is empty")
	}
	if len(r.Rate) != len(Currencies) {
		t.Error("Insufficient count of rates, got", len(r.Rate), "for", r.Date)
	}

	for _, currency := range Currencies {
		str, ok := r.Rate[currency].(string)
		if !ok {
			t.Error("Parse string error:", err)
		}
		v, err := strconv.ParseFloat(str, 32)
		if !ok {
			t.Error("Parse float error:", err)
		}
		expected := round64(100.0*round64(v, 4), 4)
		value, err := r.Convert(100, EUR, currency)
		if err != nil {
			t.Error("Converting error:", err)
		}
		if expected != value {
			t.Error("Expected rate", expected, "got", value)
		}
	}
	if _, err = r.Convert(100, Currency("XXX"), EUR); err == nil {
		t.Error("Expected error, got nil")
	}
	if _, err = r.Convert(100, EUR, Currency("XXX")); err == nil {
		t.Error("Expected error, got nil")
	}
	if _, err = r.Convert(100, Currency("XXX"), Currency("XXX")); err == nil {
		t.Error("Expected error, got nil")
	}
}

func TestFetchAllExchangeRates(t *testing.T) {
	rates, err := Load()
	if err != nil {
		t.Error(err)
	}

	if len(rates) < 50 {
		t.Error("Insufficient Count of days, got", len(rates))
	}
	for _, item := range rates {
		if item.Date == "" {
			t.Error("Date is empty")
		}
		if len(item.Rate) != len(Currencies) {
			t.Error("Day:", item.Date, "Insufficient count of rates, got", len(item.Rate))
		}
		for _, currency := range Currencies {
			if str, ok := item.Rate[currency].(string); ok {
				if v, err := strconv.ParseFloat(str, 32); err == nil {
					if v == 0 {
						t.Error("Day:", item.Date, "Zero rate for", currency)
					}
				} else {
					t.Error(err)
				}
			} else {
				t.Error("Parse rate to string unsuccessful")
			}
		}
	}
}
<commit_msg>extended test case<commit_after>package ecbrates

import (
	"strconv"
	"testing"
)

func TestFetchExchangeRates(t *testing.T) {
	r, err := New()
	if err != nil {
		t.Error(err)
	}
	if r.Date == "" {
		t.Error("Date is empty")
	}

	for currency, rate := range r.Rate {
		str, ok := rate.(string)
		if !ok {
			t.Error("Parse string error:", err)
		}
		if !currency.IsValid() {
			t.Error("Unknown currency type", currency)
		}
		v, err := strconv.ParseFloat(str, 32)
		if !ok {
			t.Error("Parse float error:", err)
		}
		expected := round64(100.0*round64(v, 4), 4)
		value, err := r.Convert(100, EUR, currency)
		if err != nil {
			t.Error("Converting error:", err)
		}
		if expected != value {
			t.Error("Expected rate", expected, "got", value)
		}
	}
	if _, err = r.Convert(100, Currency("XXX"), EUR); err == nil {
		t.Error("Expected error, got nil")
	}
	if _, err = r.Convert(100, EUR, Currency("XXX")); err == nil {
		t.Error("Expected error, got nil")
	}
	if _, err = r.Convert(100, Currency("XXX"), Currency("XXX")); err == nil {
		t.Error("Expected error, got nil")
	}
}

func TestFetchAllExchangeRates(t *testing.T) {
	rates, err := Load()
	if err != nil {
		t.Error(err)
	}

	if len(rates) < 50 {
		t.Error("Insufficient Count of days, got", len(rates))
	}
	for _, item := range rates {
		if item.Date == "" {
			t.Error("Date is empty")
		}
		for currency, rate := range item.Rate {
			if !currency.IsValid() {
				t.Error("Unknown currency type", currency)
			}
			if str, ok := rate.(string); ok {
				if v, err := strconv.ParseFloat(str, 32); err == nil {
					if v == 0 {
						t.Error("Day:", item.Date, "Zero rate for", currency)
					}
				} else {
					t.Error(err)
				}
			} else {
				t.Error("Parse rate to string unsuccessful")
			}
		}
	}
}
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2019-11-27 14:43:17.51424 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "d1dfde001e0b4842c51220711a5d680ef0d2f207"
<commit_msg>"Autogenerated build info"<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2019-11-27 14:57:13.14671 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "b0686ca66f981307bfc4cffe8d24b84e156cc866"
<|endoftext|>


<commit_before>package snakes

import (
	"math/big"
	"testing"
)

func check(t *testing.T, a, b, c int) {
	bigA := big.NewInt(int64(a))
	bigB := big.NewInt(int64(b))
	bigC := big.NewInt(int64(c))
	z := new(big.Int).Exp(bigA, bigB, bigC)
	got := MontgomeryLadderExp(bigA, bigB, bigC)
	if got.Cmp(z) != 0 {
		t.Errorf("pow(%d, %d, %d) Expected: %s, got %s", a, b, c, z.String(), got.String())
	}
}

func TestMontgomeryLadderModExp(t *testing.T) {
	check(t, 0, 0, 1)
	check(t, 0, 1, 1)
	check(t, 0, 2, 1)
	check(t, 1, 0, 1)
	check(t, 2, 0, 1)
	check(t, 2, 10, 1)
	check(t, 4, 13, 1)
	check(t, 13, 4, 1)
	check(t, 2, 10, 15)
	check(t, 3, 10, 15)
	check(t, 13, 4, 7)
	check(t, 19, 65, 3)
	check(t, 1432, 432, 123)
}
<commit_msg>Added a benchmark, is it good who knows?<commit_after>package snakes

import (
	"math/big"
	"testing"
)

func check(t *testing.T, a, b, c int) {
	bigA := big.NewInt(int64(a))
	bigB := big.NewInt(int64(b))
	bigC := big.NewInt(int64(c))
	z := new(big.Int).Exp(bigA, bigB, bigC)
	got := MontgomeryLadderExp(bigA, bigB, bigC)
	if got.Cmp(z) != 0 {
		t.Errorf("pow(%d, %d, %d) Expected: %s, got %s", a, b, c, z.String(), got.String())
	}
}

func TestMontgomeryLadderExp(t *testing.T) {
	check(t, 0, 0, 1)
	check(t, 0, 1, 1)
	check(t, 0, 2, 1)
	check(t, 1, 0, 1)
	check(t, 2, 0, 1)
	check(t, 2, 10, 1)
	check(t, 4, 13, 1)
	check(t, 13, 4, 1)
	check(t, 2, 10, 15)
	check(t, 3, 10, 15)
	check(t, 13, 4, 7)
	check(t, 19, 65, 3)
	check(t, 1432, 432, 123)
}

func BenchmarkBigIntExp(b *testing.B) {
	x := new(big.Int).Lsh(big.NewInt(1), 1374)
	y := new(big.Int).Lsh(big.NewInt(1), 4096)
	z := new(big.Int).Lsh(big.NewInt(1), 234)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		new(big.Int).Exp(x, y, z)
	}
}

func BenchmarkMontgomeryLadderExp(b *testing.B) {
	x := new(big.Int).Lsh(big.NewInt(1), 1374)
	y := new(big.Int).Lsh(big.NewInt(1), 4096)
	z := new(big.Int).Lsh(big.NewInt(1), 234)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		MontgomeryLadderExp(x, y, z)
	}
}
<|endoftext|>