Merge pull request #957 from antechrestos/fix/scopes_asked_to_remote_registry
Upgrade go-containerregistry third-party library
This commit is contained in:
		
						commit
						65cd9124d1
					
				
							
								
								
									
										80
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										80
									
								
								go.mod
								
								
								
								
							|  | @ -2,114 +2,70 @@ module github.com/GoogleContainerTools/kaniko | |||
| 
 | ||||
| go 1.13 | ||||
| 
 | ||||
| replace ( | ||||
| 	github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf => github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf | ||||
| 	github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker v0.0.0-20190319215453-e7b5f7dbe98c | ||||
| 	github.com/tonistiigi/fsutil v0.0.0-20190819224149-3d2716dd0a4d => github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1 | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	cloud.google.com/go v0.25.0 | ||||
| 	cloud.google.com/go v0.26.0 | ||||
| 	github.com/Azure/azure-pipeline-go v0.2.2 // indirect | ||||
| 	github.com/Azure/azure-sdk-for-go v19.1.0+incompatible // indirect | ||||
| 	github.com/Azure/azure-storage-blob-go v0.8.0 | ||||
| 	github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect | ||||
| 	github.com/Azure/go-autorest v10.15.0+incompatible // indirect | ||||
| 	github.com/Microsoft/go-winio v0.4.9 // indirect | ||||
| 	github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect | ||||
| 	github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 // indirect | ||||
| 	github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect | ||||
| 	github.com/aws/aws-sdk-go v1.25.19 | ||||
| 	github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect | ||||
| 	github.com/boltdb/bolt v1.3.1 // indirect | ||||
| 	github.com/containerd/containerd v1.1.2 // indirect | ||||
| 	github.com/containerd/continuity v0.0.0-20180712174259-0377f7d76720 // indirect | ||||
| 	github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 // indirect | ||||
| 	github.com/coreos/etcd v3.3.9+incompatible // indirect | ||||
| 	github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | ||||
| 	github.com/docker/distribution v2.6.0-rc.1.0.20180720172123-0dae0957e5fe+incompatible // indirect | ||||
| 	github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197 | ||||
| 	github.com/docker/go-connections v0.4.0 // indirect | ||||
| 	github.com/docker/go-events v0.0.0-20170721190031-9461782956ad // indirect | ||||
| 	github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c | ||||
| 	github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect | ||||
| 	github.com/docker/go-units v0.3.3 // indirect | ||||
| 	github.com/docker/swarmkit v1.12.1-0.20180726190244-7567d47988d8 // indirect | ||||
| 	github.com/emirpasic/gods v1.9.0 // indirect | ||||
| 	github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.4.7 // indirect | ||||
| 	github.com/genuinetools/amicontained v0.4.3 | ||||
| 	github.com/ghodss/yaml v1.0.0 // indirect | ||||
| 	github.com/gliderlabs/ssh v0.2.2 // indirect | ||||
| 	github.com/gogo/protobuf v1.1.1 // indirect | ||||
| 	github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect | ||||
| 	github.com/golang/mock v1.3.1 | ||||
| 	github.com/golang/protobuf v1.1.0 // indirect | ||||
| 	github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a // indirect | ||||
| 	github.com/google/go-cmp v0.2.0 | ||||
| 	github.com/google/go-containerregistry v0.0.0-20190820205713-31e00cede111 | ||||
| 	github.com/google/go-cmp v0.3.0 | ||||
| 	github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed | ||||
| 	github.com/google/go-github v17.0.0+incompatible | ||||
| 	github.com/google/go-querystring v1.0.0 // indirect | ||||
| 	github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect | ||||
| 	github.com/google/martian v2.1.0+incompatible // indirect | ||||
| 	github.com/google/uuid v1.0.0 // indirect | ||||
| 	github.com/googleapis/gax-go v2.0.0+incompatible // indirect | ||||
| 	github.com/googleapis/gnostic v0.2.0 // indirect | ||||
| 	github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect | ||||
| 	github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect | ||||
| 	github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect | ||||
| 	github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa // indirect | ||||
| 	github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71 // indirect | ||||
| 	github.com/hashicorp/go-uuid v1.0.1 // indirect | ||||
| 	github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47 // indirect | ||||
| 	github.com/inconshreveable/mousetrap v1.0.0 // indirect | ||||
| 	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect | ||||
| 	github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be // indirect | ||||
| 	github.com/karrick/godirwalk v1.7.7 | ||||
| 	github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e // indirect | ||||
| 	github.com/mattn/go-ieproxy v0.0.0-20190805055040-f9202b1cfdeb // indirect | ||||
| 	github.com/mattn/go-shellwords v1.0.3 // indirect | ||||
| 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect | ||||
| 	github.com/minio/highwayhash v1.0.0 | ||||
| 	github.com/mitchellh/go-homedir v1.0.0 // indirect | ||||
| 	github.com/moby/buildkit v0.0.0-20180731175856-e57eed420c75 | ||||
| 	github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect | ||||
| 	github.com/opencontainers/go-digest v1.0.0-rc1 // indirect | ||||
| 	github.com/opencontainers/image-spec v1.0.1 // indirect | ||||
| 	github.com/opencontainers/runc v1.0.0-rc5 // indirect | ||||
| 	github.com/moby/buildkit v0.0.0-20191111154543-00bfbab0390c | ||||
| 	github.com/opencontainers/runtime-spec v1.0.1 // indirect | ||||
| 	github.com/opencontainers/selinux v1.0.0-rc1 // indirect | ||||
| 	github.com/opentracing/opentracing-go v1.0.2 // indirect | ||||
| 	github.com/otiai10/copy v1.0.2 | ||||
| 	github.com/pborman/uuid v1.2.0 // indirect | ||||
| 	github.com/pelletier/go-buffruneio v0.2.0 // indirect | ||||
| 	github.com/peterbourgon/diskv v2.0.1+incompatible // indirect | ||||
| 	github.com/pkg/errors v0.8.0 | ||||
| 	github.com/pkg/errors v0.8.1 | ||||
| 	github.com/prometheus/client_golang v0.9.0-pre1.0.20180210140205-a40133b69fbd // indirect | ||||
| 	github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect | ||||
| 	github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 // indirect | ||||
| 	github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect | ||||
| 	github.com/sergi/go-diff v1.0.0 // indirect | ||||
| 	github.com/sirupsen/logrus v1.4.2 | ||||
| 	github.com/spf13/afero v1.2.1 | ||||
| 	github.com/spf13/cobra v0.0.3 | ||||
| 	github.com/spf13/pflag v1.0.1 | ||||
| 	github.com/spf13/cobra v0.0.5 | ||||
| 	github.com/spf13/pflag v1.0.5 | ||||
| 	github.com/src-d/gcfg v1.3.0 // indirect | ||||
| 	github.com/stretchr/testify v1.4.0 // indirect | ||||
| 	github.com/syndtr/gocapability v0.0.0-20180223013746-33e07d32887e // indirect | ||||
| 	github.com/tonistiigi/fsutil v0.0.0-20180725061210-b19464cd1b6a // indirect | ||||
| 	github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1 // indirect | ||||
| 	github.com/vbatts/tar-split v0.10.2 // indirect | ||||
| 	github.com/xanzy/ssh-agent v0.2.0 // indirect | ||||
| 	go.opencensus.io v0.14.0 // indirect | ||||
| 	golang.org/x/net v0.0.0-20190311183353-d8887717615a | ||||
| 	golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc | ||||
| 	golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 | ||||
| 	golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be | ||||
| 	golang.org/x/sync v0.0.0-20190423024810-112230192c58 | ||||
| 	golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect | ||||
| 	google.golang.org/api v0.0.0-20180730000901-31ca0e01cd79 // indirect | ||||
| 	google.golang.org/appengine v1.1.0 // indirect | ||||
| 	google.golang.org/genproto v0.0.0-20180731170733-daca94659cb5 // indirect | ||||
| 	google.golang.org/grpc v1.2.1-0.20180320012744-8124abf74e76 // indirect | ||||
| 	gopkg.in/inf.v0 v0.9.1 // indirect | ||||
| 	gopkg.in/src-d/go-billy.v4 v4.2.0 // indirect | ||||
| 	gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 // indirect | ||||
| 	gopkg.in/src-d/go-git.v4 v4.6.0 | ||||
| 	gopkg.in/warnings.v0 v0.1.2 // indirect | ||||
| 	gotest.tools v2.2.0+incompatible // indirect | ||||
| 	k8s.io/api v0.0.0-20180711052118-183f3326a935 // indirect | ||||
| 	k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d // indirect | ||||
| 	k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137 // indirect | ||||
| 	k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a // indirect | ||||
| 	k8s.io/kubernetes v1.11.1 // indirect | ||||
| ) | ||||
|  |  | |||
							
								
								
									
										345
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										345
									
								
								go.sum
								
								
								
								
							|  | @ -1,62 +1,97 @@ | |||
| cloud.google.com/go v0.25.0 h1:6vD6xZTc8Jo6To8gHxFDRVsMvWFDgY3rugNszcDalN8= | ||||
| cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | ||||
| cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= | ||||
| cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | ||||
| github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= | ||||
| github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY= | ||||
| github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= | ||||
| github.com/Azure/azure-sdk-for-go v19.1.0+incompatible h1:ysqLW+tqZjJWOTE74heH/pDRbr4vlN3yV+dqQYgpyxw= | ||||
| github.com/Azure/azure-sdk-for-go v19.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= | ||||
| github.com/Azure/azure-sdk-for-go v19.1.1+incompatible h1:0nNLU6QNN8FGd3FCQa2e8LAtB3THCJ24aOZ4KbA4Jtk= | ||||
| github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= | ||||
| github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o= | ||||
| github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= | ||||
| github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= | ||||
| github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= | ||||
| github.com/Azure/go-autorest v10.15.0+incompatible h1:GqDO/9r+7tmkU8HI/DNLVkeucncU8jCul1DLeTaA3GI= | ||||
| github.com/Azure/go-autorest v10.15.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= | ||||
| github.com/Microsoft/go-winio v0.4.9 h1:3RbgqgGVqmcpbOiwrjbVtDHLlJBGF6aE+yHmNtBNsFQ= | ||||
| github.com/Microsoft/go-winio v0.4.9/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= | ||||
| github.com/Azure/go-autorest v10.15.5+incompatible h1:vdxx6wM1rVkKt/3niByPVjguoLWkWImOcJNvEykgBzY= | ||||
| github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= | ||||
| github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||||
| github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= | ||||
| github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= | ||||
| github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= | ||||
| github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= | ||||
| github.com/Microsoft/hcsshim v0.8.5/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= | ||||
| github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= | ||||
| github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= | ||||
| github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= | ||||
| github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= | ||||
| github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= | ||||
| github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= | ||||
| github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= | ||||
| github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= | ||||
| github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= | ||||
| github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= | ||||
| github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= | ||||
| github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= | ||||
| github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= | ||||
| github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= | ||||
| github.com/aws/aws-sdk-go v1.25.19 h1:sp3xP91qIAVhWufyn9qM6Zhhn6kX06WJQcmhRj7QTXc= | ||||
| github.com/aws/aws-sdk-go v1.25.19/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= | ||||
| github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= | ||||
| github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= | ||||
| github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= | ||||
| github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= | ||||
| github.com/containerd/containerd v1.1.2 h1:gojrlFOL/4A5zP4BPgK3YrCaVIgAIHZfqGco/+mfJOs= | ||||
| github.com/containerd/containerd v1.1.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= | ||||
| github.com/containerd/continuity v0.0.0-20180712174259-0377f7d76720 h1:T5LkgEMACPq7+VPRnkh51WhyV+Q0waOGGtp37Y82org= | ||||
| github.com/containerd/continuity v0.0.0-20180712174259-0377f7d76720/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= | ||||
| github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 h1:XGyg7oTtD0DoRFhbpV6x1WfV0flKC4UxXU7ab1zC08U= | ||||
| github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= | ||||
| github.com/coreos/etcd v3.3.9+incompatible h1:iKSVPXGNGqroBx4+RmUXv8emeU7y+ucRZSzTYgzLZwM= | ||||
| github.com/coreos/etcd v3.3.9+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= | ||||
| github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | ||||
| github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= | ||||
| github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= | ||||
| github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= | ||||
| github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf h1:juYsQtzJOxIaX5TW/3IU7qlvYU/nALKULBOEdiydFd0= | ||||
| github.com/containerd/containerd v0.0.0-20191014053712-acdcf13d5eaf/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= | ||||
| github.com/containerd/containerd v1.2.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= | ||||
| github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= | ||||
| github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= | ||||
| github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw= | ||||
| github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= | ||||
| github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c h1:KFbqHhDeaHM7IfFtXHfUHMDaUStpM2YwBR+iJCIOsKk= | ||||
| github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= | ||||
| github.com/containerd/go-cni v0.0.0-20190813230227-49fbd9b210f3/go.mod h1:2wlRxCQdiBY+OcjNg5x8kI+5mEL1fGt25L4IzQHYJsM= | ||||
| github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= | ||||
| github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= | ||||
| github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= | ||||
| github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= | ||||
| github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= | ||||
| github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= | ||||
| github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= | ||||
| github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= | ||||
| github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | ||||
| github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= | ||||
| github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= | ||||
| github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | ||||
| github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | ||||
| github.com/docker/distribution v2.6.0-rc.1.0.20180720172123-0dae0957e5fe+incompatible h1:8hsJ081BmnqE+fkFjgasY9S8+otMhlWxHcKSYcKzrpk= | ||||
| github.com/docker/distribution v2.6.0-rc.1.0.20180720172123-0dae0957e5fe+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= | ||||
| github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197 h1:7X3lPJrEEhoUt1UnISqyUB4phKf9aAKVMdFXD63DJO8= | ||||
| github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= | ||||
| github.com/docker/cli v0.0.0-20190321234815-f40f9c240ab0/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= | ||||
| github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558= | ||||
| github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= | ||||
| github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= | ||||
| github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE= | ||||
| github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= | ||||
| github.com/docker/docker v0.0.0-20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= | ||||
| github.com/docker/docker v0.0.0-20190319215453-e7b5f7dbe98c h1:1Pev8v0EhB6Fbu9FHCLzZD74gJdJk+QVmlbezI6OToM= | ||||
| github.com/docker/docker v0.0.0-20190319215453-e7b5f7dbe98c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= | ||||
| github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= | ||||
| github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= | ||||
| github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= | ||||
| github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= | ||||
| github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= | ||||
| github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= | ||||
| github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= | ||||
| github.com/docker/go-events v0.0.0-20170721190031-9461782956ad h1:VXIse57M5C6ezDuCPyq6QmMvEJ2xclYKZ35SfkXdm3E= | ||||
| github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= | ||||
| github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= | ||||
| github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= | ||||
| github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= | ||||
| github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= | ||||
| github.com/docker/go-units v0.3.1/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= | ||||
| github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= | ||||
| github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= | ||||
| github.com/docker/libnetwork v0.8.0-dev.2.0.20190604151032-3c26b4e7495e/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= | ||||
| github.com/docker/swarmkit v1.12.1-0.20180726190244-7567d47988d8 h1:ASmFyV8Sc6XrH1ng0TBPpYLspA8b7qRT84IbrQY1jSY= | ||||
| github.com/docker/swarmkit v1.12.1-0.20180726190244-7567d47988d8/go.mod h1:n3Z4lIEl7g261ptkGDBcYi/3qBMDl9csaAhwi2MPejs= | ||||
| github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= | ||||
| github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= | ||||
| github.com/emirpasic/gods v1.9.0 h1:rUF4PuzEjMChMiNsVjdI+SyLu7rEqpQ5reNFnhC7oFo= | ||||
| github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= | ||||
| github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= | ||||
|  | @ -70,76 +105,119 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= | |||
| github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | ||||
| github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= | ||||
| github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= | ||||
| github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= | ||||
| github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= | ||||
| github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= | ||||
| github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= | ||||
| github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= | ||||
| github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= | ||||
| github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= | ||||
| github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= | ||||
| github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= | ||||
| github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= | ||||
| github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= | ||||
| github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | ||||
| 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/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= | ||||
| github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||||
| github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= | ||||
| github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= | ||||
| github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | ||||
| github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | ||||
| github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= | ||||
| github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= | ||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= | ||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||||
| github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | ||||
| github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= | ||||
| github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= | ||||
| github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
| github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= | ||||
| github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
| github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
| github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
| github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= | ||||
| github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
| github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a h1:ZJu5NB1Bk5ms4vw0Xu4i+jD32SE9jQXyfnOvwhHqlT0= | ||||
| github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | ||||
| github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= | ||||
| github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | ||||
| github.com/google/go-containerregistry v0.0.0-20190820205713-31e00cede111 h1:5F39eE4QsUnAd6iGzt1/zBs3dhX877U2hJyOJHFmQF0= | ||||
| github.com/google/go-containerregistry v0.0.0-20190820205713-31e00cede111/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk= | ||||
| github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= | ||||
| github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
| github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed h1:0AwV9UBwwKPKrfpTYLOKr8ymevanUxrsSEkAo0uU9aA= | ||||
| github.com/google/go-containerregistry v0.0.0-20191218175032-34fb8ff33bed/go.mod h1:rodaC7jYStJ2mjR8Y+5a/jCzcRPFRH74KmqSnJC88co= | ||||
| github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= | ||||
| github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= | ||||
| github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= | ||||
| github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= | ||||
| github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= | ||||
| github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= | ||||
| github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= | ||||
| github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= | ||||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||||
| github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= | ||||
| github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= | ||||
| github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | ||||
| github.com/google/shlex v0.0.0-20150127133951-6f45313302b9/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= | ||||
| github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= | ||||
| github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= | ||||
| github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= | ||||
| github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= | ||||
| github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= | ||||
| github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= | ||||
| github.com/googleapis/gnostic v0.2.2 h1:DcFegQ7+ECdmkJMfVwWlC+89I4esJ7p8nkGt9ainGDk= | ||||
| github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= | ||||
| github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= | ||||
| github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= | ||||
| github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= | ||||
| github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= | ||||
| github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= | ||||
| github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= | ||||
| github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= | ||||
| github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= | ||||
| github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa h1:0nA8i+6Rwqaq9xlpmVxxTwk6rxiEhX+E6Wh4vPNHiS8= | ||||
| github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa/go.mod h1:6ij3Z20p+OhOkCSrA0gImAWoHYQRGbnlcuk6XYTiaRw= | ||||
| github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= | ||||
| github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= | ||||
| github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71 h1:yxxFgVz31vFoKKTtRUNbXLNe4GFnbLKqg+0N7yG42L8= | ||||
| github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE= | ||||
| github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||
| github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= | ||||
| github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||
| github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47 h1:UnszMmmmm5vLwWzDjTFVIkfhvWF1NdrmChl8L2NUDCw= | ||||
| github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||
| github.com/hashicorp/golang-lru v0.0.0-20160207214719-a0d98a5f2880/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||
| github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= | ||||
| github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||
| github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= | ||||
| github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09UnyJyqyW+bFuq864eh+wC7dj65aXmXLRe5to0= | ||||
| github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= | ||||
| github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | ||||
| github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | ||||
| github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= | ||||
| github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= | ||||
| github.com/ishidawataru/sctp v0.0.0-20180213033435-07191f837fed/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8= | ||||
| github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea/go.mod h1:QMdK4dGB3YhEW2BmA1wgGpPYI3HZy/5gD705PXKUVSg= | ||||
| github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= | ||||
| github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= | ||||
| github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= | ||||
| github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= | ||||
| github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= | ||||
| github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= | ||||
| github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | ||||
| github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPUhEF5KNCkrUyqTSA5zWUl8sQ2bfGBE= | ||||
| github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | ||||
| github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= | ||||
| github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | ||||
| github.com/karrick/godirwalk v1.7.7 h1:lLkPCA+C0u1pI4fLFseaupvh5/THlPJIqSPmnGGViKs= | ||||
| github.com/karrick/godirwalk v1.7.7/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= | ||||
| github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8= | ||||
| github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= | ||||
| github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= | ||||
| github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | ||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= | ||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||||
| github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= | ||||
| github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||||
| 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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= | ||||
| github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= | ||||
| 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/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= | ||||
| github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= | ||||
| github.com/mattn/go-ieproxy v0.0.0-20190805055040-f9202b1cfdeb h1:hXqqXzQtJbENrsb+rsIqkVqcg4FUJL0SQFGw08Dgivw= | ||||
|  | @ -148,50 +226,72 @@ github.com/mattn/go-shellwords v1.0.3 h1:K/VxK7SZ+cvuPgFSLKi5QPI9Vr/ipOf4C1gN+nt | |||
| github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= | ||||
| github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA= | ||||
| github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= | ||||
| github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= | ||||
| github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | ||||
| github.com/moby/buildkit v0.0.0-20180731175856-e57eed420c75 h1:xlqeydzXCHEsRtsDyT0rvOBF7t3iTxNSG8gTQk2rfms= | ||||
| github.com/moby/buildkit v0.0.0-20180731175856-e57eed420c75/go.mod h1:nnELdKPRkUAQR6pAB3mRU3+IlbqL3SSaAWqQL8k/K+4= | ||||
| github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= | ||||
| github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | ||||
| github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= | ||||
| github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | ||||
| github.com/moby/buildkit v0.0.0-20191111154543-00bfbab0390c h1:QsHXQZ/5EQsj9IIXVVmTWaeEM0VAhZIrEMJ7XKB1Qu0= | ||||
| github.com/moby/buildkit v0.0.0-20191111154543-00bfbab0390c/go.mod h1:UjmFBX/gZo+/+B1YEiH9Or4s7wBgwvOHhidh3rOtCXw= | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= | ||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||
| github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= | ||||
| github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||
| github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= | ||||
| github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= | ||||
| github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= | ||||
| github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c h1:Hww8mOyEKTeON4bZn7FrlLismspbPc1teNRUVH7wLQ8= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= | ||||
| github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c h1:eSfnfIuwhxZyULg1NNuZycJcYkjYVGYe7FczwQReM6U= | ||||
| github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= | ||||
| github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= | ||||
| github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= | ||||
| github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= | ||||
| github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= | ||||
| github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= | ||||
| github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= | ||||
| github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= | ||||
| github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= | ||||
| github.com/opencontainers/runc v1.0.0-rc5 h1:rYjdzMDXVly2Av0RLs3nf/iVkaWh2UrDhuTdTT2KggQ= | ||||
| github.com/opencontainers/runc v1.0.0-rc5/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= | ||||
| github.com/opencontainers/runc v1.0.0-rc6/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= | ||||
| github.com/opencontainers/runc v1.0.0-rc8.0.20190621203724-f4982d86f7fd h1:w9DJ/JL7fK4VjMoGo4e9gsq2xRhZThNI4PFuAwN8dJ0= | ||||
| github.com/opencontainers/runc v1.0.0-rc8.0.20190621203724-f4982d86f7fd/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= | ||||
| github.com/opencontainers/runtime-spec v0.0.0-20180909173843-eba862dc2470/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= | ||||
| github.com/opencontainers/runtime-spec v1.0.1 h1:wY4pOY8fBdSIvs9+IDHC55thBuEulhzfSgKeC1yFvzQ= | ||||
| github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= | ||||
| github.com/opencontainers/selinux v1.0.0-rc1 h1:Q70KvmpJSrYzryl/d0tC3vWUiTn23cSdStKodlokEPs= | ||||
| github.com/opencontainers/selinux v1.0.0-rc1/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= | ||||
| github.com/opentracing-contrib/go-stdlib v0.0.0-20171029140428-b1a47cfbdd75/go.mod h1:PLldrQSroqzH70Xl+1DQcGnefIbqsKR7UDaiux3zV+w= | ||||
| github.com/opentracing/opentracing-go v0.0.0-20171003133519-1361b9cd60be/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | ||||
| github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= | ||||
| github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | ||||
| github.com/otiai10/copy v0.0.0-20180813032824-7e9a647135a1 h1:A7kMXwDPBTfIVRv2l6XV3U6Su3SzLUzZjxnDDQVZDIY= | ||||
| github.com/otiai10/copy v0.0.0-20180813032824-7e9a647135a1/go.mod h1:pXzZSDlN+HPzSdyIBnKNN9ptD9Hx7iZMWIJPTwo4FPE= | ||||
| github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc= | ||||
| github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= | ||||
| github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs= | ||||
| github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= | ||||
| github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= | ||||
| github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= | ||||
| github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= | ||||
| github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= | ||||
| github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA= | ||||
| github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= | ||||
| github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= | ||||
| github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= | ||||
| github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= | ||||
| github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= | ||||
| github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | ||||
| github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= | ||||
| github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
|  | @ -201,74 +301,156 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f | |||
| github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | ||||
| github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 h1:osmNoEW2SCW3L7EX0km2LYM8HKpNWRiouxjE3XHkyGc= | ||||
| github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= | ||||
| github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0= | ||||
| github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | ||||
| github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= | ||||
| github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= | ||||
| github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= | ||||
| github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | ||||
| github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= | ||||
| github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= | ||||
| github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= | ||||
| github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= | ||||
| github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= | ||||
| github.com/sirupsen/logrus v1.0.3/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= | ||||
| github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | ||||
| github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= | ||||
| github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | ||||
| github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= | ||||
| github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M= | ||||
| github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= | ||||
| github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= | ||||
| github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= | ||||
| github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= | ||||
| github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= | ||||
| github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= | ||||
| github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= | ||||
| github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= | ||||
| github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= | ||||
| github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= | ||||
| github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= | ||||
| github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||||
| github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||||
| github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= | ||||
| github.com/src-d/gcfg v1.3.0 h1:2BEDr8r0I0b8h/fOqwtxCEiq2HJu8n2JGZJQFGXWLjg= | ||||
| github.com/src-d/gcfg v1.3.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= | ||||
| github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||
| github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||
| github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||||
| github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||
| github.com/syndtr/gocapability v0.0.0-20180223013746-33e07d32887e h1:QjF5rxNgRSLHJDwKUvfYP3qOx1vTDzUi/+oSC8FXnCI= | ||||
| github.com/syndtr/gocapability v0.0.0-20180223013746-33e07d32887e/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= | ||||
| github.com/tonistiigi/fsutil v0.0.0-20180725061210-b19464cd1b6a h1:qd/ItJwqOuirA+l39OBtUOLokgzKyqKsHMTdzHpoWFk= | ||||
| github.com/tonistiigi/fsutil v0.0.0-20180725061210-b19464cd1b6a/go.mod h1:eden9dLzAAuNQ0L7whFr6/Mzgz6btsvQpUnxOOI+CCE= | ||||
| github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8= | ||||
| github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= | ||||
| github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1 h1:WRlNtJ2whFMKo95/e6uaNuAnn5TxLcMzczqMcfbIDxo= | ||||
| github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1/go.mod h1:hP47OZfgT1aNVDJj28EnEKaKg6mjPEoS5Tb4BsWCTPs= | ||||
| github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= | ||||
| github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= | ||||
| github.com/uber/jaeger-lib v1.2.1/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= | ||||
| github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= | ||||
| github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= | ||||
| github.com/vbatts/tar-split v0.10.2 h1:CXd7HEKGkTLjBMinpObcJZU5Hm8EKlor2a1JtX6msXQ= | ||||
| github.com/vbatts/tar-split v0.10.2/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g= | ||||
| github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= | ||||
| github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= | ||||
| github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro= | ||||
| github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= | ||||
| github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= | ||||
| go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= | ||||
| go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= | ||||
| go.opencensus.io v0.14.0 h1:1eTLxqxSIAylcKoxnNkdhvvBNZDA8JwkKNXxgyma0IA= | ||||
| go.opencensus.io v0.14.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= | ||||
| golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||
| golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
| golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
| golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= | ||||
| golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
| golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | ||||
| golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= | ||||
| golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||
| golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= | ||||
| golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | ||||
| golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= | ||||
| golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= | ||||
| golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc h1:3ElrZeO6IBP+M8kgu5YFwRo92Gqr+zBg3aooYQ6ziqU= | ||||
| golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | ||||
| golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= | ||||
| golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= | ||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||
| golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= | ||||
| golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190130150945-aca44879d564 h1:o6ENHFwwr1TZ9CUPQcfo1HGvLP1OPsPOTB7xCIOPNmU= | ||||
| golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= | ||||
| golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= | ||||
| golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= | ||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||
| golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM= | ||||
| golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||
| golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||
| golang.org/x/tools v0.0.0-20190425150028-36563e24a262 h1:qsl9y/CJx34tuA7QCPNp86JNJe4spst6Ff8MjvPUdPg= | ||||
| golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | ||||
| golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | ||||
| golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | ||||
| golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | ||||
| golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= | ||||
| golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
| golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
| golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= | ||||
| gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= | ||||
| gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= | ||||
| google.golang.org/api v0.0.0-20180730000901-31ca0e01cd79 h1:wCy2/9bhO1JeP2zZUALrj7ZdZuZoR4mRV57kTxjqRpo= | ||||
| google.golang.org/api v0.0.0-20180730000901-31ca0e01cd79/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= | ||||
| google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= | ||||
| google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | ||||
| google.golang.org/genproto v0.0.0-20180731170733-daca94659cb5 h1:2PjFmwzH/sxgW9CRJDlEiwMHO8rOk1eMDzVL14HC1e4= | ||||
| google.golang.org/genproto v0.0.0-20180731170733-daca94659cb5/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||||
| google.golang.org/grpc v1.2.1-0.20180320012744-8124abf74e76 h1:vTe0EiECbrLSj5+6SXMi+eWwYW/bjmd26LE5lv52YVs= | ||||
| google.golang.org/grpc v1.2.1-0.20180320012744-8124abf74e76/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= | ||||
| google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= | ||||
| google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||||
| google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | ||||
| google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= | ||||
| google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= | ||||
| gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= | ||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | ||||
| gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= | ||||
| gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||||
| gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= | ||||
| gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= | ||||
| gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= | ||||
| gopkg.in/src-d/go-billy.v4 v4.2.0 h1:VGbrP1EsYxtvVPEiHui+4//imr4E5MGEFLx66bQtusg= | ||||
|  | @ -277,25 +459,40 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOA | |||
| gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= | ||||
| gopkg.in/src-d/go-git.v4 v4.6.0 h1:3XrA9Qxiwfj7Iusd7dVYUqxMjJYPsLuBdUeQbwnL/NQ= | ||||
| gopkg.in/src-d/go-git.v4 v4.6.0/go.mod h1:CzbUWqMn4pvmvndg3gnh5iZFmSsbhyhUWdI0IQ60AQo= | ||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | ||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | ||||
| gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= | ||||
| gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= | ||||
| gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= | ||||
| gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= | ||||
| gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= | ||||
| gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= | ||||
| gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= | ||||
| k8s.io/api v0.0.0-20180711052118-183f3326a935 h1:K2hsi4kfw1BvCEKX5J1A51pQtXjico7lOEmSiIHQ3/E= | ||||
| k8s.io/api v0.0.0-20180711052118-183f3326a935/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= | ||||
| k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d h1:MZjlsu9igBoVPZkXpIGoxI6EonqNsXXZU7hhvfQLkd4= | ||||
| k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= | ||||
| honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
| honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= | ||||
| k8s.io/api v0.0.0-20180904230853-4e7be11eab3f h1:DLRkv8Ps4Sdx8Srj+UtGisj4whV7v/HezlHx6QqiZqE= | ||||
| k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= | ||||
| k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512 h1:/Z1m/6oEN6hE2SzWP4BHW2yATeUrBRr+1GxNf1Ny58Y= | ||||
| k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= | ||||
| k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137 h1:4DIWGqvAjLME47asVwjb14H+6bDRu+4h43Ssw6tMAHc= | ||||
| k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= | ||||
| k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= | ||||
| k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= | ||||
| k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= | ||||
| k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= | ||||
| k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= | ||||
| k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= | ||||
| k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= | ||||
| k8s.io/kubernetes v1.11.1 h1:wHOPX+teuYaSlUWfL/b24jMH0n7HECbj4Xt8i7kSZIw= | ||||
| k8s.io/kubernetes v1.11.1/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= | ||||
| k8s.io/kubernetes v1.11.10 h1:wCo67+wmguioiYv0ipIiTaXbVPfFBBjOTgIngeGGG+A= | ||||
| k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= | ||||
| modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= | ||||
| modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= | ||||
| modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= | ||||
| modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= | ||||
| modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= | ||||
| sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= | ||||
| sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= | ||||
|  |  | |||
|  | @ -689,7 +689,7 @@ func getHasher(snapshotMode string) (func(string) (string, error), error) { | |||
| } | ||||
| 
 | ||||
| func resolveOnBuild(stage *config.KanikoStage, config *v1.Config) error { | ||||
| 	if config.OnBuild == nil { | ||||
| 	if config.OnBuild == nil || len(config.OnBuild) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	// Otherwise, parse into commands
 | ||||
|  |  | |||
|  | @ -49,12 +49,12 @@ var ( | |||
| func RetrieveSourceImage(stage config.KanikoStage, opts *config.KanikoOptions) (v1.Image, error) { | ||||
| 	t := timing.Start("Retrieving Source Image") | ||||
| 	defer timing.DefaultRun.Stop(t) | ||||
| 	buildArgs := opts.BuildArgs | ||||
| 	var metaArgsString []string | ||||
| 	var buildArgs []string | ||||
| 
 | ||||
| 	for _, arg := range stage.MetaArgs { | ||||
| 		metaArgsString = append(metaArgsString, fmt.Sprintf("%s=%s", arg.Key, arg.ValueString())) | ||||
| 		buildArgs = append(buildArgs, fmt.Sprintf("%s=%s", arg.Key, arg.ValueString())) | ||||
| 	} | ||||
| 	buildArgs = append(buildArgs, metaArgsString...) | ||||
| 	buildArgs = append(buildArgs, opts.BuildArgs...) | ||||
| 	currentBaseName, err := ResolveEnvironmentReplacement(stage.BaseName, buildArgs, false) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
|  |  | |||
|  | @ -48,10 +48,21 @@ const ( | |||
| 	AllAuthenticatedUsers ACLEntity = "allAuthenticatedUsers" | ||||
| ) | ||||
| 
 | ||||
| // ACLRule represents a grant for a role to an entity (user, group or team) for a Google Cloud Storage object or bucket.
 | ||||
| // ACLRule represents a grant for a role to an entity (user, group or team) for a
 | ||||
| // Google Cloud Storage object or bucket.
 | ||||
| type ACLRule struct { | ||||
| 	Entity      ACLEntity | ||||
| 	EntityID    string | ||||
| 	Role        ACLRole | ||||
| 	Domain      string | ||||
| 	Email       string | ||||
| 	ProjectTeam *ProjectTeam | ||||
| } | ||||
| 
 | ||||
| // ProjectTeam is the project team associated with the entity, if any.
 | ||||
| type ProjectTeam struct { | ||||
| 	ProjectNumber string | ||||
| 	Team          string | ||||
| } | ||||
| 
 | ||||
| // ACLHandle provides operations on an access control list for a Google Cloud Storage bucket or object.
 | ||||
|  | @ -77,7 +88,7 @@ func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) { | |||
| 	return a.bucketDelete(ctx, entity) | ||||
| } | ||||
| 
 | ||||
| // Set sets the permission level for the given entity.
 | ||||
| // Set sets the role for the given entity.
 | ||||
| func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) { | ||||
| 	ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Set") | ||||
| 	defer func() { trace.EndSpan(ctx, err) }() | ||||
|  | @ -117,7 +128,7 @@ func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return toACLRules(acls.Items), nil | ||||
| 	return toObjectACLRules(acls.Items), nil | ||||
| } | ||||
| 
 | ||||
| func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error { | ||||
|  | @ -140,12 +151,7 @@ func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r := make([]ACLRule, len(acls.Items)) | ||||
| 	for i, v := range acls.Items { | ||||
| 		r[i].Entity = ACLEntity(v.Entity) | ||||
| 		r[i].Role = ACLRole(v.Role) | ||||
| 	} | ||||
| 	return r, nil | ||||
| 	return toBucketACLRules(acls.Items), nil | ||||
| } | ||||
| 
 | ||||
| func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRole) error { | ||||
|  | @ -167,15 +173,11 @@ func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRol | |||
| } | ||||
| 
 | ||||
| func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error { | ||||
| 	err := runWithRetry(ctx, func() error { | ||||
| 	return runWithRetry(ctx, func() error { | ||||
| 		req := a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity)) | ||||
| 		a.configureCall(req, ctx) | ||||
| 		return req.Do() | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) { | ||||
|  | @ -190,7 +192,7 @@ func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return toACLRules(acls.Items), nil | ||||
| 	return toObjectACLRules(acls.Items), nil | ||||
| } | ||||
| 
 | ||||
| func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error { | ||||
|  | @ -225,9 +227,7 @@ func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error { | |||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (a *ACLHandle) configureCall(call interface { | ||||
| 	Header() http.Header | ||||
| }, ctx context.Context) { | ||||
| func (a *ACLHandle) configureCall(call interface{ Header() http.Header }, ctx context.Context) { | ||||
| 	vc := reflect.ValueOf(call) | ||||
| 	vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)}) | ||||
| 	if a.userProject != "" { | ||||
|  | @ -236,10 +236,100 @@ func (a *ACLHandle) configureCall(call interface { | |||
| 	setClientHeader(call.Header()) | ||||
| } | ||||
| 
 | ||||
| func toACLRules(items []*raw.ObjectAccessControl) []ACLRule { | ||||
| 	r := make([]ACLRule, 0, len(items)) | ||||
| func toObjectACLRules(items []*raw.ObjectAccessControl) []ACLRule { | ||||
| 	var rs []ACLRule | ||||
| 	for _, item := range items { | ||||
| 		r = append(r, ACLRule{Entity: ACLEntity(item.Entity), Role: ACLRole(item.Role)}) | ||||
| 		rs = append(rs, toObjectACLRule(item)) | ||||
| 	} | ||||
| 	return rs | ||||
| } | ||||
| 
 | ||||
| func toBucketACLRules(items []*raw.BucketAccessControl) []ACLRule { | ||||
| 	var rs []ACLRule | ||||
| 	for _, item := range items { | ||||
| 		rs = append(rs, toBucketACLRule(item)) | ||||
| 	} | ||||
| 	return rs | ||||
| } | ||||
| 
 | ||||
| func toObjectACLRule(a *raw.ObjectAccessControl) ACLRule { | ||||
| 	return ACLRule{ | ||||
| 		Entity:      ACLEntity(a.Entity), | ||||
| 		EntityID:    a.EntityId, | ||||
| 		Role:        ACLRole(a.Role), | ||||
| 		Domain:      a.Domain, | ||||
| 		Email:       a.Email, | ||||
| 		ProjectTeam: toObjectProjectTeam(a.ProjectTeam), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toBucketACLRule(a *raw.BucketAccessControl) ACLRule { | ||||
| 	return ACLRule{ | ||||
| 		Entity:      ACLEntity(a.Entity), | ||||
| 		EntityID:    a.EntityId, | ||||
| 		Role:        ACLRole(a.Role), | ||||
| 		Domain:      a.Domain, | ||||
| 		Email:       a.Email, | ||||
| 		ProjectTeam: toBucketProjectTeam(a.ProjectTeam), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toRawObjectACL(rules []ACLRule) []*raw.ObjectAccessControl { | ||||
| 	if len(rules) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	r := make([]*raw.ObjectAccessControl, 0, len(rules)) | ||||
| 	for _, rule := range rules { | ||||
| 		r = append(r, rule.toRawObjectAccessControl("")) // bucket name unnecessary
 | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
| 
 | ||||
| func toRawBucketACL(rules []ACLRule) []*raw.BucketAccessControl { | ||||
| 	if len(rules) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	r := make([]*raw.BucketAccessControl, 0, len(rules)) | ||||
| 	for _, rule := range rules { | ||||
| 		r = append(r, rule.toRawBucketAccessControl("")) // bucket name unnecessary
 | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
| 
 | ||||
| func (r ACLRule) toRawBucketAccessControl(bucket string) *raw.BucketAccessControl { | ||||
| 	return &raw.BucketAccessControl{ | ||||
| 		Bucket: bucket, | ||||
| 		Entity: string(r.Entity), | ||||
| 		Role:   string(r.Role), | ||||
| 		// The other fields are not settable.
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (r ACLRule) toRawObjectAccessControl(bucket string) *raw.ObjectAccessControl { | ||||
| 	return &raw.ObjectAccessControl{ | ||||
| 		Bucket: bucket, | ||||
| 		Entity: string(r.Entity), | ||||
| 		Role:   string(r.Role), | ||||
| 		// The other fields are not settable.
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toBucketProjectTeam(p *raw.BucketAccessControlProjectTeam) *ProjectTeam { | ||||
| 	if p == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &ProjectTeam{ | ||||
| 		ProjectNumber: p.ProjectNumber, | ||||
| 		Team:          p.Team, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toObjectProjectTeam(p *raw.ObjectAccessControlProjectTeam) *ProjectTeam { | ||||
| 	if p == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &ProjectTeam{ | ||||
| 		ProjectNumber: p.ProjectNumber, | ||||
| 		Team:          p.Team, | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -82,6 +82,12 @@ func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *Buck | |||
| 	} | ||||
| 	req := b.c.raw.Buckets.Insert(projectID, bkt) | ||||
| 	setClientHeader(req.Header()) | ||||
| 	if attrs != nil && attrs.PredefinedACL != "" { | ||||
| 		req.PredefinedAcl(attrs.PredefinedACL) | ||||
| 	} | ||||
| 	if attrs != nil && attrs.PredefinedDefaultObjectACL != "" { | ||||
| 		req.PredefinedDefaultObjectAcl(attrs.PredefinedDefaultObjectACL) | ||||
| 	} | ||||
| 	return runWithRetry(ctx, func() error { _, err := req.Context(ctx).Do(); return err }) | ||||
| } | ||||
| 
 | ||||
|  | @ -188,6 +194,12 @@ func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) ( | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if uattrs.PredefinedACL != "" { | ||||
| 		req.PredefinedAcl(uattrs.PredefinedACL) | ||||
| 	} | ||||
| 	if uattrs.PredefinedDefaultObjectACL != "" { | ||||
| 		req.PredefinedDefaultObjectAcl(uattrs.PredefinedDefaultObjectACL) | ||||
| 	} | ||||
| 	// TODO(jba): retry iff metagen is set?
 | ||||
| 	rb, err := req.Context(ctx).Do() | ||||
| 	if err != nil { | ||||
|  | @ -223,6 +235,20 @@ type BucketAttrs struct { | |||
| 	// apply to new objects when no object ACL is provided.
 | ||||
| 	DefaultObjectACL []ACLRule | ||||
| 
 | ||||
| 	// If not empty, applies a predefined set of access controls. It should be set
 | ||||
| 	// only when creating a bucket.
 | ||||
| 	// It is always empty for BucketAttrs returned from the service.
 | ||||
| 	// See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
 | ||||
| 	// for valid values.
 | ||||
| 	PredefinedACL string | ||||
| 
 | ||||
| 	// If not empty, applies a predefined set of default object access controls.
 | ||||
| 	// It should be set only when creating a bucket.
 | ||||
| 	// It is always empty for BucketAttrs returned from the service.
 | ||||
| 	// See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
 | ||||
| 	// for valid values.
 | ||||
| 	PredefinedDefaultObjectACL string | ||||
| 
 | ||||
| 	// Location is the location of the bucket. It defaults to "US".
 | ||||
| 	Location string | ||||
| 
 | ||||
|  | @ -272,6 +298,12 @@ type BucketAttrs struct { | |||
| 
 | ||||
| 	// The encryption configuration used by default for newly inserted objects.
 | ||||
| 	Encryption *BucketEncryption | ||||
| 
 | ||||
| 	// The logging configuration.
 | ||||
| 	Logging *BucketLogging | ||||
| 
 | ||||
| 	// The website configuration.
 | ||||
| 	Website *BucketWebsite | ||||
| } | ||||
| 
 | ||||
| // Lifecycle is the lifecycle configuration for objects in the bucket.
 | ||||
|  | @ -389,6 +421,34 @@ type LifecycleCondition struct { | |||
| 	NumNewerVersions int64 | ||||
| } | ||||
| 
 | ||||
| // BucketLogging holds the bucket's logging configuration, which defines the
 | ||||
| // destination bucket and optional name prefix for the current bucket's
 | ||||
| // logs.
 | ||||
| type BucketLogging struct { | ||||
| 	// The destination bucket where the current bucket's logs
 | ||||
| 	// should be placed.
 | ||||
| 	LogBucket string | ||||
| 
 | ||||
| 	// A prefix for log object names.
 | ||||
| 	LogObjectPrefix string | ||||
| } | ||||
| 
 | ||||
| // Website holds the bucket's website configuration, controlling how the
 | ||||
| // service behaves when accessing bucket contents as a web site. See
 | ||||
| // https://cloud.google.com/storage/docs/static-website for more information.
 | ||||
| type BucketWebsite struct { | ||||
| 	// If the requested object path is missing, the service will ensure the path has
 | ||||
| 	// a trailing '/', append this suffix, and attempt to retrieve the resulting
 | ||||
| 	// object. This allows the creation of index.html objects to represent directory
 | ||||
| 	// pages.
 | ||||
| 	MainPageSuffix string | ||||
| 
 | ||||
| 	// If the requested object path is missing, and any mainPageSuffix object is
 | ||||
| 	// missing, if applicable, the service will return the named object from this
 | ||||
| 	// bucket as the content for a 404 Not Found result.
 | ||||
| 	NotFoundPage string | ||||
| } | ||||
| 
 | ||||
| func newBucket(b *raw.Bucket) (*BucketAttrs, error) { | ||||
| 	if b == nil { | ||||
| 		return nil, nil | ||||
|  | @ -397,52 +457,28 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	bucket := &BucketAttrs{ | ||||
| 	return &BucketAttrs{ | ||||
| 		Name:              b.Name, | ||||
| 		Location:          b.Location, | ||||
| 		MetaGeneration:    b.Metageneration, | ||||
| 		StorageClass:      b.StorageClass, | ||||
| 		Created:           convertTime(b.TimeCreated), | ||||
| 		VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled, | ||||
| 		ACL:               toBucketACLRules(b.Acl), | ||||
| 		DefaultObjectACL:  toObjectACLRules(b.DefaultObjectAcl), | ||||
| 		Labels:            b.Labels, | ||||
| 		RequesterPays:     b.Billing != nil && b.Billing.RequesterPays, | ||||
| 		Lifecycle:         toLifecycle(b.Lifecycle), | ||||
| 		RetentionPolicy:   rp, | ||||
| 		CORS:              toCORS(b.Cors), | ||||
| 		Encryption:        toBucketEncryption(b.Encryption), | ||||
| 	} | ||||
| 	acl := make([]ACLRule, len(b.Acl)) | ||||
| 	for i, rule := range b.Acl { | ||||
| 		acl[i] = ACLRule{ | ||||
| 			Entity: ACLEntity(rule.Entity), | ||||
| 			Role:   ACLRole(rule.Role), | ||||
| 		} | ||||
| 	} | ||||
| 	bucket.ACL = acl | ||||
| 	objACL := make([]ACLRule, len(b.DefaultObjectAcl)) | ||||
| 	for i, rule := range b.DefaultObjectAcl { | ||||
| 		objACL[i] = ACLRule{ | ||||
| 			Entity: ACLEntity(rule.Entity), | ||||
| 			Role:   ACLRole(rule.Role), | ||||
| 		} | ||||
| 	} | ||||
| 	bucket.DefaultObjectACL = objACL | ||||
| 	return bucket, nil | ||||
| 		Logging:           toBucketLogging(b.Logging), | ||||
| 		Website:           toBucketWebsite(b.Website), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // toRawBucket copies the editable attribute from b to the raw library's Bucket type.
 | ||||
| func (b *BucketAttrs) toRawBucket() *raw.Bucket { | ||||
| 	var acl []*raw.BucketAccessControl | ||||
| 	if len(b.ACL) > 0 { | ||||
| 		acl = make([]*raw.BucketAccessControl, len(b.ACL)) | ||||
| 		for i, rule := range b.ACL { | ||||
| 			acl[i] = &raw.BucketAccessControl{ | ||||
| 				Entity: string(rule.Entity), | ||||
| 				Role:   string(rule.Role), | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	dACL := toRawObjectACL(b.DefaultObjectACL) | ||||
| 	// Copy label map.
 | ||||
| 	var labels map[string]string | ||||
| 	if len(b.Labels) > 0 { | ||||
|  | @ -464,10 +500,10 @@ func (b *BucketAttrs) toRawBucket() *raw.Bucket { | |||
| 	} | ||||
| 	return &raw.Bucket{ | ||||
| 		Name:             b.Name, | ||||
| 		DefaultObjectAcl: dACL, | ||||
| 		Location:         b.Location, | ||||
| 		StorageClass:     b.StorageClass, | ||||
| 		Acl:              acl, | ||||
| 		Acl:              toRawBucketACL(b.ACL), | ||||
| 		DefaultObjectAcl: toRawObjectACL(b.DefaultObjectACL), | ||||
| 		Versioning:       v, | ||||
| 		Labels:           labels, | ||||
| 		Billing:          bb, | ||||
|  | @ -475,6 +511,8 @@ func (b *BucketAttrs) toRawBucket() *raw.Bucket { | |||
| 		RetentionPolicy:  b.RetentionPolicy.toRawRetentionPolicy(), | ||||
| 		Cors:             toRawCORS(b.CORS), | ||||
| 		Encryption:       b.Encryption.toRawBucketEncryption(), | ||||
| 		Logging:          b.Logging.toRawBucketLogging(), | ||||
| 		Website:          b.Website.toRawBucketWebsite(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -536,6 +574,20 @@ type BucketAttrsToUpdate struct { | |||
| 	// If set, replaces the lifecycle configuration of the bucket.
 | ||||
| 	Lifecycle *Lifecycle | ||||
| 
 | ||||
| 	// If set, replaces the logging configuration of the bucket.
 | ||||
| 	Logging *BucketLogging | ||||
| 
 | ||||
| 	// If set, replaces the website configuration of the bucket.
 | ||||
| 	Website *BucketWebsite | ||||
| 
 | ||||
| 	// If not empty, applies a predefined set of access controls.
 | ||||
| 	// See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
 | ||||
| 	PredefinedACL string | ||||
| 
 | ||||
| 	// If not empty, applies a predefined set of default object access controls.
 | ||||
| 	// See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
 | ||||
| 	PredefinedDefaultObjectACL string | ||||
| 
 | ||||
| 	setLabels    map[string]string | ||||
| 	deleteLabels map[string]bool | ||||
| } | ||||
|  | @ -595,6 +647,32 @@ func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket { | |||
| 	if ua.Lifecycle != nil { | ||||
| 		rb.Lifecycle = toRawLifecycle(*ua.Lifecycle) | ||||
| 	} | ||||
| 	if ua.Logging != nil { | ||||
| 		if *ua.Logging == (BucketLogging{}) { | ||||
| 			rb.NullFields = append(rb.NullFields, "Logging") | ||||
| 			rb.Logging = nil | ||||
| 		} else { | ||||
| 			rb.Logging = ua.Logging.toRawBucketLogging() | ||||
| 		} | ||||
| 	} | ||||
| 	if ua.Website != nil { | ||||
| 		if *ua.Website == (BucketWebsite{}) { | ||||
| 			rb.NullFields = append(rb.NullFields, "Website") | ||||
| 			rb.Website = nil | ||||
| 		} else { | ||||
| 			rb.Website = ua.Website.toRawBucketWebsite() | ||||
| 		} | ||||
| 	} | ||||
| 	if ua.PredefinedACL != "" { | ||||
| 		// Clear ACL or the call will fail.
 | ||||
| 		rb.Acl = nil | ||||
| 		rb.ForceSendFields = append(rb.ForceSendFields, "Acl") | ||||
| 	} | ||||
| 	if ua.PredefinedDefaultObjectACL != "" { | ||||
| 		// Clear ACLs or the call will fail.
 | ||||
| 		rb.DefaultObjectAcl = nil | ||||
| 		rb.ForceSendFields = append(rb.ForceSendFields, "DefaultObjectAcl") | ||||
| 	} | ||||
| 	if ua.setLabels != nil || ua.deleteLabels != nil { | ||||
| 		rb.Labels = map[string]string{} | ||||
| 		for k, v := range ua.setLabels { | ||||
|  | @ -836,6 +914,46 @@ func toBucketEncryption(e *raw.BucketEncryption) *BucketEncryption { | |||
| 	return &BucketEncryption{DefaultKMSKeyName: e.DefaultKmsKeyName} | ||||
| } | ||||
| 
 | ||||
| func (b *BucketLogging) toRawBucketLogging() *raw.BucketLogging { | ||||
| 	if b == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &raw.BucketLogging{ | ||||
| 		LogBucket:       b.LogBucket, | ||||
| 		LogObjectPrefix: b.LogObjectPrefix, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toBucketLogging(b *raw.BucketLogging) *BucketLogging { | ||||
| 	if b == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &BucketLogging{ | ||||
| 		LogBucket:       b.LogBucket, | ||||
| 		LogObjectPrefix: b.LogObjectPrefix, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (w *BucketWebsite) toRawBucketWebsite() *raw.BucketWebsite { | ||||
| 	if w == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &raw.BucketWebsite{ | ||||
| 		MainPageSuffix: w.MainPageSuffix, | ||||
| 		NotFoundPage:   w.NotFoundPage, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toBucketWebsite(w *raw.BucketWebsite) *BucketWebsite { | ||||
| 	if w == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return &BucketWebsite{ | ||||
| 		MainPageSuffix: w.MainPageSuffix, | ||||
| 		NotFoundPage:   w.NotFoundPage, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Objects returns an iterator over the objects in the bucket that match the Query q.
 | ||||
| // If q is nil, no filtering is done.
 | ||||
| func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator { | ||||
|  |  | |||
|  | @ -115,6 +115,9 @@ func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.Rewr | |||
| 	if c.DestinationKMSKeyName != "" { | ||||
| 		call.DestinationKmsKeyName(c.DestinationKMSKeyName) | ||||
| 	} | ||||
| 	if c.PredefinedACL != "" { | ||||
| 		call.DestinationPredefinedAcl(c.PredefinedACL) | ||||
| 	} | ||||
| 	if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -209,6 +212,9 @@ func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err error) { | |||
| 	if c.dst.userProject != "" { | ||||
| 		call.UserProject(c.dst.userProject) | ||||
| 	} | ||||
| 	if c.PredefinedACL != "" { | ||||
| 		call.DestinationPredefinedAcl(c.PredefinedACL) | ||||
| 	} | ||||
| 	if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  |  | |||
|  | @ -22,9 +22,11 @@ https://cloud.google.com/storage/docs. | |||
| See https://godoc.org/cloud.google.com/go for authentication, timeouts,
 | ||||
| connection pooling and similar aspects of this package. | ||||
| 
 | ||||
| All of the methods of this package use exponential backoff to retry calls | ||||
| that fail with certain errors, as described in | ||||
| https://cloud.google.com/storage/docs/exponential-backoff.
 | ||||
| All of the methods of this package use exponential backoff to retry calls that fail | ||||
| with certain errors, as described in | ||||
| https://cloud.google.com/storage/docs/exponential-backoff. Retrying continues
 | ||||
| indefinitely unless the controlling context is canceled or the client is closed. See | ||||
| context.WithTimeout and context.WithCancel. | ||||
| 
 | ||||
| 
 | ||||
| Creating a Client | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ func shouldRetry(err error) bool { | |||
| 		// Retry on 429 and 5xx, according to
 | ||||
| 		// https://cloud.google.com/storage/docs/exponential-backoff.
 | ||||
| 		return e.Code == 429 || (e.Code >= 500 && e.Code < 600) | ||||
| 	case interface{ Temporary() bool }: | ||||
| 		return e.Temporary() | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
|  |  | |||
|  | @ -34,6 +34,8 @@ func shouldRetry(err error) bool { | |||
| 		// Unfortunately the error type is unexported, so we resort to string
 | ||||
| 		// matching.
 | ||||
| 		return strings.Contains(e.Error(), "REFUSED_STREAM") | ||||
| 	case interface{ Temporary() bool }: | ||||
| 		return e.Temporary() | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
|  |  | |||
|  | @ -467,6 +467,9 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) ( | |||
| 	if o.userProject != "" { | ||||
| 		call.UserProject(o.userProject) | ||||
| 	} | ||||
| 	if uattrs.PredefinedACL != "" { | ||||
| 		call.PredefinedAcl(uattrs.PredefinedACL) | ||||
| 	} | ||||
| 	if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -501,6 +504,10 @@ type ObjectAttrsToUpdate struct { | |||
| 	CacheControl       optional.String | ||||
| 	Metadata           map[string]string // set to map[string]string{} to delete
 | ||||
| 	ACL                []ACLRule | ||||
| 
 | ||||
| 	// If not empty, applies a predefined set of access controls. ACL must be nil.
 | ||||
| 	// See https://cloud.google.com/storage/docs/json_api/v1/objects/patch.
 | ||||
| 	PredefinedACL string | ||||
| } | ||||
| 
 | ||||
| // Delete deletes the single specified object.
 | ||||
|  | @ -595,23 +602,8 @@ func parseKey(key []byte) (*rsa.PrivateKey, error) { | |||
| 	return parsed, nil | ||||
| } | ||||
| 
 | ||||
| func toRawObjectACL(oldACL []ACLRule) []*raw.ObjectAccessControl { | ||||
| 	var acl []*raw.ObjectAccessControl | ||||
| 	if len(oldACL) > 0 { | ||||
| 		acl = make([]*raw.ObjectAccessControl, len(oldACL)) | ||||
| 		for i, rule := range oldACL { | ||||
| 			acl[i] = &raw.ObjectAccessControl{ | ||||
| 				Entity: string(rule.Entity), | ||||
| 				Role:   string(rule.Role), | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return acl | ||||
| } | ||||
| 
 | ||||
| // toRawObject copies the editable attributes from o to the raw library's Object type.
 | ||||
| func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object { | ||||
| 	acl := toRawObjectACL(o.ACL) | ||||
| 	return &raw.Object{ | ||||
| 		Bucket:             bucket, | ||||
| 		Name:               o.Name, | ||||
|  | @ -621,7 +613,7 @@ func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object { | |||
| 		CacheControl:       o.CacheControl, | ||||
| 		ContentDisposition: o.ContentDisposition, | ||||
| 		StorageClass:       o.StorageClass, | ||||
| 		Acl:                acl, | ||||
| 		Acl:                toRawObjectACL(o.ACL), | ||||
| 		Metadata:           o.Metadata, | ||||
| 	} | ||||
| } | ||||
|  | @ -649,6 +641,14 @@ type ObjectAttrs struct { | |||
| 	// ACL is the list of access control rules for the object.
 | ||||
| 	ACL []ACLRule | ||||
| 
 | ||||
| 	// If not empty, applies a predefined set of access controls. It should be set
 | ||||
| 	// only when writing, copying or composing an object. When copying or composing,
 | ||||
| 	// it acts as the destinationPredefinedAcl parameter.
 | ||||
| 	// PredefinedACL is always empty for ObjectAttrs returned from the service.
 | ||||
| 	// See https://cloud.google.com/storage/docs/json_api/v1/objects/insert
 | ||||
| 	// for valid values.
 | ||||
| 	PredefinedACL string | ||||
| 
 | ||||
| 	// Owner is the owner of the object. This field is read-only.
 | ||||
| 	//
 | ||||
| 	// If non-zero, it is in the form of "user-<userId>".
 | ||||
|  | @ -751,13 +751,6 @@ func newObject(o *raw.Object) *ObjectAttrs { | |||
| 	if o == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	acl := make([]ACLRule, len(o.Acl)) | ||||
| 	for i, rule := range o.Acl { | ||||
| 		acl[i] = ACLRule{ | ||||
| 			Entity: ACLEntity(rule.Entity), | ||||
| 			Role:   ACLRole(rule.Role), | ||||
| 		} | ||||
| 	} | ||||
| 	owner := "" | ||||
| 	if o.Owner != nil { | ||||
| 		owner = o.Owner.Entity | ||||
|  | @ -774,7 +767,7 @@ func newObject(o *raw.Object) *ObjectAttrs { | |||
| 		ContentType:        o.ContentType, | ||||
| 		ContentLanguage:    o.ContentLanguage, | ||||
| 		CacheControl:       o.CacheControl, | ||||
| 		ACL:                acl, | ||||
| 		ACL:                toObjectACLRules(o.Acl), | ||||
| 		Owner:              owner, | ||||
| 		ContentEncoding:    o.ContentEncoding, | ||||
| 		ContentDisposition: o.ContentDisposition, | ||||
|  |  | |||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -125,6 +125,9 @@ func (w *Writer) open() error { | |||
| 		if attrs.KMSKeyName != "" { | ||||
| 			call.KmsKeyName(attrs.KMSKeyName) | ||||
| 		} | ||||
| 		if attrs.PredefinedACL != "" { | ||||
| 			call.PredefinedAcl(attrs.PredefinedACL) | ||||
| 		} | ||||
| 		if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil { | ||||
| 			w.mu.Lock() | ||||
| 			w.err = err | ||||
|  |  | |||
|  | @ -18,4 +18,4 @@ package version | |||
| // Changes may cause incorrect behavior and will be lost if the code is regenerated.
 | ||||
| 
 | ||||
| // Number contains the semantic version of this SDK.
 | ||||
| const Number = "v19.1.0" | ||||
| const Number = "v19.1.1" | ||||
|  |  | |||
|  | @ -119,7 +119,10 @@ func (f *Future) Done(sender autorest.Sender) (bool, error) { | |||
| 	if err := f.pt.updatePollingState(f.pt.provisioningStateApplicable()); err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	if err := f.pt.updateHeaders(); err != nil { | ||||
| 	if err := f.pt.initPollingMethod(); err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	if err := f.pt.updatePollingMethod(); err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return f.pt.hasTerminated(), f.pt.pollingError() | ||||
|  | @ -264,7 +267,7 @@ type pollingTracker interface { | |||
| 	// these methods can differ per tracker
 | ||||
| 
 | ||||
| 	// checks the response headers and status code to determine the polling mechanism
 | ||||
| 	updateHeaders() error | ||||
| 	updatePollingMethod() error | ||||
| 
 | ||||
| 	// checks the response for tracker-specific error conditions
 | ||||
| 	checkForErrors() error | ||||
|  | @ -274,6 +277,10 @@ type pollingTracker interface { | |||
| 
 | ||||
| 	// methods common to all trackers
 | ||||
| 
 | ||||
| 	// initializes a tracker's polling URL and method, called for each iteration.
 | ||||
| 	// these values can be overridden by each polling tracker as required.
 | ||||
| 	initPollingMethod() error | ||||
| 
 | ||||
| 	// initializes the tracker's internal state, call this when the tracker is created
 | ||||
| 	initializeState() error | ||||
| 
 | ||||
|  | @ -348,6 +355,10 @@ func (pt *pollingTrackerBase) initializeState() error { | |||
| 	case http.StatusOK: | ||||
| 		if ps := pt.getProvisioningState(); ps != nil { | ||||
| 			pt.State = *ps | ||||
| 			if pt.hasFailed() { | ||||
| 				pt.updateErrorFromResponse() | ||||
| 				return pt.pollingError() | ||||
| 			} | ||||
| 		} else { | ||||
| 			pt.State = operationSucceeded | ||||
| 		} | ||||
|  | @ -364,8 +375,9 @@ func (pt *pollingTrackerBase) initializeState() error { | |||
| 	default: | ||||
| 		pt.State = operationFailed | ||||
| 		pt.updateErrorFromResponse() | ||||
| 		return pt.pollingError() | ||||
| 	} | ||||
| 	return nil | ||||
| 	return pt.initPollingMethod() | ||||
| } | ||||
| 
 | ||||
| func (pt pollingTrackerBase) getProvisioningState() *string { | ||||
|  | @ -416,12 +428,14 @@ func (pt *pollingTrackerBase) pollForStatus(sender autorest.Sender) error { | |||
| 	} else { | ||||
| 		// check response body for error content
 | ||||
| 		pt.updateErrorFromResponse() | ||||
| 		err = pt.pollingError() | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // attempts to unmarshal a ServiceError type from the response body.
 | ||||
| // if that fails then make a best attempt at creating something meaningful.
 | ||||
| // NOTE: this assumes that the async operation has failed.
 | ||||
| func (pt *pollingTrackerBase) updateErrorFromResponse() { | ||||
| 	var err error | ||||
| 	if pt.resp.ContentLength != 0 { | ||||
|  | @ -431,8 +445,7 @@ func (pt *pollingTrackerBase) updateErrorFromResponse() { | |||
| 		re := respErr{} | ||||
| 		defer pt.resp.Body.Close() | ||||
| 		var b []byte | ||||
| 		b, err = ioutil.ReadAll(pt.resp.Body) | ||||
| 		if err != nil { | ||||
| 		if b, err = ioutil.ReadAll(pt.resp.Body); err != nil { | ||||
| 			goto Default | ||||
| 		} | ||||
| 		if err = json.Unmarshal(b, &re); err != nil { | ||||
|  | @ -445,20 +458,29 @@ func (pt *pollingTrackerBase) updateErrorFromResponse() { | |||
| 				goto Default | ||||
| 			} | ||||
| 		} | ||||
| 		if re.ServiceError != nil { | ||||
| 		// the unmarshaller will ensure re.ServiceError is non-nil
 | ||||
| 		// even if there was no content unmarshalled so check the code.
 | ||||
| 		if re.ServiceError.Code != "" { | ||||
| 			pt.Err = re.ServiceError | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| Default: | ||||
| 	se := &ServiceError{ | ||||
| 		Code:    fmt.Sprintf("HTTP status code %v", pt.resp.StatusCode), | ||||
| 		Message: pt.resp.Status, | ||||
| 		Code:    pt.pollingStatus(), | ||||
| 		Message: "The async operation failed.", | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		se.InnerError = make(map[string]interface{}) | ||||
| 		se.InnerError["unmarshalError"] = err.Error() | ||||
| 	} | ||||
| 	// stick the response body into the error object in hopes
 | ||||
| 	// it contains something useful to help diagnose the failure.
 | ||||
| 	if len(pt.rawBody) > 0 { | ||||
| 		se.AdditionalInfo = []map[string]interface{}{ | ||||
| 			pt.rawBody, | ||||
| 		} | ||||
| 	} | ||||
| 	pt.Err = se | ||||
| } | ||||
| 
 | ||||
|  | @ -538,13 +560,33 @@ func (pt pollingTrackerBase) baseCheckForErrors() error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // default initialization of polling URL/method.  each verb tracker will update this as required.
 | ||||
| func (pt *pollingTrackerBase) initPollingMethod() error { | ||||
| 	if ao, err := getURLFromAsyncOpHeader(pt.resp); err != nil { | ||||
| 		return err | ||||
| 	} else if ao != "" { | ||||
| 		pt.URI = ao | ||||
| 		pt.Pm = PollingAsyncOperation | ||||
| 		return nil | ||||
| 	} | ||||
| 	if lh, err := getURLFromLocationHeader(pt.resp); err != nil { | ||||
| 		return err | ||||
| 	} else if lh != "" { | ||||
| 		pt.URI = lh | ||||
| 		pt.Pm = PollingLocation | ||||
| 		return nil | ||||
| 	} | ||||
| 	// it's ok if we didn't find a polling header, this will be handled elsewhere
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // DELETE
 | ||||
| 
 | ||||
| type pollingTrackerDelete struct { | ||||
| 	pollingTrackerBase | ||||
| } | ||||
| 
 | ||||
| func (pt *pollingTrackerDelete) updateHeaders() error { | ||||
| func (pt *pollingTrackerDelete) updatePollingMethod() error { | ||||
| 	// for 201 the Location header is required
 | ||||
| 	if pt.resp.StatusCode == http.StatusCreated { | ||||
| 		if lh, err := getURLFromLocationHeader(pt.resp); err != nil { | ||||
|  | @ -600,7 +642,7 @@ type pollingTrackerPatch struct { | |||
| 	pollingTrackerBase | ||||
| } | ||||
| 
 | ||||
| func (pt *pollingTrackerPatch) updateHeaders() error { | ||||
| func (pt *pollingTrackerPatch) updatePollingMethod() error { | ||||
| 	// by default we can use the original URL for polling and final GET
 | ||||
| 	if pt.URI == "" { | ||||
| 		pt.URI = pt.resp.Request.URL.String() | ||||
|  | @ -658,7 +700,7 @@ type pollingTrackerPost struct { | |||
| 	pollingTrackerBase | ||||
| } | ||||
| 
 | ||||
| func (pt *pollingTrackerPost) updateHeaders() error { | ||||
| func (pt *pollingTrackerPost) updatePollingMethod() error { | ||||
| 	// 201 requires Location header
 | ||||
| 	if pt.resp.StatusCode == http.StatusCreated { | ||||
| 		if lh, err := getURLFromLocationHeader(pt.resp); err != nil { | ||||
|  | @ -714,7 +756,7 @@ type pollingTrackerPut struct { | |||
| 	pollingTrackerBase | ||||
| } | ||||
| 
 | ||||
| func (pt *pollingTrackerPut) updateHeaders() error { | ||||
| func (pt *pollingTrackerPut) updatePollingMethod() error { | ||||
| 	// by default we can use the original URL for polling and final GET
 | ||||
| 	if pt.URI == "" { | ||||
| 		pt.URI = pt.resp.Request.URL.String() | ||||
|  | @ -808,7 +850,7 @@ func createPollingTracker(resp *http.Response) (pollingTracker, error) { | |||
| 	// this initializes the polling header values, we do this during creation in case the
 | ||||
| 	// initial response send us invalid values; this way the API call will return a non-nil
 | ||||
| 	// error (not doing this means the error shows up in Future.Done)
 | ||||
| 	return pt, pt.updateHeaders() | ||||
| 	return pt, pt.updatePollingMethod() | ||||
| } | ||||
| 
 | ||||
| // gets the polling URL from the Azure-AsyncOperation header.
 | ||||
|  |  | |||
|  | @ -234,7 +234,7 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se | |||
| 				} | ||||
| 				delayed := DelayWithRetryAfter(resp, r.Context().Done()) | ||||
| 				if !delayed && !DelayForBackoff(backoff, attempt, r.Context().Done()) { | ||||
| 					return nil, r.Context().Err() | ||||
| 					return resp, r.Context().Err() | ||||
| 				} | ||||
| 				// don't count a 429 against the number of attempts
 | ||||
| 				// so that we continue to retry until it succeeds
 | ||||
|  |  | |||
|  | @ -282,7 +282,7 @@ func (fl fileLogger) WriteRequest(req *http.Request, filter Filter) { | |||
| 	} | ||||
| 	fl.mu.Lock() | ||||
| 	defer fl.mu.Unlock() | ||||
| 	fmt.Fprintf(fl.logFile, b.String()) | ||||
| 	fmt.Fprint(fl.logFile, b.String()) | ||||
| 	fl.logFile.Sync() | ||||
| } | ||||
| 
 | ||||
|  | @ -311,7 +311,7 @@ func (fl fileLogger) WriteResponse(resp *http.Response, filter Filter) { | |||
| 	} | ||||
| 	fl.mu.Lock() | ||||
| 	defer fl.mu.Unlock() | ||||
| 	fmt.Fprintf(fl.logFile, b.String()) | ||||
| 	fmt.Fprint(fl.logFile, b.String()) | ||||
| 	fl.logFile.Sync() | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ import ( | |||
| ) | ||||
| 
 | ||||
| // Number contains the semantic version of this SDK.
 | ||||
| const Number = "v10.15.0" | ||||
| const Number = "v10.15.5" | ||||
| 
 | ||||
| var ( | ||||
| 	userAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s", | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ import ( | |||
| //sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
 | ||||
| //sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
 | ||||
| //sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
 | ||||
| //sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
 | ||||
| 
 | ||||
| type atomicBool int32 | ||||
| 
 | ||||
|  | @ -79,6 +80,7 @@ type win32File struct { | |||
| 	wg            sync.WaitGroup | ||||
| 	wgLock        sync.RWMutex | ||||
| 	closing       atomicBool | ||||
| 	socket        bool | ||||
| 	readDeadline  deadlineHandler | ||||
| 	writeDeadline deadlineHandler | ||||
| } | ||||
|  | @ -109,7 +111,13 @@ func makeWin32File(h syscall.Handle) (*win32File, error) { | |||
| } | ||||
| 
 | ||||
| func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { | ||||
| 	return makeWin32File(h) | ||||
| 	// If we return the result of makeWin32File directly, it can result in an
 | ||||
| 	// interface-wrapped nil, rather than a nil interface value.
 | ||||
| 	f, err := makeWin32File(h) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return f, nil | ||||
| } | ||||
| 
 | ||||
| // closeHandle closes the resources associated with a Win32 handle
 | ||||
|  | @ -190,6 +198,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er | |||
| 			if f.closing.isSet() { | ||||
| 				err = ErrFileClosed | ||||
| 			} | ||||
| 		} else if err != nil && f.socket { | ||||
| 			// err is from Win32. Query the overlapped structure to get the winsock error.
 | ||||
| 			var bytes, flags uint32 | ||||
| 			err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) | ||||
| 		} | ||||
| 	case <-timeout: | ||||
| 		cancelIoEx(f.handle, &c.o) | ||||
|  | @ -265,6 +277,10 @@ func (f *win32File) Flush() error { | |||
| 	return syscall.FlushFileBuffers(f.handle) | ||||
| } | ||||
| 
 | ||||
| func (f *win32File) Fd() uintptr { | ||||
| 	return uintptr(f.handle) | ||||
| } | ||||
| 
 | ||||
| func (d *deadlineHandler) set(deadline time.Time) error { | ||||
| 	d.setLock.Lock() | ||||
| 	defer d.setLock.Unlock() | ||||
|  |  | |||
|  | @ -20,7 +20,8 @@ const ( | |||
| // FileBasicInfo contains file access time and file attributes information.
 | ||||
| type FileBasicInfo struct { | ||||
| 	CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime | ||||
| 	FileAttributes                                          uintptr // includes padding
 | ||||
| 	FileAttributes                                          uint32 | ||||
| 	pad                                                     uint32 // padding
 | ||||
| } | ||||
| 
 | ||||
| // GetFileBasicInfo retrieves times and attributes for a file.
 | ||||
|  |  | |||
|  | @ -0,0 +1,9 @@ | |||
| module github.com/Microsoft/go-winio | ||||
| 
 | ||||
| go 1.12 | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/pkg/errors v0.8.1 | ||||
| 	github.com/sirupsen/logrus v1.4.1 | ||||
| 	golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b | ||||
| ) | ||||
|  | @ -0,0 +1,16 @@ | |||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | ||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||||
| github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | ||||
| github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= | ||||
| github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | ||||
| github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= | ||||
| github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||
| golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA= | ||||
| golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
|  | @ -0,0 +1,305 @@ | |||
| package winio | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
| 
 | ||||
| 	"github.com/Microsoft/go-winio/pkg/guid" | ||||
| ) | ||||
| 
 | ||||
| //sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
 | ||||
| 
 | ||||
| const ( | ||||
| 	afHvSock = 34 // AF_HYPERV
 | ||||
| 
 | ||||
| 	socketError = ^uintptr(0) | ||||
| ) | ||||
| 
 | ||||
| // An HvsockAddr is an address for a AF_HYPERV socket.
 | ||||
| type HvsockAddr struct { | ||||
| 	VMID      guid.GUID | ||||
| 	ServiceID guid.GUID | ||||
| } | ||||
| 
 | ||||
| type rawHvsockAddr struct { | ||||
| 	Family    uint16 | ||||
| 	_         uint16 | ||||
| 	VMID      guid.GUID | ||||
| 	ServiceID guid.GUID | ||||
| } | ||||
| 
 | ||||
| // Network returns the address's network name, "hvsock".
 | ||||
| func (addr *HvsockAddr) Network() string { | ||||
| 	return "hvsock" | ||||
| } | ||||
| 
 | ||||
| func (addr *HvsockAddr) String() string { | ||||
| 	return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID) | ||||
| } | ||||
| 
 | ||||
| // VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
 | ||||
| func VsockServiceID(port uint32) guid.GUID { | ||||
| 	g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3") | ||||
| 	g.Data1 = port | ||||
| 	return g | ||||
| } | ||||
| 
 | ||||
| func (addr *HvsockAddr) raw() rawHvsockAddr { | ||||
| 	return rawHvsockAddr{ | ||||
| 		Family:    afHvSock, | ||||
| 		VMID:      addr.VMID, | ||||
| 		ServiceID: addr.ServiceID, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) { | ||||
| 	addr.VMID = raw.VMID | ||||
| 	addr.ServiceID = raw.ServiceID | ||||
| } | ||||
| 
 | ||||
| // HvsockListener is a socket listener for the AF_HYPERV address family.
 | ||||
| type HvsockListener struct { | ||||
| 	sock *win32File | ||||
| 	addr HvsockAddr | ||||
| } | ||||
| 
 | ||||
| // HvsockConn is a connected socket of the AF_HYPERV address family.
 | ||||
| type HvsockConn struct { | ||||
| 	sock          *win32File | ||||
| 	local, remote HvsockAddr | ||||
| } | ||||
| 
 | ||||
| func newHvSocket() (*win32File, error) { | ||||
| 	fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1) | ||||
| 	if err != nil { | ||||
| 		return nil, os.NewSyscallError("socket", err) | ||||
| 	} | ||||
| 	f, err := makeWin32File(fd) | ||||
| 	if err != nil { | ||||
| 		syscall.Close(fd) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	f.socket = true | ||||
| 	return f, nil | ||||
| } | ||||
| 
 | ||||
| // ListenHvsock listens for connections on the specified hvsock address.
 | ||||
| func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { | ||||
| 	l := &HvsockListener{addr: *addr} | ||||
| 	sock, err := newHvSocket() | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("listen", err) | ||||
| 	} | ||||
| 	sa := addr.raw() | ||||
| 	err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa))) | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("listen", os.NewSyscallError("socket", err)) | ||||
| 	} | ||||
| 	err = syscall.Listen(sock.handle, 16) | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("listen", os.NewSyscallError("listen", err)) | ||||
| 	} | ||||
| 	return &HvsockListener{sock: sock, addr: *addr}, nil | ||||
| } | ||||
| 
 | ||||
| func (l *HvsockListener) opErr(op string, err error) error { | ||||
| 	return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err} | ||||
| } | ||||
| 
 | ||||
| // Addr returns the listener's network address.
 | ||||
| func (l *HvsockListener) Addr() net.Addr { | ||||
| 	return &l.addr | ||||
| } | ||||
| 
 | ||||
| // Accept waits for the next connection and returns it.
 | ||||
| func (l *HvsockListener) Accept() (_ net.Conn, err error) { | ||||
| 	sock, err := newHvSocket() | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("accept", err) | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if sock != nil { | ||||
| 			sock.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	c, err := l.sock.prepareIo() | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("accept", err) | ||||
| 	} | ||||
| 	defer l.sock.wg.Done() | ||||
| 
 | ||||
| 	// AcceptEx, per documentation, requires an extra 16 bytes per address.
 | ||||
| 	const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{})) | ||||
| 	var addrbuf [addrlen * 2]byte | ||||
| 
 | ||||
| 	var bytes uint32 | ||||
| 	err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) | ||||
| 	_, err = l.sock.asyncIo(c, nil, bytes, err) | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) | ||||
| 	} | ||||
| 	conn := &HvsockConn{ | ||||
| 		sock: sock, | ||||
| 	} | ||||
| 	conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0]))) | ||||
| 	conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) | ||||
| 	sock = nil | ||||
| 	return conn, nil | ||||
| } | ||||
| 
 | ||||
| // Close closes the listener, causing any pending Accept calls to fail.
 | ||||
| func (l *HvsockListener) Close() error { | ||||
| 	return l.sock.Close() | ||||
| } | ||||
| 
 | ||||
| /* Need to finish ConnectEx handling | ||||
| func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) { | ||||
| 	sock, err := newHvSocket() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if sock != nil { | ||||
| 			sock.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	c, err := sock.prepareIo() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer sock.wg.Done() | ||||
| 	var bytes uint32 | ||||
| 	err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o) | ||||
| 	_, err = sock.asyncIo(ctx, c, nil, bytes, err) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	conn := &HvsockConn{ | ||||
| 		sock:   sock, | ||||
| 		remote: *addr, | ||||
| 	} | ||||
| 	sock = nil | ||||
| 	return conn, nil | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| func (conn *HvsockConn) opErr(op string, err error) error { | ||||
| 	return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err} | ||||
| } | ||||
| 
 | ||||
| func (conn *HvsockConn) Read(b []byte) (int, error) { | ||||
| 	c, err := conn.sock.prepareIo() | ||||
| 	if err != nil { | ||||
| 		return 0, conn.opErr("read", err) | ||||
| 	} | ||||
| 	defer conn.sock.wg.Done() | ||||
| 	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} | ||||
| 	var flags, bytes uint32 | ||||
| 	err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) | ||||
| 	n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err) | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(syscall.Errno); ok { | ||||
| 			err = os.NewSyscallError("wsarecv", err) | ||||
| 		} | ||||
| 		return 0, conn.opErr("read", err) | ||||
| 	} else if n == 0 { | ||||
| 		err = io.EOF | ||||
| 	} | ||||
| 	return n, err | ||||
| } | ||||
| 
 | ||||
| func (conn *HvsockConn) Write(b []byte) (int, error) { | ||||
| 	t := 0 | ||||
| 	for len(b) != 0 { | ||||
| 		n, err := conn.write(b) | ||||
| 		if err != nil { | ||||
| 			return t + n, err | ||||
| 		} | ||||
| 		t += n | ||||
| 		b = b[n:] | ||||
| 	} | ||||
| 	return t, nil | ||||
| } | ||||
| 
 | ||||
| func (conn *HvsockConn) write(b []byte) (int, error) { | ||||
| 	c, err := conn.sock.prepareIo() | ||||
| 	if err != nil { | ||||
| 		return 0, conn.opErr("write", err) | ||||
| 	} | ||||
| 	defer conn.sock.wg.Done() | ||||
| 	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} | ||||
| 	var bytes uint32 | ||||
| 	err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) | ||||
| 	n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err) | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(syscall.Errno); ok { | ||||
| 			err = os.NewSyscallError("wsasend", err) | ||||
| 		} | ||||
| 		return 0, conn.opErr("write", err) | ||||
| 	} | ||||
| 	return n, err | ||||
| } | ||||
| 
 | ||||
| // Close closes the socket connection, failing any pending read or write calls.
 | ||||
| func (conn *HvsockConn) Close() error { | ||||
| 	return conn.sock.Close() | ||||
| } | ||||
| 
 | ||||
| func (conn *HvsockConn) shutdown(how int) error { | ||||
| 	err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) | ||||
| 	if err != nil { | ||||
| 		return os.NewSyscallError("shutdown", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // CloseRead shuts down the read end of the socket.
 | ||||
| func (conn *HvsockConn) CloseRead() error { | ||||
| 	err := conn.shutdown(syscall.SHUT_RD) | ||||
| 	if err != nil { | ||||
| 		return conn.opErr("close", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // CloseWrite shuts down the write end of the socket, notifying the other endpoint that
 | ||||
| // no more data will be written.
 | ||||
| func (conn *HvsockConn) CloseWrite() error { | ||||
| 	err := conn.shutdown(syscall.SHUT_WR) | ||||
| 	if err != nil { | ||||
| 		return conn.opErr("close", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // LocalAddr returns the local address of the connection.
 | ||||
| func (conn *HvsockConn) LocalAddr() net.Addr { | ||||
| 	return &conn.local | ||||
| } | ||||
| 
 | ||||
| // RemoteAddr returns the remote address of the connection.
 | ||||
| func (conn *HvsockConn) RemoteAddr() net.Addr { | ||||
| 	return &conn.remote | ||||
| } | ||||
| 
 | ||||
| // SetDeadline implements the net.Conn SetDeadline method.
 | ||||
| func (conn *HvsockConn) SetDeadline(t time.Time) error { | ||||
| 	conn.SetReadDeadline(t) | ||||
| 	conn.SetWriteDeadline(t) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SetReadDeadline implements the net.Conn SetReadDeadline method.
 | ||||
| func (conn *HvsockConn) SetReadDeadline(t time.Time) error { | ||||
| 	return conn.sock.SetReadDeadline(t) | ||||
| } | ||||
| 
 | ||||
| // SetWriteDeadline implements the net.Conn SetWriteDeadline method.
 | ||||
| func (conn *HvsockConn) SetWriteDeadline(t time.Time) error { | ||||
| 	return conn.sock.SetWriteDeadline(t) | ||||
| } | ||||
|  | @ -3,10 +3,13 @@ | |||
| package winio | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
|  | @ -18,6 +21,48 @@ import ( | |||
| //sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
 | ||||
| //sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
 | ||||
| //sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
 | ||||
| //sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
 | ||||
| //sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
 | ||||
| //sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
 | ||||
| //sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
 | ||||
| 
 | ||||
| type ioStatusBlock struct { | ||||
| 	Status, Information uintptr | ||||
| } | ||||
| 
 | ||||
| type objectAttributes struct { | ||||
| 	Length             uintptr | ||||
| 	RootDirectory      uintptr | ||||
| 	ObjectName         *unicodeString | ||||
| 	Attributes         uintptr | ||||
| 	SecurityDescriptor *securityDescriptor | ||||
| 	SecurityQoS        uintptr | ||||
| } | ||||
| 
 | ||||
| type unicodeString struct { | ||||
| 	Length        uint16 | ||||
| 	MaximumLength uint16 | ||||
| 	Buffer        uintptr | ||||
| } | ||||
| 
 | ||||
| type securityDescriptor struct { | ||||
| 	Revision byte | ||||
| 	Sbz1     byte | ||||
| 	Control  uint16 | ||||
| 	Owner    uintptr | ||||
| 	Group    uintptr | ||||
| 	Sacl     uintptr | ||||
| 	Dacl     uintptr | ||||
| } | ||||
| 
 | ||||
| type ntstatus int32 | ||||
| 
 | ||||
| func (status ntstatus) Err() error { | ||||
| 	if status >= 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return rtlNtStatusToDosError(status) | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	cERROR_PIPE_BUSY      = syscall.Errno(231) | ||||
|  | @ -25,21 +70,20 @@ const ( | |||
| 	cERROR_PIPE_CONNECTED = syscall.Errno(535) | ||||
| 	cERROR_SEM_TIMEOUT    = syscall.Errno(121) | ||||
| 
 | ||||
| 	cPIPE_ACCESS_DUPLEX            = 0x3 | ||||
| 	cFILE_FLAG_FIRST_PIPE_INSTANCE = 0x80000 | ||||
| 	cSECURITY_SQOS_PRESENT = 0x100000 | ||||
| 	cSECURITY_ANONYMOUS    = 0 | ||||
| 
 | ||||
| 	cPIPE_REJECT_REMOTE_CLIENTS = 0x8 | ||||
| 
 | ||||
| 	cPIPE_UNLIMITED_INSTANCES = 255 | ||||
| 
 | ||||
| 	cNMPWAIT_USE_DEFAULT_WAIT = 0 | ||||
| 	cNMPWAIT_NOWAIT           = 1 | ||||
| 
 | ||||
| 	cPIPE_TYPE_MESSAGE = 4 | ||||
| 
 | ||||
| 	cPIPE_READMODE_MESSAGE = 2 | ||||
| 
 | ||||
| 	cFILE_OPEN   = 1 | ||||
| 	cFILE_CREATE = 2 | ||||
| 
 | ||||
| 	cFILE_PIPE_MESSAGE_TYPE          = 1 | ||||
| 	cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2 | ||||
| 
 | ||||
| 	cSE_DACL_PRESENT = 4 | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -137,9 +181,30 @@ func (s pipeAddress) String() string { | |||
| 	return string(s) | ||||
| } | ||||
| 
 | ||||
| // tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
 | ||||
| func tryDialPipe(ctx context.Context, path *string) (syscall.Handle, error) { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-ctx.Done(): | ||||
| 			return syscall.Handle(0), ctx.Err() | ||||
| 		default: | ||||
| 			h, err := createFile(*path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) | ||||
| 			if err == nil { | ||||
| 				return h, nil | ||||
| 			} | ||||
| 			if err != cERROR_PIPE_BUSY { | ||||
| 				return h, &os.PathError{Err: err, Op: "open", Path: *path} | ||||
| 			} | ||||
| 			// Wait 10 msec and try again. This is a rather simplistic
 | ||||
| 			// view, as we always try each 10 milliseconds.
 | ||||
| 			time.Sleep(time.Millisecond * 10) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // DialPipe connects to a named pipe by path, timing out if the connection
 | ||||
| // takes longer than the specified duration. If timeout is nil, then we use
 | ||||
| // a default timeout of 5 seconds.  (We do not use WaitNamedPipe.)
 | ||||
| // a default timeout of 2 seconds.  (We do not use WaitNamedPipe.)
 | ||||
| func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { | ||||
| 	var absTimeout time.Time | ||||
| 	if timeout != nil { | ||||
|  | @ -147,23 +212,22 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { | |||
| 	} else { | ||||
| 		absTimeout = time.Now().Add(time.Second * 2) | ||||
| 	} | ||||
| 	var err error | ||||
| 	var h syscall.Handle | ||||
| 	for { | ||||
| 		h, err = createFile(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) | ||||
| 		if err != cERROR_PIPE_BUSY { | ||||
| 			break | ||||
| 		} | ||||
| 		if time.Now().After(absTimeout) { | ||||
| 	ctx, _ := context.WithDeadline(context.Background(), absTimeout) | ||||
| 	conn, err := DialPipeContext(ctx, path) | ||||
| 	if err == context.DeadlineExceeded { | ||||
| 		return nil, ErrTimeout | ||||
| 	} | ||||
| 	return conn, err | ||||
| } | ||||
| 
 | ||||
| 		// Wait 10 msec and try again. This is a rather simplistic
 | ||||
| 		// view, as we always try each 10 milliseconds.
 | ||||
| 		time.Sleep(time.Millisecond * 10) | ||||
| 	} | ||||
| // DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
 | ||||
| // cancellation or timeout.
 | ||||
| func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { | ||||
| 	var err error | ||||
| 	var h syscall.Handle | ||||
| 	h, err = tryDialPipe(ctx, &path) | ||||
| 	if err != nil { | ||||
| 		return nil, &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var flags uint32 | ||||
|  | @ -196,41 +260,85 @@ type acceptResponse struct { | |||
| type win32PipeListener struct { | ||||
| 	firstHandle syscall.Handle | ||||
| 	path        string | ||||
| 	securityDescriptor []byte | ||||
| 	config      PipeConfig | ||||
| 	acceptCh    chan (chan acceptResponse) | ||||
| 	closeCh     chan int | ||||
| 	doneCh      chan int | ||||
| } | ||||
| 
 | ||||
| func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig, first bool) (syscall.Handle, error) { | ||||
| 	var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED | ||||
| 	if first { | ||||
| 		flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE | ||||
| 	} | ||||
| 
 | ||||
| 	var mode uint32 = cPIPE_REJECT_REMOTE_CLIENTS | ||||
| 	if c.MessageMode { | ||||
| 		mode |= cPIPE_TYPE_MESSAGE | ||||
| 	} | ||||
| 
 | ||||
| 	sa := &syscall.SecurityAttributes{} | ||||
| 	sa.Length = uint32(unsafe.Sizeof(*sa)) | ||||
| 	if securityDescriptor != nil { | ||||
| 		len := uint32(len(securityDescriptor)) | ||||
| 		sa.SecurityDescriptor = localAlloc(0, len) | ||||
| 		defer localFree(sa.SecurityDescriptor) | ||||
| 		copy((*[0xffff]byte)(unsafe.Pointer(sa.SecurityDescriptor))[:], securityDescriptor) | ||||
| 	} | ||||
| 	h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa) | ||||
| func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) { | ||||
| 	path16, err := syscall.UTF16FromString(path) | ||||
| 	if err != nil { | ||||
| 		return 0, &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 	} | ||||
| 
 | ||||
| 	var oa objectAttributes | ||||
| 	oa.Length = unsafe.Sizeof(oa) | ||||
| 
 | ||||
| 	var ntPath unicodeString | ||||
| 	if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil { | ||||
| 		return 0, &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 	} | ||||
| 	defer localFree(ntPath.Buffer) | ||||
| 	oa.ObjectName = &ntPath | ||||
| 
 | ||||
| 	// The security descriptor is only needed for the first pipe.
 | ||||
| 	if first { | ||||
| 		if sd != nil { | ||||
| 			len := uint32(len(sd)) | ||||
| 			sdb := localAlloc(0, len) | ||||
| 			defer localFree(sdb) | ||||
| 			copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) | ||||
| 			oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) | ||||
| 		} else { | ||||
| 			// Construct the default named pipe security descriptor.
 | ||||
| 			var dacl uintptr | ||||
| 			if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { | ||||
| 				return 0, fmt.Errorf("getting default named pipe ACL: %s", err) | ||||
| 			} | ||||
| 			defer localFree(dacl) | ||||
| 
 | ||||
| 			sdb := &securityDescriptor{ | ||||
| 				Revision: 1, | ||||
| 				Control:  cSE_DACL_PRESENT, | ||||
| 				Dacl:     dacl, | ||||
| 			} | ||||
| 			oa.SecurityDescriptor = sdb | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS) | ||||
| 	if c.MessageMode { | ||||
| 		typ |= cFILE_PIPE_MESSAGE_TYPE | ||||
| 	} | ||||
| 
 | ||||
| 	disposition := uint32(cFILE_OPEN) | ||||
| 	access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) | ||||
| 	if first { | ||||
| 		disposition = cFILE_CREATE | ||||
| 		// By not asking for read or write access, the named pipe file system
 | ||||
| 		// will put this pipe into an initially disconnected state, blocking
 | ||||
| 		// client connections until the next call with first == false.
 | ||||
| 		access = syscall.SYNCHRONIZE | ||||
| 	} | ||||
| 
 | ||||
| 	timeout := int64(-50 * 10000) // 50ms
 | ||||
| 
 | ||||
| 	var ( | ||||
| 		h    syscall.Handle | ||||
| 		iosb ioStatusBlock | ||||
| 	) | ||||
| 	err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() | ||||
| 	if err != nil { | ||||
| 		return 0, &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 	} | ||||
| 
 | ||||
| 	runtime.KeepAlive(ntPath) | ||||
| 	return h, nil | ||||
| } | ||||
| 
 | ||||
| func (l *win32PipeListener) makeServerPipe() (*win32File, error) { | ||||
| 	h, err := makeServerPipeHandle(l.path, l.securityDescriptor, &l.config, false) | ||||
| 	h, err := makeServerPipeHandle(l.path, nil, &l.config, false) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -341,28 +449,9 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// Create a client handle and connect it.  This results in the pipe
 | ||||
| 	// instance always existing, so that clients see ERROR_PIPE_BUSY
 | ||||
| 	// rather than ERROR_FILE_NOT_FOUND.  This ties the first instance
 | ||||
| 	// up so that no other instances can be used.  This would have been
 | ||||
| 	// cleaner if the Win32 API matched CreateFile with ConnectNamedPipe
 | ||||
| 	// instead of CreateNamedPipe.  (Apparently created named pipes are
 | ||||
| 	// considered to be in listening state regardless of whether any
 | ||||
| 	// active calls to ConnectNamedPipe are outstanding.)
 | ||||
| 	h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) | ||||
| 	if err != nil { | ||||
| 		syscall.Close(h) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// Close the client handle. The server side of the instance will
 | ||||
| 	// still be busy, leading to ERROR_PIPE_BUSY instead of
 | ||||
| 	// ERROR_NOT_FOUND, as long as we don't close the server handle,
 | ||||
| 	// or disconnect the client with DisconnectNamedPipe.
 | ||||
| 	syscall.Close(h2) | ||||
| 	l := &win32PipeListener{ | ||||
| 		firstHandle: h, | ||||
| 		path:        path, | ||||
| 		securityDescriptor: sd, | ||||
| 		config:      *c, | ||||
| 		acceptCh:    make(chan (chan acceptResponse)), | ||||
| 		closeCh:     make(chan int), | ||||
|  |  | |||
|  | @ -0,0 +1,235 @@ | |||
| // Package guid provides a GUID type. The backing structure for a GUID is
 | ||||
| // identical to that used by the golang.org/x/sys/windows GUID type.
 | ||||
| // There are two main binary encodings used for a GUID, the big-endian encoding,
 | ||||
| // and the Windows (mixed-endian) encoding. See here for details:
 | ||||
| // https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
 | ||||
| package guid | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha1" | ||||
| 	"encoding" | ||||
| 	"encoding/binary" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
| 
 | ||||
| // Variant specifies which GUID variant (or "type") of the GUID. It determines
 | ||||
| // how the entirety of the rest of the GUID is interpreted.
 | ||||
| type Variant uint8 | ||||
| 
 | ||||
| // The variants specified by RFC 4122.
 | ||||
| const ( | ||||
| 	// VariantUnknown specifies a GUID variant which does not conform to one of
 | ||||
| 	// the variant encodings specified in RFC 4122.
 | ||||
| 	VariantUnknown Variant = iota | ||||
| 	VariantNCS | ||||
| 	VariantRFC4122 | ||||
| 	VariantMicrosoft | ||||
| 	VariantFuture | ||||
| ) | ||||
| 
 | ||||
| // Version specifies how the bits in the GUID were generated. For instance, a
 | ||||
| // version 4 GUID is randomly generated, and a version 5 is generated from the
 | ||||
| // hash of an input string.
 | ||||
| type Version uint8 | ||||
| 
 | ||||
| var _ = (encoding.TextMarshaler)(GUID{}) | ||||
| var _ = (encoding.TextUnmarshaler)(&GUID{}) | ||||
| 
 | ||||
| // GUID represents a GUID/UUID. It has the same structure as
 | ||||
| // golang.org/x/sys/windows.GUID so that it can be used with functions expecting
 | ||||
| // that type. It is defined as its own type so that stringification and
 | ||||
| // marshaling can be supported. The representation matches that used by native
 | ||||
| // Windows code.
 | ||||
| type GUID windows.GUID | ||||
| 
 | ||||
| // NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
 | ||||
| func NewV4() (GUID, error) { | ||||
| 	var b [16]byte | ||||
| 	if _, err := rand.Read(b[:]); err != nil { | ||||
| 		return GUID{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	g := FromArray(b) | ||||
| 	g.setVersion(4) // Version 4 means randomly generated.
 | ||||
| 	g.setVariant(VariantRFC4122) | ||||
| 
 | ||||
| 	return g, nil | ||||
| } | ||||
| 
 | ||||
| // NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
 | ||||
| // GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
 | ||||
| // and the sample code treats it as a series of bytes, so we do the same here.
 | ||||
| //
 | ||||
| // Some implementations, such as those found on Windows, treat the name as a
 | ||||
| // big-endian UTF16 stream of bytes. If that is desired, the string can be
 | ||||
| // encoded as such before being passed to this function.
 | ||||
| func NewV5(namespace GUID, name []byte) (GUID, error) { | ||||
| 	b := sha1.New() | ||||
| 	namespaceBytes := namespace.ToArray() | ||||
| 	b.Write(namespaceBytes[:]) | ||||
| 	b.Write(name) | ||||
| 
 | ||||
| 	a := [16]byte{} | ||||
| 	copy(a[:], b.Sum(nil)) | ||||
| 
 | ||||
| 	g := FromArray(a) | ||||
| 	g.setVersion(5) // Version 5 means generated from a string.
 | ||||
| 	g.setVariant(VariantRFC4122) | ||||
| 
 | ||||
| 	return g, nil | ||||
| } | ||||
| 
 | ||||
| func fromArray(b [16]byte, order binary.ByteOrder) GUID { | ||||
| 	var g GUID | ||||
| 	g.Data1 = order.Uint32(b[0:4]) | ||||
| 	g.Data2 = order.Uint16(b[4:6]) | ||||
| 	g.Data3 = order.Uint16(b[6:8]) | ||||
| 	copy(g.Data4[:], b[8:16]) | ||||
| 	return g | ||||
| } | ||||
| 
 | ||||
| func (g GUID) toArray(order binary.ByteOrder) [16]byte { | ||||
| 	b := [16]byte{} | ||||
| 	order.PutUint32(b[0:4], g.Data1) | ||||
| 	order.PutUint16(b[4:6], g.Data2) | ||||
| 	order.PutUint16(b[6:8], g.Data3) | ||||
| 	copy(b[8:16], g.Data4[:]) | ||||
| 	return b | ||||
| } | ||||
| 
 | ||||
| // FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
 | ||||
| func FromArray(b [16]byte) GUID { | ||||
| 	return fromArray(b, binary.BigEndian) | ||||
| } | ||||
| 
 | ||||
| // ToArray returns an array of 16 bytes representing the GUID in big-endian
 | ||||
| // encoding.
 | ||||
| func (g GUID) ToArray() [16]byte { | ||||
| 	return g.toArray(binary.BigEndian) | ||||
| } | ||||
| 
 | ||||
| // FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
 | ||||
| func FromWindowsArray(b [16]byte) GUID { | ||||
| 	return fromArray(b, binary.LittleEndian) | ||||
| } | ||||
| 
 | ||||
| // ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
 | ||||
| // encoding.
 | ||||
| func (g GUID) ToWindowsArray() [16]byte { | ||||
| 	return g.toArray(binary.LittleEndian) | ||||
| } | ||||
| 
 | ||||
| func (g GUID) String() string { | ||||
| 	return fmt.Sprintf( | ||||
| 		"%08x-%04x-%04x-%04x-%012x", | ||||
| 		g.Data1, | ||||
| 		g.Data2, | ||||
| 		g.Data3, | ||||
| 		g.Data4[:2], | ||||
| 		g.Data4[2:]) | ||||
| } | ||||
| 
 | ||||
| // FromString parses a string containing a GUID and returns the GUID. The only
 | ||||
| // format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
 | ||||
| // format.
 | ||||
| func FromString(s string) (GUID, error) { | ||||
| 	if len(s) != 36 { | ||||
| 		return GUID{}, fmt.Errorf("invalid GUID %q", s) | ||||
| 	} | ||||
| 	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { | ||||
| 		return GUID{}, fmt.Errorf("invalid GUID %q", s) | ||||
| 	} | ||||
| 
 | ||||
| 	var g GUID | ||||
| 
 | ||||
| 	data1, err := strconv.ParseUint(s[0:8], 16, 32) | ||||
| 	if err != nil { | ||||
| 		return GUID{}, fmt.Errorf("invalid GUID %q", s) | ||||
| 	} | ||||
| 	g.Data1 = uint32(data1) | ||||
| 
 | ||||
| 	data2, err := strconv.ParseUint(s[9:13], 16, 16) | ||||
| 	if err != nil { | ||||
| 		return GUID{}, fmt.Errorf("invalid GUID %q", s) | ||||
| 	} | ||||
| 	g.Data2 = uint16(data2) | ||||
| 
 | ||||
| 	data3, err := strconv.ParseUint(s[14:18], 16, 16) | ||||
| 	if err != nil { | ||||
| 		return GUID{}, fmt.Errorf("invalid GUID %q", s) | ||||
| 	} | ||||
| 	g.Data3 = uint16(data3) | ||||
| 
 | ||||
| 	for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} { | ||||
| 		v, err := strconv.ParseUint(s[x:x+2], 16, 8) | ||||
| 		if err != nil { | ||||
| 			return GUID{}, fmt.Errorf("invalid GUID %q", s) | ||||
| 		} | ||||
| 		g.Data4[i] = uint8(v) | ||||
| 	} | ||||
| 
 | ||||
| 	return g, nil | ||||
| } | ||||
| 
 | ||||
| func (g *GUID) setVariant(v Variant) { | ||||
| 	d := g.Data4[0] | ||||
| 	switch v { | ||||
| 	case VariantNCS: | ||||
| 		d = (d & 0x7f) | ||||
| 	case VariantRFC4122: | ||||
| 		d = (d & 0x3f) | 0x80 | ||||
| 	case VariantMicrosoft: | ||||
| 		d = (d & 0x1f) | 0xc0 | ||||
| 	case VariantFuture: | ||||
| 		d = (d & 0x0f) | 0xe0 | ||||
| 	case VariantUnknown: | ||||
| 		fallthrough | ||||
| 	default: | ||||
| 		panic(fmt.Sprintf("invalid variant: %d", v)) | ||||
| 	} | ||||
| 	g.Data4[0] = d | ||||
| } | ||||
| 
 | ||||
| // Variant returns the GUID variant, as defined in RFC 4122.
 | ||||
| func (g GUID) Variant() Variant { | ||||
| 	b := g.Data4[0] | ||||
| 	if b&0x80 == 0 { | ||||
| 		return VariantNCS | ||||
| 	} else if b&0xc0 == 0x80 { | ||||
| 		return VariantRFC4122 | ||||
| 	} else if b&0xe0 == 0xc0 { | ||||
| 		return VariantMicrosoft | ||||
| 	} else if b&0xe0 == 0xe0 { | ||||
| 		return VariantFuture | ||||
| 	} | ||||
| 	return VariantUnknown | ||||
| } | ||||
| 
 | ||||
| func (g *GUID) setVersion(v Version) { | ||||
| 	g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12) | ||||
| } | ||||
| 
 | ||||
| // Version returns the GUID version, as defined in RFC 4122.
 | ||||
| func (g GUID) Version() Version { | ||||
| 	return Version((g.Data3 & 0xF000) >> 12) | ||||
| } | ||||
| 
 | ||||
| // MarshalText returns the textual representation of the GUID.
 | ||||
| func (g GUID) MarshalText() ([]byte, error) { | ||||
| 	return []byte(g.String()), nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalText takes the textual representation of a GUID, and unmarhals it
 | ||||
| // into this GUID.
 | ||||
| func (g *GUID) UnmarshalText(text []byte) error { | ||||
| 	g2, err := FromString(string(text)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*g = g2 | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,3 +1,3 @@ | |||
| package winio | ||||
| 
 | ||||
| //go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go
 | ||||
| //go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| // MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
 | ||||
| // Code generated by 'go generate'; DO NOT EDIT.
 | ||||
| 
 | ||||
| package winio | ||||
| 
 | ||||
|  | @ -38,19 +38,25 @@ func errnoErr(e syscall.Errno) error { | |||
| 
 | ||||
| var ( | ||||
| 	modkernel32 = windows.NewLazySystemDLL("kernel32.dll") | ||||
| 	modws2_32   = windows.NewLazySystemDLL("ws2_32.dll") | ||||
| 	modntdll    = windows.NewLazySystemDLL("ntdll.dll") | ||||
| 	modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") | ||||
| 
 | ||||
| 	procCancelIoEx                                           = modkernel32.NewProc("CancelIoEx") | ||||
| 	procCreateIoCompletionPort                               = modkernel32.NewProc("CreateIoCompletionPort") | ||||
| 	procGetQueuedCompletionStatus                            = modkernel32.NewProc("GetQueuedCompletionStatus") | ||||
| 	procSetFileCompletionNotificationModes                   = modkernel32.NewProc("SetFileCompletionNotificationModes") | ||||
| 	procWSAGetOverlappedResult                               = modws2_32.NewProc("WSAGetOverlappedResult") | ||||
| 	procConnectNamedPipe                                     = modkernel32.NewProc("ConnectNamedPipe") | ||||
| 	procCreateNamedPipeW                                     = modkernel32.NewProc("CreateNamedPipeW") | ||||
| 	procCreateFileW                                          = modkernel32.NewProc("CreateFileW") | ||||
| 	procWaitNamedPipeW                                       = modkernel32.NewProc("WaitNamedPipeW") | ||||
| 	procGetNamedPipeInfo                                     = modkernel32.NewProc("GetNamedPipeInfo") | ||||
| 	procGetNamedPipeHandleStateW                             = modkernel32.NewProc("GetNamedPipeHandleStateW") | ||||
| 	procLocalAlloc                                           = modkernel32.NewProc("LocalAlloc") | ||||
| 	procNtCreateNamedPipeFile                                = modntdll.NewProc("NtCreateNamedPipeFile") | ||||
| 	procRtlNtStatusToDosErrorNoTeb                           = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") | ||||
| 	procRtlDosPathNameToNtPathName_U                         = modntdll.NewProc("RtlDosPathNameToNtPathName_U") | ||||
| 	procRtlDefaultNpAcl                                      = modntdll.NewProc("RtlDefaultNpAcl") | ||||
| 	procLookupAccountNameW                                   = modadvapi32.NewProc("LookupAccountNameW") | ||||
| 	procConvertSidToStringSidW                               = modadvapi32.NewProc("ConvertSidToStringSidW") | ||||
| 	procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") | ||||
|  | @ -69,6 +75,7 @@ var ( | |||
| 	procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") | ||||
| 	procBackupRead                                           = modkernel32.NewProc("BackupRead") | ||||
| 	procBackupWrite                                          = modkernel32.NewProc("BackupWrite") | ||||
| 	procbind                                                 = modws2_32.NewProc("bind") | ||||
| ) | ||||
| 
 | ||||
| func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { | ||||
|  | @ -120,6 +127,24 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro | |||
| 	return | ||||
| } | ||||
| 
 | ||||
| func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { | ||||
| 	var _p0 uint32 | ||||
| 	if wait { | ||||
| 		_p0 = 1 | ||||
| 	} else { | ||||
| 		_p0 = 0 | ||||
| 	} | ||||
| 	r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) | ||||
| 	if r1 == 0 { | ||||
| 		if e1 != 0 { | ||||
| 			err = errnoErr(e1) | ||||
| 		} else { | ||||
| 			err = syscall.EINVAL | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) | ||||
| 	if r1 == 0 { | ||||
|  | @ -176,27 +201,6 @@ func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityA | |||
| 	return | ||||
| } | ||||
| 
 | ||||
| func waitNamedPipe(name string, timeout uint32) (err error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, err = syscall.UTF16PtrFromString(name) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _waitNamedPipe(_p0, timeout) | ||||
| } | ||||
| 
 | ||||
| func _waitNamedPipe(name *uint16, timeout uint32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0) | ||||
| 	if r1 == 0 { | ||||
| 		if e1 != 0 { | ||||
| 			err = errnoErr(e1) | ||||
| 		} else { | ||||
| 			err = syscall.EINVAL | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) | ||||
| 	if r1 == 0 { | ||||
|  | @ -227,6 +231,32 @@ func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { | |||
| 	return | ||||
| } | ||||
| 
 | ||||
| func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { | ||||
| 	r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) | ||||
| 	status = ntstatus(r0) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func rtlNtStatusToDosError(status ntstatus) (winerr error) { | ||||
| 	r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) | ||||
| 	if r0 != 0 { | ||||
| 		winerr = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { | ||||
| 	r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) | ||||
| 	status = ntstatus(r0) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { | ||||
| 	r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) | ||||
| 	status = ntstatus(r0) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, err = syscall.UTF16PtrFromString(accountName) | ||||
|  | @ -518,3 +548,15 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p | |||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) | ||||
| 	if r1 == socketError { | ||||
| 		if e1 != 0 { | ||||
| 			err = errnoErr(e1) | ||||
| 		} else { | ||||
| 			err = syscall.EINVAL | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  |  | |||
|  | @ -1,26 +0,0 @@ | |||
| Copyright (c) 2012, Neal van Veen (nealvanveen@gmail.com) | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met:  | ||||
| 
 | ||||
| 1. Redistributions of source code must retain the above copyright notice, this | ||||
|    list of conditions and the following disclaimer.  | ||||
| 2. 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.  | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
| The views and conclusions contained in the software and documentation are those | ||||
| of the authors and should not be interpreted as representing official policies,  | ||||
| either expressed or implied, of the FreeBSD Project. | ||||
|  | @ -1,5 +0,0 @@ | |||
| Gotty is a library written in Go that determines and reads termcap database | ||||
| files to produce an interface for interacting with the capabilities of a | ||||
| terminal. | ||||
| See the godoc documentation or the source code for more information about | ||||
| function usage. | ||||
|  | @ -1,3 +0,0 @@ | |||
| gotty.go:// TODO add more concurrency to name lookup, look for more opportunities. | ||||
| all:// TODO add more documentation, with function usage in a doc.go file. | ||||
| all:// TODO add more testing/benchmarking with go test. | ||||
|  | @ -1,514 +0,0 @@ | |||
| // Copyright 2012 Neal van Veen. All rights reserved.
 | ||||
| // Usage of this source code is governed by a BSD-style license that can be
 | ||||
| // found in the LICENSE file.
 | ||||
| 
 | ||||
| package gotty | ||||
| 
 | ||||
| // Boolean capabilities
 | ||||
| var BoolAttr = [...]string{ | ||||
| 	"auto_left_margin", "bw", | ||||
| 	"auto_right_margin", "am", | ||||
| 	"no_esc_ctlc", "xsb", | ||||
| 	"ceol_standout_glitch", "xhp", | ||||
| 	"eat_newline_glitch", "xenl", | ||||
| 	"erase_overstrike", "eo", | ||||
| 	"generic_type", "gn", | ||||
| 	"hard_copy", "hc", | ||||
| 	"has_meta_key", "km", | ||||
| 	"has_status_line", "hs", | ||||
| 	"insert_null_glitch", "in", | ||||
| 	"memory_above", "da", | ||||
| 	"memory_below", "db", | ||||
| 	"move_insert_mode", "mir", | ||||
| 	"move_standout_mode", "msgr", | ||||
| 	"over_strike", "os", | ||||
| 	"status_line_esc_ok", "eslok", | ||||
| 	"dest_tabs_magic_smso", "xt", | ||||
| 	"tilde_glitch", "hz", | ||||
| 	"transparent_underline", "ul", | ||||
| 	"xon_xoff", "nxon", | ||||
| 	"needs_xon_xoff", "nxon", | ||||
| 	"prtr_silent", "mc5i", | ||||
| 	"hard_cursor", "chts", | ||||
| 	"non_rev_rmcup", "nrrmc", | ||||
| 	"no_pad_char", "npc", | ||||
| 	"non_dest_scroll_region", "ndscr", | ||||
| 	"can_change", "ccc", | ||||
| 	"back_color_erase", "bce", | ||||
| 	"hue_lightness_saturation", "hls", | ||||
| 	"col_addr_glitch", "xhpa", | ||||
| 	"cr_cancels_micro_mode", "crxm", | ||||
| 	"has_print_wheel", "daisy", | ||||
| 	"row_addr_glitch", "xvpa", | ||||
| 	"semi_auto_right_margin", "sam", | ||||
| 	"cpi_changes_res", "cpix", | ||||
| 	"lpi_changes_res", "lpix", | ||||
| 	"backspaces_with_bs", "", | ||||
| 	"crt_no_scrolling", "", | ||||
| 	"no_correctly_working_cr", "", | ||||
| 	"gnu_has_meta_key", "", | ||||
| 	"linefeed_is_newline", "", | ||||
| 	"has_hardware_tabs", "", | ||||
| 	"return_does_clr_eol", "", | ||||
| } | ||||
| 
 | ||||
| // Numerical capabilities
 | ||||
| var NumAttr = [...]string{ | ||||
| 	"columns", "cols", | ||||
| 	"init_tabs", "it", | ||||
| 	"lines", "lines", | ||||
| 	"lines_of_memory", "lm", | ||||
| 	"magic_cookie_glitch", "xmc", | ||||
| 	"padding_baud_rate", "pb", | ||||
| 	"virtual_terminal", "vt", | ||||
| 	"width_status_line", "wsl", | ||||
| 	"num_labels", "nlab", | ||||
| 	"label_height", "lh", | ||||
| 	"label_width", "lw", | ||||
| 	"max_attributes", "ma", | ||||
| 	"maximum_windows", "wnum", | ||||
| 	"max_colors", "colors", | ||||
| 	"max_pairs", "pairs", | ||||
| 	"no_color_video", "ncv", | ||||
| 	"buffer_capacity", "bufsz", | ||||
| 	"dot_vert_spacing", "spinv", | ||||
| 	"dot_horz_spacing", "spinh", | ||||
| 	"max_micro_address", "maddr", | ||||
| 	"max_micro_jump", "mjump", | ||||
| 	"micro_col_size", "mcs", | ||||
| 	"micro_line_size", "mls", | ||||
| 	"number_of_pins", "npins", | ||||
| 	"output_res_char", "orc", | ||||
| 	"output_res_line", "orl", | ||||
| 	"output_res_horz_inch", "orhi", | ||||
| 	"output_res_vert_inch", "orvi", | ||||
| 	"print_rate", "cps", | ||||
| 	"wide_char_size", "widcs", | ||||
| 	"buttons", "btns", | ||||
| 	"bit_image_entwining", "bitwin", | ||||
| 	"bit_image_type", "bitype", | ||||
| 	"magic_cookie_glitch_ul", "", | ||||
| 	"carriage_return_delay", "", | ||||
| 	"new_line_delay", "", | ||||
| 	"backspace_delay", "", | ||||
| 	"horizontal_tab_delay", "", | ||||
| 	"number_of_function_keys", "", | ||||
| } | ||||
| 
 | ||||
| // String capabilities
 | ||||
| var StrAttr = [...]string{ | ||||
| 	"back_tab", "cbt", | ||||
| 	"bell", "bel", | ||||
| 	"carriage_return", "cr", | ||||
| 	"change_scroll_region", "csr", | ||||
| 	"clear_all_tabs", "tbc", | ||||
| 	"clear_screen", "clear", | ||||
| 	"clr_eol", "el", | ||||
| 	"clr_eos", "ed", | ||||
| 	"column_address", "hpa", | ||||
| 	"command_character", "cmdch", | ||||
| 	"cursor_address", "cup", | ||||
| 	"cursor_down", "cud1", | ||||
| 	"cursor_home", "home", | ||||
| 	"cursor_invisible", "civis", | ||||
| 	"cursor_left", "cub1", | ||||
| 	"cursor_mem_address", "mrcup", | ||||
| 	"cursor_normal", "cnorm", | ||||
| 	"cursor_right", "cuf1", | ||||
| 	"cursor_to_ll", "ll", | ||||
| 	"cursor_up", "cuu1", | ||||
| 	"cursor_visible", "cvvis", | ||||
| 	"delete_character", "dch1", | ||||
| 	"delete_line", "dl1", | ||||
| 	"dis_status_line", "dsl", | ||||
| 	"down_half_line", "hd", | ||||
| 	"enter_alt_charset_mode", "smacs", | ||||
| 	"enter_blink_mode", "blink", | ||||
| 	"enter_bold_mode", "bold", | ||||
| 	"enter_ca_mode", "smcup", | ||||
| 	"enter_delete_mode", "smdc", | ||||
| 	"enter_dim_mode", "dim", | ||||
| 	"enter_insert_mode", "smir", | ||||
| 	"enter_secure_mode", "invis", | ||||
| 	"enter_protected_mode", "prot", | ||||
| 	"enter_reverse_mode", "rev", | ||||
| 	"enter_standout_mode", "smso", | ||||
| 	"enter_underline_mode", "smul", | ||||
| 	"erase_chars", "ech", | ||||
| 	"exit_alt_charset_mode", "rmacs", | ||||
| 	"exit_attribute_mode", "sgr0", | ||||
| 	"exit_ca_mode", "rmcup", | ||||
| 	"exit_delete_mode", "rmdc", | ||||
| 	"exit_insert_mode", "rmir", | ||||
| 	"exit_standout_mode", "rmso", | ||||
| 	"exit_underline_mode", "rmul", | ||||
| 	"flash_screen", "flash", | ||||
| 	"form_feed", "ff", | ||||
| 	"from_status_line", "fsl", | ||||
| 	"init_1string", "is1", | ||||
| 	"init_2string", "is2", | ||||
| 	"init_3string", "is3", | ||||
| 	"init_file", "if", | ||||
| 	"insert_character", "ich1", | ||||
| 	"insert_line", "il1", | ||||
| 	"insert_padding", "ip", | ||||
| 	"key_backspace", "kbs", | ||||
| 	"key_catab", "ktbc", | ||||
| 	"key_clear", "kclr", | ||||
| 	"key_ctab", "kctab", | ||||
| 	"key_dc", "kdch1", | ||||
| 	"key_dl", "kdl1", | ||||
| 	"key_down", "kcud1", | ||||
| 	"key_eic", "krmir", | ||||
| 	"key_eol", "kel", | ||||
| 	"key_eos", "ked", | ||||
| 	"key_f0", "kf0", | ||||
| 	"key_f1", "kf1", | ||||
| 	"key_f10", "kf10", | ||||
| 	"key_f2", "kf2", | ||||
| 	"key_f3", "kf3", | ||||
| 	"key_f4", "kf4", | ||||
| 	"key_f5", "kf5", | ||||
| 	"key_f6", "kf6", | ||||
| 	"key_f7", "kf7", | ||||
| 	"key_f8", "kf8", | ||||
| 	"key_f9", "kf9", | ||||
| 	"key_home", "khome", | ||||
| 	"key_ic", "kich1", | ||||
| 	"key_il", "kil1", | ||||
| 	"key_left", "kcub1", | ||||
| 	"key_ll", "kll", | ||||
| 	"key_npage", "knp", | ||||
| 	"key_ppage", "kpp", | ||||
| 	"key_right", "kcuf1", | ||||
| 	"key_sf", "kind", | ||||
| 	"key_sr", "kri", | ||||
| 	"key_stab", "khts", | ||||
| 	"key_up", "kcuu1", | ||||
| 	"keypad_local", "rmkx", | ||||
| 	"keypad_xmit", "smkx", | ||||
| 	"lab_f0", "lf0", | ||||
| 	"lab_f1", "lf1", | ||||
| 	"lab_f10", "lf10", | ||||
| 	"lab_f2", "lf2", | ||||
| 	"lab_f3", "lf3", | ||||
| 	"lab_f4", "lf4", | ||||
| 	"lab_f5", "lf5", | ||||
| 	"lab_f6", "lf6", | ||||
| 	"lab_f7", "lf7", | ||||
| 	"lab_f8", "lf8", | ||||
| 	"lab_f9", "lf9", | ||||
| 	"meta_off", "rmm", | ||||
| 	"meta_on", "smm", | ||||
| 	"newline", "_glitch", | ||||
| 	"pad_char", "npc", | ||||
| 	"parm_dch", "dch", | ||||
| 	"parm_delete_line", "dl", | ||||
| 	"parm_down_cursor", "cud", | ||||
| 	"parm_ich", "ich", | ||||
| 	"parm_index", "indn", | ||||
| 	"parm_insert_line", "il", | ||||
| 	"parm_left_cursor", "cub", | ||||
| 	"parm_right_cursor", "cuf", | ||||
| 	"parm_rindex", "rin", | ||||
| 	"parm_up_cursor", "cuu", | ||||
| 	"pkey_key", "pfkey", | ||||
| 	"pkey_local", "pfloc", | ||||
| 	"pkey_xmit", "pfx", | ||||
| 	"print_screen", "mc0", | ||||
| 	"prtr_off", "mc4", | ||||
| 	"prtr_on", "mc5", | ||||
| 	"repeat_char", "rep", | ||||
| 	"reset_1string", "rs1", | ||||
| 	"reset_2string", "rs2", | ||||
| 	"reset_3string", "rs3", | ||||
| 	"reset_file", "rf", | ||||
| 	"restore_cursor", "rc", | ||||
| 	"row_address", "mvpa", | ||||
| 	"save_cursor", "row_address", | ||||
| 	"scroll_forward", "ind", | ||||
| 	"scroll_reverse", "ri", | ||||
| 	"set_attributes", "sgr", | ||||
| 	"set_tab", "hts", | ||||
| 	"set_window", "wind", | ||||
| 	"tab", "s_magic_smso", | ||||
| 	"to_status_line", "tsl", | ||||
| 	"underline_char", "uc", | ||||
| 	"up_half_line", "hu", | ||||
| 	"init_prog", "iprog", | ||||
| 	"key_a1", "ka1", | ||||
| 	"key_a3", "ka3", | ||||
| 	"key_b2", "kb2", | ||||
| 	"key_c1", "kc1", | ||||
| 	"key_c3", "kc3", | ||||
| 	"prtr_non", "mc5p", | ||||
| 	"char_padding", "rmp", | ||||
| 	"acs_chars", "acsc", | ||||
| 	"plab_norm", "pln", | ||||
| 	"key_btab", "kcbt", | ||||
| 	"enter_xon_mode", "smxon", | ||||
| 	"exit_xon_mode", "rmxon", | ||||
| 	"enter_am_mode", "smam", | ||||
| 	"exit_am_mode", "rmam", | ||||
| 	"xon_character", "xonc", | ||||
| 	"xoff_character", "xoffc", | ||||
| 	"ena_acs", "enacs", | ||||
| 	"label_on", "smln", | ||||
| 	"label_off", "rmln", | ||||
| 	"key_beg", "kbeg", | ||||
| 	"key_cancel", "kcan", | ||||
| 	"key_close", "kclo", | ||||
| 	"key_command", "kcmd", | ||||
| 	"key_copy", "kcpy", | ||||
| 	"key_create", "kcrt", | ||||
| 	"key_end", "kend", | ||||
| 	"key_enter", "kent", | ||||
| 	"key_exit", "kext", | ||||
| 	"key_find", "kfnd", | ||||
| 	"key_help", "khlp", | ||||
| 	"key_mark", "kmrk", | ||||
| 	"key_message", "kmsg", | ||||
| 	"key_move", "kmov", | ||||
| 	"key_next", "knxt", | ||||
| 	"key_open", "kopn", | ||||
| 	"key_options", "kopt", | ||||
| 	"key_previous", "kprv", | ||||
| 	"key_print", "kprt", | ||||
| 	"key_redo", "krdo", | ||||
| 	"key_reference", "kref", | ||||
| 	"key_refresh", "krfr", | ||||
| 	"key_replace", "krpl", | ||||
| 	"key_restart", "krst", | ||||
| 	"key_resume", "kres", | ||||
| 	"key_save", "ksav", | ||||
| 	"key_suspend", "kspd", | ||||
| 	"key_undo", "kund", | ||||
| 	"key_sbeg", "kBEG", | ||||
| 	"key_scancel", "kCAN", | ||||
| 	"key_scommand", "kCMD", | ||||
| 	"key_scopy", "kCPY", | ||||
| 	"key_screate", "kCRT", | ||||
| 	"key_sdc", "kDC", | ||||
| 	"key_sdl", "kDL", | ||||
| 	"key_select", "kslt", | ||||
| 	"key_send", "kEND", | ||||
| 	"key_seol", "kEOL", | ||||
| 	"key_sexit", "kEXT", | ||||
| 	"key_sfind", "kFND", | ||||
| 	"key_shelp", "kHLP", | ||||
| 	"key_shome", "kHOM", | ||||
| 	"key_sic", "kIC", | ||||
| 	"key_sleft", "kLFT", | ||||
| 	"key_smessage", "kMSG", | ||||
| 	"key_smove", "kMOV", | ||||
| 	"key_snext", "kNXT", | ||||
| 	"key_soptions", "kOPT", | ||||
| 	"key_sprevious", "kPRV", | ||||
| 	"key_sprint", "kPRT", | ||||
| 	"key_sredo", "kRDO", | ||||
| 	"key_sreplace", "kRPL", | ||||
| 	"key_sright", "kRIT", | ||||
| 	"key_srsume", "kRES", | ||||
| 	"key_ssave", "kSAV", | ||||
| 	"key_ssuspend", "kSPD", | ||||
| 	"key_sundo", "kUND", | ||||
| 	"req_for_input", "rfi", | ||||
| 	"key_f11", "kf11", | ||||
| 	"key_f12", "kf12", | ||||
| 	"key_f13", "kf13", | ||||
| 	"key_f14", "kf14", | ||||
| 	"key_f15", "kf15", | ||||
| 	"key_f16", "kf16", | ||||
| 	"key_f17", "kf17", | ||||
| 	"key_f18", "kf18", | ||||
| 	"key_f19", "kf19", | ||||
| 	"key_f20", "kf20", | ||||
| 	"key_f21", "kf21", | ||||
| 	"key_f22", "kf22", | ||||
| 	"key_f23", "kf23", | ||||
| 	"key_f24", "kf24", | ||||
| 	"key_f25", "kf25", | ||||
| 	"key_f26", "kf26", | ||||
| 	"key_f27", "kf27", | ||||
| 	"key_f28", "kf28", | ||||
| 	"key_f29", "kf29", | ||||
| 	"key_f30", "kf30", | ||||
| 	"key_f31", "kf31", | ||||
| 	"key_f32", "kf32", | ||||
| 	"key_f33", "kf33", | ||||
| 	"key_f34", "kf34", | ||||
| 	"key_f35", "kf35", | ||||
| 	"key_f36", "kf36", | ||||
| 	"key_f37", "kf37", | ||||
| 	"key_f38", "kf38", | ||||
| 	"key_f39", "kf39", | ||||
| 	"key_f40", "kf40", | ||||
| 	"key_f41", "kf41", | ||||
| 	"key_f42", "kf42", | ||||
| 	"key_f43", "kf43", | ||||
| 	"key_f44", "kf44", | ||||
| 	"key_f45", "kf45", | ||||
| 	"key_f46", "kf46", | ||||
| 	"key_f47", "kf47", | ||||
| 	"key_f48", "kf48", | ||||
| 	"key_f49", "kf49", | ||||
| 	"key_f50", "kf50", | ||||
| 	"key_f51", "kf51", | ||||
| 	"key_f52", "kf52", | ||||
| 	"key_f53", "kf53", | ||||
| 	"key_f54", "kf54", | ||||
| 	"key_f55", "kf55", | ||||
| 	"key_f56", "kf56", | ||||
| 	"key_f57", "kf57", | ||||
| 	"key_f58", "kf58", | ||||
| 	"key_f59", "kf59", | ||||
| 	"key_f60", "kf60", | ||||
| 	"key_f61", "kf61", | ||||
| 	"key_f62", "kf62", | ||||
| 	"key_f63", "kf63", | ||||
| 	"clr_bol", "el1", | ||||
| 	"clear_margins", "mgc", | ||||
| 	"set_left_margin", "smgl", | ||||
| 	"set_right_margin", "smgr", | ||||
| 	"label_format", "fln", | ||||
| 	"set_clock", "sclk", | ||||
| 	"display_clock", "dclk", | ||||
| 	"remove_clock", "rmclk", | ||||
| 	"create_window", "cwin", | ||||
| 	"goto_window", "wingo", | ||||
| 	"hangup", "hup", | ||||
| 	"dial_phone", "dial", | ||||
| 	"quick_dial", "qdial", | ||||
| 	"tone", "tone", | ||||
| 	"pulse", "pulse", | ||||
| 	"flash_hook", "hook", | ||||
| 	"fixed_pause", "pause", | ||||
| 	"wait_tone", "wait", | ||||
| 	"user0", "u0", | ||||
| 	"user1", "u1", | ||||
| 	"user2", "u2", | ||||
| 	"user3", "u3", | ||||
| 	"user4", "u4", | ||||
| 	"user5", "u5", | ||||
| 	"user6", "u6", | ||||
| 	"user7", "u7", | ||||
| 	"user8", "u8", | ||||
| 	"user9", "u9", | ||||
| 	"orig_pair", "op", | ||||
| 	"orig_colors", "oc", | ||||
| 	"initialize_color", "initc", | ||||
| 	"initialize_pair", "initp", | ||||
| 	"set_color_pair", "scp", | ||||
| 	"set_foreground", "setf", | ||||
| 	"set_background", "setb", | ||||
| 	"change_char_pitch", "cpi", | ||||
| 	"change_line_pitch", "lpi", | ||||
| 	"change_res_horz", "chr", | ||||
| 	"change_res_vert", "cvr", | ||||
| 	"define_char", "defc", | ||||
| 	"enter_doublewide_mode", "swidm", | ||||
| 	"enter_draft_quality", "sdrfq", | ||||
| 	"enter_italics_mode", "sitm", | ||||
| 	"enter_leftward_mode", "slm", | ||||
| 	"enter_micro_mode", "smicm", | ||||
| 	"enter_near_letter_quality", "snlq", | ||||
| 	"enter_normal_quality", "snrmq", | ||||
| 	"enter_shadow_mode", "sshm", | ||||
| 	"enter_subscript_mode", "ssubm", | ||||
| 	"enter_superscript_mode", "ssupm", | ||||
| 	"enter_upward_mode", "sum", | ||||
| 	"exit_doublewide_mode", "rwidm", | ||||
| 	"exit_italics_mode", "ritm", | ||||
| 	"exit_leftward_mode", "rlm", | ||||
| 	"exit_micro_mode", "rmicm", | ||||
| 	"exit_shadow_mode", "rshm", | ||||
| 	"exit_subscript_mode", "rsubm", | ||||
| 	"exit_superscript_mode", "rsupm", | ||||
| 	"exit_upward_mode", "rum", | ||||
| 	"micro_column_address", "mhpa", | ||||
| 	"micro_down", "mcud1", | ||||
| 	"micro_left", "mcub1", | ||||
| 	"micro_right", "mcuf1", | ||||
| 	"micro_row_address", "mvpa", | ||||
| 	"micro_up", "mcuu1", | ||||
| 	"order_of_pins", "porder", | ||||
| 	"parm_down_micro", "mcud", | ||||
| 	"parm_left_micro", "mcub", | ||||
| 	"parm_right_micro", "mcuf", | ||||
| 	"parm_up_micro", "mcuu", | ||||
| 	"select_char_set", "scs", | ||||
| 	"set_bottom_margin", "smgb", | ||||
| 	"set_bottom_margin_parm", "smgbp", | ||||
| 	"set_left_margin_parm", "smglp", | ||||
| 	"set_right_margin_parm", "smgrp", | ||||
| 	"set_top_margin", "smgt", | ||||
| 	"set_top_margin_parm", "smgtp", | ||||
| 	"start_bit_image", "sbim", | ||||
| 	"start_char_set_def", "scsd", | ||||
| 	"stop_bit_image", "rbim", | ||||
| 	"stop_char_set_def", "rcsd", | ||||
| 	"subscript_characters", "subcs", | ||||
| 	"superscript_characters", "supcs", | ||||
| 	"these_cause_cr", "docr", | ||||
| 	"zero_motion", "zerom", | ||||
| 	"char_set_names", "csnm", | ||||
| 	"key_mouse", "kmous", | ||||
| 	"mouse_info", "minfo", | ||||
| 	"req_mouse_pos", "reqmp", | ||||
| 	"get_mouse", "getm", | ||||
| 	"set_a_foreground", "setaf", | ||||
| 	"set_a_background", "setab", | ||||
| 	"pkey_plab", "pfxl", | ||||
| 	"device_type", "devt", | ||||
| 	"code_set_init", "csin", | ||||
| 	"set0_des_seq", "s0ds", | ||||
| 	"set1_des_seq", "s1ds", | ||||
| 	"set2_des_seq", "s2ds", | ||||
| 	"set3_des_seq", "s3ds", | ||||
| 	"set_lr_margin", "smglr", | ||||
| 	"set_tb_margin", "smgtb", | ||||
| 	"bit_image_repeat", "birep", | ||||
| 	"bit_image_newline", "binel", | ||||
| 	"bit_image_carriage_return", "bicr", | ||||
| 	"color_names", "colornm", | ||||
| 	"define_bit_image_region", "defbi", | ||||
| 	"end_bit_image_region", "endbi", | ||||
| 	"set_color_band", "setcolor", | ||||
| 	"set_page_length", "slines", | ||||
| 	"display_pc_char", "dispc", | ||||
| 	"enter_pc_charset_mode", "smpch", | ||||
| 	"exit_pc_charset_mode", "rmpch", | ||||
| 	"enter_scancode_mode", "smsc", | ||||
| 	"exit_scancode_mode", "rmsc", | ||||
| 	"pc_term_options", "pctrm", | ||||
| 	"scancode_escape", "scesc", | ||||
| 	"alt_scancode_esc", "scesa", | ||||
| 	"enter_horizontal_hl_mode", "ehhlm", | ||||
| 	"enter_left_hl_mode", "elhlm", | ||||
| 	"enter_low_hl_mode", "elohlm", | ||||
| 	"enter_right_hl_mode", "erhlm", | ||||
| 	"enter_top_hl_mode", "ethlm", | ||||
| 	"enter_vertical_hl_mode", "evhlm", | ||||
| 	"set_a_attributes", "sgr1", | ||||
| 	"set_pglen_inch", "slength", | ||||
| 	"termcap_init2", "", | ||||
| 	"termcap_reset", "", | ||||
| 	"linefeed_if_not_lf", "", | ||||
| 	"backspace_if_not_bs", "", | ||||
| 	"other_non_function_keys", "", | ||||
| 	"arrow_key_map", "", | ||||
| 	"acs_ulcorner", "", | ||||
| 	"acs_llcorner", "", | ||||
| 	"acs_urcorner", "", | ||||
| 	"acs_lrcorner", "", | ||||
| 	"acs_ltee", "", | ||||
| 	"acs_rtee", "", | ||||
| 	"acs_btee", "", | ||||
| 	"acs_ttee", "", | ||||
| 	"acs_hline", "", | ||||
| 	"acs_vline", "", | ||||
| 	"acs_plus", "", | ||||
| 	"memory_lock", "", | ||||
| 	"memory_unlock", "", | ||||
| 	"box_chars_1", "", | ||||
| } | ||||
|  | @ -1,238 +0,0 @@ | |||
| // Copyright 2012 Neal van Veen. All rights reserved.
 | ||||
| // Usage of this source code is governed by a BSD-style license that can be
 | ||||
| // found in the LICENSE file.
 | ||||
| 
 | ||||
| // Gotty is a Go-package for reading and parsing the terminfo database
 | ||||
| package gotty | ||||
| 
 | ||||
| // TODO add more concurrency to name lookup, look for more opportunities.
 | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| // Open a terminfo file by the name given and construct a TermInfo object.
 | ||||
| // If something went wrong reading the terminfo database file, an error is
 | ||||
| // returned.
 | ||||
| func OpenTermInfo(termName string) (*TermInfo, error) { | ||||
| 	var term *TermInfo | ||||
| 	var err error | ||||
| 	// Find the environment variables
 | ||||
| 	termloc := os.Getenv("TERMINFO") | ||||
| 	if len(termloc) == 0 { | ||||
| 		// Search like ncurses
 | ||||
| 		locations := []string{os.Getenv("HOME") + "/.terminfo/", "/etc/terminfo/", | ||||
| 			"/lib/terminfo/", "/usr/share/terminfo/"} | ||||
| 		var path string | ||||
| 		for _, str := range locations { | ||||
| 			// Construct path
 | ||||
| 			path = str + string(termName[0]) + "/" + termName | ||||
| 			// Check if path can be opened
 | ||||
| 			file, _ := os.Open(path) | ||||
| 			if file != nil { | ||||
| 				// Path can open, fall out and use current path
 | ||||
| 				file.Close() | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		if len(path) > 0 { | ||||
| 			term, err = readTermInfo(path) | ||||
| 		} else { | ||||
| 			err = errors.New(fmt.Sprintf("No terminfo file(-location) found")) | ||||
| 		} | ||||
| 	} | ||||
| 	return term, err | ||||
| } | ||||
| 
 | ||||
| // Open a terminfo file from the environment variable containing the current
 | ||||
| // terminal name and construct a TermInfo object. If something went wrong
 | ||||
| // reading the terminfo database file, an error is returned.
 | ||||
| func OpenTermInfoEnv() (*TermInfo, error) { | ||||
| 	termenv := os.Getenv("TERM") | ||||
| 	return OpenTermInfo(termenv) | ||||
| } | ||||
| 
 | ||||
| // Return an attribute by the name attr provided. If none can be found,
 | ||||
| // an error is returned.
 | ||||
| func (term *TermInfo) GetAttribute(attr string) (stacker, error) { | ||||
| 	// Channel to store the main value in.
 | ||||
| 	var value stacker | ||||
| 	// Add a blocking WaitGroup
 | ||||
| 	var block sync.WaitGroup | ||||
| 	// Keep track of variable being written.
 | ||||
| 	written := false | ||||
| 	// Function to put into goroutine.
 | ||||
| 	f := func(ats interface{}) { | ||||
| 		var ok bool | ||||
| 		var v stacker | ||||
| 		// Switch on type of map to use and assign value to it.
 | ||||
| 		switch reflect.TypeOf(ats).Elem().Kind() { | ||||
| 		case reflect.Bool: | ||||
| 			v, ok = ats.(map[string]bool)[attr] | ||||
| 		case reflect.Int16: | ||||
| 			v, ok = ats.(map[string]int16)[attr] | ||||
| 		case reflect.String: | ||||
| 			v, ok = ats.(map[string]string)[attr] | ||||
| 		} | ||||
| 		// If ok, a value is found, so we can write.
 | ||||
| 		if ok { | ||||
| 			value = v | ||||
| 			written = true | ||||
| 		} | ||||
| 		// Goroutine is done
 | ||||
| 		block.Done() | ||||
| 	} | ||||
| 	block.Add(3) | ||||
| 	// Go for all 3 attribute lists.
 | ||||
| 	go f(term.boolAttributes) | ||||
| 	go f(term.numAttributes) | ||||
| 	go f(term.strAttributes) | ||||
| 	// Wait until every goroutine is done.
 | ||||
| 	block.Wait() | ||||
| 	// If a value has been written, return it.
 | ||||
| 	if written { | ||||
| 		return value, nil | ||||
| 	} | ||||
| 	// Otherwise, error.
 | ||||
| 	return nil, fmt.Errorf("Erorr finding attribute") | ||||
| } | ||||
| 
 | ||||
| // Return an attribute by the name attr provided. If none can be found,
 | ||||
| // an error is returned. A name is first converted to its termcap value.
 | ||||
| func (term *TermInfo) GetAttributeName(name string) (stacker, error) { | ||||
| 	tc := GetTermcapName(name) | ||||
| 	return term.GetAttribute(tc) | ||||
| } | ||||
| 
 | ||||
| // A utility function that finds and returns the termcap equivalent of a 
 | ||||
| // variable name.
 | ||||
| func GetTermcapName(name string) string { | ||||
| 	// Termcap name
 | ||||
| 	var tc string | ||||
| 	// Blocking group
 | ||||
| 	var wait sync.WaitGroup | ||||
| 	// Function to put into a goroutine
 | ||||
| 	f := func(attrs []string) { | ||||
| 		// Find the string corresponding to the name
 | ||||
| 		for i, s := range attrs { | ||||
| 			if s == name { | ||||
| 				tc = attrs[i+1] | ||||
| 			} | ||||
| 		} | ||||
| 		// Goroutine is finished
 | ||||
| 		wait.Done() | ||||
| 	} | ||||
| 	wait.Add(3) | ||||
| 	// Go for all 3 attribute lists
 | ||||
| 	go f(BoolAttr[:]) | ||||
| 	go f(NumAttr[:]) | ||||
| 	go f(StrAttr[:]) | ||||
| 	// Wait until every goroutine is done
 | ||||
| 	wait.Wait() | ||||
| 	// Return the termcap name
 | ||||
| 	return tc | ||||
| } | ||||
| 
 | ||||
| // This function takes a path to a terminfo file and reads it in binary
 | ||||
| // form to construct the actual TermInfo file.
 | ||||
| func readTermInfo(path string) (*TermInfo, error) { | ||||
| 	// Open the terminfo file
 | ||||
| 	file, err := os.Open(path) | ||||
| 	defer file.Close() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// magic, nameSize, boolSize, nrSNum, nrOffsetsStr, strSize
 | ||||
| 	// Header is composed of the magic 0432 octal number, size of the name
 | ||||
| 	// section, size of the boolean section, the amount of number values,
 | ||||
| 	// the number of offsets of strings, and the size of the string section.
 | ||||
| 	var header [6]int16 | ||||
| 	// Byte array is used to read in byte values
 | ||||
| 	var byteArray []byte | ||||
| 	// Short array is used to read in short values
 | ||||
| 	var shArray []int16 | ||||
| 	// TermInfo object to store values
 | ||||
| 	var term TermInfo | ||||
| 
 | ||||
| 	// Read in the header
 | ||||
| 	err = binary.Read(file, binary.LittleEndian, &header) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// If magic number isn't there or isn't correct, we have the wrong filetype
 | ||||
| 	if header[0] != 0432 { | ||||
| 		return nil, errors.New(fmt.Sprintf("Wrong filetype")) | ||||
| 	} | ||||
| 
 | ||||
| 	// Read in the names
 | ||||
| 	byteArray = make([]byte, header[1]) | ||||
| 	err = binary.Read(file, binary.LittleEndian, &byteArray) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	term.Names = strings.Split(string(byteArray), "|") | ||||
| 
 | ||||
| 	// Read in the booleans
 | ||||
| 	byteArray = make([]byte, header[2]) | ||||
| 	err = binary.Read(file, binary.LittleEndian, &byteArray) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	term.boolAttributes = make(map[string]bool) | ||||
| 	for i, b := range byteArray { | ||||
| 		if b == 1 { | ||||
| 			term.boolAttributes[BoolAttr[i*2+1]] = true | ||||
| 		} | ||||
| 	} | ||||
| 	// If the number of bytes read is not even, a byte for alignment is added
 | ||||
| 	if len(byteArray)%2 != 0 { | ||||
| 		err = binary.Read(file, binary.LittleEndian, make([]byte, 1)) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Read in shorts
 | ||||
| 	shArray = make([]int16, header[3]) | ||||
| 	err = binary.Read(file, binary.LittleEndian, &shArray) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	term.numAttributes = make(map[string]int16) | ||||
| 	for i, n := range shArray { | ||||
| 		if n != 0377 && n > -1 { | ||||
| 			term.numAttributes[NumAttr[i*2+1]] = n | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Read the offsets into the short array
 | ||||
| 	shArray = make([]int16, header[4]) | ||||
| 	err = binary.Read(file, binary.LittleEndian, &shArray) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// Read the actual strings in the byte array
 | ||||
| 	byteArray = make([]byte, header[5]) | ||||
| 	err = binary.Read(file, binary.LittleEndian, &byteArray) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	term.strAttributes = make(map[string]string) | ||||
| 	// We get an offset, and then iterate until the string is null-terminated
 | ||||
| 	for i, offset := range shArray { | ||||
| 		if offset > -1 { | ||||
| 			r := offset | ||||
| 			for ; byteArray[r] != 0; r++ { | ||||
| 			} | ||||
| 			term.strAttributes[StrAttr[i*2+1]] = string(byteArray[offset:r]) | ||||
| 		} | ||||
| 	} | ||||
| 	return &term, nil | ||||
| } | ||||
|  | @ -1,362 +0,0 @@ | |||
| // Copyright 2012 Neal van Veen. All rights reserved.
 | ||||
| // Usage of this source code is governed by a BSD-style license that can be
 | ||||
| // found in the LICENSE file.
 | ||||
| 
 | ||||
| package gotty | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| var exp = [...]string{ | ||||
| 	"%%", | ||||
| 	"%c", | ||||
| 	"%s", | ||||
| 	"%p(\\d)", | ||||
| 	"%P([A-z])", | ||||
| 	"%g([A-z])", | ||||
| 	"%'(.)'", | ||||
| 	"%{([0-9]+)}", | ||||
| 	"%l", | ||||
| 	"%\\+|%-|%\\*|%/|%m", | ||||
| 	"%&|%\\||%\\^", | ||||
| 	"%=|%>|%<", | ||||
| 	"%A|%O", | ||||
| 	"%!|%~", | ||||
| 	"%i", | ||||
| 	"%(:[\\ #\\-\\+]{0,4})?(\\d+\\.\\d+|\\d+)?[doxXs]", | ||||
| 	"%\\?(.*?);", | ||||
| } | ||||
| 
 | ||||
| var regex *regexp.Regexp | ||||
| var staticVar map[byte]stacker | ||||
| 
 | ||||
| // Parses the attribute that is received with name attr and parameters params.
 | ||||
| func (term *TermInfo) Parse(attr string, params ...interface{}) (string, error) { | ||||
| 	// Get the attribute name first.
 | ||||
| 	iface, err := term.GetAttribute(attr) | ||||
| 	str, ok := iface.(string) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if !ok { | ||||
| 		return str, errors.New("Only string capabilities can be parsed.") | ||||
| 	} | ||||
| 	// Construct the hidden parser struct so we can use a recursive stack based
 | ||||
| 	// parser.
 | ||||
| 	ps := &parser{} | ||||
| 	// Dynamic variables only exist in this context.
 | ||||
| 	ps.dynamicVar = make(map[byte]stacker, 26) | ||||
| 	ps.parameters = make([]stacker, len(params)) | ||||
| 	// Convert the parameters to insert them into the parser struct.
 | ||||
| 	for i, x := range params { | ||||
| 		ps.parameters[i] = x | ||||
| 	} | ||||
| 	// Recursively walk and return.
 | ||||
| 	result, err := ps.walk(str) | ||||
| 	return result, err | ||||
| } | ||||
| 
 | ||||
| // Parses the attribute that is received with name attr and parameters params.
 | ||||
| // Only works on full name of a capability that is given, which it uses to
 | ||||
| // search for the termcap name.
 | ||||
| func (term *TermInfo) ParseName(attr string, params ...interface{}) (string, error) { | ||||
| 	tc := GetTermcapName(attr) | ||||
| 	return term.Parse(tc, params) | ||||
| } | ||||
| 
 | ||||
| // Identify each token in a stack based manner and do the actual parsing.
 | ||||
| func (ps *parser) walk(attr string) (string, error) { | ||||
| 	// We use a buffer to get the modified string.
 | ||||
| 	var buf bytes.Buffer | ||||
| 	// Next, find and identify all tokens by their indices and strings.
 | ||||
| 	tokens := regex.FindAllStringSubmatch(attr, -1) | ||||
| 	if len(tokens) == 0 { | ||||
| 		return attr, nil | ||||
| 	} | ||||
| 	indices := regex.FindAllStringIndex(attr, -1) | ||||
| 	q := 0 // q counts the matches of one token
 | ||||
| 	// Iterate through the string per character.
 | ||||
| 	for i := 0; i < len(attr); i++ { | ||||
| 		// If the current position is an identified token, execute the following
 | ||||
| 		// steps.
 | ||||
| 		if q < len(indices) && i >= indices[q][0] && i < indices[q][1] { | ||||
| 			// Switch on token.
 | ||||
| 			switch { | ||||
| 			case tokens[q][0][:2] == "%%": | ||||
| 				// Literal percentage character.
 | ||||
| 				buf.WriteByte('%') | ||||
| 			case tokens[q][0][:2] == "%c": | ||||
| 				// Pop a character.
 | ||||
| 				c, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				buf.WriteByte(c.(byte)) | ||||
| 			case tokens[q][0][:2] == "%s": | ||||
| 				// Pop a string.
 | ||||
| 				str, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				if _, ok := str.(string); !ok { | ||||
| 					return buf.String(), errors.New("Stack head is not a string") | ||||
| 				} | ||||
| 				buf.WriteString(str.(string)) | ||||
| 			case tokens[q][0][:2] == "%p": | ||||
| 				// Push a parameter on the stack.
 | ||||
| 				index, err := strconv.ParseInt(tokens[q][1], 10, 8) | ||||
| 				index-- | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				if int(index) >= len(ps.parameters) { | ||||
| 					return buf.String(), errors.New("Parameters index out of bound") | ||||
| 				} | ||||
| 				ps.st.push(ps.parameters[index]) | ||||
| 			case tokens[q][0][:2] == "%P": | ||||
| 				// Pop a variable from the stack as a dynamic or static variable.
 | ||||
| 				val, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				index := tokens[q][2] | ||||
| 				if len(index) > 1 { | ||||
| 					errorStr := fmt.Sprintf("%s is not a valid dynamic variables index", | ||||
| 						index) | ||||
| 					return buf.String(), errors.New(errorStr) | ||||
| 				} | ||||
| 				// Specify either dynamic or static.
 | ||||
| 				if index[0] >= 'a' && index[0] <= 'z' { | ||||
| 					ps.dynamicVar[index[0]] = val | ||||
| 				} else if index[0] >= 'A' && index[0] <= 'Z' { | ||||
| 					staticVar[index[0]] = val | ||||
| 				} | ||||
| 			case tokens[q][0][:2] == "%g": | ||||
| 				// Push a variable from the stack as a dynamic or static variable.
 | ||||
| 				index := tokens[q][3] | ||||
| 				if len(index) > 1 { | ||||
| 					errorStr := fmt.Sprintf("%s is not a valid static variables index", | ||||
| 						index) | ||||
| 					return buf.String(), errors.New(errorStr) | ||||
| 				} | ||||
| 				var val stacker | ||||
| 				if index[0] >= 'a' && index[0] <= 'z' { | ||||
| 					val = ps.dynamicVar[index[0]] | ||||
| 				} else if index[0] >= 'A' && index[0] <= 'Z' { | ||||
| 					val = staticVar[index[0]] | ||||
| 				} | ||||
| 				ps.st.push(val) | ||||
| 			case tokens[q][0][:2] == "%'": | ||||
| 				// Push a character constant.
 | ||||
| 				con := tokens[q][4] | ||||
| 				if len(con) > 1 { | ||||
| 					errorStr := fmt.Sprintf("%s is not a valid character constant", con) | ||||
| 					return buf.String(), errors.New(errorStr) | ||||
| 				} | ||||
| 				ps.st.push(con[0]) | ||||
| 			case tokens[q][0][:2] == "%{": | ||||
| 				// Push an integer constant.
 | ||||
| 				con, err := strconv.ParseInt(tokens[q][5], 10, 32) | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				ps.st.push(con) | ||||
| 			case tokens[q][0][:2] == "%l": | ||||
| 				// Push the length of the string that is popped from the stack.
 | ||||
| 				popStr, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				if _, ok := popStr.(string); !ok { | ||||
| 					errStr := fmt.Sprintf("Stack head is not a string") | ||||
| 					return buf.String(), errors.New(errStr) | ||||
| 				} | ||||
| 				ps.st.push(len(popStr.(string))) | ||||
| 			case tokens[q][0][:2] == "%?": | ||||
| 				// If-then-else construct. First, the whole string is identified and
 | ||||
| 				// then inside this substring, we can specify which parts to switch on.
 | ||||
| 				ifReg, _ := regexp.Compile("%\\?(.*)%t(.*)%e(.*);|%\\?(.*)%t(.*);") | ||||
| 				ifTokens := ifReg.FindStringSubmatch(tokens[q][0]) | ||||
| 				var ( | ||||
| 					ifStr string | ||||
| 					err   error | ||||
| 				) | ||||
| 				// Parse the if-part to determine if-else.
 | ||||
| 				if len(ifTokens[1]) > 0 { | ||||
| 					ifStr, err = ps.walk(ifTokens[1]) | ||||
| 				} else { // else
 | ||||
| 					ifStr, err = ps.walk(ifTokens[4]) | ||||
| 				} | ||||
| 				// Return any errors
 | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} else if len(ifStr) > 0 { | ||||
| 					// Self-defined limitation, not sure if this is correct, but didn't
 | ||||
| 					// seem like it.
 | ||||
| 					return buf.String(), errors.New("If-clause cannot print statements") | ||||
| 				} | ||||
| 				var thenStr string | ||||
| 				// Pop the first value that is set by parsing the if-clause.
 | ||||
| 				choose, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				// Switch to if or else.
 | ||||
| 				if choose.(int) == 0 && len(ifTokens[1]) > 0 { | ||||
| 					thenStr, err = ps.walk(ifTokens[3]) | ||||
| 				} else if choose.(int) != 0 { | ||||
| 					if len(ifTokens[1]) > 0 { | ||||
| 						thenStr, err = ps.walk(ifTokens[2]) | ||||
| 					} else { | ||||
| 						thenStr, err = ps.walk(ifTokens[5]) | ||||
| 					} | ||||
| 				} | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				buf.WriteString(thenStr) | ||||
| 			case tokens[q][0][len(tokens[q][0])-1] == 'd': // Fallthrough for printing
 | ||||
| 				fallthrough | ||||
| 			case tokens[q][0][len(tokens[q][0])-1] == 'o': // digits.
 | ||||
| 				fallthrough | ||||
| 			case tokens[q][0][len(tokens[q][0])-1] == 'x': | ||||
| 				fallthrough | ||||
| 			case tokens[q][0][len(tokens[q][0])-1] == 'X': | ||||
| 				fallthrough | ||||
| 			case tokens[q][0][len(tokens[q][0])-1] == 's': | ||||
| 				token := tokens[q][0] | ||||
| 				// Remove the : that comes before a flag.
 | ||||
| 				if token[1] == ':' { | ||||
| 					token = token[:1] + token[2:] | ||||
| 				} | ||||
| 				digit, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				// The rest is determined like the normal formatted prints.
 | ||||
| 				digitStr := fmt.Sprintf(token, digit.(int)) | ||||
| 				buf.WriteString(digitStr) | ||||
| 			case tokens[q][0][:2] == "%i": | ||||
| 				// Increment the parameters by one.
 | ||||
| 				if len(ps.parameters) < 2 { | ||||
| 					return buf.String(), errors.New("Not enough parameters to increment.") | ||||
| 				} | ||||
| 				val1, val2 := ps.parameters[0].(int), ps.parameters[1].(int) | ||||
| 				val1++ | ||||
| 				val2++ | ||||
| 				ps.parameters[0], ps.parameters[1] = val1, val2 | ||||
| 			default: | ||||
| 				// The rest of the tokens is a special case, where two values are
 | ||||
| 				// popped and then operated on by the token that comes after them.
 | ||||
| 				op1, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				op2, err := ps.st.pop() | ||||
| 				if err != nil { | ||||
| 					return buf.String(), err | ||||
| 				} | ||||
| 				var result stacker | ||||
| 				switch tokens[q][0][:2] { | ||||
| 				case "%+": | ||||
| 					// Addition
 | ||||
| 					result = op2.(int) + op1.(int) | ||||
| 				case "%-": | ||||
| 					// Subtraction
 | ||||
| 					result = op2.(int) - op1.(int) | ||||
| 				case "%*": | ||||
| 					// Multiplication
 | ||||
| 					result = op2.(int) * op1.(int) | ||||
| 				case "%/": | ||||
| 					// Division
 | ||||
| 					result = op2.(int) / op1.(int) | ||||
| 				case "%m": | ||||
| 					// Modulo
 | ||||
| 					result = op2.(int) % op1.(int) | ||||
| 				case "%&": | ||||
| 					// Bitwise AND
 | ||||
| 					result = op2.(int) & op1.(int) | ||||
| 				case "%|": | ||||
| 					// Bitwise OR
 | ||||
| 					result = op2.(int) | op1.(int) | ||||
| 				case "%^": | ||||
| 					// Bitwise XOR
 | ||||
| 					result = op2.(int) ^ op1.(int) | ||||
| 				case "%=": | ||||
| 					// Equals
 | ||||
| 					result = op2 == op1 | ||||
| 				case "%>": | ||||
| 					// Greater-than
 | ||||
| 					result = op2.(int) > op1.(int) | ||||
| 				case "%<": | ||||
| 					// Lesser-than
 | ||||
| 					result = op2.(int) < op1.(int) | ||||
| 				case "%A": | ||||
| 					// Logical AND
 | ||||
| 					result = op2.(bool) && op1.(bool) | ||||
| 				case "%O": | ||||
| 					// Logical OR
 | ||||
| 					result = op2.(bool) || op1.(bool) | ||||
| 				case "%!": | ||||
| 					// Logical complement
 | ||||
| 					result = !op1.(bool) | ||||
| 				case "%~": | ||||
| 					// Bitwise complement
 | ||||
| 					result = ^(op1.(int)) | ||||
| 				} | ||||
| 				ps.st.push(result) | ||||
| 			} | ||||
| 
 | ||||
| 			i = indices[q][1] - 1 | ||||
| 			q++ | ||||
| 		} else { | ||||
| 			// We are not "inside" a token, so just skip until the end or the next
 | ||||
| 			// token, and add all characters to the buffer.
 | ||||
| 			j := i | ||||
| 			if q != len(indices) { | ||||
| 				for !(j >= indices[q][0] && j < indices[q][1]) { | ||||
| 					j++ | ||||
| 				} | ||||
| 			} else { | ||||
| 				j = len(attr) | ||||
| 			} | ||||
| 			buf.WriteString(string(attr[i:j])) | ||||
| 			i = j | ||||
| 		} | ||||
| 	} | ||||
| 	// Return the buffer as a string.
 | ||||
| 	return buf.String(), nil | ||||
| } | ||||
| 
 | ||||
| // Push a stacker-value onto the stack.
 | ||||
| func (st *stack) push(s stacker) { | ||||
| 	*st = append(*st, s) | ||||
| } | ||||
| 
 | ||||
| // Pop a stacker-value from the stack.
 | ||||
| func (st *stack) pop() (stacker, error) { | ||||
| 	if len(*st) == 0 { | ||||
| 		return nil, errors.New("Stack is empty.") | ||||
| 	} | ||||
| 	newStack := make(stack, len(*st)-1) | ||||
| 	val := (*st)[len(*st)-1] | ||||
| 	copy(newStack, (*st)[:len(*st)-1]) | ||||
| 	*st = newStack | ||||
| 	return val, nil | ||||
| } | ||||
| 
 | ||||
| // Initialize regexes and the static vars (that don't get changed between
 | ||||
| // calls.
 | ||||
| func init() { | ||||
| 	// Initialize the main regex.
 | ||||
| 	expStr := strings.Join(exp[:], "|") | ||||
| 	regex, _ = regexp.Compile(expStr) | ||||
| 	// Initialize the static variables.
 | ||||
| 	staticVar = make(map[byte]stacker, 26) | ||||
| } | ||||
|  | @ -1,23 +0,0 @@ | |||
| // Copyright 2012 Neal van Veen. All rights reserved.
 | ||||
| // Usage of this source code is governed by a BSD-style license that can be
 | ||||
| // found in the LICENSE file.
 | ||||
| 
 | ||||
| package gotty | ||||
| 
 | ||||
| type TermInfo struct { | ||||
| 	boolAttributes map[string]bool | ||||
| 	numAttributes  map[string]int16 | ||||
| 	strAttributes  map[string]string | ||||
| 	// The various names of the TermInfo file.
 | ||||
| 	Names []string | ||||
| } | ||||
| 
 | ||||
| type stacker interface { | ||||
| } | ||||
| type stack []stacker | ||||
| 
 | ||||
| type parser struct { | ||||
| 	st         stack | ||||
| 	parameters []stacker | ||||
| 	dynamicVar map[byte]stacker | ||||
| } | ||||
|  | @ -1,18 +0,0 @@ | |||
| BRANCH=`git rev-parse --abbrev-ref HEAD` | ||||
| COMMIT=`git rev-parse --short HEAD` | ||||
| GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" | ||||
| 
 | ||||
| default: build | ||||
| 
 | ||||
| race: | ||||
| 	@go test -v -race -test.run="TestSimulate_(100op|1000op)" | ||||
| 
 | ||||
| # go get github.com/kisielk/errcheck
 | ||||
| errcheck: | ||||
| 	@errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt | ||||
| 
 | ||||
| test:  | ||||
| 	@go test -v -cover . | ||||
| 	@go test -v ./cmd/bolt | ||||
| 
 | ||||
| .PHONY: fmt test | ||||
|  | @ -1,18 +0,0 @@ | |||
| version: "{build}" | ||||
| 
 | ||||
| os: Windows Server 2012 R2 | ||||
| 
 | ||||
| clone_folder: c:\gopath\src\github.com\boltdb\bolt | ||||
| 
 | ||||
| environment: | ||||
|   GOPATH: c:\gopath | ||||
| 
 | ||||
| install: | ||||
|   - echo %PATH% | ||||
|   - echo %GOPATH% | ||||
|   - go version | ||||
|   - go env | ||||
|   - go get -v -t ./... | ||||
| 
 | ||||
| build_script: | ||||
|   - go test -v ./... | ||||
|  | @ -1,252 +0,0 @@ | |||
| package bolt | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // freelist represents a list of all pages that are available for allocation.
 | ||||
| // It also tracks pages that have been freed but are still in use by open transactions.
 | ||||
| type freelist struct { | ||||
| 	ids     []pgid          // all free and available free page ids.
 | ||||
| 	pending map[txid][]pgid // mapping of soon-to-be free page ids by tx.
 | ||||
| 	cache   map[pgid]bool   // fast lookup of all free and pending page ids.
 | ||||
| } | ||||
| 
 | ||||
| // newFreelist returns an empty, initialized freelist.
 | ||||
| func newFreelist() *freelist { | ||||
| 	return &freelist{ | ||||
| 		pending: make(map[txid][]pgid), | ||||
| 		cache:   make(map[pgid]bool), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // size returns the size of the page after serialization.
 | ||||
| func (f *freelist) size() int { | ||||
| 	n := f.count() | ||||
| 	if n >= 0xFFFF { | ||||
| 		// The first element will be used to store the count. See freelist.write.
 | ||||
| 		n++ | ||||
| 	} | ||||
| 	return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n) | ||||
| } | ||||
| 
 | ||||
| // count returns count of pages on the freelist
 | ||||
| func (f *freelist) count() int { | ||||
| 	return f.free_count() + f.pending_count() | ||||
| } | ||||
| 
 | ||||
| // free_count returns count of free pages
 | ||||
| func (f *freelist) free_count() int { | ||||
| 	return len(f.ids) | ||||
| } | ||||
| 
 | ||||
| // pending_count returns count of pending pages
 | ||||
| func (f *freelist) pending_count() int { | ||||
| 	var count int | ||||
| 	for _, list := range f.pending { | ||||
| 		count += len(list) | ||||
| 	} | ||||
| 	return count | ||||
| } | ||||
| 
 | ||||
| // copyall copies into dst a list of all free ids and all pending ids in one sorted list.
 | ||||
| // f.count returns the minimum length required for dst.
 | ||||
| func (f *freelist) copyall(dst []pgid) { | ||||
| 	m := make(pgids, 0, f.pending_count()) | ||||
| 	for _, list := range f.pending { | ||||
| 		m = append(m, list...) | ||||
| 	} | ||||
| 	sort.Sort(m) | ||||
| 	mergepgids(dst, f.ids, m) | ||||
| } | ||||
| 
 | ||||
| // allocate returns the starting page id of a contiguous list of pages of a given size.
 | ||||
| // If a contiguous block cannot be found then 0 is returned.
 | ||||
| func (f *freelist) allocate(n int) pgid { | ||||
| 	if len(f.ids) == 0 { | ||||
| 		return 0 | ||||
| 	} | ||||
| 
 | ||||
| 	var initial, previd pgid | ||||
| 	for i, id := range f.ids { | ||||
| 		if id <= 1 { | ||||
| 			panic(fmt.Sprintf("invalid page allocation: %d", id)) | ||||
| 		} | ||||
| 
 | ||||
| 		// Reset initial page if this is not contiguous.
 | ||||
| 		if previd == 0 || id-previd != 1 { | ||||
| 			initial = id | ||||
| 		} | ||||
| 
 | ||||
| 		// If we found a contiguous block then remove it and return it.
 | ||||
| 		if (id-initial)+1 == pgid(n) { | ||||
| 			// If we're allocating off the beginning then take the fast path
 | ||||
| 			// and just adjust the existing slice. This will use extra memory
 | ||||
| 			// temporarily but the append() in free() will realloc the slice
 | ||||
| 			// as is necessary.
 | ||||
| 			if (i + 1) == n { | ||||
| 				f.ids = f.ids[i+1:] | ||||
| 			} else { | ||||
| 				copy(f.ids[i-n+1:], f.ids[i+1:]) | ||||
| 				f.ids = f.ids[:len(f.ids)-n] | ||||
| 			} | ||||
| 
 | ||||
| 			// Remove from the free cache.
 | ||||
| 			for i := pgid(0); i < pgid(n); i++ { | ||||
| 				delete(f.cache, initial+i) | ||||
| 			} | ||||
| 
 | ||||
| 			return initial | ||||
| 		} | ||||
| 
 | ||||
| 		previd = id | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| // free releases a page and its overflow for a given transaction id.
 | ||||
| // If the page is already free then a panic will occur.
 | ||||
| func (f *freelist) free(txid txid, p *page) { | ||||
| 	if p.id <= 1 { | ||||
| 		panic(fmt.Sprintf("cannot free page 0 or 1: %d", p.id)) | ||||
| 	} | ||||
| 
 | ||||
| 	// Free page and all its overflow pages.
 | ||||
| 	var ids = f.pending[txid] | ||||
| 	for id := p.id; id <= p.id+pgid(p.overflow); id++ { | ||||
| 		// Verify that page is not already free.
 | ||||
| 		if f.cache[id] { | ||||
| 			panic(fmt.Sprintf("page %d already freed", id)) | ||||
| 		} | ||||
| 
 | ||||
| 		// Add to the freelist and cache.
 | ||||
| 		ids = append(ids, id) | ||||
| 		f.cache[id] = true | ||||
| 	} | ||||
| 	f.pending[txid] = ids | ||||
| } | ||||
| 
 | ||||
| // release moves all page ids for a transaction id (or older) to the freelist.
 | ||||
| func (f *freelist) release(txid txid) { | ||||
| 	m := make(pgids, 0) | ||||
| 	for tid, ids := range f.pending { | ||||
| 		if tid <= txid { | ||||
| 			// Move transaction's pending pages to the available freelist.
 | ||||
| 			// Don't remove from the cache since the page is still free.
 | ||||
| 			m = append(m, ids...) | ||||
| 			delete(f.pending, tid) | ||||
| 		} | ||||
| 	} | ||||
| 	sort.Sort(m) | ||||
| 	f.ids = pgids(f.ids).merge(m) | ||||
| } | ||||
| 
 | ||||
| // rollback removes the pages from a given pending tx.
 | ||||
| func (f *freelist) rollback(txid txid) { | ||||
| 	// Remove page ids from cache.
 | ||||
| 	for _, id := range f.pending[txid] { | ||||
| 		delete(f.cache, id) | ||||
| 	} | ||||
| 
 | ||||
| 	// Remove pages from pending list.
 | ||||
| 	delete(f.pending, txid) | ||||
| } | ||||
| 
 | ||||
| // freed returns whether a given page is in the free list.
 | ||||
| func (f *freelist) freed(pgid pgid) bool { | ||||
| 	return f.cache[pgid] | ||||
| } | ||||
| 
 | ||||
| // read initializes the freelist from a freelist page.
 | ||||
| func (f *freelist) read(p *page) { | ||||
| 	// If the page.count is at the max uint16 value (64k) then it's considered
 | ||||
| 	// an overflow and the size of the freelist is stored as the first element.
 | ||||
| 	idx, count := 0, int(p.count) | ||||
| 	if count == 0xFFFF { | ||||
| 		idx = 1 | ||||
| 		count = int(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0]) | ||||
| 	} | ||||
| 
 | ||||
| 	// Copy the list of page ids from the freelist.
 | ||||
| 	if count == 0 { | ||||
| 		f.ids = nil | ||||
| 	} else { | ||||
| 		ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] | ||||
| 		f.ids = make([]pgid, len(ids)) | ||||
| 		copy(f.ids, ids) | ||||
| 
 | ||||
| 		// Make sure they're sorted.
 | ||||
| 		sort.Sort(pgids(f.ids)) | ||||
| 	} | ||||
| 
 | ||||
| 	// Rebuild the page cache.
 | ||||
| 	f.reindex() | ||||
| } | ||||
| 
 | ||||
| // write writes the page ids onto a freelist page. All free and pending ids are
 | ||||
| // saved to disk since in the event of a program crash, all pending ids will
 | ||||
| // become free.
 | ||||
| func (f *freelist) write(p *page) error { | ||||
| 	// Combine the old free pgids and pgids waiting on an open transaction.
 | ||||
| 
 | ||||
| 	// Update the header flag.
 | ||||
| 	p.flags |= freelistPageFlag | ||||
| 
 | ||||
| 	// The page.count can only hold up to 64k elements so if we overflow that
 | ||||
| 	// number then we handle it by putting the size in the first element.
 | ||||
| 	lenids := f.count() | ||||
| 	if lenids == 0 { | ||||
| 		p.count = uint16(lenids) | ||||
| 	} else if lenids < 0xFFFF { | ||||
| 		p.count = uint16(lenids) | ||||
| 		f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:]) | ||||
| 	} else { | ||||
| 		p.count = 0xFFFF | ||||
| 		((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(lenids) | ||||
| 		f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:]) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // reload reads the freelist from a page and filters out pending items.
 | ||||
| func (f *freelist) reload(p *page) { | ||||
| 	f.read(p) | ||||
| 
 | ||||
| 	// Build a cache of only pending pages.
 | ||||
| 	pcache := make(map[pgid]bool) | ||||
| 	for _, pendingIDs := range f.pending { | ||||
| 		for _, pendingID := range pendingIDs { | ||||
| 			pcache[pendingID] = true | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Check each page in the freelist and build a new available freelist
 | ||||
| 	// with any pages not in the pending lists.
 | ||||
| 	var a []pgid | ||||
| 	for _, id := range f.ids { | ||||
| 		if !pcache[id] { | ||||
| 			a = append(a, id) | ||||
| 		} | ||||
| 	} | ||||
| 	f.ids = a | ||||
| 
 | ||||
| 	// Once the available list is rebuilt then rebuild the free cache so that
 | ||||
| 	// it includes the available and pending free pages.
 | ||||
| 	f.reindex() | ||||
| } | ||||
| 
 | ||||
| // reindex rebuilds the free cache based on available and pending free lists.
 | ||||
| func (f *freelist) reindex() { | ||||
| 	f.cache = make(map[pgid]bool, len(f.ids)) | ||||
| 	for _, id := range f.ids { | ||||
| 		f.cache[id] = true | ||||
| 	} | ||||
| 	for _, pendingIDs := range f.pending { | ||||
| 		for _, pendingID := range pendingIDs { | ||||
| 			f.cache[pendingID] = true | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -18,9 +18,13 @@ package cio | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/containerd/containerd/defaults" | ||||
|  | @ -140,6 +144,15 @@ func NewCreator(opts ...Opt) Creator { | |||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if streams.Stdin == nil { | ||||
| 			fifos.Stdin = "" | ||||
| 		} | ||||
| 		if streams.Stdout == nil { | ||||
| 			fifos.Stdout = "" | ||||
| 		} | ||||
| 		if streams.Stderr == nil { | ||||
| 			fifos.Stderr = "" | ||||
| 		} | ||||
| 		return copyIO(fifos, streams) | ||||
| 	} | ||||
| } | ||||
|  | @ -212,7 +225,90 @@ type DirectIO struct { | |||
| 	cio | ||||
| } | ||||
| 
 | ||||
| var _ IO = &DirectIO{} | ||||
| var ( | ||||
| 	_ IO = &DirectIO{} | ||||
| 	_ IO = &logURI{} | ||||
| ) | ||||
| 
 | ||||
| // LogURI provides the raw logging URI
 | ||||
| func LogURI(uri *url.URL) Creator { | ||||
| 	return func(_ string) (IO, error) { | ||||
| 		return &logURI{ | ||||
| 			config: Config{ | ||||
| 				Stdout: uri.String(), | ||||
| 				Stderr: uri.String(), | ||||
| 			}, | ||||
| 		}, nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // BinaryIO forwards container STDOUT|STDERR directly to a logging binary
 | ||||
| func BinaryIO(binary string, args map[string]string) Creator { | ||||
| 	return func(_ string) (IO, error) { | ||||
| 		binary = filepath.Clean(binary) | ||||
| 		if !strings.HasPrefix(binary, "/") { | ||||
| 			return nil, errors.New("absolute path needed") | ||||
| 		} | ||||
| 		uri := &url.URL{ | ||||
| 			Scheme: "binary", | ||||
| 			Path:   binary, | ||||
| 		} | ||||
| 		q := uri.Query() | ||||
| 		for k, v := range args { | ||||
| 			q.Set(k, v) | ||||
| 		} | ||||
| 		uri.RawQuery = q.Encode() | ||||
| 		res := uri.String() | ||||
| 		return &logURI{ | ||||
| 			config: Config{ | ||||
| 				Stdout: res, | ||||
| 				Stderr: res, | ||||
| 			}, | ||||
| 		}, nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // LogFile creates a file on disk that logs the task's STDOUT,STDERR.
 | ||||
| // If the log file already exists, the logs will be appended to the file.
 | ||||
| func LogFile(path string) Creator { | ||||
| 	return func(_ string) (IO, error) { | ||||
| 		path = filepath.Clean(path) | ||||
| 		if !strings.HasPrefix(path, "/") { | ||||
| 			return nil, errors.New("absolute path needed") | ||||
| 		} | ||||
| 		uri := &url.URL{ | ||||
| 			Scheme: "file", | ||||
| 			Path:   path, | ||||
| 		} | ||||
| 		res := uri.String() | ||||
| 		return &logURI{ | ||||
| 			config: Config{ | ||||
| 				Stdout: res, | ||||
| 				Stderr: res, | ||||
| 			}, | ||||
| 		}, nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type logURI struct { | ||||
| 	config Config | ||||
| } | ||||
| 
 | ||||
| func (l *logURI) Config() Config { | ||||
| 	return l.config | ||||
| } | ||||
| 
 | ||||
| func (l *logURI) Cancel() { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func (l *logURI) Wait() { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func (l *logURI) Close() error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Load the io for a container but do not attach
 | ||||
| //
 | ||||
|  | @ -224,3 +320,7 @@ func Load(set *FIFOSet) (IO, error) { | |||
| 		closers: []io.Closer{set}, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func (p *pipes) closers() []io.Closer { | ||||
| 	return []io.Closer{p.Stdin, p.Stdout, p.Stderr} | ||||
| } | ||||
|  |  | |||
|  | @ -72,6 +72,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | |||
| 	} | ||||
| 
 | ||||
| 	var wg = &sync.WaitGroup{} | ||||
| 	if fifos.Stdout != "" { | ||||
| 		wg.Add(1) | ||||
| 		go func() { | ||||
| 			p := bufPool.Get().(*[]byte) | ||||
|  | @ -81,8 +82,9 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | |||
| 			pipes.Stdout.Close() | ||||
| 			wg.Done() | ||||
| 		}() | ||||
| 	} | ||||
| 
 | ||||
| 	if !fifos.Terminal { | ||||
| 	if !fifos.Terminal && fifos.Stderr != "" { | ||||
| 		wg.Add(1) | ||||
| 		go func() { | ||||
| 			p := bufPool.Get().(*[]byte) | ||||
|  | @ -152,7 +154,3 @@ func NewDirectIO(ctx context.Context, fifos *FIFOSet) (*DirectIO, error) { | |||
| 		}, | ||||
| 	}, err | ||||
| } | ||||
| 
 | ||||
| func (p *pipes) closers() []io.Closer { | ||||
| 	return []io.Closer{p.Stdin, p.Stdout, p.Stderr} | ||||
| } | ||||
|  |  | |||
|  | @ -17,10 +17,10 @@ | |||
| package cio | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	winio "github.com/Microsoft/go-winio" | ||||
| 	"github.com/containerd/containerd/log" | ||||
|  | @ -31,17 +31,20 @@ const pipeRoot = `\\.\pipe` | |||
| 
 | ||||
| // NewFIFOSetInDir returns a new set of fifos for the task
 | ||||
| func NewFIFOSetInDir(_, id string, terminal bool) (*FIFOSet, error) { | ||||
| 	stderrPipe := "" | ||||
| 	if !terminal { | ||||
| 		stderrPipe = fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id) | ||||
| 	} | ||||
| 	return NewFIFOSet(Config{ | ||||
| 		Terminal: terminal, | ||||
| 		Stdin:    fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id), | ||||
| 		Stdout:   fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id), | ||||
| 		Stderr:   fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id), | ||||
| 		Stderr:   stderrPipe, | ||||
| 	}, nil), nil | ||||
| } | ||||
| 
 | ||||
| func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | ||||
| 	var ( | ||||
| 		wg  sync.WaitGroup | ||||
| 		set []io.Closer | ||||
| 	) | ||||
| 
 | ||||
|  | @ -76,7 +79,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | |||
| 	if fifos.Stdout != "" { | ||||
| 		l, err := winio.ListenPipe(fifos.Stdout, nil) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdout) | ||||
| 			return nil, errors.Wrapf(err, "failed to create stdout pipe %s", fifos.Stdout) | ||||
| 		} | ||||
| 		defer func(l net.Listener) { | ||||
| 			if err != nil { | ||||
|  | @ -85,9 +88,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | |||
| 		}(l) | ||||
| 		set = append(set, l) | ||||
| 
 | ||||
| 		wg.Add(1) | ||||
| 		go func() { | ||||
| 			defer wg.Done() | ||||
| 			c, err := l.Accept() | ||||
| 			if err != nil { | ||||
| 				log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout) | ||||
|  | @ -103,7 +104,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | |||
| 		}() | ||||
| 	} | ||||
| 
 | ||||
| 	if !fifos.Terminal && fifos.Stderr != "" { | ||||
| 	if fifos.Stderr != "" { | ||||
| 		l, err := winio.ListenPipe(fifos.Stderr, nil) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Stderr) | ||||
|  | @ -115,9 +116,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { | |||
| 		}(l) | ||||
| 		set = append(set, l) | ||||
| 
 | ||||
| 		wg.Add(1) | ||||
| 		go func() { | ||||
| 			defer wg.Done() | ||||
| 			c, err := l.Accept() | ||||
| 			if err != nil { | ||||
| 				log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr) | ||||
|  | @ -150,3 +149,22 @@ func NewDirectIO(stdin io.WriteCloser, stdout, stderr io.ReadCloser, terminal bo | |||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewDirectIOFromFIFOSet returns an IO implementation that exposes the IO streams as io.ReadCloser
 | ||||
| // and io.WriteCloser.
 | ||||
| func NewDirectIOFromFIFOSet(ctx context.Context, stdin io.WriteCloser, stdout, stderr io.ReadCloser, fifos *FIFOSet) *DirectIO { | ||||
| 	_, cancel := context.WithCancel(ctx) | ||||
| 	pipes := pipes{ | ||||
| 		Stdin:  stdin, | ||||
| 		Stdout: stdout, | ||||
| 		Stderr: stderr, | ||||
| 	} | ||||
| 	return &DirectIO{ | ||||
| 		pipes: pipes, | ||||
| 		cio: cio{ | ||||
| 			config:  fifos.Config, | ||||
| 			closers: append(pipes.closers(), fifos), | ||||
| 			cancel:  cancel, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -23,4 +23,10 @@ const ( | |||
| 	// DefaultMaxSendMsgSize defines the default maximum message size for
 | ||||
| 	// sending protobufs passed over the GRPC API.
 | ||||
| 	DefaultMaxSendMsgSize = 16 << 20 | ||||
| 	// DefaultRuntimeNSLabel defines the namespace label to check for the
 | ||||
| 	// default runtime
 | ||||
| 	DefaultRuntimeNSLabel = "containerd.io/defaults/runtime" | ||||
| 	// DefaultSnapshotterNSLabel defines the namespace label to check for the
 | ||||
| 	// default snapshotter
 | ||||
| 	DefaultSnapshotterNSLabel = "containerd.io/defaults/snapshotter" | ||||
| ) | ||||
|  |  | |||
|  | @ -32,4 +32,6 @@ const ( | |||
| 	// DefaultFIFODir is the default location used by client-side cio library
 | ||||
| 	// to store FIFOs.
 | ||||
| 	DefaultFIFODir = "/run/containerd/fifo" | ||||
| 	// DefaultRuntime is the default linux runtime
 | ||||
| 	DefaultRuntime = "io.containerd.runc.v2" | ||||
| ) | ||||
|  |  | |||
|  | @ -26,10 +26,10 @@ import ( | |||
| var ( | ||||
| 	// DefaultRootDir is the default location used by containerd to store
 | ||||
| 	// persistent data
 | ||||
| 	DefaultRootDir = filepath.Join(os.Getenv("programfiles"), "containerd", "root") | ||||
| 	DefaultRootDir = filepath.Join(os.Getenv("ProgramData"), "containerd", "root") | ||||
| 	// DefaultStateDir is the default location used by containerd to store
 | ||||
| 	// transient data
 | ||||
| 	DefaultStateDir = filepath.Join(os.Getenv("programfiles"), "containerd", "state") | ||||
| 	DefaultStateDir = filepath.Join(os.Getenv("ProgramData"), "containerd", "state") | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
|  | @ -40,4 +40,6 @@ const ( | |||
| 	// DefaultFIFODir is the default location used by client-side cio library
 | ||||
| 	// to store FIFOs. Unused on Windows.
 | ||||
| 	DefaultFIFODir = "" | ||||
| 	// DefaultRuntime is the default windows runtime
 | ||||
| 	DefaultRuntime = "io.containerd.runhcs.v1" | ||||
| ) | ||||
|  |  | |||
|  | @ -0,0 +1,93 @@ | |||
| /* | ||||
|    Copyright The containerd 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 errdefs defines the common errors used throughout containerd
 | ||||
| // packages.
 | ||||
| //
 | ||||
| // Use with errors.Wrap and error.Wrapf to add context to an error.
 | ||||
| //
 | ||||
| // To detect an error class, use the IsXXX functions to tell whether an error
 | ||||
| // is of a certain type.
 | ||||
| //
 | ||||
| // The functions ToGRPC and FromGRPC can be used to map server-side and
 | ||||
| // client-side errors to the correct types.
 | ||||
| package errdefs | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
| 
 | ||||
| // Definitions of common error types used throughout containerd. All containerd
 | ||||
| // errors returned by most packages will map into one of these errors classes.
 | ||||
| // Packages should return errors of these types when they want to instruct a
 | ||||
| // client to take a particular action.
 | ||||
| //
 | ||||
| // For the most part, we just try to provide local grpc errors. Most conditions
 | ||||
| // map very well to those defined by grpc.
 | ||||
| var ( | ||||
| 	ErrUnknown            = errors.New("unknown") // used internally to represent a missed mapping.
 | ||||
| 	ErrInvalidArgument    = errors.New("invalid argument") | ||||
| 	ErrNotFound           = errors.New("not found") | ||||
| 	ErrAlreadyExists      = errors.New("already exists") | ||||
| 	ErrFailedPrecondition = errors.New("failed precondition") | ||||
| 	ErrUnavailable        = errors.New("unavailable") | ||||
| 	ErrNotImplemented     = errors.New("not implemented") // represents not supported and unimplemented
 | ||||
| ) | ||||
| 
 | ||||
| // IsInvalidArgument returns true if the error is due to an invalid argument
 | ||||
| func IsInvalidArgument(err error) bool { | ||||
| 	return errors.Cause(err) == ErrInvalidArgument | ||||
| } | ||||
| 
 | ||||
| // IsNotFound returns true if the error is due to a missing object
 | ||||
| func IsNotFound(err error) bool { | ||||
| 	return errors.Cause(err) == ErrNotFound | ||||
| } | ||||
| 
 | ||||
| // IsAlreadyExists returns true if the error is due to an already existing
 | ||||
| // metadata item
 | ||||
| func IsAlreadyExists(err error) bool { | ||||
| 	return errors.Cause(err) == ErrAlreadyExists | ||||
| } | ||||
| 
 | ||||
| // IsFailedPrecondition returns true if an operation could not proceed to the
 | ||||
| // lack of a particular condition
 | ||||
| func IsFailedPrecondition(err error) bool { | ||||
| 	return errors.Cause(err) == ErrFailedPrecondition | ||||
| } | ||||
| 
 | ||||
| // IsUnavailable returns true if the error is due to a resource being unavailable
 | ||||
| func IsUnavailable(err error) bool { | ||||
| 	return errors.Cause(err) == ErrUnavailable | ||||
| } | ||||
| 
 | ||||
| // IsNotImplemented returns true if the error is due to not being implemented
 | ||||
| func IsNotImplemented(err error) bool { | ||||
| 	return errors.Cause(err) == ErrNotImplemented | ||||
| } | ||||
| 
 | ||||
| // IsCanceled returns true if the error is due to `context.Canceled`.
 | ||||
| func IsCanceled(err error) bool { | ||||
| 	return errors.Cause(err) == context.Canceled | ||||
| } | ||||
| 
 | ||||
| // IsDeadlineExceeded returns true if the error is due to
 | ||||
| // `context.DeadlineExceeded`.
 | ||||
| func IsDeadlineExceeded(err error) bool { | ||||
| 	return errors.Cause(err) == context.DeadlineExceeded | ||||
| } | ||||
|  | @ -0,0 +1,147 @@ | |||
| /* | ||||
|    Copyright The containerd 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 errdefs | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/pkg/errors" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
| 
 | ||||
| // ToGRPC will attempt to map the backend containerd error into a grpc error,
 | ||||
| // using the original error message as a description.
 | ||||
| //
 | ||||
| // Further information may be extracted from certain errors depending on their
 | ||||
| // type.
 | ||||
| //
 | ||||
| // If the error is unmapped, the original error will be returned to be handled
 | ||||
| // by the regular grpc error handling stack.
 | ||||
| func ToGRPC(err error) error { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if isGRPCError(err) { | ||||
| 		// error has already been mapped to grpc
 | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	switch { | ||||
| 	case IsInvalidArgument(err): | ||||
| 		return status.Errorf(codes.InvalidArgument, err.Error()) | ||||
| 	case IsNotFound(err): | ||||
| 		return status.Errorf(codes.NotFound, err.Error()) | ||||
| 	case IsAlreadyExists(err): | ||||
| 		return status.Errorf(codes.AlreadyExists, err.Error()) | ||||
| 	case IsFailedPrecondition(err): | ||||
| 		return status.Errorf(codes.FailedPrecondition, err.Error()) | ||||
| 	case IsUnavailable(err): | ||||
| 		return status.Errorf(codes.Unavailable, err.Error()) | ||||
| 	case IsNotImplemented(err): | ||||
| 		return status.Errorf(codes.Unimplemented, err.Error()) | ||||
| 	case IsCanceled(err): | ||||
| 		return status.Errorf(codes.Canceled, err.Error()) | ||||
| 	case IsDeadlineExceeded(err): | ||||
| 		return status.Errorf(codes.DeadlineExceeded, err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // ToGRPCf maps the error to grpc error codes, assembling the formatting string
 | ||||
| // and combining it with the target error string.
 | ||||
| //
 | ||||
| // This is equivalent to errors.ToGRPC(errors.Wrapf(err, format, args...))
 | ||||
| func ToGRPCf(err error, format string, args ...interface{}) error { | ||||
| 	return ToGRPC(errors.Wrapf(err, format, args...)) | ||||
| } | ||||
| 
 | ||||
| // FromGRPC returns the underlying error from a grpc service based on the grpc error code
 | ||||
| func FromGRPC(err error) error { | ||||
| 	if err == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	var cls error // divide these into error classes, becomes the cause
 | ||||
| 
 | ||||
| 	switch code(err) { | ||||
| 	case codes.InvalidArgument: | ||||
| 		cls = ErrInvalidArgument | ||||
| 	case codes.AlreadyExists: | ||||
| 		cls = ErrAlreadyExists | ||||
| 	case codes.NotFound: | ||||
| 		cls = ErrNotFound | ||||
| 	case codes.Unavailable: | ||||
| 		cls = ErrUnavailable | ||||
| 	case codes.FailedPrecondition: | ||||
| 		cls = ErrFailedPrecondition | ||||
| 	case codes.Unimplemented: | ||||
| 		cls = ErrNotImplemented | ||||
| 	case codes.Canceled: | ||||
| 		cls = context.Canceled | ||||
| 	case codes.DeadlineExceeded: | ||||
| 		cls = context.DeadlineExceeded | ||||
| 	default: | ||||
| 		cls = ErrUnknown | ||||
| 	} | ||||
| 
 | ||||
| 	msg := rebaseMessage(cls, err) | ||||
| 	if msg != "" { | ||||
| 		err = errors.Wrap(cls, msg) | ||||
| 	} else { | ||||
| 		err = errors.WithStack(cls) | ||||
| 	} | ||||
| 
 | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // rebaseMessage removes the repeats for an error at the end of an error
 | ||||
| // string. This will happen when taking an error over grpc then remapping it.
 | ||||
| //
 | ||||
| // Effectively, we just remove the string of cls from the end of err if it
 | ||||
| // appears there.
 | ||||
| func rebaseMessage(cls error, err error) string { | ||||
| 	desc := errDesc(err) | ||||
| 	clss := cls.Error() | ||||
| 	if desc == clss { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	return strings.TrimSuffix(desc, ": "+clss) | ||||
| } | ||||
| 
 | ||||
| func isGRPCError(err error) bool { | ||||
| 	_, ok := status.FromError(err) | ||||
| 	return ok | ||||
| } | ||||
| 
 | ||||
| func code(err error) codes.Code { | ||||
| 	if s, ok := status.FromError(err); ok { | ||||
| 		return s.Code() | ||||
| 	} | ||||
| 	return codes.Unknown | ||||
| } | ||||
| 
 | ||||
| func errDesc(err error) string { | ||||
| 	if s, ok := status.FromError(err); ok { | ||||
| 		return s.Message() | ||||
| 	} | ||||
| 	return err.Error() | ||||
| } | ||||
|  | @ -30,7 +30,7 @@ var ( | |||
| 	// messages.
 | ||||
| 	G = GetLogger | ||||
| 
 | ||||
| 	// L is an alias for the the standard logger.
 | ||||
| 	// L is an alias for the standard logger.
 | ||||
| 	L = logrus.NewEntry(logrus.StandardLogger()) | ||||
| ) | ||||
| 
 | ||||
|  | @ -42,6 +42,10 @@ type ( | |||
| // and is usually used to trace detailed behavior of the program.
 | ||||
| const TraceLevel = logrus.Level(uint32(logrus.DebugLevel + 1)) | ||||
| 
 | ||||
| // RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to
 | ||||
| // ensure the formatted time is always the same number of characters.
 | ||||
| const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" | ||||
| 
 | ||||
| // ParseLevel takes a string level and returns the Logrus log level constant.
 | ||||
| // It supports trace level.
 | ||||
| func ParseLevel(lvl string) (logrus.Level, error) { | ||||
|  |  | |||
|  | @ -0,0 +1,229 @@ | |||
| /* | ||||
|    Copyright The containerd 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 platforms | ||||
| 
 | ||||
| import specs "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| 
 | ||||
| // MatchComparer is able to match and compare platforms to
 | ||||
| // filter and sort platforms.
 | ||||
| type MatchComparer interface { | ||||
| 	Matcher | ||||
| 
 | ||||
| 	Less(specs.Platform, specs.Platform) bool | ||||
| } | ||||
| 
 | ||||
| // Only returns a match comparer for a single platform
 | ||||
| // using default resolution logic for the platform.
 | ||||
| //
 | ||||
| // For ARMv8, will also match ARMv7, ARMv6 and ARMv5 (for 32bit runtimes)
 | ||||
| // For ARMv7, will also match ARMv6 and ARMv5
 | ||||
| // For ARMv6, will also match ARMv5
 | ||||
| func Only(platform specs.Platform) MatchComparer { | ||||
| 	platform = Normalize(platform) | ||||
| 	if platform.Architecture == "arm" { | ||||
| 		if platform.Variant == "v8" { | ||||
| 			return orderedPlatformComparer{ | ||||
| 				matchers: []Matcher{ | ||||
| 					&matcher{ | ||||
| 						Platform: platform, | ||||
| 					}, | ||||
| 					&matcher{ | ||||
| 						Platform: specs.Platform{ | ||||
| 							Architecture: platform.Architecture, | ||||
| 							OS:           platform.OS, | ||||
| 							OSVersion:    platform.OSVersion, | ||||
| 							OSFeatures:   platform.OSFeatures, | ||||
| 							Variant:      "v7", | ||||
| 						}, | ||||
| 					}, | ||||
| 					&matcher{ | ||||
| 						Platform: specs.Platform{ | ||||
| 							Architecture: platform.Architecture, | ||||
| 							OS:           platform.OS, | ||||
| 							OSVersion:    platform.OSVersion, | ||||
| 							OSFeatures:   platform.OSFeatures, | ||||
| 							Variant:      "v6", | ||||
| 						}, | ||||
| 					}, | ||||
| 					&matcher{ | ||||
| 						Platform: specs.Platform{ | ||||
| 							Architecture: platform.Architecture, | ||||
| 							OS:           platform.OS, | ||||
| 							OSVersion:    platform.OSVersion, | ||||
| 							OSFeatures:   platform.OSFeatures, | ||||
| 							Variant:      "v5", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			} | ||||
| 		} | ||||
| 		if platform.Variant == "v7" { | ||||
| 			return orderedPlatformComparer{ | ||||
| 				matchers: []Matcher{ | ||||
| 					&matcher{ | ||||
| 						Platform: platform, | ||||
| 					}, | ||||
| 					&matcher{ | ||||
| 						Platform: specs.Platform{ | ||||
| 							Architecture: platform.Architecture, | ||||
| 							OS:           platform.OS, | ||||
| 							OSVersion:    platform.OSVersion, | ||||
| 							OSFeatures:   platform.OSFeatures, | ||||
| 							Variant:      "v6", | ||||
| 						}, | ||||
| 					}, | ||||
| 					&matcher{ | ||||
| 						Platform: specs.Platform{ | ||||
| 							Architecture: platform.Architecture, | ||||
| 							OS:           platform.OS, | ||||
| 							OSVersion:    platform.OSVersion, | ||||
| 							OSFeatures:   platform.OSFeatures, | ||||
| 							Variant:      "v5", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			} | ||||
| 		} | ||||
| 		if platform.Variant == "v6" { | ||||
| 			return orderedPlatformComparer{ | ||||
| 				matchers: []Matcher{ | ||||
| 					&matcher{ | ||||
| 						Platform: platform, | ||||
| 					}, | ||||
| 					&matcher{ | ||||
| 						Platform: specs.Platform{ | ||||
| 							Architecture: platform.Architecture, | ||||
| 							OS:           platform.OS, | ||||
| 							OSVersion:    platform.OSVersion, | ||||
| 							OSFeatures:   platform.OSFeatures, | ||||
| 							Variant:      "v5", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return singlePlatformComparer{ | ||||
| 		Matcher: &matcher{ | ||||
| 			Platform: platform, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Ordered returns a platform MatchComparer which matches any of the platforms
 | ||||
| // but orders them in order they are provided.
 | ||||
| func Ordered(platforms ...specs.Platform) MatchComparer { | ||||
| 	matchers := make([]Matcher, len(platforms)) | ||||
| 	for i := range platforms { | ||||
| 		matchers[i] = NewMatcher(platforms[i]) | ||||
| 	} | ||||
| 	return orderedPlatformComparer{ | ||||
| 		matchers: matchers, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Any returns a platform MatchComparer which matches any of the platforms
 | ||||
| // with no preference for ordering.
 | ||||
| func Any(platforms ...specs.Platform) MatchComparer { | ||||
| 	matchers := make([]Matcher, len(platforms)) | ||||
| 	for i := range platforms { | ||||
| 		matchers[i] = NewMatcher(platforms[i]) | ||||
| 	} | ||||
| 	return anyPlatformComparer{ | ||||
| 		matchers: matchers, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // All is a platform MatchComparer which matches all platforms
 | ||||
| // with preference for ordering.
 | ||||
| var All MatchComparer = allPlatformComparer{} | ||||
| 
 | ||||
| type singlePlatformComparer struct { | ||||
| 	Matcher | ||||
| } | ||||
| 
 | ||||
| func (c singlePlatformComparer) Less(p1, p2 specs.Platform) bool { | ||||
| 	return c.Match(p1) && !c.Match(p2) | ||||
| } | ||||
| 
 | ||||
| type orderedPlatformComparer struct { | ||||
| 	matchers []Matcher | ||||
| } | ||||
| 
 | ||||
| func (c orderedPlatformComparer) Match(platform specs.Platform) bool { | ||||
| 	for _, m := range c.matchers { | ||||
| 		if m.Match(platform) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (c orderedPlatformComparer) Less(p1 specs.Platform, p2 specs.Platform) bool { | ||||
| 	for _, m := range c.matchers { | ||||
| 		p1m := m.Match(p1) | ||||
| 		p2m := m.Match(p2) | ||||
| 		if p1m && !p2m { | ||||
| 			return true | ||||
| 		} | ||||
| 		if p1m || p2m { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| type anyPlatformComparer struct { | ||||
| 	matchers []Matcher | ||||
| } | ||||
| 
 | ||||
| func (c anyPlatformComparer) Match(platform specs.Platform) bool { | ||||
| 	for _, m := range c.matchers { | ||||
| 		if m.Match(platform) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (c anyPlatformComparer) Less(p1, p2 specs.Platform) bool { | ||||
| 	var p1m, p2m bool | ||||
| 	for _, m := range c.matchers { | ||||
| 		if !p1m && m.Match(p1) { | ||||
| 			p1m = true | ||||
| 		} | ||||
| 		if !p2m && m.Match(p2) { | ||||
| 			p2m = true | ||||
| 		} | ||||
| 		if p1m && p2m { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	// If one matches, and the other does, sort match first
 | ||||
| 	return p1m && !p2m | ||||
| } | ||||
| 
 | ||||
| type allPlatformComparer struct{} | ||||
| 
 | ||||
| func (allPlatformComparer) Match(specs.Platform) bool { | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (allPlatformComparer) Less(specs.Platform, specs.Platform) bool { | ||||
| 	return false | ||||
| } | ||||
|  | @ -0,0 +1,117 @@ | |||
| /* | ||||
|    Copyright The containerd 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 platforms | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/containerd/containerd/errdefs" | ||||
| 	"github.com/containerd/containerd/log" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
| 
 | ||||
| // Present the ARM instruction set architecture, eg: v7, v8
 | ||||
| var cpuVariant string | ||||
| 
 | ||||
| func init() { | ||||
| 	if isArmArch(runtime.GOARCH) { | ||||
| 		cpuVariant = getCPUVariant() | ||||
| 	} else { | ||||
| 		cpuVariant = "" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // For Linux, the kernel has already detected the ABI, ISA and Features.
 | ||||
| // So we don't need to access the ARM registers to detect platform information
 | ||||
| // by ourselves. We can just parse these information from /proc/cpuinfo
 | ||||
| func getCPUInfo(pattern string) (info string, err error) { | ||||
| 	if !isLinuxOS(runtime.GOOS) { | ||||
| 		return "", errors.Wrapf(errdefs.ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) | ||||
| 	} | ||||
| 
 | ||||
| 	cpuinfo, err := os.Open("/proc/cpuinfo") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	defer cpuinfo.Close() | ||||
| 
 | ||||
| 	// Start to Parse the Cpuinfo line by line. For SMP SoC, we parse
 | ||||
| 	// the first core is enough.
 | ||||
| 	scanner := bufio.NewScanner(cpuinfo) | ||||
| 	for scanner.Scan() { | ||||
| 		newline := scanner.Text() | ||||
| 		list := strings.Split(newline, ":") | ||||
| 
 | ||||
| 		if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) { | ||||
| 			return strings.TrimSpace(list[1]), nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Check whether the scanner encountered errors
 | ||||
| 	err = scanner.Err() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return "", errors.Wrapf(errdefs.ErrNotFound, "getCPUInfo for pattern: %s", pattern) | ||||
| } | ||||
| 
 | ||||
| func getCPUVariant() string { | ||||
| 	if runtime.GOOS == "windows" { | ||||
| 		// Windows only supports v7 for ARM32 and v8 for ARM64 and so we can use
 | ||||
| 		// runtime.GOARCH to determine the variants
 | ||||
| 		var variant string | ||||
| 		switch runtime.GOARCH { | ||||
| 		case "arm64": | ||||
| 			variant = "v8" | ||||
| 		case "arm": | ||||
| 			variant = "v7" | ||||
| 		default: | ||||
| 			variant = "unknown" | ||||
| 		} | ||||
| 
 | ||||
| 		return variant | ||||
| 	} | ||||
| 
 | ||||
| 	variant, err := getCPUInfo("Cpu architecture") | ||||
| 	if err != nil { | ||||
| 		log.L.WithError(err).Error("failure getting variant") | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	switch variant { | ||||
| 	case "8", "AArch64": | ||||
| 		variant = "v8" | ||||
| 	case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)": | ||||
| 		variant = "v7" | ||||
| 	case "6", "6TEJ": | ||||
| 		variant = "v6" | ||||
| 	case "5", "5T", "5TE", "5TEJ": | ||||
| 		variant = "v5" | ||||
| 	case "4", "4T": | ||||
| 		variant = "v4" | ||||
| 	case "3": | ||||
| 		variant = "v3" | ||||
| 	default: | ||||
| 		variant = "unknown" | ||||
| 	} | ||||
| 
 | ||||
| 	return variant | ||||
| } | ||||
|  | @ -0,0 +1,114 @@ | |||
| /* | ||||
|    Copyright The containerd 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 platforms | ||||
| 
 | ||||
| import ( | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // isLinuxOS returns true if the operating system is Linux.
 | ||||
| //
 | ||||
| // The OS value should be normalized before calling this function.
 | ||||
| func isLinuxOS(os string) bool { | ||||
| 	return os == "linux" | ||||
| } | ||||
| 
 | ||||
| // These function are generated from https://golang.org/src/go/build/syslist.go.
 | ||||
| //
 | ||||
| // We use switch statements because they are slightly faster than map lookups
 | ||||
| // and use a little less memory.
 | ||||
| 
 | ||||
| // isKnownOS returns true if we know about the operating system.
 | ||||
| //
 | ||||
| // The OS value should be normalized before calling this function.
 | ||||
| func isKnownOS(os string) bool { | ||||
| 	switch os { | ||||
| 	case "aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos": | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // isArmArch returns true if the architecture is ARM.
 | ||||
| //
 | ||||
| // The arch value should be normalized before being passed to this function.
 | ||||
| func isArmArch(arch string) bool { | ||||
| 	switch arch { | ||||
| 	case "arm", "arm64": | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // isKnownArch returns true if we know about the architecture.
 | ||||
| //
 | ||||
| // The arch value should be normalized before being passed to this function.
 | ||||
| func isKnownArch(arch string) bool { | ||||
| 	switch arch { | ||||
| 	case "386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", "ppc", "riscv", "riscv64", "s390", "s390x", "sparc", "sparc64", "wasm": | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func normalizeOS(os string) string { | ||||
| 	if os == "" { | ||||
| 		return runtime.GOOS | ||||
| 	} | ||||
| 	os = strings.ToLower(os) | ||||
| 
 | ||||
| 	switch os { | ||||
| 	case "macos": | ||||
| 		os = "darwin" | ||||
| 	} | ||||
| 	return os | ||||
| } | ||||
| 
 | ||||
| // normalizeArch normalizes the architecture.
 | ||||
| func normalizeArch(arch, variant string) (string, string) { | ||||
| 	arch, variant = strings.ToLower(arch), strings.ToLower(variant) | ||||
| 	switch arch { | ||||
| 	case "i386": | ||||
| 		arch = "386" | ||||
| 		variant = "" | ||||
| 	case "x86_64", "x86-64": | ||||
| 		arch = "amd64" | ||||
| 		variant = "" | ||||
| 	case "aarch64", "arm64": | ||||
| 		arch = "arm64" | ||||
| 		switch variant { | ||||
| 		case "8", "v8": | ||||
| 			variant = "" | ||||
| 		} | ||||
| 	case "armhf": | ||||
| 		arch = "arm" | ||||
| 		variant = "v7" | ||||
| 	case "armel": | ||||
| 		arch = "arm" | ||||
| 		variant = "v6" | ||||
| 	case "arm": | ||||
| 		switch variant { | ||||
| 		case "", "7": | ||||
| 			variant = "v7" | ||||
| 		case "5", "6", "8": | ||||
| 			variant = "v" + variant | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return arch, variant | ||||
| } | ||||
|  | @ -0,0 +1,38 @@ | |||
| /* | ||||
|    Copyright The containerd 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 platforms | ||||
| 
 | ||||
| import ( | ||||
| 	"runtime" | ||||
| 
 | ||||
| 	specs "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| ) | ||||
| 
 | ||||
| // DefaultString returns the default string specifier for the platform.
 | ||||
| func DefaultString() string { | ||||
| 	return Format(DefaultSpec()) | ||||
| } | ||||
| 
 | ||||
| // DefaultSpec returns the current platform's default platform specification.
 | ||||
| func DefaultSpec() specs.Platform { | ||||
| 	return specs.Platform{ | ||||
| 		OS:           runtime.GOOS, | ||||
| 		Architecture: runtime.GOARCH, | ||||
| 		// The Variant field will be empty if arch != ARM.
 | ||||
| 		Variant: cpuVariant, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/containerd/containerd/platforms/defaults_unix.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										24
									
								
								vendor/github.com/containerd/containerd/platforms/defaults_unix.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,24 @@ | |||
| // +build !windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 platforms | ||||
| 
 | ||||
| // Default returns the default matcher for the platform.
 | ||||
| func Default() MatchComparer { | ||||
| 	return Only(DefaultSpec()) | ||||
| } | ||||
							
								
								
									
										31
									
								
								vendor/github.com/containerd/containerd/platforms/defaults_windows.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										31
									
								
								vendor/github.com/containerd/containerd/platforms/defaults_windows.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,31 @@ | |||
| // +build windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 platforms | ||||
| 
 | ||||
| import ( | ||||
| 	specs "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| ) | ||||
| 
 | ||||
| // Default returns the default matcher for the platform.
 | ||||
| func Default() MatchComparer { | ||||
| 	return Ordered(DefaultSpec(), specs.Platform{ | ||||
| 		OS:           "linux", | ||||
| 		Architecture: "amd64", | ||||
| 	}) | ||||
| } | ||||
|  | @ -0,0 +1,279 @@ | |||
| /* | ||||
|    Copyright The containerd 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 platforms provides a toolkit for normalizing, matching and
 | ||||
| // specifying container platforms.
 | ||||
| //
 | ||||
| // Centered around OCI platform specifications, we define a string-based
 | ||||
| // specifier syntax that can be used for user input. With a specifier, users
 | ||||
| // only need to specify the parts of the platform that are relevant to their
 | ||||
| // context, providing an operating system or architecture or both.
 | ||||
| //
 | ||||
| // How do I use this package?
 | ||||
| //
 | ||||
| // The vast majority of use cases should simply use the match function with
 | ||||
| // user input. The first step is to parse a specifier into a matcher:
 | ||||
| //
 | ||||
| //   m, err := Parse("linux")
 | ||||
| //   if err != nil { ... }
 | ||||
| //
 | ||||
| // Once you have a matcher, use it to match against the platform declared by a
 | ||||
| // component, typically from an image or runtime. Since extracting an images
 | ||||
| // platform is a little more involved, we'll use an example against the
 | ||||
| // platform default:
 | ||||
| //
 | ||||
| //   if ok := m.Match(Default()); !ok { /* doesn't match */ }
 | ||||
| //
 | ||||
| // This can be composed in loops for resolving runtimes or used as a filter for
 | ||||
| // fetch and select images.
 | ||||
| //
 | ||||
| // More details of the specifier syntax and platform spec follow.
 | ||||
| //
 | ||||
| // Declaring Platform Support
 | ||||
| //
 | ||||
| // Components that have strict platform requirements should use the OCI
 | ||||
| // platform specification to declare their support. Typically, this will be
 | ||||
| // images and runtimes that should make these declaring which platform they
 | ||||
| // support specifically. This looks roughly as follows:
 | ||||
| //
 | ||||
| //   type Platform struct {
 | ||||
| //	   Architecture string
 | ||||
| //	   OS           string
 | ||||
| //	   Variant      string
 | ||||
| //   }
 | ||||
| //
 | ||||
| // Most images and runtimes should at least set Architecture and OS, according
 | ||||
| // to their GOARCH and GOOS values, respectively (follow the OCI image
 | ||||
| // specification when in doubt). ARM should set variant under certain
 | ||||
| // discussions, which are outlined below.
 | ||||
| //
 | ||||
| // Platform Specifiers
 | ||||
| //
 | ||||
| // While the OCI platform specifications provide a tool for components to
 | ||||
| // specify structured information, user input typically doesn't need the full
 | ||||
| // context and much can be inferred. To solve this problem, we introduced
 | ||||
| // "specifiers". A specifier has the format
 | ||||
| // `<os>|<arch>|<os>/<arch>[/<variant>]`.  The user can provide either the
 | ||||
| // operating system or the architecture or both.
 | ||||
| //
 | ||||
| // An example of a common specifier is `linux/amd64`. If the host has a default
 | ||||
| // of runtime that matches this, the user can simply provide the component that
 | ||||
| // matters. For example, if a image provides amd64 and arm64 support, the
 | ||||
| // operating system, `linux` can be inferred, so they only have to provide
 | ||||
| // `arm64` or `amd64`. Similar behavior is implemented for operating systems,
 | ||||
| // where the architecture may be known but a runtime may support images from
 | ||||
| // different operating systems.
 | ||||
| //
 | ||||
| // Normalization
 | ||||
| //
 | ||||
| // Because not all users are familiar with the way the Go runtime represents
 | ||||
| // platforms, several normalizations have been provided to make this package
 | ||||
| // easier to user.
 | ||||
| //
 | ||||
| // The following are performed for architectures:
 | ||||
| //
 | ||||
| //   Value    Normalized
 | ||||
| //   aarch64  arm64
 | ||||
| //   armhf    arm
 | ||||
| //   armel    arm/v6
 | ||||
| //   i386     386
 | ||||
| //   x86_64   amd64
 | ||||
| //   x86-64   amd64
 | ||||
| //
 | ||||
| // We also normalize the operating system `macos` to `darwin`.
 | ||||
| //
 | ||||
| // ARM Support
 | ||||
| //
 | ||||
| // To qualify ARM architecture, the Variant field is used to qualify the arm
 | ||||
| // version. The most common arm version, v7, is represented without the variant
 | ||||
| // unless it is explicitly provided. This is treated as equivalent to armhf. A
 | ||||
| // previous architecture, armel, will be normalized to arm/v6.
 | ||||
| //
 | ||||
| // While these normalizations are provided, their support on arm platforms has
 | ||||
| // not yet been fully implemented and tested.
 | ||||
| package platforms | ||||
| 
 | ||||
| import ( | ||||
| 	"regexp" | ||||
| 	"runtime" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/containerd/containerd/errdefs" | ||||
| 	specs "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	specifierRe = regexp.MustCompile(`^[A-Za-z0-9_-]+$`) | ||||
| ) | ||||
| 
 | ||||
| // Matcher matches platforms specifications, provided by an image or runtime.
 | ||||
| type Matcher interface { | ||||
| 	Match(platform specs.Platform) bool | ||||
| } | ||||
| 
 | ||||
| // NewMatcher returns a simple matcher based on the provided platform
 | ||||
| // specification. The returned matcher only looks for equality based on os,
 | ||||
| // architecture and variant.
 | ||||
| //
 | ||||
| // One may implement their own matcher if this doesn't provide the required
 | ||||
| // functionality.
 | ||||
| //
 | ||||
| // Applications should opt to use `Match` over directly parsing specifiers.
 | ||||
| func NewMatcher(platform specs.Platform) Matcher { | ||||
| 	return &matcher{ | ||||
| 		Platform: Normalize(platform), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type matcher struct { | ||||
| 	specs.Platform | ||||
| } | ||||
| 
 | ||||
| func (m *matcher) Match(platform specs.Platform) bool { | ||||
| 	normalized := Normalize(platform) | ||||
| 	return m.OS == normalized.OS && | ||||
| 		m.Architecture == normalized.Architecture && | ||||
| 		m.Variant == normalized.Variant | ||||
| } | ||||
| 
 | ||||
| func (m *matcher) String() string { | ||||
| 	return Format(m.Platform) | ||||
| } | ||||
| 
 | ||||
| // Parse parses the platform specifier syntax into a platform declaration.
 | ||||
| //
 | ||||
| // Platform specifiers are in the format `<os>|<arch>|<os>/<arch>[/<variant>]`.
 | ||||
| // The minimum required information for a platform specifier is the operating
 | ||||
| // system or architecture. If there is only a single string (no slashes), the
 | ||||
| // value will be matched against the known set of operating systems, then fall
 | ||||
| // back to the known set of architectures. The missing component will be
 | ||||
| // inferred based on the local environment.
 | ||||
| func Parse(specifier string) (specs.Platform, error) { | ||||
| 	if strings.Contains(specifier, "*") { | ||||
| 		// TODO(stevvooe): need to work out exact wildcard handling
 | ||||
| 		return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: wildcards not yet supported", specifier) | ||||
| 	} | ||||
| 
 | ||||
| 	parts := strings.Split(specifier, "/") | ||||
| 
 | ||||
| 	for _, part := range parts { | ||||
| 		if !specifierRe.MatchString(part) { | ||||
| 			return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q is an invalid component of %q: platform specifier component must match %q", part, specifier, specifierRe.String()) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var p specs.Platform | ||||
| 	switch len(parts) { | ||||
| 	case 1: | ||||
| 		// in this case, we will test that the value might be an OS, then look
 | ||||
| 		// it up. If it is not known, we'll treat it as an architecture. Since
 | ||||
| 		// we have very little information about the platform here, we are
 | ||||
| 		// going to be a little more strict if we don't know about the argument
 | ||||
| 		// value.
 | ||||
| 		p.OS = normalizeOS(parts[0]) | ||||
| 		if isKnownOS(p.OS) { | ||||
| 			// picks a default architecture
 | ||||
| 			p.Architecture = runtime.GOARCH | ||||
| 			if p.Architecture == "arm" { | ||||
| 				// TODO(stevvooe): Resolve arm variant, if not v6 (default)
 | ||||
| 				return specs.Platform{}, errors.Wrapf(errdefs.ErrNotImplemented, "arm support not fully implemented") | ||||
| 			} | ||||
| 
 | ||||
| 			return p, nil | ||||
| 		} | ||||
| 
 | ||||
| 		p.Architecture, p.Variant = normalizeArch(parts[0], "") | ||||
| 		if p.Architecture == "arm" && p.Variant == "v7" { | ||||
| 			p.Variant = "" | ||||
| 		} | ||||
| 		if isKnownArch(p.Architecture) { | ||||
| 			p.OS = runtime.GOOS | ||||
| 			return p, nil | ||||
| 		} | ||||
| 
 | ||||
| 		return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: unknown operating system or architecture", specifier) | ||||
| 	case 2: | ||||
| 		// In this case, we treat as a regular os/arch pair. We don't care
 | ||||
| 		// about whether or not we know of the platform.
 | ||||
| 		p.OS = normalizeOS(parts[0]) | ||||
| 		p.Architecture, p.Variant = normalizeArch(parts[1], "") | ||||
| 		if p.Architecture == "arm" && p.Variant == "v7" { | ||||
| 			p.Variant = "" | ||||
| 		} | ||||
| 
 | ||||
| 		return p, nil | ||||
| 	case 3: | ||||
| 		// we have a fully specified variant, this is rare
 | ||||
| 		p.OS = normalizeOS(parts[0]) | ||||
| 		p.Architecture, p.Variant = normalizeArch(parts[1], parts[2]) | ||||
| 		if p.Architecture == "arm64" && p.Variant == "" { | ||||
| 			p.Variant = "v8" | ||||
| 		} | ||||
| 
 | ||||
| 		return p, nil | ||||
| 	} | ||||
| 
 | ||||
| 	return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: cannot parse platform specifier", specifier) | ||||
| } | ||||
| 
 | ||||
| // MustParse is like Parses but panics if the specifier cannot be parsed.
 | ||||
| // Simplifies initialization of global variables.
 | ||||
| func MustParse(specifier string) specs.Platform { | ||||
| 	p, err := Parse(specifier) | ||||
| 	if err != nil { | ||||
| 		panic("platform: Parse(" + strconv.Quote(specifier) + "): " + err.Error()) | ||||
| 	} | ||||
| 	return p | ||||
| } | ||||
| 
 | ||||
| // Format returns a string specifier from the provided platform specification.
 | ||||
| func Format(platform specs.Platform) string { | ||||
| 	if platform.OS == "" { | ||||
| 		return "unknown" | ||||
| 	} | ||||
| 
 | ||||
| 	return joinNotEmpty(platform.OS, platform.Architecture, platform.Variant) | ||||
| } | ||||
| 
 | ||||
| func joinNotEmpty(s ...string) string { | ||||
| 	var ss []string | ||||
| 	for _, s := range s { | ||||
| 		if s == "" { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		ss = append(ss, s) | ||||
| 	} | ||||
| 
 | ||||
| 	return strings.Join(ss, "/") | ||||
| } | ||||
| 
 | ||||
| // Normalize validates and translate the platform to the canonical value.
 | ||||
| //
 | ||||
| // For example, if "Aarch64" is encountered, we change it to "arm64" or if
 | ||||
| // "x86_64" is encountered, it becomes "amd64".
 | ||||
| func Normalize(platform specs.Platform) specs.Platform { | ||||
| 	platform.OS = normalizeOS(platform.OS) | ||||
| 	platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant) | ||||
| 
 | ||||
| 	// these fields are deprecated, remove them
 | ||||
| 	platform.OSFeatures = nil | ||||
| 	platform.OSVersion = "" | ||||
| 
 | ||||
| 	return platform | ||||
| } | ||||
|  | @ -1,6 +1,7 @@ | |||
| 
 | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
|                         https://www.apache.org/licenses/ | ||||
| 
 | ||||
|    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||
| 
 | ||||
|  | @ -175,28 +176,16 @@ | |||
| 
 | ||||
|    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} | ||||
|    Copyright The containerd 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 | ||||
|        https://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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 devices | ||||
| 
 | ||||
| import "fmt" | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build linux darwin freebsd solaris
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 devices | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 devices | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 driver | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build linux darwin freebsd solaris
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 driver | ||||
| 
 | ||||
| import ( | ||||
|  | @ -13,7 +29,11 @@ import ( | |||
| ) | ||||
| 
 | ||||
| func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error { | ||||
| 	return devices.Mknod(path, mode, major, minor) | ||||
| 	err := devices.Mknod(path, mode, major, minor) | ||||
| 	if err != nil { | ||||
| 		err = &os.PathError{Op: "mknod", Path: path, Err: err} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (d *driver) Mkfifo(path string, mode os.FileMode) error { | ||||
|  | @ -22,7 +42,11 @@ func (d *driver) Mkfifo(path string, mode os.FileMode) error { | |||
| 	} | ||||
| 	// mknod with a mode that has ModeNamedPipe set creates a fifo, not a
 | ||||
| 	// device.
 | ||||
| 	return devices.Mknod(path, mode, 0, 0) | ||||
| 	err := devices.Mknod(path, mode, 0, 0) | ||||
| 	if err != nil { | ||||
| 		err = &os.PathError{Op: "mkfifo", Path: path, Err: err} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Getxattr returns all of the extended attributes for the file at path p.
 | ||||
|  |  | |||
|  | @ -1,18 +1,33 @@ | |||
| /* | ||||
|    Copyright The containerd 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 driver | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/containerd/continuity/sysx" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
| 
 | ||||
| func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error { | ||||
| 	return errors.Wrap(ErrNotSupported, "cannot create device node on Windows") | ||||
| 	return &os.PathError{Op: "mknod", Path: path, Err: ErrNotSupported} | ||||
| } | ||||
| 
 | ||||
| func (d *driver) Mkfifo(path string, mode os.FileMode) error { | ||||
| 	return errors.Wrap(ErrNotSupported, "cannot create fifo on Windows") | ||||
| 	return &os.PathError{Op: "mkfifo", Path: path, Err: ErrNotSupported} | ||||
| } | ||||
| 
 | ||||
| // Lchmod changes the mode of an file not following symlinks.
 | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 driver | ||||
| 
 | ||||
| import ( | ||||
|  | @ -15,5 +31,9 @@ func (d *driver) Lchmod(path string, mode os.FileMode) error { | |||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0) | ||||
| 	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0) | ||||
| 	if err != nil { | ||||
| 		err = &os.PathError{Op: "lchmod", Path: path, Err: err} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build darwin freebsd solaris
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 driver | ||||
| 
 | ||||
| import ( | ||||
|  | @ -10,5 +26,9 @@ import ( | |||
| 
 | ||||
| // Lchmod changes the mode of a file not following symlinks.
 | ||||
| func (d *driver) Lchmod(path string, mode os.FileMode) error { | ||||
| 	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW) | ||||
| 	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW) | ||||
| 	if err != nil { | ||||
| 		err = &os.PathError{Op: "lchmod", Path: path, Err: err} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 driver | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  | @ -16,20 +32,55 @@ var bufferPool = &sync.Pool{ | |||
| 	}, | ||||
| } | ||||
| 
 | ||||
| // CopyDir copies the directory from src to dst.
 | ||||
| // Most efficient copy of files is attempted.
 | ||||
| func CopyDir(dst, src string) error { | ||||
| 	inodes := map[uint64]string{} | ||||
| 	return copyDirectory(dst, src, inodes) | ||||
| // XAttrErrorHandlers transform a non-nil xattr error.
 | ||||
| // Return nil to ignore an error.
 | ||||
| // xattrKey can be empty for listxattr operation.
 | ||||
| type XAttrErrorHandler func(dst, src, xattrKey string, err error) error | ||||
| 
 | ||||
| type copyDirOpts struct { | ||||
| 	xeh XAttrErrorHandler | ||||
| } | ||||
| 
 | ||||
| func copyDirectory(dst, src string, inodes map[uint64]string) error { | ||||
| type CopyDirOpt func(*copyDirOpts) error | ||||
| 
 | ||||
| // WithXAttrErrorHandler allows specifying XAttrErrorHandler
 | ||||
| // If nil XAttrErrorHandler is specified (default), CopyDir stops
 | ||||
| // on a non-nil xattr error.
 | ||||
| func WithXAttrErrorHandler(xeh XAttrErrorHandler) CopyDirOpt { | ||||
| 	return func(o *copyDirOpts) error { | ||||
| 		o.xeh = xeh | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WithAllowXAttrErrors allows ignoring xattr errors.
 | ||||
| func WithAllowXAttrErrors() CopyDirOpt { | ||||
| 	xeh := func(dst, src, xattrKey string, err error) error { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return WithXAttrErrorHandler(xeh) | ||||
| } | ||||
| 
 | ||||
| // CopyDir copies the directory from src to dst.
 | ||||
| // Most efficient copy of files is attempted.
 | ||||
| func CopyDir(dst, src string, opts ...CopyDirOpt) error { | ||||
| 	var o copyDirOpts | ||||
| 	for _, opt := range opts { | ||||
| 		if err := opt(&o); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	inodes := map[uint64]string{} | ||||
| 	return copyDirectory(dst, src, inodes, &o) | ||||
| } | ||||
| 
 | ||||
| func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) error { | ||||
| 	stat, err := os.Stat(src) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "failed to stat %s", src) | ||||
| 	} | ||||
| 	if !stat.IsDir() { | ||||
| 		return errors.Errorf("source is not directory") | ||||
| 		return errors.Errorf("source %s is not directory", src) | ||||
| 	} | ||||
| 
 | ||||
| 	if st, err := os.Stat(dst); err != nil { | ||||
|  | @ -59,7 +110,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string) error { | |||
| 
 | ||||
| 		switch { | ||||
| 		case fi.IsDir(): | ||||
| 			if err := copyDirectory(target, source, inodes); err != nil { | ||||
| 			if err := copyDirectory(target, source, inodes, o); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			continue | ||||
|  | @ -95,7 +146,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string) error { | |||
| 			return errors.Wrap(err, "failed to copy file info") | ||||
| 		} | ||||
| 
 | ||||
| 		if err := copyXAttrs(target, source); err != nil { | ||||
| 		if err := copyXAttrs(target, source, o.xeh); err != nil { | ||||
| 			return errors.Wrap(err, "failed to copy xattrs") | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  | @ -43,6 +59,8 @@ func copyFileInfo(fi os.FileInfo, name string) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| const maxSSizeT = int64(^uint(0) >> 1) | ||||
| 
 | ||||
| func copyFileContent(dst, src *os.File) error { | ||||
| 	st, err := src.Stat() | ||||
| 	if err != nil { | ||||
|  | @ -55,7 +73,16 @@ func copyFileContent(dst, src *os.File) error { | |||
| 	dstFd := int(dst.Fd()) | ||||
| 
 | ||||
| 	for size > 0 { | ||||
| 		n, err := unix.CopyFileRange(srcFd, nil, dstFd, nil, int(size), 0) | ||||
| 		// Ensure that we are never trying to copy more than SSIZE_MAX at a
 | ||||
| 		// time and at the same time avoids overflows when the file is larger
 | ||||
| 		// than 4GB on 32-bit systems.
 | ||||
| 		var copySize int | ||||
| 		if size > maxSSizeT { | ||||
| 			copySize = int(maxSSizeT) | ||||
| 		} else { | ||||
| 			copySize = int(size) | ||||
| 		} | ||||
| 		n, err := unix.CopyFileRange(srcFd, nil, dstFd, nil, copySize, 0) | ||||
| 		if err != nil { | ||||
| 			if (err != unix.ENOSYS && err != unix.EXDEV) || !first { | ||||
| 				return errors.Wrap(err, "copy file range failed") | ||||
|  | @ -74,18 +101,34 @@ func copyFileContent(dst, src *os.File) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func copyXAttrs(dst, src string) error { | ||||
| func copyXAttrs(dst, src string, xeh XAttrErrorHandler) error { | ||||
| 	xattrKeys, err := sysx.LListxattr(src) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "failed to list xattrs on %s", src) | ||||
| 		e := errors.Wrapf(err, "failed to list xattrs on %s", src) | ||||
| 		if xeh != nil { | ||||
| 			e = xeh(dst, src, "", e) | ||||
| 		} | ||||
| 		return e | ||||
| 	} | ||||
| 	for _, xattr := range xattrKeys { | ||||
| 		data, err := sysx.LGetxattr(src, xattr) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) | ||||
| 			e := errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) | ||||
| 			if xeh != nil { | ||||
| 				if e = xeh(dst, src, xattr, e); e == nil { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			return e | ||||
| 		} | ||||
| 		if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { | ||||
| 			return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) | ||||
| 			e := errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) | ||||
| 			if xeh != nil { | ||||
| 				if e = xeh(dst, src, xattr, e); e == nil { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			return e | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build solaris darwin freebsd
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  | @ -53,18 +69,34 @@ func copyFileContent(dst, src *os.File) error { | |||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func copyXAttrs(dst, src string) error { | ||||
| func copyXAttrs(dst, src string, xeh XAttrErrorHandler) error { | ||||
| 	xattrKeys, err := sysx.LListxattr(src) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "failed to list xattrs on %s", src) | ||||
| 		e := errors.Wrapf(err, "failed to list xattrs on %s", src) | ||||
| 		if xeh != nil { | ||||
| 			e = xeh(dst, src, "", e) | ||||
| 		} | ||||
| 		return e | ||||
| 	} | ||||
| 	for _, xattr := range xattrKeys { | ||||
| 		data, err := sysx.LGetxattr(src, xattr) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) | ||||
| 			e := errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) | ||||
| 			if xeh != nil { | ||||
| 				if e = xeh(dst, src, xattr, e); e == nil { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			return e | ||||
| 		} | ||||
| 		if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { | ||||
| 			return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) | ||||
| 			e := errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) | ||||
| 			if xeh != nil { | ||||
| 				if e = xeh(dst, src, xattr, e); e == nil { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			return e | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  | @ -24,7 +40,7 @@ func copyFileContent(dst, src *os.File) error { | |||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func copyXAttrs(dst, src string) error { | ||||
| func copyXAttrs(dst, src string, xeh XAttrErrorHandler) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build !windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build linux
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import "context" | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build !windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import "os" | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build !windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import "os" | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  | @ -6,7 +22,6 @@ import ( | |||
| 	"io" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | @ -31,9 +46,8 @@ func pathChange(lower, upper *currentPath) (ChangeKind, string) { | |||
| 	if upper == nil { | ||||
| 		return ChangeKindDelete, lower.path | ||||
| 	} | ||||
| 	// TODO: compare by directory
 | ||||
| 
 | ||||
| 	switch i := strings.Compare(lower.path, upper.path); { | ||||
| 	switch i := directoryCompare(lower.path, upper.path); { | ||||
| 	case i < 0: | ||||
| 		// File in lower that is not in upper
 | ||||
| 		return ChangeKindDelete, lower.path | ||||
|  | @ -45,6 +59,35 @@ func pathChange(lower, upper *currentPath) (ChangeKind, string) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func directoryCompare(a, b string) int { | ||||
| 	l := len(a) | ||||
| 	if len(b) < l { | ||||
| 		l = len(b) | ||||
| 	} | ||||
| 	for i := 0; i < l; i++ { | ||||
| 		c1, c2 := a[i], b[i] | ||||
| 		if c1 == filepath.Separator { | ||||
| 			c1 = byte(0) | ||||
| 		} | ||||
| 		if c2 == filepath.Separator { | ||||
| 			c2 = byte(0) | ||||
| 		} | ||||
| 		if c1 < c2 { | ||||
| 			return -1 | ||||
| 		} | ||||
| 		if c1 > c2 { | ||||
| 			return +1 | ||||
| 		} | ||||
| 	} | ||||
| 	if len(a) < len(b) { | ||||
| 		return -1 | ||||
| 	} | ||||
| 	if len(a) > len(b) { | ||||
| 		return +1 | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| func sameFile(f1, f2 *currentPath) (bool, error) { | ||||
| 	if os.SameFile(f1.f, f2.f) { | ||||
| 		return true, nil | ||||
|  | @ -232,12 +275,6 @@ func walkLink(root, path string, linksWalked *int) (newpath string, islink bool, | |||
| 	if err != nil { | ||||
| 		return "", false, err | ||||
| 	} | ||||
| 	if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) { | ||||
| 		newpath = newpath[:len(root)] | ||||
| 		if !strings.HasPrefix(newpath, "/") { | ||||
| 			newpath = "/" + newpath | ||||
| 		} | ||||
| 	} | ||||
| 	*linksWalked++ | ||||
| 	return newpath, true, nil | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build darwin freebsd
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 fs | ||||
| 
 | ||||
| import "time" | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 pathdriver | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build !windows
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 syscallx | ||||
| 
 | ||||
| import "syscall" | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 syscallx | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -0,0 +1,3 @@ | |||
| This package is for internal use only. It is intended to only have | ||||
| temporary changes before they are upstreamed to golang.org/x/sys/ | ||||
| (a.k.a. https://github.com/golang/sys). | ||||
|  | @ -1,10 +0,0 @@ | |||
| // Copyright 2014 The Go Authors.  All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| // +build !gccgo | ||||
| 
 | ||||
| #include "textflag.h" | ||||
| 
 | ||||
| TEXT ·use(SB),NOSPLIT,$0 | ||||
| 	RET | ||||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 sysx | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,20 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| #   Copyright The containerd 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. | ||||
| 
 | ||||
| 
 | ||||
| set -e | ||||
| 
 | ||||
| mksyscall="$(go env GOROOT)/src/syscall/mksyscall.pl" | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 sysx | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,3 +1,19 @@ | |||
| /* | ||||
|    Copyright The containerd 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 sysx | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,5 +1,21 @@ | |||
| // +build darwin freebsd
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 sysx | ||||
| 
 | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,37 +0,0 @@ | |||
| package sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| var _zero uintptr | ||||
| 
 | ||||
| // 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) | ||||
| 
 | ||||
| // Do the interface allocations only once for common
 | ||||
| // Errno values.
 | ||||
| var ( | ||||
| 	errEAGAIN error = syscall.EAGAIN | ||||
| 	errEINVAL error = syscall.EINVAL | ||||
| 	errENOENT error = syscall.ENOENT | ||||
| ) | ||||
| 
 | ||||
| // errnoErr returns common boxed Errno values, to prevent
 | ||||
| // allocations at runtime.
 | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case syscall.EAGAIN: | ||||
| 		return errEAGAIN | ||||
| 	case syscall.EINVAL: | ||||
| 		return errEINVAL | ||||
| 	case syscall.ENOENT: | ||||
| 		return errENOENT | ||||
| 	} | ||||
| 	return e | ||||
| } | ||||
|  | @ -1,14 +1,72 @@ | |||
| // +build linux darwin
 | ||||
| 
 | ||||
| /* | ||||
|    Copyright The containerd 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 sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
| 
 | ||||
| const defaultXattrBufferSize = 5 | ||||
| // Listxattr calls syscall listxattr and reads all content
 | ||||
| // and returns a string array
 | ||||
| func Listxattr(path string) ([]string, error) { | ||||
| 	return listxattrAll(path, unix.Listxattr) | ||||
| } | ||||
| 
 | ||||
| var ErrNotSupported = fmt.Errorf("not supported") | ||||
| // Removexattr calls syscall removexattr
 | ||||
| func Removexattr(path string, attr string) (err error) { | ||||
| 	return unix.Removexattr(path, attr) | ||||
| } | ||||
| 
 | ||||
| // Setxattr calls syscall setxattr
 | ||||
| func Setxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	return unix.Setxattr(path, attr, data, flags) | ||||
| } | ||||
| 
 | ||||
| // Getxattr calls syscall getxattr
 | ||||
| func Getxattr(path, attr string) ([]byte, error) { | ||||
| 	return getxattrAll(path, attr, unix.Getxattr) | ||||
| } | ||||
| 
 | ||||
| // LListxattr lists xattrs, not following symlinks
 | ||||
| func LListxattr(path string) ([]string, error) { | ||||
| 	return listxattrAll(path, unix.Llistxattr) | ||||
| } | ||||
| 
 | ||||
| // LRemovexattr removes an xattr, not following symlinks
 | ||||
| func LRemovexattr(path string, attr string) (err error) { | ||||
| 	return unix.Lremovexattr(path, attr) | ||||
| } | ||||
| 
 | ||||
| // LSetxattr sets an xattr, not following symlinks
 | ||||
| func LSetxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	return unix.Lsetxattr(path, attr, data, flags) | ||||
| } | ||||
| 
 | ||||
| // LGetxattr gets an xattr, not following symlinks
 | ||||
| func LGetxattr(path, attr string) ([]byte, error) { | ||||
| 	return getxattrAll(path, attr, unix.Lgetxattr) | ||||
| } | ||||
| 
 | ||||
| const defaultXattrBufferSize = 5 | ||||
| 
 | ||||
| type listxattrFunc func(path string, dest []byte) (int, error) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,70 +0,0 @@ | |||
| package sysx | ||||
| 
 | ||||
| // These functions will be generated by generate.sh
 | ||||
| //    $ GOOS=darwin GOARCH=386 ./generate.sh xattr
 | ||||
| //    $ GOOS=darwin GOARCH=amd64 ./generate.sh xattr
 | ||||
| 
 | ||||
| //sys  getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error)
 | ||||
| //sys  setxattr(path string, attr string, data []byte, flags int) (err error)
 | ||||
| //sys  removexattr(path string, attr string, options int) (err error)
 | ||||
| //sys  listxattr(path string, dest []byte, options int) (sz int, err error)
 | ||||
| 
 | ||||
| const ( | ||||
| 	xattrNoFollow = 0x01 | ||||
| ) | ||||
| 
 | ||||
| func listxattrFollow(path string, dest []byte) (sz int, err error) { | ||||
| 	return listxattr(path, dest, 0) | ||||
| } | ||||
| 
 | ||||
| // Listxattr calls syscall getxattr
 | ||||
| func Listxattr(path string) ([]string, error) { | ||||
| 	return listxattrAll(path, listxattrFollow) | ||||
| } | ||||
| 
 | ||||
| // Removexattr calls syscall getxattr
 | ||||
| func Removexattr(path string, attr string) (err error) { | ||||
| 	return removexattr(path, attr, 0) | ||||
| } | ||||
| 
 | ||||
| // Setxattr calls syscall setxattr
 | ||||
| func Setxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	return setxattr(path, attr, data, flags) | ||||
| } | ||||
| 
 | ||||
| func getxattrFollow(path, attr string, dest []byte) (sz int, err error) { | ||||
| 	return getxattr(path, attr, dest, 0, 0) | ||||
| } | ||||
| 
 | ||||
| // Getxattr calls syscall getxattr
 | ||||
| func Getxattr(path, attr string) ([]byte, error) { | ||||
| 	return getxattrAll(path, attr, getxattrFollow) | ||||
| } | ||||
| 
 | ||||
| func listxattrNoFollow(path string, dest []byte) (sz int, err error) { | ||||
| 	return listxattr(path, dest, xattrNoFollow) | ||||
| } | ||||
| 
 | ||||
| // LListxattr calls syscall listxattr with XATTR_NOFOLLOW
 | ||||
| func LListxattr(path string) ([]string, error) { | ||||
| 	return listxattrAll(path, listxattrNoFollow) | ||||
| } | ||||
| 
 | ||||
| // LRemovexattr calls syscall removexattr with XATTR_NOFOLLOW
 | ||||
| func LRemovexattr(path string, attr string) (err error) { | ||||
| 	return removexattr(path, attr, xattrNoFollow) | ||||
| } | ||||
| 
 | ||||
| // Setxattr calls syscall setxattr with XATTR_NOFOLLOW
 | ||||
| func LSetxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	return setxattr(path, attr, data, flags|xattrNoFollow) | ||||
| } | ||||
| 
 | ||||
| func getxattrNoFollow(path, attr string, dest []byte) (sz int, err error) { | ||||
| 	return getxattr(path, attr, dest, 0, xattrNoFollow) | ||||
| } | ||||
| 
 | ||||
| // LGetxattr calls syscall getxattr with XATTR_NOFOLLOW
 | ||||
| func LGetxattr(path, attr string) ([]byte, error) { | ||||
| 	return getxattrAll(path, attr, getxattrNoFollow) | ||||
| } | ||||
|  | @ -1,111 +0,0 @@ | |||
| // mksyscall.pl -l32 xattr_darwin.go
 | ||||
| // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 | ||||
| 
 | ||||
| package sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = syscall.BytePtrFromString(attr) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p2 unsafe.Pointer | ||||
| 	if len(dest) > 0 { | ||||
| 		_p2 = unsafe.Pointer(&dest[0]) | ||||
| 	} else { | ||||
| 		_p2 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	use(unsafe.Pointer(_p1)) | ||||
| 	sz = int(r0) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func setxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = syscall.BytePtrFromString(attr) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p2 unsafe.Pointer | ||||
| 	if len(data) > 0 { | ||||
| 		_p2 = unsafe.Pointer(&data[0]) | ||||
| 	} else { | ||||
| 		_p2 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	use(unsafe.Pointer(_p1)) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func removexattr(path string, attr string, options int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = syscall.BytePtrFromString(attr) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	_, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	use(unsafe.Pointer(_p1)) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func listxattr(path string, dest []byte, options int) (sz int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(dest) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&dest[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	sz = int(r0) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | @ -1,111 +0,0 @@ | |||
| // mksyscall.pl xattr_darwin.go
 | ||||
| // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 | ||||
| 
 | ||||
| package sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = syscall.BytePtrFromString(attr) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p2 unsafe.Pointer | ||||
| 	if len(dest) > 0 { | ||||
| 		_p2 = unsafe.Pointer(&dest[0]) | ||||
| 	} else { | ||||
| 		_p2 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	use(unsafe.Pointer(_p1)) | ||||
| 	sz = int(r0) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func setxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = syscall.BytePtrFromString(attr) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p2 unsafe.Pointer | ||||
| 	if len(data) > 0 { | ||||
| 		_p2 = unsafe.Pointer(&data[0]) | ||||
| 	} else { | ||||
| 		_p2 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	use(unsafe.Pointer(_p1)) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func removexattr(path string, attr string, options int) (err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 *byte | ||||
| 	_p1, err = syscall.BytePtrFromString(attr) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	_, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	use(unsafe.Pointer(_p1)) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 | ||||
| 
 | ||||
| func listxattr(path string, dest []byte, options int) (sz int, err error) { | ||||
| 	var _p0 *byte | ||||
| 	_p0, err = syscall.BytePtrFromString(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	var _p1 unsafe.Pointer | ||||
| 	if len(dest) > 0 { | ||||
| 		_p1 = unsafe.Pointer(&dest[0]) | ||||
| 	} else { | ||||
| 		_p1 = unsafe.Pointer(&_zero) | ||||
| 	} | ||||
| 	r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) | ||||
| 	use(unsafe.Pointer(_p0)) | ||||
| 	sz = int(r0) | ||||
| 	if e1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | @ -1,12 +0,0 @@ | |||
| package sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // Initial stub version for FreeBSD. FreeBSD has a different
 | ||||
| // syscall API from Darwin and Linux for extended attributes;
 | ||||
| // it is also not widely used. It is not exposed at all by the
 | ||||
| // Go syscall package, so we need to implement directly eventually.
 | ||||
| 
 | ||||
| var unsupported = errors.New("extended attributes unsupported on FreeBSD") | ||||
|  | @ -1,44 +0,0 @@ | |||
| package sysx | ||||
| 
 | ||||
| import "golang.org/x/sys/unix" | ||||
| 
 | ||||
| // Listxattr calls syscall listxattr and reads all content
 | ||||
| // and returns a string array
 | ||||
| func Listxattr(path string) ([]string, error) { | ||||
| 	return listxattrAll(path, unix.Listxattr) | ||||
| } | ||||
| 
 | ||||
| // Removexattr calls syscall removexattr
 | ||||
| func Removexattr(path string, attr string) (err error) { | ||||
| 	return unix.Removexattr(path, attr) | ||||
| } | ||||
| 
 | ||||
| // Setxattr calls syscall setxattr
 | ||||
| func Setxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	return unix.Setxattr(path, attr, data, flags) | ||||
| } | ||||
| 
 | ||||
| // Getxattr calls syscall getxattr
 | ||||
| func Getxattr(path, attr string) ([]byte, error) { | ||||
| 	return getxattrAll(path, attr, unix.Getxattr) | ||||
| } | ||||
| 
 | ||||
| // LListxattr lists xattrs, not following symlinks
 | ||||
| func LListxattr(path string) ([]string, error) { | ||||
| 	return listxattrAll(path, unix.Llistxattr) | ||||
| } | ||||
| 
 | ||||
| // LRemovexattr removes an xattr, not following symlinks
 | ||||
| func LRemovexattr(path string, attr string) (err error) { | ||||
| 	return unix.Lremovexattr(path, attr) | ||||
| } | ||||
| 
 | ||||
| // LSetxattr sets an xattr, not following symlinks
 | ||||
| func LSetxattr(path string, attr string, data []byte, flags int) (err error) { | ||||
| 	return unix.Lsetxattr(path, attr, data, flags) | ||||
| } | ||||
| 
 | ||||
| // LGetxattr gets an xattr, not following symlinks
 | ||||
| func LGetxattr(path, attr string) ([]byte, error) { | ||||
| 	return getxattrAll(path, attr, unix.Lgetxattr) | ||||
| } | ||||
|  | @ -1,7 +0,0 @@ | |||
| package sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| var unsupported = errors.New("extended attributes unsupported on OpenBSD") | ||||
|  | @ -1,12 +0,0 @@ | |||
| package sysx | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // Initial stub version for Solaris. Solaris has a different
 | ||||
| // syscall API from Darwin and Linux for extended attributes;
 | ||||
| // it is also not widely used. It is not exposed at all by the
 | ||||
| // Go syscall package, so we need to implement directly eventually.
 | ||||
| 
 | ||||
| var unsupported = errors.New("extended attributes unsupported on Solaris") | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue