Add TLS and basic authentication
Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
This commit is contained in:
		
							parent
							
								
									5055dfbbe4
								
							
						
					
					
						commit
						5b4f46a348
					
				|  | @ -46,6 +46,8 @@ import ( | |||
| 	"github.com/prometheus/common/promlog" | ||||
| 	promlogflag "github.com/prometheus/common/promlog/flag" | ||||
| 	"github.com/prometheus/common/version" | ||||
| 	"github.com/prometheus/exporter-toolkit/https" | ||||
| 	httpsflag "github.com/prometheus/exporter-toolkit/https/kingpinflag" | ||||
| 	jcfg "github.com/uber/jaeger-client-go/config" | ||||
| 	jprom "github.com/uber/jaeger-lib/metrics/prometheus" | ||||
| 	"go.uber.org/atomic" | ||||
|  | @ -151,6 +153,8 @@ func main() { | |||
| 	a.Flag("web.listen-address", "Address to listen on for UI, API, and telemetry."). | ||||
| 		Default("0.0.0.0:9090").StringVar(&cfg.web.ListenAddress) | ||||
| 
 | ||||
| 	httpsConfig := httpsflag.AddFlags(a) | ||||
| 
 | ||||
| 	a.Flag("web.read-timeout", | ||||
| 		"Maximum duration before timing out read of the request, and closing idle connections."). | ||||
| 		Default("5m").SetValue(&cfg.webTimeout) | ||||
|  | @ -564,6 +568,12 @@ func main() { | |||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	err = https.Validate(*httpsConfig) | ||||
| 	if err != nil { | ||||
| 		level.Error(logger).Log("msg", "Unable to validate web configuration file", "err", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	var g run.Group | ||||
| 	{ | ||||
| 		// Termination handler.
 | ||||
|  | @ -778,7 +788,7 @@ func main() { | |||
| 		// Web handler.
 | ||||
| 		g.Add( | ||||
| 			func() error { | ||||
| 				if err := webHandler.Run(ctxWeb, listener); err != nil { | ||||
| 				if err := webHandler.Run(ctxWeb, listener, *httpsConfig); err != nil { | ||||
| 					return errors.Wrapf(err, "error starting web server") | ||||
| 				} | ||||
| 				return nil | ||||
|  |  | |||
|  | @ -0,0 +1,72 @@ | |||
| # HTTPS and authentication | ||||
| 
 | ||||
| Prometheus supports basic authentication and TLS. | ||||
| This is **experimental** and might change in the future. | ||||
| 
 | ||||
| To specify which web configuration file to load, use the `--web.config.file` flag. | ||||
| 
 | ||||
| The file is written in [YAML format](https://en.wikipedia.org/wiki/YAML), | ||||
| defined by the scheme described below. | ||||
| Brackets indicate that a parameter is optional. For non-list parameters the | ||||
| value is set to the specified default. | ||||
| 
 | ||||
| The file is read upon every http request, such as any change in the | ||||
| configuration and the certificates is picked up immediately. | ||||
| 
 | ||||
| Generic placeholders are defined as follows: | ||||
| 
 | ||||
| * `<boolean>`: a boolean that can take the values `true` or `false` | ||||
| * `<filename>`: a valid path in the current working directory | ||||
| * `<secret>`: a regular string that is a secret, such as a password | ||||
| * `<string>`: a regular string | ||||
| 
 | ||||
| ``` | ||||
| tls_server_config: | ||||
|   # Certificate and key files for server to use to authenticate to client. | ||||
|   cert_file: <filename> | ||||
|   key_file: <filename> | ||||
| 
 | ||||
|   # Server policy for client authentication. Maps to ClientAuth Policies. | ||||
|   # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType) | ||||
|   [ client_auth_type: <string> | default = "NoClientCert" ] | ||||
| 
 | ||||
|   # CA certificate for client certificate authentication to the server. | ||||
|   [ client_ca_file: <filename> ] | ||||
| 
 | ||||
|   # Minimum TLS version that is acceptable. | ||||
|   [ min_version: <string> | default = "TLS12" ] | ||||
| 
 | ||||
|   # Maximum TLS version that is acceptable. | ||||
|   [ max_version: <string> | default = "TLS13" ] | ||||
| 
 | ||||
|   # List of supported cipher suites for TLS versions up to TLS 1.2. If empty, | ||||
|   # Go default cipher suites are used. Available cipher suites are documented | ||||
|   # in the go documentation: | ||||
|   # https://golang.org/pkg/crypto/tls/#pkg-constants | ||||
|   [ cipher_suites: | ||||
|     [ - <string> ] ] | ||||
| 
 | ||||
|   # prefer_server_cipher_suites controls whether the server selects the | ||||
|   # client's most preferred ciphersuite, or the server's most preferred | ||||
|   # ciphersuite. If true then the server's preference, as expressed in | ||||
|   # the order of elements in cipher_suites, is used. | ||||
|   [ prefer_server_cipher_suites: <bool> | default = true ] | ||||
| 
 | ||||
|   # Elliptic curves that will be used in an ECDHE handshake, in preference | ||||
|   # order. Available curves are documented in the go documentation: | ||||
|   # https://golang.org/pkg/crypto/tls/#CurveID | ||||
|   [ curve_preferences: | ||||
|     [ - <string> ] ] | ||||
| 
 | ||||
| http_server_config: | ||||
|   # Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. | ||||
|   # This can not be changed on the fly. | ||||
|   [ http2: <boolean> | default = true ] | ||||
| 
 | ||||
| # Usernames and hashed passwords that have full access to the web | ||||
| # server via basic authentication. If empty, no basic authentication is | ||||
| # required. Passwords are hashed with bcrypt. | ||||
| basic_auth_users: | ||||
|   [ <string>: <secret> ... ] | ||||
| ``` | ||||
| 
 | ||||
|  | @ -24,6 +24,7 @@ Things considered unstable for 2.x: | |||
| * Any feature listed as experimental or subject to change, including: | ||||
|   * The [`holt_winters` PromQL function](https://github.com/prometheus/prometheus/issues/2458) | ||||
|   * Remote read, remote write and the remote read endpoint | ||||
| * Server-side HTTPS and basic authentication | ||||
| * Service discovery integrations, with the exception of `static_configs` and `file_sd_configs` | ||||
| * Go APIs of packages that are part of the server | ||||
| * HTML generated by the web UI | ||||
|  |  | |||
							
								
								
									
										1
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										1
									
								
								go.mod
								
								
								
								
							|  | @ -52,6 +52,7 @@ require ( | |||
| 	github.com/prometheus/client_golang v1.9.0 | ||||
| 	github.com/prometheus/client_model v0.2.0 | ||||
| 	github.com/prometheus/common v0.15.0 | ||||
| 	github.com/prometheus/exporter-toolkit v0.4.0 | ||||
| 	github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 | ||||
| 	github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 | ||||
| 	github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 | ||||
|  |  | |||
							
								
								
									
										46
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										46
									
								
								go.sum
								
								
								
								
							|  | @ -13,7 +13,6 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 | |||
| cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= | ||||
| cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= | ||||
| cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= | ||||
| cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= | ||||
| cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= | ||||
| cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww= | ||||
| cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= | ||||
|  | @ -49,7 +48,6 @@ github.com/Azure/go-autorest/autorest v0.11.15 h1:S5SDFpmgoVyvMEOcULyEDlYFrdPmu6 | |||
| github.com/Azure/go-autorest/autorest v0.11.15/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.10 h1:r6fZHMaHD8B6LDCn0o5vyBFHIHrM6Ywwx7mb49lPItI= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.10/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= | ||||
|  | @ -98,7 +96,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo | |||
| github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= | ||||
| github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | ||||
| github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | ||||
| github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= | ||||
| github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= | ||||
| github.com/alecthomas/units v0.0.0-20201120081800-1786d5ef83d4 h1:EBTWhcAX7rNQ80RLwLCpHZBBrJuzallFHnF+yMXo928= | ||||
| github.com/alecthomas/units v0.0.0-20201120081800-1786d5ef83d4/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= | ||||
|  | @ -116,7 +113,6 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI | |||
| github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= | ||||
| github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= | ||||
| github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= | ||||
| github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= | ||||
| github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= | ||||
| github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= | ||||
| github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= | ||||
|  | @ -144,7 +140,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf | |||
| github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= | ||||
| github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | ||||
| github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= | ||||
| github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | ||||
| github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | ||||
| github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= | ||||
|  | @ -237,7 +232,6 @@ github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpR | |||
| github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= | ||||
| github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= | ||||
| github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= | ||||
| github.com/go-openapi/analysis v0.19.10 h1:5BHISBAXOc/aJK25irLZnx2D3s6WyYaY9D4gmuz9fdE= | ||||
| github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= | ||||
| github.com/go-openapi/analysis v0.19.14 h1:OPuUe8ApFeu59GeTsZtb0mLWHu5MipU4fDvxNLsG3bw= | ||||
| github.com/go-openapi/analysis v0.19.14/go.mod h1:zN0kY6i38wo2LQOwltVyMk61bqlqOm86n1/Iszo8F8Y= | ||||
|  | @ -245,7 +239,6 @@ github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQH | |||
| github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= | ||||
| github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= | ||||
| github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= | ||||
| github.com/go-openapi/errors v0.19.4 h1:fSGwO1tSYHFu70NKaWJt5Qh0qoBRtCm/mXS1yhf+0W0= | ||||
| github.com/go-openapi/errors v0.19.4/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= | ||||
| github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= | ||||
| github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= | ||||
|  | @ -254,14 +247,12 @@ github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpX | |||
| github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= | ||||
| github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= | ||||
| github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= | ||||
| github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= | ||||
| github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= | ||||
| github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= | ||||
| github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= | ||||
| github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= | ||||
| github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= | ||||
| github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= | ||||
| github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= | ||||
| github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= | ||||
| github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= | ||||
| github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= | ||||
|  | @ -271,14 +262,12 @@ github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf | |||
| github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= | ||||
| github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= | ||||
| github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= | ||||
| github.com/go-openapi/loads v0.19.5 h1:jZVYWawIQiA1NBnHla28ktg6hrcfTHsCE+3QLVRBIls= | ||||
| github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= | ||||
| github.com/go-openapi/loads v0.19.6 h1:6IAtnx22MNSjPocZZ2sV7EjgF6wW5rDC9r6ZkNxjiN8= | ||||
| github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= | ||||
| github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= | ||||
| github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= | ||||
| github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= | ||||
| github.com/go-openapi/runtime v0.19.15 h1:2GIefxs9Rx1vCDNghRtypRq+ig8KSLrjHbAYI/gCLCM= | ||||
| github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= | ||||
| github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= | ||||
| github.com/go-openapi/runtime v0.19.24 h1:TqagMVlRAOTwllE/7hNKx6rQ10O6T8ZzeJdMjSTKaD4= | ||||
|  | @ -288,7 +277,6 @@ github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd | |||
| github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= | ||||
| github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= | ||||
| github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= | ||||
| github.com/go-openapi/spec v0.19.8 h1:qAdZLh1r6QF/hI/gTq+TJTvsQUodZsM7KLqkAJdiJNg= | ||||
| github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= | ||||
| github.com/go-openapi/spec v0.19.14 h1:r4fbYFo6N4ZelmSX8G6p+cv/hZRXzcuqQIADGT1iNKM= | ||||
| github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA= | ||||
|  | @ -298,7 +286,6 @@ github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+Z | |||
| github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= | ||||
| github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= | ||||
| github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= | ||||
| github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM= | ||||
| github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= | ||||
| github.com/go-openapi/strfmt v0.19.11 h1:0+YvbNh05rmBkgztd6zHp4OCFn7Mtu30bn46NQo2ZRw= | ||||
| github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= | ||||
|  | @ -307,7 +294,6 @@ github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/ | |||
| github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= | ||||
| github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= | ||||
| github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= | ||||
| github.com/go-openapi/swag v0.19.9 h1:1IxuqvBUU3S2Bi4YC7tlP9SJF1gVpCvqN0T2Qof4azE= | ||||
| github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= | ||||
| github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY= | ||||
| github.com/go-openapi/swag v0.19.12 h1:Bc0bnY2c3AoF7Gc+IMIAQQsD8fLHjHpc19wXvYuayQI= | ||||
|  | @ -315,7 +301,6 @@ github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5H | |||
| github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= | ||||
| github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= | ||||
| github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= | ||||
| github.com/go-openapi/validate v0.19.8 h1:YFzsdWIDfVuLvIOF+ZmKjVg1MbPJ1QgY9PihMwei1ys= | ||||
| github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= | ||||
| github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8= | ||||
| github.com/go-openapi/validate v0.19.12/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4= | ||||
|  | @ -385,7 +370,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU | |||
| github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | ||||
| github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | ||||
| github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= | ||||
| github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= | ||||
| github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
| github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= | ||||
| github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
|  | @ -404,7 +388,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||
| github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= | ||||
| github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= | ||||
| github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
|  | @ -428,7 +411,6 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2 h1:LR89qFljJ48s990kEK | |||
| github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= | ||||
| github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | ||||
| github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= | ||||
| github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= | ||||
| github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
|  | @ -505,7 +487,6 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= | |||
| github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | ||||
| github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= | ||||
| github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | ||||
| github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= | ||||
| github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | ||||
| github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | ||||
| github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= | ||||
|  | @ -563,11 +544,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv | |||
| github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= | ||||
| github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||||
| github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | ||||
| github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= | ||||
| github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | ||||
| github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||
| github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= | ||||
| github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||||
| github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||||
| github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||||
| github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | ||||
|  | @ -581,7 +560,6 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN | |||
| github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= | ||||
| github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= | ||||
| github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= | ||||
| github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8= | ||||
| github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= | ||||
| github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
|  | @ -715,7 +693,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn | |||
| github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= | ||||
| github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= | ||||
| github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= | ||||
| github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= | ||||
| github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= | ||||
| github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= | ||||
| github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= | ||||
|  | @ -734,12 +711,13 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b | |||
| github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= | ||||
| github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= | ||||
| github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= | ||||
| github.com/prometheus/exporter-toolkit v0.4.0 h1:O7Bw+ZKEMzW7vD10IuVF70b8EE4JIG7BvHFj9UKz49g= | ||||
| github.com/prometheus/exporter-toolkit v0.4.0/go.mod h1:OCkM4805mmisBhLmVFw858QYi3v0wKdY6/UxrT0pZVg= | ||||
| github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | ||||
| github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | ||||
| github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= | ||||
| github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= | ||||
| github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | ||||
| github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= | ||||
| github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | ||||
| github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= | ||||
| github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= | ||||
|  | @ -843,7 +821,6 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | |||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= | ||||
| go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= | ||||
| go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= | ||||
|  | @ -874,8 +851,9 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 | |||
| golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
| golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604= | ||||
| golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | ||||
| golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
|  | @ -952,7 +930,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R | |||
| golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | ||||
| golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||||
| golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||||
| golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= | ||||
| golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||||
| golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= | ||||
| golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
|  | @ -961,9 +938,7 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr | |||
| golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc= | ||||
| golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
| golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 h1:Mj83v+wSRNEar42a/MQgxk9X42TdEmrOl9i+y8WbxLo= | ||||
| golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
| golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4= | ||||
| golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= | ||||
|  | @ -976,7 +951,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||
| golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= | ||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= | ||||
| golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
|  | @ -1038,18 +1012,18 @@ golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7w | |||
| golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= | ||||
| golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||
| golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= | ||||
| golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
|  | @ -1057,7 +1031,6 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb | |||
| golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= | ||||
| golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= | ||||
| golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
|  | @ -1154,7 +1127,6 @@ google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ | |||
| google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= | ||||
| google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= | ||||
| google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo= | ||||
| google.golang.org/api v0.35.0 h1:TBCmTTxUrRDA1iTctnK/fIeitxIZ+TQuaf0j29fmCGo= | ||||
| google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= | ||||
| google.golang.org/api v0.36.0 h1:l2Nfbl2GPXdWorv+dT2XfinX2jOOw4zv1VhLstx+6rE= | ||||
| google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= | ||||
|  | @ -1164,7 +1136,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 | |||
| google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | ||||
| google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | ||||
| google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= | ||||
| google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= | ||||
| google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= | ||||
| google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= | ||||
| google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= | ||||
|  | @ -1200,7 +1171,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY | |||
| google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= | ||||
| google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d h1:92D1fum1bJLKSdr11OJ+54YeCMCGYIygTA7R/YZxH5M= | ||||
| google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e h1:wYR00/Ht+i/79g/gzhdehBgLIJCklKoc8Q/NebdzzpY= | ||||
|  | @ -1222,7 +1192,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa | |||
| google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= | ||||
| google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= | ||||
| google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= | ||||
| google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc= | ||||
| google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= | ||||
| google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= | ||||
| google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= | ||||
|  | @ -1234,7 +1203,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi | |||
| google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= | ||||
| google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= | ||||
| google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= | ||||
| google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | ||||
|  | @ -1242,7 +1210,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQ | |||
| gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= | ||||
| gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | ||||
| gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
|  | @ -1266,7 +1233,6 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
| gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= | ||||
| gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | ||||
| gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= | ||||
|  |  | |||
|  | @ -0,0 +1,201 @@ | |||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
| 
 | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
| 
 | ||||
|    1. Definitions. | ||||
| 
 | ||||
|       "License" shall mean the terms and conditions for use, reproduction, | ||||
|       and distribution as defined by Sections 1 through 9 of this document. | ||||
| 
 | ||||
|       "Licensor" shall mean the copyright owner or entity authorized by | ||||
|       the copyright owner that is granting the License. | ||||
| 
 | ||||
|       "Legal Entity" shall mean the union of the acting entity and all | ||||
|       other entities that control, are controlled by, or are under common | ||||
|       control with that entity. For the purposes of this definition, | ||||
|       "control" means (i) the power, direct or indirect, to cause the | ||||
|       direction or management of such entity, whether by contract or | ||||
|       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||
|       outstanding shares, or (iii) beneficial ownership of such entity. | ||||
| 
 | ||||
|       "You" (or "Your") shall mean an individual or Legal Entity | ||||
|       exercising permissions granted by this License. | ||||
| 
 | ||||
|       "Source" form shall mean the preferred form for making modifications, | ||||
|       including but not limited to software source code, documentation | ||||
|       source, and configuration files. | ||||
| 
 | ||||
|       "Object" form shall mean any form resulting from mechanical | ||||
|       transformation or translation of a Source form, including but | ||||
|       not limited to compiled object code, generated documentation, | ||||
|       and conversions to other media types. | ||||
| 
 | ||||
|       "Work" shall mean the work of authorship, whether in Source or | ||||
|       Object form, made available under the License, as indicated by a | ||||
|       copyright notice that is included in or attached to the work | ||||
|       (an example is provided in the Appendix below). | ||||
| 
 | ||||
|       "Derivative Works" shall mean any work, whether in Source or Object | ||||
|       form, that is based on (or derived from) the Work and for which the | ||||
|       editorial revisions, annotations, elaborations, or other modifications | ||||
|       represent, as a whole, an original work of authorship. For the purposes | ||||
|       of this License, Derivative Works shall not include works that remain | ||||
|       separable from, or merely link (or bind by name) to the interfaces of, | ||||
|       the Work and Derivative Works thereof. | ||||
| 
 | ||||
|       "Contribution" shall mean any work of authorship, including | ||||
|       the original version of the Work and any modifications or additions | ||||
|       to that Work or Derivative Works thereof, that is intentionally | ||||
|       submitted to Licensor for inclusion in the Work by the copyright owner | ||||
|       or by an individual or Legal Entity authorized to submit on behalf of | ||||
|       the copyright owner. For the purposes of this definition, "submitted" | ||||
|       means any form of electronic, verbal, or written communication sent | ||||
|       to the Licensor or its representatives, including but not limited to | ||||
|       communication on electronic mailing lists, source code control systems, | ||||
|       and issue tracking systems that are managed by, or on behalf of, the | ||||
|       Licensor for the purpose of discussing and improving the Work, but | ||||
|       excluding communication that is conspicuously marked or otherwise | ||||
|       designated in writing by the copyright owner as "Not a Contribution." | ||||
| 
 | ||||
|       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||
|       on behalf of whom a Contribution has been received by Licensor and | ||||
|       subsequently incorporated within the Work. | ||||
| 
 | ||||
|    2. Grant of Copyright License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       copyright license to reproduce, prepare Derivative Works of, | ||||
|       publicly display, publicly perform, sublicense, and distribute the | ||||
|       Work and such Derivative Works in Source or Object form. | ||||
| 
 | ||||
|    3. Grant of Patent License. Subject to the terms and conditions of | ||||
|       this License, each Contributor hereby grants to You a perpetual, | ||||
|       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||
|       (except as stated in this section) patent license to make, have made, | ||||
|       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||
|       where such license applies only to those patent claims licensable | ||||
|       by such Contributor that are necessarily infringed by their | ||||
|       Contribution(s) alone or by combination of their Contribution(s) | ||||
|       with the Work to which such Contribution(s) was submitted. If You | ||||
|       institute patent litigation against any entity (including a | ||||
|       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||
|       or a Contribution incorporated within the Work constitutes direct | ||||
|       or contributory patent infringement, then any patent licenses | ||||
|       granted to You under this License for that Work shall terminate | ||||
|       as of the date such litigation is filed. | ||||
| 
 | ||||
|    4. Redistribution. You may reproduce and distribute copies of the | ||||
|       Work or Derivative Works thereof in any medium, with or without | ||||
|       modifications, and in Source or Object form, provided that You | ||||
|       meet the following conditions: | ||||
| 
 | ||||
|       (a) You must give any other recipients of the Work or | ||||
|           Derivative Works a copy of this License; and | ||||
| 
 | ||||
|       (b) You must cause any modified files to carry prominent notices | ||||
|           stating that You changed the files; and | ||||
| 
 | ||||
|       (c) You must retain, in the Source form of any Derivative Works | ||||
|           that You distribute, all copyright, patent, trademark, and | ||||
|           attribution notices from the Source form of the Work, | ||||
|           excluding those notices that do not pertain to any part of | ||||
|           the Derivative Works; and | ||||
| 
 | ||||
|       (d) If the Work includes a "NOTICE" text file as part of its | ||||
|           distribution, then any Derivative Works that You distribute must | ||||
|           include a readable copy of the attribution notices contained | ||||
|           within such NOTICE file, excluding those notices that do not | ||||
|           pertain to any part of the Derivative Works, in at least one | ||||
|           of the following places: within a NOTICE text file distributed | ||||
|           as part of the Derivative Works; within the Source form or | ||||
|           documentation, if provided along with the Derivative Works; or, | ||||
|           within a display generated by the Derivative Works, if and | ||||
|           wherever such third-party notices normally appear. The contents | ||||
|           of the NOTICE file are for informational purposes only and | ||||
|           do not modify the License. You may add Your own attribution | ||||
|           notices within Derivative Works that You distribute, alongside | ||||
|           or as an addendum to the NOTICE text from the Work, provided | ||||
|           that such additional attribution notices cannot be construed | ||||
|           as modifying the License. | ||||
| 
 | ||||
|       You may add Your own copyright statement to Your modifications and | ||||
|       may provide additional or different license terms and conditions | ||||
|       for use, reproduction, or distribution of Your modifications, or | ||||
|       for any such Derivative Works as a whole, provided Your use, | ||||
|       reproduction, and distribution of the Work otherwise complies with | ||||
|       the conditions stated in this License. | ||||
| 
 | ||||
|    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||
|       any Contribution intentionally submitted for inclusion in the Work | ||||
|       by You to the Licensor shall be under the terms and conditions of | ||||
|       this License, without any additional terms or conditions. | ||||
|       Notwithstanding the above, nothing herein shall supersede or modify | ||||
|       the terms of any separate license agreement you may have executed | ||||
|       with Licensor regarding such Contributions. | ||||
| 
 | ||||
|    6. Trademarks. This License does not grant permission to use the trade | ||||
|       names, trademarks, service marks, or product names of the Licensor, | ||||
|       except as required for reasonable and customary use in describing the | ||||
|       origin of the Work and reproducing the content of the NOTICE file. | ||||
| 
 | ||||
|    7. Disclaimer of Warranty. Unless required by applicable law or | ||||
|       agreed to in writing, Licensor provides the Work (and each | ||||
|       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||
|       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||
|       implied, including, without limitation, any warranties or conditions | ||||
|       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||
|       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||
|       appropriateness of using or redistributing the Work and assume any | ||||
|       risks associated with Your exercise of permissions under this License. | ||||
| 
 | ||||
|    8. Limitation of Liability. In no event and under no legal theory, | ||||
|       whether in tort (including negligence), contract, or otherwise, | ||||
|       unless required by applicable law (such as deliberate and grossly | ||||
|       negligent acts) or agreed to in writing, shall any Contributor be | ||||
|       liable to You for damages, including any direct, indirect, special, | ||||
|       incidental, or consequential damages of any character arising as a | ||||
|       result of this License or out of the use or inability to use the | ||||
|       Work (including but not limited to damages for loss of goodwill, | ||||
|       work stoppage, computer failure or malfunction, or any and all | ||||
|       other commercial damages or losses), even if such Contributor | ||||
|       has been advised of the possibility of such damages. | ||||
| 
 | ||||
|    9. Accepting Warranty or Additional Liability. While redistributing | ||||
|       the Work or Derivative Works thereof, You may choose to offer, | ||||
|       and charge a fee for, acceptance of support, warranty, indemnity, | ||||
|       or other liability obligations and/or rights consistent with this | ||||
|       License. However, in accepting such obligations, You may act only | ||||
|       on Your own behalf and on Your sole responsibility, not on behalf | ||||
|       of any other Contributor, and only if You agree to indemnify, | ||||
|       defend, and hold each Contributor harmless for any liability | ||||
|       incurred by, or claims asserted against, such Contributor by reason | ||||
|       of your accepting any such warranty or additional liability. | ||||
| 
 | ||||
|    END OF TERMS AND CONDITIONS | ||||
| 
 | ||||
|    APPENDIX: How to apply the Apache License to your work. | ||||
| 
 | ||||
|       To apply the Apache License to your work, attach the following | ||||
|       boilerplate notice, with the fields enclosed by brackets "[]" | ||||
|       replaced with your own identifying information. (Don't include | ||||
|       the brackets!)  The text should be enclosed in the appropriate | ||||
|       comment syntax for the file format. We also recommend that a | ||||
|       file or class name and description of purpose be included on the | ||||
|       same "printed page" as the copyright notice for easier | ||||
|       identification within third-party archives. | ||||
| 
 | ||||
|    Copyright [yyyy] [name of copyright owner] | ||||
| 
 | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
| 
 | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
|  | @ -0,0 +1,81 @@ | |||
| # HTTPS Package for Prometheus | ||||
| 
 | ||||
| The `https` directory contains a Go package and a sample configuration file for | ||||
| running `node_exporter` with HTTPS instead of HTTP. We currently support TLS 1.3 | ||||
| and TLS 1.2. | ||||
| 
 | ||||
| To run a server with TLS, use the flag `--web.config`. | ||||
| 
 | ||||
| e.g. `./node_exporter --web.config="web-config.yml"` | ||||
| If the config is kept within the https directory. | ||||
| 
 | ||||
| The config file should be written in YAML format, and is reloaded on each connection to check for new certificates and/or authentication policy. | ||||
| 
 | ||||
| ## Sample Config | ||||
| 
 | ||||
| ``` | ||||
| tls_server_config: | ||||
|   # Certificate and key files for server to use to authenticate to client. | ||||
|   cert_file: <filename> | ||||
|   key_file: <filename> | ||||
| 
 | ||||
|   # Server policy for client authentication. Maps to ClientAuth Policies. | ||||
|   # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType) | ||||
|   [ client_auth_type: <string> | default = "NoClientCert" ] | ||||
| 
 | ||||
|   # CA certificate for client certificate authentication to the server. | ||||
|   [ client_ca_file: <filename> ] | ||||
| 
 | ||||
|   # Minimum TLS version that is acceptable. | ||||
|   [ min_version: <string> | default = "TLS12" ] | ||||
| 
 | ||||
|   # Maximum TLS version that is acceptable. | ||||
|   [ max_version: <string> | default = "TLS13" ] | ||||
| 
 | ||||
|   # List of supported cipher suites for TLS versions up to TLS 1.2. If empty, | ||||
|   # Go default cipher suites are used. Available cipher suites are documented | ||||
|   # in the go documentation: | ||||
|   # https://golang.org/pkg/crypto/tls/#pkg-constants | ||||
|   [ cipher_suites: | ||||
|     [ - <string> ] ] | ||||
| 
 | ||||
|   # prefer_server_cipher_suites controls whether the server selects the | ||||
|   # client's most preferred ciphersuite, or the server's most preferred | ||||
|   # ciphersuite. If true then the server's preference, as expressed in | ||||
|   # the order of elements in cipher_suites, is used. | ||||
|   [ prefer_server_cipher_suites: <bool> | default = true ] | ||||
| 
 | ||||
|   # Elliptic curves that will be used in an ECDHE handshake, in preference | ||||
|   # order. Available curves are documented in the go documentation: | ||||
|   # https://golang.org/pkg/crypto/tls/#CurveID | ||||
|   [ curve_preferences: | ||||
|     [ - <string> ] ] | ||||
| 
 | ||||
| http_server_config: | ||||
|   # Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. | ||||
|   # This can not be changed on the fly. | ||||
|   [ http2: <bool> | default = true ] | ||||
| 
 | ||||
| # Usernames and hashed passwords that have full access to the web | ||||
| # server via basic authentication. If empty, no basic authentication is | ||||
| # required. Passwords are hashed with bcrypt. | ||||
| basic_auth_users: | ||||
|   [ <string>: <secret> ... ] | ||||
| ``` | ||||
| 
 | ||||
| ## About bcrypt | ||||
| 
 | ||||
| There are several tools out there to generate bcrypt passwords, e.g. | ||||
| [htpasswd](https://httpd.apache.org/docs/2.4/programs/htpasswd.html): | ||||
| 
 | ||||
| `htpasswd -nBC 10 "" | tr -d ':\n'` | ||||
| 
 | ||||
| That command will prompt you for a password and output the hashed password, | ||||
| which will look something like: | ||||
| `$2y$10$X0h1gDsPszWURQaxFh.zoubFi6DXncSjhoQNJgRrnGs7EsimhC7zG` | ||||
| 
 | ||||
| The cost (10 in the example) influences the time it takes for computing the | ||||
| hash. A higher cost will en up slowing down the authentication process. | ||||
| Depending on the machine, a cost of 10 will take about ~70ms where a cost of | ||||
| 18 can take up to a few seconds. That hash will be computed on every | ||||
| password-protected request. | ||||
							
								
								
									
										26
									
								
								vendor/github.com/prometheus/exporter-toolkit/https/kingpinflag/flag.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										26
									
								
								vendor/github.com/prometheus/exporter-toolkit/https/kingpinflag/flag.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,26 @@ | |||
| // Copyright 2020 The Prometheus Authors
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| // http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| package kingpinflag | ||||
| 
 | ||||
| import ( | ||||
| 	"gopkg.in/alecthomas/kingpin.v2" | ||||
| ) | ||||
| 
 | ||||
| // AddFlags adds the flags used by this package to the Kingpin application.
 | ||||
| // To use the default Kingpin application, call AddFlags(kingpin.CommandLine)
 | ||||
| func AddFlags(a *kingpin.Application) *string { | ||||
| 	return a.Flag( | ||||
| 		"web.config.file", | ||||
| 		"[EXPERIMENTAL] Path to configuration file that can enable TLS or authentication.", | ||||
| 	).Default("").String() | ||||
| } | ||||
							
								
								
									
										343
									
								
								vendor/github.com/prometheus/exporter-toolkit/https/tls_config.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										343
									
								
								vendor/github.com/prometheus/exporter-toolkit/https/tls_config.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,343 @@ | |||
| // Copyright 2019 The Prometheus Authors
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| // http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| // Package https allows the implementation of TLS.
 | ||||
| package https | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/go-kit/kit/log" | ||||
| 	"github.com/go-kit/kit/log/level" | ||||
| 	"github.com/pkg/errors" | ||||
| 	config_util "github.com/prometheus/common/config" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	errNoTLSConfig = errors.New("TLS config is not present") | ||||
| ) | ||||
| 
 | ||||
| type Config struct { | ||||
| 	TLSConfig  TLSStruct                     `yaml:"tls_server_config"` | ||||
| 	HTTPConfig HTTPStruct                    `yaml:"http_server_config"` | ||||
| 	Users      map[string]config_util.Secret `yaml:"basic_auth_users"` | ||||
| } | ||||
| 
 | ||||
| type TLSStruct struct { | ||||
| 	TLSCertPath              string     `yaml:"cert_file"` | ||||
| 	TLSKeyPath               string     `yaml:"key_file"` | ||||
| 	ClientAuth               string     `yaml:"client_auth_type"` | ||||
| 	ClientCAs                string     `yaml:"client_ca_file"` | ||||
| 	CipherSuites             []cipher   `yaml:"cipher_suites"` | ||||
| 	CurvePreferences         []curve    `yaml:"curve_preferences"` | ||||
| 	MinVersion               tlsVersion `yaml:"min_version"` | ||||
| 	MaxVersion               tlsVersion `yaml:"max_version"` | ||||
| 	PreferServerCipherSuites bool       `yaml:"prefer_server_cipher_suites"` | ||||
| } | ||||
| 
 | ||||
| // SetDirectory joins any relative file paths with dir.
 | ||||
| func (t *TLSStruct) SetDirectory(dir string) { | ||||
| 	t.TLSCertPath = config_util.JoinDir(dir, t.TLSCertPath) | ||||
| 	t.TLSKeyPath = config_util.JoinDir(dir, t.TLSKeyPath) | ||||
| 	t.ClientCAs = config_util.JoinDir(dir, t.ClientCAs) | ||||
| } | ||||
| 
 | ||||
| type HTTPStruct struct { | ||||
| 	HTTP2 bool `yaml:"http2"` | ||||
| } | ||||
| 
 | ||||
| func getConfig(configPath string) (*Config, error) { | ||||
| 	content, err := ioutil.ReadFile(configPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	c := &Config{ | ||||
| 		TLSConfig: TLSStruct{ | ||||
| 			MinVersion:               tls.VersionTLS12, | ||||
| 			MaxVersion:               tls.VersionTLS13, | ||||
| 			PreferServerCipherSuites: true, | ||||
| 		}, | ||||
| 		HTTPConfig: HTTPStruct{HTTP2: true}, | ||||
| 	} | ||||
| 	err = yaml.UnmarshalStrict(content, c) | ||||
| 	c.TLSConfig.SetDirectory(filepath.Dir(configPath)) | ||||
| 	return c, err | ||||
| } | ||||
| 
 | ||||
| func getTLSConfig(configPath string) (*tls.Config, error) { | ||||
| 	c, err := getConfig(configPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ConfigToTLSConfig(&c.TLSConfig) | ||||
| } | ||||
| 
 | ||||
| // ConfigToTLSConfig generates the golang tls.Config from the TLSStruct config.
 | ||||
| func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { | ||||
| 	if c.TLSCertPath == "" && c.TLSKeyPath == "" && c.ClientAuth == "" && c.ClientCAs == "" { | ||||
| 		return nil, errNoTLSConfig | ||||
| 	} | ||||
| 
 | ||||
| 	if c.TLSCertPath == "" { | ||||
| 		return nil, errors.New("missing cert_file") | ||||
| 	} | ||||
| 
 | ||||
| 	if c.TLSKeyPath == "" { | ||||
| 		return nil, errors.New("missing key_file") | ||||
| 	} | ||||
| 
 | ||||
| 	loadCert := func() (*tls.Certificate, error) { | ||||
| 		cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrap(err, "failed to load X509KeyPair") | ||||
| 		} | ||||
| 		return &cert, nil | ||||
| 	} | ||||
| 
 | ||||
| 	// Confirm that certificate and key paths are valid.
 | ||||
| 	if _, err := loadCert(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	cfg := &tls.Config{ | ||||
| 		MinVersion:               (uint16)(c.MinVersion), | ||||
| 		MaxVersion:               (uint16)(c.MaxVersion), | ||||
| 		PreferServerCipherSuites: c.PreferServerCipherSuites, | ||||
| 	} | ||||
| 
 | ||||
| 	cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { | ||||
| 		return loadCert() | ||||
| 	} | ||||
| 
 | ||||
| 	var cf []uint16 | ||||
| 	for _, c := range c.CipherSuites { | ||||
| 		cf = append(cf, (uint16)(c)) | ||||
| 	} | ||||
| 	if len(cf) > 0 { | ||||
| 		cfg.CipherSuites = cf | ||||
| 	} | ||||
| 
 | ||||
| 	var cp []tls.CurveID | ||||
| 	for _, c := range c.CurvePreferences { | ||||
| 		cp = append(cp, (tls.CurveID)(c)) | ||||
| 	} | ||||
| 	if len(cp) > 0 { | ||||
| 		cfg.CurvePreferences = cp | ||||
| 	} | ||||
| 
 | ||||
| 	if c.ClientCAs != "" { | ||||
| 		clientCAPool := x509.NewCertPool() | ||||
| 		clientCAFile, err := ioutil.ReadFile(c.ClientCAs) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		clientCAPool.AppendCertsFromPEM(clientCAFile) | ||||
| 		cfg.ClientCAs = clientCAPool | ||||
| 	} | ||||
| 
 | ||||
| 	switch c.ClientAuth { | ||||
| 	case "RequestClientCert": | ||||
| 		cfg.ClientAuth = tls.RequestClientCert | ||||
| 	case "RequireClientCert": | ||||
| 		cfg.ClientAuth = tls.RequireAnyClientCert | ||||
| 	case "VerifyClientCertIfGiven": | ||||
| 		cfg.ClientAuth = tls.VerifyClientCertIfGiven | ||||
| 	case "RequireAndVerifyClientCert": | ||||
| 		cfg.ClientAuth = tls.RequireAndVerifyClientCert | ||||
| 	case "", "NoClientCert": | ||||
| 		cfg.ClientAuth = tls.NoClientCert | ||||
| 	default: | ||||
| 		return nil, errors.New("Invalid ClientAuth: " + c.ClientAuth) | ||||
| 	} | ||||
| 
 | ||||
| 	if c.ClientCAs != "" && cfg.ClientAuth == tls.NoClientCert { | ||||
| 		return nil, errors.New("Client CA's have been configured without a Client Auth Policy") | ||||
| 	} | ||||
| 
 | ||||
| 	return cfg, nil | ||||
| } | ||||
| 
 | ||||
| // Listen starts the server on the given address. Based on the file
 | ||||
| // tlsConfigPath, TLS or basic auth could be enabled.
 | ||||
| func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error { | ||||
| 	listener, err := net.Listen("tcp", server.Addr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer listener.Close() | ||||
| 	return Serve(listener, server, tlsConfigPath, logger) | ||||
| } | ||||
| 
 | ||||
| // Server starts the server on the given listener. Based on the file
 | ||||
| // tlsConfigPath, TLS or basic auth could be enabled.
 | ||||
| func Serve(l net.Listener, server *http.Server, tlsConfigPath string, logger log.Logger) error { | ||||
| 	if tlsConfigPath == "" { | ||||
| 		level.Info(logger).Log("msg", "TLS is disabled.", "http2", false) | ||||
| 		return server.Serve(l) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := validateUsers(tlsConfigPath); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Setup basic authentication.
 | ||||
| 	var handler http.Handler = http.DefaultServeMux | ||||
| 	if server.Handler != nil { | ||||
| 		handler = server.Handler | ||||
| 	} | ||||
| 	server.Handler = &userAuthRoundtrip{ | ||||
| 		tlsConfigPath: tlsConfigPath, | ||||
| 		logger:        logger, | ||||
| 		handler:       handler, | ||||
| 	} | ||||
| 
 | ||||
| 	c, err := getConfig(tlsConfigPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	config, err := ConfigToTLSConfig(&c.TLSConfig) | ||||
| 	switch err { | ||||
| 	case nil: | ||||
| 		if !c.HTTPConfig.HTTP2 { | ||||
| 			server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) | ||||
| 		} | ||||
| 		// Valid TLS config.
 | ||||
| 		level.Info(logger).Log("msg", "TLS is enabled.", "http2", c.HTTPConfig.HTTP2) | ||||
| 	case errNoTLSConfig: | ||||
| 		// No TLS config, back to plain HTTP.
 | ||||
| 		level.Info(logger).Log("msg", "TLS is disabled.", "http2", false) | ||||
| 		return server.Serve(l) | ||||
| 	default: | ||||
| 		// Invalid TLS config.
 | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	server.TLSConfig = config | ||||
| 
 | ||||
| 	// Set the GetConfigForClient method of the HTTPS server so that the config
 | ||||
| 	// and certs are reloaded on new connections.
 | ||||
| 	server.TLSConfig.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { | ||||
| 		return getTLSConfig(tlsConfigPath) | ||||
| 	} | ||||
| 	return server.ServeTLS(l, "", "") | ||||
| } | ||||
| 
 | ||||
| // Validate configuration file by reading the configuration and the certificates.
 | ||||
| func Validate(tlsConfigPath string) error { | ||||
| 	if tlsConfigPath == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if err := validateUsers(tlsConfigPath); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	c, err := getConfig(tlsConfigPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = ConfigToTLSConfig(&c.TLSConfig) | ||||
| 	if err == errNoTLSConfig { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| type cipher uint16 | ||||
| 
 | ||||
| func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var s string | ||||
| 	err := unmarshal((*string)(&s)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, cs := range tls.CipherSuites() { | ||||
| 		if cs.Name == s { | ||||
| 			*c = (cipher)(cs.ID) | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	return errors.New("unknown cipher: " + s) | ||||
| } | ||||
| 
 | ||||
| func (c cipher) MarshalYAML() (interface{}, error) { | ||||
| 	return tls.CipherSuiteName((uint16)(c)), nil | ||||
| } | ||||
| 
 | ||||
| type curve tls.CurveID | ||||
| 
 | ||||
| var curves = map[string]curve{ | ||||
| 	"CurveP256": (curve)(tls.CurveP256), | ||||
| 	"CurveP384": (curve)(tls.CurveP384), | ||||
| 	"CurveP521": (curve)(tls.CurveP521), | ||||
| 	"X25519":    (curve)(tls.X25519), | ||||
| } | ||||
| 
 | ||||
| func (c *curve) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var s string | ||||
| 	err := unmarshal((*string)(&s)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if curveid, ok := curves[s]; ok { | ||||
| 		*c = curveid | ||||
| 		return nil | ||||
| 	} | ||||
| 	return errors.New("unknown curve: " + s) | ||||
| } | ||||
| 
 | ||||
| func (c *curve) MarshalYAML() (interface{}, error) { | ||||
| 	for s, curveid := range curves { | ||||
| 		if *c == curveid { | ||||
| 			return s, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return fmt.Sprintf("%v", c), nil | ||||
| } | ||||
| 
 | ||||
| type tlsVersion uint16 | ||||
| 
 | ||||
| var tlsVersions = map[string]tlsVersion{ | ||||
| 	"TLS13": (tlsVersion)(tls.VersionTLS13), | ||||
| 	"TLS12": (tlsVersion)(tls.VersionTLS12), | ||||
| 	"TLS11": (tlsVersion)(tls.VersionTLS11), | ||||
| 	"TLS10": (tlsVersion)(tls.VersionTLS10), | ||||
| } | ||||
| 
 | ||||
| func (tv *tlsVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var s string | ||||
| 	err := unmarshal((*string)(&s)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if v, ok := tlsVersions[s]; ok { | ||||
| 		*tv = v | ||||
| 		return nil | ||||
| 	} | ||||
| 	return errors.New("unknown TLS version: " + s) | ||||
| } | ||||
| 
 | ||||
| func (tv *tlsVersion) MarshalYAML() (interface{}, error) { | ||||
| 	for s, v := range tlsVersions { | ||||
| 		if *tv == v { | ||||
| 			return s, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return fmt.Sprintf("%v", tv), nil | ||||
| } | ||||
|  | @ -0,0 +1,70 @@ | |||
| // Copyright 2020 The Prometheus Authors
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| // http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| package https | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/go-kit/kit/log" | ||||
| 	"golang.org/x/crypto/bcrypt" | ||||
| ) | ||||
| 
 | ||||
| func validateUsers(configPath string) error { | ||||
| 	c, err := getConfig(configPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, p := range c.Users { | ||||
| 		_, err = bcrypt.Cost([]byte(p)) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| type userAuthRoundtrip struct { | ||||
| 	tlsConfigPath string | ||||
| 	handler       http.Handler | ||||
| 	logger        log.Logger | ||||
| } | ||||
| 
 | ||||
| func (u *userAuthRoundtrip) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 	c, err := getConfig(u.tlsConfigPath) | ||||
| 	if err != nil { | ||||
| 		u.logger.Log("msg", "Unable to parse configuration", "err", err) | ||||
| 		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if len(c.Users) == 0 { | ||||
| 		u.handler.ServeHTTP(w, r) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user, pass, auth := r.BasicAuth() | ||||
| 	if auth { | ||||
| 		if hashedPassword, ok := c.Users[user]; ok { | ||||
| 			if err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(pass)); err == nil { | ||||
| 				u.handler.ServeHTTP(w, r) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	w.Header().Set("WWW-Authenticate", "Basic") | ||||
| 	http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| # Minimal TLS configuration example. Additionally, a certificate and a key file | ||||
| # are needed. | ||||
| tls_server_config: | ||||
|   cert_file: server.crt | ||||
|   key_file: server.key | ||||
| 
 | ||||
|  | @ -0,0 +1,35 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package bcrypt | ||||
| 
 | ||||
| import "encoding/base64" | ||||
| 
 | ||||
| const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" | ||||
| 
 | ||||
| var bcEncoding = base64.NewEncoding(alphabet) | ||||
| 
 | ||||
| func base64Encode(src []byte) []byte { | ||||
| 	n := bcEncoding.EncodedLen(len(src)) | ||||
| 	dst := make([]byte, n) | ||||
| 	bcEncoding.Encode(dst, src) | ||||
| 	for dst[n-1] == '=' { | ||||
| 		n-- | ||||
| 	} | ||||
| 	return dst[:n] | ||||
| } | ||||
| 
 | ||||
| func base64Decode(src []byte) ([]byte, error) { | ||||
| 	numOfEquals := 4 - (len(src) % 4) | ||||
| 	for i := 0; i < numOfEquals; i++ { | ||||
| 		src = append(src, '=') | ||||
| 	} | ||||
| 
 | ||||
| 	dst := make([]byte, bcEncoding.DecodedLen(len(src))) | ||||
| 	n, err := bcEncoding.Decode(dst, src) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return dst[:n], nil | ||||
| } | ||||
|  | @ -0,0 +1,295 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
 | ||||
| // algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
 | ||||
| package bcrypt // import "golang.org/x/crypto/bcrypt"
 | ||||
| 
 | ||||
| // The code is a port of Provos and Mazières's C implementation.
 | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"crypto/subtle" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"golang.org/x/crypto/blowfish" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	MinCost     int = 4  // the minimum allowable cost as passed in to GenerateFromPassword
 | ||||
| 	MaxCost     int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
 | ||||
| 	DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
 | ||||
| ) | ||||
| 
 | ||||
| // The error returned from CompareHashAndPassword when a password and hash do
 | ||||
| // not match.
 | ||||
| var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") | ||||
| 
 | ||||
| // The error returned from CompareHashAndPassword when a hash is too short to
 | ||||
| // be a bcrypt hash.
 | ||||
| var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") | ||||
| 
 | ||||
| // The error returned from CompareHashAndPassword when a hash was created with
 | ||||
| // a bcrypt algorithm newer than this implementation.
 | ||||
| type HashVersionTooNewError byte | ||||
| 
 | ||||
| func (hv HashVersionTooNewError) Error() string { | ||||
| 	return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) | ||||
| } | ||||
| 
 | ||||
| // The error returned from CompareHashAndPassword when a hash starts with something other than '$'
 | ||||
| type InvalidHashPrefixError byte | ||||
| 
 | ||||
| func (ih InvalidHashPrefixError) Error() string { | ||||
| 	return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) | ||||
| } | ||||
| 
 | ||||
| type InvalidCostError int | ||||
| 
 | ||||
| func (ic InvalidCostError) Error() string { | ||||
| 	return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	majorVersion       = '2' | ||||
| 	minorVersion       = 'a' | ||||
| 	maxSaltSize        = 16 | ||||
| 	maxCryptedHashSize = 23 | ||||
| 	encodedSaltSize    = 22 | ||||
| 	encodedHashSize    = 31 | ||||
| 	minHashSize        = 59 | ||||
| ) | ||||
| 
 | ||||
| // magicCipherData is an IV for the 64 Blowfish encryption calls in
 | ||||
| // bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
 | ||||
| var magicCipherData = []byte{ | ||||
| 	0x4f, 0x72, 0x70, 0x68, | ||||
| 	0x65, 0x61, 0x6e, 0x42, | ||||
| 	0x65, 0x68, 0x6f, 0x6c, | ||||
| 	0x64, 0x65, 0x72, 0x53, | ||||
| 	0x63, 0x72, 0x79, 0x44, | ||||
| 	0x6f, 0x75, 0x62, 0x74, | ||||
| } | ||||
| 
 | ||||
| type hashed struct { | ||||
| 	hash  []byte | ||||
| 	salt  []byte | ||||
| 	cost  int // allowed range is MinCost to MaxCost
 | ||||
| 	major byte | ||||
| 	minor byte | ||||
| } | ||||
| 
 | ||||
| // GenerateFromPassword returns the bcrypt hash of the password at the given
 | ||||
| // cost. If the cost given is less than MinCost, the cost will be set to
 | ||||
| // DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
 | ||||
| // to compare the returned hashed password with its cleartext version.
 | ||||
| func GenerateFromPassword(password []byte, cost int) ([]byte, error) { | ||||
| 	p, err := newFromPassword(password, cost) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return p.Hash(), nil | ||||
| } | ||||
| 
 | ||||
| // CompareHashAndPassword compares a bcrypt hashed password with its possible
 | ||||
| // plaintext equivalent. Returns nil on success, or an error on failure.
 | ||||
| func CompareHashAndPassword(hashedPassword, password []byte) error { | ||||
| 	p, err := newFromHash(hashedPassword) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	otherHash, err := bcrypt(password, p.cost, p.salt) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} | ||||
| 	if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return ErrMismatchedHashAndPassword | ||||
| } | ||||
| 
 | ||||
| // Cost returns the hashing cost used to create the given hashed
 | ||||
| // password. When, in the future, the hashing cost of a password system needs
 | ||||
| // to be increased in order to adjust for greater computational power, this
 | ||||
| // function allows one to establish which passwords need to be updated.
 | ||||
| func Cost(hashedPassword []byte) (int, error) { | ||||
| 	p, err := newFromHash(hashedPassword) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return p.cost, nil | ||||
| } | ||||
| 
 | ||||
| func newFromPassword(password []byte, cost int) (*hashed, error) { | ||||
| 	if cost < MinCost { | ||||
| 		cost = DefaultCost | ||||
| 	} | ||||
| 	p := new(hashed) | ||||
| 	p.major = majorVersion | ||||
| 	p.minor = minorVersion | ||||
| 
 | ||||
| 	err := checkCost(cost) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	p.cost = cost | ||||
| 
 | ||||
| 	unencodedSalt := make([]byte, maxSaltSize) | ||||
| 	_, err = io.ReadFull(rand.Reader, unencodedSalt) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	p.salt = base64Encode(unencodedSalt) | ||||
| 	hash, err := bcrypt(password, p.cost, p.salt) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	p.hash = hash | ||||
| 	return p, err | ||||
| } | ||||
| 
 | ||||
| func newFromHash(hashedSecret []byte) (*hashed, error) { | ||||
| 	if len(hashedSecret) < minHashSize { | ||||
| 		return nil, ErrHashTooShort | ||||
| 	} | ||||
| 	p := new(hashed) | ||||
| 	n, err := p.decodeVersion(hashedSecret) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	hashedSecret = hashedSecret[n:] | ||||
| 	n, err = p.decodeCost(hashedSecret) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	hashedSecret = hashedSecret[n:] | ||||
| 
 | ||||
| 	// The "+2" is here because we'll have to append at most 2 '=' to the salt
 | ||||
| 	// when base64 decoding it in expensiveBlowfishSetup().
 | ||||
| 	p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) | ||||
| 	copy(p.salt, hashedSecret[:encodedSaltSize]) | ||||
| 
 | ||||
| 	hashedSecret = hashedSecret[encodedSaltSize:] | ||||
| 	p.hash = make([]byte, len(hashedSecret)) | ||||
| 	copy(p.hash, hashedSecret) | ||||
| 
 | ||||
| 	return p, nil | ||||
| } | ||||
| 
 | ||||
| func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { | ||||
| 	cipherData := make([]byte, len(magicCipherData)) | ||||
| 	copy(cipherData, magicCipherData) | ||||
| 
 | ||||
| 	c, err := expensiveBlowfishSetup(password, uint32(cost), salt) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < 24; i += 8 { | ||||
| 		for j := 0; j < 64; j++ { | ||||
| 			c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Bug compatibility with C bcrypt implementations. We only encode 23 of
 | ||||
| 	// the 24 bytes encrypted.
 | ||||
| 	hsh := base64Encode(cipherData[:maxCryptedHashSize]) | ||||
| 	return hsh, nil | ||||
| } | ||||
| 
 | ||||
| func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { | ||||
| 	csalt, err := base64Decode(salt) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Bug compatibility with C bcrypt implementations. They use the trailing
 | ||||
| 	// NULL in the key string during expansion.
 | ||||
| 	// We copy the key to prevent changing the underlying array.
 | ||||
| 	ckey := append(key[:len(key):len(key)], 0) | ||||
| 
 | ||||
| 	c, err := blowfish.NewSaltedCipher(ckey, csalt) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var i, rounds uint64 | ||||
| 	rounds = 1 << cost | ||||
| 	for i = 0; i < rounds; i++ { | ||||
| 		blowfish.ExpandKey(ckey, c) | ||||
| 		blowfish.ExpandKey(csalt, c) | ||||
| 	} | ||||
| 
 | ||||
| 	return c, nil | ||||
| } | ||||
| 
 | ||||
| func (p *hashed) Hash() []byte { | ||||
| 	arr := make([]byte, 60) | ||||
| 	arr[0] = '$' | ||||
| 	arr[1] = p.major | ||||
| 	n := 2 | ||||
| 	if p.minor != 0 { | ||||
| 		arr[2] = p.minor | ||||
| 		n = 3 | ||||
| 	} | ||||
| 	arr[n] = '$' | ||||
| 	n++ | ||||
| 	copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) | ||||
| 	n += 2 | ||||
| 	arr[n] = '$' | ||||
| 	n++ | ||||
| 	copy(arr[n:], p.salt) | ||||
| 	n += encodedSaltSize | ||||
| 	copy(arr[n:], p.hash) | ||||
| 	n += encodedHashSize | ||||
| 	return arr[:n] | ||||
| } | ||||
| 
 | ||||
| func (p *hashed) decodeVersion(sbytes []byte) (int, error) { | ||||
| 	if sbytes[0] != '$' { | ||||
| 		return -1, InvalidHashPrefixError(sbytes[0]) | ||||
| 	} | ||||
| 	if sbytes[1] > majorVersion { | ||||
| 		return -1, HashVersionTooNewError(sbytes[1]) | ||||
| 	} | ||||
| 	p.major = sbytes[1] | ||||
| 	n := 3 | ||||
| 	if sbytes[2] != '$' { | ||||
| 		p.minor = sbytes[2] | ||||
| 		n++ | ||||
| 	} | ||||
| 	return n, nil | ||||
| } | ||||
| 
 | ||||
| // sbytes should begin where decodeVersion left off.
 | ||||
| func (p *hashed) decodeCost(sbytes []byte) (int, error) { | ||||
| 	cost, err := strconv.Atoi(string(sbytes[0:2])) | ||||
| 	if err != nil { | ||||
| 		return -1, err | ||||
| 	} | ||||
| 	err = checkCost(cost) | ||||
| 	if err != nil { | ||||
| 		return -1, err | ||||
| 	} | ||||
| 	p.cost = cost | ||||
| 	return 3, nil | ||||
| } | ||||
| 
 | ||||
| func (p *hashed) String() string { | ||||
| 	return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) | ||||
| } | ||||
| 
 | ||||
| func checkCost(cost int) error { | ||||
| 	if cost < MinCost || cost > MaxCost { | ||||
| 		return InvalidCostError(cost) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,159 @@ | |||
| // Copyright 2010 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package blowfish | ||||
| 
 | ||||
| // getNextWord returns the next big-endian uint32 value from the byte slice
 | ||||
| // at the given position in a circular manner, updating the position.
 | ||||
| func getNextWord(b []byte, pos *int) uint32 { | ||||
| 	var w uint32 | ||||
| 	j := *pos | ||||
| 	for i := 0; i < 4; i++ { | ||||
| 		w = w<<8 | uint32(b[j]) | ||||
| 		j++ | ||||
| 		if j >= len(b) { | ||||
| 			j = 0 | ||||
| 		} | ||||
| 	} | ||||
| 	*pos = j | ||||
| 	return w | ||||
| } | ||||
| 
 | ||||
| // ExpandKey performs a key expansion on the given *Cipher. Specifically, it
 | ||||
| // performs the Blowfish algorithm's key schedule which sets up the *Cipher's
 | ||||
| // pi and substitution tables for calls to Encrypt. This is used, primarily,
 | ||||
| // by the bcrypt package to reuse the Blowfish key schedule during its
 | ||||
| // set up. It's unlikely that you need to use this directly.
 | ||||
| func ExpandKey(key []byte, c *Cipher) { | ||||
| 	j := 0 | ||||
| 	for i := 0; i < 18; i++ { | ||||
| 		// Using inlined getNextWord for performance.
 | ||||
| 		var d uint32 | ||||
| 		for k := 0; k < 4; k++ { | ||||
| 			d = d<<8 | uint32(key[j]) | ||||
| 			j++ | ||||
| 			if j >= len(key) { | ||||
| 				j = 0 | ||||
| 			} | ||||
| 		} | ||||
| 		c.p[i] ^= d | ||||
| 	} | ||||
| 
 | ||||
| 	var l, r uint32 | ||||
| 	for i := 0; i < 18; i += 2 { | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.p[i], c.p[i+1] = l, r | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s0[i], c.s0[i+1] = l, r | ||||
| 	} | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s1[i], c.s1[i+1] = l, r | ||||
| 	} | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s2[i], c.s2[i+1] = l, r | ||||
| 	} | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s3[i], c.s3[i+1] = l, r | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // This is similar to ExpandKey, but folds the salt during the key
 | ||||
| // schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
 | ||||
| // salt passed in, reusing ExpandKey turns out to be a place of inefficiency
 | ||||
| // and specializing it here is useful.
 | ||||
| func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { | ||||
| 	j := 0 | ||||
| 	for i := 0; i < 18; i++ { | ||||
| 		c.p[i] ^= getNextWord(key, &j) | ||||
| 	} | ||||
| 
 | ||||
| 	j = 0 | ||||
| 	var l, r uint32 | ||||
| 	for i := 0; i < 18; i += 2 { | ||||
| 		l ^= getNextWord(salt, &j) | ||||
| 		r ^= getNextWord(salt, &j) | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.p[i], c.p[i+1] = l, r | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l ^= getNextWord(salt, &j) | ||||
| 		r ^= getNextWord(salt, &j) | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s0[i], c.s0[i+1] = l, r | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l ^= getNextWord(salt, &j) | ||||
| 		r ^= getNextWord(salt, &j) | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s1[i], c.s1[i+1] = l, r | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l ^= getNextWord(salt, &j) | ||||
| 		r ^= getNextWord(salt, &j) | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s2[i], c.s2[i+1] = l, r | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < 256; i += 2 { | ||||
| 		l ^= getNextWord(salt, &j) | ||||
| 		r ^= getNextWord(salt, &j) | ||||
| 		l, r = encryptBlock(l, r, c) | ||||
| 		c.s3[i], c.s3[i+1] = l, r | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { | ||||
| 	xl, xr := l, r | ||||
| 	xl ^= c.p[0] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] | ||||
| 	xr ^= c.p[17] | ||||
| 	return xr, xl | ||||
| } | ||||
| 
 | ||||
| func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { | ||||
| 	xl, xr := l, r | ||||
| 	xl ^= c.p[17] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] | ||||
| 	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] | ||||
| 	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] | ||||
| 	xr ^= c.p[0] | ||||
| 	return xr, xl | ||||
| } | ||||
|  | @ -0,0 +1,99 @@ | |||
| // Copyright 2010 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
 | ||||
| //
 | ||||
| // Blowfish is a legacy cipher and its short block size makes it vulnerable to
 | ||||
| // birthday bound attacks (see https://sweet32.info). It should only be used
 | ||||
| // where compatibility with legacy systems, not security, is the goal.
 | ||||
| //
 | ||||
| // Deprecated: any new system should use AES (from crypto/aes, if necessary in
 | ||||
| // an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
 | ||||
| // golang.org/x/crypto/chacha20poly1305).
 | ||||
| package blowfish // import "golang.org/x/crypto/blowfish"
 | ||||
| 
 | ||||
| // The code is a port of Bruce Schneier's C implementation.
 | ||||
| // See https://www.schneier.com/blowfish.html.
 | ||||
| 
 | ||||
| import "strconv" | ||||
| 
 | ||||
| // The Blowfish block size in bytes.
 | ||||
| const BlockSize = 8 | ||||
| 
 | ||||
| // A Cipher is an instance of Blowfish encryption using a particular key.
 | ||||
| type Cipher struct { | ||||
| 	p              [18]uint32 | ||||
| 	s0, s1, s2, s3 [256]uint32 | ||||
| } | ||||
| 
 | ||||
| type KeySizeError int | ||||
| 
 | ||||
| func (k KeySizeError) Error() string { | ||||
| 	return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) | ||||
| } | ||||
| 
 | ||||
| // NewCipher creates and returns a Cipher.
 | ||||
| // The key argument should be the Blowfish key, from 1 to 56 bytes.
 | ||||
| func NewCipher(key []byte) (*Cipher, error) { | ||||
| 	var result Cipher | ||||
| 	if k := len(key); k < 1 || k > 56 { | ||||
| 		return nil, KeySizeError(k) | ||||
| 	} | ||||
| 	initCipher(&result) | ||||
| 	ExpandKey(key, &result) | ||||
| 	return &result, nil | ||||
| } | ||||
| 
 | ||||
| // NewSaltedCipher creates a returns a Cipher that folds a salt into its key
 | ||||
| // schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
 | ||||
| // sufficient and desirable. For bcrypt compatibility, the key can be over 56
 | ||||
| // bytes.
 | ||||
| func NewSaltedCipher(key, salt []byte) (*Cipher, error) { | ||||
| 	if len(salt) == 0 { | ||||
| 		return NewCipher(key) | ||||
| 	} | ||||
| 	var result Cipher | ||||
| 	if k := len(key); k < 1 { | ||||
| 		return nil, KeySizeError(k) | ||||
| 	} | ||||
| 	initCipher(&result) | ||||
| 	expandKeyWithSalt(key, salt, &result) | ||||
| 	return &result, nil | ||||
| } | ||||
| 
 | ||||
| // BlockSize returns the Blowfish block size, 8 bytes.
 | ||||
| // It is necessary to satisfy the Block interface in the
 | ||||
| // package "crypto/cipher".
 | ||||
| func (c *Cipher) BlockSize() int { return BlockSize } | ||||
| 
 | ||||
| // Encrypt encrypts the 8-byte buffer src using the key k
 | ||||
| // and stores the result in dst.
 | ||||
| // Note that for amounts of data larger than a block,
 | ||||
| // it is not safe to just call Encrypt on successive blocks;
 | ||||
| // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
 | ||||
| func (c *Cipher) Encrypt(dst, src []byte) { | ||||
| 	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) | ||||
| 	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) | ||||
| 	l, r = encryptBlock(l, r, c) | ||||
| 	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) | ||||
| 	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) | ||||
| } | ||||
| 
 | ||||
| // Decrypt decrypts the 8-byte buffer src using the key k
 | ||||
| // and stores the result in dst.
 | ||||
| func (c *Cipher) Decrypt(dst, src []byte) { | ||||
| 	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) | ||||
| 	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) | ||||
| 	l, r = decryptBlock(l, r, c) | ||||
| 	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) | ||||
| 	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) | ||||
| } | ||||
| 
 | ||||
| func initCipher(c *Cipher) { | ||||
| 	copy(c.p[0:], p[0:]) | ||||
| 	copy(c.s0[0:], s0[0:]) | ||||
| 	copy(c.s1[0:], s1[0:]) | ||||
| 	copy(c.s2[0:], s2[0:]) | ||||
| 	copy(c.s3[0:], s3[0:]) | ||||
| } | ||||
|  | @ -0,0 +1,199 @@ | |||
| // Copyright 2010 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.
 | ||||
| 
 | ||||
| // The startup permutation array and substitution boxes.
 | ||||
| // They are the hexadecimal digits of PI; see:
 | ||||
| // https://www.schneier.com/code/constants.txt.
 | ||||
| 
 | ||||
| package blowfish | ||||
| 
 | ||||
| var s0 = [256]uint32{ | ||||
| 	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, | ||||
| 	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, | ||||
| 	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, | ||||
| 	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, | ||||
| 	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, | ||||
| 	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, | ||||
| 	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, | ||||
| 	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, | ||||
| 	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, | ||||
| 	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, | ||||
| 	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, | ||||
| 	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, | ||||
| 	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, | ||||
| 	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, | ||||
| 	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, | ||||
| 	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, | ||||
| 	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, | ||||
| 	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, | ||||
| 	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, | ||||
| 	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, | ||||
| 	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, | ||||
| 	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, | ||||
| 	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, | ||||
| 	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, | ||||
| 	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, | ||||
| 	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, | ||||
| 	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, | ||||
| 	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, | ||||
| 	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, | ||||
| 	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, | ||||
| 	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, | ||||
| 	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, | ||||
| 	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, | ||||
| 	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, | ||||
| 	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, | ||||
| 	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, | ||||
| 	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, | ||||
| 	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, | ||||
| 	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, | ||||
| 	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, | ||||
| 	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, | ||||
| 	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, | ||||
| 	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, | ||||
| } | ||||
| 
 | ||||
| var s1 = [256]uint32{ | ||||
| 	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, | ||||
| 	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, | ||||
| 	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, | ||||
| 	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, | ||||
| 	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, | ||||
| 	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, | ||||
| 	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, | ||||
| 	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, | ||||
| 	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, | ||||
| 	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, | ||||
| 	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, | ||||
| 	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, | ||||
| 	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, | ||||
| 	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, | ||||
| 	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, | ||||
| 	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, | ||||
| 	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, | ||||
| 	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, | ||||
| 	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, | ||||
| 	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, | ||||
| 	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, | ||||
| 	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, | ||||
| 	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, | ||||
| 	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, | ||||
| 	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, | ||||
| 	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, | ||||
| 	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, | ||||
| 	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, | ||||
| 	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, | ||||
| 	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, | ||||
| 	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, | ||||
| 	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, | ||||
| 	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, | ||||
| 	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, | ||||
| 	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, | ||||
| 	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, | ||||
| 	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, | ||||
| 	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, | ||||
| 	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, | ||||
| 	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, | ||||
| 	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, | ||||
| 	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, | ||||
| 	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, | ||||
| } | ||||
| 
 | ||||
| var s2 = [256]uint32{ | ||||
| 	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, | ||||
| 	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, | ||||
| 	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, | ||||
| 	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, | ||||
| 	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, | ||||
| 	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, | ||||
| 	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, | ||||
| 	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, | ||||
| 	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, | ||||
| 	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, | ||||
| 	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, | ||||
| 	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, | ||||
| 	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, | ||||
| 	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, | ||||
| 	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, | ||||
| 	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, | ||||
| 	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, | ||||
| 	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, | ||||
| 	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, | ||||
| 	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, | ||||
| 	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, | ||||
| 	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, | ||||
| 	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, | ||||
| 	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, | ||||
| 	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, | ||||
| 	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, | ||||
| 	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, | ||||
| 	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, | ||||
| 	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, | ||||
| 	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, | ||||
| 	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, | ||||
| 	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, | ||||
| 	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, | ||||
| 	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, | ||||
| 	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, | ||||
| 	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, | ||||
| 	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, | ||||
| 	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, | ||||
| 	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, | ||||
| 	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, | ||||
| 	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, | ||||
| 	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, | ||||
| 	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, | ||||
| } | ||||
| 
 | ||||
| var s3 = [256]uint32{ | ||||
| 	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, | ||||
| 	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, | ||||
| 	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, | ||||
| 	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, | ||||
| 	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, | ||||
| 	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, | ||||
| 	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, | ||||
| 	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, | ||||
| 	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, | ||||
| 	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, | ||||
| 	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, | ||||
| 	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, | ||||
| 	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, | ||||
| 	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, | ||||
| 	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, | ||||
| 	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, | ||||
| 	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, | ||||
| 	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, | ||||
| 	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, | ||||
| 	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, | ||||
| 	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, | ||||
| 	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, | ||||
| 	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, | ||||
| 	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, | ||||
| 	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, | ||||
| 	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, | ||||
| 	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, | ||||
| 	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, | ||||
| 	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, | ||||
| 	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, | ||||
| 	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, | ||||
| 	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, | ||||
| 	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, | ||||
| 	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, | ||||
| 	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, | ||||
| 	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, | ||||
| 	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, | ||||
| 	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, | ||||
| 	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, | ||||
| 	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, | ||||
| 	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, | ||||
| 	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, | ||||
| 	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, | ||||
| } | ||||
| 
 | ||||
| var p = [18]uint32{ | ||||
| 	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, | ||||
| 	0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, | ||||
| 	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,8 @@ | |||
| // 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. | ||||
| 
 | ||||
| #include "textflag.h" | ||||
| 
 | ||||
| TEXT ·use(SB),NOSPLIT,$0 | ||||
| 	RET | ||||
|  | @ -0,0 +1,30 @@ | |||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| #include "textflag.h" | ||||
| 
 | ||||
| // | ||||
| // System call support for 386, Plan 9 | ||||
| // | ||||
| 
 | ||||
| // Just jump to package syscall's implementation for all these functions. | ||||
| // The runtime may know about them. | ||||
| 
 | ||||
| TEXT	·Syscall(SB),NOSPLIT,$0-32 | ||||
| 	JMP	syscall·Syscall(SB) | ||||
| 
 | ||||
| TEXT	·Syscall6(SB),NOSPLIT,$0-44 | ||||
| 	JMP	syscall·Syscall6(SB) | ||||
| 
 | ||||
| TEXT ·RawSyscall(SB),NOSPLIT,$0-28 | ||||
| 	JMP	syscall·RawSyscall(SB) | ||||
| 
 | ||||
| TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 | ||||
| 	JMP	syscall·RawSyscall6(SB) | ||||
| 
 | ||||
| TEXT ·seek(SB),NOSPLIT,$0-36 | ||||
| 	JMP	syscall·seek(SB) | ||||
| 
 | ||||
| TEXT ·exit(SB),NOSPLIT,$4-4 | ||||
| 	JMP	syscall·exit(SB) | ||||
|  | @ -0,0 +1,30 @@ | |||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| #include "textflag.h" | ||||
| 
 | ||||
| // | ||||
| // System call support for amd64, Plan 9 | ||||
| // | ||||
| 
 | ||||
| // Just jump to package syscall's implementation for all these functions. | ||||
| // The runtime may know about them. | ||||
| 
 | ||||
| TEXT	·Syscall(SB),NOSPLIT,$0-64 | ||||
| 	JMP	syscall·Syscall(SB) | ||||
| 
 | ||||
| TEXT	·Syscall6(SB),NOSPLIT,$0-88 | ||||
| 	JMP	syscall·Syscall6(SB) | ||||
| 
 | ||||
| TEXT ·RawSyscall(SB),NOSPLIT,$0-56 | ||||
| 	JMP	syscall·RawSyscall(SB) | ||||
| 
 | ||||
| TEXT	·RawSyscall6(SB),NOSPLIT,$0-80 | ||||
| 	JMP	syscall·RawSyscall6(SB) | ||||
| 
 | ||||
| TEXT ·seek(SB),NOSPLIT,$0-56 | ||||
| 	JMP	syscall·seek(SB) | ||||
| 
 | ||||
| TEXT ·exit(SB),NOSPLIT,$8-8 | ||||
| 	JMP	syscall·exit(SB) | ||||
|  | @ -0,0 +1,25 @@ | |||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| #include "textflag.h" | ||||
| 
 | ||||
| // System call support for plan9 on arm | ||||
| 
 | ||||
| // Just jump to package syscall's implementation for all these functions. | ||||
| // The runtime may know about them. | ||||
| 
 | ||||
| TEXT ·Syscall(SB),NOSPLIT,$0-32 | ||||
| 	JMP	syscall·Syscall(SB) | ||||
| 
 | ||||
| TEXT ·Syscall6(SB),NOSPLIT,$0-44 | ||||
| 	JMP	syscall·Syscall6(SB) | ||||
| 
 | ||||
| TEXT ·RawSyscall(SB),NOSPLIT,$0-28 | ||||
| 	JMP	syscall·RawSyscall(SB) | ||||
| 
 | ||||
| TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 | ||||
| 	JMP	syscall·RawSyscall6(SB) | ||||
| 
 | ||||
| TEXT ·seek(SB),NOSPLIT,$0-36 | ||||
| 	JMP	syscall·exit(SB) | ||||
|  | @ -0,0 +1,70 @@ | |||
| package plan9 | ||||
| 
 | ||||
| // Plan 9 Constants
 | ||||
| 
 | ||||
| // Open modes
 | ||||
| const ( | ||||
| 	O_RDONLY  = 0 | ||||
| 	O_WRONLY  = 1 | ||||
| 	O_RDWR    = 2 | ||||
| 	O_TRUNC   = 16 | ||||
| 	O_CLOEXEC = 32 | ||||
| 	O_EXCL    = 0x1000 | ||||
| ) | ||||
| 
 | ||||
| // Rfork flags
 | ||||
| const ( | ||||
| 	RFNAMEG  = 1 << 0 | ||||
| 	RFENVG   = 1 << 1 | ||||
| 	RFFDG    = 1 << 2 | ||||
| 	RFNOTEG  = 1 << 3 | ||||
| 	RFPROC   = 1 << 4 | ||||
| 	RFMEM    = 1 << 5 | ||||
| 	RFNOWAIT = 1 << 6 | ||||
| 	RFCNAMEG = 1 << 10 | ||||
| 	RFCENVG  = 1 << 11 | ||||
| 	RFCFDG   = 1 << 12 | ||||
| 	RFREND   = 1 << 13 | ||||
| 	RFNOMNT  = 1 << 14 | ||||
| ) | ||||
| 
 | ||||
| // Qid.Type bits
 | ||||
| const ( | ||||
| 	QTDIR    = 0x80 | ||||
| 	QTAPPEND = 0x40 | ||||
| 	QTEXCL   = 0x20 | ||||
| 	QTMOUNT  = 0x10 | ||||
| 	QTAUTH   = 0x08 | ||||
| 	QTTMP    = 0x04 | ||||
| 	QTFILE   = 0x00 | ||||
| ) | ||||
| 
 | ||||
| // Dir.Mode bits
 | ||||
| const ( | ||||
| 	DMDIR    = 0x80000000 | ||||
| 	DMAPPEND = 0x40000000 | ||||
| 	DMEXCL   = 0x20000000 | ||||
| 	DMMOUNT  = 0x10000000 | ||||
| 	DMAUTH   = 0x08000000 | ||||
| 	DMTMP    = 0x04000000 | ||||
| 	DMREAD   = 0x4 | ||||
| 	DMWRITE  = 0x2 | ||||
| 	DMEXEC   = 0x1 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	STATMAX    = 65535 | ||||
| 	ERRMAX     = 128 | ||||
| 	STATFIXLEN = 49 | ||||
| ) | ||||
| 
 | ||||
| // Mount and bind flags
 | ||||
| const ( | ||||
| 	MREPL   = 0x0000 | ||||
| 	MBEFORE = 0x0001 | ||||
| 	MAFTER  = 0x0002 | ||||
| 	MORDER  = 0x0003 | ||||
| 	MCREATE = 0x0004 | ||||
| 	MCACHE  = 0x0010 | ||||
| 	MMASK   = 0x0017 | ||||
| ) | ||||
|  | @ -0,0 +1,212 @@ | |||
| // Copyright 2012 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Plan 9 directory marshalling. See intro(5).
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import "errors" | ||||
| 
 | ||||
| var ( | ||||
| 	ErrShortStat = errors.New("stat buffer too short") | ||||
| 	ErrBadStat   = errors.New("malformed stat buffer") | ||||
| 	ErrBadName   = errors.New("bad character in file name") | ||||
| ) | ||||
| 
 | ||||
| // A Qid represents a 9P server's unique identification for a file.
 | ||||
| type Qid struct { | ||||
| 	Path uint64 // the file server's unique identification for the file
 | ||||
| 	Vers uint32 // version number for given Path
 | ||||
| 	Type uint8  // the type of the file (plan9.QTDIR for example)
 | ||||
| } | ||||
| 
 | ||||
| // A Dir contains the metadata for a file.
 | ||||
| type Dir struct { | ||||
| 	// system-modified data
 | ||||
| 	Type uint16 // server type
 | ||||
| 	Dev  uint32 // server subtype
 | ||||
| 
 | ||||
| 	// file data
 | ||||
| 	Qid    Qid    // unique id from server
 | ||||
| 	Mode   uint32 // permissions
 | ||||
| 	Atime  uint32 // last read time
 | ||||
| 	Mtime  uint32 // last write time
 | ||||
| 	Length int64  // file length
 | ||||
| 	Name   string // last element of path
 | ||||
| 	Uid    string // owner name
 | ||||
| 	Gid    string // group name
 | ||||
| 	Muid   string // last modifier name
 | ||||
| } | ||||
| 
 | ||||
| var nullDir = Dir{ | ||||
| 	Type: ^uint16(0), | ||||
| 	Dev:  ^uint32(0), | ||||
| 	Qid: Qid{ | ||||
| 		Path: ^uint64(0), | ||||
| 		Vers: ^uint32(0), | ||||
| 		Type: ^uint8(0), | ||||
| 	}, | ||||
| 	Mode:   ^uint32(0), | ||||
| 	Atime:  ^uint32(0), | ||||
| 	Mtime:  ^uint32(0), | ||||
| 	Length: ^int64(0), | ||||
| } | ||||
| 
 | ||||
| // Null assigns special "don't touch" values to members of d to
 | ||||
| // avoid modifying them during plan9.Wstat.
 | ||||
| func (d *Dir) Null() { *d = nullDir } | ||||
| 
 | ||||
| // Marshal encodes a 9P stat message corresponding to d into b
 | ||||
| //
 | ||||
| // If there isn't enough space in b for a stat message, ErrShortStat is returned.
 | ||||
| func (d *Dir) Marshal(b []byte) (n int, err error) { | ||||
| 	n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid) | ||||
| 	if n > len(b) { | ||||
| 		return n, ErrShortStat | ||||
| 	} | ||||
| 
 | ||||
| 	for _, c := range d.Name { | ||||
| 		if c == '/' { | ||||
| 			return n, ErrBadName | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	b = pbit16(b, uint16(n)-2) | ||||
| 	b = pbit16(b, d.Type) | ||||
| 	b = pbit32(b, d.Dev) | ||||
| 	b = pbit8(b, d.Qid.Type) | ||||
| 	b = pbit32(b, d.Qid.Vers) | ||||
| 	b = pbit64(b, d.Qid.Path) | ||||
| 	b = pbit32(b, d.Mode) | ||||
| 	b = pbit32(b, d.Atime) | ||||
| 	b = pbit32(b, d.Mtime) | ||||
| 	b = pbit64(b, uint64(d.Length)) | ||||
| 	b = pstring(b, d.Name) | ||||
| 	b = pstring(b, d.Uid) | ||||
| 	b = pstring(b, d.Gid) | ||||
| 	b = pstring(b, d.Muid) | ||||
| 
 | ||||
| 	return n, nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
 | ||||
| //
 | ||||
| // If b is too small to hold a valid stat message, ErrShortStat is returned.
 | ||||
| //
 | ||||
| // If the stat message itself is invalid, ErrBadStat is returned.
 | ||||
| func UnmarshalDir(b []byte) (*Dir, error) { | ||||
| 	if len(b) < STATFIXLEN { | ||||
| 		return nil, ErrShortStat | ||||
| 	} | ||||
| 	size, buf := gbit16(b) | ||||
| 	if len(b) != int(size)+2 { | ||||
| 		return nil, ErrBadStat | ||||
| 	} | ||||
| 	b = buf | ||||
| 
 | ||||
| 	var d Dir | ||||
| 	d.Type, b = gbit16(b) | ||||
| 	d.Dev, b = gbit32(b) | ||||
| 	d.Qid.Type, b = gbit8(b) | ||||
| 	d.Qid.Vers, b = gbit32(b) | ||||
| 	d.Qid.Path, b = gbit64(b) | ||||
| 	d.Mode, b = gbit32(b) | ||||
| 	d.Atime, b = gbit32(b) | ||||
| 	d.Mtime, b = gbit32(b) | ||||
| 
 | ||||
| 	n, b := gbit64(b) | ||||
| 	d.Length = int64(n) | ||||
| 
 | ||||
| 	var ok bool | ||||
| 	if d.Name, b, ok = gstring(b); !ok { | ||||
| 		return nil, ErrBadStat | ||||
| 	} | ||||
| 	if d.Uid, b, ok = gstring(b); !ok { | ||||
| 		return nil, ErrBadStat | ||||
| 	} | ||||
| 	if d.Gid, b, ok = gstring(b); !ok { | ||||
| 		return nil, ErrBadStat | ||||
| 	} | ||||
| 	if d.Muid, b, ok = gstring(b); !ok { | ||||
| 		return nil, ErrBadStat | ||||
| 	} | ||||
| 
 | ||||
| 	return &d, nil | ||||
| } | ||||
| 
 | ||||
| // pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
 | ||||
| func pbit8(b []byte, v uint8) []byte { | ||||
| 	b[0] = byte(v) | ||||
| 	return b[1:] | ||||
| } | ||||
| 
 | ||||
| // pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
 | ||||
| func pbit16(b []byte, v uint16) []byte { | ||||
| 	b[0] = byte(v) | ||||
| 	b[1] = byte(v >> 8) | ||||
| 	return b[2:] | ||||
| } | ||||
| 
 | ||||
| // pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
 | ||||
| func pbit32(b []byte, v uint32) []byte { | ||||
| 	b[0] = byte(v) | ||||
| 	b[1] = byte(v >> 8) | ||||
| 	b[2] = byte(v >> 16) | ||||
| 	b[3] = byte(v >> 24) | ||||
| 	return b[4:] | ||||
| } | ||||
| 
 | ||||
| // pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
 | ||||
| func pbit64(b []byte, v uint64) []byte { | ||||
| 	b[0] = byte(v) | ||||
| 	b[1] = byte(v >> 8) | ||||
| 	b[2] = byte(v >> 16) | ||||
| 	b[3] = byte(v >> 24) | ||||
| 	b[4] = byte(v >> 32) | ||||
| 	b[5] = byte(v >> 40) | ||||
| 	b[6] = byte(v >> 48) | ||||
| 	b[7] = byte(v >> 56) | ||||
| 	return b[8:] | ||||
| } | ||||
| 
 | ||||
| // pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
 | ||||
| // returning the remaining slice of b..
 | ||||
| func pstring(b []byte, s string) []byte { | ||||
| 	b = pbit16(b, uint16(len(s))) | ||||
| 	n := copy(b, s) | ||||
| 	return b[n:] | ||||
| } | ||||
| 
 | ||||
| // gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
 | ||||
| func gbit8(b []byte) (uint8, []byte) { | ||||
| 	return uint8(b[0]), b[1:] | ||||
| } | ||||
| 
 | ||||
| // gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
 | ||||
| func gbit16(b []byte) (uint16, []byte) { | ||||
| 	return uint16(b[0]) | uint16(b[1])<<8, b[2:] | ||||
| } | ||||
| 
 | ||||
| // gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
 | ||||
| func gbit32(b []byte) (uint32, []byte) { | ||||
| 	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:] | ||||
| } | ||||
| 
 | ||||
| // gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
 | ||||
| func gbit64(b []byte) (uint64, []byte) { | ||||
| 	lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 | ||||
| 	hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24 | ||||
| 	return uint64(lo) | uint64(hi)<<32, b[8:] | ||||
| } | ||||
| 
 | ||||
| // gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
 | ||||
| // It returns the string with the remaining slice of b and a boolean. If the length is
 | ||||
| // greater than the number of bytes in b, the boolean will be false.
 | ||||
| func gstring(b []byte) (string, []byte, bool) { | ||||
| 	n, b := gbit16(b) | ||||
| 	if int(n) > len(b) { | ||||
| 		return "", b, false | ||||
| 	} | ||||
| 	return string(b[:n]), b[n:], true | ||||
| } | ||||
|  | @ -0,0 +1,31 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Plan 9 environment variables.
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| func Getenv(key string) (value string, found bool) { | ||||
| 	return syscall.Getenv(key) | ||||
| } | ||||
| 
 | ||||
| func Setenv(key, value string) error { | ||||
| 	return syscall.Setenv(key, value) | ||||
| } | ||||
| 
 | ||||
| func Clearenv() { | ||||
| 	syscall.Clearenv() | ||||
| } | ||||
| 
 | ||||
| func Environ() []string { | ||||
| 	return syscall.Environ() | ||||
| } | ||||
| 
 | ||||
| func Unsetenv(key string) error { | ||||
| 	return syscall.Unsetenv(key) | ||||
| } | ||||
|  | @ -0,0 +1,50 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import "syscall" | ||||
| 
 | ||||
| // Constants
 | ||||
| const ( | ||||
| 	// Invented values to support what package os expects.
 | ||||
| 	O_CREAT    = 0x02000 | ||||
| 	O_APPEND   = 0x00400 | ||||
| 	O_NOCTTY   = 0x00000 | ||||
| 	O_NONBLOCK = 0x00000 | ||||
| 	O_SYNC     = 0x00000 | ||||
| 	O_ASYNC    = 0x00000 | ||||
| 
 | ||||
| 	S_IFMT   = 0x1f000 | ||||
| 	S_IFIFO  = 0x1000 | ||||
| 	S_IFCHR  = 0x2000 | ||||
| 	S_IFDIR  = 0x4000 | ||||
| 	S_IFBLK  = 0x6000 | ||||
| 	S_IFREG  = 0x8000 | ||||
| 	S_IFLNK  = 0xa000 | ||||
| 	S_IFSOCK = 0xc000 | ||||
| ) | ||||
| 
 | ||||
| // Errors
 | ||||
| var ( | ||||
| 	EINVAL       = syscall.NewError("bad arg in system call") | ||||
| 	ENOTDIR      = syscall.NewError("not a directory") | ||||
| 	EISDIR       = syscall.NewError("file is a directory") | ||||
| 	ENOENT       = syscall.NewError("file does not exist") | ||||
| 	EEXIST       = syscall.NewError("file already exists") | ||||
| 	EMFILE       = syscall.NewError("no free file descriptors") | ||||
| 	EIO          = syscall.NewError("i/o error") | ||||
| 	ENAMETOOLONG = syscall.NewError("file name too long") | ||||
| 	EINTR        = syscall.NewError("interrupted") | ||||
| 	EPERM        = syscall.NewError("permission denied") | ||||
| 	EBUSY        = syscall.NewError("no free devices") | ||||
| 	ETIMEDOUT    = syscall.NewError("connection timed out") | ||||
| 	EPLAN9       = syscall.NewError("not supported by plan 9") | ||||
| 
 | ||||
| 	// The following errors do not correspond to any
 | ||||
| 	// Plan 9 system messages. Invented to support
 | ||||
| 	// what package os and others expect.
 | ||||
| 	EACCES       = syscall.NewError("access permission denied") | ||||
| 	EAFNOSUPPORT = syscall.NewError("address family not supported by protocol") | ||||
| ) | ||||
|  | @ -0,0 +1,150 @@ | |||
| #!/usr/bin/env bash | ||||
| # Copyright 2009 The Go Authors. All rights reserved. | ||||
| # Use of this source code is governed by a BSD-style | ||||
| # license that can be found in the LICENSE file. | ||||
| 
 | ||||
| # The plan9 package provides access to the raw system call | ||||
| # interface of the underlying operating system.  Porting Go to | ||||
| # a new architecture/operating system combination requires | ||||
| # some manual effort, though there are tools that automate | ||||
| # much of the process.  The auto-generated files have names | ||||
| # beginning with z. | ||||
| # | ||||
| # This script runs or (given -n) prints suggested commands to generate z files | ||||
| # for the current system.  Running those commands is not automatic. | ||||
| # This script is documentation more than anything else. | ||||
| # | ||||
| # * asm_${GOOS}_${GOARCH}.s | ||||
| # | ||||
| # This hand-written assembly file implements system call dispatch. | ||||
| # There are three entry points: | ||||
| # | ||||
| # 	func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr); | ||||
| # 	func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); | ||||
| # 	func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr); | ||||
| # | ||||
| # The first and second are the standard ones; they differ only in | ||||
| # how many arguments can be passed to the kernel. | ||||
| # The third is for low-level use by the ForkExec wrapper; | ||||
| # unlike the first two, it does not call into the scheduler to | ||||
| # let it know that a system call is running. | ||||
| # | ||||
| # * syscall_${GOOS}.go | ||||
| # | ||||
| # This hand-written Go file implements system calls that need | ||||
| # special handling and lists "//sys" comments giving prototypes | ||||
| # for ones that can be auto-generated.  Mksyscall reads those | ||||
| # comments to generate the stubs. | ||||
| # | ||||
| # * syscall_${GOOS}_${GOARCH}.go | ||||
| # | ||||
| # Same as syscall_${GOOS}.go except that it contains code specific | ||||
| # to ${GOOS} on one particular architecture. | ||||
| # | ||||
| # * types_${GOOS}.c | ||||
| # | ||||
| # This hand-written C file includes standard C headers and then | ||||
| # creates typedef or enum names beginning with a dollar sign | ||||
| # (use of $ in variable names is a gcc extension).  The hardest | ||||
| # part about preparing this file is figuring out which headers to | ||||
| # include and which symbols need to be #defined to get the | ||||
| # actual data structures that pass through to the kernel system calls. | ||||
| # Some C libraries present alternate versions for binary compatibility | ||||
| # and translate them on the way in and out of system calls, but | ||||
| # there is almost always a #define that can get the real ones. | ||||
| # See types_darwin.c and types_linux.c for examples. | ||||
| # | ||||
| # * zerror_${GOOS}_${GOARCH}.go | ||||
| # | ||||
| # This machine-generated file defines the system's error numbers, | ||||
| # error strings, and signal numbers.  The generator is "mkerrors.sh". | ||||
| # Usually no arguments are needed, but mkerrors.sh will pass its | ||||
| # arguments on to godefs. | ||||
| # | ||||
| # * zsyscall_${GOOS}_${GOARCH}.go | ||||
| # | ||||
| # Generated by mksyscall.pl; see syscall_${GOOS}.go above. | ||||
| # | ||||
| # * zsysnum_${GOOS}_${GOARCH}.go | ||||
| # | ||||
| # Generated by mksysnum_${GOOS}. | ||||
| # | ||||
| # * ztypes_${GOOS}_${GOARCH}.go | ||||
| # | ||||
| # Generated by godefs; see types_${GOOS}.c above. | ||||
| 
 | ||||
| GOOSARCH="${GOOS}_${GOARCH}" | ||||
| 
 | ||||
| # defaults | ||||
| mksyscall="go run mksyscall.go" | ||||
| mkerrors="./mkerrors.sh" | ||||
| zerrors="zerrors_$GOOSARCH.go" | ||||
| mksysctl="" | ||||
| zsysctl="zsysctl_$GOOSARCH.go" | ||||
| mksysnum= | ||||
| mktypes= | ||||
| run="sh" | ||||
| 
 | ||||
| case "$1" in | ||||
| -syscalls) | ||||
| 	for i in zsyscall*go | ||||
| 	do | ||||
| 		sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i | ||||
| 		rm _$i | ||||
| 	done | ||||
| 	exit 0 | ||||
| 	;; | ||||
| -n) | ||||
| 	run="cat" | ||||
| 	shift | ||||
| esac | ||||
| 
 | ||||
| case "$#" in | ||||
| 0) | ||||
| 	;; | ||||
| *) | ||||
| 	echo 'usage: mkall.sh [-n]' 1>&2 | ||||
| 	exit 2 | ||||
| esac | ||||
| 
 | ||||
| case "$GOOSARCH" in | ||||
| _* | *_ | _) | ||||
| 	echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 | ||||
| 	exit 1 | ||||
| 	;; | ||||
| plan9_386) | ||||
| 	mkerrors= | ||||
| 	mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,386" | ||||
| 	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h" | ||||
| 	mktypes="XXX" | ||||
| 	;; | ||||
| plan9_amd64) | ||||
| 	mkerrors= | ||||
| 	mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,amd64" | ||||
| 	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h" | ||||
| 	mktypes="XXX" | ||||
| 	;; | ||||
| plan9_arm) | ||||
| 	mkerrors= | ||||
| 	mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,arm" | ||||
| 	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h" | ||||
| 	mktypes="XXX" | ||||
| 	;; | ||||
| *) | ||||
| 	echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 | ||||
| 	exit 1 | ||||
| 	;; | ||||
| esac | ||||
| 
 | ||||
| ( | ||||
| 	if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi | ||||
| 	case "$GOOS" in | ||||
| 	plan9) | ||||
| 		syscall_goos="syscall_$GOOS.go" | ||||
| 		if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos |gofmt >zsyscall_$GOOSARCH.go"; fi | ||||
| 		;; | ||||
| 	esac | ||||
| 	if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi | ||||
| 	if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi | ||||
| 	if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi | ||||
| ) | $run | ||||
|  | @ -0,0 +1,246 @@ | |||
| #!/usr/bin/env bash | ||||
| # Copyright 2009 The Go Authors. All rights reserved. | ||||
| # Use of this source code is governed by a BSD-style | ||||
| # license that can be found in the LICENSE file. | ||||
| 
 | ||||
| # Generate Go code listing errors and other #defined constant | ||||
| # values (ENAMETOOLONG etc.), by asking the preprocessor | ||||
| # about the definitions. | ||||
| 
 | ||||
| unset LANG | ||||
| export LC_ALL=C | ||||
| export LC_CTYPE=C | ||||
| 
 | ||||
| CC=${CC:-gcc} | ||||
| 
 | ||||
| uname=$(uname) | ||||
| 
 | ||||
| includes=' | ||||
| #include <sys/types.h> | ||||
| #include <sys/file.h> | ||||
| #include <fcntl.h> | ||||
| #include <dirent.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <netinet/ip.h> | ||||
| #include <netinet/ip6.h> | ||||
| #include <netinet/tcp.h> | ||||
| #include <errno.h> | ||||
| #include <sys/signal.h> | ||||
| #include <signal.h> | ||||
| #include <sys/resource.h> | ||||
| ' | ||||
| 
 | ||||
| ccflags="$@" | ||||
| 
 | ||||
| # Write go tool cgo -godefs input. | ||||
| ( | ||||
| 	echo package plan9 | ||||
| 	echo | ||||
| 	echo '/*' | ||||
| 	indirect="includes_$(uname)" | ||||
| 	echo "${!indirect} $includes" | ||||
| 	echo '*/' | ||||
| 	echo 'import "C"' | ||||
| 	echo | ||||
| 	echo 'const (' | ||||
| 
 | ||||
| 	# The gcc command line prints all the #defines | ||||
| 	# it encounters while processing the input | ||||
| 	echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags | | ||||
| 	awk ' | ||||
| 		$1 != "#define" || $2 ~ /\(/ || $3 == "" {next} | ||||
| 
 | ||||
| 		$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next}  # 386 registers | ||||
| 		$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next} | ||||
| 		$2 ~ /^(SCM_SRCRT)$/ {next} | ||||
| 		$2 ~ /^(MAP_FAILED)$/ {next} | ||||
| 
 | ||||
| 		$2 !~ /^ETH_/ && | ||||
| 		$2 !~ /^EPROC_/ && | ||||
| 		$2 !~ /^EQUIV_/ && | ||||
| 		$2 !~ /^EXPR_/ && | ||||
| 		$2 ~ /^E[A-Z0-9_]+$/ || | ||||
| 		$2 ~ /^B[0-9_]+$/ || | ||||
| 		$2 ~ /^V[A-Z0-9]+$/ || | ||||
| 		$2 ~ /^CS[A-Z0-9]/ || | ||||
| 		$2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ || | ||||
| 		$2 ~ /^IGN/ || | ||||
| 		$2 ~ /^IX(ON|ANY|OFF)$/ || | ||||
| 		$2 ~ /^IN(LCR|PCK)$/ || | ||||
| 		$2 ~ /(^FLU?SH)|(FLU?SH$)/ || | ||||
| 		$2 ~ /^C(LOCAL|READ)$/ || | ||||
| 		$2 == "BRKINT" || | ||||
| 		$2 == "HUPCL" || | ||||
| 		$2 == "PENDIN" || | ||||
| 		$2 == "TOSTOP" || | ||||
| 		$2 ~ /^PAR/ || | ||||
| 		$2 ~ /^SIG[^_]/ || | ||||
| 		$2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ || | ||||
| 		$2 ~ /^IN_/ || | ||||
| 		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ || | ||||
| 		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || | ||||
| 		$2 == "ICMPV6_FILTER" || | ||||
| 		$2 == "SOMAXCONN" || | ||||
| 		$2 == "NAME_MAX" || | ||||
| 		$2 == "IFNAMSIZ" || | ||||
| 		$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ || | ||||
| 		$2 ~ /^SYSCTL_VERS/ || | ||||
| 		$2 ~ /^(MS|MNT)_/ || | ||||
| 		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || | ||||
| 		$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ || | ||||
| 		$2 ~ /^LINUX_REBOOT_CMD_/ || | ||||
| 		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || | ||||
| 		$2 !~ "NLA_TYPE_MASK" && | ||||
| 		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ || | ||||
| 		$2 ~ /^SIOC/ || | ||||
| 		$2 ~ /^TIOC/ || | ||||
| 		$2 !~ "RTF_BITS" && | ||||
| 		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || | ||||
| 		$2 ~ /^BIOC/ || | ||||
| 		$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || | ||||
| 		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ || | ||||
| 		$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || | ||||
| 		$2 ~ /^CLONE_[A-Z_]+/ || | ||||
| 		$2 !~ /^(BPF_TIMEVAL)$/ && | ||||
| 		$2 ~ /^(BPF|DLT)_/ || | ||||
| 		$2 !~ "WMESGLEN" && | ||||
| 		$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)} | ||||
| 		$2 ~ /^__WCOREFLAG$/ {next} | ||||
| 		$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} | ||||
| 
 | ||||
| 		{next} | ||||
| 	' | sort | ||||
| 
 | ||||
| 	echo ')' | ||||
| ) >_const.go | ||||
| 
 | ||||
| # Pull out the error names for later. | ||||
| errors=$( | ||||
| 	echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags | | ||||
| 	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' | | ||||
| 	sort | ||||
| ) | ||||
| 
 | ||||
| # Pull out the signal names for later. | ||||
| signals=$( | ||||
| 	echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | | ||||
| 	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | | ||||
| 	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | | ||||
| 	sort | ||||
| ) | ||||
| 
 | ||||
| # Again, writing regexps to a file. | ||||
| echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags | | ||||
| 	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' | | ||||
| 	sort >_error.grep | ||||
| echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | | ||||
| 	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | | ||||
| 	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | | ||||
| 	sort >_signal.grep | ||||
| 
 | ||||
| echo '// mkerrors.sh' "$@" | ||||
| echo '// Code generated by the command above; DO NOT EDIT.' | ||||
| echo | ||||
| go tool cgo -godefs -- "$@" _const.go >_error.out | ||||
| cat _error.out | grep -vf _error.grep | grep -vf _signal.grep | ||||
| echo | ||||
| echo '// Errors' | ||||
| echo 'const (' | ||||
| cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/' | ||||
| echo ')' | ||||
| 
 | ||||
| echo | ||||
| echo '// Signals' | ||||
| echo 'const (' | ||||
| cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/' | ||||
| echo ')' | ||||
| 
 | ||||
| # Run C program to print error and syscall strings. | ||||
| ( | ||||
| 	echo -E " | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <errno.h> | ||||
| #include <ctype.h> | ||||
| #include <string.h> | ||||
| #include <signal.h> | ||||
| 
 | ||||
| #define nelem(x) (sizeof(x)/sizeof((x)[0])) | ||||
| 
 | ||||
| enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below | ||||
| 
 | ||||
| int errors[] = { | ||||
| " | ||||
| 	for i in $errors | ||||
| 	do | ||||
| 		echo -E '	'$i, | ||||
| 	done | ||||
| 
 | ||||
| 	echo -E " | ||||
| }; | ||||
| 
 | ||||
| int signals[] = { | ||||
| " | ||||
| 	for i in $signals | ||||
| 	do | ||||
| 		echo -E '	'$i, | ||||
| 	done | ||||
| 
 | ||||
| 	# Use -E because on some systems bash builtin interprets \n itself. | ||||
| 	echo -E ' | ||||
| }; | ||||
| 
 | ||||
| static int | ||||
| intcmp(const void *a, const void *b) | ||||
| { | ||||
| 	return *(int*)a - *(int*)b; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| main(void) | ||||
| { | ||||
| 	int i, j, e; | ||||
| 	char buf[1024], *p; | ||||
| 
 | ||||
| 	printf("\n\n// Error table\n"); | ||||
| 	printf("var errors = [...]string {\n"); | ||||
| 	qsort(errors, nelem(errors), sizeof errors[0], intcmp); | ||||
| 	for(i=0; i<nelem(errors); i++) { | ||||
| 		e = errors[i]; | ||||
| 		if(i > 0 && errors[i-1] == e) | ||||
| 			continue; | ||||
| 		strcpy(buf, strerror(e)); | ||||
| 		// lowercase first letter: Bad -> bad, but STREAM -> STREAM. | ||||
| 		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) | ||||
| 			buf[0] += a - A; | ||||
| 		printf("\t%d: \"%s\",\n", e, buf); | ||||
| 	} | ||||
| 	printf("}\n\n"); | ||||
| 	 | ||||
| 	printf("\n\n// Signal table\n"); | ||||
| 	printf("var signals = [...]string {\n"); | ||||
| 	qsort(signals, nelem(signals), sizeof signals[0], intcmp); | ||||
| 	for(i=0; i<nelem(signals); i++) { | ||||
| 		e = signals[i]; | ||||
| 		if(i > 0 && signals[i-1] == e) | ||||
| 			continue; | ||||
| 		strcpy(buf, strsignal(e)); | ||||
| 		// lowercase first letter: Bad -> bad, but STREAM -> STREAM. | ||||
| 		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) | ||||
| 			buf[0] += a - A; | ||||
| 		// cut trailing : number. | ||||
| 		p = strrchr(buf, ":"[0]); | ||||
| 		if(p) | ||||
| 			*p = '\0'; | ||||
| 		printf("\t%d: \"%s\",\n", e, buf); | ||||
| 	} | ||||
| 	printf("}\n\n"); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| ' | ||||
| ) >_errors.c | ||||
| 
 | ||||
| $CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out | ||||
|  | @ -0,0 +1,23 @@ | |||
| #!/bin/sh | ||||
| # Copyright 2009 The Go Authors. All rights reserved. | ||||
| # Use of this source code is governed by a BSD-style | ||||
| # license that can be found in the LICENSE file. | ||||
| 
 | ||||
| COMMAND="mksysnum_plan9.sh $@" | ||||
| 
 | ||||
| cat <<EOF | ||||
| // $COMMAND | ||||
| // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| const( | ||||
| EOF | ||||
| 
 | ||||
| SP='[ 	]' # space or tab | ||||
| sed "s/^#define${SP}\\([A-Z0-9_][A-Z0-9_]*\\)${SP}${SP}*\\([0-9][0-9]*\\)/SYS_\\1=\\2/g" \ | ||||
| 	< $1 | grep -v SYS__ | ||||
| 
 | ||||
| cat <<EOF | ||||
| ) | ||||
| EOF | ||||
|  | @ -0,0 +1,21 @@ | |||
| // Copyright 2015 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.5
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import "syscall" | ||||
| 
 | ||||
| func fixwd() { | ||||
| 	syscall.Fixwd() | ||||
| } | ||||
| 
 | ||||
| func Getwd() (wd string, err error) { | ||||
| 	return syscall.Getwd() | ||||
| } | ||||
| 
 | ||||
| func Chdir(path string) error { | ||||
| 	return syscall.Chdir(path) | ||||
| } | ||||
|  | @ -0,0 +1,23 @@ | |||
| // Copyright 2015 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.5
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| func fixwd() { | ||||
| } | ||||
| 
 | ||||
| func Getwd() (wd string, err error) { | ||||
| 	fd, err := open(".", O_RDONLY) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	defer Close(fd) | ||||
| 	return Fd2path(fd) | ||||
| } | ||||
| 
 | ||||
| func Chdir(path string) error { | ||||
| 	return chdir(path) | ||||
| } | ||||
|  | @ -0,0 +1,30 @@ | |||
| // Copyright 2012 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // +build plan9,race
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import ( | ||||
| 	"runtime" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| const raceenabled = true | ||||
| 
 | ||||
| func raceAcquire(addr unsafe.Pointer) { | ||||
| 	runtime.RaceAcquire(addr) | ||||
| } | ||||
| 
 | ||||
| func raceReleaseMerge(addr unsafe.Pointer) { | ||||
| 	runtime.RaceReleaseMerge(addr) | ||||
| } | ||||
| 
 | ||||
| func raceReadRange(addr unsafe.Pointer, len int) { | ||||
| 	runtime.RaceReadRange(addr, len) | ||||
| } | ||||
| 
 | ||||
| func raceWriteRange(addr unsafe.Pointer, len int) { | ||||
| 	runtime.RaceWriteRange(addr, len) | ||||
| } | ||||
|  | @ -0,0 +1,25 @@ | |||
| // Copyright 2012 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // +build plan9,!race
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| const raceenabled = false | ||||
| 
 | ||||
| func raceAcquire(addr unsafe.Pointer) { | ||||
| } | ||||
| 
 | ||||
| func raceReleaseMerge(addr unsafe.Pointer) { | ||||
| } | ||||
| 
 | ||||
| func raceReadRange(addr unsafe.Pointer, len int) { | ||||
| } | ||||
| 
 | ||||
| func raceWriteRange(addr unsafe.Pointer, len int) { | ||||
| } | ||||
|  | @ -0,0 +1,22 @@ | |||
| // Copyright 2009 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // +build plan9
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| func itoa(val int) string { // do it here rather than with fmt to avoid dependency
 | ||||
| 	if val < 0 { | ||||
| 		return "-" + itoa(-val) | ||||
| 	} | ||||
| 	var buf [32]byte // big enough for int64
 | ||||
| 	i := len(buf) - 1 | ||||
| 	for val >= 10 { | ||||
| 		buf[i] = byte(val%10 + '0') | ||||
| 		i-- | ||||
| 		val /= 10 | ||||
| 	} | ||||
| 	buf[i] = byte(val + '0') | ||||
| 	return string(buf[i:]) | ||||
| } | ||||
|  | @ -0,0 +1,116 @@ | |||
| // Copyright 2009 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // +build plan9
 | ||||
| 
 | ||||
| // Package plan9 contains an interface to the low-level operating system
 | ||||
| // primitives. OS details vary depending on the underlying system, and
 | ||||
| // by default, godoc will display the OS-specific documentation for the current
 | ||||
| // system. If you want godoc to display documentation for another
 | ||||
| // system, set $GOOS and $GOARCH to the desired system. For example, if
 | ||||
| // you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
 | ||||
| // to freebsd and $GOARCH to arm.
 | ||||
| //
 | ||||
| // The primary use of this package is inside other packages that provide a more
 | ||||
| // portable interface to the system, such as "os", "time" and "net".  Use
 | ||||
| // those packages rather than this one if you can.
 | ||||
| //
 | ||||
| // For details of the functions and data types in this package consult
 | ||||
| // the manuals for the appropriate operating system.
 | ||||
| //
 | ||||
| // These calls return err == nil to indicate success; otherwise
 | ||||
| // err represents an operating system error describing the failure and
 | ||||
| // holds a value of type syscall.ErrorString.
 | ||||
| package plan9 // import "golang.org/x/sys/plan9"
 | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"strings" | ||||
| 	"unsafe" | ||||
| 
 | ||||
| 	"golang.org/x/sys/internal/unsafeheader" | ||||
| ) | ||||
| 
 | ||||
| // ByteSliceFromString returns a NUL-terminated slice of bytes
 | ||||
| // containing the text of s. If s contains a NUL byte at any
 | ||||
| // location, it returns (nil, EINVAL).
 | ||||
| func ByteSliceFromString(s string) ([]byte, error) { | ||||
| 	if strings.IndexByte(s, 0) != -1 { | ||||
| 		return nil, EINVAL | ||||
| 	} | ||||
| 	a := make([]byte, len(s)+1) | ||||
| 	copy(a, s) | ||||
| 	return a, nil | ||||
| } | ||||
| 
 | ||||
| // BytePtrFromString returns a pointer to a NUL-terminated array of
 | ||||
| // bytes containing the text of s. If s contains a NUL byte at any
 | ||||
| // location, it returns (nil, EINVAL).
 | ||||
| func BytePtrFromString(s string) (*byte, error) { | ||||
| 	a, err := ByteSliceFromString(s) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &a[0], nil | ||||
| } | ||||
| 
 | ||||
| // ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any
 | ||||
| // bytes after the NUL removed.
 | ||||
| func ByteSliceToString(s []byte) string { | ||||
| 	if i := bytes.IndexByte(s, 0); i != -1 { | ||||
| 		s = s[:i] | ||||
| 	} | ||||
| 	return string(s) | ||||
| } | ||||
| 
 | ||||
| // BytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
 | ||||
| // If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated
 | ||||
| // at a zero byte; if the zero byte is not present, the program may crash.
 | ||||
| func BytePtrToString(p *byte) string { | ||||
| 	if p == nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	if *p == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	// Find NUL terminator.
 | ||||
| 	n := 0 | ||||
| 	for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { | ||||
| 		ptr = unsafe.Pointer(uintptr(ptr) + 1) | ||||
| 	} | ||||
| 
 | ||||
| 	var s []byte | ||||
| 	h := (*unsafeheader.Slice)(unsafe.Pointer(&s)) | ||||
| 	h.Data = unsafe.Pointer(p) | ||||
| 	h.Len = n | ||||
| 	h.Cap = n | ||||
| 
 | ||||
| 	return string(s) | ||||
| } | ||||
| 
 | ||||
| // Single-word zero for use when we need a valid pointer to 0 bytes.
 | ||||
| // See mksyscall.pl.
 | ||||
| var _zero uintptr | ||||
| 
 | ||||
| func (ts *Timespec) Unix() (sec int64, nsec int64) { | ||||
| 	return int64(ts.Sec), int64(ts.Nsec) | ||||
| } | ||||
| 
 | ||||
| func (tv *Timeval) Unix() (sec int64, nsec int64) { | ||||
| 	return int64(tv.Sec), int64(tv.Usec) * 1000 | ||||
| } | ||||
| 
 | ||||
| func (ts *Timespec) Nano() int64 { | ||||
| 	return int64(ts.Sec)*1e9 + int64(ts.Nsec) | ||||
| } | ||||
| 
 | ||||
| func (tv *Timeval) Nano() int64 { | ||||
| 	return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 | ||||
| } | ||||
| 
 | ||||
| // use is a no-op, but the compiler cannot see that it is.
 | ||||
| // Calling use(p) ensures that p is kept live until that point.
 | ||||
| //go:noescape
 | ||||
| func use(p unsafe.Pointer) | ||||
|  | @ -0,0 +1,349 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Plan 9 system calls.
 | ||||
| // This file is compiled as ordinary Go code,
 | ||||
| // but it is also input to mksyscall,
 | ||||
| // which parses the //sys lines and generates system call stubs.
 | ||||
| // Note that sometimes we use a lowercase //sys name and
 | ||||
| // wrap it in our own nicer implementation.
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // A Note is a string describing a process note.
 | ||||
| // It implements the os.Signal interface.
 | ||||
| type Note string | ||||
| 
 | ||||
| func (n Note) Signal() {} | ||||
| 
 | ||||
| func (n Note) String() string { | ||||
| 	return string(n) | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	Stdin  = 0 | ||||
| 	Stdout = 1 | ||||
| 	Stderr = 2 | ||||
| ) | ||||
| 
 | ||||
| // For testing: clients can set this flag to force
 | ||||
| // creation of IPv6 sockets to return EAFNOSUPPORT.
 | ||||
| var SocketDisableIPv6 bool | ||||
| 
 | ||||
| func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString) | ||||
| func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString) | ||||
| func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) | ||||
| func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) | ||||
| 
 | ||||
| func atoi(b []byte) (n uint) { | ||||
| 	n = 0 | ||||
| 	for i := 0; i < len(b); i++ { | ||||
| 		n = n*10 + uint(b[i]-'0') | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func cstring(s []byte) string { | ||||
| 	i := bytes.IndexByte(s, 0) | ||||
| 	if i == -1 { | ||||
| 		i = len(s) | ||||
| 	} | ||||
| 	return string(s[:i]) | ||||
| } | ||||
| 
 | ||||
| func errstr() string { | ||||
| 	var buf [ERRMAX]byte | ||||
| 
 | ||||
| 	RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) | ||||
| 
 | ||||
| 	buf[len(buf)-1] = 0 | ||||
| 	return cstring(buf[:]) | ||||
| } | ||||
| 
 | ||||
| // Implemented in assembly to import from runtime.
 | ||||
| func exit(code int) | ||||
| 
 | ||||
| func Exit(code int) { exit(code) } | ||||
| 
 | ||||
| func readnum(path string) (uint, error) { | ||||
| 	var b [12]byte | ||||
| 
 | ||||
| 	fd, e := Open(path, O_RDONLY) | ||||
| 	if e != nil { | ||||
| 		return 0, e | ||||
| 	} | ||||
| 	defer Close(fd) | ||||
| 
 | ||||
| 	n, e := Pread(fd, b[:], 0) | ||||
| 
 | ||||
| 	if e != nil { | ||||
| 		return 0, e | ||||
| 	} | ||||
| 
 | ||||
| 	m := 0 | ||||
| 	for ; m < n && b[m] == ' '; m++ { | ||||
| 	} | ||||
| 
 | ||||
| 	return atoi(b[m : n-1]), nil | ||||
| } | ||||
| 
 | ||||
| func Getpid() (pid int) { | ||||
| 	n, _ := readnum("#c/pid") | ||||
| 	return int(n) | ||||
| } | ||||
| 
 | ||||
| func Getppid() (ppid int) { | ||||
| 	n, _ := readnum("#c/ppid") | ||||
| 	return int(n) | ||||
| } | ||||
| 
 | ||||
| func Read(fd int, p []byte) (n int, err error) { | ||||
| 	return Pread(fd, p, -1) | ||||
| } | ||||
| 
 | ||||
| func Write(fd int, p []byte) (n int, err error) { | ||||
| 	return Pwrite(fd, p, -1) | ||||
| } | ||||
| 
 | ||||
| var ioSync int64 | ||||
| 
 | ||||
| //sys	fd2path(fd int, buf []byte) (err error)
 | ||||
| func Fd2path(fd int) (path string, err error) { | ||||
| 	var buf [512]byte | ||||
| 
 | ||||
| 	e := fd2path(fd, buf[:]) | ||||
| 	if e != nil { | ||||
| 		return "", e | ||||
| 	} | ||||
| 	return cstring(buf[:]), nil | ||||
| } | ||||
| 
 | ||||
| //sys	pipe(p *[2]int32) (err error)
 | ||||
| func Pipe(p []int) (err error) { | ||||
| 	if len(p) != 2 { | ||||
| 		return syscall.ErrorString("bad arg in system call") | ||||
| 	} | ||||
| 	var pp [2]int32 | ||||
| 	err = pipe(&pp) | ||||
| 	p[0] = int(pp[0]) | ||||
| 	p[1] = int(pp[1]) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Underlying system call writes to newoffset via pointer.
 | ||||
| // Implemented in assembly to avoid allocation.
 | ||||
| func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string) | ||||
| 
 | ||||
| func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { | ||||
| 	newoffset, e := seek(0, fd, offset, whence) | ||||
| 
 | ||||
| 	if newoffset == -1 { | ||||
| 		err = syscall.ErrorString(e) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func Mkdir(path string, mode uint32) (err error) { | ||||
| 	fd, err := Create(path, O_RDONLY, DMDIR|mode) | ||||
| 
 | ||||
| 	if fd != -1 { | ||||
| 		Close(fd) | ||||
| 	} | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| type Waitmsg struct { | ||||
| 	Pid  int | ||||
| 	Time [3]uint32 | ||||
| 	Msg  string | ||||
| } | ||||
| 
 | ||||
| func (w Waitmsg) Exited() bool   { return true } | ||||
| func (w Waitmsg) Signaled() bool { return false } | ||||
| 
 | ||||
| func (w Waitmsg) ExitStatus() int { | ||||
| 	if len(w.Msg) == 0 { | ||||
| 		// a normal exit returns no message
 | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| //sys	await(s []byte) (n int, err error)
 | ||||
| func Await(w *Waitmsg) (err error) { | ||||
| 	var buf [512]byte | ||||
| 	var f [5][]byte | ||||
| 
 | ||||
| 	n, err := await(buf[:]) | ||||
| 
 | ||||
| 	if err != nil || w == nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	nf := 0 | ||||
| 	p := 0 | ||||
| 	for i := 0; i < n && nf < len(f)-1; i++ { | ||||
| 		if buf[i] == ' ' { | ||||
| 			f[nf] = buf[p:i] | ||||
| 			p = i + 1 | ||||
| 			nf++ | ||||
| 		} | ||||
| 	} | ||||
| 	f[nf] = buf[p:] | ||||
| 	nf++ | ||||
| 
 | ||||
| 	if nf != len(f) { | ||||
| 		return syscall.ErrorString("invalid wait message") | ||||
| 	} | ||||
| 	w.Pid = int(atoi(f[0])) | ||||
| 	w.Time[0] = uint32(atoi(f[1])) | ||||
| 	w.Time[1] = uint32(atoi(f[2])) | ||||
| 	w.Time[2] = uint32(atoi(f[3])) | ||||
| 	w.Msg = cstring(f[4]) | ||||
| 	if w.Msg == "''" { | ||||
| 		// await() returns '' for no error
 | ||||
| 		w.Msg = "" | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func Unmount(name, old string) (err error) { | ||||
| 	fixwd() | ||||
| 	oldp, err := BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	oldptr := uintptr(unsafe.Pointer(oldp)) | ||||
| 
 | ||||
| 	var r0 uintptr | ||||
| 	var e syscall.ErrorString | ||||
| 
 | ||||
| 	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
 | ||||
| 	if name == "" { | ||||
| 		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0) | ||||
| 	} else { | ||||
| 		namep, err := BytePtrFromString(name) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0) | ||||
| 	} | ||||
| 
 | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func Fchdir(fd int) (err error) { | ||||
| 	path, err := Fd2path(fd) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	return Chdir(path) | ||||
| } | ||||
| 
 | ||||
| type Timespec struct { | ||||
| 	Sec  int32 | ||||
| 	Nsec int32 | ||||
| } | ||||
| 
 | ||||
| type Timeval struct { | ||||
| 	Sec  int32 | ||||
| 	Usec int32 | ||||
| } | ||||
| 
 | ||||
| func NsecToTimeval(nsec int64) (tv Timeval) { | ||||
| 	nsec += 999 // round up to microsecond
 | ||||
| 	tv.Usec = int32(nsec % 1e9 / 1e3) | ||||
| 	tv.Sec = int32(nsec / 1e9) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func nsec() int64 { | ||||
| 	var scratch int64 | ||||
| 
 | ||||
| 	r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0) | ||||
| 	// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
 | ||||
| 	if r0 == 0 { | ||||
| 		return scratch | ||||
| 	} | ||||
| 	return int64(r0) | ||||
| } | ||||
| 
 | ||||
| func Gettimeofday(tv *Timeval) error { | ||||
| 	nsec := nsec() | ||||
| 	*tv = NsecToTimeval(nsec) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func Getpagesize() int { return 0x1000 } | ||||
| 
 | ||||
| func Getegid() (egid int) { return -1 } | ||||
| func Geteuid() (euid int) { return -1 } | ||||
| func Getgid() (gid int)   { return -1 } | ||||
| func Getuid() (uid int)   { return -1 } | ||||
| 
 | ||||
| func Getgroups() (gids []int, err error) { | ||||
| 	return make([]int, 0), nil | ||||
| } | ||||
| 
 | ||||
| //sys	open(path string, mode int) (fd int, err error)
 | ||||
| func Open(path string, mode int) (fd int, err error) { | ||||
| 	fixwd() | ||||
| 	return open(path, mode) | ||||
| } | ||||
| 
 | ||||
| //sys	create(path string, mode int, perm uint32) (fd int, err error)
 | ||||
| func Create(path string, mode int, perm uint32) (fd int, err error) { | ||||
| 	fixwd() | ||||
| 	return create(path, mode, perm) | ||||
| } | ||||
| 
 | ||||
| //sys	remove(path string) (err error)
 | ||||
| func Remove(path string) error { | ||||
| 	fixwd() | ||||
| 	return remove(path) | ||||
| } | ||||
| 
 | ||||
| //sys	stat(path string, edir []byte) (n int, err error)
 | ||||
| func Stat(path string, edir []byte) (n int, err error) { | ||||
| 	fixwd() | ||||
| 	return stat(path, edir) | ||||
| } | ||||
| 
 | ||||
| //sys	bind(name string, old string, flag int) (err error)
 | ||||
| func Bind(name string, old string, flag int) (err error) { | ||||
| 	fixwd() | ||||
| 	return bind(name, old, flag) | ||||
| } | ||||
| 
 | ||||
| //sys	mount(fd int, afd int, old string, flag int, aname string) (err error)
 | ||||
| func Mount(fd int, afd int, old string, flag int, aname string) (err error) { | ||||
| 	fixwd() | ||||
| 	return mount(fd, afd, old, flag, aname) | ||||
| } | ||||
| 
 | ||||
| //sys	wstat(path string, edir []byte) (err error)
 | ||||
| func Wstat(path string, edir []byte) (err error) { | ||||
| 	fixwd() | ||||
| 	return wstat(path, edir) | ||||
| } | ||||
| 
 | ||||
| //sys	chdir(path string) (err error)
 | ||||
| //sys	Dup(oldfd int, newfd int) (fd int, err error)
 | ||||
| //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 | ||||
| //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
 | ||||
| //sys	Close(fd int) (err error)
 | ||||
| //sys	Fstat(fd int, edir []byte) (n int, err error)
 | ||||
| //sys	Fwstat(fd int, edir []byte) (err error)
 | ||||
|  | @ -0,0 +1,284 @@ | |||
| // go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go
 | ||||
| // Code generated by the command above; see README.md. DO NOT EDIT.
 | ||||
| 
 | ||||
| // +build plan9,386
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import "unsafe" | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func fd2path(fd int, buf []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(buf) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&buf[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func pipe(p *[2]int32) (err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func await(s []byte) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(s) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&s[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func open(path string, mode int) (fd int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func create(path string, mode int, perm uint32) (fd int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func remove(path string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func stat(path string, edir []byte) (n int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func bind(name string, old string, flag int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(name) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func mount(fd int, afd int, old string, flag int, aname string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = BytePtrFromString(aname) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func wstat(path string, edir []byte) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func chdir(path string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Dup(oldfd int, newfd int) (fd int, err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Pread(fd int, p []byte, offset int64) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(p) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&p[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Pwrite(fd int, p []byte, offset int64) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(p) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&p[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Close(fd int) (err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Fstat(fd int, edir []byte) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Fwstat(fd int, edir []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | @ -0,0 +1,284 @@ | |||
| // go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go
 | ||||
| // Code generated by the command above; see README.md. DO NOT EDIT.
 | ||||
| 
 | ||||
| // +build plan9,amd64
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import "unsafe" | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func fd2path(fd int, buf []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(buf) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&buf[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func pipe(p *[2]int32) (err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func await(s []byte) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(s) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&s[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func open(path string, mode int) (fd int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func create(path string, mode int, perm uint32) (fd int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func remove(path string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func stat(path string, edir []byte) (n int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func bind(name string, old string, flag int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(name) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func mount(fd int, afd int, old string, flag int, aname string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = BytePtrFromString(aname) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func wstat(path string, edir []byte) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func chdir(path string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Dup(oldfd int, newfd int) (fd int, err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Pread(fd int, p []byte, offset int64) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(p) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&p[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Pwrite(fd int, p []byte, offset int64) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(p) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&p[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Close(fd int) (err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Fstat(fd int, edir []byte) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Fwstat(fd int, edir []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | @ -0,0 +1,284 @@ | |||
| // go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go
 | ||||
| // Code generated by the command above; see README.md. DO NOT EDIT.
 | ||||
| 
 | ||||
| // +build plan9,arm
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| import "unsafe" | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func fd2path(fd int, buf []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(buf) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&buf[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func pipe(p *[2]int32) (err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func await(s []byte) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(s) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&s[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func open(path string, mode int) (fd int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func create(path string, mode int, perm uint32) (fd int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func remove(path string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func stat(path string, edir []byte) (n int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func bind(name string, old string, flag int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(name) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func mount(fd int, afd int, old string, flag int, aname string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(old) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = BytePtrFromString(aname) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func wstat(path string, edir []byte) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func chdir(path string) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Dup(oldfd int, newfd int) (fd int, err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) | ||||
| 	fd = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Pread(fd int, p []byte, offset int64) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(p) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&p[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Pwrite(fd int, p []byte, offset int64) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(p) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&p[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Close(fd int) (err error) { | ||||
| 	r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Fstat(fd int, edir []byte) (n int, err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) | ||||
| 	n = int(r0) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func Fwstat(fd int, edir []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(edir) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&edir[0]) | ||||
| 	} else { | ||||
| 		_p0 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) | ||||
| 	if int32(r0) == -1 { | ||||
| 		err = e1 | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | @ -0,0 +1,49 @@ | |||
| // mksysnum_plan9.sh /opt/plan9/sys/src/libc/9syscall/sys.h
 | ||||
| // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 | ||||
| 
 | ||||
| package plan9 | ||||
| 
 | ||||
| const ( | ||||
| 	SYS_SYSR1       = 0 | ||||
| 	SYS_BIND        = 2 | ||||
| 	SYS_CHDIR       = 3 | ||||
| 	SYS_CLOSE       = 4 | ||||
| 	SYS_DUP         = 5 | ||||
| 	SYS_ALARM       = 6 | ||||
| 	SYS_EXEC        = 7 | ||||
| 	SYS_EXITS       = 8 | ||||
| 	SYS_FAUTH       = 10 | ||||
| 	SYS_SEGBRK      = 12 | ||||
| 	SYS_OPEN        = 14 | ||||
| 	SYS_OSEEK       = 16 | ||||
| 	SYS_SLEEP       = 17 | ||||
| 	SYS_RFORK       = 19 | ||||
| 	SYS_PIPE        = 21 | ||||
| 	SYS_CREATE      = 22 | ||||
| 	SYS_FD2PATH     = 23 | ||||
| 	SYS_BRK_        = 24 | ||||
| 	SYS_REMOVE      = 25 | ||||
| 	SYS_NOTIFY      = 28 | ||||
| 	SYS_NOTED       = 29 | ||||
| 	SYS_SEGATTACH   = 30 | ||||
| 	SYS_SEGDETACH   = 31 | ||||
| 	SYS_SEGFREE     = 32 | ||||
| 	SYS_SEGFLUSH    = 33 | ||||
| 	SYS_RENDEZVOUS  = 34 | ||||
| 	SYS_UNMOUNT     = 35 | ||||
| 	SYS_SEMACQUIRE  = 37 | ||||
| 	SYS_SEMRELEASE  = 38 | ||||
| 	SYS_SEEK        = 39 | ||||
| 	SYS_FVERSION    = 40 | ||||
| 	SYS_ERRSTR      = 41 | ||||
| 	SYS_STAT        = 42 | ||||
| 	SYS_FSTAT       = 43 | ||||
| 	SYS_WSTAT       = 44 | ||||
| 	SYS_FWSTAT      = 45 | ||||
| 	SYS_MOUNT       = 46 | ||||
| 	SYS_AWAIT       = 47 | ||||
| 	SYS_PREAD       = 50 | ||||
| 	SYS_PWRITE      = 51 | ||||
| 	SYS_TSEMACQUIRE = 52 | ||||
| 	SYS_NSEC        = 53 | ||||
| ) | ||||
|  | @ -0,0 +1,3 @@ | |||
| # This source code refers to The Go Authors for copyright purposes. | ||||
| # The master list of authors is in the main Go distribution, | ||||
| # visible at http://tip.golang.org/AUTHORS. | ||||
|  | @ -0,0 +1,26 @@ | |||
| # Contributing to Go | ||||
| 
 | ||||
| Go is an open source project. | ||||
| 
 | ||||
| It is the work of hundreds of contributors. We appreciate your help! | ||||
| 
 | ||||
| ## Filing issues | ||||
| 
 | ||||
| When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: | ||||
| 
 | ||||
| 1.  What version of Go are you using (`go version`)? | ||||
| 2.  What operating system and processor architecture are you using? | ||||
| 3.  What did you do? | ||||
| 4.  What did you expect to see? | ||||
| 5.  What did you see instead? | ||||
| 
 | ||||
| General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. | ||||
| The gophers there will answer or ask you to file an issue if you've tripped over a bug. | ||||
| 
 | ||||
| ## Contributing code | ||||
| 
 | ||||
| Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) | ||||
| before sending patches. | ||||
| 
 | ||||
| Unless otherwise noted, the Go source files are distributed under | ||||
| the BSD-style license found in the LICENSE file. | ||||
|  | @ -0,0 +1,3 @@ | |||
| # This source code was written by the Go contributors. | ||||
| # The master list of contributors is in the main Go distribution, | ||||
| # visible at http://tip.golang.org/CONTRIBUTORS. | ||||
|  | @ -0,0 +1,27 @@ | |||
| Copyright (c) 2009 The Go Authors. All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are | ||||
| met: | ||||
| 
 | ||||
|    * Redistributions of source code must retain the above copyright | ||||
| notice, this list of conditions and the following disclaimer. | ||||
|    * Redistributions in binary form must reproduce the above | ||||
| copyright notice, this list of conditions and the following disclaimer | ||||
| in the documentation and/or other materials provided with the | ||||
| distribution. | ||||
|    * Neither the name of Google Inc. nor the names of its | ||||
| contributors may be used to endorse or promote products derived from | ||||
| this software without specific prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | @ -0,0 +1,22 @@ | |||
| Additional IP Rights Grant (Patents) | ||||
| 
 | ||||
| "This implementation" means the copyrightable works distributed by | ||||
| Google as part of the Go project. | ||||
| 
 | ||||
| Google hereby grants to You a perpetual, worldwide, non-exclusive, | ||||
| no-charge, royalty-free, irrevocable (except as stated in this section) | ||||
| patent license to make, have made, use, offer to sell, sell, import, | ||||
| transfer and otherwise run, modify and propagate the contents of this | ||||
| implementation of Go, where such license applies only to those patent | ||||
| claims, both currently owned or controlled by Google and acquired in | ||||
| the future, licensable by Google that are necessarily infringed by this | ||||
| implementation of Go.  This grant does not include claims that would be | ||||
| infringed only as a consequence of further modification of this | ||||
| implementation.  If you or your agent or exclusive licensee institute or | ||||
| order or agree to the institution of patent litigation against any | ||||
| entity (including a cross-claim or counterclaim in a lawsuit) alleging | ||||
| that this implementation of Go or any code incorporated within this | ||||
| implementation of Go constitutes direct or contributory patent | ||||
| infringement, or inducement of patent infringement, then any patent | ||||
| rights granted to you under this License for this implementation of Go | ||||
| shall terminate as of the date such litigation is filed. | ||||
|  | @ -0,0 +1,17 @@ | |||
| # Go terminal/console support | ||||
| 
 | ||||
| This repository provides Go terminal and console support packages. | ||||
| 
 | ||||
| ## Download/Install | ||||
| 
 | ||||
| The easiest way to install is to run `go get -u golang.org/x/term`. You can | ||||
| also manually git clone the repository to `$GOPATH/src/golang.org/x/term`. | ||||
| 
 | ||||
| ## Report Issues / Send Patches | ||||
| 
 | ||||
| This repository uses Gerrit for code changes. To learn how to submit changes to | ||||
| this repository, see https://golang.org/doc/contribute.html. | ||||
| 
 | ||||
| The main issue tracker for the term repository is located at | ||||
| https://github.com/golang/go/issues. Prefix your issue with "x/term:" in the | ||||
| subject line, so it is easy to find. | ||||
|  | @ -0,0 +1,5 @@ | |||
| module golang.org/x/term | ||||
| 
 | ||||
| go 1.11 | ||||
| 
 | ||||
| require golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 | ||||
|  | @ -0,0 +1,2 @@ | |||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
							
								
								
									
										36
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go → vendor/golang.org/x/term/term.go
								
								
									generated
								
								
									vendored
								
								
							
							
						
						
									
										36
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go → vendor/golang.org/x/term/term.go
								
								
									generated
								
								
									vendored
								
								
							|  | @ -1,8 +1,8 @@ | |||
| // Copyright 2016 The Go Authors. All rights reserved.
 | ||||
| // Copyright 2019 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Package terminal provides support functions for dealing with terminals, as
 | ||||
| // Package term provides support functions for dealing with terminals, as
 | ||||
| // commonly found on UNIX systems.
 | ||||
| //
 | ||||
| // Putting a terminal into raw mode is the most common requirement:
 | ||||
|  | @ -12,47 +12,47 @@ | |||
| // 	        panic(err)
 | ||||
| // 	}
 | ||||
| // 	defer terminal.Restore(0, oldState)
 | ||||
| package terminal | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| ) | ||||
| 
 | ||||
| type State struct{} | ||||
| // State contains the state of a terminal.
 | ||||
| type State struct { | ||||
| 	state | ||||
| } | ||||
| 
 | ||||
| // IsTerminal returns whether the given file descriptor is a terminal.
 | ||||
| func IsTerminal(fd int) bool { | ||||
| 	return false | ||||
| 	return isTerminal(fd) | ||||
| } | ||||
| 
 | ||||
| // MakeRaw put the terminal connected to the given file descriptor into raw
 | ||||
| // MakeRaw puts the terminal connected to the given file descriptor into raw
 | ||||
| // mode and returns the previous state of the terminal so that it can be
 | ||||
| // restored.
 | ||||
| func MakeRaw(fd int) (*State, error) { | ||||
| 	return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| 	return makeRaw(fd) | ||||
| } | ||||
| 
 | ||||
| // GetState returns the current state of a terminal which may be useful to
 | ||||
| // restore the terminal after a signal.
 | ||||
| func GetState(fd int) (*State, error) { | ||||
| 	return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| 	return getState(fd) | ||||
| } | ||||
| 
 | ||||
| // Restore restores the terminal connected to the given file descriptor to a
 | ||||
| // previous state.
 | ||||
| func Restore(fd int, state *State) error { | ||||
| 	return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| func Restore(fd int, oldState *State) error { | ||||
| 	return restore(fd, oldState) | ||||
| } | ||||
| 
 | ||||
| // GetSize returns the dimensions of the given terminal.
 | ||||
| // GetSize returns the visible dimensions of the given terminal.
 | ||||
| //
 | ||||
| // These dimensions don't include any scrollback buffer height.
 | ||||
| func GetSize(fd int) (width, height int, err error) { | ||||
| 	return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| 	return getSize(fd) | ||||
| } | ||||
| 
 | ||||
| // ReadPassword reads a line of input from a terminal without local echo.  This
 | ||||
| // is commonly used for inputting passwords and other sensitive data. The slice
 | ||||
| // returned does not include the \n.
 | ||||
| func ReadPassword(fd int) ([]byte, error) { | ||||
| 	return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| 	return readPassword(fd) | ||||
| } | ||||
|  | @ -0,0 +1,42 @@ | |||
| // Copyright 2019 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| 
 | ||||
| 	"golang.org/x/sys/plan9" | ||||
| ) | ||||
| 
 | ||||
| type state struct{} | ||||
| 
 | ||||
| func isTerminal(fd int) bool { | ||||
| 	path, err := plan9.Fd2path(fd) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return path == "/dev/cons" || path == "/mnt/term/dev/cons" | ||||
| } | ||||
| 
 | ||||
| func makeRaw(fd int) (*State, error) { | ||||
| 	return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func getState(fd int) (*State, error) { | ||||
| 	return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func restore(fd int, state *State) error { | ||||
| 	return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func getSize(fd int) (width, height int, err error) { | ||||
| 	return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func readPassword(fd int) ([]byte, error) { | ||||
| 	return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
|  | @ -1,32 +1,27 @@ | |||
| // Copyright 2015 The Go Authors. All rights reserved.
 | ||||
| // Copyright 2019 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 solaris
 | ||||
| 
 | ||||
| package terminal // import "golang.org/x/crypto/ssh/terminal"
 | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"golang.org/x/sys/unix" | ||||
| 	"io" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
| 
 | ||||
| // State contains the state of a terminal.
 | ||||
| type State struct { | ||||
| type state struct { | ||||
| 	termios unix.Termios | ||||
| } | ||||
| 
 | ||||
| // IsTerminal returns whether the given file descriptor is a terminal.
 | ||||
| func IsTerminal(fd int) bool { | ||||
| func isTerminal(fd int) bool { | ||||
| 	_, err := unix.IoctlGetTermio(fd, unix.TCGETA) | ||||
| 	return err == nil | ||||
| } | ||||
| 
 | ||||
| // ReadPassword reads a line of input from a terminal without local echo.  This
 | ||||
| // is commonly used for inputting passwords and other sensitive data. The slice
 | ||||
| // returned does not include the \n.
 | ||||
| func ReadPassword(fd int) ([]byte, error) { | ||||
| func readPassword(fd int) ([]byte, error) { | ||||
| 	// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
 | ||||
| 	val, err := unix.IoctlGetTermios(fd, unix.TCGETS) | ||||
| 	if err != nil { | ||||
|  | @ -70,17 +65,14 @@ func ReadPassword(fd int) ([]byte, error) { | |||
| 	return ret, nil | ||||
| } | ||||
| 
 | ||||
| // MakeRaw puts the terminal connected to the given file descriptor into raw
 | ||||
| // mode and returns the previous state of the terminal so that it can be
 | ||||
| // restored.
 | ||||
| func makeRaw(fd int) (*State, error) { | ||||
| 	// see http://cr.illumos.org/~webrev/andy_js/1060/
 | ||||
| func MakeRaw(fd int) (*State, error) { | ||||
| 	termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	oldState := State{termios: *termios} | ||||
| 	oldState := State{state{termios: *termios}} | ||||
| 
 | ||||
| 	termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON | ||||
| 	termios.Oflag &^= unix.OPOST | ||||
|  | @ -97,25 +89,20 @@ func MakeRaw(fd int) (*State, error) { | |||
| 	return &oldState, nil | ||||
| } | ||||
| 
 | ||||
| // Restore restores the terminal connected to the given file descriptor to a
 | ||||
| // previous state.
 | ||||
| func Restore(fd int, oldState *State) error { | ||||
| func restore(fd int, oldState *State) error { | ||||
| 	return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios) | ||||
| } | ||||
| 
 | ||||
| // GetState returns the current state of a terminal which may be useful to
 | ||||
| // restore the terminal after a signal.
 | ||||
| func GetState(fd int) (*State, error) { | ||||
| func getState(fd int) (*State, error) { | ||||
| 	termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &State{termios: *termios}, nil | ||||
| 	return &State{state{termios: *termios}}, nil | ||||
| } | ||||
| 
 | ||||
| // GetSize returns the dimensions of the given terminal.
 | ||||
| func GetSize(fd int) (width, height int, err error) { | ||||
| func getSize(fd int) (width, height int, err error) { | ||||
| 	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) | ||||
| 	if err != nil { | ||||
| 		return 0, 0, err | ||||
							
								
								
									
										47
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util.go → vendor/golang.org/x/term/term_unix.go
								
								
									generated
								
								
									vendored
								
								
							
							
						
						
									
										47
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util.go → vendor/golang.org/x/term/term_unix.go
								
								
									generated
								
								
									vendored
								
								
							|  | @ -1,46 +1,31 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Copyright 2019 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 aix darwin dragonfly freebsd linux,!appengine netbsd openbsd
 | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd zos
 | ||||
| 
 | ||||
| // Package terminal provides support functions for dealing with terminals, as
 | ||||
| // commonly found on UNIX systems.
 | ||||
| //
 | ||||
| // Putting a terminal into raw mode is the most common requirement:
 | ||||
| //
 | ||||
| // 	oldState, err := terminal.MakeRaw(0)
 | ||||
| // 	if err != nil {
 | ||||
| // 	        panic(err)
 | ||||
| // 	}
 | ||||
| // 	defer terminal.Restore(0, oldState)
 | ||||
| package terminal // import "golang.org/x/crypto/ssh/terminal"
 | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
| 
 | ||||
| // State contains the state of a terminal.
 | ||||
| type State struct { | ||||
| type state struct { | ||||
| 	termios unix.Termios | ||||
| } | ||||
| 
 | ||||
| // IsTerminal returns whether the given file descriptor is a terminal.
 | ||||
| func IsTerminal(fd int) bool { | ||||
| func isTerminal(fd int) bool { | ||||
| 	_, err := unix.IoctlGetTermios(fd, ioctlReadTermios) | ||||
| 	return err == nil | ||||
| } | ||||
| 
 | ||||
| // MakeRaw put the terminal connected to the given file descriptor into raw
 | ||||
| // mode and returns the previous state of the terminal so that it can be
 | ||||
| // restored.
 | ||||
| func MakeRaw(fd int) (*State, error) { | ||||
| func makeRaw(fd int) (*State, error) { | ||||
| 	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	oldState := State{termios: *termios} | ||||
| 	oldState := State{state{termios: *termios}} | ||||
| 
 | ||||
| 	// This attempts to replicate the behaviour documented for cfmakeraw in
 | ||||
| 	// the termios(3) manpage.
 | ||||
|  | @ -58,25 +43,20 @@ func MakeRaw(fd int) (*State, error) { | |||
| 	return &oldState, nil | ||||
| } | ||||
| 
 | ||||
| // GetState returns the current state of a terminal which may be useful to
 | ||||
| // restore the terminal after a signal.
 | ||||
| func GetState(fd int) (*State, error) { | ||||
| func getState(fd int) (*State, error) { | ||||
| 	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &State{termios: *termios}, nil | ||||
| 	return &State{state{termios: *termios}}, nil | ||||
| } | ||||
| 
 | ||||
| // Restore restores the terminal connected to the given file descriptor to a
 | ||||
| // previous state.
 | ||||
| func Restore(fd int, state *State) error { | ||||
| func restore(fd int, state *State) error { | ||||
| 	return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios) | ||||
| } | ||||
| 
 | ||||
| // GetSize returns the dimensions of the given terminal.
 | ||||
| func GetSize(fd int) (width, height int, err error) { | ||||
| func getSize(fd int) (width, height int, err error) { | ||||
| 	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) | ||||
| 	if err != nil { | ||||
| 		return -1, -1, err | ||||
|  | @ -91,10 +71,7 @@ func (r passwordReader) Read(buf []byte) (int, error) { | |||
| 	return unix.Read(int(r), buf) | ||||
| } | ||||
| 
 | ||||
| // ReadPassword reads a line of input from a terminal without local echo.  This
 | ||||
| // is commonly used for inputting passwords and other sensitive data. The slice
 | ||||
| // returned does not include the \n.
 | ||||
| func ReadPassword(fd int) ([]byte, error) { | ||||
| func readPassword(fd int) ([]byte, error) { | ||||
| 	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
|  | @ -1,8 +1,8 @@ | |||
| // Copyright 2013 The Go Authors. All rights reserved.
 | ||||
| // Copyright 2019 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package terminal | ||||
| package term | ||||
| 
 | ||||
| import "golang.org/x/sys/unix" | ||||
| 
 | ||||
|  | @ -4,7 +4,7 @@ | |||
| 
 | ||||
| // +build darwin dragonfly freebsd netbsd openbsd
 | ||||
| 
 | ||||
| package terminal | ||||
| package term | ||||
| 
 | ||||
| import "golang.org/x/sys/unix" | ||||
| 
 | ||||
|  | @ -1,10 +1,8 @@ | |||
| // Copyright 2018 The Go Authors. All rights reserved.
 | ||||
| // Copyright 2019 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 aix
 | ||||
| 
 | ||||
| package terminal | ||||
| package term | ||||
| 
 | ||||
| import "golang.org/x/sys/unix" | ||||
| 
 | ||||
|  | @ -0,0 +1,10 @@ | |||
| // Copyright 2020 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package term | ||||
| 
 | ||||
| import "golang.org/x/sys/unix" | ||||
| 
 | ||||
| const ioctlReadTermios = unix.TCGETS | ||||
| const ioctlWriteTermios = unix.TCSETS | ||||
|  | @ -0,0 +1,38 @@ | |||
| // Copyright 2019 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 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!zos,!windows,!solaris,!plan9
 | ||||
| 
 | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| ) | ||||
| 
 | ||||
| type state struct{} | ||||
| 
 | ||||
| func isTerminal(fd int) bool { | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func makeRaw(fd int) (*State, error) { | ||||
| 	return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func getState(fd int) (*State, error) { | ||||
| 	return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func restore(fd int, state *State) error { | ||||
| 	return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func getSize(fd int) (width, height int, err error) { | ||||
| 	return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
| 
 | ||||
| func readPassword(fd int) ([]byte, error) { | ||||
| 	return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) | ||||
| } | ||||
|  | @ -1,20 +1,8 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Copyright 2019 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
 | ||||
| 
 | ||||
| // Package terminal provides support functions for dealing with terminals, as
 | ||||
| // commonly found on UNIX systems.
 | ||||
| //
 | ||||
| // Putting a terminal into raw mode is the most common requirement:
 | ||||
| //
 | ||||
| // 	oldState, err := terminal.MakeRaw(0)
 | ||||
| // 	if err != nil {
 | ||||
| // 	        panic(err)
 | ||||
| // 	}
 | ||||
| // 	defer terminal.Restore(0, oldState)
 | ||||
| package terminal | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
|  | @ -22,21 +10,17 @@ import ( | |||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
| 
 | ||||
| type State struct { | ||||
| type state struct { | ||||
| 	mode uint32 | ||||
| } | ||||
| 
 | ||||
| // IsTerminal returns whether the given file descriptor is a terminal.
 | ||||
| func IsTerminal(fd int) bool { | ||||
| func isTerminal(fd int) bool { | ||||
| 	var st uint32 | ||||
| 	err := windows.GetConsoleMode(windows.Handle(fd), &st) | ||||
| 	return err == nil | ||||
| } | ||||
| 
 | ||||
| // MakeRaw put the terminal connected to the given file descriptor into raw
 | ||||
| // mode and returns the previous state of the terminal so that it can be
 | ||||
| // restored.
 | ||||
| func MakeRaw(fd int) (*State, error) { | ||||
| func makeRaw(fd int) (*State, error) { | ||||
| 	var st uint32 | ||||
| 	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { | ||||
| 		return nil, err | ||||
|  | @ -45,29 +29,22 @@ func MakeRaw(fd int) (*State, error) { | |||
| 	if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &State{st}, nil | ||||
| 	return &State{state{st}}, nil | ||||
| } | ||||
| 
 | ||||
| // GetState returns the current state of a terminal which may be useful to
 | ||||
| // restore the terminal after a signal.
 | ||||
| func GetState(fd int) (*State, error) { | ||||
| func getState(fd int) (*State, error) { | ||||
| 	var st uint32 | ||||
| 	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &State{st}, nil | ||||
| 	return &State{state{st}}, nil | ||||
| } | ||||
| 
 | ||||
| // Restore restores the terminal connected to the given file descriptor to a
 | ||||
| // previous state.
 | ||||
| func Restore(fd int, state *State) error { | ||||
| func restore(fd int, state *State) error { | ||||
| 	return windows.SetConsoleMode(windows.Handle(fd), state.mode) | ||||
| } | ||||
| 
 | ||||
| // GetSize returns the visible dimensions of the given terminal.
 | ||||
| //
 | ||||
| // These dimensions don't include any scrollback buffer height.
 | ||||
| func GetSize(fd int) (width, height int, err error) { | ||||
| func getSize(fd int) (width, height int, err error) { | ||||
| 	var info windows.ConsoleScreenBufferInfo | ||||
| 	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { | ||||
| 		return 0, 0, err | ||||
|  | @ -75,10 +52,7 @@ func GetSize(fd int) (width, height int, err error) { | |||
| 	return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil | ||||
| } | ||||
| 
 | ||||
| // ReadPassword reads a line of input from a terminal without local echo.  This
 | ||||
| // is commonly used for inputting passwords and other sensitive data. The slice
 | ||||
| // returned does not include the \n.
 | ||||
| func ReadPassword(fd int) ([]byte, error) { | ||||
| func readPassword(fd int) ([]byte, error) { | ||||
| 	var st uint32 | ||||
| 	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { | ||||
| 		return nil, err | ||||
|  | @ -0,0 +1,987 @@ | |||
| // Copyright 2011 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package term | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"runtime" | ||||
| 	"strconv" | ||||
| 	"sync" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
| 
 | ||||
| // EscapeCodes contains escape sequences that can be written to the terminal in
 | ||||
| // order to achieve different styles of text.
 | ||||
| type EscapeCodes struct { | ||||
| 	// Foreground colors
 | ||||
| 	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte | ||||
| 
 | ||||
| 	// Reset all attributes
 | ||||
| 	Reset []byte | ||||
| } | ||||
| 
 | ||||
| var vt100EscapeCodes = EscapeCodes{ | ||||
| 	Black:   []byte{keyEscape, '[', '3', '0', 'm'}, | ||||
| 	Red:     []byte{keyEscape, '[', '3', '1', 'm'}, | ||||
| 	Green:   []byte{keyEscape, '[', '3', '2', 'm'}, | ||||
| 	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'}, | ||||
| 	Blue:    []byte{keyEscape, '[', '3', '4', 'm'}, | ||||
| 	Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, | ||||
| 	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'}, | ||||
| 	White:   []byte{keyEscape, '[', '3', '7', 'm'}, | ||||
| 
 | ||||
| 	Reset: []byte{keyEscape, '[', '0', 'm'}, | ||||
| } | ||||
| 
 | ||||
| // Terminal contains the state for running a VT100 terminal that is capable of
 | ||||
| // reading lines of input.
 | ||||
| type Terminal struct { | ||||
| 	// AutoCompleteCallback, if non-null, is called for each keypress with
 | ||||
| 	// the full input line and the current position of the cursor (in
 | ||||
| 	// bytes, as an index into |line|). If it returns ok=false, the key
 | ||||
| 	// press is processed normally. Otherwise it returns a replacement line
 | ||||
| 	// and the new cursor position.
 | ||||
| 	AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) | ||||
| 
 | ||||
| 	// Escape contains a pointer to the escape codes for this terminal.
 | ||||
| 	// It's always a valid pointer, although the escape codes themselves
 | ||||
| 	// may be empty if the terminal doesn't support them.
 | ||||
| 	Escape *EscapeCodes | ||||
| 
 | ||||
| 	// lock protects the terminal and the state in this object from
 | ||||
| 	// concurrent processing of a key press and a Write() call.
 | ||||
| 	lock sync.Mutex | ||||
| 
 | ||||
| 	c      io.ReadWriter | ||||
| 	prompt []rune | ||||
| 
 | ||||
| 	// line is the current line being entered.
 | ||||
| 	line []rune | ||||
| 	// pos is the logical position of the cursor in line
 | ||||
| 	pos int | ||||
| 	// echo is true if local echo is enabled
 | ||||
| 	echo bool | ||||
| 	// pasteActive is true iff there is a bracketed paste operation in
 | ||||
| 	// progress.
 | ||||
| 	pasteActive bool | ||||
| 
 | ||||
| 	// cursorX contains the current X value of the cursor where the left
 | ||||
| 	// edge is 0. cursorY contains the row number where the first row of
 | ||||
| 	// the current line is 0.
 | ||||
| 	cursorX, cursorY int | ||||
| 	// maxLine is the greatest value of cursorY so far.
 | ||||
| 	maxLine int | ||||
| 
 | ||||
| 	termWidth, termHeight int | ||||
| 
 | ||||
| 	// outBuf contains the terminal data to be sent.
 | ||||
| 	outBuf []byte | ||||
| 	// remainder contains the remainder of any partial key sequences after
 | ||||
| 	// a read. It aliases into inBuf.
 | ||||
| 	remainder []byte | ||||
| 	inBuf     [256]byte | ||||
| 
 | ||||
| 	// history contains previously entered commands so that they can be
 | ||||
| 	// accessed with the up and down keys.
 | ||||
| 	history stRingBuffer | ||||
| 	// historyIndex stores the currently accessed history entry, where zero
 | ||||
| 	// means the immediately previous entry.
 | ||||
| 	historyIndex int | ||||
| 	// When navigating up and down the history it's possible to return to
 | ||||
| 	// the incomplete, initial line. That value is stored in
 | ||||
| 	// historyPending.
 | ||||
| 	historyPending string | ||||
| } | ||||
| 
 | ||||
| // NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
 | ||||
| // a local terminal, that terminal must first have been put into raw mode.
 | ||||
| // prompt is a string that is written at the start of each input line (i.e.
 | ||||
| // "> ").
 | ||||
| func NewTerminal(c io.ReadWriter, prompt string) *Terminal { | ||||
| 	return &Terminal{ | ||||
| 		Escape:       &vt100EscapeCodes, | ||||
| 		c:            c, | ||||
| 		prompt:       []rune(prompt), | ||||
| 		termWidth:    80, | ||||
| 		termHeight:   24, | ||||
| 		echo:         true, | ||||
| 		historyIndex: -1, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	keyCtrlC     = 3 | ||||
| 	keyCtrlD     = 4 | ||||
| 	keyCtrlU     = 21 | ||||
| 	keyEnter     = '\r' | ||||
| 	keyEscape    = 27 | ||||
| 	keyBackspace = 127 | ||||
| 	keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota | ||||
| 	keyUp | ||||
| 	keyDown | ||||
| 	keyLeft | ||||
| 	keyRight | ||||
| 	keyAltLeft | ||||
| 	keyAltRight | ||||
| 	keyHome | ||||
| 	keyEnd | ||||
| 	keyDeleteWord | ||||
| 	keyDeleteLine | ||||
| 	keyClearScreen | ||||
| 	keyPasteStart | ||||
| 	keyPasteEnd | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	crlf       = []byte{'\r', '\n'} | ||||
| 	pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} | ||||
| 	pasteEnd   = []byte{keyEscape, '[', '2', '0', '1', '~'} | ||||
| ) | ||||
| 
 | ||||
| // bytesToKey tries to parse a key sequence from b. If successful, it returns
 | ||||
| // the key and the remainder of the input. Otherwise it returns utf8.RuneError.
 | ||||
| func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { | ||||
| 	if len(b) == 0 { | ||||
| 		return utf8.RuneError, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if !pasteActive { | ||||
| 		switch b[0] { | ||||
| 		case 1: // ^A
 | ||||
| 			return keyHome, b[1:] | ||||
| 		case 2: // ^B
 | ||||
| 			return keyLeft, b[1:] | ||||
| 		case 5: // ^E
 | ||||
| 			return keyEnd, b[1:] | ||||
| 		case 6: // ^F
 | ||||
| 			return keyRight, b[1:] | ||||
| 		case 8: // ^H
 | ||||
| 			return keyBackspace, b[1:] | ||||
| 		case 11: // ^K
 | ||||
| 			return keyDeleteLine, b[1:] | ||||
| 		case 12: // ^L
 | ||||
| 			return keyClearScreen, b[1:] | ||||
| 		case 23: // ^W
 | ||||
| 			return keyDeleteWord, b[1:] | ||||
| 		case 14: // ^N
 | ||||
| 			return keyDown, b[1:] | ||||
| 		case 16: // ^P
 | ||||
| 			return keyUp, b[1:] | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if b[0] != keyEscape { | ||||
| 		if !utf8.FullRune(b) { | ||||
| 			return utf8.RuneError, b | ||||
| 		} | ||||
| 		r, l := utf8.DecodeRune(b) | ||||
| 		return r, b[l:] | ||||
| 	} | ||||
| 
 | ||||
| 	if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { | ||||
| 		switch b[2] { | ||||
| 		case 'A': | ||||
| 			return keyUp, b[3:] | ||||
| 		case 'B': | ||||
| 			return keyDown, b[3:] | ||||
| 		case 'C': | ||||
| 			return keyRight, b[3:] | ||||
| 		case 'D': | ||||
| 			return keyLeft, b[3:] | ||||
| 		case 'H': | ||||
| 			return keyHome, b[3:] | ||||
| 		case 'F': | ||||
| 			return keyEnd, b[3:] | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { | ||||
| 		switch b[5] { | ||||
| 		case 'C': | ||||
| 			return keyAltRight, b[6:] | ||||
| 		case 'D': | ||||
| 			return keyAltLeft, b[6:] | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { | ||||
| 		return keyPasteStart, b[6:] | ||||
| 	} | ||||
| 
 | ||||
| 	if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { | ||||
| 		return keyPasteEnd, b[6:] | ||||
| 	} | ||||
| 
 | ||||
| 	// If we get here then we have a key that we don't recognise, or a
 | ||||
| 	// partial sequence. It's not clear how one should find the end of a
 | ||||
| 	// sequence without knowing them all, but it seems that [a-zA-Z~] only
 | ||||
| 	// appears at the end of a sequence.
 | ||||
| 	for i, c := range b[0:] { | ||||
| 		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { | ||||
| 			return keyUnknown, b[i+1:] | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return utf8.RuneError, b | ||||
| } | ||||
| 
 | ||||
| // queue appends data to the end of t.outBuf
 | ||||
| func (t *Terminal) queue(data []rune) { | ||||
| 	t.outBuf = append(t.outBuf, []byte(string(data))...) | ||||
| } | ||||
| 
 | ||||
| var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} | ||||
| var space = []rune{' '} | ||||
| 
 | ||||
| func isPrintable(key rune) bool { | ||||
| 	isInSurrogateArea := key >= 0xd800 && key <= 0xdbff | ||||
| 	return key >= 32 && !isInSurrogateArea | ||||
| } | ||||
| 
 | ||||
| // moveCursorToPos appends data to t.outBuf which will move the cursor to the
 | ||||
| // given, logical position in the text.
 | ||||
| func (t *Terminal) moveCursorToPos(pos int) { | ||||
| 	if !t.echo { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	x := visualLength(t.prompt) + pos | ||||
| 	y := x / t.termWidth | ||||
| 	x = x % t.termWidth | ||||
| 
 | ||||
| 	up := 0 | ||||
| 	if y < t.cursorY { | ||||
| 		up = t.cursorY - y | ||||
| 	} | ||||
| 
 | ||||
| 	down := 0 | ||||
| 	if y > t.cursorY { | ||||
| 		down = y - t.cursorY | ||||
| 	} | ||||
| 
 | ||||
| 	left := 0 | ||||
| 	if x < t.cursorX { | ||||
| 		left = t.cursorX - x | ||||
| 	} | ||||
| 
 | ||||
| 	right := 0 | ||||
| 	if x > t.cursorX { | ||||
| 		right = x - t.cursorX | ||||
| 	} | ||||
| 
 | ||||
| 	t.cursorX = x | ||||
| 	t.cursorY = y | ||||
| 	t.move(up, down, left, right) | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) move(up, down, left, right int) { | ||||
| 	m := []rune{} | ||||
| 
 | ||||
| 	// 1 unit up can be expressed as ^[[A or ^[A
 | ||||
| 	// 5 units up can be expressed as ^[[5A
 | ||||
| 
 | ||||
| 	if up == 1 { | ||||
| 		m = append(m, keyEscape, '[', 'A') | ||||
| 	} else if up > 1 { | ||||
| 		m = append(m, keyEscape, '[') | ||||
| 		m = append(m, []rune(strconv.Itoa(up))...) | ||||
| 		m = append(m, 'A') | ||||
| 	} | ||||
| 
 | ||||
| 	if down == 1 { | ||||
| 		m = append(m, keyEscape, '[', 'B') | ||||
| 	} else if down > 1 { | ||||
| 		m = append(m, keyEscape, '[') | ||||
| 		m = append(m, []rune(strconv.Itoa(down))...) | ||||
| 		m = append(m, 'B') | ||||
| 	} | ||||
| 
 | ||||
| 	if right == 1 { | ||||
| 		m = append(m, keyEscape, '[', 'C') | ||||
| 	} else if right > 1 { | ||||
| 		m = append(m, keyEscape, '[') | ||||
| 		m = append(m, []rune(strconv.Itoa(right))...) | ||||
| 		m = append(m, 'C') | ||||
| 	} | ||||
| 
 | ||||
| 	if left == 1 { | ||||
| 		m = append(m, keyEscape, '[', 'D') | ||||
| 	} else if left > 1 { | ||||
| 		m = append(m, keyEscape, '[') | ||||
| 		m = append(m, []rune(strconv.Itoa(left))...) | ||||
| 		m = append(m, 'D') | ||||
| 	} | ||||
| 
 | ||||
| 	t.queue(m) | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) clearLineToRight() { | ||||
| 	op := []rune{keyEscape, '[', 'K'} | ||||
| 	t.queue(op) | ||||
| } | ||||
| 
 | ||||
| const maxLineLength = 4096 | ||||
| 
 | ||||
| func (t *Terminal) setLine(newLine []rune, newPos int) { | ||||
| 	if t.echo { | ||||
| 		t.moveCursorToPos(0) | ||||
| 		t.writeLine(newLine) | ||||
| 		for i := len(newLine); i < len(t.line); i++ { | ||||
| 			t.writeLine(space) | ||||
| 		} | ||||
| 		t.moveCursorToPos(newPos) | ||||
| 	} | ||||
| 	t.line = newLine | ||||
| 	t.pos = newPos | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) advanceCursor(places int) { | ||||
| 	t.cursorX += places | ||||
| 	t.cursorY += t.cursorX / t.termWidth | ||||
| 	if t.cursorY > t.maxLine { | ||||
| 		t.maxLine = t.cursorY | ||||
| 	} | ||||
| 	t.cursorX = t.cursorX % t.termWidth | ||||
| 
 | ||||
| 	if places > 0 && t.cursorX == 0 { | ||||
| 		// Normally terminals will advance the current position
 | ||||
| 		// when writing a character. But that doesn't happen
 | ||||
| 		// for the last character in a line. However, when
 | ||||
| 		// writing a character (except a new line) that causes
 | ||||
| 		// a line wrap, the position will be advanced two
 | ||||
| 		// places.
 | ||||
| 		//
 | ||||
| 		// So, if we are stopping at the end of a line, we
 | ||||
| 		// need to write a newline so that our cursor can be
 | ||||
| 		// advanced to the next line.
 | ||||
| 		t.outBuf = append(t.outBuf, '\r', '\n') | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) eraseNPreviousChars(n int) { | ||||
| 	if n == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if t.pos < n { | ||||
| 		n = t.pos | ||||
| 	} | ||||
| 	t.pos -= n | ||||
| 	t.moveCursorToPos(t.pos) | ||||
| 
 | ||||
| 	copy(t.line[t.pos:], t.line[n+t.pos:]) | ||||
| 	t.line = t.line[:len(t.line)-n] | ||||
| 	if t.echo { | ||||
| 		t.writeLine(t.line[t.pos:]) | ||||
| 		for i := 0; i < n; i++ { | ||||
| 			t.queue(space) | ||||
| 		} | ||||
| 		t.advanceCursor(n) | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // countToLeftWord returns then number of characters from the cursor to the
 | ||||
| // start of the previous word.
 | ||||
| func (t *Terminal) countToLeftWord() int { | ||||
| 	if t.pos == 0 { | ||||
| 		return 0 | ||||
| 	} | ||||
| 
 | ||||
| 	pos := t.pos - 1 | ||||
| 	for pos > 0 { | ||||
| 		if t.line[pos] != ' ' { | ||||
| 			break | ||||
| 		} | ||||
| 		pos-- | ||||
| 	} | ||||
| 	for pos > 0 { | ||||
| 		if t.line[pos] == ' ' { | ||||
| 			pos++ | ||||
| 			break | ||||
| 		} | ||||
| 		pos-- | ||||
| 	} | ||||
| 
 | ||||
| 	return t.pos - pos | ||||
| } | ||||
| 
 | ||||
| // countToRightWord returns then number of characters from the cursor to the
 | ||||
| // start of the next word.
 | ||||
| func (t *Terminal) countToRightWord() int { | ||||
| 	pos := t.pos | ||||
| 	for pos < len(t.line) { | ||||
| 		if t.line[pos] == ' ' { | ||||
| 			break | ||||
| 		} | ||||
| 		pos++ | ||||
| 	} | ||||
| 	for pos < len(t.line) { | ||||
| 		if t.line[pos] != ' ' { | ||||
| 			break | ||||
| 		} | ||||
| 		pos++ | ||||
| 	} | ||||
| 	return pos - t.pos | ||||
| } | ||||
| 
 | ||||
| // visualLength returns the number of visible glyphs in s.
 | ||||
| func visualLength(runes []rune) int { | ||||
| 	inEscapeSeq := false | ||||
| 	length := 0 | ||||
| 
 | ||||
| 	for _, r := range runes { | ||||
| 		switch { | ||||
| 		case inEscapeSeq: | ||||
| 			if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { | ||||
| 				inEscapeSeq = false | ||||
| 			} | ||||
| 		case r == '\x1b': | ||||
| 			inEscapeSeq = true | ||||
| 		default: | ||||
| 			length++ | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return length | ||||
| } | ||||
| 
 | ||||
| // handleKey processes the given key and, optionally, returns a line of text
 | ||||
| // that the user has entered.
 | ||||
| func (t *Terminal) handleKey(key rune) (line string, ok bool) { | ||||
| 	if t.pasteActive && key != keyEnter { | ||||
| 		t.addKeyToLine(key) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	switch key { | ||||
| 	case keyBackspace: | ||||
| 		if t.pos == 0 { | ||||
| 			return | ||||
| 		} | ||||
| 		t.eraseNPreviousChars(1) | ||||
| 	case keyAltLeft: | ||||
| 		// move left by a word.
 | ||||
| 		t.pos -= t.countToLeftWord() | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyAltRight: | ||||
| 		// move right by a word.
 | ||||
| 		t.pos += t.countToRightWord() | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyLeft: | ||||
| 		if t.pos == 0 { | ||||
| 			return | ||||
| 		} | ||||
| 		t.pos-- | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyRight: | ||||
| 		if t.pos == len(t.line) { | ||||
| 			return | ||||
| 		} | ||||
| 		t.pos++ | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyHome: | ||||
| 		if t.pos == 0 { | ||||
| 			return | ||||
| 		} | ||||
| 		t.pos = 0 | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyEnd: | ||||
| 		if t.pos == len(t.line) { | ||||
| 			return | ||||
| 		} | ||||
| 		t.pos = len(t.line) | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyUp: | ||||
| 		entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) | ||||
| 		if !ok { | ||||
| 			return "", false | ||||
| 		} | ||||
| 		if t.historyIndex == -1 { | ||||
| 			t.historyPending = string(t.line) | ||||
| 		} | ||||
| 		t.historyIndex++ | ||||
| 		runes := []rune(entry) | ||||
| 		t.setLine(runes, len(runes)) | ||||
| 	case keyDown: | ||||
| 		switch t.historyIndex { | ||||
| 		case -1: | ||||
| 			return | ||||
| 		case 0: | ||||
| 			runes := []rune(t.historyPending) | ||||
| 			t.setLine(runes, len(runes)) | ||||
| 			t.historyIndex-- | ||||
| 		default: | ||||
| 			entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) | ||||
| 			if ok { | ||||
| 				t.historyIndex-- | ||||
| 				runes := []rune(entry) | ||||
| 				t.setLine(runes, len(runes)) | ||||
| 			} | ||||
| 		} | ||||
| 	case keyEnter: | ||||
| 		t.moveCursorToPos(len(t.line)) | ||||
| 		t.queue([]rune("\r\n")) | ||||
| 		line = string(t.line) | ||||
| 		ok = true | ||||
| 		t.line = t.line[:0] | ||||
| 		t.pos = 0 | ||||
| 		t.cursorX = 0 | ||||
| 		t.cursorY = 0 | ||||
| 		t.maxLine = 0 | ||||
| 	case keyDeleteWord: | ||||
| 		// Delete zero or more spaces and then one or more characters.
 | ||||
| 		t.eraseNPreviousChars(t.countToLeftWord()) | ||||
| 	case keyDeleteLine: | ||||
| 		// Delete everything from the current cursor position to the
 | ||||
| 		// end of line.
 | ||||
| 		for i := t.pos; i < len(t.line); i++ { | ||||
| 			t.queue(space) | ||||
| 			t.advanceCursor(1) | ||||
| 		} | ||||
| 		t.line = t.line[:t.pos] | ||||
| 		t.moveCursorToPos(t.pos) | ||||
| 	case keyCtrlD: | ||||
| 		// Erase the character under the current position.
 | ||||
| 		// The EOF case when the line is empty is handled in
 | ||||
| 		// readLine().
 | ||||
| 		if t.pos < len(t.line) { | ||||
| 			t.pos++ | ||||
| 			t.eraseNPreviousChars(1) | ||||
| 		} | ||||
| 	case keyCtrlU: | ||||
| 		t.eraseNPreviousChars(t.pos) | ||||
| 	case keyClearScreen: | ||||
| 		// Erases the screen and moves the cursor to the home position.
 | ||||
| 		t.queue([]rune("\x1b[2J\x1b[H")) | ||||
| 		t.queue(t.prompt) | ||||
| 		t.cursorX, t.cursorY = 0, 0 | ||||
| 		t.advanceCursor(visualLength(t.prompt)) | ||||
| 		t.setLine(t.line, t.pos) | ||||
| 	default: | ||||
| 		if t.AutoCompleteCallback != nil { | ||||
| 			prefix := string(t.line[:t.pos]) | ||||
| 			suffix := string(t.line[t.pos:]) | ||||
| 
 | ||||
| 			t.lock.Unlock() | ||||
| 			newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) | ||||
| 			t.lock.Lock() | ||||
| 
 | ||||
| 			if completeOk { | ||||
| 				t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 		if !isPrintable(key) { | ||||
| 			return | ||||
| 		} | ||||
| 		if len(t.line) == maxLineLength { | ||||
| 			return | ||||
| 		} | ||||
| 		t.addKeyToLine(key) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // addKeyToLine inserts the given key at the current position in the current
 | ||||
| // line.
 | ||||
| func (t *Terminal) addKeyToLine(key rune) { | ||||
| 	if len(t.line) == cap(t.line) { | ||||
| 		newLine := make([]rune, len(t.line), 2*(1+len(t.line))) | ||||
| 		copy(newLine, t.line) | ||||
| 		t.line = newLine | ||||
| 	} | ||||
| 	t.line = t.line[:len(t.line)+1] | ||||
| 	copy(t.line[t.pos+1:], t.line[t.pos:]) | ||||
| 	t.line[t.pos] = key | ||||
| 	if t.echo { | ||||
| 		t.writeLine(t.line[t.pos:]) | ||||
| 	} | ||||
| 	t.pos++ | ||||
| 	t.moveCursorToPos(t.pos) | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) writeLine(line []rune) { | ||||
| 	for len(line) != 0 { | ||||
| 		remainingOnLine := t.termWidth - t.cursorX | ||||
| 		todo := len(line) | ||||
| 		if todo > remainingOnLine { | ||||
| 			todo = remainingOnLine | ||||
| 		} | ||||
| 		t.queue(line[:todo]) | ||||
| 		t.advanceCursor(visualLength(line[:todo])) | ||||
| 		line = line[todo:] | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
 | ||||
| func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) { | ||||
| 	for len(buf) > 0 { | ||||
| 		i := bytes.IndexByte(buf, '\n') | ||||
| 		todo := len(buf) | ||||
| 		if i >= 0 { | ||||
| 			todo = i | ||||
| 		} | ||||
| 
 | ||||
| 		var nn int | ||||
| 		nn, err = w.Write(buf[:todo]) | ||||
| 		n += nn | ||||
| 		if err != nil { | ||||
| 			return n, err | ||||
| 		} | ||||
| 		buf = buf[todo:] | ||||
| 
 | ||||
| 		if i >= 0 { | ||||
| 			if _, err = w.Write(crlf); err != nil { | ||||
| 				return n, err | ||||
| 			} | ||||
| 			n++ | ||||
| 			buf = buf[1:] | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return n, nil | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) Write(buf []byte) (n int, err error) { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
| 
 | ||||
| 	if t.cursorX == 0 && t.cursorY == 0 { | ||||
| 		// This is the easy case: there's nothing on the screen that we
 | ||||
| 		// have to move out of the way.
 | ||||
| 		return writeWithCRLF(t.c, buf) | ||||
| 	} | ||||
| 
 | ||||
| 	// We have a prompt and possibly user input on the screen. We
 | ||||
| 	// have to clear it first.
 | ||||
| 	t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) | ||||
| 	t.cursorX = 0 | ||||
| 	t.clearLineToRight() | ||||
| 
 | ||||
| 	for t.cursorY > 0 { | ||||
| 		t.move(1 /* up */, 0, 0, 0) | ||||
| 		t.cursorY-- | ||||
| 		t.clearLineToRight() | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err = t.c.Write(t.outBuf); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	t.outBuf = t.outBuf[:0] | ||||
| 
 | ||||
| 	if n, err = writeWithCRLF(t.c, buf); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	t.writeLine(t.prompt) | ||||
| 	if t.echo { | ||||
| 		t.writeLine(t.line) | ||||
| 	} | ||||
| 
 | ||||
| 	t.moveCursorToPos(t.pos) | ||||
| 
 | ||||
| 	if _, err = t.c.Write(t.outBuf); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	t.outBuf = t.outBuf[:0] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // ReadPassword temporarily changes the prompt and reads a password, without
 | ||||
| // echo, from the terminal.
 | ||||
| func (t *Terminal) ReadPassword(prompt string) (line string, err error) { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
| 
 | ||||
| 	oldPrompt := t.prompt | ||||
| 	t.prompt = []rune(prompt) | ||||
| 	t.echo = false | ||||
| 
 | ||||
| 	line, err = t.readLine() | ||||
| 
 | ||||
| 	t.prompt = oldPrompt | ||||
| 	t.echo = true | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // ReadLine returns a line of input from the terminal.
 | ||||
| func (t *Terminal) ReadLine() (line string, err error) { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
| 
 | ||||
| 	return t.readLine() | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) readLine() (line string, err error) { | ||||
| 	// t.lock must be held at this point
 | ||||
| 
 | ||||
| 	if t.cursorX == 0 && t.cursorY == 0 { | ||||
| 		t.writeLine(t.prompt) | ||||
| 		t.c.Write(t.outBuf) | ||||
| 		t.outBuf = t.outBuf[:0] | ||||
| 	} | ||||
| 
 | ||||
| 	lineIsPasted := t.pasteActive | ||||
| 
 | ||||
| 	for { | ||||
| 		rest := t.remainder | ||||
| 		lineOk := false | ||||
| 		for !lineOk { | ||||
| 			var key rune | ||||
| 			key, rest = bytesToKey(rest, t.pasteActive) | ||||
| 			if key == utf8.RuneError { | ||||
| 				break | ||||
| 			} | ||||
| 			if !t.pasteActive { | ||||
| 				if key == keyCtrlD { | ||||
| 					if len(t.line) == 0 { | ||||
| 						return "", io.EOF | ||||
| 					} | ||||
| 				} | ||||
| 				if key == keyCtrlC { | ||||
| 					return "", io.EOF | ||||
| 				} | ||||
| 				if key == keyPasteStart { | ||||
| 					t.pasteActive = true | ||||
| 					if len(t.line) == 0 { | ||||
| 						lineIsPasted = true | ||||
| 					} | ||||
| 					continue | ||||
| 				} | ||||
| 			} else if key == keyPasteEnd { | ||||
| 				t.pasteActive = false | ||||
| 				continue | ||||
| 			} | ||||
| 			if !t.pasteActive { | ||||
| 				lineIsPasted = false | ||||
| 			} | ||||
| 			line, lineOk = t.handleKey(key) | ||||
| 		} | ||||
| 		if len(rest) > 0 { | ||||
| 			n := copy(t.inBuf[:], rest) | ||||
| 			t.remainder = t.inBuf[:n] | ||||
| 		} else { | ||||
| 			t.remainder = nil | ||||
| 		} | ||||
| 		t.c.Write(t.outBuf) | ||||
| 		t.outBuf = t.outBuf[:0] | ||||
| 		if lineOk { | ||||
| 			if t.echo { | ||||
| 				t.historyIndex = -1 | ||||
| 				t.history.Add(line) | ||||
| 			} | ||||
| 			if lineIsPasted { | ||||
| 				err = ErrPasteIndicator | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// t.remainder is a slice at the beginning of t.inBuf
 | ||||
| 		// containing a partial key sequence
 | ||||
| 		readBuf := t.inBuf[len(t.remainder):] | ||||
| 		var n int | ||||
| 
 | ||||
| 		t.lock.Unlock() | ||||
| 		n, err = t.c.Read(readBuf) | ||||
| 		t.lock.Lock() | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		t.remainder = t.inBuf[:n+len(t.remainder)] | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SetPrompt sets the prompt to be used when reading subsequent lines.
 | ||||
| func (t *Terminal) SetPrompt(prompt string) { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
| 
 | ||||
| 	t.prompt = []rune(prompt) | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { | ||||
| 	// Move cursor to column zero at the start of the line.
 | ||||
| 	t.move(t.cursorY, 0, t.cursorX, 0) | ||||
| 	t.cursorX, t.cursorY = 0, 0 | ||||
| 	t.clearLineToRight() | ||||
| 	for t.cursorY < numPrevLines { | ||||
| 		// Move down a line
 | ||||
| 		t.move(0, 1, 0, 0) | ||||
| 		t.cursorY++ | ||||
| 		t.clearLineToRight() | ||||
| 	} | ||||
| 	// Move back to beginning.
 | ||||
| 	t.move(t.cursorY, 0, 0, 0) | ||||
| 	t.cursorX, t.cursorY = 0, 0 | ||||
| 
 | ||||
| 	t.queue(t.prompt) | ||||
| 	t.advanceCursor(visualLength(t.prompt)) | ||||
| 	t.writeLine(t.line) | ||||
| 	t.moveCursorToPos(t.pos) | ||||
| } | ||||
| 
 | ||||
| func (t *Terminal) SetSize(width, height int) error { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
| 
 | ||||
| 	if width == 0 { | ||||
| 		width = 1 | ||||
| 	} | ||||
| 
 | ||||
| 	oldWidth := t.termWidth | ||||
| 	t.termWidth, t.termHeight = width, height | ||||
| 
 | ||||
| 	switch { | ||||
| 	case width == oldWidth: | ||||
| 		// If the width didn't change then nothing else needs to be
 | ||||
| 		// done.
 | ||||
| 		return nil | ||||
| 	case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: | ||||
| 		// If there is nothing on current line and no prompt printed,
 | ||||
| 		// just do nothing
 | ||||
| 		return nil | ||||
| 	case width < oldWidth: | ||||
| 		// Some terminals (e.g. xterm) will truncate lines that were
 | ||||
| 		// too long when shinking. Others, (e.g. gnome-terminal) will
 | ||||
| 		// attempt to wrap them. For the former, repainting t.maxLine
 | ||||
| 		// works great, but that behaviour goes badly wrong in the case
 | ||||
| 		// of the latter because they have doubled every full line.
 | ||||
| 
 | ||||
| 		// We assume that we are working on a terminal that wraps lines
 | ||||
| 		// and adjust the cursor position based on every previous line
 | ||||
| 		// wrapping and turning into two. This causes the prompt on
 | ||||
| 		// xterms to move upwards, which isn't great, but it avoids a
 | ||||
| 		// huge mess with gnome-terminal.
 | ||||
| 		if t.cursorX >= t.termWidth { | ||||
| 			t.cursorX = t.termWidth - 1 | ||||
| 		} | ||||
| 		t.cursorY *= 2 | ||||
| 		t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) | ||||
| 	case width > oldWidth: | ||||
| 		// If the terminal expands then our position calculations will
 | ||||
| 		// be wrong in the future because we think the cursor is
 | ||||
| 		// |t.pos| chars into the string, but there will be a gap at
 | ||||
| 		// the end of any wrapped line.
 | ||||
| 		//
 | ||||
| 		// But the position will actually be correct until we move, so
 | ||||
| 		// we can move back to the beginning and repaint everything.
 | ||||
| 		t.clearAndRepaintLinePlusNPrevious(t.maxLine) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err := t.c.Write(t.outBuf) | ||||
| 	t.outBuf = t.outBuf[:0] | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| type pasteIndicatorError struct{} | ||||
| 
 | ||||
| func (pasteIndicatorError) Error() string { | ||||
| 	return "terminal: ErrPasteIndicator not correctly handled" | ||||
| } | ||||
| 
 | ||||
| // ErrPasteIndicator may be returned from ReadLine as the error, in addition
 | ||||
| // to valid line data. It indicates that bracketed paste mode is enabled and
 | ||||
| // that the returned line consists only of pasted data. Programs may wish to
 | ||||
| // interpret pasted data more literally than typed data.
 | ||||
| var ErrPasteIndicator = pasteIndicatorError{} | ||||
| 
 | ||||
| // SetBracketedPasteMode requests that the terminal bracket paste operations
 | ||||
| // with markers. Not all terminals support this but, if it is supported, then
 | ||||
| // enabling this mode will stop any autocomplete callback from running due to
 | ||||
| // pastes. Additionally, any lines that are completely pasted will be returned
 | ||||
| // from ReadLine with the error set to ErrPasteIndicator.
 | ||||
| func (t *Terminal) SetBracketedPasteMode(on bool) { | ||||
| 	if on { | ||||
| 		io.WriteString(t.c, "\x1b[?2004h") | ||||
| 	} else { | ||||
| 		io.WriteString(t.c, "\x1b[?2004l") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // stRingBuffer is a ring buffer of strings.
 | ||||
| type stRingBuffer struct { | ||||
| 	// entries contains max elements.
 | ||||
| 	entries []string | ||||
| 	max     int | ||||
| 	// head contains the index of the element most recently added to the ring.
 | ||||
| 	head int | ||||
| 	// size contains the number of elements in the ring.
 | ||||
| 	size int | ||||
| } | ||||
| 
 | ||||
| func (s *stRingBuffer) Add(a string) { | ||||
| 	if s.entries == nil { | ||||
| 		const defaultNumEntries = 100 | ||||
| 		s.entries = make([]string, defaultNumEntries) | ||||
| 		s.max = defaultNumEntries | ||||
| 	} | ||||
| 
 | ||||
| 	s.head = (s.head + 1) % s.max | ||||
| 	s.entries[s.head] = a | ||||
| 	if s.size < s.max { | ||||
| 		s.size++ | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NthPreviousEntry returns the value passed to the nth previous call to Add.
 | ||||
| // If n is zero then the immediately prior value is returned, if one, then the
 | ||||
| // next most recent, and so on. If such an element doesn't exist then ok is
 | ||||
| // false.
 | ||||
| func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { | ||||
| 	if n >= s.size { | ||||
| 		return "", false | ||||
| 	} | ||||
| 	index := s.head - n | ||||
| 	if index < 0 { | ||||
| 		index += s.max | ||||
| 	} | ||||
| 	return s.entries[index], true | ||||
| } | ||||
| 
 | ||||
| // readPasswordLine reads from reader until it finds \n or io.EOF.
 | ||||
| // The slice returned does not include the \n.
 | ||||
| // readPasswordLine also ignores any \r it finds.
 | ||||
| // Windows uses \r as end of line. So, on Windows, readPasswordLine
 | ||||
| // reads until it finds \r and ignores any \n it finds during processing.
 | ||||
| func readPasswordLine(reader io.Reader) ([]byte, error) { | ||||
| 	var buf [1]byte | ||||
| 	var ret []byte | ||||
| 
 | ||||
| 	for { | ||||
| 		n, err := reader.Read(buf[:]) | ||||
| 		if n > 0 { | ||||
| 			switch buf[0] { | ||||
| 			case '\b': | ||||
| 				if len(ret) > 0 { | ||||
| 					ret = ret[:len(ret)-1] | ||||
| 				} | ||||
| 			case '\n': | ||||
| 				if runtime.GOOS != "windows" { | ||||
| 					return ret, nil | ||||
| 				} | ||||
| 				// otherwise ignore \n
 | ||||
| 			case '\r': | ||||
| 				if runtime.GOOS == "windows" { | ||||
| 					return ret, nil | ||||
| 				} | ||||
| 				// otherwise ignore \r
 | ||||
| 			default: | ||||
| 				ret = append(ret, buf[0]) | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			if err == io.EOF && len(ret) > 0 { | ||||
| 				return ret, nil | ||||
| 			} | ||||
| 			return ret, err | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -395,6 +395,10 @@ github.com/prometheus/common/promlog/flag | |||
| github.com/prometheus/common/route | ||||
| github.com/prometheus/common/server | ||||
| github.com/prometheus/common/version | ||||
| # github.com/prometheus/exporter-toolkit v0.4.0 | ||||
| ## explicit | ||||
| github.com/prometheus/exporter-toolkit/https | ||||
| github.com/prometheus/exporter-toolkit/https/kingpinflag | ||||
| # github.com/prometheus/procfs v0.2.0 | ||||
| github.com/prometheus/procfs | ||||
| github.com/prometheus/procfs/internal/fs | ||||
|  | @ -472,7 +476,9 @@ go.uber.org/atomic | |||
| ## explicit | ||||
| go.uber.org/goleak | ||||
| go.uber.org/goleak/internal/stack | ||||
| # golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 | ||||
| # golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 | ||||
| golang.org/x/crypto/bcrypt | ||||
| golang.org/x/crypto/blowfish | ||||
| golang.org/x/crypto/ed25519 | ||||
| golang.org/x/crypto/ed25519/internal/edwards25519 | ||||
| golang.org/x/crypto/pkcs12 | ||||
|  | @ -515,8 +521,11 @@ golang.org/x/sync/errgroup | |||
| # golang.org/x/sys v0.0.0-20201223074533-0d417f636930 | ||||
| ## explicit | ||||
| golang.org/x/sys/internal/unsafeheader | ||||
| golang.org/x/sys/plan9 | ||||
| golang.org/x/sys/unix | ||||
| golang.org/x/sys/windows | ||||
| # golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 | ||||
| golang.org/x/term | ||||
| # golang.org/x/text v0.3.4 | ||||
| golang.org/x/text/secure/bidirule | ||||
| golang.org/x/text/transform | ||||
|  |  | |||
							
								
								
									
										12
									
								
								web/web.go
								
								
								
								
							
							
						
						
									
										12
									
								
								web/web.go
								
								
								
								
							|  | @ -50,6 +50,7 @@ import ( | |||
| 	"github.com/prometheus/common/model" | ||||
| 	"github.com/prometheus/common/route" | ||||
| 	"github.com/prometheus/common/server" | ||||
| 	"github.com/prometheus/exporter-toolkit/https" | ||||
| 	"go.uber.org/atomic" | ||||
| 	"golang.org/x/net/netutil" | ||||
| 
 | ||||
|  | @ -543,7 +544,14 @@ func (h *Handler) Listener() (net.Listener, error) { | |||
| } | ||||
| 
 | ||||
| // Run serves the HTTP endpoints.
 | ||||
| func (h *Handler) Run(ctx context.Context, listener net.Listener) error { | ||||
| func (h *Handler) Run(ctx context.Context, listener net.Listener, httpsConfig string) error { | ||||
| 	if listener == nil { | ||||
| 		var err error | ||||
| 		listener, err = h.Listener() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	operationName := nethttp.OperationNameFunc(func(r *http.Request) string { | ||||
| 		return fmt.Sprintf("%s %s", r.Method, r.URL.Path) | ||||
| 	}) | ||||
|  | @ -572,7 +580,7 @@ func (h *Handler) Run(ctx context.Context, listener net.Listener) error { | |||
| 
 | ||||
| 	errCh := make(chan error) | ||||
| 	go func() { | ||||
| 		errCh <- httpSrv.Serve(listener) | ||||
| 		errCh <- https.Serve(listener, httpSrv, httpsConfig, h.logger) | ||||
| 	}() | ||||
| 
 | ||||
| 	select { | ||||
|  |  | |||
|  | @ -151,7 +151,7 @@ func TestReadyAndHealthy(t *testing.T) { | |||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	defer cancel() | ||||
| 	go func() { | ||||
| 		err := webHandler.Run(ctx, l) | ||||
| 		err := webHandler.Run(ctx, l, "") | ||||
| 		if err != nil { | ||||
| 			panic(fmt.Sprintf("Can't start web handler:%s", err)) | ||||
| 		} | ||||
|  | @ -263,7 +263,7 @@ func TestRoutePrefix(t *testing.T) { | |||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	defer cancel() | ||||
| 	go func() { | ||||
| 		err := webHandler.Run(ctx, l) | ||||
| 		err := webHandler.Run(ctx, l, "") | ||||
| 		if err != nil { | ||||
| 			panic(fmt.Sprintf("Can't start web handler:%s", err)) | ||||
| 		} | ||||
|  | @ -437,7 +437,7 @@ func TestShutdownWithStaleConnection(t *testing.T) { | |||
| 
 | ||||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	go func() { | ||||
| 		err := webHandler.Run(ctx, l) | ||||
| 		err := webHandler.Run(ctx, l, "") | ||||
| 		if err != nil { | ||||
| 			panic(fmt.Sprintf("Can't start web handler:%s", err)) | ||||
| 		} | ||||
|  | @ -486,7 +486,7 @@ func TestHandleMultipleQuitRequests(t *testing.T) { | |||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	closed := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		err := webHandler.Run(ctx, l) | ||||
| 		err := webHandler.Run(ctx, l, "") | ||||
| 		if err != nil { | ||||
| 			panic(fmt.Sprintf("Can't start web handler:%s", err)) | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue