1
0
mirror of https://github.com/go-task/task.git synced 2025-04-21 12:17:07 +02:00

Update dependencies

Fixes #86
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
View File

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

33
vendor/github.com/imdario/mergo/.gitignore generated vendored Normal file
View 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

View File

@ -1,2 +1,7 @@
language: go 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

View File

@ -2,17 +2,16 @@
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements. 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. Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region of Marche.
![Mergo dall'alto](http://www.comune.mergo.an.it/Siti/Mergo/Immagini/Foto/mergo_dall_alto.jpg)
## Status ## 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] [![Build Status][1]][2]
[![GoDoc][3]][4] [![GoDoc][3]][4]
[![GoCard][5]][6] [![GoCard][5]][6]
[![Coverage Status][7]][8]
[1]: https://travis-ci.org/imdario/mergo.png [1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo [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 [4]: https://godoc.org/github.com/imdario/mergo
[5]: https://goreportcard.com/badge/imdario/mergo [5]: https://goreportcard.com/badge/imdario/mergo
[6]: https://goreportcard.com/report/github.com/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 ### 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). 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 ### 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) - [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) - [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) - [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) - [EagerIO/Stout](https://github.com/EagerIO/Stout)
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api) - [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
- [russross/canvasassignments](https://github.com/russross/canvasassignments) - [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) - [thoas/picfit](https://github.com/thoas/picfit)
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server) - [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
- [jnuthong/item_search](https://github.com/jnuthong/item_search) - [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 ## 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 ```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 ```go
if err := mergo.Map(&dst, srcMap); err != nil { 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). More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo).
@ -111,13 +132,10 @@ func main() {
A: "one", A: "one",
B: 2, B: 2,
} }
dest := Foo{ dest := Foo{
A: "two", A: "two",
} }
mergo.Merge(&dest, src) mergo.Merge(&dest, src)
fmt.Println(dest) fmt.Println(dest)
// Will print // Will print
// {two 2} // {two 2}
@ -126,7 +144,55 @@ func main() {
Note: if test are failing due missing package, please execute: 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 ## Contact me

View File

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

View File

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

View File

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

View File

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

View File

@ -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 Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@ -59,7 +59,7 @@ func main() {
## Copyright ## 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. UUID package released under MIT License.
See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. 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
View 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
View 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
View 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)
}

View File

@ -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 // Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the // a copy of this software and associated documentation files (the
@ -26,23 +26,29 @@ package uuid
import ( import (
"bytes" "bytes"
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"database/sql/driver"
"encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" )
"hash"
"net" // Size of a UUID in bytes.
"os" const Size = 16
"sync"
"time" // 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. // UUID layout variants.
const ( const (
VariantNCS = iota VariantNCS byte = iota
VariantRFC4122 VariantRFC4122
VariantMicrosoft VariantMicrosoft
VariantFuture VariantFuture
@ -55,136 +61,48 @@ const (
DomainOrg 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. // String parse helpers.
var ( var (
urnPrefix = []byte("urn:uuid:") urnPrefix = []byte("urn:uuid:")
byteGroups = []int{8, 4, 4, 4, 12} byteGroups = []int{8, 4, 4, 4, 12}
) )
func initClockSequence() { // Nil is special form of UUID that is specified to have all
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
// 128 bits set to zero. // 128 bits set to zero.
var Nil = UUID{} var Nil = UUID{}
// Predefined namespace UUIDs. // Predefined namespace UUIDs.
var ( var (
NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8") NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8") NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NamespaceX500, _ = FromString("6ba7b814-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. // Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool { func Equal(u1 UUID, u2 UUID) bool {
return bytes.Equal(u1[:], u2[:]) return bytes.Equal(u1[:], u2[:])
} }
// Version returns algorithm version used to generate UUID. // Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint { func (u UUID) Version() byte {
return uint(u[6] >> 4) return u[6] >> 4
} }
// Variant returns UUID layout variant. // Variant returns UUID layout variant.
func (u UUID) Variant() uint { func (u UUID) Variant() byte {
switch { switch {
case (u[8] & 0x80) == 0x00: case (u[8] >> 7) == 0x00:
return VariantNCS return VariantNCS
case (u[8]&0xc0)|0x80 == 0x80: case (u[8] >> 6) == 0x02:
return VariantRFC4122 return VariantRFC4122
case (u[8]&0xe0)|0xc0 == 0xc0: case (u[8] >> 5) == 0x06:
return VariantMicrosoft return VariantMicrosoft
} case (u[8] >> 5) == 0x07:
fallthrough
default:
return VariantFuture return VariantFuture
}
} }
// Bytes returns bytes slice representation of UUID. // Bytes returns bytes slice representation of UUID.
@ -198,13 +116,13 @@ func (u UUID) String() string {
buf := make([]byte, 36) buf := make([]byte, 36)
hex.Encode(buf[0:8], u[0:4]) hex.Encode(buf[0:8], u[0:4])
buf[8] = dash buf[8] = '-'
hex.Encode(buf[9:13], u[4:6]) hex.Encode(buf[9:13], u[4:6])
buf[13] = dash buf[13] = '-'
hex.Encode(buf[14:18], u[6:8]) hex.Encode(buf[14:18], u[6:8])
buf[18] = dash buf[18] = '-'
hex.Encode(buf[19:23], u[8:10]) hex.Encode(buf[19:23], u[8:10])
buf[23] = dash buf[23] = '-'
hex.Encode(buf[24:], u[10:]) hex.Encode(buf[24:], u[10:])
return string(buf) return string(buf)
@ -215,274 +133,29 @@ func (u *UUID) SetVersion(v byte) {
u[6] = (u[6] & 0x0f) | (v << 4) u[6] = (u[6] & 0x0f) | (v << 4)
} }
// SetVariant sets variant bits as described in RFC 4122. // SetVariant sets variant bits.
func (u *UUID) SetVariant() { func (u *UUID) SetVariant(v byte) {
u[8] = (u[8] & 0xbf) | 0x80 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))
}
} }
// MarshalText implements the encoding.TextMarshaler interface. // Must is a helper that wraps a call to a function returning (UUID, error)
// The encoding is the same as returned by String. // and panics if the error is non-nil. It is intended for use in variable
func (u UUID) MarshalText() (text []byte, err error) { // initializations such as
text = []byte(u.String()) // var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
return func Must(u UUID, err error) UUID {
}
// 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
}
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 { if err != nil {
return panic(err)
} }
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)
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
}
// 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 return u
} }

View File

@ -16,6 +16,9 @@ import (
"hash" "hash"
"io" "io"
"io/ioutil" "io/ioutil"
"golang.org/x/crypto/internal/chacha20"
"golang.org/x/crypto/poly1305"
) )
const ( const (
@ -111,10 +114,10 @@ var cipherModes = map[string]*streamCipherMode{
// RFC4345 introduces improved versions of Arcfour. // RFC4345 introduces improved versions of Arcfour.
"arcfour": {16, 0, 0, newRC4}, "arcfour": {16, 0, 0, newRC4},
// AES-GCM is not a stream cipher, so it is constructed with a // AEAD ciphers are special cased. If we add any more non-stream
// special case. If we add any more non-stream ciphers, we // ciphers, we should create a cleaner way to do this.
// should invest a cleaner way to do this.
gcmCipherID: {16, 12, 0, nil}, gcmCipherID: {16, 12, 0, nil},
chacha20Poly1305ID: {64, 0, 0, nil},
// CBC mode is insecure and so is not included in the default config. // 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 // (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 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
}

View File

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

View File

@ -6,6 +6,7 @@ package ssh
import ( import (
"bufio" "bufio"
"bytes"
"errors" "errors"
"io" "io"
"log" "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) { func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
iv, key, macKey := generateKeys(d, algs, kex) 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) return newGCMCipher(iv, key)
} case aes128cbcID:
if algs.Cipher == aes128cbcID {
return newAESCBCCipher(iv, key, macKey, algs) return newAESCBCCipher(iv, key, macKey, algs)
} case tripledescbcID:
if algs.Cipher == tripledescbcID {
return newTripleDESCBCCipher(iv, key, macKey, algs) return newTripleDESCBCCipher(iv, key, macKey, algs)
} }
@ -342,7 +342,7 @@ func readVersion(r io.Reader) ([]byte, error) {
var ok bool var ok bool
var buf [1]byte var buf [1]byte
for len(versionString) < maxVersionStringBytes { for length := 0; length < maxVersionStringBytes; length++ {
_, err := io.ReadFull(r, buf[:]) _, err := io.ReadFull(r, buf[:])
if err != nil { if err != nil {
return nil, err 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 // The RFC says that the version should be terminated with \r\n
// but several SSH servers actually only send a \n. // but several SSH servers actually only send a \n.
if buf[0] == '\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 ok = true
break break
} }

124
vendor/golang.org/x/sys/unix/affinity_linux.go generated vendored Normal file
View 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)
}

View File

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

View File

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

View File

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

View File

@ -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)
}

View File

@ -11,9 +11,19 @@ import "syscall"
// We can't use the gc-syntax .s files for gccgo. On the plus side // 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. // 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 //extern gccgoRealSyscall
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr) 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) { func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
syscall.Entersyscall() syscall.Entersyscall()
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0) 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) 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) { 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) r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
return r, 0, syscall.Errno(errno) return r, 0, syscall.Errno(errno)

View File

@ -31,6 +31,12 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp
return r; 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. // Define the use function in C so that it is not inlined.
extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline)); extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));

View File

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

View File

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

View File

@ -1318,6 +1318,7 @@ func Setgid(uid int) (err error) {
//sys Setpriority(which int, who int, prio 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 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 Sync()
//sys Syncfs(fd int) (err error) //sys Syncfs(fd int) (err error)
//sysnb Sysinfo(info *Sysinfo_t) (err error) //sysnb Sysinfo(info *Sysinfo_t) (err error)
@ -1455,11 +1456,9 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
// RtSigtimedwait // RtSigtimedwait
// SchedGetPriorityMax // SchedGetPriorityMax
// SchedGetPriorityMin // SchedGetPriorityMin
// SchedGetaffinity
// SchedGetparam // SchedGetparam
// SchedGetscheduler // SchedGetscheduler
// SchedRrGetInterval // SchedRrGetInterval
// SchedSetaffinity
// SchedSetparam // SchedSetparam
// SchedYield // SchedYield
// Security // Security

View File

@ -1638,6 +1638,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1639,6 +1639,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1643,6 +1643,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1629,6 +1629,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1641,6 +1641,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1696,6 +1696,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1696,6 +1696,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -1700,6 +1700,27 @@ const (
SPLICE_F_MORE = 0x4 SPLICE_F_MORE = 0x4
SPLICE_F_MOVE = 0x1 SPLICE_F_MOVE = 0x1
SPLICE_F_NONBLOCK = 0x2 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_BLKSIZE = 0x200
S_IEXEC = 0x40 S_IEXEC = 0x40
S_IFBLK = 0x6000 S_IFBLK = 0x6000

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -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 // 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() { func Sync() {
SyscallNoError(SYS_SYNC, 0, 0, 0) SyscallNoError(SYS_SYNC, 0, 0, 0)
return return

View File

@ -131,6 +131,36 @@ type Statfs_t struct {
Spare [4]int32 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -643,9 +673,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -760,6 +796,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -792,3 +846,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

View File

@ -131,6 +131,36 @@ type Statfs_t struct {
Spare [4]int64 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -661,9 +691,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -778,6 +814,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -810,3 +864,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -133,6 +133,36 @@ type Statfs_t struct {
Pad_cgo_0 [4]byte 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -632,9 +662,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -749,6 +785,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -781,3 +835,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

View File

@ -132,6 +132,36 @@ type Statfs_t struct {
Spare [4]int64 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -640,9 +670,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -757,6 +793,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -789,3 +843,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -132,6 +132,36 @@ type Statfs_t struct {
Pad_cgo_1 [4]byte 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -637,9 +667,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -754,6 +790,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -786,3 +840,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

View File

@ -132,6 +132,36 @@ type Statfs_t struct {
Spare [5]int64 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -642,9 +672,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -759,6 +795,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -791,3 +845,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -132,6 +132,36 @@ type Statfs_t struct {
Spare [5]int64 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -642,9 +672,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -759,6 +795,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -791,3 +845,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -132,6 +132,36 @@ type Statfs_t struct {
Pad_cgo_1 [4]byte 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -637,9 +667,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -754,6 +790,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -786,3 +840,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint32
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x20
)

View File

@ -133,6 +133,36 @@ type Statfs_t struct {
Spare [4]int64 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -650,9 +680,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -767,6 +803,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -799,3 +853,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -133,6 +133,36 @@ type Statfs_t struct {
Spare [4]int64 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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -650,9 +680,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -767,6 +803,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -799,3 +853,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -132,6 +132,36 @@ type Statfs_t struct {
_ [4]byte _ [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 { type Dirent struct {
Ino uint64 Ino uint64
Off int64 Off int64
@ -667,9 +697,15 @@ type EpollEvent struct {
} }
const ( const (
AT_EMPTY_PATH = 0x1000
AT_FDCWD = -0x64 AT_FDCWD = -0x64
AT_NO_AUTOMOUNT = 0x800 AT_NO_AUTOMOUNT = 0x800
AT_REMOVEDIR = 0x200 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_FOLLOW = 0x400
AT_SYMLINK_NOFOLLOW = 0x100 AT_SYMLINK_NOFOLLOW = 0x100
) )
@ -784,6 +820,24 @@ const (
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK = 0x4 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 { type Genlmsghdr struct {
Cmd uint8 Cmd uint8
Version uint8 Version uint8
@ -816,3 +870,10 @@ const (
CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_NAME = 0x1
CTRL_ATTR_MCAST_GRP_ID = 0x2 CTRL_ATTR_MCAST_GRP_ID = 0x2
) )
type cpuMask uint64
const (
_CPU_SETSIZE = 0x400
_NCPUBITS = 0x40
)

View File

@ -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)
}

View File

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

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

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

View File

@ -5,9 +5,12 @@ package interp
import ( import (
"fmt" "fmt"
"os"
"os/user" "os/user"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime"
"sort"
"strconv" "strconv"
"strings" "strings"
@ -133,9 +136,11 @@ func (r *Runner) escapedGlobField(parts []fieldPart) (escaped string, glob bool)
return escaped, glob return escaped, glob
} }
// TODO: consider making brace a special syntax Node // TODO: consider making these special syntax nodes
type brace struct { type brace struct {
seq bool // {x..y[..incr]} instead of {x,y[,...]}
chars bool // sequence is of chars, not numbers
elems []*braceWord elems []*braceWord
} }
@ -144,12 +149,13 @@ type braceWord struct {
parts []braceWordPart parts []braceWordPart
} }
// braceWordPart contains either syntax.WordPart or brace. // braceWordPart contains any syntax.WordPart or a brace.
type braceWordPart interface{} type braceWordPart interface{}
var ( var (
litLeftBrace = &syntax.Lit{Value: "{"} litLeftBrace = &syntax.Lit{Value: "{"}
litComma = &syntax.Lit{Value: ","} litComma = &syntax.Lit{Value: ","}
litDots = &syntax.Lit{Value: ".."}
litRightBrace = &syntax.Lit{Value: "}"} litRightBrace = &syntax.Lit{Value: "}"}
) )
@ -181,7 +187,7 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
continue continue
} }
last := 0 last := 0
for j, r := range lit.Value { for j := 0; j < len(lit.Value); j++ {
addlit := func() { addlit := func() {
if last == j { if last == j {
return // empty lit return // empty lit
@ -190,7 +196,7 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
l2.Value = l2.Value[last:j] l2.Value = l2.Value[last:j]
acc.parts = append(acc.parts, &l2) acc.parts = append(acc.parts, &l2)
} }
switch r { switch lit.Value[j] {
case '{': case '{':
addlit() addlit()
acc = &braceWord{} acc = &braceWord{}
@ -203,20 +209,73 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
addlit() addlit()
acc = &braceWord{} acc = &braceWord{}
cur.elems = append(cur.elems, acc) 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 '}': case '}':
if cur == nil { if cur == nil {
continue continue
} }
any = true any = true
addlit() addlit()
ended := pop() br := pop()
if len(ended.elems) > 1 { if len(br.elems) == 1 {
acc.parts = append(acc.parts, ended)
break
}
// return {x} to a non-brace // return {x} to a non-brace
acc.parts = append(acc.parts, litLeftBrace) acc.parts = append(acc.parts, litLeftBrace)
acc.parts = append(acc.parts, ended.elems[0].parts...) acc.parts = append(acc.parts, br.elems[0].parts...)
acc.parts = append(acc.parts, litRightBrace)
break
}
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)
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) acc.parts = append(acc.parts, litRightBrace)
default: default:
continue continue
@ -233,18 +292,34 @@ func (r *Runner) splitBraces(word *syntax.Word) (*braceWord, bool) {
} }
// open braces that were never closed fall back to non-braces // open braces that were never closed fall back to non-braces
for acc != top { for acc != top {
ended := pop() br := pop()
acc.parts = append(acc.parts, litLeftBrace) acc.parts = append(acc.parts, litLeftBrace)
for i, elem := range ended.elems { for i, elem := range br.elems {
if i > 0 { if i > 0 {
if br.seq {
acc.parts = append(acc.parts, litDots)
} else {
acc.parts = append(acc.parts, litComma) acc.parts = append(acc.parts, litComma)
} }
}
acc.parts = append(acc.parts, elem.parts...) acc.parts = append(acc.parts, elem.parts...)
} }
} }
return top, any 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 { func expandRec(bw *braceWord) []*syntax.Word {
var all []*syntax.Word var all []*syntax.Word
var left []syntax.WordPart var left []syntax.WordPart
@ -254,6 +329,52 @@ func expandRec(bw *braceWord) []*syntax.Word {
left = append(left, wp.(syntax.WordPart)) left = append(left, wp.(syntax.WordPart))
continue 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 { for _, elem := range br.elems {
next := *bw next := *bw
next.parts = next.parts[i+1:] next.parts = next.parts[i+1:]
@ -285,14 +406,14 @@ func (r *Runner) Fields(words ...*syntax.Word) []string {
for _, word := range words { for _, word := range words {
for _, expWord := range r.expandBraces(word) { for _, expWord := range r.expandBraces(word) {
for _, field := range r.wordFields(expWord.Parts) { for _, field := range r.wordFields(expWord.Parts) {
path, glob := r.escapedGlobField(field) path, doGlob := r.escapedGlobField(field)
var matches []string var matches []string
abs := filepath.IsAbs(path) abs := filepath.IsAbs(path)
if glob && !r.shellOpts[optNoGlob] { if doGlob && !r.shellOpts[optNoGlob] {
if !abs { if !abs {
path = filepath.Join(baseDir, path) path = filepath.Join(baseDir, path)
} }
matches, _ = filepath.Glob(path) matches = glob(path)
} }
if len(matches) == 0 { if len(matches) == 0 {
fields = append(fields, r.fieldJoin(field)) fields = append(fields, r.fieldJoin(field))
@ -553,3 +674,67 @@ func findAllIndex(pattern, name string, n int) [][]int {
rx := regexp.MustCompile(expr) rx := regexp.MustCompile(expr)
return rx.FindAllStringIndex(name, n) 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)
}

View File

@ -85,27 +85,6 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
if index != nil { if index != nil {
str = r.varInd(vr, index, 0) 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 { slicePos := func(expr syntax.ArithmExpr) int {
p := r.arithm(expr) p := r.arithm(expr)
if p < 0 { if p < 0 {
@ -118,7 +97,30 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
} }
return p 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 { if pe.Slice.Offset != nil {
offset := slicePos(pe.Slice.Offset) offset := slicePos(pe.Slice.Offset)
str = str[offset:] str = str[offset:]
@ -127,8 +129,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
length := slicePos(pe.Slice.Length) length := slicePos(pe.Slice.Length)
str = str[:length] str = str[:length]
} }
} case pe.Repl != nil:
if pe.Repl != nil {
orig := r.lonePattern(pe.Repl.Orig) orig := r.lonePattern(pe.Repl.Orig)
with := r.loneWord(pe.Repl.With) with := r.loneWord(pe.Repl.With)
n := 1 n := 1
@ -145,8 +146,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
} }
buf.WriteString(str[last:]) buf.WriteString(str[last:])
str = buf.String() str = buf.String()
} case pe.Exp != nil:
if pe.Exp != nil {
arg := r.loneWord(pe.Exp.Word) arg := r.loneWord(pe.Exp.Word)
switch pe.Exp.Op { switch pe.Exp.Op {
case syntax.SubstColPlus: case syntax.SubstColPlus:

View File

@ -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
}

View File

@ -258,8 +258,11 @@ func stringIndex(index syntax.ArithmExpr) bool {
if !ok || len(w.Parts) != 1 { if !ok || len(w.Parts) != 1 {
return false return false
} }
_, ok = w.Parts[0].(*syntax.DblQuoted) switch w.Parts[0].(type) {
return ok case *syntax.DblQuoted, *syntax.SglQuoted:
return true
}
return false
} }
func (r *Runner) assignVal(as *syntax.Assign, valType string) VarValue { func (r *Runner) assignVal(as *syntax.Assign, valType string) VarValue {
@ -358,3 +361,19 @@ func (r *Runner) ifsUpdated() {
return false 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
}

View File

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

View File

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

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"io" "io"
"strconv" "strconv"
"strings"
"unicode/utf8" "unicode/utf8"
) )
@ -29,6 +30,29 @@ func Variant(l LangVariant) func(*Parser) {
return func(p *Parser) { p.lang = l } 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. // NewParser allocates a new Parser and applies any number of options.
func NewParser(options ...func(*Parser)) *Parser { func NewParser(options ...func(*Parser)) *Parser {
p := &Parser{helperBuf: new(bytes.Buffer)} p := &Parser{helperBuf: new(bytes.Buffer)}
@ -103,6 +127,8 @@ type Parser struct {
keepComments bool keepComments bool
lang LangVariant lang LangVariant
stopAt []byte
forbidNested bool forbidNested bool
// list of pending heredoc bodies // list of pending heredoc bodies
@ -233,7 +259,6 @@ const (
testRegexp testRegexp
switchCase switchCase
paramExpName paramExpName
paramExpInd
paramExpOff paramExpOff
paramExpLen paramExpLen
paramExpRepl paramExpRepl
@ -246,10 +271,9 @@ const (
switchCase | arrayElems switchCase | arrayElems
allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd | allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd |
arithmExprBrack | allParamArith arithmExprBrack | allParamArith
allRbrack = arithmExprBrack | paramExpInd allParamArith = paramExpOff | paramExpLen
allParamArith = paramExpInd | paramExpOff | paramExpLen
allParamReg = paramExpName | allParamArith allParamReg = paramExpName | allParamArith
allParamExp = allParamReg | paramExpRepl | paramExpExp allParamExp = allParamReg | paramExpRepl | paramExpExp | arithmExprBrack
) )
type saveState struct { type saveState struct {
@ -335,10 +359,16 @@ func (p *Parser) doHeredocs() {
p.quote = old p.quote = old
} }
func (p *Parser) got(tok token) bool { func (p *Parser) newLine() bool {
if p.tok == _Newl { if p.tok == _Newl {
p.next() p.next()
return true
} }
return false
}
func (p *Parser) got(tok token) bool {
p.newLine()
if p.tok == tok { if p.tok == tok {
p.next() p.next()
return true return true
@ -347,9 +377,7 @@ func (p *Parser) got(tok token) bool {
} }
func (p *Parser) gotRsrv(val string) (Pos, bool) { func (p *Parser) gotRsrv(val string) (Pos, bool) {
if p.tok == _Newl { p.newLine()
p.next()
}
pos := p.pos pos := p.pos
if p.tok == _LitWord && p.val == val { if p.tok == _LitWord && p.val == val {
p.next() p.next()
@ -401,11 +429,7 @@ func (p *Parser) followStmts(left string, lpos Pos, stops ...string) StmtList {
if p.gotSameLine(semicolon) { if p.gotSameLine(semicolon) {
return StmtList{} return StmtList{}
} }
newLine := false newLine := p.newLine()
if p.tok == _Newl {
p.next()
newLine = true
}
sl := p.stmtList(stops...) sl := p.stmtList(stops...)
if len(sl.Stmts) < 1 && !newLine { if len(sl.Stmts) < 1 && !newLine {
p.followErr(lpos, left, "a statement list") p.followErr(lpos, left, "a statement list")
@ -494,11 +518,7 @@ func (p *Parser) stmts(fn func(*Stmt) bool, stops ...string) {
gotEnd := true gotEnd := true
loop: loop:
for p.tok != _EOF { for p.tok != _EOF {
newLine := false newLine := p.newLine()
if p.tok == _Newl {
newLine = true
p.next()
}
switch p.tok { switch p.tok {
case _LitWord: case _LitWord:
for _, stop := range stops { for _, stop := range stops {
@ -526,12 +546,12 @@ loop:
if p.tok == _EOF { if p.tok == _EOF {
break break
} }
s, end := p.getStmt(true, false, false) s := p.getStmt(true, false, false)
if s == nil { if s == nil {
p.invalidStmtStart() p.invalidStmtStart()
break break
} }
gotEnd = end gotEnd = s.Semicolon.IsValid() || s.Background || s.Coprocess
if !fn(s) { if !fn(s) {
break break
} }
@ -744,12 +764,11 @@ func (p *Parser) wordPart() WordPart {
p.quoteErr(sq.Pos(), sglQuote) p.quoteErr(sq.Pos(), sglQuote)
} }
return sq return sq
case dblQuote: case dblQuote, dollDblQuote:
if p.quote == dblQuotes { if p.quote == dblQuotes {
// p.tok == dblQuote, as "foo$" puts $ in the lit
return nil return nil
} }
fallthrough
case dollDblQuote:
if p.quote&allArithmExpr != 0 { if p.quote&allArithmExpr != 0 {
p.curErr("quotes should not be used in arithmetic expressions") 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 { if compact && p.spaced {
return left return left
} }
if p.tok == _Newl { p.newLine()
p.next()
}
newLevel := arithmOpLevel(BinAritOperator(p.tok)) newLevel := arithmOpLevel(BinAritOperator(p.tok))
if !tern && p.tok == colon && p.quote&allParamArith != 0 { if !tern && p.tok == colon && p.quote&allParamArith != 0 {
newLevel = -1 newLevel = -1
@ -943,6 +960,7 @@ func isArithName(left ArithmExpr) bool {
} }
func (p *Parser) arithmExprBase(compact bool) ArithmExpr { func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
p.newLine()
var x ArithmExpr var x ArithmExpr
switch p.tok { switch p.tok {
case exclMark: case exclMark:
@ -982,17 +1000,8 @@ func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
x = p.word(p.wps(l)) x = p.word(p.wps(l))
break break
} }
left := p.pos
pe := &ParamExp{Dollar: l.ValuePos, Short: true, Param: l} pe := &ParamExp{Dollar: l.ValuePos, Short: true, Param: l}
old := p.preNested(arithmExprBrack) pe.Index = p.eitherIndex()
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)
x = p.word(p.wps(pe)) x = p.word(p.wps(pe))
case bckQuote: case bckQuote:
if p.quote == arithmExprLet { if p.quote == arithmExprLet {
@ -1061,6 +1070,9 @@ func (p *Parser) paramExp() *ParamExp {
} }
case exclMark: case exclMark:
if paramNameOp(p.r) { if paramNameOp(p.r) {
if p.lang == LangPOSIX {
p.curErr("${!foo} is a bash feature")
}
pe.Excl = true pe.Excl = true
p.next() p.next()
} }
@ -1069,10 +1081,18 @@ func (p *Parser) paramExp() *ParamExp {
case _Lit, _LitWord: case _Lit, _LitWord:
pe.Param = p.lit(p.pos, p.val) pe.Param = p.lit(p.pos, p.val)
p.next() p.next()
case at, hash, exclMark: case at, star, hash, exclMark:
pe.Param = p.lit(p.pos, p.tok.String()) pe.Param = p.lit(p.pos, p.tok.String())
p.next() 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 op := p.tok
pe.Param = p.lit(p.pos, p.tok.String()) pe.Param = p.lit(p.pos, p.tok.String())
p.next() p.next()
@ -1093,28 +1113,23 @@ func (p *Parser) paramExp() *ParamExp {
if p.lang == LangPOSIX { if p.lang == LangPOSIX {
p.curErr("arrays are a bash feature") p.curErr("arrays are a bash feature")
} }
lpos := p.pos if !ValidName(pe.Param.Value) {
p.quote = paramExpInd p.curErr("cannot index a special parameter name")
p.next()
switch p.tok {
case star, at:
p.tok, p.val = _LitWord, p.tok.String()
} }
if p.tok == dblQuote { pe.Index = p.eitherIndex()
pe.Index = p.word(p.wps(p.dblQuoted()))
} else {
pe.Index = p.followArithm(leftBrack, lpos)
} }
p.quote = paramExpName if p.tok == rightBrace {
p.matched(lpos, leftBrack, rightBrack)
}
switch p.tok {
case rightBrace:
pe.Rbrace = p.pos pe.Rbrace = p.pos
p.quote = old p.quote = old
p.next() p.next()
return pe return pe
}
if p.tok != _EOF && (pe.Length || pe.Width) {
p.curErr("cannot combine multiple parameter expansion operators")
}
switch p.tok {
case slash, dblSlash: case slash, dblSlash:
// pattern search and replace
if p.lang == LangPOSIX { if p.lang == LangPOSIX {
p.curErr("search and replace is a bash feature") p.curErr("search and replace is a bash feature")
} }
@ -1127,6 +1142,7 @@ func (p *Parser) paramExp() *ParamExp {
pe.Repl.With = p.getWord() pe.Repl.With = p.getWord()
} }
case colon: case colon:
// slicing
if p.lang == LangPOSIX { if p.lang == LangPOSIX {
p.curErr("slicing is a bash feature") p.curErr("slicing is a bash feature")
} }
@ -1142,20 +1158,47 @@ func (p *Parser) paramExp() *ParamExp {
pe.Slice.Length = p.followArithm(colon, colonPos) pe.Slice.Length = p.followArithm(colon, colonPos)
} }
case caret, dblCaret, comma, dblComma: case caret, dblCaret, comma, dblComma:
// upper/lower case
if p.lang != LangBash { if p.lang != LangBash {
p.curErr("this expansion operator is a bash feature") p.curErr("this expansion operator is a bash feature")
} }
fallthrough pe.Exp = p.paramExpExp()
case at: case at, star:
if p.lang == LangPOSIX { switch {
case p.tok == at && p.lang == LangPOSIX:
p.curErr("this expansion operator is a bash feature") p.curErr("this expansion operator is a bash feature")
} case p.tok == star && !pe.Excl:
fallthrough p.curErr("not a valid parameter expansion operator: %v", p.tok)
case pe.Excl:
pe.Names = ParNamesOperator(p.tok)
p.next()
default: default:
pe.Exp = &Expansion{Op: ParExpOperator(p.tok)} pe.Exp = p.paramExpExp()
}
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:
p.curErr("not a valid parameter expansion operator: %v", p.tok)
}
p.quote = old
pe.Rbrace = p.pos
p.matched(pe.Dollar, dollBrace, rightBrace)
return pe
}
func (p *Parser) paramExpExp() *Expansion {
op := ParExpOperator(p.tok)
p.quote = paramExpExp p.quote = paramExpExp
p.next() p.next()
if pe.Exp.Op == OtherParamOps { if op == OtherParamOps {
switch p.tok { switch p.tok {
case _Lit, _LitWord: case _Lit, _LitWord:
default: default:
@ -1167,12 +1210,31 @@ func (p *Parser) paramExp() *ParamExp {
p.curErr("invalid @ expansion operator") p.curErr("invalid @ expansion operator")
} }
} }
pe.Exp.Word = p.getWord() 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.quote = old
pe.Rbrace = p.pos p.matched(lpos, leftBrack, rightBrack)
p.matched(pe.Dollar, dollBrace, rightBrace) return expr
return pe
} }
func (p *Parser) peekArithmEnd() bool { func (p *Parser) peekArithmEnd() bool {
@ -1251,19 +1313,8 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
as.Name = p.lit(p.pos, p.val) as.Name = p.lit(p.pos, p.val)
// hasValidIdent already checks p.r is '[' // hasValidIdent already checks p.r is '['
p.rune() p.rune()
left := posAddCol(p.pos, 1) p.pos = posAddCol(p.pos, 1)
old := p.preNested(arithmExprBrack) as.Index = p.eitherIndex()
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)
if !needEqual && (p.spaced || stopToken(p.tok)) { if !needEqual && (p.spaced || stopToken(p.tok)) {
return as return as
} }
@ -1303,30 +1354,14 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
} }
old := p.preNested(newQuote) old := p.preNested(newQuote)
p.next() p.next()
if p.tok == _Newl { p.newLine()
p.next()
}
for p.tok != _EOF && p.tok != rightParen { for p.tok != _EOF && p.tok != rightParen {
ae := &ArrayElem{} ae := &ArrayElem{}
ae.Comments, p.accComs = p.accComs, nil ae.Comments, p.accComs = p.accComs, nil
if p.tok == leftBrack { if p.tok == leftBrack {
left := p.pos left := p.pos
p.quote = arithmExprBrack ae.Index = p.eitherIndex()
p.next() p.follow(left, `"[x]"`, assgn)
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()
} }
if ae.Value = p.getWord(); ae.Value == nil { if ae.Value = p.getWord(); ae.Value == nil {
if p.tok == leftParen { if p.tok == leftParen {
@ -1343,9 +1378,7 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
} }
} }
as.Array.Elems = append(as.Array.Elems, ae) as.Array.Elems = append(as.Array.Elems, ae)
if p.tok == _Newl { p.newLine()
p.next()
}
} }
as.Array.Last, p.accComs = p.accComs, nil as.Array.Last, p.accComs = p.accComs, nil
p.postNested(old) p.postNested(old)
@ -1393,59 +1426,57 @@ func (p *Parser) doRedirect(s *Stmt) {
s.Redirs = append(s.Redirs, r) 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("!") pos, ok := p.gotRsrv("!")
s = p.stmt(pos) s := p.stmt(pos)
if ok { if ok {
s.Negated = true s.Negated = true
if stopToken(p.tok) { if stopToken(p.tok) {
p.posErr(s.Pos(), `"!" cannot form a statement alone`) 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 { if s = p.gotStmtPipe(s); s == nil || p.err != nil {
return return nil
} }
switch p.tok { // instead of using recursion, iterate manually
case andAnd, orOr:
// left associativity: in a list of BinaryCmds, the
// right recursion should only read a single element.
if binCmd {
return
}
// and instead of using recursion, iterate manually
for p.tok == andAnd || p.tok == orOr { for p.tok == andAnd || p.tok == orOr {
// left associativity: in a list of BinaryCmds, the
// right recursion should only read a single element
if binCmd {
return s
}
b := &BinaryCmd{ b := &BinaryCmd{
OpPos: p.pos, OpPos: p.pos,
Op: BinCmdOperator(p.tok), Op: BinCmdOperator(p.tok),
X: s, X: s,
} }
p.next() p.next()
b.Y, _ = p.getStmt(false, true, false) b.Y = p.getStmt(false, true, false)
if b.Y == nil || p.err != nil { if b.Y == nil || p.err != nil {
p.followErr(b.OpPos, b.Op.String(), "a statement") p.followErr(b.OpPos, b.Op.String(), "a statement")
return return nil
} }
s = p.stmt(s.Position) s = p.stmt(s.Position)
s.Cmd = b s.Cmd = b
s.Comments, b.X.Comments = b.X.Comments, nil s.Comments, b.X.Comments = b.X.Comments, nil
} }
if p.tok != semicolon {
break
}
fallthrough
case semicolon:
if readEnd { if readEnd {
switch p.tok {
case semicolon:
s.Semicolon = p.pos s.Semicolon = p.pos
p.next() p.next()
}
case and: case and:
s.Semicolon = p.pos
p.next() p.next()
s.Background = true s.Background = true
case orAnd: case orAnd:
p.next() p.next()
s.Coprocess = true s.Coprocess = true
} }
gotEnd = s.Semicolon.IsValid() || s.Background || s.Coprocess }
if len(p.accComs) > 0 && !binCmd && !fnBody { if len(p.accComs) > 0 && !binCmd && !fnBody {
c := p.accComs[0] c := p.accComs[0]
if c.Pos().Line() == s.End().Line() { 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:] p.accComs = p.accComs[1:]
} }
} }
return return s
} }
func (p *Parser) gotStmtPipe(s *Stmt) *Stmt { func (p *Parser) gotStmtPipe(s *Stmt) *Stmt {
if p.tok == _Newl { if p.newLine() {
p.next()
s.Position = p.pos s.Position = p.pos
} }
s.Comments, p.accComs = p.accComs, nil s.Comments, p.accComs = p.accComs, nil
@ -1736,7 +1766,7 @@ func (p *Parser) wordIter(ftok string, fpos Pos) *WordIter {
} }
} }
p.gotSameLine(semicolon) 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`) p.followErr(fpos, ftok+" foo", `"in", ; or a newline`)
} }
return wi return wi
@ -1772,9 +1802,7 @@ func (p *Parser) caseClause() *CaseClause {
} }
func (p *Parser) caseItems(stop string) (items []*CaseItem) { func (p *Parser) caseItems(stop string) (items []*CaseItem) {
if p.tok == _Newl { p.newLine()
p.next()
}
for p.tok != _EOF && !(p.tok == _LitWord && p.val == stop) { for p.tok != _EOF && !(p.tok == _LitWord && p.val == stop) {
ci := &CaseItem{} ci := &CaseItem{}
ci.Comments, p.accComs = p.accComs, nil ci.Comments, p.accComs = p.accComs, nil
@ -1816,9 +1844,7 @@ func (p *Parser) caseItems(stop string) (items []*CaseItem) {
} }
} }
items = append(items, ci) items = append(items, ci)
if p.tok == _Newl { p.newLine()
p.next()
}
} }
return return
} }
@ -1941,9 +1967,7 @@ func (p *Parser) testExprBase(ftok token, fpos Pos) TestExpr {
if ftok != illegalTok { if ftok != illegalTok {
fstr = ftok.String() fstr = ftok.String()
} }
if p.tok == _Newl { p.newLine()
p.next()
}
return p.followWord(fstr, fpos) return p.followWord(fstr, fpos)
} }
} }
@ -2057,8 +2081,7 @@ func (p *Parser) letClause() *LetClause {
func (p *Parser) bashFuncDecl() *FuncDecl { func (p *Parser) bashFuncDecl() *FuncDecl {
fpos := p.pos fpos := p.pos
p.next() if p.next(); p.tok != _LitWord {
if p.tok != _LitWord {
if w := p.followWord("function", fpos); p.err == nil { if w := p.followWord("function", fpos); p.err == nil {
p.posErr(w.Pos(), "invalid func name") p.posErr(w.Pos(), "invalid func name")
} }
@ -2143,7 +2166,7 @@ func (p *Parser) funcDecl(name *Lit, pos Pos) *FuncDecl {
RsrvWord: pos != name.ValuePos, RsrvWord: pos != name.ValuePos,
Name: name, 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") p.followErr(fd.Pos(), "foo()", "a statement")
} }
return fd return fd

View File

@ -11,6 +11,9 @@ import (
) )
func charClass(s string) (string, error) { func charClass(s string) (string, error) {
if strings.HasPrefix(s, "[[.") || strings.HasPrefix(s, "[[=") {
return "", fmt.Errorf("collating features not available")
}
if !strings.HasPrefix(s, "[[:") { if !strings.HasPrefix(s, "[[:") {
return "", nil return "", nil
} }
@ -32,9 +35,14 @@ func charClass(s string) (string, error) {
// TranslatePattern turns a shell pattern expression into a regular // TranslatePattern turns a shell pattern expression into a regular
// expression that can be used with regexp.Compile. It will return an // expression that can be used with regexp.Compile. It will return an
// error if the input pattern was incorrect. Otherwise, the returned // 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.`. // 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) { func TranslatePattern(pattern string, greedy bool) (string, error) {
any := false any := false
loop: loop:
@ -62,9 +70,10 @@ loop:
case '?': case '?':
buf.WriteString(".") buf.WriteString(".")
case '\\': case '\\':
buf.WriteByte(c) if i++; i >= len(pattern) {
i++ return "", fmt.Errorf(`\ at end of pattern`)
buf.WriteByte(pattern[i]) }
buf.WriteString(regexp.QuoteMeta(string(pattern[i])))
case '[': case '[':
name, err := charClass(pattern[i:]) name, err := charClass(pattern[i:])
if err != nil { if err != nil {
@ -79,20 +88,32 @@ loop:
if i++; i >= len(pattern) { if i++; i >= len(pattern) {
return "", fmt.Errorf("[ was not matched with a closing ]") return "", fmt.Errorf("[ was not matched with a closing ]")
} }
switch c = pattern[i]; c {
case '!', '^':
buf.WriteByte('^')
i++
c = pattern[i] c = pattern[i]
if c == '!' {
c = '^'
} }
buf.WriteByte(c) buf.WriteByte(c)
last := c
rangeStart := byte(0)
for { for {
if i++; i >= len(pattern) { if i++; i >= len(pattern) {
return "", fmt.Errorf("[ was not matched with a closing ]") return "", fmt.Errorf("[ was not matched with a closing ]")
} }
c = pattern[i] last, c = c, pattern[i]
buf.WriteByte(c) buf.WriteByte(c)
if c == ']' { if c == ']' {
break break
} }
if rangeStart != 0 && rangeStart > c {
return "", fmt.Errorf("invalid range: %c-%c", rangeStart, c)
}
if c == '-' {
rangeStart = last
} else {
rangeStart = 0
}
} }
default: default:
buf.WriteString(regexp.QuoteMeta(string(c))) buf.WriteString(regexp.QuoteMeta(string(c)))

View File

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

View File

@ -202,6 +202,13 @@ const (
ResumeKorn ResumeKorn
) )
type ParNamesOperator token
const (
NamesPrefix = ParNamesOperator(star)
NamesPrefixWords = ParNamesOperator(at)
)
type ParExpOperator token type ParExpOperator token
const ( const (
@ -330,6 +337,7 @@ func (o ProcOperator) String() string { return token(o).String() }
func (o GlobOperator) 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 BinCmdOperator) String() string { return token(o).String() }
func (o CaseOperator) 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 ParExpOperator) String() string { return token(o).String() }
func (o UnAritOperator) 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 BinAritOperator) String() string { return token(o).String() }