1
0
mirror of https://github.com/go-task/task.git synced 2025-03-25 21:39:05 +02:00

Update dependencies

Fixes 
This commit is contained in:
Andrey Nering 2018-01-21 09:39:15 -02:00
parent 6f74c2d823
commit 42509cf2f5
74 changed files with 2758 additions and 858 deletions

18
Gopkg.lock generated

@ -32,10 +32,10 @@
revision = "37469d0c81a7910b49d64a0d308ded4823e90937"
[[projects]]
branch = "master"
name = "github.com/imdario/mergo"
packages = ["."]
revision = "7fe0c75c13abdee74b09fcacef5ea1c6bba6a874"
version = "0.2.4"
revision = "c961a4f451fae5acb3b50c1a54576c6929e3a6d8"
[[projects]]
branch = "master"
@ -67,8 +67,8 @@
[[projects]]
name = "github.com/satori/go.uuid"
packages = ["."]
revision = "879c5887cd475cd7864858769793b2ceb0d44feb"
version = "v1.1.0"
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
version = "v1.2.0"
[[projects]]
branch = "master"
@ -90,13 +90,13 @@
"scrypt",
"ssh/terminal"
]
revision = "0fcca4842a8d74bfddc2c96a073bd2a4d2a7a2e8"
revision = "a6600008915114d9c087fad9f03d75087b1a74df"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context"]
revision = "d866cfc389cec985d6fda2859936a575a55a3ab6"
revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec"
[[projects]]
branch = "master"
@ -111,13 +111,13 @@
"unix",
"windows"
]
revision = "28a7276518d399b9634904daad79e18b44d481bc"
revision = "2c42eef0765b9837fbdab12011af7830f55f88f0"
[[projects]]
branch = "v2"
name = "gopkg.in/yaml.v2"
packages = ["."]
revision = "c95af922eae69f190717a0b7148960af8c55a072"
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
[[projects]]
branch = "master"
@ -126,7 +126,7 @@
"interp",
"syntax"
]
revision = "74c5a41b2a56e9d106305492759e4e531ed5bf47"
revision = "46a8a4e0a8ca0d45de9626b8d290ccc7bfc732b0"
[solve-meta]
analyzer-name = "dep"

33
vendor/github.com/imdario/mergo/.gitignore generated vendored Normal file

@ -0,0 +1,33 @@
#### joe made this: http://goel.io/joe
#### go ####
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
#### vim ####
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# Session
Session.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags

@ -1,2 +1,7 @@
language: go
install: go get -t
install:
- go get -t
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
script:
- $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN

@ -2,17 +2,16 @@
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region Marche.
![Mergo dall'alto](http://www.comune.mergo.an.it/Siti/Mergo/Immagini/Foto/mergo_dall_alto.jpg)
Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region of Marche.
## Status
It is ready for production use. It works fine after extensive use in the wild.
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
[![Build Status][1]][2]
[![GoDoc][3]][4]
[![GoCard][5]][6]
[![Coverage Status][7]][8]
[1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo
@ -20,19 +19,41 @@ It is ready for production use. It works fine after extensive use in the wild.
[4]: https://godoc.org/github.com/imdario/mergo
[5]: https://goreportcard.com/badge/imdario/mergo
[6]: https://goreportcard.com/report/github.com/imdario/mergo
[7]: https://coveralls.io/repos/github/imdario/mergo/badge.svg?branch=master
[8]: https://coveralls.io/github/imdario/mergo?branch=master
### Latest release
[Release 0.3.2](https://github.com/imdario/mergo/releases/tag/0.3.2) is an important release because it changes `Merge()`and `Map()` signatures to support [transformers](#transformers). An optional/variadic argument has been added, so it won't break existing code.
### Important note
Mergo is intended to assign **only** zero value fields on destination with source value. Since April 6th it works like this. Before it didn't work properly, causing some random overwrites. After some issues and PRs I found it didn't merge as I designed it. Thanks to [imdario/mergo#8](https://github.com/imdario/mergo/pull/8) overwriting functions were added and the wrong behavior was clearly detected.
If you were using Mergo **before** April 6th 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause (I hope it won't!) in existing projects after the change (release 0.2.0).
### Mergo in the wild
- [docker/docker](https://github.com/docker/docker/)
- [moby/moby](https://github.com/moby/moby)
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
- [vmware/dispatch](https://github.com/vmware/dispatch)
- [Shopify/themekit](https://github.com/Shopify/themekit)
- [imdario/zas](https://github.com/imdario/zas)
- [matcornic/hermes](https://github.com/matcornic/hermes)
- [OpenBazaar/openbazaar-go](https://github.com/OpenBazaar/openbazaar-go)
- [kataras/iris](https://github.com/kataras/iris)
- [michaelsauter/crane](https://github.com/michaelsauter/crane)
- [go-task/task](https://github.com/go-task/task)
- [sensu/uchiwa](https://github.com/sensu/uchiwa)
- [ory/hydra](https://github.com/ory/hydra)
- [sisatech/vcli](https://github.com/sisatech/vcli)
- [dairycart/dairycart](https://github.com/dairycart/dairycart)
- [projectcalico/felix](https://github.com/projectcalico/felix)
- [resin-os/balena](https://github.com/resin-os/balena)
- [go-kivik/kivik](https://github.com/go-kivik/kivik)
- [Telefonica/govice](https://github.com/Telefonica/govice)
- [supergiant/supergiant](supergiant/supergiant)
- [SergeyTsalkov/brooce](https://github.com/SergeyTsalkov/brooce)
- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
- [ohsu-comp-bio/funnel](https://github.com/ohsu-comp-bio/funnel)
- [EagerIO/Stout](https://github.com/EagerIO/Stout)
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
- [russross/canvasassignments](https://github.com/russross/canvasassignments)
@ -50,7 +71,7 @@ If you were using Mergo **before** April 6th 2015, please check your project wor
- [thoas/picfit](https://github.com/thoas/picfit)
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
- [Iris Web Framework](https://github.com/kataras/iris)
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
## Installation
@ -71,15 +92,15 @@ if err := mergo.Merge(&dst, src); err != nil {
}
```
Also, you can merge overwriting values using MergeWithOverwrite.
Also, you can merge overwriting values using the transformer `WithOverride`.
```go
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
if err := mergo.Merge(&dst, src, WithOverride); err != nil {
// ...
}
```
Additionally, you can map a map[string]interface{} to a struct (and otherwise, from struct to map), following the same restrictions as in Merge(). Keys are capitalized to find each corresponding exported field.
Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field.
```go
if err := mergo.Map(&dst, srcMap); err != nil {
@ -87,7 +108,7 @@ if err := mergo.Map(&dst, srcMap); err != nil {
}
```
Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as map[string]interface{}. They will be just assigned as values.
Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as `map[string]interface{}`. They will be just assigned as values.
More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo).
@ -111,13 +132,10 @@ func main() {
A: "one",
B: 2,
}
dest := Foo{
A: "two",
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
@ -126,7 +144,55 @@ func main() {
Note: if test are failing due missing package, please execute:
go get gopkg.in/yaml.v1
go get gopkg.in/yaml.v2
### Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
```go
package main
import (
"fmt"
"reflect"
"time"
)
type timeTransfomer struct {
}
func (t timeTransfomer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ == reflect.TypeOf(time.Time{}) {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
isZero := dst.MethodByName("IsZero")
result := isZero.Call([]reflect.Value{})
if result[0].Bool() {
dst.Set(src)
}
}
return nil
}
}
return nil
}
type Snapshot struct {
Time time.Time
// ...
}
func main() {
src := Snapshot{time.Now()}
dest := Snapshot{}
mergo.Merge(&dest, src, WithTransformers(timeTransfomer{}))
fmt.Println(dest)
// Will print
// { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 }
}
```
## Contact me

@ -31,7 +31,8 @@ func isExported(field reflect.StructField) bool {
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *config) (err error) {
overwrite := config.overwrite
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
@ -97,15 +98,15 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
continue
}
if srcKind == dstKind {
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
} else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
} else if srcKind == reflect.Map {
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
} else {
@ -127,28 +128,35 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
// doesn't apply if dst is a map.
// This is separated method from Merge because it is cleaner and it keeps sane
// semantics: merging equal types, mapping different (restricted) types.
func Map(dst, src interface{}) error {
return _map(dst, src, false)
func Map(dst, src interface{}, opts ...func(*config)) error {
return _map(dst, src, opts...)
}
// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MapWithOverwrite(dst, src interface{}) error {
return _map(dst, src, true)
// Deprecated: Use Map(…) with WithOverride
func MapWithOverwrite(dst, src interface{}, opts ...func(*config)) error {
return _map(dst, src, append(opts, WithOverride)...)
}
func _map(dst, src interface{}, overwrite bool) error {
func _map(dst, src interface{}, opts ...func(*config)) error {
var (
vDst, vSrc reflect.Value
err error
)
config := &config{}
for _, opt := range opts {
opt(config)
}
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
// To be friction-less, we redirect equal-type arguments
// to deepMerge. Only because arguments can be anything.
if vSrc.Kind() == vDst.Kind() {
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
switch vSrc.Kind() {
case reflect.Struct:
@ -162,5 +170,5 @@ func _map(dst, src interface{}, overwrite bool) error {
default:
return ErrNotSupported
}
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}

@ -8,14 +8,12 @@
package mergo
import (
"reflect"
)
import "reflect"
func hasExportedField(dst reflect.Value) (exported bool) {
for i, n := 0, dst.NumField(); i < n; i++ {
field := dst.Type().Field(i)
if field.Anonymous {
if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
exported = exported || hasExportedField(dst.Field(i))
} else {
exported = exported || len(field.PkgPath) == 0
@ -24,10 +22,21 @@ func hasExportedField(dst reflect.Value) (exported bool) {
return
}
type config struct {
overwrite bool
transformers transformers
}
type transformers interface {
Transformer(reflect.Type) func(dst, src reflect.Value) error
}
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *config) (err error) {
overwrite := config.overwrite
if !src.IsValid() {
return
}
@ -44,11 +53,19 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
// Remember, remember...
visited[h] = &visit{addr, typ, seen}
}
if config.transformers != nil && !isEmptyValue(dst) {
if fn := config.transformers.Transformer(dst.Type()); fn != nil {
err = fn(dst, src)
return
}
}
switch dst.Kind() {
case reflect.Struct:
if hasExportedField(dst) {
for i, n := 0, dst.NumField(); i < n; i++ {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
return
}
}
@ -84,9 +101,21 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
case reflect.Ptr:
fallthrough
case reflect.Map:
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
case reflect.Slice:
srcSlice := reflect.ValueOf(srcElement.Interface())
var dstSlice reflect.Value
if !dstElement.IsValid() || dstElement.IsNil() {
dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
} else {
dstSlice = reflect.ValueOf(dstElement.Interface())
}
dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
dst.SetMapIndex(key, dstSlice)
}
}
if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map {
@ -100,20 +129,25 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
dst.SetMapIndex(key, srcElement)
}
}
case reflect.Slice:
dst.Set(reflect.AppendSlice(dst, src))
case reflect.Ptr:
fallthrough
case reflect.Interface:
if src.IsNil() {
break
}
if src.Kind() != reflect.Interface {
if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
} else if src.Kind() == reflect.Ptr {
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
} else if dst.Elem().Type() == src.Type() {
if err = deepMerge(dst.Elem(), src, visited, depth+1, overwrite); err != nil {
if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
return
}
} else {
@ -121,13 +155,11 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
}
break
}
if src.IsNil() {
break
} else if dst.IsNil() || overwrite {
if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
default:
@ -142,26 +174,46 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
// src attributes if they themselves are not empty. dst and src must be valid same-type structs
// and dst must be a pointer to struct.
// It won't merge unexported (private) fields and will do recursively any exported field.
func Merge(dst, src interface{}) error {
return merge(dst, src, false)
func Merge(dst, src interface{}, opts ...func(*config)) error {
return merge(dst, src, opts...)
}
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MergeWithOverwrite(dst, src interface{}) error {
return merge(dst, src, true)
// Deprecated: use Merge(…) with WithOverride
func MergeWithOverwrite(dst, src interface{}, opts ...func(*config)) error {
return merge(dst, src, append(opts, WithOverride)...)
}
func merge(dst, src interface{}, overwrite bool) error {
// WithTransformers adds transformers to merge, allowing to customize the merging of some types.
func WithTransformers(transformers transformers) func(*config) {
return func(config *config) {
config.transformers = transformers
}
}
// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
func WithOverride(config *config) {
config.overwrite = true
}
func merge(dst, src interface{}, opts ...func(*config)) error {
var (
vDst, vSrc reflect.Value
err error
)
config := &config{}
for _, opt := range opts {
opt(config)
}
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
if vDst.Type() != vSrc.Type() {
return ErrDifferentArgumentsTypes
}
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}

@ -32,7 +32,7 @@ type visit struct {
next *visit
}
// From src/pkg/encoding/json.
// From src/pkg/encoding/json/encode.go.
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
@ -47,6 +47,8 @@ func isEmptyValue(v reflect.Value) bool {
return v.Float() == 0
case reflect.Interface, reflect.Ptr, reflect.Func:
return v.IsNil()
case reflect.Invalid:
return true
}
return false
}

@ -6,6 +6,14 @@ go:
- 1.4
- 1.5
- 1.6
- 1.7
- 1.8
- 1.9
- tip
matrix:
allow_failures:
- go: tip
fast_finish: true
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover

@ -1,4 +1,4 @@
Copyright (C) 2013-2016 by Maxim Bublis <b@codemonkey.ru>
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

@ -59,7 +59,7 @@ func main() {
## Copyright
Copyright (C) 2013-2016 by Maxim Bublis <b@codemonkey.ru>.
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>.
UUID package released under MIT License.
See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details.

206
vendor/github.com/satori/go.uuid/codec.go generated vendored Normal file

@ -0,0 +1,206 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"bytes"
"encoding/hex"
"fmt"
)
// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
err = u.UnmarshalBinary(input)
return
}
// FromBytesOrNil returns UUID converted from raw byte slice input.
// Same behavior as FromBytes, but returns a Nil UUID on error.
func FromBytesOrNil(input []byte) UUID {
uuid, err := FromBytes(input)
if err != nil {
return Nil
}
return uuid
}
// FromString returns UUID parsed from string input.
// Input is expected in a form accepted by UnmarshalText.
func FromString(input string) (u UUID, err error) {
err = u.UnmarshalText([]byte(input))
return
}
// FromStringOrNil returns UUID parsed from string input.
// Same behavior as FromString, but returns a Nil UUID on error.
func FromStringOrNil(input string) UUID {
uuid, err := FromString(input)
if err != nil {
return Nil
}
return uuid
}
// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
text = []byte(u.String())
return
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
// "6ba7b8109dad11d180b400c04fd430c8"
// ABNF for supported UUID text representation follows:
// uuid := canonical | hashlike | braced | urn
// plain := canonical | hashlike
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
// hashlike := 12hexoct
// braced := '{' plain '}'
// urn := URN ':' UUID-NID ':' plain
// URN := 'urn'
// UUID-NID := 'uuid'
// 12hexoct := 6hexoct 6hexoct
// 6hexoct := 4hexoct 2hexoct
// 4hexoct := 2hexoct 2hexoct
// 2hexoct := hexoct hexoct
// hexoct := hexdig hexdig
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
func (u *UUID) UnmarshalText(text []byte) (err error) {
switch len(text) {
case 32:
return u.decodeHashLike(text)
case 36:
return u.decodeCanonical(text)
case 38:
return u.decodeBraced(text)
case 41:
fallthrough
case 45:
return u.decodeURN(text)
default:
return fmt.Errorf("uuid: incorrect UUID length: %s", text)
}
}
// decodeCanonical decodes UUID string in format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
func (u *UUID) decodeCanonical(t []byte) (err error) {
if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' {
return fmt.Errorf("uuid: incorrect UUID format %s", t)
}
src := t[:]
dst := u[:]
for i, byteGroup := range byteGroups {
if i > 0 {
src = src[1:] // skip dash
}
_, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup])
if err != nil {
return
}
src = src[byteGroup:]
dst = dst[byteGroup/2:]
}
return
}
// decodeHashLike decodes UUID string in format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeHashLike(t []byte) (err error) {
src := t[:]
dst := u[:]
if _, err = hex.Decode(dst, src); err != nil {
return err
}
return
}
// decodeBraced decodes UUID string in format
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format
// "{6ba7b8109dad11d180b400c04fd430c8}".
func (u *UUID) decodeBraced(t []byte) (err error) {
l := len(t)
if t[0] != '{' || t[l-1] != '}' {
return fmt.Errorf("uuid: incorrect UUID format %s", t)
}
return u.decodePlain(t[1 : l-1])
}
// decodeURN decodes UUID string in format
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format
// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeURN(t []byte) (err error) {
total := len(t)
urn_uuid_prefix := t[:9]
if !bytes.Equal(urn_uuid_prefix, urnPrefix) {
return fmt.Errorf("uuid: incorrect UUID format: %s", t)
}
return u.decodePlain(t[9:total])
}
// decodePlain decodes UUID string in canonical format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodePlain(t []byte) (err error) {
switch len(t) {
case 32:
return u.decodeHashLike(t)
case 36:
return u.decodeCanonical(t)
default:
return fmt.Errorf("uuid: incorrrect UUID length: %s", t)
}
}
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
data = u.Bytes()
return
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
if len(data) != Size {
err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
return
}
copy(u[:], data)
return
}

239
vendor/github.com/satori/go.uuid/generator.go generated vendored Normal file

@ -0,0 +1,239 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"encoding/binary"
"hash"
"net"
"os"
"sync"
"time"
)
// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000
var (
global = newDefaultGenerator()
epochFunc = unixTimeFunc
posixUID = uint32(os.Getuid())
posixGID = uint32(os.Getgid())
)
// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
return global.NewV1()
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
return global.NewV2(domain)
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
return global.NewV3(ns, name)
}
// NewV4 returns random generated UUID.
func NewV4() UUID {
return global.NewV4()
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
return global.NewV5(ns, name)
}
// Generator provides interface for generating UUIDs.
type Generator interface {
NewV1() UUID
NewV2(domain byte) UUID
NewV3(ns UUID, name string) UUID
NewV4() UUID
NewV5(ns UUID, name string) UUID
}
// Default generator implementation.
type generator struct {
storageOnce sync.Once
storageMutex sync.Mutex
lastTime uint64
clockSequence uint16
hardwareAddr [6]byte
}
func newDefaultGenerator() Generator {
return &generator{}
}
// NewV1 returns UUID based on current timestamp and MAC address.
func (g *generator) NewV1() UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage()
binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
copy(u[10:], hardwareAddr)
u.SetVersion(V1)
u.SetVariant(VariantRFC4122)
return u
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func (g *generator) NewV2(domain byte) UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage()
switch domain {
case DomainPerson:
binary.BigEndian.PutUint32(u[0:], posixUID)
case DomainGroup:
binary.BigEndian.PutUint32(u[0:], posixGID)
}
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
u[9] = domain
copy(u[10:], hardwareAddr)
u.SetVersion(V2)
u.SetVariant(VariantRFC4122)
return u
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func (g *generator) NewV3(ns UUID, name string) UUID {
u := newFromHash(md5.New(), ns, name)
u.SetVersion(V3)
u.SetVariant(VariantRFC4122)
return u
}
// NewV4 returns random generated UUID.
func (g *generator) NewV4() UUID {
u := UUID{}
g.safeRandom(u[:])
u.SetVersion(V4)
u.SetVariant(VariantRFC4122)
return u
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func (g *generator) NewV5(ns UUID, name string) UUID {
u := newFromHash(sha1.New(), ns, name)
u.SetVersion(V5)
u.SetVariant(VariantRFC4122)
return u
}
func (g *generator) initStorage() {
g.initClockSequence()
g.initHardwareAddr()
}
func (g *generator) initClockSequence() {
buf := make([]byte, 2)
g.safeRandom(buf)
g.clockSequence = binary.BigEndian.Uint16(buf)
}
func (g *generator) initHardwareAddr() {
interfaces, err := net.Interfaces()
if err == nil {
for _, iface := range interfaces {
if len(iface.HardwareAddr) >= 6 {
copy(g.hardwareAddr[:], iface.HardwareAddr)
return
}
}
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence
g.safeRandom(g.hardwareAddr[:])
// Set multicast bit as recommended in RFC 4122
g.hardwareAddr[0] |= 0x01
}
func (g *generator) safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func (g *generator) getStorage() (uint64, uint16, []byte) {
g.storageOnce.Do(g.initStorage)
g.storageMutex.Lock()
defer g.storageMutex.Unlock()
timeNow := epochFunc()
// Clock changed backwards since last UUID generation.
// Should increase clock sequence.
if timeNow <= g.lastTime {
g.clockSequence++
}
g.lastTime = timeNow
return timeNow, g.clockSequence, g.hardwareAddr[:]
}
// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
return epochStart + uint64(time.Now().UnixNano()/100)
}
// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
u := UUID{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}

78
vendor/github.com/satori/go.uuid/sql.go generated vendored Normal file

@ -0,0 +1,78 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"database/sql/driver"
"fmt"
)
// Value implements the driver.Valuer interface.
func (u UUID) Value() (driver.Value, error) {
return u.String(), nil
}
// Scan implements the sql.Scanner interface.
// A 16-byte slice is handled by UnmarshalBinary, while
// a longer byte slice or a string is handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case []byte:
if len(src) == Size {
return u.UnmarshalBinary(src)
}
return u.UnmarshalText(src)
case string:
return u.UnmarshalText([]byte(src))
}
return fmt.Errorf("uuid: cannot convert %T to UUID", src)
}
// NullUUID can be used with the standard sql package to represent a
// UUID value that can be NULL in the database
type NullUUID struct {
UUID UUID
Valid bool
}
// Value implements the driver.Valuer interface.
func (u NullUUID) Value() (driver.Value, error) {
if !u.Valid {
return nil, nil
}
// Delegate to UUID Value function
return u.UUID.Value()
}
// Scan implements the sql.Scanner interface.
func (u *NullUUID) Scan(src interface{}) error {
if src == nil {
u.UUID, u.Valid = Nil, false
return nil
}
// Delegate to UUID Scan function
u.Valid = true
return u.UUID.Scan(src)
}

@ -1,4 +1,4 @@
// Copyright (C) 2013-2015 by Maxim Bublis <b@codemonkey.ru>
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@ -26,23 +26,29 @@ package uuid
import (
"bytes"
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"fmt"
"hash"
"net"
"os"
"sync"
"time"
)
// Size of a UUID in bytes.
const Size = 16
// UUID representation compliant with specification
// described in RFC 4122.
type UUID [Size]byte
// UUID versions
const (
_ byte = iota
V1
V2
V3
V4
V5
)
// UUID layout variants.
const (
VariantNCS = iota
VariantNCS byte = iota
VariantRFC4122
VariantMicrosoft
VariantFuture
@ -55,136 +61,48 @@ const (
DomainOrg
)
// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000
// Used in string method conversion
const dash byte = '-'
// UUID v1/v2 storage.
var (
storageMutex sync.Mutex
storageOnce sync.Once
epochFunc = unixTimeFunc
clockSequence uint16
lastTime uint64
hardwareAddr [6]byte
posixUID = uint32(os.Getuid())
posixGID = uint32(os.Getgid())
)
// String parse helpers.
var (
urnPrefix = []byte("urn:uuid:")
byteGroups = []int{8, 4, 4, 4, 12}
)
func initClockSequence() {
buf := make([]byte, 2)
safeRandom(buf)
clockSequence = binary.BigEndian.Uint16(buf)
}
func initHardwareAddr() {
interfaces, err := net.Interfaces()
if err == nil {
for _, iface := range interfaces {
if len(iface.HardwareAddr) >= 6 {
copy(hardwareAddr[:], iface.HardwareAddr)
return
}
}
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence
safeRandom(hardwareAddr[:])
// Set multicast bit as recommended in RFC 4122
hardwareAddr[0] |= 0x01
}
func initStorage() {
initClockSequence()
initHardwareAddr()
}
func safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
return epochStart + uint64(time.Now().UnixNano()/100)
}
// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte
// NullUUID can be used with the standard sql package to represent a
// UUID value that can be NULL in the database
type NullUUID struct {
UUID UUID
Valid bool
}
// The nil UUID is special form of UUID that is specified to have all
// Nil is special form of UUID that is specified to have all
// 128 bits set to zero.
var Nil = UUID{}
// Predefined namespace UUIDs.
var (
NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
)
// And returns result of binary AND of two UUIDs.
func And(u1 UUID, u2 UUID) UUID {
u := UUID{}
for i := 0; i < 16; i++ {
u[i] = u1[i] & u2[i]
}
return u
}
// Or returns result of binary OR of two UUIDs.
func Or(u1 UUID, u2 UUID) UUID {
u := UUID{}
for i := 0; i < 16; i++ {
u[i] = u1[i] | u2[i]
}
return u
}
// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
return bytes.Equal(u1[:], u2[:])
}
// Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint {
return uint(u[6] >> 4)
func (u UUID) Version() byte {
return u[6] >> 4
}
// Variant returns UUID layout variant.
func (u UUID) Variant() uint {
func (u UUID) Variant() byte {
switch {
case (u[8] & 0x80) == 0x00:
case (u[8] >> 7) == 0x00:
return VariantNCS
case (u[8]&0xc0)|0x80 == 0x80:
case (u[8] >> 6) == 0x02:
return VariantRFC4122
case (u[8]&0xe0)|0xc0 == 0xc0:
case (u[8] >> 5) == 0x06:
return VariantMicrosoft
case (u[8] >> 5) == 0x07:
fallthrough
default:
return VariantFuture
}
return VariantFuture
}
// Bytes returns bytes slice representation of UUID.
@ -198,13 +116,13 @@ func (u UUID) String() string {
buf := make([]byte, 36)
hex.Encode(buf[0:8], u[0:4])
buf[8] = dash
buf[8] = '-'
hex.Encode(buf[9:13], u[4:6])
buf[13] = dash
buf[13] = '-'
hex.Encode(buf[14:18], u[6:8])
buf[18] = dash
buf[18] = '-'
hex.Encode(buf[19:23], u[8:10])
buf[23] = dash
buf[23] = '-'
hex.Encode(buf[24:], u[10:])
return string(buf)
@ -215,274 +133,29 @@ func (u *UUID) SetVersion(v byte) {
u[6] = (u[6] & 0x0f) | (v << 4)
}
// SetVariant sets variant bits as described in RFC 4122.
func (u *UUID) SetVariant() {
u[8] = (u[8] & 0xbf) | 0x80
}
// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
text = []byte(u.String())
return
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
func (u *UUID) UnmarshalText(text []byte) (err error) {
if len(text) < 32 {
err = fmt.Errorf("uuid: UUID string too short: %s", text)
return
// SetVariant sets variant bits.
func (u *UUID) SetVariant(v byte) {
switch v {
case VariantNCS:
u[8] = (u[8]&(0xff>>1) | (0x00 << 7))
case VariantRFC4122:
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
case VariantMicrosoft:
u[8] = (u[8]&(0xff>>3) | (0x06 << 5))
case VariantFuture:
fallthrough
default:
u[8] = (u[8]&(0xff>>3) | (0x07 << 5))
}
t := text[:]
braced := false
if bytes.Equal(t[:9], urnPrefix) {
t = t[9:]
} else if t[0] == '{' {
braced = true
t = t[1:]
}
b := u[:]
for i, byteGroup := range byteGroups {
if i > 0 && t[0] == '-' {
t = t[1:]
} else if i > 0 && t[0] != '-' {
err = fmt.Errorf("uuid: invalid string format")
return
}
if i == 2 {
if !bytes.Contains([]byte("012345"), []byte{t[0]}) {
err = fmt.Errorf("uuid: invalid version number: %s", t[0])
return
}
}
if len(t) < byteGroup {
err = fmt.Errorf("uuid: UUID string too short: %s", text)
return
}
if i == 4 && len(t) > byteGroup &&
((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) {
err = fmt.Errorf("uuid: UUID string too long: %s", t)
return
}
_, err = hex.Decode(b[:byteGroup/2], t[:byteGroup])
if err != nil {
return
}
t = t[byteGroup:]
b = b[byteGroup/2:]
}
return
}
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
data = u.Bytes()
return
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
if len(data) != 16 {
err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
return
}
copy(u[:], data)
return
}
// Value implements the driver.Valuer interface.
func (u UUID) Value() (driver.Value, error) {
return u.String(), nil
}
// Scan implements the sql.Scanner interface.
// A 16-byte slice is handled by UnmarshalBinary, while
// a longer byte slice or a string is handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case []byte:
if len(src) == 16 {
return u.UnmarshalBinary(src)
}
return u.UnmarshalText(src)
case string:
return u.UnmarshalText([]byte(src))
}
return fmt.Errorf("uuid: cannot convert %T to UUID", src)
}
// Value implements the driver.Valuer interface.
func (u NullUUID) Value() (driver.Value, error) {
if !u.Valid {
return nil, nil
}
// Delegate to UUID Value function
return u.UUID.Value()
}
// Scan implements the sql.Scanner interface.
func (u *NullUUID) Scan(src interface{}) error {
if src == nil {
u.UUID, u.Valid = Nil, false
return nil
}
// Delegate to UUID Scan function
u.Valid = true
return u.UUID.Scan(src)
}
// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
err = u.UnmarshalBinary(input)
return
}
// FromBytesOrNil returns UUID converted from raw byte slice input.
// Same behavior as FromBytes, but returns a Nil UUID on error.
func FromBytesOrNil(input []byte) UUID {
uuid, err := FromBytes(input)
// Must is a helper that wraps a call to a function returning (UUID, error)
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
func Must(u UUID, err error) UUID {
if err != nil {
return Nil
panic(err)
}
return uuid
}
// FromString returns UUID parsed from string input.
// Input is expected in a form accepted by UnmarshalText.
func FromString(input string) (u UUID, err error) {
err = u.UnmarshalText([]byte(input))
return
}
// FromStringOrNil returns UUID parsed from string input.
// Same behavior as FromString, but returns a Nil UUID on error.
func FromStringOrNil(input string) UUID {
uuid, err := FromString(input)
if err != nil {
return Nil
}
return uuid
}
// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func getStorage() (uint64, uint16, []byte) {
storageOnce.Do(initStorage)
storageMutex.Lock()
defer storageMutex.Unlock()
timeNow := epochFunc()
// Clock changed backwards since last UUID generation.
// Should increase clock sequence.
if timeNow <= lastTime {
clockSequence++
}
lastTime = timeNow
return timeNow, clockSequence, hardwareAddr[:]
}
// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := getStorage()
binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
copy(u[10:], hardwareAddr)
u.SetVersion(1)
u.SetVariant()
return u
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := getStorage()
switch domain {
case DomainPerson:
binary.BigEndian.PutUint32(u[0:], posixUID)
case DomainGroup:
binary.BigEndian.PutUint32(u[0:], posixGID)
}
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
u[9] = domain
copy(u[10:], hardwareAddr)
u.SetVersion(2)
u.SetVariant()
return u
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
u := newFromHash(md5.New(), ns, name)
u.SetVersion(3)
u.SetVariant()
return u
}
// NewV4 returns random generated UUID.
func NewV4() UUID {
u := UUID{}
safeRandom(u[:])
u.SetVersion(4)
u.SetVariant()
return u
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
u := newFromHash(sha1.New(), ns, name)
u.SetVersion(5)
u.SetVariant()
return u
}
// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
u := UUID{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}

@ -16,6 +16,9 @@ import (
"hash"
"io"
"io/ioutil"
"golang.org/x/crypto/internal/chacha20"
"golang.org/x/crypto/poly1305"
)
const (
@ -111,10 +114,10 @@ var cipherModes = map[string]*streamCipherMode{
// RFC4345 introduces improved versions of Arcfour.
"arcfour": {16, 0, 0, newRC4},
// AES-GCM is not a stream cipher, so it is constructed with a
// special case. If we add any more non-stream ciphers, we
// should invest a cleaner way to do this.
gcmCipherID: {16, 12, 0, nil},
// AEAD ciphers are special cased. If we add any more non-stream
// ciphers, we should create a cleaner way to do this.
gcmCipherID: {16, 12, 0, nil},
chacha20Poly1305ID: {64, 0, 0, nil},
// CBC mode is insecure and so is not included in the default config.
// (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
@ -627,3 +630,142 @@ func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, pack
return nil
}
const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com
// AEAD, which is described here:
//
// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00
//
// the methods here also implement padding, which RFC4253 Section 6
// also requires of stream ciphers.
type chacha20Poly1305Cipher struct {
lengthKey [32]byte
contentKey [32]byte
buf []byte
}
func newChaCha20Cipher(key []byte) (packetCipher, error) {
if len(key) != 64 {
panic("key length")
}
c := &chacha20Poly1305Cipher{
buf: make([]byte, 256),
}
copy(c.contentKey[:], key[:32])
copy(c.lengthKey[:], key[32:])
return c, nil
}
// The Poly1305 key is obtained by encrypting 32 0-bytes.
var chacha20PolyKeyInput [32]byte
func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
var counter [16]byte
binary.BigEndian.PutUint64(counter[8:], uint64(seqNum))
var polyKey [32]byte
chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey)
encryptedLength := c.buf[:4]
if _, err := r.Read(encryptedLength); err != nil {
return nil, err
}
var lenBytes [4]byte
chacha20.XORKeyStream(lenBytes[:], encryptedLength, &counter, &c.lengthKey)
length := binary.BigEndian.Uint32(lenBytes[:])
if length > maxPacket {
return nil, errors.New("ssh: invalid packet length, packet too large")
}
contentEnd := 4 + length
packetEnd := contentEnd + poly1305.TagSize
if uint32(cap(c.buf)) < packetEnd {
c.buf = make([]byte, packetEnd)
copy(c.buf[:], encryptedLength)
} else {
c.buf = c.buf[:packetEnd]
}
if _, err := r.Read(c.buf[4:packetEnd]); err != nil {
return nil, err
}
var mac [poly1305.TagSize]byte
copy(mac[:], c.buf[contentEnd:packetEnd])
if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) {
return nil, errors.New("ssh: MAC failure")
}
counter[0] = 1
plain := c.buf[4:contentEnd]
chacha20.XORKeyStream(plain, plain, &counter, &c.contentKey)
padding := plain[0]
if padding < 4 {
// padding is a byte, so it automatically satisfies
// the maximum size, which is 255.
return nil, fmt.Errorf("ssh: illegal padding %d", padding)
}
if int(padding)+1 >= len(plain) {
return nil, fmt.Errorf("ssh: padding %d too large", padding)
}
plain = plain[1 : len(plain)-int(padding)]
return plain, nil
}
func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
var counter [16]byte
binary.BigEndian.PutUint64(counter[8:], uint64(seqNum))
var polyKey [32]byte
chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey)
// There is no blocksize, so fall back to multiple of 8 byte
// padding, as described in RFC 4253, Sec 6.
const packetSizeMultiple = 8
padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple
if padding < 4 {
padding += packetSizeMultiple
}
// size (4 bytes), padding (1), payload, padding, tag.
totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize
if cap(c.buf) < totalLength {
c.buf = make([]byte, totalLength)
} else {
c.buf = c.buf[:totalLength]
}
binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
chacha20.XORKeyStream(c.buf, c.buf[:4], &counter, &c.lengthKey)
c.buf[4] = byte(padding)
copy(c.buf[5:], payload)
packetEnd := 5 + len(payload) + padding
if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil {
return err
}
counter[0] = 1
chacha20.XORKeyStream(c.buf[4:], c.buf[4:packetEnd], &counter, &c.contentKey)
var mac [poly1305.TagSize]byte
poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey)
copy(c.buf[packetEnd:], mac[:])
if _, err := w.Write(c.buf); err != nil {
return err
}
return nil
}

@ -28,6 +28,7 @@ const (
var supportedCiphers = []string{
"aes128-ctr", "aes192-ctr", "aes256-ctr",
"aes128-gcm@openssh.com",
chacha20Poly1305ID,
"arcfour256", "arcfour128",
}

@ -6,6 +6,7 @@ package ssh
import (
"bufio"
"bytes"
"errors"
"io"
"log"
@ -253,15 +254,14 @@ func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, ke
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
iv, key, macKey := generateKeys(d, algs, kex)
if algs.Cipher == gcmCipherID {
switch algs.Cipher {
case chacha20Poly1305ID:
return newChaCha20Cipher(key)
case gcmCipherID:
return newGCMCipher(iv, key)
}
if algs.Cipher == aes128cbcID {
case aes128cbcID:
return newAESCBCCipher(iv, key, macKey, algs)
}
if algs.Cipher == tripledescbcID {
case tripledescbcID:
return newTripleDESCBCCipher(iv, key, macKey, algs)
}
@ -342,7 +342,7 @@ func readVersion(r io.Reader) ([]byte, error) {
var ok bool
var buf [1]byte
for len(versionString) < maxVersionStringBytes {
for length := 0; length < maxVersionStringBytes; length++ {
_, err := io.ReadFull(r, buf[:])
if err != nil {
return nil, err
@ -350,6 +350,13 @@ func readVersion(r io.Reader) ([]byte, error) {
// The RFC says that the version should be terminated with \r\n
// but several SSH servers actually only send a \n.
if buf[0] == '\n' {
if !bytes.HasPrefix(versionString, []byte("SSH-")) {
// RFC 4253 says we need to ignore all version string lines
// except the one containing the SSH version (provided that
// all the lines do not exceed 255 bytes in total).
versionString = versionString[:0]
continue
}
ok = true
break
}

124
vendor/golang.org/x/sys/unix/affinity_linux.go generated vendored Normal file

@ -0,0 +1,124 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// CPU affinity functions
package unix
import (
"unsafe"
)
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
// CPUSet represents a CPU affinity mask.
type CPUSet [cpuSetSize]cpuMask
func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(set)), uintptr(unsafe.Pointer(set)))
if e != 0 {
return errnoErr(e)
}
return nil
}
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
// If pid is 0 the calling thread is used.
func SchedGetaffinity(pid int, set *CPUSet) error {
return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
}
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
// If pid is 0 the calling thread is used.
func SchedSetaffinity(pid int, set *CPUSet) error {
return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
}
// Zero clears the set s, so that it contains no CPUs.
func (s *CPUSet) Zero() {
for i := range s {
s[i] = 0
}
}
func cpuBitsIndex(cpu int) int {
return cpu / _NCPUBITS
}
func cpuBitsMask(cpu int) cpuMask {
return cpuMask(1 << (uint(cpu) % _NCPUBITS))
}
// Set adds cpu to the set s.
func (s *CPUSet) Set(cpu int) {
i := cpuBitsIndex(cpu)
if i < len(s) {
s[i] |= cpuBitsMask(cpu)
}
}
// Clear removes cpu from the set s.
func (s *CPUSet) Clear(cpu int) {
i := cpuBitsIndex(cpu)
if i < len(s) {
s[i] &^= cpuBitsMask(cpu)
}
}
// IsSet reports whether cpu is in the set s.
func (s *CPUSet) IsSet(cpu int) bool {
i := cpuBitsIndex(cpu)
if i < len(s) {
return s[i]&cpuBitsMask(cpu) != 0
}
return false
}
// Count returns the number of CPUs in the set s.
func (s *CPUSet) Count() int {
c := 0
for _, b := range s {
c += onesCount64(uint64(b))
}
return c
}
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
// Once this package can require Go 1.9, we can delete this
// and update the caller to use bits.OnesCount64.
func onesCount64(x uint64) int {
const m0 = 0x5555555555555555 // 01010101 ...
const m1 = 0x3333333333333333 // 00110011 ...
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
const m3 = 0x00ff00ff00ff00ff // etc.
const m4 = 0x0000ffff0000ffff
// Implementation: Parallel summing of adjacent bits.
// See "Hacker's Delight", Chap. 5: Counting Bits.
// The following pattern shows the general approach:
//
// x = x>>1&(m0&m) + x&(m0&m)
// x = x>>2&(m1&m) + x&(m1&m)
// x = x>>4&(m2&m) + x&(m2&m)
// x = x>>8&(m3&m) + x&(m3&m)
// x = x>>16&(m4&m) + x&(m4&m)
// x = x>>32&(m5&m) + x&(m5&m)
// return int(x)
//
// Masking (& operations) can be left away when there's no
// danger that a field's sum will carry over into the next
// field: Since the result cannot be > 64, 8 bits is enough
// and we can ignore the masks for the shifts by 8 and up.
// Per "Hacker's Delight", the first line can be simplified
// more, but it saves at best one instruction, so we leave
// it alone for clarity.
const m = 1<<64 - 1
x = x>>1&(m0&m) + x&(m0&m)
x = x>>2&(m1&m) + x&(m1&m)
x = (x>>4 + x) & (m2 & m)
x += x >> 8
x += x >> 16
x += x >> 32
return int(x) & (1<<7 - 1)
}

@ -35,7 +35,6 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
BL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
B syscall·RawSyscall(SB)
@ -53,5 +52,5 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
MOVW R0, r2+20(FP)
RET
TEXT ·seek(SB),NOSPLIT,$0-32
TEXT ·seek(SB),NOSPLIT,$0-28
B syscall·seek(SB)

@ -17,7 +17,7 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
TEXT ·Syscall6(SB),NOSPLIT,$0-80
B syscall·Syscall6(SB)
TEXT ·Syscall(SB),NOSPLIT,$0-48
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
BL runtime·entersyscall(SB)
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1

@ -25,3 +25,7 @@ func Clearenv() {
func Environ() []string {
return syscall.Environ()
}
func Unsetenv(key string) error {
return syscall.Unsetenv(key)
}

@ -1,14 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.4
package unix
import "syscall"
func Unsetenv(key string) error {
// This was added in Go 1.4.
return syscall.Unsetenv(key)
}

@ -11,9 +11,19 @@ import "syscall"
// We can't use the gc-syntax .s files for gccgo. On the plus side
// much of the functionality can be written directly in Go.
//extern gccgoRealSyscallNoError
func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
//extern gccgoRealSyscall
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
syscall.Entersyscall()
r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
syscall.Exitsyscall()
return r, 0
}
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
syscall.Entersyscall()
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
@ -35,6 +45,11 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
return r, 0, syscall.Errno(errno)
}
func RawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
return r, 0
}
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
return r, 0, syscall.Errno(errno)

@ -31,6 +31,12 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp
return r;
}
uintptr_t
gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
{
return syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
// Define the use function in C so that it is not inlined.
extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));

@ -187,6 +187,7 @@ struct ltchars {
#include <linux/vm_sockets.h>
#include <linux/taskstats.h>
#include <linux/genetlink.h>
#include <linux/stat.h>
#include <linux/watchdog.h>
#include <net/route.h>
#include <asm/termbits.h>
@ -426,7 +427,9 @@ ccflags="$@"
$2 ~ /^(VM|VMADDR)_/ ||
$2 ~ /^IOCTL_VM_SOCKETS_/ ||
$2 ~ /^(TASKSTATS|TS)_/ ||
$2 ~ /^CGROUPSTATS_/ ||
$2 ~ /^GENL_/ ||
$2 ~ /^STATX_/ ||
$2 ~ /^UTIME_/ ||
$2 ~ /^XATTR_(CREATE|REPLACE)/ ||
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||

@ -61,6 +61,10 @@ func main() {
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
// Remove spare fields (e.g. in Statx_t)
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
// We refuse to export private fields on s390x
if goarch == "s390x" && goos == "linux" {
// Remove cgo padding fields
@ -68,7 +72,7 @@ func main() {
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
// Remove padding, hidden, or unused fields
removeFieldsRegex = regexp.MustCompile(`X_\S+`)
removeFieldsRegex = regexp.MustCompile(`\bX_\S+`)
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
}

@ -1318,6 +1318,7 @@ func Setgid(uid int) (err error) {
//sys Setpriority(which int, who int, prio int) (err error)
//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
//sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
//sys Sync()
//sys Syncfs(fd int) (err error)
//sysnb Sysinfo(info *Sysinfo_t) (err error)
@ -1455,11 +1456,9 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
// RtSigtimedwait
// SchedGetPriorityMax
// SchedGetPriorityMin
// SchedGetaffinity
// SchedGetparam
// SchedGetscheduler
// SchedRrGetInterval
// SchedSetaffinity
// SchedSetparam
// SchedYield
// Security

@ -1638,6 +1638,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1639,6 +1639,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1643,6 +1643,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1629,6 +1629,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1696,6 +1696,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1696,6 +1696,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1700,6 +1700,27 @@ const (
SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2
STATX_ALL = 0xfff
STATX_ATIME = 0x20
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_NODUMP = 0x40
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
STATX_SIZE = 0x200
STATX_TYPE = 0x1
STATX_UID = 0x8
STATX__RESERVED = 0x80000000
S_BLKSIZE = 0x200
S_IEXEC = 0x40
S_IFBLK = 0x6000

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -1238,6 +1238,21 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0)
return

@ -131,6 +131,36 @@ type Statfs_t struct {
Spare [4]int32
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -643,9 +673,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -760,6 +796,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -792,3 +846,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

@ -131,6 +131,36 @@ type Statfs_t struct {
Spare [4]int64
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -661,9 +691,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -778,6 +814,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -810,3 +864,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -133,6 +133,36 @@ type Statfs_t struct {
Pad_cgo_0 [4]byte
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -632,9 +662,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -749,6 +785,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -781,3 +835,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

@ -132,6 +132,36 @@ type Statfs_t struct {
Spare [4]int64
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -640,9 +670,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -757,6 +793,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -789,3 +843,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -132,6 +132,36 @@ type Statfs_t struct {
Pad_cgo_1 [4]byte
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -637,9 +667,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -754,6 +790,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -786,3 +840,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

@ -132,6 +132,36 @@ type Statfs_t struct {
Spare [5]int64
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -642,9 +672,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -759,6 +795,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -791,3 +845,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -132,6 +132,36 @@ type Statfs_t struct {
Spare [5]int64
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -642,9 +672,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -759,6 +795,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -791,3 +845,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -132,6 +132,36 @@ type Statfs_t struct {
Pad_cgo_1 [4]byte
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -637,9 +667,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -754,6 +790,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -786,3 +840,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

@ -133,6 +133,36 @@ type Statfs_t struct {
Spare [4]int64
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -650,9 +680,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -767,6 +803,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -799,3 +853,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -133,6 +133,36 @@ type Statfs_t struct {
Spare [4]int64
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
X__reserved int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -650,9 +680,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -767,6 +803,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -799,3 +853,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -132,6 +132,36 @@ type Statfs_t struct {
_ [4]byte
}
type StatxTimestamp struct {
Sec int64
Nsec uint32
_ int32
}
type Statx_t struct {
Mask uint32
Blksize uint32
Attributes uint64
Nlink uint32
Uid uint32
Gid uint32
Mode uint16
_ [1]uint16
Ino uint64
Size uint64
Blocks uint64
Attributes_mask uint64
Atime StatxTimestamp
Btime StatxTimestamp
Ctime StatxTimestamp
Mtime StatxTimestamp
Rdev_major uint32
Rdev_minor uint32
Dev_major uint32
Dev_minor uint32
_ [14]uint64
}
type Dirent struct {
Ino uint64
Off int64
@ -667,9 +697,15 @@ type EpollEvent struct {
}
const (
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200
AT_STATX_SYNC_AS_STAT = 0x0
AT_STATX_FORCE_SYNC = 0x2000
AT_STATX_DONT_SYNC = 0x4000
AT_SYMLINK_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100
)
@ -784,6 +820,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4
)
type CGroupStats struct {
Sleeping uint64
Running uint64
Stopped uint64
Uninterruptible uint64
Io_wait uint64
}
const (
CGROUPSTATS_CMD_UNSPEC = 0x3
CGROUPSTATS_CMD_GET = 0x4
CGROUPSTATS_CMD_NEW = 0x5
CGROUPSTATS_TYPE_UNSPEC = 0x0
CGROUPSTATS_TYPE_CGROUP_STATS = 0x1
CGROUPSTATS_CMD_ATTR_UNSPEC = 0x0
CGROUPSTATS_CMD_ATTR_FD = 0x1
)
type Genlmsghdr struct {
Cmd uint8
Version uint8
@ -816,3 +870,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2
)
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

@ -1,15 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
// +build go1.4
package windows
import "syscall"
func Unsetenv(key string) error {
// This was added in Go 1.4.
return syscall.Unsetenv(key)
}

@ -23,3 +23,7 @@ func Clearenv() {
func Environ() []string {
return syscall.Environ()
}
func Unsetenv(key string) error {
return syscall.Unsetenv(key)
}

2
vendor/gopkg.in/yaml.v2/README.md generated vendored

@ -67,6 +67,8 @@ b:
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {

@ -995,9 +995,9 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
space_break = false
preceded_by_whitespace = false
followed_by_whitespace = false
previous_space = false
previous_break = false
followed_by_whitespace = false
previous_space = false
previous_break = false
)
emitter.scalar_data.value = value

@ -5,9 +5,12 @@ package interp
import (
"fmt"
"os"
"os/user"
"path/filepath"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
@ -133,9 +136,11 @@ func (r *Runner) escapedGlobField(parts []fieldPart) (escaped string, glob bool)
return escaped, glob
}
// TODO: consider making brace a special syntax Node
// TODO: consider making these special syntax nodes
type brace struct {
seq bool // {x..y[..incr]} instead of {x,y[,...]}
chars bool // sequence is of chars, not numbers
elems []*braceWord
}
@ -144,12 +149,13 @@ type braceWord struct {
parts []braceWordPart
}
// braceWordPart contains either syntax.WordPart or brace.
// braceWordPart contains any syntax.WordPart or a brace.
type braceWordPart interface{}
var (
litLeftBrace = &syntax.Lit{Value: "{"}
litComma = &syntax.Lit{Value: ","}
litDots = &syntax.Lit{Value: ".."}
litRightBrace = &syntax.Lit{Value: "}"}
)
@ -181,7 +187,7 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
continue
}
last := 0
for j, r := range lit.Value {
for j := 0; j < len(lit.Value); j++ {
addlit := func() {
if last == j {
return // empty lit
@ -190,7 +196,7 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
l2.Value = l2.Value[last:j]
acc.parts = append(acc.parts, &l2)
}
switch r {
switch lit.Value[j] {
case '{':
addlit()
acc = &braceWord{}
@ -203,20 +209,73 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
addlit()
acc = &braceWord{}
cur.elems = append(cur.elems, acc)
case '.':
if cur == nil {
continue
}
if j+1 >= len(lit.Value) || lit.Value[j+1] != '.' {
continue
}
addlit()
cur.seq = true
acc = &braceWord{}
cur.elems = append(cur.elems, acc)
j++
case '}':
if cur == nil {
continue
}
any = true
addlit()
ended := pop()
if len(ended.elems) > 1 {
acc.parts = append(acc.parts, ended)
br := pop()
if len(br.elems) == 1 {
// return {x} to a non-brace
acc.parts = append(acc.parts, litLeftBrace)
acc.parts = append(acc.parts, br.elems[0].parts...)
acc.parts = append(acc.parts, litRightBrace)
break
}
// return {x} to a non-brace
if !br.seq {
acc.parts = append(acc.parts, br)
break
}
var chars [2]bool
broken := false
for i, elem := range br.elems[:2] {
val := braceWordLit(elem)
if _, err := strconv.Atoi(val); err == nil {
} else if len(val) == 1 &&
'a' <= val[0] && val[0] <= 'z' {
chars[i] = true
} else {
broken = true
}
}
if len(br.elems) == 3 {
// increment must be a number
val := braceWordLit(br.elems[2])
if _, err := strconv.Atoi(val); err != nil {
broken = true
}
}
// are start and end both chars or
// non-chars?
if chars[0] != chars[1] {
broken = true
}
if !broken {
br.chars = chars[0]
acc.parts = append(acc.parts, br)
break
}
// return broken {x..y[..incr]} to a non-brace
acc.parts = append(acc.parts, litLeftBrace)
acc.parts = append(acc.parts, ended.elems[0].parts...)
for i, elem := range br.elems {
if i > 0 {
acc.parts = append(acc.parts, litDots)
}
acc.parts = append(acc.parts, elem.parts...)
}
acc.parts = append(acc.parts, litRightBrace)
default:
continue
@ -233,11 +292,15 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
}
// open braces that were never closed fall back to non-braces
for acc != top {
ended := pop()
br := pop()
acc.parts = append(acc.parts, litLeftBrace)
for i, elem := range ended.elems {
for i, elem := range br.elems {
if i > 0 {
acc.parts = append(acc.parts, litComma)
if br.seq {
acc.parts = append(acc.parts, litDots)
} else {
acc.parts = append(acc.parts, litComma)
}
}
acc.parts = append(acc.parts, elem.parts...)
}
@ -245,6 +308,18 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
return top, any
}
func braceWordLit(v interface{}) string {
word, _ := v.(*braceWord)
if word == nil || len(word.parts) != 1 {
return ""
}
lit, ok := word.parts[0].(*syntax.Lit)
if !ok {
return ""
}
return lit.Value
}
func expandRec(bw *braceWord) []*syntax.Word {
var all []*syntax.Word
var left []syntax.WordPart
@ -254,6 +329,52 @@ func expandRec(bw *braceWord) []*syntax.Word {
left = append(left, wp.(syntax.WordPart))
continue
}
if br.seq {
var from, to int
if br.chars {
from = int(braceWordLit(br.elems[0])[0])
to = int(braceWordLit(br.elems[1])[0])
} else {
from = atoi(braceWordLit(br.elems[0]))
to = atoi(braceWordLit(br.elems[1]))
}
upward := from <= to
incr := 1
if !upward {
incr = -1
}
if len(br.elems) > 2 {
val := braceWordLit(br.elems[2])
if n := atoi(val); n != 0 && n > 0 == upward {
incr = n
}
}
n := from
for {
if upward && n > to {
break
}
if !upward && n < to {
break
}
next := *bw
next.parts = next.parts[i+1:]
lit := &syntax.Lit{}
if br.chars {
lit.Value = string(n)
} else {
lit.Value = strconv.Itoa(n)
}
next.parts = append([]braceWordPart{lit}, next.parts...)
exp := expandRec(&next)
for _, w := range exp {
w.Parts = append(left, w.Parts...)
}
all = append(all, exp...)
n += incr
}
return all
}
for _, elem := range br.elems {
next := *bw
next.parts = next.parts[i+1:]
@ -285,14 +406,14 @@ func (r *Runner) Fields(words ...*syntax.Word) []string {
for _, word := range words {
for _, expWord := range r.expandBraces(word) {
for _, field := range r.wordFields(expWord.Parts) {
path, glob := r.escapedGlobField(field)
path, doGlob := r.escapedGlobField(field)
var matches []string
abs := filepath.IsAbs(path)
if glob && !r.shellOpts[optNoGlob] {
if doGlob && !r.shellOpts[optNoGlob] {
if !abs {
path = filepath.Join(baseDir, path)
}
matches, _ = filepath.Glob(path)
matches = glob(path)
}
if len(matches) == 0 {
fields = append(fields, r.fieldJoin(field))
@ -553,3 +674,67 @@ func findAllIndex(pattern, name string, n int) [][]int {
rx := regexp.MustCompile(expr)
return rx.FindAllStringIndex(name, n)
}
func glob(pattern string) []string {
dir, file := filepath.Split(pattern)
// TODO: special case for windows, like in filepath.Glob?
dir = cleanGlobPath(dir)
expr, err := syntax.TranslatePattern(file, true)
if err != nil {
return nil
}
rx, err := regexp.Compile("^" + expr + "$")
if err != nil {
return nil
}
if !hasGlob(dir) {
return globDir(dir, rx, nil)
}
var matches []string
for _, d := range glob(dir) {
matches = globDir(d, rx, matches)
}
return matches
}
func cleanGlobPath(path string) string {
switch path {
case "":
return "."
case string(filepath.Separator):
return path
default:
return path[:len(path)-1]
}
}
func globDir(dir string, rx *regexp.Regexp, matches []string) []string {
d, err := os.Open(dir)
if err != nil {
return nil
}
defer d.Close()
names, _ := d.Readdirnames(-1)
sort.Strings(names)
for _, name := range names {
if !strings.HasPrefix(rx.String(), `^\.`) && name[0] == '.' {
continue
}
if rx.MatchString(name) {
matches = append(matches, filepath.Join(dir, name))
}
}
return matches
}
func hasGlob(path string) bool {
magicChars := `*?[`
if runtime.GOOS != "windows" {
magicChars = `*?[\`
}
return strings.ContainsAny(path, magicChars)
}

@ -85,27 +85,6 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
if index != nil {
str = r.varInd(vr, index, 0)
}
if pe.Length {
n := 1
if anyOfLit(index, "@", "*") != "" {
switch x := vr.Value.(type) {
case IndexArray:
n = len(x)
case AssocArray:
n = len(x)
}
} else {
n = utf8.RuneCountInString(str)
}
str = strconv.Itoa(n)
}
switch {
case pe.Excl:
if str != "" {
vr, set = r.lookupVar(str)
str = r.varStr(vr, 0)
}
}
slicePos := func(expr syntax.ArithmExpr) int {
p := r.arithm(expr)
if p < 0 {
@ -118,7 +97,30 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
}
return p
}
if pe.Slice != nil {
switch {
case pe.Length:
n := 1
if anyOfLit(index, "@", "*") != "" {
switch x := vr.Value.(type) {
case IndexArray:
n = len(x)
case AssocArray:
n = len(x)
}
} else {
n = utf8.RuneCountInString(str)
}
str = strconv.Itoa(n)
case pe.Excl:
if pe.Names != 0 {
str = strings.Join(r.namesByPrefix(pe.Param.Value), " ")
} else if vr.NameRef {
str = string(vr.Value.(StringVal))
} else if str != "" {
vr, _ = r.lookupVar(str)
str = r.varStr(vr, 0)
}
case pe.Slice != nil:
if pe.Slice.Offset != nil {
offset := slicePos(pe.Slice.Offset)
str = str[offset:]
@ -127,8 +129,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
length := slicePos(pe.Slice.Length)
str = str[:length]
}
}
if pe.Repl != nil {
case pe.Repl != nil:
orig := r.lonePattern(pe.Repl.Orig)
with := r.loneWord(pe.Repl.With)
n := 1
@ -145,8 +146,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
}
buf.WriteString(str[last:])
str = buf.String()
}
if pe.Exp != nil {
case pe.Exp != nil:
arg := r.loneWord(pe.Exp.Word)
switch pe.Exp.Op {
case syntax.SubstColPlus:

@ -1,79 +0,0 @@
// Copyright (c) 2018, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information
package interp
import (
"fmt"
"io"
"os"
"mvdan.cc/sh/syntax"
)
// SourceFile sources a shell file from disk and returns the variables
// declared in it.
//
// A default parser is used; to set custom options, use SourceNode
// instead.
func SourceFile(path string) (map[string]Variable, error) {
f, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("could not open: %v", err)
}
defer f.Close()
p := syntax.NewParser()
file, err := p.Parse(f, path)
if err != nil {
return nil, fmt.Errorf("could not parse: %v", err)
}
return SourceNode(file)
}
// purePrograms holds a list of common programs that do not have side
// effects, or otherwise cannot modify or harm the system that runs
// them.
var purePrograms = []string{
// string handling
"sed", "grep", "tr", "cut", "cat", "head", "tail", "seq", "yes",
"wc",
// paths
"ls", "pwd", "basename", "realpath",
// others
"env", "sleep", "uniq", "sort",
}
// SourceNode sources a shell program from a node and returns the
// variables declared in it.
//
// Any side effects or modifications to the system are forbidden when
// interpreting the program. This is enforced via whitelists when
// executing programs and opening paths.
func SourceNode(node syntax.Node) (map[string]Variable, error) {
r := Runner{}
// forbid executing programs that might cause trouble
r.Exec = func(ctx Ctxt, path string, args []string) error {
for _, name := range purePrograms {
if args[0] == name {
return DefaultExec(ctx, path, args)
}
}
return fmt.Errorf("program not in whitelist: %s", args[0])
}
// forbid opening any real files
r.Open = OpenDevImpls(func(ctx Ctxt, path string, flags int, mode os.FileMode) (io.ReadWriteCloser, error) {
return nil, fmt.Errorf("cannot open path: %s", ctx.UnixPath(path))
})
r.Reset()
if err := r.Run(node); err != nil {
return nil, fmt.Errorf("could not run: %v", err)
}
// delete the internal shell vars that the user is not
// interested in
delete(r.Vars, "PWD")
delete(r.Vars, "HOME")
delete(r.Vars, "PATH")
delete(r.Vars, "IFS")
delete(r.Vars, "OPTIND")
return r.Vars, nil
}

@ -258,8 +258,11 @@ func stringIndex(index syntax.ArithmExpr) bool {
if !ok || len(w.Parts) != 1 {
return false
}
_, ok = w.Parts[0].(*syntax.DblQuoted)
return ok
switch w.Parts[0].(type) {
case *syntax.DblQuoted, *syntax.SglQuoted:
return true
}
return false
}
func (r *Runner) assignVal(as *syntax.Assign, valType string) VarValue {
@ -358,3 +361,19 @@ func (r *Runner) ifsUpdated() {
return false
}
}
func (r *Runner) namesByPrefix(prefix string) []string {
var names []string
for name := range r.envMap {
if strings.HasPrefix(name, prefix) {
names = append(names, name)
}
}
for name := range r.Vars {
if strings.HasPrefix(name, prefix) {
names = append(names, name)
}
}
sort.Strings(names)
return names
}

@ -22,7 +22,7 @@ func regOps(r rune) bool {
func paramOps(r rune) bool {
switch r {
case '}', '#', '!', ':', '-', '+', '=', '?', '%', '[', ']', '/', '^',
',', '@':
',', '@', '*':
return true
}
return false
@ -216,6 +216,14 @@ skipSpace:
break skipSpace
}
}
if p.stopAt != nil && (p.spaced || p.tok == illegalTok || stopToken(p.tok)) {
w := utf8.RuneLen(r)
if bytes.HasPrefix(p.bs[p.bsp-w:], p.stopAt) {
p.r = utf8.RuneSelf
p.tok = _EOF
return
}
}
p.pos = p.getPos()
switch {
case p.quote&allRegTokens != 0:
@ -237,10 +245,9 @@ skipSpace:
p.litBs = nil
}
p.next()
case '[':
case '[', '=':
if p.quote == arrayElems {
p.tok = leftBrack
p.rune()
p.tok = p.paramToken(r)
} else {
p.advanceLitNone(r)
}
@ -351,7 +358,8 @@ func (p *Parser) regToken(r rune) token {
p.rune()
return dollBrace
case '[':
if p.lang != LangBash {
if p.lang != LangBash || p.quote == paramExpName {
// latter to not tokenise ${$[@]} as $[
break
}
p.rune()
@ -523,6 +531,9 @@ func (p *Parser) paramToken(r rune) token {
case '[':
p.rune()
return leftBrack
case ']':
p.rune()
return rightBrack
case '/':
if p.rune() == '/' && p.quote != paramExpRepl {
p.rune()
@ -541,9 +552,12 @@ func (p *Parser) paramToken(r rune) token {
return dblComma
}
return comma
default: // '@'
case '@':
p.rune()
return at
default: // '*'
p.rune()
return star
}
}
@ -738,12 +752,6 @@ loop:
if r = p.rune(); r == '\n' {
p.discardLit(2)
}
case '\n':
switch p.quote {
case sglQuotes, paramExpRepl, paramExpExp:
default:
break loop
}
case '\'':
switch p.quote {
case paramExpExp, paramExpRepl:
@ -764,14 +772,10 @@ loop:
break loop
}
case ']':
if p.quote&allRbrack != 0 {
if p.quote == arithmExprBrack {
break loop
}
case '!', '*':
if p.quote&allArithmExpr != 0 {
break loop
}
case ':', '=', '%', '^', ',', '?':
case ':', '=', '%', '^', ',', '?', '!', '*':
if p.quote&allArithmExpr != 0 || p.quote == paramExpName {
break loop
}
@ -782,13 +786,7 @@ loop:
if r == '[' && p.lang != LangPOSIX && p.quote&allArithmExpr != 0 {
break loop
}
case '+', '-':
switch p.quote {
case paramExpExp, paramExpRepl, sglQuotes:
default:
break loop
}
case ' ', '\t', ';', '&', '>', '<', '|', '(', ')', '\r':
case '+', '-', ' ', '\t', ';', '&', '>', '<', '|', '(', ')', '\n', '\r':
switch p.quote {
case paramExpExp, paramExpRepl, sglQuotes:
default:

@ -123,7 +123,7 @@ type Stmt struct {
Comments []Comment
Cmd Command
Position Pos
Semicolon Pos
Semicolon Pos // position of ';', '&', or '|&', if any
Negated bool // ! stmt
Background bool // stmt &
Coprocess bool // mksh's |&
@ -134,7 +134,11 @@ type Stmt struct {
func (s *Stmt) Pos() Pos { return s.Position }
func (s *Stmt) End() Pos {
if s.Semicolon.IsValid() {
return posAddCol(s.Semicolon, 1)
end := posAddCol(s.Semicolon, 1) // ';' or '&'
if s.Coprocess {
end = posAddCol(end, 1) // '|&'
}
return end
}
end := s.Position
if s.Negated {
@ -181,7 +185,7 @@ func (*CoprocClause) commandNode() {}
// Here and elsewhere, Index can either mean an index into an indexed or
// an associative array. In the former, it's just an arithmetic
// expression. In the latter, it will be a word with a single DblQuoted
// part.
// or SglQuoted part.
//
// If Index is non-nil, the value will be a word and not an array as
// nested arrays are not allowed.
@ -434,7 +438,7 @@ type SglQuoted struct {
}
func (q *SglQuoted) Pos() Pos { return q.Left }
func (q *SglQuoted) End() Pos { return q.Right }
func (q *SglQuoted) End() Pos { return posAddCol(q.Right, 1) }
// DblQuoted represents a list of nodes within double quotes.
type DblQuoted struct {
@ -474,10 +478,11 @@ type ParamExp struct {
Length bool // ${#a}
Width bool // ${%a}
Param *Lit
Index ArithmExpr // ${a[i]}, ${a["k"]}
Slice *Slice // ${a:x:y}
Repl *Replace // ${a/x/y}
Exp *Expansion // ${a:-b}, ${a#b}, etc
Index ArithmExpr // ${a[i]}, ${a["k"]}
Slice *Slice // ${a:x:y}
Repl *Replace // ${a/x/y}
Names ParNamesOperator // ${!prefix*} or ${!prefix@}
Exp *Expansion // ${a:-b}, ${a#b}, etc
}
func (p *ParamExp) Pos() Pos { return p.Dollar }

@ -8,6 +8,7 @@ import (
"fmt"
"io"
"strconv"
"strings"
"unicode/utf8"
)
@ -29,6 +30,29 @@ func Variant(l LangVariant) func(*Parser) {
return func(p *Parser) { p.lang = l }
}
// StopAt configures the lexer to stop at an arbitrary word, treating it
// as if it were the end of the input. It can contain any characters
// except whitespace, and cannot be over four bytes in size.
//
// This can be useful to embed shell code within another language, as
// one can use a special word to mark the delimiters between the two.
//
// As a word, it will only apply when following whitespace or a
// separating token. For example, StopAt("$$") will act on the inputs
// "foo $$" and "foo;$$", but not on "foo '$$'".
//
// The match is done by prefix, so the example above will also act on
// "foo $$bar".
func StopAt(word string) func(*Parser) {
if len(word) > 4 {
panic("stop word can't be over four bytes in size")
}
if strings.ContainsAny(word, " \t\n\r") {
panic("stop word can't contain whitespace characters")
}
return func(p *Parser) { p.stopAt = []byte(word) }
}
// NewParser allocates a new Parser and applies any number of options.
func NewParser(options ...func(*Parser)) *Parser {
p := &Parser{helperBuf: new(bytes.Buffer)}
@ -103,6 +127,8 @@ type Parser struct {
keepComments bool
lang LangVariant
stopAt []byte
forbidNested bool
// list of pending heredoc bodies
@ -233,7 +259,6 @@ const (
testRegexp
switchCase
paramExpName
paramExpInd
paramExpOff
paramExpLen
paramExpRepl
@ -246,10 +271,9 @@ const (
switchCase | arrayElems
allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd |
arithmExprBrack | allParamArith
allRbrack = arithmExprBrack | paramExpInd
allParamArith = paramExpInd | paramExpOff | paramExpLen
allParamArith = paramExpOff | paramExpLen
allParamReg = paramExpName | allParamArith
allParamExp = allParamReg | paramExpRepl | paramExpExp
allParamExp = allParamReg | paramExpRepl | paramExpExp | arithmExprBrack
)
type saveState struct {
@ -335,10 +359,16 @@ func (p *Parser) doHeredocs() {
p.quote = old
}
func (p *Parser) got(tok token) bool {
func (p *Parser) newLine() bool {
if p.tok == _Newl {
p.next()
return true
}
return false
}
func (p *Parser) got(tok token) bool {
p.newLine()
if p.tok == tok {
p.next()
return true
@ -347,9 +377,7 @@ func (p *Parser) got(tok token) bool {
}
func (p *Parser) gotRsrv(val string) (Pos, bool) {
if p.tok == _Newl {
p.next()
}
p.newLine()
pos := p.pos
if p.tok == _LitWord && p.val == val {
p.next()
@ -401,11 +429,7 @@ func (p *Parser) followStmts(left string, lpos Pos, stops ...string) StmtList {
if p.gotSameLine(semicolon) {
return StmtList{}
}
newLine := false
if p.tok == _Newl {
p.next()
newLine = true
}
newLine := p.newLine()
sl := p.stmtList(stops...)
if len(sl.Stmts) < 1 && !newLine {
p.followErr(lpos, left, "a statement list")
@ -494,11 +518,7 @@ func (p *Parser) stmts(fn func(*Stmt) bool, stops ...string) {
gotEnd := true
loop:
for p.tok != _EOF {
newLine := false
if p.tok == _Newl {
newLine = true
p.next()
}
newLine := p.newLine()
switch p.tok {
case _LitWord:
for _, stop := range stops {
@ -526,12 +546,12 @@ loop:
if p.tok == _EOF {
break
}
s, end := p.getStmt(true, false, false)
s := p.getStmt(true, false, false)
if s == nil {
p.invalidStmtStart()
break
}
gotEnd = end
gotEnd = s.Semicolon.IsValid() || s.Background || s.Coprocess
if !fn(s) {
break
}
@ -744,12 +764,11 @@ func (p *Parser) wordPart() WordPart {
p.quoteErr(sq.Pos(), sglQuote)
}
return sq
case dblQuote:
case dblQuote, dollDblQuote:
if p.quote == dblQuotes {
// p.tok == dblQuote, as "foo$" puts $ in the lit
return nil
}
fallthrough
case dollDblQuote:
if p.quote&allArithmExpr != 0 {
p.curErr("quotes should not be used in arithmetic expressions")
}
@ -866,9 +885,7 @@ func (p *Parser) arithmExpr(level int, compact, tern bool) ArithmExpr {
if compact && p.spaced {
return left
}
if p.tok == _Newl {
p.next()
}
p.newLine()
newLevel := arithmOpLevel(BinAritOperator(p.tok))
if !tern && p.tok == colon && p.quote&allParamArith != 0 {
newLevel = -1
@ -943,6 +960,7 @@ func isArithName(left ArithmExpr) bool {
}
func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
p.newLine()
var x ArithmExpr
switch p.tok {
case exclMark:
@ -982,17 +1000,8 @@ func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
x = p.word(p.wps(l))
break
}
left := p.pos
pe := &ParamExp{Dollar: l.ValuePos, Short: true, Param: l}
old := p.preNested(arithmExprBrack)
p.next()
if p.tok == dblQuote {
pe.Index = p.word(p.wps(p.dblQuoted()))
} else {
pe.Index = p.followArithm(leftBrack, left)
}
p.postNested(old)
p.matched(left, leftBrack, rightBrack)
pe.Index = p.eitherIndex()
x = p.word(p.wps(pe))
case bckQuote:
if p.quote == arithmExprLet {
@ -1061,6 +1070,9 @@ func (p *Parser) paramExp() *ParamExp {
}
case exclMark:
if paramNameOp(p.r) {
if p.lang == LangPOSIX {
p.curErr("${!foo} is a bash feature")
}
pe.Excl = true
p.next()
}
@ -1069,10 +1081,18 @@ func (p *Parser) paramExp() *ParamExp {
case _Lit, _LitWord:
pe.Param = p.lit(p.pos, p.val)
p.next()
case at, hash, exclMark:
case at, star, hash, exclMark:
pe.Param = p.lit(p.pos, p.tok.String())
p.next()
case dollar, quest, minus:
case quest, minus:
if pe.Length && p.r != '}' {
// actually ${#-default}, not ${#-}; error below
pe.Length = false
pe.Param = p.lit(p.pos, "#")
break
}
fallthrough
case dollar:
op := p.tok
pe.Param = p.lit(p.pos, p.tok.String())
p.next()
@ -1093,28 +1113,23 @@ func (p *Parser) paramExp() *ParamExp {
if p.lang == LangPOSIX {
p.curErr("arrays are a bash feature")
}
lpos := p.pos
p.quote = paramExpInd
p.next()
switch p.tok {
case star, at:
p.tok, p.val = _LitWord, p.tok.String()
if !ValidName(pe.Param.Value) {
p.curErr("cannot index a special parameter name")
}
if p.tok == dblQuote {
pe.Index = p.word(p.wps(p.dblQuoted()))
} else {
pe.Index = p.followArithm(leftBrack, lpos)
}
p.quote = paramExpName
p.matched(lpos, leftBrack, rightBrack)
pe.Index = p.eitherIndex()
}
switch p.tok {
case rightBrace:
if p.tok == rightBrace {
pe.Rbrace = p.pos
p.quote = old
p.next()
return pe
}
if p.tok != _EOF && (pe.Length || pe.Width) {
p.curErr("cannot combine multiple parameter expansion operators")
}
switch p.tok {
case slash, dblSlash:
// pattern search and replace
if p.lang == LangPOSIX {
p.curErr("search and replace is a bash feature")
}
@ -1127,6 +1142,7 @@ func (p *Parser) paramExp() *ParamExp {
pe.Repl.With = p.getWord()
}
case colon:
// slicing
if p.lang == LangPOSIX {
p.curErr("slicing is a bash feature")
}
@ -1142,32 +1158,35 @@ func (p *Parser) paramExp() *ParamExp {
pe.Slice.Length = p.followArithm(colon, colonPos)
}
case caret, dblCaret, comma, dblComma:
// upper/lower case
if p.lang != LangBash {
p.curErr("this expansion operator is a bash feature")
}
fallthrough
case at:
if p.lang == LangPOSIX {
pe.Exp = p.paramExpExp()
case at, star:
switch {
case p.tok == at && p.lang == LangPOSIX:
p.curErr("this expansion operator is a bash feature")
case p.tok == star && !pe.Excl:
p.curErr("not a valid parameter expansion operator: %v", p.tok)
case pe.Excl:
pe.Names = ParNamesOperator(p.tok)
p.next()
default:
pe.Exp = p.paramExpExp()
}
fallthrough
case plus, colPlus, minus, colMinus, quest, colQuest, assgn, colAssgn:
// if unset/null actions
if !ValidName(pe.Param.Value) {
p.curErr("a special parameter name can never be unset or null")
}
pe.Exp = p.paramExpExp()
case perc, dblPerc, hash, dblHash:
// pattern string manipulation
pe.Exp = p.paramExpExp()
case _EOF:
default:
pe.Exp = &Expansion{Op: ParExpOperator(p.tok)}
p.quote = paramExpExp
p.next()
if pe.Exp.Op == OtherParamOps {
switch p.tok {
case _Lit, _LitWord:
default:
p.curErr("@ expansion operator requires a literal")
}
switch p.val {
case "Q", "E", "P", "A", "a":
default:
p.curErr("invalid @ expansion operator")
}
}
pe.Exp.Word = p.getWord()
p.curErr("not a valid parameter expansion operator: %v", p.tok)
}
p.quote = old
pe.Rbrace = p.pos
@ -1175,6 +1194,49 @@ func (p *Parser) paramExp() *ParamExp {
return pe
}
func (p *Parser) paramExpExp() *Expansion {
op := ParExpOperator(p.tok)
p.quote = paramExpExp
p.next()
if op == OtherParamOps {
switch p.tok {
case _Lit, _LitWord:
default:
p.curErr("@ expansion operator requires a literal")
}
switch p.val {
case "Q", "E", "P", "A", "a":
default:
p.curErr("invalid @ expansion operator")
}
}
return &Expansion{Op: op, Word: p.getWord()}
}
func (p *Parser) eitherIndex() ArithmExpr {
old := p.quote
lpos := p.pos
p.quote = arithmExprBrack
p.next()
var expr ArithmExpr
switch p.tok {
case sglQuote, dollSglQuote, dblQuote, dollDblQuote:
// We can't use an arithm quote, as that will trigger
// the "quotes should not be used in arithmetic
// expressions" error. paramExpName is the closest.
p.quote = paramExpName
expr = p.word(p.wps(p.wordPart()))
case star, at:
p.tok, p.val = _LitWord, p.tok.String()
fallthrough
default:
expr = p.followArithm(leftBrack, lpos)
}
p.quote = old
p.matched(lpos, leftBrack, rightBrack)
return expr
}
func (p *Parser) peekArithmEnd() bool {
return p.tok == rightParen && p.r == ')'
}
@ -1251,19 +1313,8 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
as.Name = p.lit(p.pos, p.val)
// hasValidIdent already checks p.r is '['
p.rune()
left := posAddCol(p.pos, 1)
old := p.preNested(arithmExprBrack)
p.next()
if p.tok == star {
p.tok, p.val = _LitWord, p.tok.String()
}
if p.tok == dblQuote {
as.Index = p.word(p.wps(p.dblQuoted()))
} else {
as.Index = p.followArithm(leftBrack, left)
}
p.postNested(old)
p.matched(left, leftBrack, rightBrack)
p.pos = posAddCol(p.pos, 1)
as.Index = p.eitherIndex()
if !needEqual && (p.spaced || stopToken(p.tok)) {
return as
}
@ -1303,30 +1354,14 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
}
old := p.preNested(newQuote)
p.next()
if p.tok == _Newl {
p.next()
}
p.newLine()
for p.tok != _EOF && p.tok != rightParen {
ae := &ArrayElem{}
ae.Comments, p.accComs = p.accComs, nil
if p.tok == leftBrack {
left := p.pos
p.quote = arithmExprBrack
p.next()
if p.tok == dblQuote {
ae.Index = p.word(p.wps(p.dblQuoted()))
} else {
ae.Index = p.followArithm(leftBrack, left)
}
if p.tok != rightBrack {
p.matchingErr(left, leftBrack, rightBrack)
}
p.quote = arrayElems
if p.r != '=' {
p.followErr(left, `"[x]"`, "=")
}
p.rune()
p.next()
ae.Index = p.eitherIndex()
p.follow(left, `"[x]"`, assgn)
}
if ae.Value = p.getWord(); ae.Value == nil {
if p.tok == leftParen {
@ -1343,9 +1378,7 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
}
}
as.Array.Elems = append(as.Array.Elems, ae)
if p.tok == _Newl {
p.next()
}
p.newLine()
}
as.Array.Last, p.accComs = p.accComs, nil
p.postNested(old)
@ -1393,59 +1426,57 @@ func (p *Parser) doRedirect(s *Stmt) {
s.Redirs = append(s.Redirs, r)
}
func (p *Parser) getStmt(readEnd, binCmd, fnBody bool) (s *Stmt, gotEnd bool) {
func (p *Parser) getStmt(readEnd, binCmd, fnBody bool) *Stmt {
pos, ok := p.gotRsrv("!")
s = p.stmt(pos)
s := p.stmt(pos)
if ok {
s.Negated = true
if stopToken(p.tok) {
p.posErr(s.Pos(), `"!" cannot form a statement alone`)
}
if _, ok := p.gotRsrv("!"); ok {
p.posErr(s.Pos(), `cannot negate a command multiple times`)
}
}
if s = p.gotStmtPipe(s); s == nil || p.err != nil {
return
return nil
}
switch p.tok {
case andAnd, orOr:
// instead of using recursion, iterate manually
for p.tok == andAnd || p.tok == orOr {
// left associativity: in a list of BinaryCmds, the
// right recursion should only read a single element.
// right recursion should only read a single element
if binCmd {
return
return s
}
// and instead of using recursion, iterate manually
for p.tok == andAnd || p.tok == orOr {
b := &BinaryCmd{
OpPos: p.pos,
Op: BinCmdOperator(p.tok),
X: s,
}
p.next()
b.Y, _ = p.getStmt(false, true, false)
if b.Y == nil || p.err != nil {
p.followErr(b.OpPos, b.Op.String(), "a statement")
return
}
s = p.stmt(s.Position)
s.Cmd = b
s.Comments, b.X.Comments = b.X.Comments, nil
b := &BinaryCmd{
OpPos: p.pos,
Op: BinCmdOperator(p.tok),
X: s,
}
if p.tok != semicolon {
break
p.next()
b.Y = p.getStmt(false, true, false)
if b.Y == nil || p.err != nil {
p.followErr(b.OpPos, b.Op.String(), "a statement")
return nil
}
fallthrough
case semicolon:
if readEnd {
s = p.stmt(s.Position)
s.Cmd = b
s.Comments, b.X.Comments = b.X.Comments, nil
}
if readEnd {
switch p.tok {
case semicolon:
s.Semicolon = p.pos
p.next()
case and:
s.Semicolon = p.pos
p.next()
s.Background = true
case orAnd:
p.next()
s.Coprocess = true
}
case and:
p.next()
s.Background = true
case orAnd:
p.next()
s.Coprocess = true
}
gotEnd = s.Semicolon.IsValid() || s.Background || s.Coprocess
if len(p.accComs) > 0 && !binCmd && !fnBody {
c := p.accComs[0]
if c.Pos().Line() == s.End().Line() {
@ -1453,12 +1484,11 @@ func (p *Parser) getStmt(readEnd, binCmd, fnBody bool) (s *Stmt, gotEnd bool) {
p.accComs = p.accComs[1:]
}
}
return
return s
}
func (p *Parser) gotStmtPipe(s *Stmt) *Stmt {
if p.tok == _Newl {
p.next()
if p.newLine() {
s.Position = p.pos
}
s.Comments, p.accComs = p.accComs, nil
@ -1736,7 +1766,7 @@ func (p *Parser) wordIter(ftok string, fpos Pos) *WordIter {
}
}
p.gotSameLine(semicolon)
} else if p.tok != _Newl && !p.got(semicolon) {
} else if p.tok != _Newl && !p.gotSameLine(semicolon) {
p.followErr(fpos, ftok+" foo", `"in", ; or a newline`)
}
return wi
@ -1772,9 +1802,7 @@ func (p *Parser) caseClause() *CaseClause {
}
func (p *Parser) caseItems(stop string) (items []*CaseItem) {
if p.tok == _Newl {
p.next()
}
p.newLine()
for p.tok != _EOF && !(p.tok == _LitWord && p.val == stop) {
ci := &CaseItem{}
ci.Comments, p.accComs = p.accComs, nil
@ -1816,9 +1844,7 @@ func (p *Parser) caseItems(stop string) (items []*CaseItem) {
}
}
items = append(items, ci)
if p.tok == _Newl {
p.next()
}
p.newLine()
}
return
}
@ -1941,9 +1967,7 @@ func (p *Parser) testExprBase(ftok token, fpos Pos) TestExpr {
if ftok != illegalTok {
fstr = ftok.String()
}
if p.tok == _Newl {
p.next()
}
p.newLine()
return p.followWord(fstr, fpos)
}
}
@ -2057,8 +2081,7 @@ func (p *Parser) letClause() *LetClause {
func (p *Parser) bashFuncDecl() *FuncDecl {
fpos := p.pos
p.next()
if p.tok != _LitWord {
if p.next(); p.tok != _LitWord {
if w := p.followWord("function", fpos); p.err == nil {
p.posErr(w.Pos(), "invalid func name")
}
@ -2143,7 +2166,7 @@ func (p *Parser) funcDecl(name *Lit, pos Pos) *FuncDecl {
RsrvWord: pos != name.ValuePos,
Name: name,
}
if fd.Body, _ = p.getStmt(false, false, true); fd.Body == nil {
if fd.Body = p.getStmt(false, false, true); fd.Body == nil {
p.followErr(fd.Pos(), "foo()", "a statement")
}
return fd

@ -11,6 +11,9 @@ import (
)
func charClass(s string) (string, error) {
if strings.HasPrefix(s, "[[.") || strings.HasPrefix(s, "[[=") {
return "", fmt.Errorf("collating features not available")
}
if !strings.HasPrefix(s, "[[:") {
return "", nil
}
@ -32,9 +35,14 @@ func charClass(s string) (string, error) {
// TranslatePattern turns a shell pattern expression into a regular
// expression that can be used with regexp.Compile. It will return an
// error if the input pattern was incorrect. Otherwise, the returned
// expression is ensured to be valid syntax.
// expression can be passed to regexp.MustCompile.
//
// For example, TranslatePattern(`foo*bar?`, true) returns `foo.*bar.`.
//
// Note that this function (and QuotePattern) should not be directly
// used with file paths if Windows is supported, as the path separator
// on that platform is the same character as the escaping character for
// shell patterns.
func TranslatePattern(pattern string, greedy bool) (string, error) {
any := false
loop:
@ -62,9 +70,10 @@ loop:
case '?':
buf.WriteString(".")
case '\\':
buf.WriteByte(c)
i++
buf.WriteByte(pattern[i])
if i++; i >= len(pattern) {
return "", fmt.Errorf(`\ at end of pattern`)
}
buf.WriteString(regexp.QuoteMeta(string(pattern[i])))
case '[':
name, err := charClass(pattern[i:])
if err != nil {
@ -79,20 +88,32 @@ loop:
if i++; i >= len(pattern) {
return "", fmt.Errorf("[ was not matched with a closing ]")
}
c = pattern[i]
if c == '!' {
c = '^'
switch c = pattern[i]; c {
case '!', '^':
buf.WriteByte('^')
i++
c = pattern[i]
}
buf.WriteByte(c)
last := c
rangeStart := byte(0)
for {
if i++; i >= len(pattern) {
return "", fmt.Errorf("[ was not matched with a closing ]")
}
c = pattern[i]
last, c = c, pattern[i]
buf.WriteByte(c)
if c == ']' {
break
}
if rangeStart != 0 && rangeStart > c {
return "", fmt.Errorf("invalid range: %c-%c", rangeStart, c)
}
if c == '-' {
rangeStart = last
} else {
rangeStart = 0
}
}
default:
buf.WriteString(regexp.QuoteMeta(string(c)))

@ -474,6 +474,8 @@ func (p *Printer) paramExp(pe *ParamExp) {
if pe.Repl.With != nil {
p.word(pe.Repl.With)
}
} else if pe.Names != 0 {
p.WriteString(pe.Names.String())
} else if pe.Exp != nil {
p.WriteString(pe.Exp.Op.String())
if pe.Exp.Word != nil {

@ -202,6 +202,13 @@ const (
ResumeKorn
)
type ParNamesOperator token
const (
NamesPrefix = ParNamesOperator(star)
NamesPrefixWords = ParNamesOperator(at)
)
type ParExpOperator token
const (
@ -325,13 +332,14 @@ const (
TsAfter = BinTestOperator(rdrOut)
)
func (o RedirOperator) String() string { return token(o).String() }
func (o ProcOperator) String() string { return token(o).String() }
func (o GlobOperator) String() string { return token(o).String() }
func (o BinCmdOperator) String() string { return token(o).String() }
func (o CaseOperator) String() string { return token(o).String() }
func (o ParExpOperator) String() string { return token(o).String() }
func (o UnAritOperator) String() string { return token(o).String() }
func (o BinAritOperator) String() string { return token(o).String() }
func (o UnTestOperator) String() string { return token(o).String() }
func (o BinTestOperator) String() string { return token(o).String() }
func (o RedirOperator) String() string { return token(o).String() }
func (o ProcOperator) String() string { return token(o).String() }
func (o GlobOperator) String() string { return token(o).String() }
func (o BinCmdOperator) String() string { return token(o).String() }
func (o CaseOperator) String() string { return token(o).String() }
func (o ParNamesOperator) String() string { return token(o).String() }
func (o ParExpOperator) String() string { return token(o).String() }
func (o UnAritOperator) String() string { return token(o).String() }
func (o BinAritOperator) String() string { return token(o).String() }
func (o UnTestOperator) String() string { return token(o).String() }
func (o BinTestOperator) String() string { return token(o).String() }